#[macro_export]
macro_rules! impl_trait {
(
$(#[$outer:meta])*
$vis_trait:vis $trait_name:ident,
$to_from_ty:ty,
$(
#[$wrapper_outer:meta]
)*
$vis_enum:vis $wrapper_type:ident,
$( $const_enum:ident ),+
$(,)?
) => {
$(#[$outer])*
$vis_trait trait $trait_name: PartialEq
+ Clone
+ From<$to_from_ty>
+ Into<$to_from_ty>
+ Copy
+ $crate::Size
+ $crate::TypeSize
+ for<'a> $crate::FromBytes<'a>
+ $crate::ToBytes
+ std::fmt::Debug
{}
impl $trait_name for $to_from_ty {}
$(
impl $trait_name for $const_enum {}
)+
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
$(
#[$wrapper_outer]
)*
$vis_enum enum $wrapper_type {
$(
#[allow(missing_docs)]
$const_enum($const_enum),
)+
UnrecognizedConst($to_from_ty),
}
impl $crate::Size for $wrapper_type {
fn unpadded_size(&self) -> usize {
std::mem::size_of::<$to_from_ty>()
}
}
impl $crate::TypeSize for $wrapper_type {
fn type_size() -> usize {
std::mem::size_of::<$to_from_ty>()
}
}
impl $crate::ToBytes for $wrapper_type {
fn to_bytes(&self, buffer: &mut std::io::Cursor<Vec<u8>>) -> Result<(), $crate::err::SerError> {
Ok(match self {
$(
$wrapper_type::$const_enum(val) => val.to_bytes(buffer)?,
)*
$wrapper_type::UnrecognizedConst(val) => val.to_bytes(buffer)?,
})
}
}
impl<'lt> $crate::FromBytes<'lt> for $wrapper_type {
fn from_bytes(buffer: &mut std::io::Cursor<&'lt [u8]>) -> Result<Self, $crate::err::DeError> {
Ok($wrapper_type::from(<$to_from_ty as $crate::FromBytes>::from_bytes(
buffer
)?))
}
}
impl $trait_name for $wrapper_type {}
$(
impl From<$const_enum> for $wrapper_type {
fn from(e: $const_enum) -> Self {
$wrapper_type::$const_enum(e)
}
}
)+
impl From<$wrapper_type> for $to_from_ty {
fn from(w: $wrapper_type) -> Self {
match w {
$(
$wrapper_type::$const_enum(inner) => inner.into(),
)+
$wrapper_type::UnrecognizedConst(v) => v,
}
}
}
impl From<$to_from_ty> for $wrapper_type {
fn from(v: $to_from_ty) -> Self {
$(
let var = $const_enum::from(v);
if !var.is_unrecognized() {
return $wrapper_type::$const_enum(var);
}
)*
$wrapper_type::UnrecognizedConst(v)
}
}
};
}
#[macro_export]
macro_rules! impl_flags {
($(#[$outer:meta])* $vis:vis $name:ident, $type:ty, $bin_type:ty $(,)?) => {
#[derive(Debug, PartialEq, Eq, neli_proc_macros::Size, neli_proc_macros::FromBytes, neli_proc_macros::ToBytes)]
$(#[$outer])*
$vis struct $name($crate::types::FlagBuffer::<$bin_type, $type>);
impl $name {
pub fn empty() -> Self {
$name($crate::types::FlagBuffer::<$bin_type, $type>::empty())
}
pub fn from_bitmask(bitmask: $bin_type) -> Self {
$name($crate::types::FlagBuffer::<$bin_type, $type>::from_bitmask(bitmask))
}
pub fn new(flags: &[$type]) -> Self {
$name(<$crate::types::FlagBuffer::<$bin_type, $type> as From<&[$type]>>::from(flags))
}
pub fn set(&mut self, flag: &$type) {
$crate::types::FlagBuffer::<$bin_type, $type>::set(&mut self.0, flag)
}
pub fn unset(&mut self, flag: &$type) {
$crate::types::FlagBuffer::<$bin_type, $type>::unset(&mut self.0, &flag)
}
pub fn contains(&self, flag: &$type) -> bool {
$crate::types::FlagBuffer::<$bin_type, $type>::contains(&self.0, &flag)
}
}
impl $crate::TypeSize for $name {
fn type_size() -> usize {
<$crate::types::FlagBuffer::<$bin_type, $type> as $crate::TypeSize>::type_size()
}
}
};
}