summaryrefslogtreecommitdiff
path: root/vendor/educe/src/trait_handlers/default
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
committermo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
commit8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch)
tree22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/educe/src/trait_handlers/default
parent4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff)
chore: add vendor directory
Diffstat (limited to 'vendor/educe/src/trait_handlers/default')
-rw-r--r--vendor/educe/src/trait_handlers/default/default_enum.rs230
-rw-r--r--vendor/educe/src/trait_handlers/default/default_struct.rs149
-rw-r--r--vendor/educe/src/trait_handlers/default/default_union.rs153
-rw-r--r--vendor/educe/src/trait_handlers/default/mod.rs43
-rw-r--r--vendor/educe/src/trait_handlers/default/models/field_attribute.rs166
-rw-r--r--vendor/educe/src/trait_handlers/default/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/default/models/type_attribute.rs214
-rw-r--r--vendor/educe/src/trait_handlers/default/panic.rs21
8 files changed, 981 insertions, 0 deletions
diff --git a/vendor/educe/src/trait_handlers/default/default_enum.rs b/vendor/educe/src/trait_handlers/default/default_enum.rs
new file mode 100644
index 00000000..8aa4ec6e
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/default_enum.rs
@@ -0,0 +1,230 @@
+use quote::quote;
+use syn::{spanned::Spanned, Data, DeriveInput, Fields, Meta, Type, Variant};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::Trait;
+
+pub(crate) struct DefaultEnumHandler;
+
+impl TraitHandler for DefaultEnumHandler {
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_new: true,
+ enable_expression: true,
+ enable_bound: true,
+ }
+ .build_from_default_meta(meta)?;
+
+ let mut default_types: Vec<&Type> = Vec::new();
+
+ let mut default_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Enum(data) = &ast.data {
+ if let Some(expression) = type_attribute.expression {
+ for variant in data.variants.iter() {
+ let _ = TypeAttributeBuilder {
+ enable_flag: false,
+ enable_new: false,
+ enable_expression: false,
+ enable_bound: false,
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ ensure_fields_no_attribute(&variant.fields, traits)?;
+ }
+
+ default_token_stream.extend(quote!(#expression));
+ } else {
+ let variant = {
+ let variants = &data.variants;
+
+ if variants.len() == 1 {
+ let variant = &variants[0];
+
+ let _ = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_new: false,
+ enable_expression: false,
+ enable_bound: false,
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ variant
+ } else {
+ let mut default_variant: Option<&Variant> = None;
+
+ for variant in variants {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_new: false,
+ enable_expression: false,
+ enable_bound: false,
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ if type_attribute.flag {
+ if default_variant.is_some() {
+ return Err(super::panic::multiple_default_variants(
+ type_attribute.span,
+ ));
+ }
+
+ default_variant = Some(variant);
+ } else {
+ ensure_fields_no_attribute(&variant.fields, traits)?;
+ }
+ }
+
+ if let Some(default_variant) = default_variant {
+ default_variant
+ } else {
+ return Err(super::panic::no_default_variant(meta.span()));
+ }
+ }
+ };
+
+ let variant_ident = &variant.ident;
+
+ match &variant.fields {
+ Fields::Unit => {
+ default_token_stream.extend(quote!(Self::#variant_ident));
+ },
+ Fields::Named(_) => {
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+
+ for field in variant.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ let field_name = field.ident.as_ref().unwrap();
+
+ if let Some(expression) = field_attribute.expression {
+ fields_token_stream.extend(quote! {
+ #field_name: #expression,
+ });
+ } else {
+ let ty = &field.ty;
+
+ default_types.push(ty);
+
+ fields_token_stream.extend(quote! {
+ #field_name: <#ty as ::core::default::Default>::default(),
+ });
+ }
+ }
+
+ default_token_stream.extend(quote! {
+ Self::#variant_ident {
+ #fields_token_stream
+ }
+ });
+ },
+ Fields::Unnamed(_) => {
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+
+ for field in variant.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ if let Some(expression) = field_attribute.expression {
+ fields_token_stream.extend(quote!(#expression,));
+ } else {
+ let ty = &field.ty;
+
+ default_types.push(ty);
+
+ fields_token_stream
+ .extend(quote!(<#ty as ::core::default::Default>::default(),));
+ }
+ }
+
+ default_token_stream
+ .extend(quote!(Self::#variant_ident ( #fields_token_stream )));
+ },
+ }
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::default::Default)).unwrap(),
+ &default_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::default::Default for #ident #ty_generics #where_clause {
+ #[inline]
+ fn default() -> Self {
+ #default_token_stream
+ }
+ }
+ });
+
+ if type_attribute.new {
+ token_stream.extend(quote! {
+ impl #impl_generics #ident #ty_generics #where_clause {
+ /// Returns the "default value" for a type.
+ #[inline]
+ pub fn new() -> Self {
+ <Self as ::core::default::Default>::default()
+ }
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
+
+fn ensure_fields_no_attribute(fields: &Fields, traits: &[Trait]) -> syn::Result<()> {
+ match fields {
+ Fields::Unit => (),
+ Fields::Named(fields) => {
+ for field in fields.named.iter() {
+ let _ = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: false,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+ }
+ },
+ Fields::Unnamed(fields) => {
+ for field in fields.unnamed.iter() {
+ let _ = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: false,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+ }
+ },
+ }
+
+ Ok(())
+}
diff --git a/vendor/educe/src/trait_handlers/default/default_struct.rs b/vendor/educe/src/trait_handlers/default/default_struct.rs
new file mode 100644
index 00000000..ea25b565
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/default_struct.rs
@@ -0,0 +1,149 @@
+use quote::quote;
+use syn::{Data, DeriveInput, Fields, Meta, Type};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::Trait;
+
+pub(crate) struct DefaultStructHandler;
+
+impl TraitHandler for DefaultStructHandler {
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_new: true,
+ enable_expression: true,
+ enable_bound: true,
+ }
+ .build_from_default_meta(meta)?;
+
+ let mut default_types: Vec<&Type> = Vec::new();
+
+ let mut default_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Struct(data) = &ast.data {
+ if let Some(expression) = type_attribute.expression {
+ for field in data.fields.iter() {
+ let _ = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: false,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+ }
+
+ default_token_stream.extend(quote!(#expression));
+ } else {
+ match &data.fields {
+ Fields::Unit => {
+ default_token_stream.extend(quote!(Self));
+ },
+ Fields::Named(_) => {
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+
+ for field in data.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ let field_name = field.ident.as_ref().unwrap();
+
+ if let Some(expression) = field_attribute.expression {
+ fields_token_stream.extend(quote! {
+ #field_name: #expression,
+ });
+ } else {
+ let ty = &field.ty;
+
+ default_types.push(ty);
+
+ fields_token_stream.extend(quote! {
+ #field_name: <#ty as ::core::default::Default>::default(),
+ });
+ }
+ }
+
+ default_token_stream.extend(quote! {
+ Self {
+ #fields_token_stream
+ }
+ });
+ },
+ Fields::Unnamed(_) => {
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+
+ for field in data.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ if let Some(expression) = field_attribute.expression {
+ fields_token_stream.extend(quote!(#expression,));
+ } else {
+ let ty = &field.ty;
+
+ default_types.push(ty);
+
+ fields_token_stream
+ .extend(quote!(<#ty as ::core::default::Default>::default(),));
+ }
+ }
+
+ default_token_stream.extend(quote!(Self ( #fields_token_stream )));
+ },
+ }
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::default::Default)).unwrap(),
+ &default_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::default::Default for #ident #ty_generics #where_clause {
+ #[inline]
+ fn default() -> Self {
+ #default_token_stream
+ }
+ }
+ });
+
+ if type_attribute.new {
+ token_stream.extend(quote! {
+ impl #impl_generics #ident #ty_generics #where_clause {
+ /// Returns the "default value" for a type.
+ #[inline]
+ pub fn new() -> Self {
+ <Self as ::core::default::Default>::default()
+ }
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/default/default_union.rs b/vendor/educe/src/trait_handlers/default/default_union.rs
new file mode 100644
index 00000000..a535c011
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/default_union.rs
@@ -0,0 +1,153 @@
+use quote::quote;
+use syn::{spanned::Spanned, Data, DeriveInput, Field, Meta, Type};
+
+use super::{
+ models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::Trait;
+
+pub(crate) struct DefaultUnionHandler;
+
+impl TraitHandler for DefaultUnionHandler {
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_new: true,
+ enable_expression: true,
+ enable_bound: true,
+ }
+ .build_from_default_meta(meta)?;
+
+ let mut default_types: Vec<&Type> = Vec::new();
+
+ let mut default_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Union(data) = &ast.data {
+ if let Some(expression) = type_attribute.expression {
+ for field in data.fields.named.iter() {
+ let _ = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: false,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+ }
+
+ default_token_stream.extend(quote!(#expression));
+ } else {
+ let (field, field_attribute) =
+ {
+ let fields = &data.fields.named;
+
+ if fields.len() == 1 {
+ let field = &fields[0];
+
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: true,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ (field, field_attribute)
+ } else {
+ let mut default_field: Option<(&Field, FieldAttribute)> = None;
+
+ for field in fields {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: true,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ if field_attribute.flag || field_attribute.expression.is_some() {
+ if default_field.is_some() {
+ return Err(super::panic::multiple_default_fields(
+ field_attribute.span,
+ ));
+ }
+
+ default_field = Some((field, field_attribute));
+ }
+ }
+
+ if let Some(default_field) = default_field {
+ default_field
+ } else {
+ return Err(super::panic::no_default_field(meta.span()));
+ }
+ }
+ };
+
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+
+ let field_name = field.ident.as_ref().unwrap();
+
+ if let Some(expression) = field_attribute.expression {
+ fields_token_stream.extend(quote! {
+ #field_name: #expression,
+ });
+ } else {
+ let ty = &field.ty;
+
+ default_types.push(ty);
+
+ fields_token_stream.extend(quote! {
+ #field_name: <#ty as ::core::default::Default>::default(),
+ });
+ }
+
+ default_token_stream.extend(quote! {
+ Self {
+ #fields_token_stream
+ }
+ });
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::default::Default)).unwrap(),
+ &default_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::default::Default for #ident #ty_generics #where_clause {
+ #[inline]
+ fn default() -> Self {
+ #default_token_stream
+ }
+ }
+ });
+
+ if type_attribute.new {
+ token_stream.extend(quote! {
+ impl #impl_generics #ident #ty_generics #where_clause {
+ /// Returns the "default value" for a type.
+ #[inline]
+ pub fn new() -> Self {
+ <Self as ::core::default::Default>::default()
+ }
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/default/mod.rs b/vendor/educe/src/trait_handlers/default/mod.rs
new file mode 100644
index 00000000..5c1eeb8d
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/mod.rs
@@ -0,0 +1,43 @@
+mod default_enum;
+mod default_struct;
+mod default_union;
+mod models;
+mod panic;
+
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandler;
+use crate::Trait;
+
+pub(crate) struct DefaultHandler;
+
+impl TraitHandler for DefaultHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ match ast.data {
+ Data::Struct(_) => default_struct::DefaultStructHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Enum(_) => default_enum::DefaultEnumHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Union(_) => default_union::DefaultUnionHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ }
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/default/models/field_attribute.rs b/vendor/educe/src/trait_handlers/default/models/field_attribute.rs
new file mode 100644
index 00000000..6c82940d
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/models/field_attribute.rs
@@ -0,0 +1,166 @@
+use proc_macro2::Span;
+use syn::{punctuated::Punctuated, spanned::Spanned, Attribute, Expr, Meta, Token, Type};
+
+use crate::{
+ common::expr::{auto_adjust_expr, meta_2_expr},
+ panic,
+ supported_traits::Trait,
+};
+
+pub(crate) struct FieldAttribute {
+ pub(crate) flag: bool,
+ pub(crate) expression: Option<Expr>,
+ pub(crate) span: Span,
+}
+
+pub(crate) struct FieldAttributeBuilder {
+ pub(crate) enable_flag: bool,
+ pub(crate) enable_expression: bool,
+}
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_default_meta(
+ &self,
+ meta: &Meta,
+ ty: &Type,
+ ) -> syn::Result<FieldAttribute> {
+ debug_assert!(meta.path().is_ident("Default"));
+
+ let mut flag = false;
+ let mut expression = None;
+
+ let correct_usage_for_default_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(Default)]));
+ }
+
+ if self.enable_expression {
+ usage.push(stringify!(#[educe(Default = expr)]));
+
+ usage.push(stringify!(#[educe(Default(expression = expr))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_default_attribute,
+ ));
+ }
+
+ flag = true;
+ },
+ Meta::NameValue(name_value) => {
+ if !self.enable_expression {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_default_attribute,
+ ));
+ }
+
+ expression = Some(auto_adjust_expr(name_value.value.clone(), Some(ty)));
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut expression_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ match ident.to_string().as_str() {
+ "expression" | "expr" => {
+ if !self.enable_expression {
+ return Ok(false);
+ }
+
+ let v = meta_2_expr(&meta)?;
+
+ if expression_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ expression_is_set = true;
+
+ expression = Some(auto_adjust_expr(v, Some(ty)));
+
+ return Ok(true);
+ },
+ _ => (),
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_default_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(FieldAttribute {
+ flag,
+ expression,
+ span: meta.span(),
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ty: &Type,
+ ) -> syn::Result<FieldAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Default {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_default_meta(&meta, ty)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(FieldAttribute {
+ flag: false,
+ expression: None,
+ span: Span::call_site(),
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/default/models/mod.rs b/vendor/educe/src/trait_handlers/default/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/models/mod.rs
@@ -0,0 +1,5 @@
+mod field_attribute;
+mod type_attribute;
+
+pub(crate) use field_attribute::*;
+pub(crate) use type_attribute::*;
diff --git a/vendor/educe/src/trait_handlers/default/models/type_attribute.rs b/vendor/educe/src/trait_handlers/default/models/type_attribute.rs
new file mode 100644
index 00000000..ee0b901b
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/models/type_attribute.rs
@@ -0,0 +1,214 @@
+use proc_macro2::Span;
+use syn::{punctuated::Punctuated, spanned::Spanned, Attribute, Expr, Meta, Token};
+
+use crate::{
+ common::{
+ bound::Bound,
+ expr::{auto_adjust_expr, meta_2_expr},
+ ident_bool::meta_2_bool_allow_path,
+ },
+ panic, Trait,
+};
+
+pub(crate) struct TypeAttribute {
+ pub(crate) flag: bool,
+ pub(crate) new: bool,
+ pub(crate) expression: Option<Expr>,
+ pub(crate) bound: Bound,
+ pub(crate) span: Span,
+}
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_flag: bool,
+ pub(crate) enable_new: bool,
+ pub(crate) enable_expression: bool,
+ pub(crate) enable_bound: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_default_meta(&self, meta: &Meta) -> syn::Result<TypeAttribute> {
+ debug_assert!(meta.path().is_ident("Default"));
+
+ let mut flag = false;
+ let mut new = false;
+ let mut expression = None;
+ let mut bound = Bound::Auto;
+
+ let correct_usage_for_default_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(Default)]));
+ }
+
+ if self.enable_new {
+ usage.push(stringify!(#[educe(Default(new))]));
+ }
+
+ if self.enable_expression {
+ usage.push(stringify!(#[educe(Default(expression = expr))]));
+ }
+
+ if self.enable_bound {
+ usage.push(stringify!(#[educe(Default(bound(where_predicates)))]));
+ usage.push(stringify!(#[educe(Default(bound = false))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_default_attribute,
+ ));
+ }
+
+ flag = true;
+ },
+ Meta::NameValue(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_default_attribute,
+ ));
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut new_is_set = false;
+ let mut expression_is_set = false;
+ let mut bound_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ match ident.to_string().as_str() {
+ "new" => {
+ if !self.enable_new {
+ return Ok(false);
+ }
+
+ let v = meta_2_bool_allow_path(&meta)?;
+
+ if new_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ new_is_set = true;
+
+ new = v;
+
+ return Ok(true);
+ },
+ "expression" | "expr" => {
+ if !self.enable_expression {
+ return Ok(false);
+ }
+
+ let v = meta_2_expr(&meta)?;
+
+ if expression_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ expression_is_set = true;
+
+ expression = Some(auto_adjust_expr(v, None));
+
+ return Ok(true);
+ },
+ "bound" => {
+ if !self.enable_bound {
+ return Ok(false);
+ }
+
+ let v = Bound::from_meta(&meta)?;
+
+ if bound_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ bound_is_set = true;
+
+ bound = v;
+
+ return Ok(true);
+ },
+ _ => (),
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_default_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(TypeAttribute {
+ flag,
+ new,
+ expression,
+ bound,
+ span: meta.span(),
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<TypeAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Default {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_default_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(TypeAttribute {
+ flag: false,
+ new: false,
+ expression: None,
+ bound: Bound::Auto,
+ span: Span::call_site(),
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/default/panic.rs b/vendor/educe/src/trait_handlers/default/panic.rs
new file mode 100644
index 00000000..9f3598ea
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/panic.rs
@@ -0,0 +1,21 @@
+use proc_macro2::Span;
+
+#[inline]
+pub(crate) fn multiple_default_fields(span: Span) -> syn::Error {
+ syn::Error::new(span, "multiple default fields are set")
+}
+
+#[inline]
+pub(crate) fn no_default_field(span: Span) -> syn::Error {
+ syn::Error::new(span, "there is no field set as default")
+}
+
+#[inline]
+pub(crate) fn multiple_default_variants(span: Span) -> syn::Error {
+ syn::Error::new(span, "multiple default variants are set")
+}
+
+#[inline]
+pub(crate) fn no_default_variant(span: Span) -> syn::Error {
+ syn::Error::new(span, "there is no variant set as default")
+}