Refactoring derive macros
This commit is contained in:
parent
38c8b2d911
commit
d628f7c162
2 changed files with 24 additions and 21 deletions
|
@ -35,8 +35,6 @@ macro_rules! no_ref_schema {
|
|||
};
|
||||
}
|
||||
|
||||
// TODO structs, enums, tuples
|
||||
|
||||
// TODO any other serde types other than serde_json value?
|
||||
// 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,
|
||||
|
|
|
@ -23,9 +23,9 @@ pub fn derive_make_schema(input: proc_macro::TokenStream) -> proc_macro::TokenSt
|
|||
let name = cont.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = cont.generics.split_for_impl();
|
||||
|
||||
let fn_contents = match cont.data {
|
||||
Data::Struct(Style::Struct, ref fields) => struct_implementation(fields),
|
||||
Data::Enum(ref variants) => enum_implementation(variants),
|
||||
let schema_contents = match cont.data {
|
||||
Data::Struct(Style::Struct, ref fields) => schema_for_struct(fields),
|
||||
Data::Enum(ref variants) => schema_for_enum(variants),
|
||||
_ => unimplemented!("work in progress!"),
|
||||
};
|
||||
|
||||
|
@ -33,11 +33,11 @@ pub fn derive_make_schema(input: proc_macro::TokenStream) -> proc_macro::TokenSt
|
|||
#[automatically_derived]
|
||||
impl #impl_generics schemars::make_schema::MakeSchema for #name #ty_generics #where_clause {
|
||||
fn make_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
|
||||
let mut o = schemars::SchemaObject {
|
||||
schemars::SchemaObject {
|
||||
#schema_contents
|
||||
..Default::default()
|
||||
};
|
||||
#fn_contents
|
||||
o.into()
|
||||
}
|
||||
.into()
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -50,34 +50,39 @@ fn compile_error(span: Span, message: String) -> TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_unit_variant(v: &Variant) -> bool {
|
||||
fn name_for_unit_variant(v: &Variant) -> Option<String> {
|
||||
match v.style {
|
||||
Style::Unit => true,
|
||||
_ => false,
|
||||
Style::Unit => Some(v.attrs.name().deserialize_name()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn enum_implementation(variants: &[Variant]) -> TokenStream {
|
||||
if variants.iter().all(is_unit_variant) {
|
||||
let names = variants
|
||||
.into_iter()
|
||||
.map(|v| v.attrs.name().deserialize_name());
|
||||
fn schema_for_enum(variants: &[Variant]) -> TokenStream {
|
||||
// TODO handle untagged or adjacently tagged enums
|
||||
let unit_names: Vec<_> = variants.iter().filter_map(name_for_unit_variant).collect();
|
||||
|
||||
if unit_names.len() == variants.len() {
|
||||
return quote! {
|
||||
o.enum_values = Some(vec![#(#names.into()),*]);
|
||||
enum_values: Some(vec![#(#unit_names.into()),*]),
|
||||
};
|
||||
}
|
||||
|
||||
unimplemented!("work in progress!")
|
||||
}
|
||||
|
||||
fn struct_implementation(fields: &[Field]) -> TokenStream {
|
||||
fn schema_for_struct(fields: &[Field]) -> TokenStream {
|
||||
let recurse = fields.into_iter().map(|f| {
|
||||
let name = f.attrs.name().deserialize_name();
|
||||
let ty = f.ty;
|
||||
quote_spanned! {f.original.span()=>
|
||||
o.properties.insert(#name.to_owned(), gen.subschema_for::<#ty>());
|
||||
props.insert(#name.to_owned(), gen.subschema_for::<#ty>());
|
||||
}
|
||||
});
|
||||
quote! {
|
||||
#(#recurse)*
|
||||
properties: {
|
||||
let mut props = std::collections::BTreeMap::new();
|
||||
#(#recurse)*
|
||||
props
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue