Skip to content

Commit f860e94

Browse files
committed
Extend proc-macro functionality, add derives to std
1 parent 3cdf3b2 commit f860e94

38 files changed

+605
-586
lines changed

Cargo.lock

+236-47
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cw-schema-derive/src/expand.rs

+70-46
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
use std::borrow::Cow;
2-
31
use crate::bail;
42
use proc_macro2::TokenStream;
53
use quote::quote;
6-
use syn::{punctuated::Punctuated, DataEnum, DataStruct, DataUnion, DeriveInput, Lit};
4+
use std::borrow::Cow;
5+
use syn::{DataEnum, DataStruct, DataUnion, DeriveInput, Lit};
76

87
struct SerdeContainerOptions {
98
rename_all: Option<syn::LitStr>,
@@ -45,12 +44,16 @@ impl SerdeContainerOptions {
4544
}
4645

4746
struct ContainerOptions {
47+
r#as: Option<syn::Ident>,
48+
r#type: Option<syn::Expr>,
4849
crate_path: syn::Path,
4950
}
5051

5152
impl ContainerOptions {
5253
fn parse(attributes: &[syn::Attribute]) -> syn::Result<Self> {
5354
let mut options = ContainerOptions {
55+
r#as: None,
56+
r#type: None,
5457
crate_path: syn::parse_str("::cw_schema")?,
5558
};
5659

@@ -62,6 +65,10 @@ impl ContainerOptions {
6265
if meta.path.is_ident("crate") {
6366
let stringified: syn::LitStr = meta.value()?.parse()?;
6467
options.crate_path = stringified.parse()?;
68+
} else if meta.path.is_ident("as") {
69+
options.r#as = Some(meta.value()?.parse()?);
70+
} else if meta.path.is_ident("type") {
71+
options.r#type = Some(meta.value()?.parse()?);
6572
} else {
6673
bail!(meta.path, "unknown attribute");
6774
}
@@ -228,55 +235,72 @@ fn expand_struct(mut meta: ContainerMeta, input: DataStruct) -> syn::Result<Toke
228235
let description = normalize_option(meta.description.as_ref());
229236
let crate_path = &meta.options.crate_path;
230237

231-
let node_ty = match input.fields {
232-
syn::Fields::Named(named) => {
233-
let items = named.named.iter().map(|field| {
234-
let name = field.ident.as_ref().unwrap();
235-
let description = normalize_option(extract_documentation(&field.attrs)?);
236-
let field_ty = &field.ty;
237-
238-
let expanded = quote! {
239-
(
240-
stringify!(#name).into(),
241-
#crate_path::StructProperty {
242-
description: #description,
243-
value: <#field_ty as #crate_path::Schemaifier>::visit_schema(visitor),
244-
}
245-
)
246-
};
247-
248-
Ok(expanded)
249-
}).collect::<syn::Result<Vec<_>>>()?;
250-
238+
let node = if let Some(ref r#as) = meta.options.r#as {
239+
quote! {
240+
let definition_resource = #crate_path::Schemaifier::visit_schema(visitor);
241+
visitor.get_schema::<#r#as>().unwrap().clone()
242+
}
243+
} else {
244+
let node_ty = if let Some(ref r#type) = meta.options.r#type {
251245
quote! {
252-
#crate_path::StructType::Named {
253-
properties: #crate_path::reexport::BTreeMap::from([
254-
#( #items, )*
255-
])
256-
}
246+
#r#type
257247
}
258-
}
259-
syn::Fields::Unnamed(fields) => {
260-
let type_names = fields.unnamed.iter().map(|field| &field.ty);
248+
} else {
249+
let node_ty = match input.fields {
250+
syn::Fields::Named(named) => {
251+
let items = named.named.iter().map(|field| {
252+
let name = field.ident.as_ref().unwrap();
253+
let description = normalize_option(extract_documentation(&field.attrs)?);
254+
let field_ty = &field.ty;
255+
256+
let expanded = quote! {
257+
(
258+
stringify!(#name).into(),
259+
#crate_path::StructProperty {
260+
description: #description,
261+
value: <#field_ty as #crate_path::Schemaifier>::visit_schema(visitor),
262+
}
263+
)
264+
};
265+
266+
Ok(expanded)
267+
}).collect::<syn::Result<Vec<_>>>()?;
268+
269+
quote! {
270+
#crate_path::StructType::Named {
271+
properties: #crate_path::reexport::BTreeMap::from([
272+
#( #items, )*
273+
])
274+
}
275+
}
276+
}
277+
syn::Fields::Unnamed(fields) => {
278+
let type_names = fields.unnamed.iter().map(|field| &field.ty);
279+
280+
quote! {
281+
#crate_path::StructType::Tuple {
282+
items: vec![
283+
#(
284+
<#type_names as #crate_path::Schemaifier>::visit_schema(visitor),
285+
)*
286+
],
287+
}
288+
}
289+
}
290+
syn::Fields::Unit => quote! { #crate_path::StructType::Unit },
291+
};
261292

262293
quote! {
263-
#crate_path::StructType::Tuple {
264-
items: vec![
265-
#(
266-
<#type_names as #crate_path::Schemaifier>::visit_schema(visitor),
267-
)*
268-
],
269-
}
294+
#crate_path::NodeType::Struct(#node_ty)
270295
}
271-
}
272-
syn::Fields::Unit => quote! { #crate_path::StructType::Unit },
273-
};
296+
};
274297

275-
let node = quote! {
276-
#crate_path::Node {
277-
name: std::any::type_name::<Self>().into(),
278-
description: #description,
279-
value: #crate_path::NodeType::Struct(#node_ty),
298+
quote! {
299+
#crate_path::Node {
300+
name: std::any::type_name::<Self>().into(),
301+
description: #description,
302+
value: #node_ty,
303+
}
280304
}
281305
};
282306

0 commit comments

Comments
 (0)