diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
| commit | 8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch) | |
| tree | 22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/educe/src/common | |
| parent | 4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff) | |
chore: add vendor directory
Diffstat (limited to 'vendor/educe/src/common')
| -rw-r--r-- | vendor/educe/src/common/bound.rs | 57 | ||||
| -rw-r--r-- | vendor/educe/src/common/expr.rs | 109 | ||||
| -rw-r--r-- | vendor/educe/src/common/ident_bool.rs | 161 | ||||
| -rw-r--r-- | vendor/educe/src/common/ident_index.rs | 56 | ||||
| -rw-r--r-- | vendor/educe/src/common/int.rs | 63 | ||||
| -rw-r--r-- | vendor/educe/src/common/mod.rs | 43 | ||||
| -rw-r--r-- | vendor/educe/src/common/path.rs | 43 | ||||
| -rw-r--r-- | vendor/educe/src/common/tools/discriminant_type.rs | 169 | ||||
| -rw-r--r-- | vendor/educe/src/common/tools/hash_type.rs | 100 | ||||
| -rw-r--r-- | vendor/educe/src/common/tools/mod.rs | 11 | ||||
| -rw-r--r-- | vendor/educe/src/common/type.rs | 51 | ||||
| -rw-r--r-- | vendor/educe/src/common/unsafe_punctuated_meta.rs | 35 | ||||
| -rw-r--r-- | vendor/educe/src/common/where_predicates_bool.rs | 122 |
13 files changed, 1020 insertions, 0 deletions
diff --git a/vendor/educe/src/common/bound.rs b/vendor/educe/src/common/bound.rs new file mode 100644 index 00000000..78f9aed4 --- /dev/null +++ b/vendor/educe/src/common/bound.rs @@ -0,0 +1,57 @@ +use syn::{punctuated::Punctuated, token::Comma, GenericParam, Meta, Path, Type, WherePredicate}; + +use crate::common::where_predicates_bool::{ + create_where_predicates_from_all_generic_parameters, + create_where_predicates_from_generic_parameters_check_types, meta_2_where_predicates, + WherePredicates, WherePredicatesOrBool, +}; + +pub(crate) enum Bound { + Disabled, + Auto, + Custom(WherePredicates), + All, +} + +impl Bound { + #[inline] + pub(crate) fn from_meta(meta: &Meta) -> syn::Result<Self> { + debug_assert!(meta.path().is_ident("bound")); + + Ok(match meta_2_where_predicates(meta)? { + WherePredicatesOrBool::WherePredicates(where_predicates) => { + Self::Custom(where_predicates) + }, + WherePredicatesOrBool::Bool(b) => { + if b { + Self::Auto + } else { + Self::Disabled + } + }, + WherePredicatesOrBool::All => Self::All, + }) + } +} + +impl Bound { + #[inline] + pub(crate) fn into_where_predicates_by_generic_parameters_check_types( + self, + params: &Punctuated<GenericParam, Comma>, + bound_trait: &Path, + types: &[&Type], + supertraits: &[proc_macro2::TokenStream], + ) -> Punctuated<WherePredicate, Comma> { + match self { + Self::Disabled => Punctuated::new(), + Self::Auto => create_where_predicates_from_generic_parameters_check_types( + bound_trait, + types, + supertraits, + ), + Self::Custom(where_predicates) => where_predicates, + Self::All => create_where_predicates_from_all_generic_parameters(params, bound_trait), + } + } +} diff --git a/vendor/educe/src/common/expr.rs b/vendor/educe/src/common/expr.rs new file mode 100644 index 00000000..ab49d3a0 --- /dev/null +++ b/vendor/educe/src/common/expr.rs @@ -0,0 +1,109 @@ +use quote::{quote, ToTokens}; +use syn::{spanned::Spanned, Expr, Lit, Meta, Type}; + +use super::path::path_to_string; + +const INT_TYPES: [&str; 12] = + ["u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize"]; + +const FLOAT_TYPES: [&str; 2] = ["f32", "f64"]; + +#[inline] +pub(crate) fn meta_2_expr(meta: &Meta) -> syn::Result<Expr> { + match &meta { + Meta::NameValue(name_value) => Ok(name_value.value.clone()), + Meta::List(list) => list.parse_args::<Expr>(), + Meta::Path(path) => Err(syn::Error::new( + path.span(), + format!("expected `{path} = Expr` or `{path}(Expr)`", path = path_to_string(path)), + )), + } +} + +#[inline] +pub(crate) fn auto_adjust_expr(expr: Expr, ty: Option<&Type>) -> Expr { + match &expr { + Expr::Lit(lit) => { + match &lit.lit { + Lit::Int(lit) => { + if let Some(Type::Path(ty)) = ty { + let ty_string = ty.into_token_stream().to_string(); + + if lit.suffix() == ty_string || INT_TYPES.contains(&ty_string.as_str()) { + // don't call into + return expr; + } + } + }, + Lit::Float(lit) => { + if let Some(Type::Path(ty)) = ty { + let ty_string = ty.into_token_stream().to_string(); + + if lit.suffix() == ty_string || FLOAT_TYPES.contains(&ty_string.as_str()) { + // don't call into + return expr; + } + } + }, + Lit::Str(_) => { + if let Some(Type::Reference(ty)) = ty { + let ty_string = ty.elem.clone().into_token_stream().to_string(); + + if ty_string == "str" { + // don't call into + return expr; + } + } + }, + Lit::Bool(_) => { + if let Some(Type::Path(ty)) = ty { + let ty_string = ty.into_token_stream().to_string(); + + if ty_string == "bool" { + // don't call into + return expr; + } + } + }, + Lit::Char(_) => { + if let Some(Type::Path(ty)) = ty { + let ty_string = ty.into_token_stream().to_string(); + + if ty_string == "char" { + // don't call into + return expr; + } + } + }, + Lit::Byte(_) => { + if let Some(Type::Path(ty)) = ty { + let ty_string = ty.into_token_stream().to_string(); + + if ty_string == "u8" { + // don't call into + return expr; + } + } + }, + Lit::ByteStr(_) => { + if let Some(Type::Reference(ty)) = ty { + if let Type::Array(ty) = ty.elem.as_ref() { + if let Type::Path(ty) = ty.elem.as_ref() { + let ty_string = ty.into_token_stream().to_string(); + + if ty_string == "u8" { + // don't call into + return expr; + } + } + } + } + }, + _ => (), + } + + syn::parse2(quote!(::core::convert::Into::into(#expr))).unwrap() + }, + _ => expr, + } +} diff --git a/vendor/educe/src/common/ident_bool.rs b/vendor/educe/src/common/ident_bool.rs new file mode 100644 index 00000000..89bf2fb9 --- /dev/null +++ b/vendor/educe/src/common/ident_bool.rs @@ -0,0 +1,161 @@ +use syn::{ + parse::{Parse, ParseStream}, + spanned::Spanned, + Expr, Ident, Lit, LitBool, LitStr, Meta, MetaNameValue, +}; + +use super::path::path_to_string; + +#[derive(Debug)] +pub(crate) enum IdentOrBool { + Ident(Ident), + Bool(bool), +} + +impl Parse for IdentOrBool { + #[inline] + fn parse(input: ParseStream) -> syn::Result<Self> { + if let Ok(lit) = input.parse::<Lit>() { + match lit { + Lit::Bool(lit) => return Ok(Self::Bool(lit.value)), + Lit::Str(lit) => { + return match lit.parse::<Ident>() { + Ok(ident) => Ok(Self::Ident(ident)), + Err(_) if lit.value().is_empty() => Ok(Self::Bool(false)), + Err(error) => Err(error), + } + }, + _ => (), + } + } + + Ok(Self::Ident(input.parse::<Ident>()?)) + } +} + +#[inline] +pub(crate) fn meta_name_value_2_ident(name_value: &MetaNameValue) -> syn::Result<Ident> { + match &name_value.value { + Expr::Lit(lit) => { + if let Lit::Str(lit) = &lit.lit { + return lit.parse(); + } + }, + Expr::Path(path) => { + if let Some(ident) = path.path.get_ident() { + return Ok(ident.clone()); + } + }, + _ => (), + } + + Err(syn::Error::new( + name_value.value.span(), + format!("expected `{path} = Ident`", path = path_to_string(&name_value.path)), + )) +} + +#[inline] +pub(crate) fn meta_2_ident(meta: &Meta) -> syn::Result<Ident> { + match &meta { + Meta::NameValue(name_value) => meta_name_value_2_ident(name_value), + Meta::List(list) => { + if let Ok(lit) = list.parse_args::<LitStr>() { + lit.parse() + } else { + list.parse_args() + } + }, + Meta::Path(path) => Err(syn::Error::new( + path.span(), + format!("expected `{path} = Ident` or `{path}(Ident)`", path = path_to_string(path)), + )), + } +} + +#[inline] +pub(crate) fn meta_name_value_2_bool(name_value: &MetaNameValue) -> syn::Result<bool> { + if let Expr::Lit(lit) = &name_value.value { + if let Lit::Bool(b) = &lit.lit { + return Ok(b.value); + } + } + + Err(syn::Error::new( + name_value.value.span(), + format!("expected `{path} = false`", path = path_to_string(&name_value.path)), + )) +} + +#[inline] +pub(crate) fn meta_2_bool(meta: &Meta) -> syn::Result<bool> { + match &meta { + Meta::NameValue(name_value) => meta_name_value_2_bool(name_value), + Meta::List(list) => Ok(list.parse_args::<LitBool>()?.value), + Meta::Path(path) => Err(syn::Error::new( + path.span(), + format!("expected `{path} = false` or `{path}(false)`", path = path_to_string(path)), + )), + } +} + +#[inline] +pub(crate) fn meta_2_bool_allow_path(meta: &Meta) -> syn::Result<bool> { + match &meta { + Meta::Path(_) => Ok(true), + Meta::NameValue(name_value) => meta_name_value_2_bool(name_value), + Meta::List(list) => Ok(list.parse_args::<LitBool>()?.value), + } +} + +#[inline] +pub(crate) fn meta_name_value_2_ident_and_bool( + name_value: &MetaNameValue, +) -> syn::Result<IdentOrBool> { + match &name_value.value { + Expr::Lit(lit) => match &lit.lit { + Lit::Str(lit) => match lit.parse::<Ident>() { + Ok(ident) => return Ok(IdentOrBool::Ident(ident)), + Err(_) if lit.value().is_empty() => { + return Ok(IdentOrBool::Bool(false)); + }, + Err(error) => { + return Err(error); + }, + }, + Lit::Bool(lit) => { + return Ok(IdentOrBool::Bool(lit.value)); + }, + _ => (), + }, + Expr::Path(path) => { + if let Some(ident) = path.path.get_ident() { + return Ok(IdentOrBool::Ident(ident.clone())); + } + }, + _ => (), + } + + Err(syn::Error::new( + name_value.value.span(), + format!( + "expected `{path} = Ident` or `{path} = false`", + path = path_to_string(&name_value.path) + ), + )) +} + +#[inline] +pub(crate) fn meta_2_ident_and_bool(meta: &Meta) -> syn::Result<IdentOrBool> { + match &meta { + Meta::NameValue(name_value) => meta_name_value_2_ident_and_bool(name_value), + Meta::List(list) => list.parse_args::<IdentOrBool>(), + Meta::Path(path) => Err(syn::Error::new( + path.span(), + format!( + "expected `{path} = Ident`, `{path}(Ident)`, `{path} = false`, or `{path}(false)`", + path = path_to_string(path) + ), + )), + } +} diff --git a/vendor/educe/src/common/ident_index.rs b/vendor/educe/src/common/ident_index.rs new file mode 100644 index 00000000..c0e38d49 --- /dev/null +++ b/vendor/educe/src/common/ident_index.rs @@ -0,0 +1,56 @@ +use quote::ToTokens; +use syn::{Ident, Index}; + +pub(crate) enum IdentOrIndex { + Ident(Ident), + Index(Index), +} + +impl From<Ident> for IdentOrIndex { + #[inline] + fn from(value: Ident) -> Self { + Self::Ident(value) + } +} + +impl From<Index> for IdentOrIndex { + #[inline] + fn from(value: Index) -> Self { + Self::Index(value) + } +} + +impl From<&Ident> for IdentOrIndex { + #[inline] + fn from(value: &Ident) -> Self { + Self::Ident(value.clone()) + } +} + +impl From<usize> for IdentOrIndex { + #[inline] + fn from(value: usize) -> Self { + Self::Index(Index::from(value)) + } +} + +impl ToTokens for IdentOrIndex { + #[inline] + fn to_tokens(&self, token_stream: &mut proc_macro2::TokenStream) { + match self { + Self::Ident(ident) => ToTokens::to_tokens(ident, token_stream), + Self::Index(index) => ToTokens::to_tokens(index, token_stream), + } + } +} + +impl IdentOrIndex { + #[inline] + pub(crate) fn from_ident_with_index(ident: Option<&Ident>, index: usize) -> IdentOrIndex { + if let Some(ident) = ident { + Self::from(ident) + } else { + Self::from(index) + } + } +} diff --git a/vendor/educe/src/common/int.rs b/vendor/educe/src/common/int.rs new file mode 100644 index 00000000..ae52b491 --- /dev/null +++ b/vendor/educe/src/common/int.rs @@ -0,0 +1,63 @@ +use syn::{spanned::Spanned, Expr, Lit, Meta, MetaNameValue, UnOp}; + +use super::path::path_to_string; + +#[inline] +pub(crate) fn meta_name_value_2_isize(name_value: &MetaNameValue) -> syn::Result<isize> { + match &name_value.value { + Expr::Lit(lit) => match &lit.lit { + Lit::Str(lit) => { + return lit + .value() + .parse::<isize>() + .map_err(|error| syn::Error::new(lit.span(), error)) + }, + Lit::Int(lit) => return lit.base10_parse(), + _ => (), + }, + Expr::Unary(unary) => { + if let UnOp::Neg(_) = unary.op { + if let Expr::Lit(lit) = unary.expr.as_ref() { + if let Lit::Int(lit) = &lit.lit { + let s = format!("-{}", lit.base10_digits()); + + return s + .parse::<isize>() + .map_err(|error| syn::Error::new(lit.span(), error)); + } + } + } + }, + _ => (), + } + + Err(syn::Error::new( + name_value.value.span(), + format!("expected `{path} = integer`", path = path_to_string(&name_value.path)), + )) +} + +#[inline] +pub(crate) fn meta_2_isize(meta: &Meta) -> syn::Result<isize> { + match &meta { + Meta::NameValue(name_value) => meta_name_value_2_isize(name_value), + Meta::List(list) => { + let lit = list.parse_args::<Lit>()?; + + match &lit { + Lit::Str(lit) => { + lit.value().parse::<isize>().map_err(|error| syn::Error::new(lit.span(), error)) + }, + Lit::Int(lit) => lit.base10_parse(), + _ => Err(syn::Error::new(lit.span(), "not an integer")), + } + }, + Meta::Path(path) => Err(syn::Error::new( + path.span(), + format!( + "expected `{path} = integer` or `{path}(integer)`", + path = path_to_string(path) + ), + )), + } +} diff --git a/vendor/educe/src/common/mod.rs b/vendor/educe/src/common/mod.rs new file mode 100644 index 00000000..79e10bb9 --- /dev/null +++ b/vendor/educe/src/common/mod.rs @@ -0,0 +1,43 @@ +#[allow(dead_code)] +pub(crate) mod bound; +#[allow(dead_code)] +pub(crate) mod path; +#[allow(dead_code)] +pub(crate) mod r#type; +#[allow(dead_code)] +pub(crate) mod where_predicates_bool; + +#[cfg(feature = "Default")] +#[allow(dead_code)] +pub(crate) mod expr; +#[cfg(any( + feature = "Debug", + feature = "PartialEq", + feature = "PartialOrd", + feature = "Ord", + feature = "Hash", + feature = "Default" +))] +#[allow(dead_code)] +pub(crate) mod ident_bool; +#[cfg(any( + feature = "Debug", + feature = "PartialEq", + feature = "PartialOrd", + feature = "Ord", + feature = "Hash", + feature = "Deref", + feature = "DerefMut", + feature = "Into" +))] +#[allow(dead_code)] +pub(crate) mod ident_index; +#[cfg(any(feature = "PartialOrd", feature = "Ord"))] +#[allow(dead_code)] +pub(crate) mod int; +#[cfg(any(feature = "Debug", feature = "PartialEq", feature = "Hash"))] +#[allow(dead_code)] +pub(crate) mod unsafe_punctuated_meta; + +#[cfg(any(feature = "PartialOrd", feature = "Ord", feature = "Into"))] +pub(crate) mod tools; diff --git a/vendor/educe/src/common/path.rs b/vendor/educe/src/common/path.rs new file mode 100644 index 00000000..18f80b24 --- /dev/null +++ b/vendor/educe/src/common/path.rs @@ -0,0 +1,43 @@ +use quote::ToTokens; +use syn::{spanned::Spanned, Expr, Lit, LitStr, Meta, MetaNameValue, Path}; + +#[inline] +pub(crate) fn meta_name_value_2_path(name_value: &MetaNameValue) -> syn::Result<Path> { + match &name_value.value { + Expr::Lit(lit) => { + if let Lit::Str(lit) = &lit.lit { + return lit.parse(); + } + }, + Expr::Path(path) => return Ok(path.path.clone()), + _ => (), + } + + Err(syn::Error::new( + name_value.value.span(), + format!("expected `{path} = Path`", path = path_to_string(&name_value.path)), + )) +} + +#[inline] +pub(crate) fn meta_2_path(meta: &Meta) -> syn::Result<Path> { + match &meta { + Meta::NameValue(name_value) => meta_name_value_2_path(name_value), + Meta::List(list) => { + if let Ok(lit) = list.parse_args::<LitStr>() { + lit.parse() + } else { + list.parse_args() + } + }, + Meta::Path(path) => Err(syn::Error::new( + path.span(), + format!("expected `{path} = Path` or `{path}(Path)`", path = path_to_string(path)), + )), + } +} + +#[inline] +pub(crate) fn path_to_string(path: &Path) -> String { + path.into_token_stream().to_string().replace(' ', "") +} diff --git a/vendor/educe/src/common/tools/discriminant_type.rs b/vendor/educe/src/common/tools/discriminant_type.rs new file mode 100644 index 00000000..5bc0d2f8 --- /dev/null +++ b/vendor/educe/src/common/tools/discriminant_type.rs @@ -0,0 +1,169 @@ +use proc_macro2::{Ident, Span, TokenStream}; +use quote::{ToTokens, TokenStreamExt}; +use syn::{ + punctuated::Punctuated, spanned::Spanned, Data, DeriveInput, Expr, Lit, Meta, Token, UnOp, +}; + +#[derive(Debug)] +pub(crate) enum DiscriminantType { + ISize, + I8, + I16, + I32, + I64, + I128, + USize, + U8, + U16, + U32, + U64, + U128, +} + +impl DiscriminantType { + #[inline] + pub(crate) fn parse_str<S: AsRef<str>>(s: S) -> Option<Self> { + match s.as_ref() { + "i8" => Some(Self::I8), + "i16" => Some(Self::I16), + "i32" => Some(Self::I32), + "i64" => Some(Self::I64), + "i128" => Some(Self::I128), + "isize" => Some(Self::ISize), + "u8" => Some(Self::U8), + "u16" => Some(Self::U16), + "u32" => Some(Self::U32), + "u64" => Some(Self::U64), + "u128" => Some(Self::U128), + "usize" => Some(Self::USize), + _ => None, + } + } + + #[inline] + pub(crate) const fn as_str(&self) -> &'static str { + match self { + Self::ISize => "isize", + Self::I8 => "i8", + Self::I16 => "i16", + Self::I32 => "i32", + Self::I64 => "i64", + Self::I128 => "i128", + Self::USize => "usize", + Self::U8 => "u8", + Self::U16 => "u16", + Self::U32 => "u32", + Self::U64 => "u64", + Self::U128 => "u128", + } + } +} + +impl ToTokens for DiscriminantType { + #[inline] + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.append(Ident::new(self.as_str(), Span::call_site())); + } +} + +impl DiscriminantType { + pub(crate) fn from_ast(ast: &DeriveInput) -> syn::Result<Self> { + if let Data::Enum(data) = &ast.data { + for attr in ast.attrs.iter() { + if attr.path().is_ident("repr") { + // #[repr(u8)], #[repr(u16)], ..., etc. + if let Meta::List(list) = &attr.meta { + let result = + list.parse_args_with(Punctuated::<Ident, Token![,]>::parse_terminated)?; + + if let Some(value) = result.into_iter().next() { + if let Some(t) = Self::parse_str(value.to_string()) { + return Ok(t); + } + } + } + } + } + + let mut min = i128::MAX; + let mut max = i128::MIN; + let mut counter = 0i128; + + for variant in data.variants.iter() { + if let Some((_, exp)) = variant.discriminant.as_ref() { + match exp { + Expr::Lit(lit) => { + if let Lit::Int(lit) = &lit.lit { + counter = lit + .base10_parse() + .map_err(|error| syn::Error::new(lit.span(), error))?; + } else { + return Err(syn::Error::new(lit.span(), "not an integer")); + } + }, + Expr::Unary(unary) => { + if let UnOp::Neg(_) = unary.op { + if let Expr::Lit(lit) = unary.expr.as_ref() { + if let Lit::Int(lit) = &lit.lit { + match lit.base10_parse::<i128>() { + Ok(i) => { + counter = -i; + }, + Err(error) => { + // overflow + if lit.base10_digits() + == "170141183460469231731687303715884105728" + { + counter = i128::MIN; + } else { + return Err(syn::Error::new(lit.span(), error)); + } + }, + } + } else { + return Err(syn::Error::new(lit.span(), "not an integer")); + } + } else { + return Err(syn::Error::new( + unary.expr.span(), + "not a literal", + )); + } + } else { + return Err(syn::Error::new( + unary.op.span(), + "this operation is not allow here", + )); + } + }, + _ => return Err(syn::Error::new(exp.span(), "not a literal")), + } + } + + if min > counter { + min = counter; + } + + if max < counter { + max = counter; + } + + counter = counter.saturating_add(1); + } + + Ok(if min >= i8::MIN as i128 && max <= i8::MAX as i128 { + Self::I8 + } else if min >= i16::MIN as i128 && max <= i16::MAX as i128 { + Self::I16 + } else if min >= i32::MIN as i128 && max <= i32::MAX as i128 { + Self::I32 + } else if min >= i64::MIN as i128 && max <= i64::MAX as i128 { + Self::I64 + } else { + Self::I128 + }) + } else { + Err(syn::Error::new(ast.span(), "not an enum")) + } + } +} diff --git a/vendor/educe/src/common/tools/hash_type.rs b/vendor/educe/src/common/tools/hash_type.rs new file mode 100644 index 00000000..ece3d03f --- /dev/null +++ b/vendor/educe/src/common/tools/hash_type.rs @@ -0,0 +1,100 @@ +use std::{ + cmp::Ordering, + fmt::{self, Display, Formatter}, + hash::{Hash, Hasher}, + str::FromStr, +}; + +use proc_macro2::Span; +use quote::ToTokens; +use syn::{spanned::Spanned, Path, Type}; + +#[derive(Debug, Clone)] +pub(crate) struct HashType(String, Span); + +impl PartialEq for HashType { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.0.eq(&other.0) + } +} + +impl Eq for HashType {} + +impl PartialOrd for HashType { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl Ord for HashType { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.0.cmp(&other.0) + } +} + +impl Hash for HashType { + #[inline] + fn hash<H: Hasher>(&self, state: &mut H) { + Hash::hash(&self.0, state); + } +} + +impl Display for HashType { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0.replace("& '", "&'"), f) + } +} + +impl From<Type> for HashType { + #[inline] + fn from(value: Type) -> Self { + Self::from(&value) + } +} + +impl From<&Type> for HashType { + #[inline] + fn from(value: &Type) -> Self { + Self(value.into_token_stream().to_string(), value.span()) + } +} + +impl From<Path> for HashType { + #[inline] + fn from(value: Path) -> Self { + Self::from(&value) + } +} + +impl From<&Path> for HashType { + #[inline] + fn from(value: &Path) -> Self { + Self(value.into_token_stream().to_string(), value.span()) + } +} + +#[allow(dead_code)] +impl HashType { + #[inline] + pub(crate) fn to_type(&self) -> Type { + syn::parse_str(self.0.as_str()).unwrap() + } + + #[inline] + pub(crate) fn span(&self) -> Span { + self.1 + } +} + +impl ToTokens for HashType { + #[inline] + fn to_tokens(&self, token_stream: &mut proc_macro2::TokenStream) { + let ty = proc_macro2::TokenStream::from_str(self.0.as_str()).unwrap(); + + token_stream.extend(ty); + } +} diff --git a/vendor/educe/src/common/tools/mod.rs b/vendor/educe/src/common/tools/mod.rs new file mode 100644 index 00000000..23cb4970 --- /dev/null +++ b/vendor/educe/src/common/tools/mod.rs @@ -0,0 +1,11 @@ +#[cfg(any(feature = "PartialOrd", feature = "Ord"))] +mod discriminant_type; + +#[cfg(any(feature = "PartialOrd", feature = "Ord"))] +pub(crate) use discriminant_type::*; + +#[cfg(feature = "Into")] +mod hash_type; + +#[cfg(feature = "Into")] +pub(crate) use hash_type::*; diff --git a/vendor/educe/src/common/type.rs b/vendor/educe/src/common/type.rs new file mode 100644 index 00000000..c17ed73b --- /dev/null +++ b/vendor/educe/src/common/type.rs @@ -0,0 +1,51 @@ +use syn::{ + parse::{Parse, ParseStream}, + punctuated::Punctuated, + Meta, Token, Type, +}; + +pub(crate) struct TypeWithPunctuatedMeta { + pub(crate) ty: Type, + pub(crate) list: Punctuated<Meta, Token![,]>, +} + +impl Parse for TypeWithPunctuatedMeta { + #[inline] + fn parse(input: ParseStream) -> syn::Result<Self> { + let ty = input.parse::<Type>()?; + + if input.is_empty() { + return Ok(Self { + ty, + list: Punctuated::new(), + }); + } + + input.parse::<Token![,]>()?; + + let list = input.parse_terminated(Meta::parse, Token![,])?; + + Ok(Self { + ty, + list, + }) + } +} + +#[inline] +pub(crate) fn dereference(ty: &Type) -> &Type { + if let Type::Reference(ty) = ty { + dereference(ty.elem.as_ref()) + } else { + ty + } +} + +#[inline] +pub(crate) fn dereference_changed(ty: &Type) -> (&Type, bool) { + if let Type::Reference(ty) = ty { + (dereference(ty.elem.as_ref()), true) + } else { + (ty, false) + } +} diff --git a/vendor/educe/src/common/unsafe_punctuated_meta.rs b/vendor/educe/src/common/unsafe_punctuated_meta.rs new file mode 100644 index 00000000..e8ec103b --- /dev/null +++ b/vendor/educe/src/common/unsafe_punctuated_meta.rs @@ -0,0 +1,35 @@ +use syn::{ + parse::{Parse, ParseStream}, + punctuated::Punctuated, + Meta, Token, +}; + +pub(crate) struct UnsafePunctuatedMeta { + pub(crate) list: Punctuated<Meta, Token![,]>, + pub(crate) has_unsafe: bool, +} + +impl Parse for UnsafePunctuatedMeta { + #[inline] + fn parse(input: ParseStream) -> syn::Result<Self> { + let has_unsafe = input.parse::<Token![unsafe]>().is_ok(); + + if input.is_empty() { + return Ok(Self { + list: Punctuated::new(), + has_unsafe, + }); + } + + if has_unsafe { + input.parse::<Token![,]>()?; + } + + let list = input.parse_terminated(Meta::parse, Token![,])?; + + Ok(Self { + list, + has_unsafe, + }) + } +} diff --git a/vendor/educe/src/common/where_predicates_bool.rs b/vendor/educe/src/common/where_predicates_bool.rs new file mode 100644 index 00000000..4aa3695c --- /dev/null +++ b/vendor/educe/src/common/where_predicates_bool.rs @@ -0,0 +1,122 @@ +use quote::{quote, ToTokens}; +use syn::{ + parse::{Parse, ParseStream}, + punctuated::Punctuated, + spanned::Spanned, + token::Comma, + Expr, GenericParam, Lit, Meta, MetaNameValue, Path, Token, Type, WherePredicate, +}; + +use super::path::path_to_string; + +pub(crate) type WherePredicates = Punctuated<WherePredicate, Token![,]>; + +pub(crate) enum WherePredicatesOrBool { + WherePredicates(WherePredicates), + Bool(bool), + All, +} + +impl WherePredicatesOrBool { + fn from_lit(lit: &Lit) -> syn::Result<Self> { + Ok(match lit { + Lit::Bool(lit) => Self::Bool(lit.value), + Lit::Str(lit) => match lit.parse_with(WherePredicates::parse_terminated) { + Ok(where_predicates) => Self::WherePredicates(where_predicates), + Err(_) if lit.value().is_empty() => Self::Bool(false), + Err(error) => return Err(error), + }, + other => { + return Err(syn::Error::new( + other.span(), + "unexpected kind of literal (only boolean or string allowed)", + )) + }, + }) + } +} + +impl Parse for WherePredicatesOrBool { + #[inline] + fn parse(input: ParseStream) -> syn::Result<Self> { + if let Ok(lit) = input.parse::<Lit>() { + return Self::from_lit(&lit); + } + + if let Ok(_star) = input.parse::<Token![*]>() { + return Ok(Self::All); + } + + Ok(Self::WherePredicates(input.parse_terminated(WherePredicate::parse, Token![,])?)) + } +} + +#[inline] +pub(crate) fn meta_name_value_2_where_predicates_bool( + name_value: &MetaNameValue, +) -> syn::Result<WherePredicatesOrBool> { + if let Expr::Lit(lit) = &name_value.value { + return WherePredicatesOrBool::from_lit(&lit.lit); + } + + Err(syn::Error::new( + name_value.value.span(), + format!( + "expected `{path} = \"where_predicates\"` or `{path} = false`", + path = path_to_string(&name_value.path) + ), + )) +} + +#[inline] +pub(crate) fn meta_2_where_predicates(meta: &Meta) -> syn::Result<WherePredicatesOrBool> { + match &meta { + Meta::NameValue(name_value) => meta_name_value_2_where_predicates_bool(name_value), + Meta::List(list) => list.parse_args::<WherePredicatesOrBool>(), + Meta::Path(path) => Err(syn::Error::new( + path.span(), + format!( + "expected `{path} = \"where_predicates\"`, `{path}(where_predicates)`, `{path} = \ + false`, or `{path}(false)`", + path = path.clone().into_token_stream() + ), + )), + } +} + +#[inline] +pub(crate) fn create_where_predicates_from_all_generic_parameters( + params: &Punctuated<GenericParam, Comma>, + bound_trait: &Path, +) -> WherePredicates { + let mut where_predicates = Punctuated::new(); + + for param in params { + if let GenericParam::Type(ty) = param { + let ident = &ty.ident; + + where_predicates.push(syn::parse2(quote! { #ident: #bound_trait }).unwrap()); + } + } + + where_predicates +} + +#[inline] +pub(crate) fn create_where_predicates_from_generic_parameters_check_types( + bound_trait: &Path, + types: &[&Type], + supertraits: &[proc_macro2::TokenStream], +) -> WherePredicates { + let mut where_predicates = Punctuated::new(); + + for t in types { + where_predicates.push(syn::parse2(quote! { #t: #bound_trait }).unwrap()); + } + + for supertrait in supertraits { + where_predicates.push(syn::parse2(quote! { Self: #supertrait }).unwrap()); + } + + where_predicates +} |
