diff --git a/dcb/src/game/card/property.rs b/dcb/src/game/card/property.rs index 2e9b4bb..574cb3d 100644 --- a/dcb/src/game/card/property.rs +++ b/dcb/src/game/card/property.rs @@ -214,9 +214,17 @@ generate_enum_property_mod!( ); util::generate_enum_property_option!( - pub struct MaybeArrowColor (ArrowColor ) => 0, - pub struct MaybeCrossMoveEffect (CrossMoveEffect ) => 0, - pub struct MaybeDigimonProperty (DigimonProperty ) => 0, + #[derive(BytesProxySentinel)] + #[bytes_proxy_sentinel(value = 0)] + pub struct MaybeArrowColor(Option); + + #[derive(BytesProxySentinel)] + #[bytes_proxy_sentinel(value = 0)] + pub struct MaybeCrossMoveEffect(Option); + + #[derive(BytesProxySentinel)] + #[bytes_proxy_sentinel(value = 0)] + pub struct MaybeDigimonProperty(Option); ); // Complex diff --git a/dcb/src/game/deck.rs b/dcb/src/game/deck.rs index d4eaadd..1114d1c 100644 --- a/dcb/src/game/deck.rs +++ b/dcb/src/game/deck.rs @@ -57,9 +57,17 @@ generate_enum_property_mod! { } generate_enum_property_option!( - pub struct MaybeCity (City ) => 0, - pub struct MaybeArmorEvo(ArmorEvo) => 0, - pub struct MaybeMusic (Music ) => 0, + #[derive(BytesProxySentinel)] + #[bytes_proxy_sentinel(value = 0)] + pub struct MaybeCity(Option); + + #[derive(BytesProxySentinel)] + #[bytes_proxy_sentinel(value = 0)] + pub struct MaybeArmorEvo(Option); + + #[derive(BytesProxySentinel)] + #[bytes_proxy_sentinel(value = 0)] + pub struct MaybeMusic(Option); ); // Modules diff --git a/dcb/src/util/impl_bytes.rs b/dcb/src/util/impl_bytes.rs index bd1970f..dea8acc 100644 --- a/dcb/src/util/impl_bytes.rs +++ b/dcb/src/util/impl_bytes.rs @@ -133,47 +133,49 @@ macro_rules! generate_enum_property_mod /// is the first argument of this macro and an enum. /// /// This is done by supplying a sentinel value which is read/written as `None`. -pub macro generate_enum_property_option { - ( - $( $struct_vis:vis struct $struct_name:ident ( $enum_vis:vis $enum_name:ty ) => $sentinel_value:literal ),* $(,)? - ) => { - $( - #[repr(transparent)] - #[derive(derive_more::From, derive_more::Into)] - $struct_vis struct $struct_name( $enum_vis Option<$enum_name> ); +pub macro generate_enum_property_option ( + $( + #[derive(BytesProxySentinel)] + #[bytes_proxy_sentinel(value = $sentinel_value:literal)] + $struct_vis:vis struct $struct_name:ident ( $enum_vis:vis Option<$enum_name:ty> ); + )* +) { + $( + #[repr(transparent)] + #[derive(derive_more::From, derive_more::Into)] + $struct_vis struct $struct_name( $enum_vis Option<$enum_name> ); - impl<'a> From<&'a Option<$enum_name>> for &'a $struct_name { - #[allow(clippy::as_conversions)] // We need `as` to make pointer casts - fn from(opt: &'a Option<$enum_name>) -> Self { - // SAFETY: We're `repr(transparent)`, so this cast is safe - unsafe { &*(opt as *const Option<$enum_name> as *const $struct_name) } + impl<'a> From<&'a Option<$enum_name>> for &'a $struct_name { + #[allow(clippy::as_conversions)] // We need `as` to make pointer casts + fn from(opt: &'a Option<$enum_name>) -> Self { + // SAFETY: We're `repr(transparent)`, so this cast is safe + unsafe { &*(opt as *const Option<$enum_name> as *const $struct_name) } + } + } + + #[allow(clippy::diverging_sub_expression)] // Errors might be `!` + impl ::dcb_bytes::Bytes for $struct_name { + type ByteArray = <$enum_name as ::dcb_bytes::Bytes>::ByteArray; + + type FromError = <$enum_name as ::dcb_bytes::Bytes>::FromError; + fn from_bytes(bytes: &Self::ByteArray) -> Result + { + match bytes { + $sentinel_value => Ok( Self(None) ), + _ => Ok( Self(Some( ::dcb_bytes::Bytes::from_bytes(bytes)? )) ), } } - #[allow(clippy::diverging_sub_expression)] // Errors might be `!` - impl ::dcb_bytes::Bytes for $struct_name { - type ByteArray = <$enum_name as ::dcb_bytes::Bytes>::ByteArray; - - type FromError = <$enum_name as ::dcb_bytes::Bytes>::FromError; - fn from_bytes(bytes: &Self::ByteArray) -> Result - { - match bytes { - $sentinel_value => Ok( Self(None) ), - _ => Ok( Self(Some( ::dcb_bytes::Bytes::from_bytes(bytes)? )) ), - } + type ToError = <$enum_name as ::dcb_bytes::Bytes>::ToError; + fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError> + { + match &self.0 { + Some(value) => ::dcb_bytes::Bytes::to_bytes(value, bytes)?, + None => *bytes = $sentinel_value, } - type ToError = <$enum_name as ::dcb_bytes::Bytes>::ToError; - fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError> - { - match &self.0 { - Some(value) => ::dcb_bytes::Bytes::to_bytes(value, bytes)?, - None => *bytes = $sentinel_value, - } - - Ok(()) - } + Ok(()) } - )* - } + } + )* }