Moved util from game module to crate level to add functions more global, outside of game.

Removed all `as` conversions lints and fixed code using them.
This commit is contained in:
2020-07-14 22:11:14 +01:00
parent b08c6431cf
commit 09c716a804
18 changed files with 139 additions and 80 deletions

View File

@@ -1,13 +1,15 @@
#![doc(include = "digimon.md")]
// Imports
use crate::game::{
card::property::{self, ArrowColor, CrossMoveEffect, Effect, EffectCondition, Level, Move, Speciality},
use crate::{
game::{
card::property::{self, ArrowColor, CrossMoveEffect, Effect, EffectCondition, Level, Move, Speciality},
Bytes,
},
util::{
array_split, array_split_mut,
null_ascii_string::{self, NullAsciiString},
},
Bytes,
};
use byteorder::{ByteOrder, LittleEndian};

View File

@@ -1,12 +1,12 @@
#![doc(include = "digivolve.md")]
// Imports
use crate::game::{
use crate::{
game::Bytes,
util::{
array_split, array_split_mut,
null_ascii_string::{self, NullAsciiString},
},
Bytes,
};
/// A digivolve card

View File

@@ -1,13 +1,15 @@
#![doc(include = "item.md")]
// Imports
use crate::game::{
card::property::{self, ArrowColor, Effect, EffectCondition},
use crate::{
game::{
card::property::{self, ArrowColor, Effect, EffectCondition},
Bytes,
},
util::{
array_split, array_split_mut,
null_ascii_string::{self, NullAsciiString},
},
Bytes,
};
use byteorder::{ByteOrder, LittleEndian};

View File

@@ -1,10 +1,12 @@
#![doc(include = "effect.md")]
// Imports
use crate::game::{
card::property::{self, AttackType, DigimonProperty, EffectOperation, PlayerType, Slot},
use crate::{
game::{
card::property::{self, AttackType, DigimonProperty, EffectOperation, PlayerType, Slot},
Bytes,
},
util::{array_split, array_split_mut},
Bytes,
};
use byteorder::{ByteOrder, LittleEndian};

View File

@@ -1,10 +1,12 @@
#![doc(include = "effect_condition.md")]
// Imports
use crate::game::{
card::property::{self, DigimonProperty, EffectConditionOperation},
use crate::{
game::{
card::property::{self, DigimonProperty, EffectConditionOperation},
Bytes,
},
util::{array_split, array_split_mut},
Bytes,
};
use byteorder::{ByteOrder, LittleEndian};

View File

@@ -5,12 +5,12 @@
mod test;
// Imports
use crate::game::{
use crate::{
game::{Bytes, Validatable, Validation},
util::{
array_split, array_split_mut,
null_ascii_string::{self, NullAsciiString},
},
Bytes, Validatable, Validation,
};
use byteorder::{ByteOrder, LittleEndian};

View File

@@ -8,13 +8,16 @@ use crate::{
property::{self, CardType},
Digimon, Digivolve, Item,
},
util::array_split_mut,
Bytes,
},
io::{address::Data, GameFile},
util::array_split_mut,
};
use byteorder::{ByteOrder, LittleEndian};
use std::io::{Read, Seek, Write};
use std::{
convert::TryInto,
io::{Read, Seek, Write},
};
/// The table storing all cards
#[derive(Debug)]
@@ -291,9 +294,9 @@ impl Table {
}
// Then check the number of each card
let digimon_cards = LittleEndian::read_u16(&header_bytes[0x4..0x6]) as usize;
let item_cards = header_bytes[0x6] as usize;
let digivolve_cards = header_bytes[0x7] as usize;
let digimon_cards: usize = LittleEndian::read_u16(&header_bytes[0x4..0x6]).into();
let item_cards: usize = header_bytes[0x6].into();
let digivolve_cards: usize = header_bytes[0x7].into();
log::debug!("[Table Header] Found {} digimon cards", digimon_cards);
log::debug!("[Table Header] Found {} item cards", item_cards);
log::debug!("[Table Header] Found {} digivolve cards", digivolve_cards);
@@ -409,13 +412,15 @@ impl Table {
LittleEndian::write_u32(bytes.magic, Self::HEADER_MAGIC);
// Write card lens
use std::convert::TryInto;
log::debug!("[Table Header] Writing {} digimon cards", self.digimons.len());
log::debug!("[Table Header] Writing {} item cards", self.items.len());
log::debug!("[Table Header] Writing {} digivolve cards", self.digivolves.len());
LittleEndian::write_u16(bytes.digimons_len, self.digimons.len().try_into().expect("Too many digimons"));
*bytes.items_len = self.items.len().try_into().expect("Too many items");
*bytes.digivolves_len = self.digivolves.len().try_into().expect("Too many digivolves");
LittleEndian::write_u16(
bytes.digimons_len,
self.digimons.len().try_into().expect("Number of digimon cards exceeded `u16`"),
);
*bytes.items_len = self.items.len().try_into().expect("Number of item cards exceeded `u8`");
*bytes.digivolves_len = self.digivolves.len().try_into().expect("Number of digivolve cards exceeded `u8`");
}
file.write_all(&header_bytes).map_err(SerializeError::WriteHeader)?;
@@ -435,7 +440,7 @@ impl Table {
);
// Write the header
LittleEndian::write_u16(bytes.header_id, cur_id as u16);
LittleEndian::write_u16(bytes.header_id, cur_id.try_into().expect("Card ID exceeded `u16`"));
CardType::Digimon.to_bytes(bytes.header_type)?;
// Write the digimon
@@ -464,7 +469,7 @@ impl Table {
);
// Write the header
LittleEndian::write_u16(bytes.header_id, cur_id as u16);
LittleEndian::write_u16(bytes.header_id, cur_id.try_into().expect("Card ID exceeded `u16`"));
CardType::Item.to_bytes(bytes.header_type)?;
// Write the item
@@ -492,7 +497,7 @@ impl Table {
);
// Write the header
LittleEndian::write_u16(bytes.header_id, cur_id as u16);
LittleEndian::write_u16(bytes.header_id, cur_id.try_into().expect("Card ID exceeded `u16`"));
CardType::Digivolve.to_bytes(bytes.header_type)?;
// Write the digivolve

View File

@@ -1,12 +1,12 @@
//! Decks
// Imports
use crate::game::{
use crate::{
game::Bytes,
util::{
array_split, array_split_mut,
null_ascii_string::{self, NullAsciiString},
},
Bytes,
};
use byteorder::{ByteOrder, LittleEndian};

View File

@@ -1,14 +0,0 @@
//! Utility macros and functions
//!
//! This modules is used for miscellaneous macros, functions that have
//! not been moved to a more permanent location.
//!
//! All items in this module will eventually be deprecated and moved
//! somewhere else, but this change might take some time.
// Modules
pub mod array_split;
pub mod null_ascii_string;
// Exports
pub use array_split::{array_split, array_split_mut};

View File

@@ -1,109 +0,0 @@
//! Array splitters
/// Splits an array into various members
pub macro array_split {
(
$arr:expr,
$(
$name:ident :
$( [$arr_size:expr] )?
$( $val_size:literal )?
),* $(,)?
) => {{
#![allow(
clippy::used_underscore_binding,
clippy::ptr_offset_with_cast,
clippy::indexing_slicing,
)]
// Struct holding all fields
struct Fields<'a, T> {
$(
$name:
$( &'a [T; $arr_size], )?
$( &'a T, #[cfg(invalid)] __field: [u8; $val_size], )?
)*
}
// Get everything from `array_refs`
let (
$(
$name
),*
) = ::arrayref::array_refs!(
$arr,
$(
$( $arr_size )?
$( $val_size )?
),*
);
// And return the fields
Fields {
$(
$name
$( : &( $name[$val_size - $val_size] ) )?
,
)*
}
}}
}
/// Splits an array into various members mutably
#[allow(clippy::module_name_repetitions)] // `_mut` version should be in the same module
pub macro array_split_mut {
(
$arr:expr,
$(
$name:ident :
$( [$arr_size:expr] )?
$( $val_size:literal )?
),* $(,)?
) => {{
#![allow(
clippy::used_underscore_binding,
clippy::ptr_offset_with_cast,
clippy::indexing_slicing,
)]
// Struct holding all fields
struct Fields<'a, T> {
$(
$name:
$( &'a mut [T; $arr_size], )?
// Note: This `cfg` is simply done so that `__field` never appears.
// The `__field` serves to identify when this part should be written.
$( &'a mut T, #[cfg(invalid)] __field: [u8; $val_size], )?
)*
}
// Get everything from `array_refs`
let (
$(
$name
),*
) = ::arrayref::mut_array_refs!(
$arr,
$(
$( $arr_size )?
$( $val_size )?
),*
);
// And return the fields
Fields {
$(
$name
// Note: This serves to turn a `&mut [u8; 1]` into a `&mut u8`.
$( : &mut ( $name[$val_size - $val_size] ) )?
,
)*
}
}}
}

View File

@@ -1,47 +0,0 @@
//! Null-terminated ascii string helpers
// Modules
pub mod error;
// Exports
pub use error::{ReadError, WriteError};
/// Trait for reading null terminated ascii strings from a buffer
pub trait NullAsciiString {
/// Reads a null terminated ascii string from this buffer and returns it
fn read_string(&self) -> Result<&ascii::AsciiStr, ReadError>;
/// Writes a null terminated ascii string to this buffer and returns it
fn write_string(&mut self, s: &ascii::AsciiStr) -> Result<&Self, WriteError>;
}
impl NullAsciiString for [u8] {
fn read_string(&self) -> Result<&ascii::AsciiStr, ReadError> {
// Find the first null and trim the buffer until it
let buf = match self.iter().position(|&b| b == b'\0') {
Some(idx) => &self[0..idx],
None => return Err(ReadError::NoNull),
};
// Then convert it from Ascii
ascii::AsciiStr::from_ascii(buf).map_err(ReadError::NotAscii)
}
fn write_string(&mut self, input: &ascii::AsciiStr) -> Result<&Self, WriteError> {
// If the input string doesn't fit into the buffer (excluding the null byte), return Err
if input.len() >= self.len() {
return Err(WriteError::TooLarge {
input_len: input.len(),
buffer_len: self.len(),
});
}
// Else copy everything over and set the last byte to null
// Note: We leave all other bytes as they are, no need to set them to 0
self[0..input.len()].copy_from_slice(input.as_bytes());
self[input.len()] = 0;
// And return Ok with the buffer
Ok(self)
}
}

View File

@@ -1,22 +0,0 @@
//! Errors
/// Error type for [`read`](super::read)
#[derive(PartialEq, Eq, Clone, Copy, Debug, thiserror::Error)]
pub enum ReadError {
/// No null was found in the string
#[error("No null was found on the buffer")]
NoNull,
/// The string was not ascii
#[error("The buffer did not contain valid Ascii")]
NotAscii(#[source] ascii::AsAsciiStrError),
}
/// Error type for [`write`](super::read)
#[derive(PartialEq, Eq, Clone, Copy, Debug, thiserror::Error)]
#[allow(clippy::missing_docs_in_private_items)]
pub enum WriteError {
/// The input string was too large
#[error("Input string was too large for buffer. ({}+1 / {})", input_len, buffer_len)]
TooLarge { input_len: usize, buffer_len: usize },
}