Support untagged enums
This commit is contained in:
parent
c552e6d208
commit
4a9fdd3334
3 changed files with 59 additions and 76 deletions
|
@ -35,7 +35,9 @@ macro_rules! no_ref_schema {
|
|||
};
|
||||
}
|
||||
|
||||
// TODO any other serde types other than serde_json value?
|
||||
// TODO any other serde/json types other than serde_json value?
|
||||
// TODO serde yaml value/map under feature flag
|
||||
// TODO add some inline attributes
|
||||
// https://github.com/serde-rs/serde/blob/ce75418e40a593fc5c0902cbf4a45305a4178dd7/serde/src/ser/impls.rs
|
||||
// Cell<T>, RefCell<T>, Mutex<T>, RwLock<T>, Result<R,E>?, Duration, SystemTime,
|
||||
// IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV6, SocketAddrV6,
|
||||
|
|
|
@ -3,26 +3,14 @@
|
|||
"title": "schemars__schema__Schema",
|
||||
"anyOf": [
|
||||
{
|
||||
"properties": {
|
||||
"Bool": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"Ref": {
|
||||
"$ref": "#/definitions/schemars__schema__SchemaRef"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"Object": {
|
||||
"$ref": "#/definitions/schemars__schema__SchemaObject"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"definitions": {
|
||||
"schemars__schema__InstanceType": {
|
||||
|
@ -39,26 +27,14 @@
|
|||
"schemars__schema__Schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"properties": {
|
||||
"Bool": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"Ref": {
|
||||
"$ref": "#/definitions/schemars__schema__SchemaRef"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"Object": {
|
||||
"$ref": "#/definitions/schemars__schema__SchemaObject"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"schemars__schema__SchemaObject": {
|
||||
|
@ -224,43 +200,27 @@
|
|||
"schemars__schema__SingleOrVec_schemars__schema__InstanceType_": {
|
||||
"anyOf": [
|
||||
{
|
||||
"properties": {
|
||||
"Single": {
|
||||
"$ref": "#/definitions/schemars__schema__InstanceType"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"Vec": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/schemars__schema__InstanceType"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"schemars__schema__SingleOrVec_schemars__schema__Schema_": {
|
||||
"anyOf": [
|
||||
{
|
||||
"properties": {
|
||||
"Single": {
|
||||
"$ref": "#/definitions/schemars__schema__Schema"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"Vec": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/schemars__schema__Schema"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ extern crate proc_macro;
|
|||
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use serde_derive_internals::ast::{Container, Data, Field, Style, Variant};
|
||||
use serde_derive_internals::attr::{self, EnumTag};
|
||||
use serde_derive_internals::{Ctxt, Derive};
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{DeriveInput, GenericParam, Generics};
|
||||
|
@ -27,7 +28,7 @@ pub fn derive_make_schema(input: proc_macro::TokenStream) -> proc_macro::TokenSt
|
|||
|
||||
let schema = match cont.data {
|
||||
Data::Struct(Style::Struct, ref fields) => schema_for_struct(fields),
|
||||
Data::Enum(ref variants) => schema_for_enum(variants),
|
||||
Data::Enum(ref variants) => schema_for_enum(variants, &cont.attrs),
|
||||
_ => unimplemented!("work in progress!"),
|
||||
};
|
||||
|
||||
|
@ -73,8 +74,15 @@ fn is_unit_variant(v: &&Variant) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn schema_for_enum(variants: &[Variant]) -> TokenStream {
|
||||
// TODO handle untagged or adjacently tagged enums
|
||||
fn schema_for_enum(variants: &[Variant], cattrs: &attr::Container) -> TokenStream {
|
||||
match cattrs.tag() {
|
||||
EnumTag::External => schema_for_external_tagged_enum(variants),
|
||||
EnumTag::None => schema_for_untagged_enum(variants),
|
||||
_ => unimplemented!("Adjacent/internal tagged enums not yet supported."),
|
||||
}
|
||||
}
|
||||
|
||||
fn schema_for_external_tagged_enum(variants: &[Variant]) -> TokenStream {
|
||||
let (unit_variants, complex_variants): (Vec<_>, Vec<_>) =
|
||||
variants.into_iter().partition(is_unit_variant);
|
||||
let unit_count = unit_variants.len();
|
||||
|
@ -97,7 +105,34 @@ fn schema_for_enum(variants: &[Variant]) -> TokenStream {
|
|||
|
||||
schemas.extend(complex_variants.into_iter().map(|variant| {
|
||||
let name = variant.attrs.name().deserialize_name();
|
||||
let sub_schema = match variant.style {
|
||||
let sub_schema = schema_for_untagged_enum_variant(variant);
|
||||
wrap_schema_fields(quote! {
|
||||
properties: {
|
||||
let mut props = std::collections::BTreeMap::new();
|
||||
props.insert(#name.to_owned(), #sub_schema);
|
||||
props
|
||||
},
|
||||
})
|
||||
}));
|
||||
|
||||
wrap_schema_fields(quote! {
|
||||
any_of: Some(vec![#(#schemas),*]),
|
||||
})
|
||||
}
|
||||
|
||||
fn schema_for_untagged_enum(variants: &[Variant]) -> TokenStream {
|
||||
let schemas = variants.into_iter().map(schema_for_untagged_enum_variant);
|
||||
|
||||
wrap_schema_fields(quote! {
|
||||
any_of: Some(vec![#(#schemas),*]),
|
||||
})
|
||||
}
|
||||
|
||||
fn schema_for_untagged_enum_variant(variant: &Variant) -> TokenStream {
|
||||
match variant.style {
|
||||
Style::Unit => quote! {
|
||||
gen.subschema_for::<()>()
|
||||
},
|
||||
Style::Newtype => {
|
||||
let f = &variant.fields[0];
|
||||
let ty = f.ty;
|
||||
|
@ -112,21 +147,7 @@ fn schema_for_enum(variants: &[Variant]) -> TokenStream {
|
|||
}
|
||||
}
|
||||
Style::Struct => schema_for_struct(&variant.fields),
|
||||
Style::Unit => unreachable!("Unit variants already filtered out"),
|
||||
};
|
||||
|
||||
wrap_schema_fields(quote! {
|
||||
properties: {
|
||||
let mut props = std::collections::BTreeMap::new();
|
||||
props.insert(#name.to_owned(), #sub_schema);
|
||||
props
|
||||
},
|
||||
})
|
||||
}));
|
||||
|
||||
wrap_schema_fields(quote! {
|
||||
any_of: Some(vec![#(#schemas),*]),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn schema_for_struct(fields: &[Field]) -> TokenStream {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue