//! An item is something the player can hold. Some are raw, some are craftable.
use crate::{
recipe::{Recipe, RECIPES},
FcalcError, Result,
};
use lazy_static::lazy_static;
use serde::Deserialize;
use std::fmt;
lazy_static! {
pub static ref ITEMS: Items = Items::new();
}
#[derive(Clone, Debug, Deserialize)]
pub enum Item {
Raw(RawMaterial),
Product(Product),
}
impl Item {
pub fn recipe(&self) -> Option<&Recipe> {
match self {
Item::Raw(_) => None,
Item::Product(p) => RECIPES.lookup(&p),
}
}
pub fn as_product(&self) -> Result<Product> {
match self {
Item::Product(p) => Ok(p.clone()),
_ => Err(FcalcError::ProductTypeError),
}
}
pub fn as_raw(&self) -> Result<RawMaterial> {
match self {
Item::Raw(r) => Ok(r.clone()),
_ => Err(FcalcError::ProductTypeError),
}
}
}
/// A base-level raw material, not craftable.
#[derive(Clone, Debug, Deserialize)]
pub struct RawMaterial {
name: String,
}
impl fmt::Display for RawMaterial {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name)
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Hash)]
pub struct Product {
name: String,
}
impl fmt::Display for Product {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name)
}
}
/// The top-level Items struct, containing all supported items read from TOML.
#[derive(Debug, Deserialize)]
pub struct Items {
raw_materials: Vec<RawMaterial>,
products: Vec<Product>,
}
impl Items {
fn new() -> Self {
Self::default()
}
/// Find an item by name
pub fn lookup(&self, name: &str) -> Option<Item> {
for r in &self.raw_materials {
if r.name == name {
return Some(Item::Raw(r.clone()));
}
}
for p in &self.products {
if p.name == name {
return Some(Item::Product(p.clone()));
}
}
None
}
}
impl Default for Items {
fn default() -> Self {
let input = include_str!("items.toml");
toml::from_str(input).expect("Could not read items file")
}
}
#[cfg(test)]
mod test {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn it_loads_all_items() {
assert_eq!(ITEMS.raw_materials.len(), 2);
assert_eq!(ITEMS.products.len(), 1)
}
}