Skip to content
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

Is it possible to define a generic enum ? #259

Closed
szagi3891 opened this issue Apr 15, 2022 · 12 comments
Closed

Is it possible to define a generic enum ? #259

szagi3891 opened this issue Apr 15, 2022 · 12 comments
Labels
question Further information is requested

Comments

@szagi3891
Copy link

I would like to define a generic enum that I will use in the openapi specification.

I tried to define it this way:

use poem_openapi::{OneOf, Object};
use poem_openapi::types::ToJSON;

#[derive(Debug, Object)]
pub struct ProxyResponseOk<R: Send + ToJSON> {
    pub response: R
}

#[derive(Debug, Object)]
pub struct ProxyResponseMessage {
    pub code: String,
    pub message: String,
}

#[derive(Debug, Object)]
pub struct ProxyResponseUnknown {
    pub code: u32,
    pub body: String,
}

#[derive(Debug, OneOf)]
#[oai(property_name="type")]
pub enum ProxyResponse<R: Send + ToJSON> {
    Ok(ProxyResponseOk<R>),
    Error(ProxyResponseMessage),
    Unknown(ProxyResponseUnknown),
}

When trying to compile I get errors:

error[E0412]: cannot find type `R` in this scope
  --> src/proxy/handler/selection_errors.rs:25:24
   |
22 | #[derive(Debug, OneOf)]
   |                      - help: you might be missing a type parameter: `<R>`
...
25 |     Ok(ProxyResponseOk<R>),
   |                        ^ not found in this scope

error[E0107]: missing generics for enum `ProxyResponse`
  --> src/proxy/handler/selection_errors.rs:24:10
   |
24 | pub enum ProxyResponse<R: Send + ToJSON> {
   |          ^^^^^^^^^^^^^ expected 1 generic argument
   |
note: enum defined here, with 1 generic parameter: `R`
  --> src/proxy/handler/selection_errors.rs:24:10
   |
24 | pub enum ProxyResponse<R: Send + ToJSON> {
   |          ^^^^^^^^^^^^^ -
help: add missing generic argument
   |
24 | pub enum ProxyResponse<R><R: Send + ToJSON> {
   |          ~~~~~~~~~~~~~~~~

Can I ask for help?

@szagi3891 szagi3891 added the question Further information is requested label Apr 15, 2022
@sunli829
Copy link
Collaborator

Currently not supported, I will add it later.

sunli829 added a commit that referenced this issue Apr 15, 2022
@sunli829
Copy link
Collaborator

I've added support for generic union in v1.3.27, both inline and non-inline, non-inline requires specifying the name of the concrete type.

@szagi3891
Copy link
Author

There is only one problem:

warning: `example-openapi-oneof` (bin "example-openapi-oneof") generated 6 warnings
    Finished dev [unoptimized + debuginfo] target(s) in 1.52s
     Running `target/debug/example-openapi-oneof`
thread 'main' panicked at '`example_openapi_oneof::ProxyResponse<alloc::string::String>` and `example_openapi_oneof::ProxyResponse<u32>` have the same OpenAPI name `ProxyResponse`', /Users/grzegorzszeliga/.cargo/registry/src/gh.neting.cc-1ecc6299db9ec823/poem-openapi-1.3.27/src/registry/mod.rs:652:25
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Here is the code that demonstrates this problem

https://github.com/szagi3891/poem-test/blob/master/src/main.rs#L148

@sunli829
Copy link
Collaborator

If the object is generic, either specify the inline attribute to avoid creating the object in the schema. Either use concrete to give each concrete type a name.

I'll add a validator to catch this problem at compile time.

@szagi3891
Copy link
Author

I understand. Would it be possible to make the inline attribute default to a type that is generic?

@szagi3891
Copy link
Author

#[derive(Debug, Object)]
#[oai(inline)]
pub struct ProxyResponseOk<R: Send + ToJSON + ParseFromJSON> {
    pub response: R
}

#[derive(Debug, Object)]
pub struct ProxyResponseMessage {
    pub code: String,
    pub message: String,
}

#[derive(Debug, Object)]
pub struct ProxyResponseUnknown {
    pub code: u32,
    pub body: String,
}

#[derive(Debug, Union)]
#[oai(discriminator_name="type")]
#[oai(inline)]
pub enum ProxyResponse<R: Send + ToJSON + ParseFromJSON> {
    Ok(ProxyResponseOk<R>),
    Error(ProxyResponseMessage),
    Unknown(ProxyResponseUnknown),
}

Well, and if inline was added by default for types that have a generic parameter, it should nicely simplify this code.

@sunli829
Copy link
Collaborator

This is a breaking change 😂, I've improved it now, if you don't specify the inline or concretes attribute of the generic object, it will report an explicit error at compile time.

@sunli829
Copy link
Collaborator

Inline objects have the disadvantage that they cannot refer to themselves.

@szagi3891
Copy link
Author

szagi3891 commented Apr 16, 2022

This message at compile time will be very helpful.

This is a breaking change.

Why is this a breaking change ? Until now, generic types have not been generated in the openapi specification (I guess).

@sunli829
Copy link
Collaborator

Why is this a breaking change ? Until now, generic types have not been generated in the openapi specification (I guess).

For poem-openapi. 🙂

@sunli829
Copy link
Collaborator

Fixed in v1.3.28

@szagi3891
Copy link
Author

Thank you very much :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants