diff --git a/src/ffi/static_data/learnable_moves.rs b/src/ffi/static_data/learnable_moves.rs index a1dab7b..881bf7b 100644 --- a/src/ffi/static_data/learnable_moves.rs +++ b/src/ffi/static_data/learnable_moves.rs @@ -6,8 +6,8 @@ use std::ptr::drop_in_place; /// Instantiates a new Learnable Moves. #[no_mangle] -extern "C" fn learnable_moves_new() -> OwnedPtr> { - Box::into_raw(Box::new(Box::new(LearnableMovesImpl::new()))) +extern "C" fn learnable_moves_new(max_level: LevelInt) -> OwnedPtr> { + Box::into_raw(Box::new(Box::new(LearnableMovesImpl::new(max_level)))) } /// drops a learnablemoves struct. diff --git a/src/static_data/species_data/learnable_moves.rs b/src/static_data/species_data/learnable_moves.rs index 0d92ff0..b4ee6c0 100755 --- a/src/static_data/species_data/learnable_moves.rs +++ b/src/static_data/species_data/learnable_moves.rs @@ -1,5 +1,4 @@ -use hashbrown::hash_map::Entry::{Occupied, Vacant}; -use hashbrown::HashMap; +use indexmap::IndexSet; use std::fmt::Debug; use crate::defines::LevelInt; @@ -12,48 +11,42 @@ pub trait LearnableMoves: Debug { /// Gets all moves a Pokemon can learn when leveling up to a specific level. fn get_learned_by_level(&self, level: LevelInt) -> Option<&Vec>; /// Gets the distinct moves a Pokemon can learn through leveling up. - fn get_distinct_level_moves(&self) -> &Vec; + fn get_distinct_level_moves(&self) -> &IndexSet; } /// The storage of the moves a Pokemon can learn. -#[derive(Default, PartialEq, Eq, Debug)] +#[derive(PartialEq, Eq, Debug)] pub struct LearnableMovesImpl { /// A map of the moves a Pokemon can learn per level. - learned_by_level: HashMap>, + learned_by_level: Vec>, /// A list of the distinct moves a Pokemon can learn through leveling up. - distinct_level_moves: Vec, + distinct_level_moves: IndexSet, } impl LearnableMovesImpl { /// Instantiates a new Learnable Moves. - pub fn new() -> Self { - Self::default() + pub fn new(max_level: LevelInt) -> Self { + Self { + learned_by_level: vec![Vec::new(); (max_level + 1) as usize], + distinct_level_moves: Default::default(), + } } } impl LearnableMoves for LearnableMovesImpl { /// Adds a new level move the Pokemon can learn. fn add_level_move(&mut self, level: LevelInt, m: &StringKey) { - match self.learned_by_level.entry(level) { - Occupied(x) => { - x.into_mut().push(m.clone()); - } - Vacant(_) => { - self.learned_by_level.insert(level, vec![m.clone()]); - } - } - if !self.distinct_level_moves.contains(m) { - self.distinct_level_moves.push(m.clone()); - } + self.learned_by_level.get_mut(level as usize).unwrap().push(m.clone()); + self.distinct_level_moves.insert(m.clone()); } /// Gets all moves a Pokemon can learn when leveling up to a specific level. fn get_learned_by_level(&self, level: LevelInt) -> Option<&Vec> { - self.learned_by_level.get(&level) + self.learned_by_level.get(level as usize) } /// Gets the distinct moves a Pokemon can learn through leveling up. - fn get_distinct_level_moves(&self) -> &Vec { + fn get_distinct_level_moves(&self) -> &IndexSet { &self.distinct_level_moves } } @@ -64,7 +57,7 @@ pub(crate) mod tests { #[test] fn adds_level_moves() { - let mut moves = LearnableMovesImpl::new(); + let mut moves = LearnableMovesImpl::new(100); moves.add_level_move(1, &"foo".into()); moves.add_level_move(1, &"bar".into()); @@ -76,7 +69,7 @@ pub(crate) mod tests { #[test] fn adds_two_same_moves_at_different_level() { - let mut moves = LearnableMovesImpl::new(); + let mut moves = LearnableMovesImpl::new(100); moves.add_level_move(1, &"foo".into()); moves.add_level_move(5, &"foo".into()); diff --git a/src/utils/string_key.rs b/src/utils/string_key.rs index 4c3dd5d..d4d5820 100755 --- a/src/utils/string_key.rs +++ b/src/utils/string_key.rs @@ -14,7 +14,6 @@ use std::sync::LazyLock; /// free speed out of it. Note that StringKeys also compare case insensitive, so that for example /// `charmander` == `Charmander`. #[derive(Clone, Debug)] - pub struct StringKey { /// The underlying reference counted string. str: ArcStr, @@ -29,12 +28,14 @@ static STRING_CACHE: LazyLock>> = LazyLock::new(|| R static EMPTY: LazyLock = LazyLock::new(|| StringKey::new("")); impl StringKey { + #[inline(always)] /// Gets the hash of a string. pub const fn get_hash(s: &str) -> u32 { let mut crc: u32 = 0xffffffff; let mut i: usize = 0; + let bytes = s.as_bytes(); while i < s.len() { - crc = (crc >> 8) ^ CRC_TABLE[((crc ^ (to_lower(s.as_bytes()[i]) as u32)) & 0xff) as usize]; + crc = (crc >> 8) ^ CRC_TABLE[((crc ^ (to_lower(bytes[i]) as u32)) & 0xff) as usize]; i += 1; } crc ^ 0xffffffff @@ -132,6 +133,7 @@ impl ValueIdentifiable for StringKey { /// The difference in ascii characters to translate from uppercase to lowercase. const CAPITAL_DIFF: u8 = b'a' - b'A'; +#[inline(always)] /// Converts a character to lowercased in a const safe way. const fn to_lower(c: u8) -> u8 { if c >= b'A' && c <= b'Z' { diff --git a/tests/common/library_loader.rs b/tests/common/library_loader.rs index c207aac..f209c02 100755 --- a/tests/common/library_loader.rs +++ b/tests/common/library_loader.rs @@ -450,7 +450,7 @@ where } fn parse_moves(value: &Value, move_library: &Box) -> Box { - let mut moves = LearnableMovesImpl::default(); + let mut moves = LearnableMovesImpl::new(100); let level_moves = value.get("levelMoves").unwrap().as_array().unwrap(); for level_move in level_moves {