Skip to content

Commit

Permalink
use required instead of changing option<$ref> into allOf
Browse files Browse the repository at this point in the history
  • Loading branch information
kurtbuilds committed Jan 11, 2025
1 parent 747f851 commit 010dbaa
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 53 deletions.
22 changes: 6 additions & 16 deletions core/src/schema.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashMap;

use openapiv3::{RefOr, ReferenceOr, Schema, SchemaData, SchemaKind};
use openapiv3::{ReferenceOr, Schema};

#[cfg(feature = "actix")]
mod actix;
Expand Down Expand Up @@ -124,21 +124,11 @@ where

fn schema_ref() -> ReferenceOr<Schema> {
let mut schema = T::schema_ref();
match schema.as_mut() {
Some(s) => {
s.nullable = true;
schema
}
None => RefOr::Item(Schema {
data: SchemaData {
nullable: true,
..Default::default()
},
kind: SchemaKind::AllOf {
all_of: vec![schema],
},
}),
}
let Some(s) = schema.as_mut() else {
return schema;
};
s.nullable = true;
schema
}
}

Expand Down
85 changes: 55 additions & 30 deletions macro/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ use serde_derive_internals::{
attr::TagType,
};

fn is_option(ty: &syn::Type) -> bool {
let syn::Type::Path(p) = ty else {
return false;
};
let Some(segment) = p.path.segments.first() else {
return false;
};
segment.ident == "Option"
}

pub fn impl_OaSchema_schema(fields: &[Field], docstring: Option<String>) -> TokenStream2 {
if fields.len() == 1 {
let field = fields.first().unwrap();
Expand All @@ -17,11 +27,13 @@ pub fn impl_OaSchema_schema(fields: &[Field], docstring: Option<String>) -> Toke
};
}
}
let description = docstring.map(|s| {
quote! {
o.description = Some(#s.into());
}
}).unwrap_or_default();
let description = docstring
.map(|s| {
quote! {
o.description = Some(#s.into());
}
})
.unwrap_or_default();
let properties = fields
.into_iter()
.map(|f| {
Expand All @@ -48,7 +60,7 @@ pub fn impl_OaSchema_schema(fields: &[Field], docstring: Option<String>) -> Toke
}
}
} else {
let required = !(attr.skip || attr.skip_serializing_if.is_some());
let required = !(attr.skip || attr.skip_serializing_if.is_some() || is_option(ty));
let required = required.then(|| {
quote! { o.required_mut().push(#name.to_string()); }
}).unwrap_or_default();
Expand Down Expand Up @@ -79,7 +91,11 @@ pub fn impl_OaSchema_schema(fields: &[Field], docstring: Option<String>) -> Toke
}

/// Create OaSchema derive token stream for a struct from ident and fields
pub fn derive_oaschema_struct(ident: &Ident, fields: &[Field], docstring: Option<String>) -> TokenStream {
pub fn derive_oaschema_struct(
ident: &Ident,
fields: &[Field],
docstring: Option<String>,
) -> TokenStream {
let schema = impl_OaSchema_schema(fields, docstring);
let name = ident.to_string();
let submit = quote! {
Expand All @@ -97,17 +113,21 @@ pub fn derive_oaschema_struct(ident: &Ident, fields: &[Field], docstring: Option
}
}
#submit
}.into()
}
.into()
}

/// Create OaSchema derive token stream for an enum from ident and variants
pub fn derive_oaschema_enum(ident: &Ident, variants: &[Variant], tag: &TagType, _docstring: Option<String>) -> TokenStream {
let variants = variants
.into_iter()
.filter(|v| {
let openapi_attrs = FieldAttributes::try_from(&v.original.attrs).unwrap();
!openapi_attrs.skip
});
pub fn derive_oaschema_enum(
ident: &Ident,
variants: &[Variant],
tag: &TagType,
_docstring: Option<String>,
) -> TokenStream {
let variants = variants.into_iter().filter(|v| {
let openapi_attrs = FieldAttributes::try_from(&v.original.attrs).unwrap();
!openapi_attrs.skip
});
let mut complex_variants = vec![];
let mut str_variants = vec![];
for v in variants {
Expand Down Expand Up @@ -172,19 +192,22 @@ pub fn derive_oaschema_enum(ident: &Ident, variants: &[Variant], tag: &TagType,

if str_variants.len() > 0 {
match tag {
TagType::External => complex_variants.push(quote! { ::oasgen::Schema::new_str_enum(vec![#(#str_variants)*]) }),
TagType::Internal { tag } | TagType::Adjacent { tag, .. } => complex_variants.push(quote! {{
let mut o = ::oasgen::Schema::new_object();
let values = vec![#(#str_variants)*];
o.properties_mut().insert(#tag, ::oasgen::Schema::new_str_enum(values));
o.required_mut().push(#tag.to_string());
o
}}),
_ => () // a null case should be handled, which will deserialize to the first unit
// variant, but unsure how to handle this case. I tried an enum with
// type: 'null', which is supported in glademiller:openapiv3, but not in
// kurtbuilds:openapiv3
// kurt: I believe null enum is handled by setting nullable: true.
TagType::External => complex_variants
.push(quote! { ::oasgen::Schema::new_str_enum(vec![#(#str_variants)*]) }),
TagType::Internal { tag } | TagType::Adjacent { tag, .. } => {
complex_variants.push(quote! {{
let mut o = ::oasgen::Schema::new_object();
let values = vec![#(#str_variants)*];
o.properties_mut().insert(#tag, ::oasgen::Schema::new_str_enum(values));
o.required_mut().push(#tag.to_string());
o
}})
}
_ => (), // a null case should be handled, which will deserialize to the first unit
// variant, but unsure how to handle this case. I tried an enum with
// type: 'null', which is supported in glademiller:openapiv3, but not in
// kurtbuilds:openapiv3
// kurt: I believe null enum is handled by setting nullable: true.
}
}

Expand All @@ -211,7 +234,8 @@ pub fn derive_oaschema_enum(ident: &Ident, variants: &[Variant], tag: &TagType,
}
}
#submit
}.into()
}
.into()
}

pub fn derive_oaschema_newtype(ident: &Ident, field: &Field) -> TokenStream {
Expand All @@ -226,5 +250,6 @@ pub fn derive_oaschema_newtype(ident: &Ident, field: &Field) -> TokenStream {
<#ty as OaSchema>::schema()
}
}
}.into()
}
.into()
}
3 changes: 1 addition & 2 deletions oasgen/tests/test-none/02-required.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,4 @@ properties:
nullable: true
type: string
required:
- is_required
- is_nullable
- is_required
7 changes: 2 additions & 5 deletions oasgen/tests/test-none/03-newtype.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,8 @@ properties:
required:
- test
prop_d:
nullable: true
allOf:
- $ref: '#/components/schemas/Struct'
$ref: '#/components/schemas/Struct'
required:
- id
- prop_a
- prop_b
- prop_d
- prop_b

0 comments on commit 010dbaa

Please sign in to comment.