use super::super::Guid;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum RecipeKind {
BuildingBlock,
Roof,
Overgrowth,
Terrain,
Decorative,
ComfortFurniture,
Other,
}
impl RecipeKind {
pub const ALL: &[Self] = &[
Self::Other,
Self::BuildingBlock,
Self::Roof,
Self::Overgrowth,
Self::Terrain,
Self::Decorative,
Self::ComfortFurniture,
];
#[must_use]
pub const fn name(self) -> &'static str {
match self {
Self::BuildingBlock => "building-block",
Self::Roof => "roof",
Self::Overgrowth => "overgrowth",
Self::Terrain => "terrain",
Self::Decorative => "decorative",
Self::ComfortFurniture => "comfort-furniture",
Self::Other => "other",
}
}
#[must_use]
pub fn named(name: &str) -> Option<Self> {
Self::ALL.iter().copied().find(|kind| kind.name() == name)
}
#[must_use]
pub const fn code(self) -> crate::abi::RecipeKind {
use crate::abi::RecipeKind as Abi;
match self {
Self::BuildingBlock => Abi::BUILDING_BLOCK,
Self::Roof => Abi::ROOF,
Self::Overgrowth => Abi::OVERGROWTH,
Self::Terrain => Abi::TERRAIN,
Self::Decorative => Abi::DECORATIVE,
Self::ComfortFurniture => Abi::COMFORT_FURNITURE,
Self::Other => Abi::OTHER,
}
}
pub(super) fn of(item: Guid) -> Option<Self> {
let host = crate::host()?;
let mut out = crate::abi::RecipeKind::OTHER;
(host.api().recipe_kind)(
host.handle(),
crate::ItemId::new(item.fnv1a()),
&raw mut out,
)
.is_ok()
.then(|| out.into())
}
}
impl From<crate::abi::RecipeKind> for RecipeKind {
fn from(kind: crate::abi::RecipeKind) -> Self {
use crate::abi::RecipeKind as Abi;
match kind {
Abi::BUILDING_BLOCK => Self::BuildingBlock,
Abi::ROOF => Self::Roof,
Abi::OVERGROWTH => Self::Overgrowth,
Abi::TERRAIN => Self::Terrain,
Abi::DECORATIVE => Self::Decorative,
Abi::COMFORT_FURNITURE => Self::ComfortFurniture,
_ => Self::Other,
}
}
}
impl From<RecipeKind> for crate::abi::RecipeKind {
fn from(kind: RecipeKind) -> Self {
kind.code()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn every_kind_reads_back_from_its_name() {
for kind in RecipeKind::ALL {
assert_eq!(RecipeKind::named(kind.name()), Some(*kind));
}
assert_eq!(RecipeKind::named("Roof"), None);
}
#[test]
fn every_kind_reads_back_from_its_code_and_each_code_is_its_own() {
for (i, kind) in RecipeKind::ALL.iter().enumerate() {
assert_eq!(RecipeKind::from(kind.code()), *kind);
assert!(
RecipeKind::ALL[i + 1..]
.iter()
.all(|k| k.code() != kind.code())
);
}
}
#[test]
fn comfort_furniture_has_a_kind_of_its_own() {
assert_eq!(
RecipeKind::named("comfort-furniture"),
Some(RecipeKind::ComfortFurniture)
);
assert_eq!(
RecipeKind::ComfortFurniture.code(),
crate::abi::RecipeKind::COMFORT_FURNITURE
);
}
#[test]
fn decorative_props_have_a_kind_of_their_own() {
assert_eq!(
RecipeKind::named("decorative"),
Some(RecipeKind::Decorative)
);
assert_eq!(
RecipeKind::Decorative.code(),
crate::abi::RecipeKind::DECORATIVE
);
}
}