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/tools | |
| parent | 4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff) | |
chore: add vendor directory
Diffstat (limited to 'vendor/educe/src/common/tools')
| -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 |
3 files changed, 280 insertions, 0 deletions
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::*; |
