From 8cdfa445d6629ffef4cb84967ff7017654045bc2 Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 2 Jul 2025 18:36:06 -0600 Subject: chore: add vendor directory --- vendor/enum-ordinalize-derive/.cargo-checksum.json | 1 + vendor/enum-ordinalize-derive/Cargo.toml | 53 ++ vendor/enum-ordinalize-derive/LICENSE | 21 + vendor/enum-ordinalize-derive/README.md | 20 + vendor/enum-ordinalize-derive/src/int128.rs | 167 +++++ vendor/enum-ordinalize-derive/src/int_wrapper.rs | 57 ++ vendor/enum-ordinalize-derive/src/lib.rs | 808 +++++++++++++++++++++ vendor/enum-ordinalize-derive/src/panic.rs | 83 +++ vendor/enum-ordinalize-derive/src/variant_type.rs | 75 ++ 9 files changed, 1285 insertions(+) create mode 100644 vendor/enum-ordinalize-derive/.cargo-checksum.json create mode 100644 vendor/enum-ordinalize-derive/Cargo.toml create mode 100644 vendor/enum-ordinalize-derive/LICENSE create mode 100644 vendor/enum-ordinalize-derive/README.md create mode 100644 vendor/enum-ordinalize-derive/src/int128.rs create mode 100644 vendor/enum-ordinalize-derive/src/int_wrapper.rs create mode 100644 vendor/enum-ordinalize-derive/src/lib.rs create mode 100644 vendor/enum-ordinalize-derive/src/panic.rs create mode 100644 vendor/enum-ordinalize-derive/src/variant_type.rs (limited to 'vendor/enum-ordinalize-derive') diff --git a/vendor/enum-ordinalize-derive/.cargo-checksum.json b/vendor/enum-ordinalize-derive/.cargo-checksum.json new file mode 100644 index 00000000..9eee33e6 --- /dev/null +++ b/vendor/enum-ordinalize-derive/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"e08fa63e6cef52de7befa61700f0ebb389d803c778e0689a15a34506cbbb5e15","LICENSE":"dd0741aba702705d02da3e18fca5d3a27538fe6c983e9f09946e82ecfc59acab","README.md":"8f1ed96e3631c27e38af090ec060aefd4999d683fb3090786b46a8d1a2ed688e","src/int128.rs":"4dd502fa528d75a7f55bd17107e1ba1fc4a710025d10bbc24514fb56777f314a","src/int_wrapper.rs":"c16c57ab57f005b34a6776d07d3fb257380b99262701b3972c957fe9bcb698b5","src/lib.rs":"e9aab14cc9f279fbd66a1ff465f786c15ec1860cab14da3e9b64e879ee027680","src/panic.rs":"0d71b9e870d6e773f3d7f80884b34f21aa7ca12651498d666faea4afcee27cec","src/variant_type.rs":"3a4cc4107b7b91f061efc7deab437c05a973897b79c1babf73ec3d918d2b5fd9"},"package":"0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff"} \ No newline at end of file diff --git a/vendor/enum-ordinalize-derive/Cargo.toml b/vendor/enum-ordinalize-derive/Cargo.toml new file mode 100644 index 00000000..2aff73b4 --- /dev/null +++ b/vendor/enum-ordinalize-derive/Cargo.toml @@ -0,0 +1,53 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.60" +name = "enum-ordinalize-derive" +version = "4.3.1" +include = [ + "src/**/*", + "Cargo.toml", + "README.md", + "LICENSE", +] +description = "This crate provides a procedural macro that enables enums to not only obtain the ordinal values of their variants but also allows for the construction of enums from an ordinal value." +homepage = "https://magiclen.org/enum-ordinalize" +readme = "README.md" +keywords = [ + "enum", + "ordinal", + "ordinalize", + "number", +] +categories = [ + "no-std", + "rust-patterns", +] +license = "MIT" +repository = "https://github.com/magiclen/enum-ordinalize" + +[lib] +proc-macro = true + +[dependencies.proc-macro2] +version = "1" + +[dependencies.quote] +version = "1" + +[dependencies.syn] +version = "2" + +[features] +default = [] +traits = [] diff --git a/vendor/enum-ordinalize-derive/LICENSE b/vendor/enum-ordinalize-derive/LICENSE new file mode 100644 index 00000000..ba1efc6c --- /dev/null +++ b/vendor/enum-ordinalize-derive/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 magiclen.org (Ron Li) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/enum-ordinalize-derive/README.md b/vendor/enum-ordinalize-derive/README.md new file mode 100644 index 00000000..a55369ab --- /dev/null +++ b/vendor/enum-ordinalize-derive/README.md @@ -0,0 +1,20 @@ +Enum Ordinalize Derive +==================== + +[![CI](https://github.com/magiclen/enum-ordinalize/actions/workflows/ci.yml/badge.svg)](https://github.com/magiclen/enum-ordinalize/actions/workflows/ci.yml) + +This crate provides a procedural macro that enables enums to not only obtain the ordinal values of their variants but also allows for the construction of enums from an ordinal value. + +See the [`enum-ordinalize`](https://crates.io/crates/enum-ordinalize) crate. + +## Crates.io + +https://crates.io/crates/enum-ordinalize + +## Documentation + +https://docs.rs/enum-ordinalize + +## License + +[MIT](LICENSE) \ No newline at end of file diff --git a/vendor/enum-ordinalize-derive/src/int128.rs b/vendor/enum-ordinalize-derive/src/int128.rs new file mode 100644 index 00000000..755dcd7c --- /dev/null +++ b/vendor/enum-ordinalize-derive/src/int128.rs @@ -0,0 +1,167 @@ +use core::{ + cmp::Ordering, + fmt::{self, Display, Formatter}, + num::ParseIntError, + ops::Neg, + str::FromStr, +}; + +#[derive(Debug, Copy, Eq, Clone)] +pub(crate) enum Int128 { + Signed(i128), + Unsigned(u128), +} + +impl PartialEq for Int128 { + #[inline] + fn eq(&self, other: &Int128) -> bool { + match self { + Self::Signed(i) => match other { + Self::Signed(i2) => i.eq(i2), + Self::Unsigned(u2) => { + if i.is_negative() { + false + } else { + (*i as u128).eq(u2) + } + }, + }, + Self::Unsigned(u) => match other { + Self::Signed(i2) => { + if i2.is_negative() { + false + } else { + u.eq(&(*i2 as u128)) + } + }, + Self::Unsigned(u2) => u.eq(u2), + }, + } + } +} + +impl PartialOrd for Int128 { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Int128 { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + match self { + Self::Signed(i) => match other { + Self::Signed(i2) => i.cmp(i2), + Self::Unsigned(u2) => { + if i.is_negative() { + Ordering::Less + } else { + (*i as u128).cmp(u2) + } + }, + }, + Self::Unsigned(u) => match other { + Self::Signed(i2) => { + if i2.is_negative() { + Ordering::Greater + } else { + u.cmp(&(*i2 as u128)) + } + }, + Self::Unsigned(u2) => u.cmp(u2), + }, + } + } +} + +impl Display for Int128 { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + Self::Signed(i) => Display::fmt(i, f), + Self::Unsigned(u) => Display::fmt(u, f), + } + } +} + +impl Default for Int128 { + #[inline] + fn default() -> Self { + Self::ZERO + } +} + +impl Int128 { + pub(crate) const ZERO: Self = Self::Unsigned(0); +} + +macro_rules! impl_from_signed { + (@inner $t: ty) => { + impl From<$t> for Int128 { + #[inline] + fn from(value: $t) -> Self { + Int128::Signed(value as i128) + } + } + }; + ($($t: ty),+ $(,)*) => { + $( + impl_from_signed!(@inner $t); + )* + }; +} + +impl_from_signed!(i8, i16, i32, i64, i128, isize); + +impl FromStr for Int128 { + type Err = ParseIntError; + + #[inline] + fn from_str(s: &str) -> Result { + if s.starts_with('-') { + Ok(Self::Signed(s.parse()?)) + } else { + Ok(Self::Unsigned(s.parse()?)) + } + } +} + +impl Neg for Int128 { + type Output = Int128; + + fn neg(self) -> Self::Output { + match self { + Self::Signed(i) => { + if i == i128::MIN { + Self::Unsigned(1 << 127) + } else { + Self::Signed(-i) + } + }, + Self::Unsigned(u) => match u.cmp(&(1 << 127)) { + Ordering::Equal => Self::Signed(i128::MIN), + Ordering::Less => Self::Signed(-(u as i128)), + Ordering::Greater => panic!("-{} is experiencing an overflow", u), + }, + } + } +} + +impl Int128 { + #[inline] + pub(crate) fn inc(&mut self) { + match self { + Self::Signed(i) => { + if *i == i128::MAX { + *self = Self::Unsigned(1 << 127) + } else { + *i += 1; + } + }, + Self::Unsigned(u) => { + *u = u.saturating_add(1); + }, + } + } +} diff --git a/vendor/enum-ordinalize-derive/src/int_wrapper.rs b/vendor/enum-ordinalize-derive/src/int_wrapper.rs new file mode 100644 index 00000000..3747325d --- /dev/null +++ b/vendor/enum-ordinalize-derive/src/int_wrapper.rs @@ -0,0 +1,57 @@ +use proc_macro2::{Literal, TokenStream}; +use quote::{quote, ToTokens, TokenStreamExt}; +use syn::Expr; + +use crate::int128::Int128; + +pub(crate) enum IntWrapper { + Integer(Int128), + Constant(Expr, usize), +} + +impl From for IntWrapper { + #[inline] + fn from(v: Int128) -> IntWrapper { + Self::Integer(v) + } +} + +impl From for IntWrapper { + #[inline] + fn from(v: i128) -> IntWrapper { + Self::Integer(Int128::from(v)) + } +} + +impl From<(&Expr, usize)> for IntWrapper { + #[inline] + fn from((expr, counter): (&Expr, usize)) -> IntWrapper { + Self::Constant(expr.clone(), counter) + } +} + +impl ToTokens for IntWrapper { + #[inline] + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + Self::Integer(v) => { + let lit = match v { + Int128::Signed(i) => Literal::i128_unsuffixed(*i), + Int128::Unsigned(u) => Literal::u128_unsuffixed(*u), + }; + + tokens.append(lit); + }, + Self::Constant(expr, counter) => { + let counter = *counter; + + if counter > 0 { + tokens.extend(quote!(#expr +)); + tokens.append(Literal::usize_unsuffixed(counter)); + } else { + tokens.extend(quote!(#expr)); + } + }, + } + } +} diff --git a/vendor/enum-ordinalize-derive/src/lib.rs b/vendor/enum-ordinalize-derive/src/lib.rs new file mode 100644 index 00000000..5af4b2ca --- /dev/null +++ b/vendor/enum-ordinalize-derive/src/lib.rs @@ -0,0 +1,808 @@ +/*! +# Enum Ordinalize Derive + +This library enables enums to not only obtain the ordinal values of their variants but also allows for the construction of enums from an ordinal value. See the [`enum-ordinalize`](https://crates.io/crates/enum-ordinalize) crate. +*/ + +#![no_std] + +#[macro_use] +extern crate alloc; + +mod int128; +mod int_wrapper; +mod panic; +mod variant_type; + +use alloc::{string::ToString, vec::Vec}; + +use proc_macro::TokenStream; +use quote::quote; +use syn::{ + parse::{Parse, ParseStream}, + parse_macro_input, + punctuated::Punctuated, + spanned::Spanned, + Data, DeriveInput, Expr, Fields, Ident, Lit, Meta, Token, UnOp, Visibility, +}; +use variant_type::VariantType; + +use crate::{int128::Int128, int_wrapper::IntWrapper}; + +#[proc_macro_derive(Ordinalize, attributes(ordinalize))] +pub fn ordinalize_derive(input: TokenStream) -> TokenStream { + struct ConstMember { + vis: Option, + ident: Ident, + meta: Vec, + function: bool, + } + + impl Parse for ConstMember { + #[inline] + fn parse(input: ParseStream) -> syn::Result { + let vis = input.parse::().ok(); + + let _ = input.parse::(); + + let function = input.parse::().is_ok(); + + let ident = input.parse::()?; + + let mut meta = Vec::new(); + + if !input.is_empty() { + input.parse::()?; + + if !input.is_empty() { + let result = Punctuated::::parse_terminated(input)?; + + let mut has_inline = false; + + for m in result { + if m.path().is_ident("inline") { + has_inline = true; + } + + meta.push(m); + } + + if !has_inline { + meta.push(syn::parse_str("inline")?); + } + } + } + + Ok(Self { + vis, + ident, + meta, + function, + }) + } + } + + struct ConstFunctionMember { + vis: Option, + ident: Ident, + meta: Vec, + } + + impl Parse for ConstFunctionMember { + #[inline] + fn parse(input: ParseStream) -> syn::Result { + let vis = input.parse::().ok(); + + let _ = input.parse::(); + + input.parse::()?; + + let ident = input.parse::()?; + + let mut meta = Vec::new(); + + if !input.is_empty() { + input.parse::()?; + + if !input.is_empty() { + let result = Punctuated::::parse_terminated(input)?; + + let mut has_inline = false; + + for m in result { + if m.path().is_ident("inline") { + has_inline = true; + } + + meta.push(m); + } + + if !has_inline { + meta.push(syn::parse_str("inline")?); + } + } + } + + Ok(Self { + vis, + ident, + meta, + }) + } + } + + struct MyDeriveInput { + ast: DeriveInput, + variant_type: VariantType, + values: Vec, + variant_idents: Vec, + use_constant_counter: bool, + enable_trait: bool, + enable_variant_count: Option, + enable_variants: Option, + enable_values: Option, + enable_from_ordinal_unsafe: Option, + enable_from_ordinal: Option, + enable_ordinal: Option, + } + + impl Parse for MyDeriveInput { + fn parse(input: ParseStream) -> syn::Result { + let ast = input.parse::()?; + + let mut variant_type = VariantType::default(); + let mut enable_trait = cfg!(feature = "traits"); + let mut enable_variant_count = None; + let mut enable_variants = None; + let mut enable_values = None; + let mut enable_from_ordinal_unsafe = None; + let mut enable_from_ordinal = None; + let mut enable_ordinal = None; + + for attr in ast.attrs.iter() { + let path = attr.path(); + + if let Some(ident) = path.get_ident() { + match ident.to_string().as_str() { + "repr" => { + // #[repr(u8)], #[repr(u16)], ..., etc. + if let Meta::List(list) = &attr.meta { + let result = list.parse_args_with( + Punctuated::::parse_terminated, + )?; + + if let Some(value) = result.into_iter().next() { + variant_type = VariantType::from_str(value.to_string()); + } + } + + break; + }, + "ordinalize" => { + if let Meta::List(list) = &attr.meta { + let result = list.parse_args_with( + Punctuated::::parse_terminated, + )?; + + for meta in result { + let path = meta.path(); + + if let Some(ident) = path.get_ident() { + match ident.to_string().as_str() { + "impl_trait" => { + if let Meta::NameValue(meta) = &meta { + if let Expr::Lit(lit) = &meta.value { + if let Lit::Bool(value) = &lit.lit { + if cfg!(feature = "traits") { + enable_trait = value.value; + } + } else { + return Err( + panic::bool_attribute_usage( + ident, + ident.span(), + ), + ); + } + } else { + return Err(panic::bool_attribute_usage( + ident, + ident.span(), + )); + } + } else { + return Err(panic::bool_attribute_usage( + ident, + ident.span(), + )); + } + }, + "variant_count" => { + if let Meta::List(list) = &meta { + enable_variant_count = Some(list.parse_args()?); + } else { + return Err(panic::list_attribute_usage( + ident, + ident.span(), + )); + } + }, + "variants" => { + if let Meta::List(list) = &meta { + enable_variants = Some(list.parse_args()?); + } else { + return Err(panic::list_attribute_usage( + ident, + ident.span(), + )); + } + }, + "values" => { + if let Meta::List(list) = &meta { + enable_values = Some(list.parse_args()?); + } else { + return Err(panic::list_attribute_usage( + ident, + ident.span(), + )); + } + }, + "from_ordinal_unsafe" => { + if let Meta::List(list) = &meta { + enable_from_ordinal_unsafe = + Some(list.parse_args()?); + } else { + return Err(panic::list_attribute_usage( + ident, + ident.span(), + )); + } + }, + "from_ordinal" => { + if let Meta::List(list) = &meta { + enable_from_ordinal = Some(list.parse_args()?); + } else { + return Err(panic::list_attribute_usage( + ident, + ident.span(), + )); + } + }, + "ordinal" => { + if let Meta::List(list) = &meta { + enable_ordinal = Some(list.parse_args()?); + } else { + return Err(panic::list_attribute_usage( + ident, + ident.span(), + )); + } + }, + _ => { + return Err(panic::sub_attributes_for_ordinalize( + ident.span(), + )); + }, + } + } else { + return Err(panic::list_attribute_usage( + ident, + ident.span(), + )); + } + } + } else { + return Err(panic::list_attribute_usage(ident, ident.span())); + } + }, + _ => (), + } + } + } + + let name = &ast.ident; + + if let Data::Enum(data) = &ast.data { + let variant_count = data.variants.len(); + + if variant_count == 0 { + return Err(panic::no_variant(name.span())); + } + + let mut values: Vec = Vec::with_capacity(variant_count); + let mut variant_idents: Vec = Vec::with_capacity(variant_count); + + let mut use_constant_counter = false; + + if let VariantType::NonDetermined = variant_type { + let mut min = i128::MAX; + let mut max = i128::MIN; + let mut counter = 0; + + for variant in data.variants.iter() { + if let Fields::Unit = variant.fields { + 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(panic::unsupported_discriminant( + lit.span(), + )); + } + }, + Expr::Unary(unary) => { + if let UnOp::Neg(_) = unary.op { + match unary.expr.as_ref() { + Expr::Lit(lit) => { + if let Lit::Int(lit) = &lit.lit { + match lit.base10_parse::() { + 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(panic::unsupported_discriminant(lit.span())); + } + }, + Expr::Path(_) + | Expr::Cast(_) + | Expr::Binary(_) + | Expr::Call(_) => { + return Err(panic::constant_variable_on_non_determined_size_enum(unary.expr.span())) + }, + _ => return Err(panic::unsupported_discriminant(unary.expr.span())), + } + } else { + return Err(panic::unsupported_discriminant( + unary.op.span(), + )); + } + }, + Expr::Path(_) + | Expr::Cast(_) + | Expr::Binary(_) + | Expr::Call(_) => { + return Err( + panic::constant_variable_on_non_determined_size_enum( + exp.span(), + ), + ) + }, + _ => return Err(panic::unsupported_discriminant(exp.span())), + } + }; + + if min > counter { + min = counter; + } + + if max < counter { + max = counter; + } + + variant_idents.push(variant.ident.clone()); + + values.push(IntWrapper::from(counter)); + + counter = counter.saturating_add(1); + } else { + return Err(panic::not_unit_variant(variant.span())); + } + } + + if min >= i8::MIN as i128 && max <= i8::MAX as i128 { + variant_type = VariantType::I8; + } else if min >= i16::MIN as i128 && max <= i16::MAX as i128 { + variant_type = VariantType::I16; + } else if min >= i32::MIN as i128 && max <= i32::MAX as i128 { + variant_type = VariantType::I32; + } else if min >= i64::MIN as i128 && max <= i64::MAX as i128 { + variant_type = VariantType::I64; + } else { + variant_type = VariantType::I128; + } + } else { + let mut counter = Int128::ZERO; + let mut constant_counter = 0; + let mut last_exp: Option<&Expr> = None; + + for variant in data.variants.iter() { + if let Fields::Unit = variant.fields { + 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) + })?; + + values.push(IntWrapper::from(counter)); + + counter.inc(); + + last_exp = None; + } else { + return Err(panic::unsupported_discriminant( + lit.span(), + )); + } + }, + Expr::Unary(unary) => { + if let UnOp::Neg(_) = unary.op { + match unary.expr.as_ref() { + Expr::Lit(lit) => { + if let Lit::Int(lit) = &lit.lit { + counter = -lit.base10_parse().map_err( + |error| { + syn::Error::new(lit.span(), error) + }, + )?; + + values.push(IntWrapper::from(counter)); + + counter.inc(); + + last_exp = None; + } else { + return Err( + panic::unsupported_discriminant( + lit.span(), + ), + ); + } + }, + Expr::Path(_) => { + values.push(IntWrapper::from((exp, 0))); + + last_exp = Some(exp); + constant_counter = 1; + }, + Expr::Cast(_) | Expr::Binary(_) | Expr::Call(_) => { + values.push(IntWrapper::from((exp, 0))); + + last_exp = Some(exp); + constant_counter = 1; + + use_constant_counter = true; + }, + _ => { + return Err(panic::unsupported_discriminant( + exp.span(), + )); + }, + } + } else { + return Err(panic::unsupported_discriminant( + unary.op.span(), + )); + } + }, + Expr::Path(_) => { + values.push(IntWrapper::from((exp, 0))); + + last_exp = Some(exp); + constant_counter = 1; + }, + Expr::Cast(_) | Expr::Binary(_) | Expr::Call(_) => { + values.push(IntWrapper::from((exp, 0))); + + last_exp = Some(exp); + constant_counter = 1; + + use_constant_counter = true; + }, + _ => return Err(panic::unsupported_discriminant(exp.span())), + } + } else if let Some(exp) = last_exp { + values.push(IntWrapper::from((exp, constant_counter))); + + constant_counter += 1; + + use_constant_counter = true; + } else { + values.push(IntWrapper::from(counter)); + + counter.inc(); + } + + variant_idents.push(variant.ident.clone()); + } else { + return Err(panic::not_unit_variant(variant.span())); + } + } + } + + Ok(MyDeriveInput { + ast, + variant_type, + values, + variant_idents, + use_constant_counter, + enable_trait, + enable_variant_count, + enable_variants, + enable_values, + enable_from_ordinal_unsafe, + enable_from_ordinal, + enable_ordinal, + }) + } else { + Err(panic::not_enum(ast.ident.span())) + } + } + } + + // Parse the token stream + let derive_input = parse_macro_input!(input as MyDeriveInput); + + let MyDeriveInput { + ast, + variant_type, + values, + variant_idents, + use_constant_counter, + enable_trait, + enable_variant_count, + enable_variants, + enable_values, + enable_ordinal, + enable_from_ordinal_unsafe, + enable_from_ordinal, + } = derive_input; + + // Get the identifier of the type. + let name = &ast.ident; + + let variant_count = values.len(); + + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); + + // Build the code + let mut expanded = proc_macro2::TokenStream::new(); + + if enable_trait { + #[cfg(feature = "traits")] + { + let from_ordinal_unsafe = if variant_count == 1 { + let variant_ident = &variant_idents[0]; + + quote! { + #[inline] + unsafe fn from_ordinal_unsafe(_number: #variant_type) -> Self { + Self::#variant_ident + } + } + } else { + quote! { + #[inline] + unsafe fn from_ordinal_unsafe(number: #variant_type) -> Self { + ::core::mem::transmute(number) + } + } + }; + + let from_ordinal = if use_constant_counter { + quote! { + #[inline] + fn from_ordinal(number: #variant_type) -> Option { + if false { + unreachable!() + } #( else if number == #values { + Some(Self::#variant_idents) + } )* else { + None + } + } + } + } else { + quote! { + #[inline] + fn from_ordinal(number: #variant_type) -> Option { + match number{ + #( + #values => Some(Self::#variant_idents), + )* + _ => None + } + } + } + }; + + expanded.extend(quote! { + impl #impl_generics Ordinalize for #name #ty_generics #where_clause { + type VariantType = #variant_type; + + const VARIANT_COUNT: usize = #variant_count; + + const VARIANTS: &'static [Self] = &[#( Self::#variant_idents, )*]; + + const VALUES: &'static [#variant_type] = &[#( #values, )*]; + + #[inline] + fn ordinal(&self) -> #variant_type { + match self { + #( + Self::#variant_idents => #values, + )* + } + } + + #from_ordinal_unsafe + + #from_ordinal + } + }); + } + } + + let mut expanded_2 = proc_macro2::TokenStream::new(); + + if let Some(ConstMember { + vis, + ident, + meta, + function, + }) = enable_variant_count + { + expanded_2.extend(if function { + quote! { + #(#[#meta])* + #vis const fn #ident () -> usize { + #variant_count + } + } + } else { + quote! { + #(#[#meta])* + #vis const #ident: usize = #variant_count; + } + }); + } + + if let Some(ConstMember { + vis, + ident, + meta, + function, + }) = enable_variants + { + expanded_2.extend(if function { + quote! { + #(#[#meta])* + #vis const fn #ident () -> [Self; #variant_count] { + [#( Self::#variant_idents, )*] + } + } + } else { + quote! { + #(#[#meta])* + #vis const #ident: [Self; #variant_count] = [#( Self::#variant_idents, )*]; + } + }); + } + + if let Some(ConstMember { + vis, + ident, + meta, + function, + }) = enable_values + { + expanded_2.extend(if function { + quote! { + #(#[#meta])* + #vis const fn #ident () -> [#variant_type; #variant_count] { + [#( #values, )*] + } + } + } else { + quote! { + #(#[#meta])* + #vis const #ident: [#variant_type; #variant_count] = [#( #values, )*]; + } + }); + } + + if let Some(ConstFunctionMember { + vis, + ident, + meta, + }) = enable_from_ordinal_unsafe + { + let from_ordinal_unsafe = if variant_count == 1 { + let variant_ident = &variant_idents[0]; + + quote! { + #(#[#meta])* + #vis const unsafe fn #ident (_number: #variant_type) -> Self { + Self::#variant_ident + } + } + } else { + quote! { + #(#[#meta])* + #vis const unsafe fn #ident (number: #variant_type) -> Self { + ::core::mem::transmute(number) + } + } + }; + + expanded_2.extend(from_ordinal_unsafe); + } + + if let Some(ConstFunctionMember { + vis, + ident, + meta, + }) = enable_from_ordinal + { + let from_ordinal = if use_constant_counter { + quote! { + #(#[#meta])* + #vis const fn #ident (number: #variant_type) -> Option { + if false { + unreachable!() + } #( else if number == #values { + Some(Self::#variant_idents) + } )* else { + None + } + } + } + } else { + quote! { + #(#[#meta])* + #vis const fn #ident (number: #variant_type) -> Option { + match number{ + #( + #values => Some(Self::#variant_idents), + )* + _ => None + } + } + } + }; + + expanded_2.extend(from_ordinal); + } + + if let Some(ConstFunctionMember { + vis, + ident, + meta, + }) = enable_ordinal + { + expanded_2.extend(quote! { + #(#[#meta])* + #vis const fn #ident (&self) -> #variant_type { + match self { + #( + Self::#variant_idents => #values, + )* + } + } + }); + } + + if !expanded_2.is_empty() { + expanded.extend(quote! { + impl #impl_generics #name #ty_generics #where_clause { + #expanded_2 + } + }); + } + + expanded.into() +} diff --git a/vendor/enum-ordinalize-derive/src/panic.rs b/vendor/enum-ordinalize-derive/src/panic.rs new file mode 100644 index 00000000..5066656f --- /dev/null +++ b/vendor/enum-ordinalize-derive/src/panic.rs @@ -0,0 +1,83 @@ +use core::fmt::{self, Display, Formatter}; + +use proc_macro2::Span; +use syn::Ident; + +struct DisplayStringSlice<'a>(&'a [&'static str]); + +impl<'a> Display for DisplayStringSlice<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + for &s in self.0 { + f.write_str("\n ")?; + f.write_str(s)?; + } + + Ok(()) + } +} + +#[inline] +pub(crate) fn not_enum(span: Span) -> syn::Error { + syn::Error::new(span, "only enums can be ordinalized") +} + +#[inline] +pub(crate) fn no_variant(span: Span) -> syn::Error { + syn::Error::new(span, "an ordinalized enum needs to have at least one variant") +} + +#[inline] +pub(crate) fn not_unit_variant(span: Span) -> syn::Error { + syn::Error::new(span, "an ordinalized enum can only have unit variants") +} + +#[inline] +pub(crate) fn unsupported_discriminant(span: Span) -> syn::Error { + syn::Error::new( + span, + "the discriminant of a variant of an ordinalized enum needs to be a legal literal \ + integer, a constant variable/function or a constant expression", + ) +} +#[inline] +pub(crate) fn constant_variable_on_non_determined_size_enum(span: Span) -> syn::Error { + syn::Error::new( + span, + "the discriminant of a variant can be assigned not to a literal integer only when the \ + ordinalized enum is using the `repr` attribute to determine it's size before compilation", + ) +} + +#[inline] +pub fn list_attribute_usage(name: &Ident, span: Span) -> syn::Error { + syn::Error::new(span, format!("the `{name}` attribute should be a list")) + // use `name = name` to support Rust 1.56 +} + +#[inline] +pub(crate) fn bool_attribute_usage(name: &Ident, span: Span) -> syn::Error { + syn::Error::new( + span, + format!("the `{name}` attribute should be a name-value pair. The value type is boolean"), + ) + // use `name = name` to support Rust 1.56 +} + +#[inline] +pub(crate) fn sub_attributes_for_ordinalize(span: Span) -> syn::Error { + syn::Error::new( + span, + format!( + "available sub-attributes for the `ordinalize` attribute:{}", + DisplayStringSlice(&[ + "impl_trait", + "variant_count", + "variants", + "values", + "ordinal", + "from_ordinal_unsafe", + "from_ordinal", + ]) + ), + ) +} diff --git a/vendor/enum-ordinalize-derive/src/variant_type.rs b/vendor/enum-ordinalize-derive/src/variant_type.rs new file mode 100644 index 00000000..70a9072f --- /dev/null +++ b/vendor/enum-ordinalize-derive/src/variant_type.rs @@ -0,0 +1,75 @@ +use proc_macro2::{Ident, Span, TokenStream}; +use quote::{ToTokens, TokenStreamExt}; + +#[derive(Debug)] +pub(crate) enum VariantType { + ISize, + I8, + I16, + I32, + I64, + I128, + USize, + U8, + U16, + U32, + U64, + U128, + NonDetermined, +} + +impl VariantType { + #[inline] + pub(crate) fn from_str>(s: S) -> VariantType { + let s = s.as_ref(); + + match s { + "i8" => VariantType::I8, + "i16" => VariantType::I16, + "i32" => VariantType::I32, + "i64" => VariantType::I64, + "i128" => VariantType::I128, + "isize" => VariantType::ISize, + "u8" => VariantType::U8, + "u16" => VariantType::U16, + "u32" => VariantType::U32, + "u64" => VariantType::U64, + "u128" => VariantType::U128, + "usize" => VariantType::USize, + _ => VariantType::NonDetermined, + } + } + + #[inline] + pub(crate) fn as_str(&self) -> &'static str { + match self { + VariantType::ISize => "isize", + VariantType::I8 => "i8", + VariantType::I16 => "i16", + VariantType::I32 => "i32", + VariantType::I64 => "i64", + VariantType::I128 => "i128", + VariantType::USize => "usize", + VariantType::U8 => "u8", + VariantType::U16 => "u16", + VariantType::U32 => "u32", + VariantType::U64 => "u64", + VariantType::U128 => "u128", + _ => unreachable!(), + } + } +} + +impl Default for VariantType { + #[inline] + fn default() -> Self { + VariantType::NonDetermined + } +} + +impl ToTokens for VariantType { + #[inline] + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.append(Ident::new(self.as_str(), Span::call_site())); + } +} -- cgit v1.2.3