summaryrefslogtreecommitdiff
path: root/vendor/educe/src/common/tools
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/tools
parent4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff)
chore: add vendor directory
Diffstat (limited to 'vendor/educe/src/common/tools')
-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
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::*;