Replace most panics in the core library with results
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2023-04-19 18:44:11 +02:00
parent 00d596d656
commit c0e4702e45
33 changed files with 222 additions and 102 deletions

View File

@@ -70,6 +70,8 @@ pub struct AbilityIndex {
}
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
#[allow(clippy::unwrap_used)]
pub(crate) mod tests {
use super::*;

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;