summaryrefslogtreecommitdiff
path: root/vendor/educe/src/trait_handlers/debug
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/educe/src/trait_handlers/debug')
-rw-r--r--vendor/educe/src/trait_handlers/debug/common.rs55
-rw-r--r--vendor/educe/src/trait_handlers/debug/debug_enum.rs371
-rw-r--r--vendor/educe/src/trait_handlers/debug/debug_struct.rs185
-rw-r--r--vendor/educe/src/trait_handlers/debug/debug_union.rs86
-rw-r--r--vendor/educe/src/trait_handlers/debug/mod.rs38
-rw-r--r--vendor/educe/src/trait_handlers/debug/models/field_attribute.rs224
-rw-r--r--vendor/educe/src/trait_handlers/debug/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/debug/models/type_attribute.rs264
-rw-r--r--vendor/educe/src/trait_handlers/debug/panic.rs43
9 files changed, 1271 insertions, 0 deletions
diff --git a/vendor/educe/src/trait_handlers/debug/common.rs b/vendor/educe/src/trait_handlers/debug/common.rs
new file mode 100644
index 00000000..e2c59a9d
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/common.rs
@@ -0,0 +1,55 @@
+use quote::quote;
+use syn::{DeriveInput, Path, Type};
+
+#[inline]
+pub(crate) fn create_debug_map_builder() -> proc_macro2::TokenStream {
+ quote!(
+ #[allow(non_camel_case_types)] // We're using __ to help avoid clashes.
+ struct Educe__RawString(&'static str);
+
+ impl ::core::fmt::Debug for Educe__RawString {
+ #[inline]
+ fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
+ f.write_str(self.0)
+ }
+ }
+
+ let mut builder = f.debug_map();
+ )
+}
+
+#[inline]
+pub(crate) fn create_format_arg(
+ ast: &DeriveInput,
+ field_ty: &Type,
+ format_method: &Path,
+ field_expr: proc_macro2::TokenStream,
+) -> proc_macro2::TokenStream {
+ let ty_ident = &ast.ident;
+
+ // We use the complete original generics, not filtered by field,
+ // and include a PhantomData<Self> in our wrapper struct to use the generics.
+ //
+ // This avoids having to try to calculate the right *subset* of the generics
+ // relevant for this field, which is nontrivial and maybe impossible.
+ let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
+
+ quote!(
+ let arg = {
+ #[allow(non_camel_case_types)] // We're using __ to help avoid clashes.
+ struct Educe__DebugField<V, M>(V, ::core::marker::PhantomData<M>);
+
+ impl #impl_generics ::core::fmt::Debug
+ for Educe__DebugField<&#field_ty, #ty_ident #ty_generics>
+ #where_clause
+ {
+ #[inline]
+ fn fmt(&self, educe__f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
+ #format_method(self.0, educe__f)
+ }
+ }
+
+ Educe__DebugField(#field_expr, ::core::marker::PhantomData::<Self>)
+ };
+ )
+}
diff --git a/vendor/educe/src/trait_handlers/debug/debug_enum.rs b/vendor/educe/src/trait_handlers/debug/debug_enum.rs
new file mode 100644
index 00000000..1e423818
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/debug_enum.rs
@@ -0,0 +1,371 @@
+use quote::{format_ident, quote, ToTokens};
+use syn::{Data, DeriveInput, Fields, Meta, Type};
+
+use super::models::{FieldAttributeBuilder, FieldName, TypeAttributeBuilder, TypeName};
+use crate::{common::path::path_to_string, supported_traits::Trait, trait_handlers::TraitHandler};
+
+pub(crate) struct DebugEnumHandler;
+
+impl TraitHandler for DebugEnumHandler {
+ 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_unsafe: false,
+ enable_name: true,
+ enable_named_field: false,
+ enable_bound: true,
+ name: TypeName::Disable,
+ named_field: false,
+ }
+ .build_from_debug_meta(meta)?;
+
+ let name = type_attribute.name.to_ident_by_ident(&ast.ident);
+
+ let mut debug_types: Vec<&Type> = Vec::new();
+
+ let mut builder_token_stream = proc_macro2::TokenStream::new();
+
+ let mut arms_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Enum(data) = &ast.data {
+ for variant in data.variants.iter() {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: false,
+ enable_unsafe: false,
+ enable_name: true,
+ enable_named_field: true,
+ enable_bound: false,
+ name: TypeName::Default,
+ named_field: matches!(&variant.fields, Fields::Named(_)),
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ let variant_ident = &variant.ident;
+
+ let variant_name = type_attribute.name.to_ident_by_ident(variant_ident);
+
+ let named_field = type_attribute.named_field;
+
+ let name_string = if let Some(name) = name {
+ if let Some(variant_name) = variant_name {
+ Some(path_to_string(&syn::parse2(quote!(#name::#variant_name)).unwrap()))
+ } else {
+ Some(name.into_token_stream().to_string())
+ }
+ } else {
+ variant_name.map(|variant_name| variant_name.into_token_stream().to_string())
+ };
+
+ match &variant.fields {
+ Fields::Unit => {
+ if name_string.is_none() {
+ return Err(super::panic::unit_variant_need_name(variant));
+ }
+
+ arms_token_stream
+ .extend(quote!( Self::#variant_ident => f.write_str(#name_string), ));
+ },
+ Fields::Named(fields) => {
+ let mut has_fields = false;
+
+ let mut pattern_token_stream = proc_macro2::TokenStream::new();
+ let mut block_token_stream = proc_macro2::TokenStream::new();
+
+ if named_field {
+ block_token_stream
+ .extend(create_named_field_builder(name_string.as_deref()));
+
+ for field in fields.named.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: true,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ let field_name_real = field.ident.as_ref().unwrap();
+ let field_name_var = format_ident!("_{}", field_name_real);
+
+ if field_attribute.ignore {
+ pattern_token_stream.extend(quote!(#field_name_real: _,));
+
+ continue;
+ }
+
+ let key = match field_attribute.name {
+ FieldName::Custom(name) => name,
+ FieldName::Default => field_name_real.clone(),
+ };
+
+ pattern_token_stream
+ .extend(quote!(#field_name_real: #field_name_var,));
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ block_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(#field_name_var),
+ ));
+
+ block_token_stream.extend(if name_string.is_some() {
+ quote! (builder.field(stringify!(#key), &arg);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), &arg);)
+ });
+ } else {
+ debug_types.push(ty);
+
+ block_token_stream.extend(if name_string.is_some() {
+ quote! (builder.field(stringify!(#key), #field_name_var);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), #field_name_var);)
+ });
+ }
+
+ has_fields = true;
+ }
+ } else {
+ block_token_stream
+ .extend(quote!(let mut builder = f.debug_tuple(#name_string);));
+
+ for field in fields.named.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: false,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ let field_name_real = field.ident.as_ref().unwrap();
+ let field_name_var = format_ident!("_{}", field_name_real);
+
+ if field_attribute.ignore {
+ pattern_token_stream.extend(quote!(#field_name_real: _,));
+
+ continue;
+ }
+
+ pattern_token_stream
+ .extend(quote!(#field_name_real: #field_name_var,));
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ block_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(#field_name_var),
+ ));
+
+ block_token_stream.extend(quote! (builder.field(&arg);));
+ } else {
+ debug_types.push(ty);
+
+ block_token_stream
+ .extend(quote! (builder.field(#field_name_var);));
+ }
+
+ has_fields = true;
+ }
+ }
+
+ if !has_fields && name_string.is_none() {
+ return Err(super::panic::unit_struct_need_name(variant_ident));
+ }
+
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident { #pattern_token_stream } => {
+ #block_token_stream
+
+ builder.finish()
+ },
+ });
+ },
+ Fields::Unnamed(fields) => {
+ let mut has_fields = false;
+
+ let mut pattern_token_stream = proc_macro2::TokenStream::new();
+ let mut block_token_stream = proc_macro2::TokenStream::new();
+
+ if named_field {
+ block_token_stream
+ .extend(create_named_field_builder(name_string.as_deref()));
+
+ for (index, field) in fields.unnamed.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: true,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ pattern_token_stream.extend(quote!(_,));
+
+ continue;
+ }
+
+ let field_name_var = format_ident!("_{}", index);
+
+ let key = match field_attribute.name {
+ FieldName::Custom(name) => name,
+ FieldName::Default => field_name_var.clone(),
+ };
+
+ pattern_token_stream.extend(quote!(#field_name_var,));
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ block_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(#field_name_var),
+ ));
+
+ block_token_stream.extend(if name_string.is_some() {
+ quote! (builder.field(stringify!(#key), &arg);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), &arg);)
+ });
+ } else {
+ debug_types.push(ty);
+
+ block_token_stream.extend(if name_string.is_some() {
+ quote! (builder.field(stringify!(#key), #field_name_var);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), #field_name_var);)
+ });
+ }
+
+ has_fields = true;
+ }
+ } else {
+ block_token_stream
+ .extend(quote!(let mut builder = f.debug_tuple(#name_string);));
+
+ for (index, field) in fields.unnamed.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: false,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ pattern_token_stream.extend(quote!(_,));
+
+ continue;
+ }
+
+ let field_name_var = format_ident!("_{}", index);
+
+ pattern_token_stream.extend(quote!(#field_name_var,));
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ block_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(#field_name_var),
+ ));
+
+ block_token_stream.extend(quote! (builder.field(&arg);));
+ } else {
+ debug_types.push(ty);
+
+ block_token_stream
+ .extend(quote! (builder.field(#field_name_var);));
+ }
+
+ has_fields = true;
+ }
+ }
+
+ if !has_fields && name_string.is_none() {
+ return Err(super::panic::unit_struct_need_name(variant_ident));
+ }
+
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident ( #pattern_token_stream ) => {
+ #block_token_stream
+
+ builder.finish()
+ },
+ });
+ },
+ }
+ }
+ }
+
+ let ident = &ast.ident;
+
+ if arms_token_stream.is_empty() {
+ if let Some(ident) = name {
+ builder_token_stream.extend(quote! {
+ f.write_str(stringify!(#ident))
+ });
+ } else {
+ return Err(super::panic::unit_enum_need_name(ident));
+ }
+ } else {
+ builder_token_stream.extend(quote! {
+ match self {
+ #arms_token_stream
+ }
+ });
+ }
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::fmt::Debug)).unwrap(),
+ &debug_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::fmt::Debug for #ident #ty_generics #where_clause {
+ #[inline]
+ fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
+ #builder_token_stream
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
+
+#[inline]
+fn create_named_field_builder(name_string: Option<&str>) -> proc_macro2::TokenStream {
+ if let Some(name_string) = name_string {
+ quote!(let mut builder = f.debug_struct(#name_string);)
+ } else {
+ super::common::create_debug_map_builder()
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/debug/debug_struct.rs b/vendor/educe/src/trait_handlers/debug/debug_struct.rs
new file mode 100644
index 00000000..6430480b
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/debug_struct.rs
@@ -0,0 +1,185 @@
+use quote::{format_ident, quote};
+use syn::{Data, DeriveInput, Fields, Meta, Type};
+
+use super::{
+ models::{FieldAttributeBuilder, FieldName, TypeAttributeBuilder, TypeName},
+ TraitHandler,
+};
+use crate::{common::ident_index::IdentOrIndex, Trait};
+
+pub struct DebugStructHandler;
+
+impl TraitHandler for DebugStructHandler {
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let is_tuple = {
+ if let Data::Struct(data) = &ast.data {
+ matches!(data.fields, Fields::Unnamed(_))
+ } else {
+ true
+ }
+ };
+
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_unsafe: false,
+ enable_name: true,
+ enable_named_field: true,
+ enable_bound: true,
+ name: TypeName::Default,
+ named_field: !is_tuple,
+ }
+ .build_from_debug_meta(meta)?;
+
+ let name = type_attribute.name.to_ident_by_ident(&ast.ident);
+
+ let mut debug_types: Vec<&Type> = Vec::new();
+
+ let mut builder_token_stream = proc_macro2::TokenStream::new();
+ let mut has_fields = false;
+
+ if type_attribute.named_field {
+ builder_token_stream.extend(if let Some(name) = name {
+ quote!(let mut builder = f.debug_struct(stringify!(#name));)
+ } else {
+ super::common::create_debug_map_builder()
+ });
+
+ if let Data::Struct(data) = &ast.data {
+ for (index, field) in data.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: true,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ continue;
+ }
+
+ let (key, field_name) = match field_attribute.name {
+ FieldName::Custom(name) => {
+ (name, IdentOrIndex::from_ident_with_index(field.ident.as_ref(), index))
+ },
+ FieldName::Default => {
+ if let Some(ident) = field.ident.as_ref() {
+ (ident.clone(), IdentOrIndex::from(ident))
+ } else {
+ (format_ident!("_{}", index), IdentOrIndex::from(index))
+ }
+ },
+ };
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ builder_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(&self.#field_name),
+ ));
+
+ builder_token_stream.extend(if name.is_some() {
+ quote! (builder.field(stringify!(#key), &arg);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), &arg);)
+ });
+ } else {
+ debug_types.push(ty);
+
+ builder_token_stream.extend(if name.is_some() {
+ quote! (builder.field(stringify!(#key), &self.#field_name);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), &self.#field_name);)
+ });
+ }
+
+ has_fields = true;
+ }
+ }
+ } else {
+ builder_token_stream
+ .extend(quote!(let mut builder = f.debug_tuple(stringify!(#name));));
+
+ if let Data::Struct(data) = &ast.data {
+ for (index, field) in data.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: false,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ continue;
+ }
+
+ let field_name =
+ IdentOrIndex::from_ident_with_index(field.ident.as_ref(), index);
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ builder_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(&self.#field_name),
+ ));
+
+ builder_token_stream.extend(quote! (builder.field(&arg);));
+ } else {
+ debug_types.push(ty);
+
+ builder_token_stream.extend(quote! (builder.field(&self.#field_name);));
+ }
+
+ has_fields = true;
+ }
+ }
+ }
+
+ let ident = &ast.ident;
+
+ if !has_fields && name.is_none() {
+ return Err(super::panic::unit_struct_need_name(ident));
+ }
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::fmt::Debug)).unwrap(),
+ &debug_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::fmt::Debug for #ident #ty_generics #where_clause {
+ #[inline]
+ fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
+ #builder_token_stream
+
+ builder.finish()
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/debug/debug_union.rs b/vendor/educe/src/trait_handlers/debug/debug_union.rs
new file mode 100644
index 00000000..096ea776
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/debug_union.rs
@@ -0,0 +1,86 @@
+use quote::quote;
+use syn::{Data, DeriveInput, Meta};
+
+use super::{
+ models::{FieldAttributeBuilder, FieldName, TypeAttributeBuilder, TypeName},
+ TraitHandler,
+};
+use crate::supported_traits::Trait;
+
+pub(crate) struct DebugUnionHandler;
+
+impl TraitHandler for DebugUnionHandler {
+ 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_unsafe: true,
+ enable_name: true,
+ enable_named_field: false,
+ enable_bound: false,
+ name: TypeName::Default,
+ named_field: false,
+ }
+ .build_from_debug_meta(meta)?;
+
+ if !type_attribute.has_unsafe {
+ return Err(super::panic::union_without_unsafe(meta));
+ }
+
+ let name = type_attribute.name.to_ident_by_ident(&ast.ident);
+
+ let mut builder_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Union(data) = &ast.data {
+ for field in data.fields.named.iter() {
+ let _ = FieldAttributeBuilder {
+ enable_name: false,
+ enable_ignore: false,
+ enable_method: false,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+ }
+
+ if let Some(name) = name {
+ builder_token_stream.extend(quote!(
+ let mut builder = f.debug_tuple(stringify!(#name));
+
+ let size = ::core::mem::size_of::<Self>();
+
+ let data = unsafe { ::core::slice::from_raw_parts(self as *const Self as *const u8, size) };
+
+ builder.field(&data);
+
+ builder.finish()
+ ));
+ } else {
+ builder_token_stream.extend(quote!(
+ let size = ::core::mem::size_of::<Self>();
+ let data = unsafe { ::core::slice::from_raw_parts(self as *const Self as *const u8, size) };
+
+ ::core::fmt::Debug::fmt(data, f)
+ ));
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::fmt::Debug for #ident #ty_generics #where_clause {
+ #[inline]
+ fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
+ #builder_token_stream
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/debug/mod.rs b/vendor/educe/src/trait_handlers/debug/mod.rs
new file mode 100644
index 00000000..367ddb71
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/mod.rs
@@ -0,0 +1,38 @@
+mod common;
+mod debug_enum;
+mod debug_struct;
+mod debug_union;
+mod models;
+mod panic;
+
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandler;
+use crate::Trait;
+
+pub(crate) struct DebugHandler;
+
+impl TraitHandler for DebugHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ match ast.data {
+ Data::Struct(_) => debug_struct::DebugStructHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Enum(_) => {
+ debug_enum::DebugEnumHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ Data::Union(_) => {
+ debug_union::DebugUnionHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ }
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/debug/models/field_attribute.rs b/vendor/educe/src/trait_handlers/debug/models/field_attribute.rs
new file mode 100644
index 00000000..f2cd3e28
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/models/field_attribute.rs
@@ -0,0 +1,224 @@
+use syn::{punctuated::Punctuated, Attribute, Ident, Meta, Path, Token};
+
+use crate::{
+ common::{
+ ident_bool::{
+ meta_2_bool_allow_path, meta_2_ident, meta_name_value_2_bool, meta_name_value_2_ident,
+ meta_name_value_2_ident_and_bool, IdentOrBool,
+ },
+ path::meta_2_path,
+ },
+ panic,
+ supported_traits::Trait,
+};
+
+#[derive(Debug, Clone)]
+pub(crate) enum FieldName {
+ Default,
+ Custom(Ident),
+}
+
+pub(crate) struct FieldAttribute {
+ pub(crate) name: FieldName,
+ pub(crate) ignore: bool,
+ pub(crate) method: Option<Path>,
+}
+
+pub(crate) struct FieldAttributeBuilder {
+ pub(crate) enable_name: bool,
+ pub(crate) enable_ignore: bool,
+ pub(crate) enable_method: bool,
+ pub(crate) name: FieldName,
+}
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_debug_meta(&self, meta: &Meta) -> syn::Result<FieldAttribute> {
+ debug_assert!(meta.path().is_ident("Debug"));
+
+ let mut name = self.name.clone();
+ let mut ignore = false;
+ let mut method = None;
+
+ let correct_usage_for_debug_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_name {
+ usage.push(stringify!(#[educe(Debug = NewName)]));
+ usage.push(stringify!(#[educe(Debug(name(NewName)))]));
+ }
+
+ if self.enable_ignore {
+ usage.push(stringify!(#[educe(Debug = false)]));
+ usage.push(stringify!(#[educe(Debug(ignore))]));
+ }
+
+ if self.enable_method {
+ usage.push(stringify!(#[educe(Debug(method(path_to_method)))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_debug_attribute,
+ ));
+ },
+ Meta::NameValue(name_value) => {
+ if self.enable_name {
+ if self.enable_ignore {
+ match meta_name_value_2_ident_and_bool(name_value)? {
+ IdentOrBool::Ident(ident) => {
+ name = FieldName::Custom(ident);
+ },
+ IdentOrBool::Bool(b) => {
+ ignore = !b;
+ },
+ }
+ } else {
+ name = FieldName::Custom(meta_name_value_2_ident(name_value)?);
+ }
+ } else if self.enable_ignore {
+ ignore = !meta_name_value_2_bool(name_value)?;
+ } else {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_debug_attribute,
+ ));
+ }
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut name_is_set = false;
+ let mut ignore_is_set = false;
+ let mut method_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() {
+ "name" | "rename" => {
+ if !self.enable_name {
+ return Ok(false);
+ }
+
+ let v = meta_2_ident(&meta)?;
+
+ if name_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ name_is_set = true;
+
+ name = FieldName::Custom(v);
+
+ return Ok(true);
+ },
+ "ignore" => {
+ if !self.enable_ignore {
+ return Ok(false);
+ }
+
+ let v = meta_2_bool_allow_path(&meta)?;
+
+ if ignore_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ ignore_is_set = true;
+
+ ignore = v;
+
+ return Ok(true);
+ },
+ "method" => {
+ if !self.enable_method {
+ return Ok(false);
+ }
+
+ let v = meta_2_path(&meta)?;
+
+ if method_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ method_is_set = true;
+
+ method = Some(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_debug_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(FieldAttribute {
+ name,
+ ignore,
+ method,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> 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::Debug {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_debug_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(FieldAttribute {
+ name: self.name.clone(),
+ ignore: false,
+ method: None,
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/debug/models/mod.rs b/vendor/educe/src/trait_handlers/debug/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/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/debug/models/type_attribute.rs b/vendor/educe/src/trait_handlers/debug/models/type_attribute.rs
new file mode 100644
index 00000000..ed84ddf3
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/models/type_attribute.rs
@@ -0,0 +1,264 @@
+use proc_macro2::Ident;
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{
+ common::{
+ bound::Bound,
+ ident_bool::{meta_2_bool, meta_2_ident_and_bool, meta_name_value_2_ident, IdentOrBool},
+ unsafe_punctuated_meta::UnsafePunctuatedMeta,
+ },
+ panic, Trait,
+};
+
+#[derive(Debug, Clone)]
+pub(crate) enum TypeName {
+ Disable,
+ Default,
+ Custom(Ident),
+}
+
+impl TypeName {
+ #[inline]
+ pub(crate) fn to_ident_by_ident<'a, 'b: 'a>(&'a self, ident: &'b Ident) -> Option<&'a Ident> {
+ match self {
+ Self::Disable => None,
+ Self::Default => Some(ident),
+ Self::Custom(ident) => Some(ident),
+ }
+ }
+}
+
+pub(crate) struct TypeAttribute {
+ pub(crate) has_unsafe: bool,
+ pub(crate) name: TypeName,
+ pub(crate) named_field: bool,
+ pub(crate) bound: Bound,
+}
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_flag: bool,
+ pub(crate) enable_unsafe: bool,
+ pub(crate) enable_name: bool,
+ pub(crate) enable_named_field: bool,
+ pub(crate) enable_bound: bool,
+ pub(crate) name: TypeName,
+ pub(crate) named_field: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_debug_meta(&self, meta: &Meta) -> syn::Result<TypeAttribute> {
+ debug_assert!(meta.path().is_ident("Debug"));
+
+ let mut has_unsafe = false;
+ let mut name = self.name.clone();
+ let mut named_field = self.named_field;
+ let mut bound = Bound::Auto;
+
+ let correct_usage_for_debug_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(Debug)]));
+ }
+
+ if self.enable_name {
+ if !self.enable_unsafe {
+ usage.push(stringify!(#[educe(Debug = NewName)]));
+ }
+
+ usage.push(stringify!(#[educe(Debug(name(NewName)))]));
+
+ if let TypeName::Disable = &name {
+ usage.push(stringify!(#[educe(Debug(name = true))]));
+ } else {
+ usage.push(stringify!(#[educe(Debug(name = false))]));
+ }
+ }
+
+ if self.enable_named_field {
+ if !self.named_field {
+ usage.push(stringify!(#[educe(Debug(named_field = true))]));
+ } else {
+ usage.push(stringify!(#[educe(Debug(named_field = false))]));
+ }
+ }
+
+ if self.enable_bound {
+ usage.push(stringify!(#[educe(Debug(bound(where_predicates)))]));
+ usage.push(stringify!(#[educe(Debug(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_debug_attribute,
+ ));
+ }
+ },
+ Meta::NameValue(name_value) => {
+ if !self.enable_name {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_debug_attribute,
+ ));
+ }
+
+ name = TypeName::Custom(meta_name_value_2_ident(name_value)?);
+ },
+ Meta::List(list) => {
+ let result = if self.enable_unsafe {
+ let result: UnsafePunctuatedMeta = list.parse_args()?;
+
+ has_unsafe = result.has_unsafe;
+
+ result.list
+ } else {
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?
+ };
+
+ let mut name_is_set = false;
+ let mut named_field_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() {
+ "name" | "rename" => {
+ if !self.enable_name {
+ return Ok(false);
+ }
+
+ let v = meta_2_ident_and_bool(&meta)?;
+
+ if name_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ name_is_set = true;
+
+ name = match v {
+ IdentOrBool::Ident(ident) => TypeName::Custom(ident),
+ IdentOrBool::Bool(b) => {
+ if b {
+ TypeName::Default
+ } else {
+ TypeName::Disable
+ }
+ },
+ };
+
+ return Ok(true);
+ },
+ "named_field" => {
+ if !self.enable_named_field {
+ return Ok(false);
+ }
+
+ let v = meta_2_bool(&meta)?;
+
+ if named_field_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ named_field_is_set = true;
+
+ named_field = v;
+
+ 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_debug_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(TypeAttribute {
+ has_unsafe,
+ name,
+ named_field,
+ bound,
+ })
+ }
+
+ 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::Debug {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_debug_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(TypeAttribute {
+ has_unsafe: false,
+ name: self.name.clone(),
+ named_field: self.named_field,
+ bound: Bound::Auto,
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/debug/panic.rs b/vendor/educe/src/trait_handlers/debug/panic.rs
new file mode 100644
index 00000000..a29646a7
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/panic.rs
@@ -0,0 +1,43 @@
+use quote::ToTokens;
+use syn::{spanned::Spanned, Ident, Meta, Variant};
+
+#[inline]
+pub(crate) fn unit_struct_need_name(name: &Ident) -> syn::Error {
+ syn::Error::new(name.span(), "a unit struct needs to have a name")
+}
+
+#[inline]
+pub(crate) fn unit_variant_need_name(variant: &Variant) -> syn::Error {
+ syn::Error::new(
+ variant.span(),
+ "a unit variant which doesn't use an enum name needs to have a name",
+ )
+}
+
+#[inline]
+pub(crate) fn unit_enum_need_name(name: &Ident) -> syn::Error {
+ syn::Error::new(name.span(), "a unit enum needs to have a name")
+}
+
+#[inline]
+pub(crate) fn union_without_unsafe(meta: &Meta) -> syn::Error {
+ let mut s = meta.into_token_stream().to_string().replace(" , ", ", ");
+
+ match s.len() {
+ 5 => s.push_str("(unsafe)"),
+ 7 => s.insert_str(6, "unsafe"),
+ _ => s.insert_str(6, "unsafe, "),
+ }
+
+ syn::Error::new(
+ meta.span(),
+ format!(
+ "a union's `Debug` implementation may expose uninitialized memory\n* It is \
+ recommended that, for a union where `Debug` is implemented, types that allow \
+ uninitialized memory should not be used in it.\n* If you can ensure that the union \
+ uses no such types, use `#[educe({s})]` to implement the `Debug` trait for it.\n* \
+ The `unsafe` keyword should be placed as the first parameter of the `Debug` \
+ attribute."
+ ),
+ )
+}