-
Notifications
You must be signed in to change notification settings - Fork 222
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for generics? #108
Comments
Hi, This seems to touch the same topic already discussed here #101. But in short currently there is a limited support for generics. Since this is library is compile time and more over macro compile time thus it needs to know the types when macros are being executed and this makes it bit of a challenge. But as what comes for the
This is merely for documentation purposes and does not really matter whether this is
If you have a struct like one below you can use #[derive(Deserialize, Serialize, Component)]
struct Foo {
#[component(value_type = String)]
id: Uuid,
} And currently |
For what comes to UUID coming with next release the The |
In a nutshell the the biggest obstacle with the generics is that in code above I don't know how to map Then the next question is if this was somehow possible. How would The current generic support works pretty well with types with lifetimes or traits. In general if there is a way to get around these obstacles the support for these kind of generics could be added for sure. :) But so far I haven't figured out a solution yet. It's also typical to some cases actually have different types for data transfers like dto pattern in java (data transfer object) where there is another set of types for communication layer which is typically in a shared codebase between api:s or clients and another set of types for internals. But yes some cases bit of a overhead I agree. |
@juhaku to me, like we discussed a bit, to be openapi compliant (even for everyone safety) noone should use directly Best world to me, crate could/should support type aliases over generics and not generics directly like mention by issuer as it will never be possible to be compliant (just talking about end use of struct type). |
Yes, the direct generic types cannot be presented in OpenAPI spec as components which itself rules out the use of direct generics as is unless there is a way to get around it. But as so far the type aliases cannot have their own Thinking this further. I need to test it out whether I could "use" the type aliases as part of the source to the component with generic types. Perhaps there will be then another trait to use something like |
For the time being to avoid complete manual declaration, rework to struct/enum, I was wondering if it would be possible to achieve something manual+automatic for these types in an I had in mind keeping everything as it is, alias on api declaration but later on doing something like this: // this does not compile obviously as it comes from my mind!
impl Modify for ExtraSchemas {
fn modify(&self, openapi: &mut openapi::OpenApi) {
openapi.components.as_mut().map(|lst| {
// I do not know if such feature already exists
l.schemas.insert("FooBar", Components::From(Foo<Bar, BarResources>))
}
}
} Just throwing an idea like this as it is something I did for some very simple type alias over String, Uuid etc. To me it could be an acceptable alternative until/if we found a more suitable approach. Drawback is that currently Is this idea completely stupid or not? What do you think @juhaku? NB: Anyway just a positive note, thanks for your work! |
I think this has some point. For simple entities something like this is probably feasible. But for entities like structs with fields the issue that arises is that how to get access to the fields of the
Most likely there is a need for derive type of macro. As it is easiest way to get access to the Like calling the figuragive function
😄 yeah Anytime.. Good that this has been found useful. :) |
@juhaku Hm, do you know how the other OpenAPI crate (e.g. okapi, opg) support generic types? To monomorphize my generic type for each case where it's used, I'm trying to use a macro to avoid duplication: macro_rules! foo {
($typ: ident, $d: ty, $r: ty) => {
#[derive(Debug, Serialize, Component)]
pub struct $typ {
pub data: $d,
pub resources: $r,
}
};
}
foo!(GetFooBody, Foo, FooResources); But I'm getting the error:
Any idea why? |
Actually no, I have no idea about internals of other frameworks and how things are implemented there.
Actually yes, seemingly the |
As what I checked about opg. It indeed has some sort of support for generics, but it also does not come without drawbacks. It leverages the idea that when you call Better approach would be Rust type aliases with some macros most likely, if I can leverage them. Still need to investigate possibilities. Or if direct generics is wanted behaviour, then the types need to be directly inlined and not added under "components" in OpenAPI schema. |
@bhoudebert @oliver-impero I have now played a little with the syntax and now I have rought idea how the generics could roll out. See the example: struct A {
a: String,
}
struct B {
b: i64,
}
struct CC {
a: String,
}
struct DD {
b: i64,
}
#[derive(Component)]
#[aliases(FooAB = Foo<A, B>, FooCD = Foo<CC, DD>)]
struct Foo<T, R> {
field_1: T,
field_2: R,
}
#[derive(OpenApi)]
#[openapi(
components(FooAB, FooCD)
)]
struct ApiDoc; Note that the |
@juhaku oh nice!, I think this would be very nice indeed, afaik it would solve a lot of my current issues! |
@bhoudebert Now there is a support for this in master. Feel free to try it out. It will be released along with few other things in short future. :) |
This has now been released, so closing this issue for now. |
I have a struct like this:
And I want to use it like this with a rocket request handler:
I'm getting multiple errors:
Uuid
is not aComponent
. I'm forced to writeString
instead. I wish I could writeUuid
because it makes the doc clearer.<
, it expects a comma. So I guess the proc-macro can't handle generics yet, is this planned? :)I tried this instead:
and then
then it compiles but I get an error in the browser when browsing the swagger doc:
This refers to the type params
D
andR
. Even though bothBar
andBarResources
areComponent
, the proc-macro doesn't treat them as expected. And in the swagger UI, it shows both fields' type asstring
:(Is it possible / planned to add support for generics? :)
So that I don't have to write a second set of types just for the doc, but can use the actual types that I'm using in the request handlers also for the doc.
The text was updated successfully, but these errors were encountered: