use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RecipeId {
pub namespace: String,
pub path: String,
}
impl RecipeId {
pub fn new(namespace: impl Into<String>, path: impl Into<String>) -> Self {
Self {
namespace: namespace.into(),
path: path.into(),
}
}
pub fn vanilla(path: impl Into<String>) -> Self {
Self::new("minecraft", path)
}
pub fn parse(input: &str) -> Option<Self> {
let (ns, path) = input.split_once(':')?;
if ns.is_empty() || path.is_empty() {
return None;
}
Some(Self::new(ns, path))
}
}
impl fmt::Display for RecipeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.namespace, self.path)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_owns_strings() {
let id = RecipeId::new("plugin", "magic_sword");
assert_eq!(id.namespace, "plugin");
assert_eq!(id.path, "magic_sword");
}
#[test]
fn vanilla_uses_minecraft_namespace() {
let id = RecipeId::vanilla("oak_planks");
assert_eq!(id.namespace, "minecraft");
assert_eq!(id.path, "oak_planks");
}
#[test]
fn display_round_trips_with_parse() {
let id = RecipeId::vanilla("crafting_table");
let s = id.to_string();
assert_eq!(s, "minecraft:crafting_table");
assert_eq!(RecipeId::parse(&s), Some(id));
}
#[test]
fn parse_rejects_missing_colon() {
assert_eq!(RecipeId::parse("oak_planks"), None);
}
#[test]
fn parse_rejects_empty_namespace() {
assert_eq!(RecipeId::parse(":oak_planks"), None);
}
#[test]
fn parse_rejects_empty_path() {
assert_eq!(RecipeId::parse("minecraft:"), None);
}
#[test]
fn parse_takes_first_colon() {
let id = RecipeId::parse("ns:a:b").unwrap();
assert_eq!(id.namespace, "ns");
assert_eq!(id.path, "a:b");
}
#[test]
fn equality_is_exact() {
assert_eq!(
RecipeId::vanilla("oak_planks"),
RecipeId::new("minecraft", "oak_planks")
);
assert_ne!(
RecipeId::vanilla("oak_planks"),
RecipeId::vanilla("birch_planks")
);
}
#[test]
fn hashable_in_collections() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(RecipeId::vanilla("oak_planks"));
assert!(set.contains(&RecipeId::new("minecraft", "oak_planks")));
}
}