mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-04 00:21:57 +00:00
Moved Bytes interface to dcb-bytes crate.
Instead of implementing `Bytes for Option<T>`, a proxy is now used, as `dcb-bytes` is in a separate crate.
This commit is contained in:
parent
152c8250ff
commit
2a39f8b438
@ -1,5 +1,7 @@
|
||||
[workspace]
|
||||
|
||||
members = [
|
||||
"dcb"
|
||||
"dcb",
|
||||
"dcb-bytes",
|
||||
"dcb-bytes-derive"
|
||||
]
|
||||
|
||||
8
dcb-bytes-derive/Cargo.toml
Normal file
8
dcb-bytes-derive/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "dcb-bytes-derive"
|
||||
version = "0.1.0"
|
||||
authors = ["Filipe Rodrigues <filipejacintorodrigues1@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
|
||||
1
dcb-bytes-derive/src/lib.rs
Normal file
1
dcb-bytes-derive/src/lib.rs
Normal file
@ -0,0 +1 @@
|
||||
//! Derive macros for [`Bytes`](dcb_bytes::Bytes)
|
||||
8
dcb-bytes/Cargo.toml
Normal file
8
dcb-bytes/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "dcb-bytes"
|
||||
version = "0.1.0"
|
||||
authors = ["Filipe Rodrigues <filipejacintorodrigues1@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
|
||||
62
dcb-bytes/src/lib.rs
Normal file
62
dcb-bytes/src/lib.rs
Normal file
@ -0,0 +1,62 @@
|
||||
//! Bytes conversions for [`dcb`].
|
||||
|
||||
// Features
|
||||
#![feature(unsafe_block_in_unsafe_fn, min_const_generics)]
|
||||
// Lints
|
||||
#![warn(clippy::restriction, clippy::pedantic, clippy::nursery)]
|
||||
// Instead of `unwrap`, we must use `expect` and provide a reason
|
||||
#![forbid(clippy::unwrap_used)]
|
||||
// We must use `unsafe` in unsafe `fn`s and specify if the guarantee is
|
||||
// made by the caller or by us.
|
||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
// We'll disable the ones we don't need
|
||||
#![allow(clippy::blanket_clippy_restriction_lints)]
|
||||
// Necessary items may be inlined using `LTO`, so we don't need to mark them as inline
|
||||
#![allow(clippy::missing_inline_in_public_items)]
|
||||
// We prefer tail returns where possible, as they help with code readability in most cases.
|
||||
#![allow(clippy::implicit_return)]
|
||||
// We're fine with shadowing, as long as the variable is used for the same purpose.
|
||||
// Hence why `clippy::shadow_unrelated` isn't allowed.
|
||||
#![allow(clippy::shadow_reuse, clippy::shadow_same)]
|
||||
// We panic when we know it won't happen, or if it does happen, then a panic is the best option
|
||||
#![allow(clippy::panic, clippy::expect_used, clippy::unreachable, clippy::todo)]
|
||||
// We use `expect` even in functions that return a `Result` / `Option` if there is a logic error
|
||||
#![allow(clippy::unwrap_in_result)]
|
||||
// We find it more important to be able to copy paste literals such as `0xabcd1234` than
|
||||
// being able to read them, which does not provide many benefits
|
||||
#![allow(clippy::unreadable_literal, clippy::unseparated_literal_suffix)]
|
||||
// We separate implementations per their functionality usually, such as constructors, getters, setters, and others.
|
||||
#![allow(clippy::multiple_inherent_impl)]
|
||||
// Many operations we need to repeat, and to keep symmetry
|
||||
#![allow(clippy::identity_op)]
|
||||
// We only introduce items before their first usage, which sometimes is half-way through the code.
|
||||
// We make sure that we only use the item after introduced, however.
|
||||
#![allow(clippy::items_after_statements)]
|
||||
// Useful for when they either change a lot with new variants / data,
|
||||
// or for symmetry purposes
|
||||
#![allow(clippy::match_same_arms)]
|
||||
// In this library we have very grain-level error types, each function
|
||||
// will have it's own error type ideally, so any errors are explicit
|
||||
// by the type, without needing a section for them
|
||||
#![allow(clippy::missing_errors_doc)]
|
||||
// Although we generally try to avoid this, this can happen due to our module organization.
|
||||
// In the future, this lint should be removed globally and only enabled for modules which
|
||||
// actually require the use of it.
|
||||
#![allow(clippy::module_inception, clippy::module_name_repetitions)]
|
||||
// We use integer arithmetic and operations with the correct intent
|
||||
#![allow(clippy::integer_arithmetic, clippy::integer_division)]
|
||||
// We prefer using match ergonomic where possible
|
||||
#![allow(clippy::pattern_type_mismatch)]
|
||||
// Sometimes the blocks make it easier to invert their order
|
||||
#![allow(clippy::if_not_else)]
|
||||
// False positives:
|
||||
// TODO: Remove them in the future once they are no longer triggered.
|
||||
// We only slice arrays, which are verified at compile time. This
|
||||
// lint currently triggers for `&[T; N]`, which we pass around a lot.
|
||||
#![allow(clippy::indexing_slicing)]
|
||||
|
||||
// Modules
|
||||
pub mod bytes;
|
||||
|
||||
// Exports
|
||||
pub use bytes::{ByteArray, Bytes};
|
||||
@ -6,6 +6,9 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
|
||||
# Dcb
|
||||
dcb-bytes = { version = "0.1", path = "../dcb-bytes" }
|
||||
|
||||
# Log
|
||||
log = "0.4"
|
||||
|
||||
|
||||
@ -15,13 +15,11 @@
|
||||
//#![allow(clippy::missing_docs_in_private_items)] // A lot of our private items are simple digimon types, so they don't need documentation
|
||||
|
||||
// Modules
|
||||
pub mod bytes;
|
||||
pub mod card;
|
||||
pub mod deck;
|
||||
pub mod validation;
|
||||
|
||||
// Exports
|
||||
pub use bytes::Bytes;
|
||||
pub use card::{Digimon, Digivolve, Item, Table as CardTable};
|
||||
pub use deck::{Deck, Table as DeckTable};
|
||||
pub use validation::{Validatable, Validation};
|
||||
|
||||
@ -8,14 +8,15 @@ pub use error::{FromBytesError, ToBytesError};
|
||||
|
||||
// Imports
|
||||
use crate::{
|
||||
game::{
|
||||
card::property::{ArrowColor, CrossMoveEffect, Effect, EffectCondition, Level, Move, Speciality},
|
||||
Bytes,
|
||||
game::card::property::{
|
||||
ArrowColor, CrossMoveEffect, Effect, EffectCondition, Level, MaybeArrowColor, MaybeCrossMoveEffect, MaybeEffect, MaybeEffectCondition, Move,
|
||||
Speciality,
|
||||
},
|
||||
util::{array_split, null_ascii_string::NullAsciiString, array_split_mut},
|
||||
util::{array_split, array_split_mut, null_ascii_string::NullAsciiString},
|
||||
AsciiStrArr,
|
||||
};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use dcb_bytes::Bytes;
|
||||
|
||||
// TODO: Remove these
|
||||
/// Name alias for [`Digimon`]
|
||||
@ -148,19 +149,27 @@ impl Bytes for Digimon {
|
||||
|
||||
// Effects
|
||||
effect_conditions: [
|
||||
Option::<EffectCondition>::from_bytes(bytes.condition_first).map_err(FromBytesError::EffectConditionFirst)?,
|
||||
Option::<EffectCondition>::from_bytes(bytes.condition_second).map_err(FromBytesError::EffectConditionSecond)?,
|
||||
MaybeEffectCondition::from_bytes(bytes.condition_first)
|
||||
.map_err(FromBytesError::EffectConditionFirst)?
|
||||
.into(),
|
||||
MaybeEffectCondition::from_bytes(bytes.condition_second)
|
||||
.map_err(FromBytesError::EffectConditionSecond)?
|
||||
.into(),
|
||||
],
|
||||
|
||||
effects: [
|
||||
Option::<Effect>::from_bytes(bytes.effect_first).map_err(FromBytesError::EffectFirst)?,
|
||||
Option::<Effect>::from_bytes(bytes.effect_second).map_err(FromBytesError::EffectSecond)?,
|
||||
Option::<Effect>::from_bytes(bytes.effect_third).map_err(FromBytesError::EffectThird)?,
|
||||
MaybeEffect::from_bytes(bytes.effect_first).map_err(FromBytesError::EffectFirst)?.into(),
|
||||
MaybeEffect::from_bytes(bytes.effect_second).map_err(FromBytesError::EffectSecond)?.into(),
|
||||
MaybeEffect::from_bytes(bytes.effect_third).map_err(FromBytesError::EffectThird)?.into(),
|
||||
],
|
||||
|
||||
cross_move_effect: Option::<CrossMoveEffect>::from_bytes(bytes.cross_move_effect).map_err(FromBytesError::CrossMoveEffect)?,
|
||||
cross_move_effect: MaybeCrossMoveEffect::from_bytes(bytes.cross_move_effect)
|
||||
.map_err(FromBytesError::CrossMoveEffect)?
|
||||
.into(),
|
||||
|
||||
effect_arrow_color: Option::<ArrowColor>::from_bytes(bytes.effect_arrow_color).map_err(FromBytesError::ArrowColor)?,
|
||||
effect_arrow_color: MaybeArrowColor::from_bytes(bytes.effect_arrow_color)
|
||||
.map_err(FromBytesError::ArrowColor)?
|
||||
.into(),
|
||||
|
||||
effect_description: [
|
||||
bytes.effect_description_0.read_string().map_err(FromBytesError::EffectDescription1)?,
|
||||
@ -231,16 +240,30 @@ impl Bytes for Digimon {
|
||||
self.move_cross.to_bytes(bytes.move_cross).into_ok();
|
||||
|
||||
// Effects
|
||||
self.effect_conditions[0].to_bytes(bytes.condition_first).into_ok();
|
||||
self.effect_conditions[1].to_bytes(bytes.condition_second).into_ok();
|
||||
<&MaybeEffectCondition>::from(&self.effect_conditions[0])
|
||||
.to_bytes(bytes.condition_first)
|
||||
.into_ok();
|
||||
<&MaybeEffectCondition>::from(&self.effect_conditions[1])
|
||||
.to_bytes(bytes.condition_second)
|
||||
.into_ok();
|
||||
|
||||
self.effects[0].to_bytes(bytes.effect_first).map_err(ToBytesError::EffectFirst)?;
|
||||
self.effects[1].to_bytes(bytes.effect_second).map_err(ToBytesError::EffectSecond)?;
|
||||
self.effects[2].to_bytes(bytes.effect_third).map_err(ToBytesError::EffectThird)?;
|
||||
<&MaybeEffect>::from(&self.effects[0])
|
||||
.to_bytes(bytes.effect_first)
|
||||
.map_err(ToBytesError::EffectFirst)?;
|
||||
<&MaybeEffect>::from(&self.effects[1])
|
||||
.to_bytes(bytes.effect_second)
|
||||
.map_err(ToBytesError::EffectSecond)?;
|
||||
<&MaybeEffect>::from(&self.effects[2])
|
||||
.to_bytes(bytes.effect_third)
|
||||
.map_err(ToBytesError::EffectThird)?;
|
||||
|
||||
Option::<CrossMoveEffect>::to_bytes(&self.cross_move_effect, bytes.cross_move_effect).into_ok();
|
||||
<&MaybeCrossMoveEffect>::from(&self.cross_move_effect)
|
||||
.to_bytes(bytes.cross_move_effect)
|
||||
.into_ok();
|
||||
|
||||
Option::<ArrowColor>::to_bytes(&self.effect_arrow_color, bytes.effect_arrow_color).into_ok();
|
||||
<&MaybeArrowColor>::from(&self.effect_arrow_color)
|
||||
.to_bytes(bytes.effect_arrow_color)
|
||||
.into_ok();
|
||||
|
||||
bytes.effect_description_0.write_string(&self.effect_description[0]);
|
||||
bytes.effect_description_1.write_string(&self.effect_description[1]);
|
||||
|
||||
@ -2,13 +2,13 @@
|
||||
|
||||
// Imports
|
||||
use crate::{
|
||||
game::Bytes,
|
||||
util::{
|
||||
array_split, array_split_mut,
|
||||
null_ascii_string::{self, NullAsciiString},
|
||||
},
|
||||
AsciiStrArr,
|
||||
};
|
||||
use dcb_bytes::Bytes;
|
||||
|
||||
// TODO: Remove these
|
||||
/// Name alias for [`Digimon`]
|
||||
|
||||
@ -2,10 +2,7 @@
|
||||
|
||||
// Imports
|
||||
use crate::{
|
||||
game::{
|
||||
card::property::{self, ArrowColor, Effect, EffectCondition},
|
||||
Bytes,
|
||||
},
|
||||
game::card::property::{self, ArrowColor, Effect, EffectCondition, MaybeArrowColor, MaybeEffect, MaybeEffectCondition},
|
||||
util::{
|
||||
array_split, array_split_mut,
|
||||
null_ascii_string::{self, NullAsciiString},
|
||||
@ -13,6 +10,7 @@ use crate::{
|
||||
AsciiStrArr,
|
||||
};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use dcb_bytes::Bytes;
|
||||
|
||||
// TODO: Remove these
|
||||
/// Name alias for [`Digimon`]
|
||||
@ -147,17 +145,23 @@ impl Bytes for Item {
|
||||
|
||||
// Effects
|
||||
effect_conditions: [
|
||||
Option::<EffectCondition>::from_bytes(bytes.condition_first).map_err(FromBytesError::EffectConditionFirst)?,
|
||||
Option::<EffectCondition>::from_bytes(bytes.condition_second).map_err(FromBytesError::EffectConditionSecond)?,
|
||||
MaybeEffectCondition::from_bytes(bytes.condition_first)
|
||||
.map_err(FromBytesError::EffectConditionFirst)?
|
||||
.into(),
|
||||
MaybeEffectCondition::from_bytes(bytes.condition_second)
|
||||
.map_err(FromBytesError::EffectConditionSecond)?
|
||||
.into(),
|
||||
],
|
||||
|
||||
effects: [
|
||||
Option::<Effect>::from_bytes(bytes.effect_first).map_err(FromBytesError::EffectFirst)?,
|
||||
Option::<Effect>::from_bytes(bytes.effect_second).map_err(FromBytesError::EffectSecond)?,
|
||||
Option::<Effect>::from_bytes(bytes.effect_third).map_err(FromBytesError::EffectThird)?,
|
||||
MaybeEffect::from_bytes(bytes.effect_first).map_err(FromBytesError::EffectFirst)?.into(),
|
||||
MaybeEffect::from_bytes(bytes.effect_second).map_err(FromBytesError::EffectSecond)?.into(),
|
||||
MaybeEffect::from_bytes(bytes.effect_third).map_err(FromBytesError::EffectThird)?.into(),
|
||||
],
|
||||
|
||||
effect_arrow_color: Option::<ArrowColor>::from_bytes(bytes.effect_arrow_color).map_err(FromBytesError::ArrowColor)?,
|
||||
effect_arrow_color: MaybeArrowColor::from_bytes(bytes.effect_arrow_color)
|
||||
.map_err(FromBytesError::ArrowColor)?
|
||||
.into(),
|
||||
|
||||
effect_description: [
|
||||
bytes.effect_description_0.read_string().map_err(FromBytesError::EffectDescription1)?,
|
||||
@ -192,14 +196,26 @@ impl Bytes for Item {
|
||||
bytes.name.write_string(&self.name);
|
||||
|
||||
// Effects
|
||||
self.effect_conditions[0].to_bytes(bytes.condition_first).into_ok();
|
||||
self.effect_conditions[1].to_bytes(bytes.condition_second).into_ok();
|
||||
<&MaybeEffectCondition>::from(&self.effect_conditions[0])
|
||||
.to_bytes(bytes.condition_first)
|
||||
.into_ok();
|
||||
<&MaybeEffectCondition>::from(&self.effect_conditions[1])
|
||||
.to_bytes(bytes.condition_second)
|
||||
.into_ok();
|
||||
|
||||
self.effects[0].to_bytes(bytes.effect_first).map_err(ToBytesError::EffectFirst)?;
|
||||
self.effects[1].to_bytes(bytes.effect_second).map_err(ToBytesError::EffectSecond)?;
|
||||
self.effects[2].to_bytes(bytes.effect_third).map_err(ToBytesError::EffectThird)?;
|
||||
<&MaybeEffect>::from(&self.effects[0])
|
||||
.to_bytes(bytes.effect_first)
|
||||
.map_err(ToBytesError::EffectFirst)?;
|
||||
<&MaybeEffect>::from(&self.effects[1])
|
||||
.to_bytes(bytes.effect_second)
|
||||
.map_err(ToBytesError::EffectSecond)?;
|
||||
<&MaybeEffect>::from(&self.effects[2])
|
||||
.to_bytes(bytes.effect_third)
|
||||
.map_err(ToBytesError::EffectThird)?;
|
||||
|
||||
Option::<ArrowColor>::to_bytes(&self.effect_arrow_color, bytes.effect_arrow_color).into_ok();
|
||||
<&MaybeArrowColor>::from(&self.effect_arrow_color)
|
||||
.to_bytes(bytes.effect_arrow_color)
|
||||
.into_ok();
|
||||
|
||||
bytes.effect_description_0.write_string(&self.effect_description[0]);
|
||||
bytes.effect_description_1.write_string(&self.effect_description[1]);
|
||||
|
||||
@ -58,11 +58,14 @@ generate_enum_property_mod!(
|
||||
#[must_use]
|
||||
pub const fn byte_size(self) -> usize
|
||||
{
|
||||
use crate::game::card::{Digimon, Item, Digivolve};
|
||||
use dcb_bytes::Bytes;
|
||||
|
||||
match self
|
||||
{
|
||||
Self::Digimon => std::mem::size_of::< <crate::game::card::Digimon as crate::game::Bytes>::ByteArray >(),
|
||||
Self::Item => std::mem::size_of::< <crate::game::card::Item as crate::game::Bytes>::ByteArray >(),
|
||||
Self::Digivolve => std::mem::size_of::< <crate::game::card::Digivolve as crate::game::Bytes>::ByteArray >(),
|
||||
Self::Digimon => std::mem::size_of::< <Digimon as Bytes>::ByteArray >(),
|
||||
Self::Item => std::mem::size_of::< <Item as Bytes>::ByteArray >(),
|
||||
Self::Digivolve => std::mem::size_of::< <Digivolve as Bytes>::ByteArray >(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -211,9 +214,9 @@ generate_enum_property_mod!(
|
||||
);
|
||||
|
||||
util::generate_enum_property_option!(
|
||||
ArrowColor => 0,
|
||||
CrossMoveEffect => 0,
|
||||
DigimonProperty => 0,
|
||||
pub struct MaybeArrowColor (ArrowColor ) => 0,
|
||||
pub struct MaybeCrossMoveEffect (CrossMoveEffect ) => 0,
|
||||
pub struct MaybeDigimonProperty (DigimonProperty ) => 0,
|
||||
);
|
||||
|
||||
// Complex
|
||||
@ -227,8 +230,8 @@ pub use attack_type::AttackType;
|
||||
pub use card_type::CardType;
|
||||
pub use cross_move_effect::CrossMoveEffect;
|
||||
pub use digimon_property::DigimonProperty;
|
||||
pub use effect::Effect;
|
||||
pub use effect_condition::EffectCondition;
|
||||
pub use effect::{Effect, MaybeEffect};
|
||||
pub use effect_condition::{EffectCondition, MaybeEffectCondition};
|
||||
pub use effect_condition_operation::EffectConditionOperation;
|
||||
pub use effect_operation::EffectOperation;
|
||||
pub use level::Level;
|
||||
|
||||
@ -2,13 +2,11 @@
|
||||
|
||||
// Imports
|
||||
use crate::{
|
||||
game::{
|
||||
card::property::{self, AttackType, DigimonProperty, EffectOperation, PlayerType, Slot},
|
||||
Bytes,
|
||||
},
|
||||
game::card::property::{self, AttackType, DigimonProperty, EffectOperation, PlayerType, Slot},
|
||||
util::{array_split, array_split_mut},
|
||||
};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use dcb_bytes::Bytes;
|
||||
|
||||
/// A digimon's support effects
|
||||
///
|
||||
@ -460,7 +458,19 @@ impl Bytes for Effect {
|
||||
}
|
||||
}
|
||||
|
||||
impl Bytes for Option<Effect> {
|
||||
/// A possible effect
|
||||
#[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;
|
||||
type ToError = ToBytesError;
|
||||
@ -474,11 +484,11 @@ impl Bytes for Option<Effect> {
|
||||
|
||||
// If the exists byte is 0, return None
|
||||
if *bytes.exists == 0 {
|
||||
return Ok(None);
|
||||
return Ok(Self(None));
|
||||
}
|
||||
|
||||
// Else get the effect
|
||||
Ok(Some(Effect::from_bytes(bytes.effect)?))
|
||||
Ok(Self(Some(Effect::from_bytes(bytes.effect)?)))
|
||||
}
|
||||
|
||||
fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError> {
|
||||
@ -488,7 +498,7 @@ impl Bytes for Option<Effect> {
|
||||
);
|
||||
|
||||
// Check if we exist
|
||||
match self {
|
||||
match &self.0 {
|
||||
Some(effect) => {
|
||||
*bytes.exists = 1;
|
||||
effect.to_bytes(bytes.effect)?;
|
||||
|
||||
@ -2,13 +2,11 @@
|
||||
|
||||
// Imports
|
||||
use crate::{
|
||||
game::{
|
||||
card::property::{self, DigimonProperty, EffectConditionOperation},
|
||||
Bytes,
|
||||
},
|
||||
game::card::property::{self, DigimonProperty, EffectConditionOperation, MaybeDigimonProperty},
|
||||
util::{array_split, array_split_mut},
|
||||
};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use dcb_bytes::Bytes;
|
||||
|
||||
/// A digimon's support effect condition
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
|
||||
@ -84,7 +82,9 @@ impl Bytes for EffectCondition {
|
||||
misfire: (*bytes.misfire != 0),
|
||||
property_cmp: DigimonProperty::from_bytes(bytes.property_cmp).map_err(FromBytesError::Condition)?,
|
||||
|
||||
arg_property: Option::<DigimonProperty>::from_bytes(bytes.arg_property).map_err(FromBytesError::PropertyArgument)?,
|
||||
arg_property: MaybeDigimonProperty::from_bytes(bytes.arg_property)
|
||||
.map_err(FromBytesError::PropertyArgument)?
|
||||
.into(),
|
||||
|
||||
arg_num: LittleEndian::read_u16(bytes.arg_num),
|
||||
|
||||
@ -119,7 +119,7 @@ impl Bytes for EffectCondition {
|
||||
self.property_cmp.to_bytes(bytes.property_cmp).into_ok();
|
||||
|
||||
// Arguments
|
||||
self.arg_property.to_bytes(bytes.arg_property).into_ok();
|
||||
<&MaybeDigimonProperty>::from(&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();
|
||||
|
||||
@ -135,25 +135,39 @@ impl Bytes for EffectCondition {
|
||||
}
|
||||
}
|
||||
|
||||
impl Bytes for Option<EffectCondition> {
|
||||
/// A possible effect condition
|
||||
#[repr(transparent)]
|
||||
#[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;
|
||||
type ToError = <EffectCondition as crate::game::Bytes>::ToError;
|
||||
type ToError = <EffectCondition as Bytes>::ToError;
|
||||
|
||||
fn from_bytes(bytes: &Self::ByteArray) -> Result<Self, Self::FromError> {
|
||||
// If we have no property comparison, return None
|
||||
if bytes[0x2] == 0 {
|
||||
return Ok(None);
|
||||
return Ok(Self(None));
|
||||
}
|
||||
|
||||
// Else build the type
|
||||
Ok(Some(EffectCondition::from_bytes(bytes)?))
|
||||
Ok(Self(Some(EffectCondition::from_bytes(bytes)?)))
|
||||
}
|
||||
|
||||
#[allow(clippy::diverging_sub_expression)] // For if we ever change `EffectCondition::ToError`
|
||||
fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError> {
|
||||
// Check if we exist
|
||||
match self {
|
||||
match self.0 {
|
||||
Some(cond) => cond.to_bytes(bytes)?,
|
||||
None => bytes[0x2] = 0,
|
||||
};
|
||||
|
||||
@ -6,7 +6,7 @@ mod test;
|
||||
|
||||
// Imports
|
||||
use crate::{
|
||||
game::{Bytes, Validatable, Validation},
|
||||
game::{Validatable, Validation},
|
||||
util::{
|
||||
array_split, array_split_mut,
|
||||
null_ascii_string::{self, NullAsciiString},
|
||||
@ -14,6 +14,7 @@ use crate::{
|
||||
AsciiStrArr,
|
||||
};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use dcb_bytes::Bytes;
|
||||
|
||||
// TODO: Remove these
|
||||
/// Name alias for [`Digimon`]
|
||||
|
||||
@ -8,18 +8,16 @@ pub use error::{DeserializeError, SerializeError};
|
||||
|
||||
// Imports
|
||||
use crate::{
|
||||
game::{
|
||||
card::{
|
||||
self,
|
||||
property::{self, CardType},
|
||||
Digimon, Digivolve, Item,
|
||||
},
|
||||
Bytes,
|
||||
game::card::{
|
||||
self,
|
||||
property::{self, CardType},
|
||||
Digimon, Digivolve, Item,
|
||||
},
|
||||
io::{address::Data, GameFile},
|
||||
util::{array_split, array_split_mut},
|
||||
};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use dcb_bytes::Bytes;
|
||||
use std::{
|
||||
convert::TryInto,
|
||||
io::{Read, Seek, Write},
|
||||
|
||||
@ -57,9 +57,9 @@ generate_enum_property_mod! {
|
||||
}
|
||||
|
||||
generate_enum_property_option!(
|
||||
City => 0,
|
||||
ArmorEvo => 0,
|
||||
Music => 0,
|
||||
pub struct MaybeCity (City ) => 0,
|
||||
pub struct MaybeArmorEvo(ArmorEvo) => 0,
|
||||
pub struct MaybeMusic (Music ) => 0,
|
||||
);
|
||||
|
||||
// Modules
|
||||
|
||||
@ -2,10 +2,7 @@
|
||||
|
||||
// Imports
|
||||
use crate::{
|
||||
game::{
|
||||
deck::{armor_evo, city, music, ArmorEvo, City, Music},
|
||||
Bytes,
|
||||
},
|
||||
game::deck::{armor_evo, city, music, ArmorEvo, City, MaybeArmorEvo, MaybeCity, MaybeMusic, Music},
|
||||
util::{
|
||||
array_split, array_split_mut,
|
||||
null_ascii_string::{self, NullAsciiString},
|
||||
@ -13,6 +10,7 @@ use crate::{
|
||||
AsciiStrArr,
|
||||
};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use dcb_bytes::Bytes;
|
||||
|
||||
/// Card id type
|
||||
pub type CardId = u16;
|
||||
@ -119,10 +117,10 @@ impl Bytes for Deck {
|
||||
name: bytes.name.read_string().map_err(FromBytesError::Name)?,
|
||||
owner: bytes.owner.read_string().map_err(FromBytesError::Owner)?,
|
||||
cards,
|
||||
city: Option::<City>::from_bytes(bytes.city).map_err(FromBytesError::City)?,
|
||||
armor_evo: Option::<ArmorEvo>::from_bytes(bytes.armor_evo).map_err(FromBytesError::ArmorEvo)?,
|
||||
battle_music: Option::<Music>::from_bytes(bytes.battle_music).map_err(FromBytesError::BattleMusic)?,
|
||||
polygon_music: Option::<Music>::from_bytes(bytes.polygon_music).map_err(FromBytesError::PolygonMusic)?,
|
||||
city: MaybeCity::from_bytes(bytes.city).map_err(FromBytesError::City)?.into(),
|
||||
armor_evo: MaybeArmorEvo::from_bytes(bytes.armor_evo).map_err(FromBytesError::ArmorEvo)?.into(),
|
||||
battle_music: MaybeMusic::from_bytes(bytes.battle_music).map_err(FromBytesError::BattleMusic)?.into(),
|
||||
polygon_music: MaybeMusic::from_bytes(bytes.polygon_music).map_err(FromBytesError::PolygonMusic)?.into(),
|
||||
experience: *bytes.experience,
|
||||
unknown_64: *bytes.unknown_64,
|
||||
unknown_6a: *bytes.unknown_6a,
|
||||
@ -160,14 +158,14 @@ impl Bytes for Deck {
|
||||
*bytes.experience = self.experience;
|
||||
|
||||
// City
|
||||
self.city.to_bytes(bytes.city).into_ok();
|
||||
<&MaybeCity>::from(&self.city).to_bytes(bytes.city).into_ok();
|
||||
|
||||
// Armor evo
|
||||
self.armor_evo.to_bytes(bytes.armor_evo).into_ok();
|
||||
<&MaybeArmorEvo>::from(&self.armor_evo).to_bytes(bytes.armor_evo).into_ok();
|
||||
|
||||
// Music
|
||||
self.battle_music.to_bytes(bytes.battle_music).into_ok();
|
||||
self.polygon_music.to_bytes(bytes.polygon_music).into_ok();
|
||||
<&MaybeMusic>::from(&self.battle_music).to_bytes(bytes.battle_music).into_ok();
|
||||
<&MaybeMusic>::from(&self.polygon_music).to_bytes(bytes.polygon_music).into_ok();
|
||||
|
||||
// Unknown
|
||||
*bytes.unknown_64 = self.unknown_64;
|
||||
|
||||
@ -8,7 +8,7 @@ pub use error::{DeserializeError, SerializeError};
|
||||
|
||||
// Imports
|
||||
use crate::{
|
||||
game::{Bytes, Deck},
|
||||
game::{Deck},
|
||||
io::{address::Data, GameFile},
|
||||
util::array_split_mut,
|
||||
};
|
||||
@ -17,6 +17,7 @@ use std::{
|
||||
convert::TryInto,
|
||||
io::{Read, Seek, Write},
|
||||
};
|
||||
use dcb_bytes::Bytes;
|
||||
|
||||
/// The decks table, where all decks are stored
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
|
||||
@ -107,5 +107,5 @@ mod util;
|
||||
|
||||
// Exports
|
||||
pub use ascii_str_arr::AsciiStrArr;
|
||||
pub use game::{Bytes, CardTable, Deck, DeckTable, Digimon, Digivolve, Item, Validatable, Validation};
|
||||
pub use game::{CardTable, Deck, DeckTable, Digimon, Digivolve, Item, Validatable, Validation};
|
||||
pub use io::GameFile;
|
||||
|
||||
@ -74,7 +74,7 @@ macro_rules! generate_enum_property_mod
|
||||
)+
|
||||
}
|
||||
|
||||
/// Error type for [`$crate::game::Bytes::from_bytes`]
|
||||
/// Error type for [`::dcb_bytes::Bytes::from_bytes`]
|
||||
#[derive(PartialEq, Eq, Clone, Copy, ::std::fmt::Debug, ::thiserror::Error)]
|
||||
pub enum FromBytesError {
|
||||
|
||||
@ -85,7 +85,7 @@ macro_rules! generate_enum_property_mod
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::game::Bytes for $enum_name
|
||||
impl ::dcb_bytes::Bytes for $enum_name
|
||||
{
|
||||
type ByteArray = u8;
|
||||
|
||||
@ -129,33 +129,45 @@ macro_rules! generate_enum_property_mod
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements [`Bytes`](crate::game::Bytes) for `Option<E>` where `E`
|
||||
/// Implements [`Bytes`](dcb_bytes::Bytes) for `Option<E>` where `E`
|
||||
/// 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 {
|
||||
(
|
||||
$( $enum_name:ty => $sentinel_value:literal ),* $(,)?
|
||||
$( $struct_vis:vis struct $struct_name:ident ( $enum_vis:vis $enum_name:ty ) => $sentinel_value:literal ),* $(,)?
|
||||
) => {
|
||||
$(
|
||||
#[allow(clippy::diverging_sub_expression)] // Errors might be `!`
|
||||
impl $crate::game::Bytes for Option<$enum_name> {
|
||||
type ByteArray = <$enum_name as $crate::game::Bytes>::ByteArray;
|
||||
#[repr(transparent)]
|
||||
#[derive(derive_more::From, derive_more::Into)]
|
||||
$struct_vis struct $struct_name( $enum_vis Option<$enum_name> );
|
||||
|
||||
type FromError = <$enum_name as $crate::game::Bytes>::FromError;
|
||||
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( None ),
|
||||
_ => Ok( Some( $crate::game::Bytes::from_bytes(bytes)? ) ),
|
||||
$sentinel_value => Ok( Self(None) ),
|
||||
_ => Ok( Self(Some( ::dcb_bytes::Bytes::from_bytes(bytes)? )) ),
|
||||
}
|
||||
}
|
||||
|
||||
type ToError = <$enum_name as $crate::game::Bytes>::ToError;
|
||||
type ToError = <$enum_name as ::dcb_bytes::Bytes>::ToError;
|
||||
fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError>
|
||||
{
|
||||
match self {
|
||||
Some(value) => $crate::game::Bytes::to_bytes(value, bytes)?,
|
||||
match &self.0 {
|
||||
Some(value) => ::dcb_bytes::Bytes::to_bytes(value, bytes)?,
|
||||
None => *bytes = $sentinel_value,
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user