savestate: add various TryFrom impl for Moves and Move

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
Maxime “pep” Buquet 2020-06-30 15:21:44 +02:00
parent 08ad8073c8
commit ea93ad32cb
Signed by: pep
GPG key ID: DEDA74AEECA9D0F2

View file

@ -321,22 +321,30 @@ impl fmt::Debug for Move {
}
}
impl TryFrom<&[u8; 2]> for Move {
impl TryFrom<(u8, u8)> for Move {
type Error = Error;
fn try_from(data: &[u8; 2]) -> Result<Move, Error> {
if data[0x0] > 165 { // Gen1 doesn't have more than that number of moves
fn try_from((id, pp): (u8, u8)) -> Result<Move, Error> {
if id > 165 { // Gen1 doesn't have more than that number of moves
return Err(Error::InvalidPokemonMove);
}
Ok(Move {
id: data[0x0],
pp: data[0x1] & 0b00111111,
up: PPUp::try_from((data[0x1] & 0b11000000) >> 6)?,
id: id,
pp: pp & 0b00111111,
up: PPUp::try_from((pp & 0b11000000) >> 6)?,
})
}
}
impl TryFrom<&[u8; 2]> for Move {
type Error = Error;
fn try_from(data: &[u8; 2]) -> Result<Move, Error> {
Move::try_from((data[0], data[1]))
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Moves([Option<Move>; 4]);
@ -348,35 +356,33 @@ impl Deref for Moves {
}
}
impl TryFrom<&[u8]> for Moves {
impl TryFrom<(&[u8], &[u8])> for Moves {
type Error = Error;
fn try_from(data: &[u8]) -> Result<Moves, Error> {
let data: &[u8; 8] = data.try_into()?;
Moves::try_from(data)
fn try_from(data: (&[u8], &[u8])) -> Result<Moves, Error> {
let moves: &[u8; 4] = data.0.try_into()?;
let pps: &[u8; 4] = data.1.try_into()?;
Moves::try_from((moves, pps))
}
}
impl TryFrom<&[u8; 8]> for Moves {
impl TryFrom<(&[u8; 4], &[u8; 4])> for Moves {
type Error = Error;
fn try_from(data: &[u8; 8]) -> Result<Moves, Error> {
const PP_OFFSET: usize = 0x4;
fn try_from((moves, pps): (&[u8; 4], &[u8; 4])) -> Result<Moves, Error> {
let array: [Option<Move>; 4] = [None; 4];
let mut vec = array.to_vec();
for i in 0..4 {
if data[i] == 0x0 {
if moves[i] == 0x0 {
continue;
}
let sub: [u8; 2] = [data[i], data[PP_OFFSET + i]];
vec[i] = Some(Move::try_from(&sub)?);
vec[i] = Some(Move::try_from((moves[i], pps[i]))?);
}
let foo: [Option<Move>; 4] = vec.as_slice().try_into()?;
Ok(Moves (foo))
let tmp: [Option<Move>; 4] = vec.as_slice().try_into()?;
Ok(Moves (tmp))
}
}
@ -551,9 +557,7 @@ impl TryFrom<&[u8]> for IndividualPk {
(data[PK_XP_OFFSET + 0x2] as u32)
};
let original_trainer: u16 = u16::from_be_bytes(data[PK_OT_RANGE].try_into().unwrap());
let mut moves_data: Vec<u8> = data[PK_MOVES_RANGE].to_vec();
moves_data.extend_from_slice(&data[PK_PP_RANGE]);
let moves = Moves::try_from(moves_data.as_slice())?;
let moves = Moves::try_from((&data[PK_MOVES_RANGE], &data[PK_PP_RANGE]))?;
Ok(IndividualPk {
_data: data.to_vec(),
@ -574,7 +578,10 @@ impl TryFrom<&[u8]> for IndividualPk {
#[cfg(test)]
mod tests {
use std::convert::TryFrom;
use crate::species::{EV, IndividualPk, IV, Move, PPUp, PKTypes, PKType, Species, StatusConditions};
use crate::species::{
EV, IndividualPk, IV, Moves, Move, PPUp,
PKTypes, PKType, Species, StatusConditions,
};
const KADABRA: [u8; 44] = [
// Species id
@ -675,10 +682,32 @@ mod tests {
].into());
}
#[test]
fn test_move_try_from() {
let data1: (u8, u8) = (0x65, 0x52);
let move1 = Move::try_from(data1).unwrap();
let data2: &[u8; 2] = &[0x65, 0x52];
let move2 = Move::try_from(data2).unwrap();
assert_eq!(move1, Move { id: 0x65, pp: 18, up: PPUp::PPUp1 });
assert_eq!(move1, move2);
}
#[test]
fn test_move_ppup() {
let data: [u8; 2] = [0x65, 0x52];
let move1 = Move::try_from(&data).unwrap();
assert_eq!(move1, Move { id: 0x65, pp: 18, up: PPUp::PPUp1 });
}
#[test]
fn test_moves_try_from() {
let moves: [u8; 4] = [0x64, 0x5d, 0x0, 0x0];
let pps: [u8; 4] = [0x14, 0x19, 0x0, 0x0];
let results = Moves::try_from((&moves, &pps)).unwrap();
assert_eq!(results, [
Some(Move { id: 0x64, pp: 20, up: PPUp::None }),
Some(Move { id: 0x5d, pp: 25, up: PPUp::None }),
None, None,
].into());
}
}