Now using ref-cast for casting between repr(transparent) references instead of a From hack.

This commit is contained in:
2020-10-06 08:24:50 +01:00
parent 47303aa8e9
commit 4c9fa02bf2
7 changed files with 28 additions and 44 deletions

View File

@@ -24,6 +24,7 @@ serde = { version = "1.0", features = ["derive"] }
# Derives
derive_more = "0.99"
thiserror = "1.0"
ref-cast = "1.0"
[dev-dependencies]

View File

@@ -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();

View File

@@ -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();

View File

@@ -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<Effect>);
impl<'a> From<&'a Option<Effect>> for &'a MaybeEffect {
#[allow(clippy::as_conversions)] // We need `as` to make pointer casts
fn from(opt: &'a Option<Effect>) -> Self {
// SAFETY: We're `repr(transparent)`, so this cast is safe
unsafe { &*(opt as *const Option<Effect> as *const MaybeEffect) }
}
}
impl Bytes for MaybeEffect {
type ByteArray = [u8; 0x10];
type FromError = FromBytesError;

View File

@@ -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<EffectCondition>);
impl<'a> From<&'a Option<EffectCondition>> for &'a MaybeEffectCondition {
#[allow(clippy::as_conversions)] // We need `as` to make pointer casts
fn from(opt: &'a Option<EffectCondition>) -> Self {
// SAFETY: We're `repr(transparent)`, so this cast is safe
unsafe { &*(opt as *const Option<EffectCondition> as *const MaybeEffectCondition) }
}
}
impl Bytes for MaybeEffectCondition {
type ByteArray = [u8; 0x20];
type FromError = FromBytesError;

View File

@@ -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;

View File

@@ -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;