Revised generate_enum_property_option to be closer to an eventual derive.

This commit is contained in:
2020-09-20 02:48:32 +01:00
parent 2a39f8b438
commit 47303aa8e9
3 changed files with 60 additions and 42 deletions

View File

@@ -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<ArrowColor>);
#[derive(BytesProxySentinel)]
#[bytes_proxy_sentinel(value = 0)]
pub struct MaybeCrossMoveEffect(Option<CrossMoveEffect>);
#[derive(BytesProxySentinel)]
#[bytes_proxy_sentinel(value = 0)]
pub struct MaybeDigimonProperty(Option<DigimonProperty>);
);
// Complex

View File

@@ -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<City>);
#[derive(BytesProxySentinel)]
#[bytes_proxy_sentinel(value = 0)]
pub struct MaybeArmorEvo(Option<ArmorEvo>);
#[derive(BytesProxySentinel)]
#[bytes_proxy_sentinel(value = 0)]
pub struct MaybeMusic(Option<Music>);
);
// Modules

View File

@@ -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<Self, Self::FromError>
{
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<Self, Self::FromError>
{
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(())
}
)*
}
}
)*
}