summaryrefslogtreecommitdiff
path: root/vendor/educe/src/common
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/common
parent4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff)
chore: add vendor directory
Diffstat (limited to 'vendor/educe/src/common')
-rw-r--r--vendor/educe/src/common/bound.rs57
-rw-r--r--vendor/educe/src/common/expr.rs109
-rw-r--r--vendor/educe/src/common/ident_bool.rs161
-rw-r--r--vendor/educe/src/common/ident_index.rs56
-rw-r--r--vendor/educe/src/common/int.rs63
-rw-r--r--vendor/educe/src/common/mod.rs43
-rw-r--r--vendor/educe/src/common/path.rs43
-rw-r--r--vendor/educe/src/common/tools/discriminant_type.rs169
-rw-r--r--vendor/educe/src/common/tools/hash_type.rs100
-rw-r--r--vendor/educe/src/common/tools/mod.rs11
-rw-r--r--vendor/educe/src/common/type.rs51
-rw-r--r--vendor/educe/src/common/unsafe_punctuated_meta.rs35
-rw-r--r--vendor/educe/src/common/where_predicates_bool.rs122
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
+}