diff --git a/typify-impl/src/lib.rs b/typify-impl/src/lib.rs index a1299cc9..35e97d71 100644 --- a/typify-impl/src/lib.rs +++ b/typify-impl/src/lib.rs @@ -242,6 +242,7 @@ pub(crate) enum DefaultImpl { pub struct TypeSpaceSettings { type_mod: Option, extra_derives: Vec, + extra_attrs: Vec, struct_builder: bool, unknown_crates: UnknownPolicy, @@ -307,8 +308,12 @@ impl CrateVers { /// Contains a set of modifications that may be applied to an existing type. #[derive(Debug, Default, Clone)] pub struct TypeSpacePatch { - rename: Option, - derives: Vec, + /// Rename the type + pub rename: Option, + /// Derives to add + pub derives: Vec, + /// Attributes to add + pub attrs: Vec, } /// Contains the attributes of a replacement of an existing type. @@ -365,6 +370,13 @@ impl TypeSpaceSettings { } self } + /// Add an additional attribute to apply to all defined types. + pub fn with_attr(&mut self, attr: String) -> &mut Self { + if !self.extra_attrs.contains(&attr) { + self.extra_attrs.push(attr); + } + self + } /// For structs, include a "builder" type that can be used to construct it. pub fn with_struct_builder(&mut self, struct_builder: bool) -> &mut Self { @@ -468,6 +480,11 @@ impl TypeSpacePatch { self.derives.push(derive.to_string()); self } + /// Specify an additional attribute to apply to the patched type. + pub fn with_attr(&mut self, attr: S) -> &mut Self { + self.attrs.push(attr.to_string()); + self + } } impl TypeSpace { diff --git a/typify-impl/src/type_entry.rs b/typify-impl/src/type_entry.rs index 15b03a18..2d853038 100644 --- a/typify-impl/src/type_entry.rs +++ b/typify-impl/src/type_entry.rs @@ -666,6 +666,7 @@ impl TypeEntry { enum_details: &TypeEntryEnum, mut derive_set: BTreeSet<&str>, ) { + let extra_attrs = attrs_from_type_space(type_space); let TypeEntryEnum { name, rename, @@ -980,6 +981,7 @@ impl TypeEntry { #doc #[derive(#(#derives),*)] #serde + #(#extra_attrs)* pub enum #type_name { #(#variants_decl)* } @@ -1017,6 +1019,7 @@ impl TypeEntry { } = struct_details; let doc = make_doc(name, description.as_ref(), schema); + let extra_attrs = attrs_from_type_space(type_space); // Generate the serde directives as needed. let mut serde_options = Vec::new(); if let Some(old_name) = rename { @@ -1097,6 +1100,7 @@ impl TypeEntry { #doc #[derive(#(#derives),*)] #serde + #(#extra_attrs)* pub struct #type_name { #( #prop_doc @@ -1226,6 +1230,7 @@ impl TypeEntry { schema: SchemaWrapper(schema), } = newtype_details; let doc = make_doc(name, description.as_ref(), schema); + let extra_attrs = attrs_from_type_space(type_space); let serde = rename.as_ref().map(|old_name| { quote! { @@ -1524,6 +1529,7 @@ impl TypeEntry { #doc #[derive(#(#derives),*)] #serde + #(#extra_attrs)* pub struct #type_name(#vis #inner_type_name); impl ::std::ops::Deref for #type_name { @@ -1842,6 +1848,19 @@ impl TypeEntry { } } +fn attrs_from_type_space(type_space: &TypeSpace) -> Vec { + let extra_attrs: Vec = { + type_space + .settings + .extra_attrs + .clone() + .into_iter() + .map(|attr| attr.parse::().unwrap()) + .collect() + }; + extra_attrs +} + fn make_doc(name: &str, description: Option<&String>, schema: &Schema) -> TokenStream { let desc = description.map_or(name, |desc| desc.as_str()); let schema_json = serde_json::to_string_pretty(schema).unwrap();