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
|
// 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,
|
// Cell<T>, RefCell<T>, Mutex<T>, RwLock<T>, Result<R,E>?, Duration, SystemTime,
|
||||||
// IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV6, SocketAddrV6,
|
// IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV6, SocketAddrV6,
|
||||||
|
|
|
@ -3,25 +3,13 @@
|
||||||
"title": "schemars__schema__Schema",
|
"title": "schemars__schema__Schema",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"properties": {
|
"type": "boolean"
|
||||||
"Bool": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"properties": {
|
"$ref": "#/definitions/schemars__schema__SchemaRef"
|
||||||
"Ref": {
|
|
||||||
"$ref": "#/definitions/schemars__schema__SchemaRef"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"properties": {
|
"$ref": "#/definitions/schemars__schema__SchemaObject"
|
||||||
"Object": {
|
|
||||||
"$ref": "#/definitions/schemars__schema__SchemaObject"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"definitions": {
|
"definitions": {
|
||||||
|
@ -39,25 +27,13 @@
|
||||||
"schemars__schema__Schema": {
|
"schemars__schema__Schema": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"properties": {
|
"type": "boolean"
|
||||||
"Bool": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"properties": {
|
"$ref": "#/definitions/schemars__schema__SchemaRef"
|
||||||
"Ref": {
|
|
||||||
"$ref": "#/definitions/schemars__schema__SchemaRef"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"properties": {
|
"$ref": "#/definitions/schemars__schema__SchemaObject"
|
||||||
"Object": {
|
|
||||||
"$ref": "#/definitions/schemars__schema__SchemaObject"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -224,20 +200,12 @@
|
||||||
"schemars__schema__SingleOrVec_schemars__schema__InstanceType_": {
|
"schemars__schema__SingleOrVec_schemars__schema__InstanceType_": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"properties": {
|
"$ref": "#/definitions/schemars__schema__InstanceType"
|
||||||
"Single": {
|
|
||||||
"$ref": "#/definitions/schemars__schema__InstanceType"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"properties": {
|
"type": "array",
|
||||||
"Vec": {
|
"items": {
|
||||||
"type": "array",
|
"$ref": "#/definitions/schemars__schema__InstanceType"
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/schemars__schema__InstanceType"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -245,20 +213,12 @@
|
||||||
"schemars__schema__SingleOrVec_schemars__schema__Schema_": {
|
"schemars__schema__SingleOrVec_schemars__schema__Schema_": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"properties": {
|
"$ref": "#/definitions/schemars__schema__Schema"
|
||||||
"Single": {
|
|
||||||
"$ref": "#/definitions/schemars__schema__Schema"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"properties": {
|
"type": "array",
|
||||||
"Vec": {
|
"items": {
|
||||||
"type": "array",
|
"$ref": "#/definitions/schemars__schema__Schema"
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/schemars__schema__Schema"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -7,6 +7,7 @@ extern crate proc_macro;
|
||||||
|
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use serde_derive_internals::ast::{Container, Data, Field, Style, Variant};
|
use serde_derive_internals::ast::{Container, Data, Field, Style, Variant};
|
||||||
|
use serde_derive_internals::attr::{self, EnumTag};
|
||||||
use serde_derive_internals::{Ctxt, Derive};
|
use serde_derive_internals::{Ctxt, Derive};
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::{DeriveInput, GenericParam, Generics};
|
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 {
|
let schema = match cont.data {
|
||||||
Data::Struct(Style::Struct, ref fields) => schema_for_struct(fields),
|
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!"),
|
_ => unimplemented!("work in progress!"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,8 +74,15 @@ fn is_unit_variant(v: &&Variant) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn schema_for_enum(variants: &[Variant]) -> TokenStream {
|
fn schema_for_enum(variants: &[Variant], cattrs: &attr::Container) -> TokenStream {
|
||||||
// TODO handle untagged or adjacently tagged enums
|
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<_>) =
|
let (unit_variants, complex_variants): (Vec<_>, Vec<_>) =
|
||||||
variants.into_iter().partition(is_unit_variant);
|
variants.into_iter().partition(is_unit_variant);
|
||||||
let unit_count = unit_variants.len();
|
let unit_count = unit_variants.len();
|
||||||
|
@ -97,24 +105,7 @@ fn schema_for_enum(variants: &[Variant]) -> TokenStream {
|
||||||
|
|
||||||
schemas.extend(complex_variants.into_iter().map(|variant| {
|
schemas.extend(complex_variants.into_iter().map(|variant| {
|
||||||
let name = variant.attrs.name().deserialize_name();
|
let name = variant.attrs.name().deserialize_name();
|
||||||
let sub_schema = match variant.style {
|
let sub_schema = schema_for_untagged_enum_variant(variant);
|
||||||
Style::Newtype => {
|
|
||||||
let f = &variant.fields[0];
|
|
||||||
let ty = f.ty;
|
|
||||||
quote_spanned! {f.original.span()=>
|
|
||||||
gen.subschema_for::<#ty>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Style::Tuple => {
|
|
||||||
let types = variant.fields.iter().map(|f| f.ty);
|
|
||||||
quote! {
|
|
||||||
gen.subschema_for::<(#(#types),*)>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Style::Struct => schema_for_struct(&variant.fields),
|
|
||||||
Style::Unit => unreachable!("Unit variants already filtered out"),
|
|
||||||
};
|
|
||||||
|
|
||||||
wrap_schema_fields(quote! {
|
wrap_schema_fields(quote! {
|
||||||
properties: {
|
properties: {
|
||||||
let mut props = std::collections::BTreeMap::new();
|
let mut props = std::collections::BTreeMap::new();
|
||||||
|
@ -129,6 +120,36 @@ fn schema_for_enum(variants: &[Variant]) -> TokenStream {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
quote_spanned! {f.original.span()=>
|
||||||
|
gen.subschema_for::<#ty>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Style::Tuple => {
|
||||||
|
let types = variant.fields.iter().map(|f| f.ty);
|
||||||
|
quote! {
|
||||||
|
gen.subschema_for::<(#(#types),*)>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Style::Struct => schema_for_struct(&variant.fields),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn schema_for_struct(fields: &[Field]) -> TokenStream {
|
fn schema_for_struct(fields: &[Field]) -> TokenStream {
|
||||||
let recurse = fields.into_iter().map(|f| {
|
let recurse = fields.into_iter().map(|f| {
|
||||||
let name = f.attrs.name().deserialize_name();
|
let name = f.attrs.name().deserialize_name();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue