Last active
September 15, 2024 22:29
-
-
Save novafacing/aad21dcad051c6f2f616895844eceef7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[macro_export] | |
// https://stackoverflow.com/a/70222282 | |
macro_rules! field_size { | |
($t:ident :: $field:ident) => {{ | |
let m = core::mem::MaybeUninit::<$t>::uninit(); | |
// According to https://doc.rust-lang.org/stable/std/ptr/macro.addr_of_mut.html#examples, | |
// you can dereference an uninitialized MaybeUninit pointer in addr_of! | |
// Raw pointer deref in const contexts is stabilized in 1.58: | |
// https://github.com/rust-lang/rust/pull/89551 | |
let p = unsafe { core::ptr::addr_of!((*(&m as *const _ as *const $t)).$field) }; | |
const fn size_of_raw<T>(_: *const T) -> usize { | |
core::mem::size_of::<T>() | |
} | |
size_of_raw(p) | |
}}; | |
} | |
#[macro_export] | |
macro_rules! from_primitive_patterns { | |
{ | |
$match_ty:ty, | |
$match_val:expr, | |
@parse {$($eout:tt)*}, | |
#[$variant_meta:meta] $($rest:tt)* | |
} => { | |
$crate::from_primitive_patterns! { | |
$match_ty, | |
$match_val, | |
@parse { | |
$($eout)* | |
}, | |
$($rest)* | |
} | |
}; | |
{ | |
$match_ty:ty, | |
$match_val:expr, | |
@parse {$($eout:tt)*}, | |
$variant:ident = $value:expr, | |
$($rest:tt)* | |
} => { | |
$crate::from_primitive_patterns! { | |
$match_ty, | |
$match_val, | |
@parse { | |
$($eout)* | |
if ($value as $match_ty) == $match_val { | |
return Some(Self::$variant); | |
} | |
}, | |
$($rest)* | |
} | |
}; | |
{ | |
$match_ty:ty, | |
$match_val:expr, | |
@parse {$($eout:tt)*}, | |
$variant:ident($param:ty), | |
$($rest:tt)* | |
} => { | |
$crate::from_primitive_patterns! { | |
$match_ty, | |
$match_val, | |
@parse { | |
$($eout)* | |
Some(Self::$variant($match_val as $param)) | |
}, | |
$($rest)* | |
} | |
}; | |
{ | |
$match_ty:ty, | |
$match_val:expr, | |
@parse {$($eout:tt)*}, | |
} => { | |
$($eout)* | |
}; | |
} | |
#[macro_export] | |
macro_rules! to_primitive_patterns { | |
{ | |
$self:ident, | |
$match_ty:ty, | |
@parse {$($eout:tt)*}, | |
#[$variant_meta:meta] $($rest:tt)* | |
} => { | |
$crate::to_primitive_patterns! { | |
$self, | |
$match_ty, | |
@parse { | |
$($eout)* | |
}, | |
$($rest)* | |
} | |
}; | |
{ | |
$self:ident, | |
$match_ty:ty, | |
@parse {$($eout:tt)*}, | |
$variant:ident = $value:expr, | |
$($rest:tt)* | |
} => { | |
$crate::to_primitive_patterns! { | |
$self, | |
$match_ty, | |
@parse { | |
$($eout)* | |
Self::$variant => Some($value as $match_ty), | |
}, | |
$($rest)* | |
} | |
}; | |
{ | |
$self:ident, | |
$match_ty:ty, | |
@parse {$($eout:tt)*}, | |
$variant:ident($param:ty), | |
$($rest:tt)* | |
} => { | |
$crate::to_primitive_patterns! { | |
$self, | |
$match_ty, | |
@parse { | |
$($eout)* | |
Self::$variant(value) => Some(*value as $match_ty), | |
}, | |
$($rest)* | |
} | |
}; | |
{ | |
$self:ident, | |
$match_ty:ty, | |
@parse {$($eout:tt)*}, | |
} => { | |
match $self { | |
$($eout)* | |
} | |
}; | |
} | |
#[macro_export] | |
macro_rules! parse_enum_variant { | |
{ | |
$(#[$enum_meta:meta])*, | |
$vis:vis, | |
$name:ident, | |
$(<$($generic_param:tt),*>)?, | |
@where_clauses {$($where:tt)*}, | |
@parse {$($eout:tt)*}, | |
#[$variant_meta:meta] $($rest:tt)* | |
} => { | |
$crate::parse_enum_variant! { | |
$(#[$enum_meta])*, | |
$vis, | |
$name, | |
$(<$($generic_param),*>)?, | |
@where_clauses {$($where)*}, | |
@parse { | |
$($eout)* | |
#[$variant_meta] | |
}, | |
$($rest)* | |
} | |
}; | |
{ | |
$(#[$enum_meta:meta])*, | |
$vis:vis, | |
$name:ident, | |
$(<$($generic_param:tt),*>)?, | |
@where_clauses {$($where:tt)*}, | |
@parse {$($eout:tt)*}, | |
$variant:ident, | |
$($rest:tt)* | |
} => { | |
$crate::parse_enum_variant! { | |
$(#[$enum_meta])*, | |
$vis, | |
$name, | |
$(<$($generic_param),*>)?, | |
@where_clauses {$($where)*}, | |
@parse { | |
$($eout)* | |
$variant, | |
}, | |
$($rest)* | |
} | |
}; | |
{ | |
$(#[$enum_meta:meta])*, | |
$vis:vis, | |
$name:ident, | |
$(<$($generic_param:tt),*>)?, | |
@where_clauses {$($where:tt)*}, | |
@parse {$($eout:tt)*}, | |
$variant:ident = $value:expr, | |
$($rest:tt)* | |
} => { | |
$crate::parse_enum_variant!{ | |
$(#[$enum_meta])*, | |
$vis, | |
$name, | |
$(<$($generic_param),*>)?, | |
@where_clauses {$($where)*}, | |
@parse { | |
$($eout)* | |
$variant = $value, | |
}, | |
$($rest)* | |
} | |
}; | |
{ | |
$(#[$enum_meta:meta])*, | |
$vis:vis, | |
$name:ident, | |
$(<$($generic_param:tt),*>)?, | |
@where_clauses {$($where:tt)*}, | |
@parse {$($eout:tt)*}, | |
$variant:ident($param:ty), | |
$($rest:tt)* | |
} => { | |
$crate::parse_enum_variant!{ | |
$(#[$enum_meta])*, | |
$vis, | |
$name, | |
$(<$($generic_param),*>)?, | |
@where_clauses {$($where)*}, | |
@parse { | |
$($eout)* | |
$variant($param), | |
}, | |
$($rest)* | |
} | |
}; | |
{ | |
$(#[$enum_meta:meta])*, | |
$vis:vis, | |
$name:ident, | |
$(<$($generic_param:tt),*>)?, | |
@where_clauses {$($where:tt)*}, | |
@parse {$($eout:tt)*}, | |
$variant:ident { $($fields:tt)* }, | |
$($rest:tt)* | |
} => { | |
$crate::parse_enum_variant!{ | |
$(#[$enum_meta])*, | |
$vis, | |
$name, | |
$(<$($generic_param),*>)?, | |
@where_clauses {$($where)*}, | |
@parse { | |
$($eout)* | |
$variant { $($fields)* }, | |
}, | |
$($rest)* | |
} | |
}; | |
{ | |
$(#[$enum_meta:meta])*, | |
$vis:vis, | |
$name:ident, | |
$(<$($generic_param:tt),*>)?, | |
@where_clauses {$($where:tt)*}, | |
@parse {$($eout:tt)*} $(,)* | |
} => { | |
$(#[$enum_meta])* | |
$vis enum $name | |
$(<$($generic_param),*>)? | |
$($where)* | |
{ | |
$($eout)* | |
} | |
impl $(<$($generic_param),*>)? num_traits::FromPrimitive for $name $(<$($generic_param),*>)? $($where:tt)* { | |
fn from_i64(n: i64) -> Option<Self> { | |
$crate::from_primitive_patterns! { | |
i64, | |
n, | |
@parse {}, | |
$($eout)* | |
} | |
} | |
fn from_u64(n: u64) -> Option<Self> { | |
$crate::from_primitive_patterns! { | |
u64, | |
n, | |
@parse {}, | |
$($eout)* | |
} | |
} | |
} | |
impl $(<$($generic_param),*>)? num_traits::ToPrimitive for $name $(<$($generic_param),*>)? $($where:tt)* { | |
fn to_i64(&self) -> Option<i64> { | |
$crate::to_primitive_patterns! { | |
self, | |
i64, | |
@parse {}, | |
$($eout)* | |
} | |
} | |
fn to_u64(&self) -> Option<u64> { | |
$crate::to_primitive_patterns! { | |
self, | |
u64, | |
@parse {}, | |
$($eout)* | |
} | |
} | |
} | |
}; | |
{ | |
$(#[$enum_meta:meta])*, | |
$vis:vis, | |
$name:ident, | |
$(<$($generic_param:tt),*>)?, | |
@where_clauses {$($where:tt)*}, | |
@parse {$($eout:tt)*} $(,)* | |
} => { | |
$(#[$enum_meta])* | |
$vis enum $name | |
$(<$($generic_param),*>)? | |
$($where)* | |
{ | |
$($eout)* | |
} | |
}; | |
{ | |
$(#[$enum_meta:meta])*, | |
$vis:vis, | |
$name:ident, | |
$(<$($generic_param:tt),*>)?, | |
@where_clauses {$($where:tt)*}, | |
@parse {$($eout:tt)*} $(,)* | |
} => { | |
$(#[$enum_meta])* | |
$vis enum $name | |
$(<$($generic_param),*>)? | |
$($where)* | |
{ | |
$($eout)* | |
} | |
}; | |
{ | |
$(#[$enum_meta:meta])*, | |
$vis:vis, | |
$name:ident, | |
$(<$($generic_param:tt),*>)?, | |
@where_clauses {$($where:tt)*}, | |
@parse {$($eout:tt)*} $(,)* | |
} => { | |
$(#[$enum_meta])* | |
$vis enum $name | |
$(<$($generic_param),*>)? | |
$($where)* | |
{ | |
$($eout)* | |
} | |
}; | |
} | |
#[macro_export] | |
/// Add the ability to convert a primitive to an enum with ToPrimitive/FromPrimitive. | |
/// A trailing 1-element tuple variant is used as a fallback if one is found. | |
macro_rules! convert_primitive { | |
( | |
$(#[$enum_meta:meta])* | |
$vis:vis enum $enum_name:ident | |
$(<$($generic_param:tt),*>)? | |
{ | |
$($variants:tt)* | |
} | |
) => { | |
$crate::parse_enum_variant! { | |
$(#[$enum_meta])*, | |
$vis, | |
$enum_name, | |
$(<$($generic_param),*>)?, | |
@where_clauses {}, | |
@parse {}, $($variants)* | |
} | |
}; | |
( | |
$(#[$enum_meta:meta])* | |
$vis:vis enum $enum_name:ident | |
$(<$($generic_param:tt),*>)? | |
where | |
$where_clause:tt $(<$($where_generic_param:tt),*>)?: | |
$where_clause_bound:tt $(<$($where_clause_bound_generic_param:tt),*>)? | |
$(+ $where_clause_bound_plus:tt $(<$($where_clause_bound_generic_param_plus:tt),*>)?)* | |
$(, $more_where_clause:tt $(<$($more_where_generic_param:tt),*>)?: | |
$more_where_clause_bound:tt $(<$($more_where_clause_bound_generic_param:tt),*>)? | |
$(+ $more_where_clause_bound_plus:tt $(<$($more_where_clause_bounds_generic_param_plus:tt),*>)?)* )* | |
{ | |
$($variants:tt)* | |
} | |
) => { | |
$crate::parse_enum_variant! { | |
$(#[$enum_meta])*, | |
$vis, | |
$enum_name, | |
$(<$($generic_param),*>)?, | |
@where_clauses { | |
where | |
$where_clause $(<$($where_generic_param),*>)?: | |
$where_clause_bound $(<$($where_clause_bound_generic_param),*>)? | |
$(+ $where_clause_bound_plus $(<$($where_clause_bound_generic_param_plus),*>)?)* | |
$(, $more_where_clause $(<$($more_where_generic_param),*>)?: | |
$more_where_clause_bound $(<$($more_where_clause_bound_generic_param),*>)? | |
$(+ $more_where_clause_bound_plus $(<$($more_where_clause_bounds_generic_param_plus),*>)?)* )* | |
}, | |
@parse {}, $($variants)* | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated to not use match() in from_primitive_patterns because it wasn't working with externally-defined constants.