Replace most panics in the core library with results
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
@@ -70,6 +70,8 @@ pub struct AbilityIndex {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use anyhow_ext::{ensure, Result};
|
||||
use hashbrown::HashSet;
|
||||
use std::fmt::Debug;
|
||||
|
||||
@@ -5,8 +6,8 @@ use crate::static_data::Statistic;
|
||||
use crate::static_data::TypeIdentifier;
|
||||
use crate::static_data::{Ability, StaticStatisticSet};
|
||||
use crate::static_data::{AbilityIndex, LearnableMoves};
|
||||
use crate::StringKey;
|
||||
use crate::{Random, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::{StringKey, VecExt};
|
||||
|
||||
/// A form is a variant of a specific species. A species always has at least one form, but can have
|
||||
/// many more.
|
||||
@@ -34,7 +35,7 @@ pub trait Form: ValueIdentifiable + Debug {
|
||||
fn flags(&self) -> &HashSet<StringKey>;
|
||||
|
||||
/// Get a type of the move at a certain index.
|
||||
fn get_type(&self, index: usize) -> TypeIdentifier;
|
||||
fn get_type(&self, index: usize) -> Result<TypeIdentifier>;
|
||||
|
||||
/// Gets a single base stat value.
|
||||
fn get_base_stat(&self, stat: Statistic) -> u16;
|
||||
@@ -42,12 +43,12 @@ pub trait Form: ValueIdentifiable + Debug {
|
||||
fn find_ability_index(&self, ability: &dyn Ability) -> Option<AbilityIndex>;
|
||||
|
||||
/// Gets an ability from the form.
|
||||
fn get_ability(&self, index: AbilityIndex) -> &StringKey;
|
||||
fn get_ability(&self, index: AbilityIndex) -> Result<&StringKey>;
|
||||
|
||||
/// Gets a random ability from the form.
|
||||
fn get_random_ability(&self, rand: &mut Random) -> &StringKey;
|
||||
fn get_random_ability(&self, rand: &mut Random) -> Result<&StringKey>;
|
||||
/// Gets a random hidden ability from the form.
|
||||
fn get_random_hidden_ability(&self, rand: &mut Random) -> &StringKey;
|
||||
fn get_random_hidden_ability(&self, rand: &mut Random) -> Result<&StringKey>;
|
||||
|
||||
/// Check if the form has a specific flag set.
|
||||
fn has_flag(&self, key: &StringKey) -> bool;
|
||||
@@ -158,8 +159,8 @@ impl Form for FormImpl {
|
||||
}
|
||||
|
||||
/// Get a type of the move at a certain index.
|
||||
fn get_type(&self, index: usize) -> TypeIdentifier {
|
||||
self.types[index]
|
||||
fn get_type(&self, index: usize) -> Result<TypeIdentifier> {
|
||||
Ok(*self.types.get_res(index)?)
|
||||
}
|
||||
|
||||
/// Gets a single base stat value.
|
||||
@@ -189,21 +190,25 @@ impl Form for FormImpl {
|
||||
}
|
||||
|
||||
/// Gets an ability from the form.
|
||||
fn get_ability(&self, index: AbilityIndex) -> &StringKey {
|
||||
fn get_ability(&self, index: AbilityIndex) -> Result<&StringKey> {
|
||||
if index.hidden {
|
||||
&self.hidden_abilities[index.index as usize]
|
||||
Ok(self.hidden_abilities.get_res(index.index as usize)?)
|
||||
} else {
|
||||
&self.abilities[index.index as usize]
|
||||
Ok(self.abilities.get_res(index.index as usize)?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a random ability from the form.
|
||||
fn get_random_ability(&self, rand: &mut Random) -> &StringKey {
|
||||
&self.abilities[rand.get_between_unsigned(0, self.abilities.len() as u32) as usize]
|
||||
fn get_random_ability(&self, rand: &mut Random) -> Result<&StringKey> {
|
||||
ensure!(!self.abilities.is_empty(), "No abilities on form");
|
||||
self.abilities
|
||||
.get_res(rand.get_between_unsigned(0, self.abilities.len() as u32) as usize)
|
||||
}
|
||||
/// Gets a random hidden ability from the form.
|
||||
fn get_random_hidden_ability(&self, rand: &mut Random) -> &StringKey {
|
||||
&self.hidden_abilities[rand.get_between_unsigned(0, self.hidden_abilities.len() as u32) as usize]
|
||||
fn get_random_hidden_ability(&self, rand: &mut Random) -> Result<&StringKey> {
|
||||
ensure!(!self.hidden_abilities.is_empty(), "No hidden abilities on form");
|
||||
self.hidden_abilities
|
||||
.get_res(rand.get_between_unsigned(0, self.hidden_abilities.len() as u32) as usize)
|
||||
}
|
||||
|
||||
/// Check if the form has a specific flag set.
|
||||
@@ -223,6 +228,8 @@ impl ValueIdentifiable for FormImpl {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -240,12 +247,12 @@ pub(crate) mod tests {
|
||||
fn hidden_abilities(&self) -> &Vec<StringKey>;
|
||||
fn moves(&self) -> &Box<dyn LearnableMoves>;
|
||||
fn flags(&self) -> &HashSet<StringKey>;
|
||||
fn get_type(&self, index: usize) -> TypeIdentifier;
|
||||
fn get_type(&self, index: usize) -> Result<TypeIdentifier>;
|
||||
fn get_base_stat(&self, stat: Statistic) -> u16;
|
||||
fn find_ability_index(&self, ability: &dyn Ability) -> Option<AbilityIndex>;
|
||||
fn get_ability(&self, index: AbilityIndex) -> &StringKey;
|
||||
fn get_random_ability(&self, rand: &mut Random) -> &StringKey;
|
||||
fn get_random_hidden_ability(&self, rand: &mut Random) -> &StringKey;
|
||||
fn get_ability<'a>(&'a self, index: AbilityIndex) -> Result<&'a StringKey>;
|
||||
fn get_random_ability<'a>(&'a self, rand: &mut Random) -> Result<&'a StringKey>;
|
||||
fn get_random_hidden_ability<'a>(&'a self, rand: &mut Random) -> Result<&'a StringKey>;
|
||||
fn has_flag(&self, key: &StringKey) -> bool;
|
||||
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
use anyhow_ext::Result;
|
||||
use indexmap::IndexSet;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::defines::LevelInt;
|
||||
use crate::StringKey;
|
||||
use crate::{StringKey, VecExt};
|
||||
|
||||
/// The storage of the moves a Pokemon can learn.
|
||||
pub trait LearnableMoves: Debug {
|
||||
/// Adds a new level move the Pokemon can learn.
|
||||
fn add_level_move(&mut self, level: LevelInt, m: &StringKey);
|
||||
fn add_level_move(&mut self, level: LevelInt, m: &StringKey) -> Result<()>;
|
||||
/// Gets all moves a Pokemon can learn when leveling up to a specific level.
|
||||
fn get_learned_by_level(&self, level: LevelInt) -> Option<&Vec<StringKey>>;
|
||||
/// Gets the distinct moves a Pokemon can learn through leveling up.
|
||||
@@ -35,9 +36,10 @@ impl LearnableMovesImpl {
|
||||
|
||||
impl LearnableMoves for LearnableMovesImpl {
|
||||
/// Adds a new level move the Pokemon can learn.
|
||||
fn add_level_move(&mut self, level: LevelInt, m: &StringKey) {
|
||||
self.learned_by_level.get_mut(level as usize).unwrap().push(m.clone());
|
||||
fn add_level_move(&mut self, level: LevelInt, m: &StringKey) -> Result<()> {
|
||||
self.learned_by_level.get_mut_res(level as usize)?.push(m.clone());
|
||||
self.distinct_level_moves.insert(m.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets all moves a Pokemon can learn when leveling up to a specific level.
|
||||
@@ -52,14 +54,16 @@ impl LearnableMoves for LearnableMovesImpl {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn adds_level_moves() {
|
||||
let mut moves = LearnableMovesImpl::new(100);
|
||||
moves.add_level_move(1, &"foo".into());
|
||||
moves.add_level_move(1, &"bar".into());
|
||||
moves.add_level_move(1, &"foo".into()).unwrap();
|
||||
moves.add_level_move(1, &"bar".into()).unwrap();
|
||||
|
||||
let m = moves.get_learned_by_level(1u8).unwrap();
|
||||
assert_eq!(m.len(), 2);
|
||||
@@ -71,8 +75,8 @@ pub(crate) mod tests {
|
||||
fn adds_two_same_moves_at_different_level() {
|
||||
let mut moves = LearnableMovesImpl::new(100);
|
||||
|
||||
moves.add_level_move(1, &"foo".into());
|
||||
moves.add_level_move(5, &"foo".into());
|
||||
moves.add_level_move(1, &"foo".into()).unwrap();
|
||||
moves.add_level_move(5, &"foo".into()).unwrap();
|
||||
|
||||
let m = moves.get_learned_by_level(1u8).unwrap();
|
||||
assert_eq!(m.len(), 1);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use anyhow_ext::{anyhow, Result};
|
||||
use std::fmt::Debug;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
|
||||
@@ -34,7 +35,7 @@ pub trait Species: ValueIdentifiable + Debug {
|
||||
/// Gets a form by the hash of its name.
|
||||
fn get_form_by_hash(&self, name_hash: u32) -> Option<Arc<dyn Form>>;
|
||||
/// Gets the form the Pokemon will have by default, if no other form is specified.
|
||||
fn get_default_form(&self) -> Arc<dyn Form>;
|
||||
fn get_default_form(&self) -> Result<Arc<dyn Form>>;
|
||||
/// Gets a random gender.
|
||||
fn get_random_gender(&self, rand: &mut Random) -> Gender;
|
||||
/// Check whether the Pokemon has a specific flag set.
|
||||
@@ -145,8 +146,13 @@ impl Species for SpeciesImpl {
|
||||
}
|
||||
|
||||
/// Gets the form the Pokemon will have by default, if no other form is specified.
|
||||
fn get_default_form(&self) -> Arc<dyn Form> {
|
||||
self.forms.read().get(&get_default_key()).unwrap().clone()
|
||||
fn get_default_form(&self) -> Result<Arc<dyn Form>> {
|
||||
Ok(self
|
||||
.forms
|
||||
.read()
|
||||
.get(&get_default_key())
|
||||
.ok_or(anyhow!("No default form for species"))?
|
||||
.clone())
|
||||
}
|
||||
|
||||
/// Gets a random gender.
|
||||
@@ -177,6 +183,8 @@ impl ValueIdentifiable for SpeciesImpl {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -194,7 +202,7 @@ pub(crate) mod tests {
|
||||
fn add_form(&self, id: StringKey, form: Arc<dyn Form>);
|
||||
fn get_form(&self, id: &StringKey) -> Option<Arc<dyn Form>>;
|
||||
fn get_form_by_hash(&self, name_hash: u32) -> Option<Arc<dyn Form>>;
|
||||
fn get_default_form(&self) -> Arc<dyn Form>;
|
||||
fn get_default_form(&self) -> Result<Arc<dyn Form>>;
|
||||
fn get_random_gender(&self, rand: &mut Random) -> Gender;
|
||||
fn has_flag(&self, key: &StringKey) -> bool;
|
||||
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
|
||||
|
||||
Reference in New Issue
Block a user