From 4c9fa02bf2bdc7aa64d26acff9de3b463bee9e28 Mon Sep 17 00:00:00 2001 From: Filipe Rodrigues Date: Tue, 6 Oct 2020 08:24:50 +0100 Subject: [PATCH] Now using `ref-cast` for casting between `repr(transparent)` references instead of a `From` hack. --- dcb/Cargo.toml | 1 + dcb/src/game/card/digimon.rs | 15 ++++++++------- dcb/src/game/card/item.rs | 13 +++++++------ dcb/src/game/card/property/effect.rs | 10 ++-------- dcb/src/game/card/property/effect_condition.rs | 13 +++---------- dcb/src/game/deck/deck.rs | 9 +++++---- dcb/src/util/impl_bytes.rs | 11 ++--------- 7 files changed, 28 insertions(+), 44 deletions(-) diff --git a/dcb/Cargo.toml b/dcb/Cargo.toml index abbc12f..6818e50 100644 --- a/dcb/Cargo.toml +++ b/dcb/Cargo.toml @@ -24,6 +24,7 @@ serde = { version = "1.0", features = ["derive"] } # Derives derive_more = "0.99" thiserror = "1.0" +ref-cast = "1.0" [dev-dependencies] diff --git a/dcb/src/game/card/digimon.rs b/dcb/src/game/card/digimon.rs index 84916d4..a418763 100644 --- a/dcb/src/game/card/digimon.rs +++ b/dcb/src/game/card/digimon.rs @@ -17,6 +17,7 @@ use crate::{ }; use byteorder::{ByteOrder, LittleEndian}; use dcb_bytes::Bytes; +use ref_cast::RefCast; // TODO: Remove these /// Name alias for [`Digimon`] @@ -240,28 +241,28 @@ impl Bytes for Digimon { self.move_cross.to_bytes(bytes.move_cross).into_ok(); // Effects - <&MaybeEffectCondition>::from(&self.effect_conditions[0]) + MaybeEffectCondition::ref_cast(&self.effect_conditions[0]) .to_bytes(bytes.condition_first) .into_ok(); - <&MaybeEffectCondition>::from(&self.effect_conditions[1]) + MaybeEffectCondition::ref_cast(&self.effect_conditions[1]) .to_bytes(bytes.condition_second) .into_ok(); - <&MaybeEffect>::from(&self.effects[0]) + MaybeEffect::ref_cast(&self.effects[0]) .to_bytes(bytes.effect_first) .map_err(ToBytesError::EffectFirst)?; - <&MaybeEffect>::from(&self.effects[1]) + MaybeEffect::ref_cast(&self.effects[1]) .to_bytes(bytes.effect_second) .map_err(ToBytesError::EffectSecond)?; - <&MaybeEffect>::from(&self.effects[2]) + MaybeEffect::ref_cast(&self.effects[2]) .to_bytes(bytes.effect_third) .map_err(ToBytesError::EffectThird)?; - <&MaybeCrossMoveEffect>::from(&self.cross_move_effect) + MaybeCrossMoveEffect::ref_cast(&self.cross_move_effect) .to_bytes(bytes.cross_move_effect) .into_ok(); - <&MaybeArrowColor>::from(&self.effect_arrow_color) + MaybeArrowColor::ref_cast(&self.effect_arrow_color) .to_bytes(bytes.effect_arrow_color) .into_ok(); diff --git a/dcb/src/game/card/item.rs b/dcb/src/game/card/item.rs index c901a97..b20846f 100644 --- a/dcb/src/game/card/item.rs +++ b/dcb/src/game/card/item.rs @@ -11,6 +11,7 @@ use crate::{ }; use byteorder::{ByteOrder, LittleEndian}; use dcb_bytes::Bytes; +use ref_cast::RefCast; // TODO: Remove these /// Name alias for [`Digimon`] @@ -196,24 +197,24 @@ impl Bytes for Item { bytes.name.write_string(&self.name); // Effects - <&MaybeEffectCondition>::from(&self.effect_conditions[0]) + MaybeEffectCondition::ref_cast(&self.effect_conditions[0]) .to_bytes(bytes.condition_first) .into_ok(); - <&MaybeEffectCondition>::from(&self.effect_conditions[1]) + MaybeEffectCondition::ref_cast(&self.effect_conditions[1]) .to_bytes(bytes.condition_second) .into_ok(); - <&MaybeEffect>::from(&self.effects[0]) + MaybeEffect::ref_cast(&self.effects[0]) .to_bytes(bytes.effect_first) .map_err(ToBytesError::EffectFirst)?; - <&MaybeEffect>::from(&self.effects[1]) + MaybeEffect::ref_cast(&self.effects[1]) .to_bytes(bytes.effect_second) .map_err(ToBytesError::EffectSecond)?; - <&MaybeEffect>::from(&self.effects[2]) + MaybeEffect::ref_cast(&self.effects[2]) .to_bytes(bytes.effect_third) .map_err(ToBytesError::EffectThird)?; - <&MaybeArrowColor>::from(&self.effect_arrow_color) + MaybeArrowColor::ref_cast(&self.effect_arrow_color) .to_bytes(bytes.effect_arrow_color) .into_ok(); diff --git a/dcb/src/game/card/property/effect.rs b/dcb/src/game/card/property/effect.rs index cf48252..5441336 100644 --- a/dcb/src/game/card/property/effect.rs +++ b/dcb/src/game/card/property/effect.rs @@ -459,17 +459,11 @@ impl Bytes for Effect { } /// A possible effect +#[repr(transparent)] +#[derive(ref_cast::RefCast)] #[derive(derive_more::From, derive_more::Into)] pub struct MaybeEffect(Option); -impl<'a> From<&'a Option> for &'a MaybeEffect { - #[allow(clippy::as_conversions)] // We need `as` to make pointer casts - fn from(opt: &'a Option) -> Self { - // SAFETY: We're `repr(transparent)`, so this cast is safe - unsafe { &*(opt as *const Option as *const MaybeEffect) } - } -} - impl Bytes for MaybeEffect { type ByteArray = [u8; 0x10]; type FromError = FromBytesError; diff --git a/dcb/src/game/card/property/effect_condition.rs b/dcb/src/game/card/property/effect_condition.rs index 97cbe36..c9cabfc 100644 --- a/dcb/src/game/card/property/effect_condition.rs +++ b/dcb/src/game/card/property/effect_condition.rs @@ -7,6 +7,7 @@ use crate::{ }; use byteorder::{ByteOrder, LittleEndian}; use dcb_bytes::Bytes; +use ref_cast::RefCast; /// A digimon's support effect condition #[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)] @@ -119,7 +120,7 @@ impl Bytes for EffectCondition { self.property_cmp.to_bytes(bytes.property_cmp).into_ok(); // Arguments - <&MaybeDigimonProperty>::from(&self.arg_property).to_bytes(bytes.arg_property).into_ok(); + MaybeDigimonProperty::ref_cast(&self.arg_property).to_bytes(bytes.arg_property).into_ok(); LittleEndian::write_u16(bytes.arg_num, self.arg_num); self.operation.to_bytes(bytes.operation).into_ok(); @@ -137,18 +138,10 @@ impl Bytes for EffectCondition { /// A possible effect condition #[repr(transparent)] +#[derive(ref_cast::RefCast)] #[derive(derive_more::From, derive_more::Into)] pub struct MaybeEffectCondition(Option); -impl<'a> From<&'a Option> for &'a MaybeEffectCondition { - #[allow(clippy::as_conversions)] // We need `as` to make pointer casts - fn from(opt: &'a Option) -> Self { - // SAFETY: We're `repr(transparent)`, so this cast is safe - unsafe { &*(opt as *const Option as *const MaybeEffectCondition) } - } -} - - impl Bytes for MaybeEffectCondition { type ByteArray = [u8; 0x20]; type FromError = FromBytesError; diff --git a/dcb/src/game/deck/deck.rs b/dcb/src/game/deck/deck.rs index 6039f29..773d994 100644 --- a/dcb/src/game/deck/deck.rs +++ b/dcb/src/game/deck/deck.rs @@ -11,6 +11,7 @@ use crate::{ }; use byteorder::{ByteOrder, LittleEndian}; use dcb_bytes::Bytes; +use ref_cast::RefCast; /// Card id type pub type CardId = u16; @@ -158,14 +159,14 @@ impl Bytes for Deck { *bytes.experience = self.experience; // City - <&MaybeCity>::from(&self.city).to_bytes(bytes.city).into_ok(); + MaybeCity::ref_cast(&self.city).to_bytes(bytes.city).into_ok(); // Armor evo - <&MaybeArmorEvo>::from(&self.armor_evo).to_bytes(bytes.armor_evo).into_ok(); + MaybeArmorEvo::ref_cast(&self.armor_evo).to_bytes(bytes.armor_evo).into_ok(); // Music - <&MaybeMusic>::from(&self.battle_music).to_bytes(bytes.battle_music).into_ok(); - <&MaybeMusic>::from(&self.polygon_music).to_bytes(bytes.polygon_music).into_ok(); + MaybeMusic::ref_cast(&self.battle_music).to_bytes(bytes.battle_music).into_ok(); + MaybeMusic::ref_cast(&self.polygon_music).to_bytes(bytes.polygon_music).into_ok(); // Unknown *bytes.unknown_64 = self.unknown_64; diff --git a/dcb/src/util/impl_bytes.rs b/dcb/src/util/impl_bytes.rs index dea8acc..23a452c 100644 --- a/dcb/src/util/impl_bytes.rs +++ b/dcb/src/util/impl_bytes.rs @@ -142,17 +142,10 @@ pub macro generate_enum_property_option ( ) { $( #[repr(transparent)] - #[derive(derive_more::From, derive_more::Into)] + #[derive(::ref_cast::RefCast)] + #[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) } - } - } - #[allow(clippy::diverging_sub_expression)] // Errors might be `!` impl ::dcb_bytes::Bytes for $struct_name { type ByteArray = <$enum_name as ::dcb_bytes::Bytes>::ByteArray;