use crate::{FromArma, FromArmaError, IntoArma, Value};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum InventoryItem {
Item(String, u32),
Magazine(String, u32, u32),
}
impl InventoryItem {
#[must_use]
pub const fn new_item(class: String, count: u32) -> Self {
Self::Item(class, count)
}
#[must_use]
pub const fn new_magazine(class: String, count: u32, ammo: u32) -> Self {
Self::Magazine(class, count, ammo)
}
#[must_use]
pub const fn is_magazine(&self) -> bool {
matches!(self, Self::Magazine(_, _, _))
}
#[must_use]
pub fn class(&self) -> &str {
match self {
Self::Item(c, _) | Self::Magazine(c, _, _) => c.as_str(),
}
}
pub fn set_class(&mut self, class: String) {
match self {
Self::Item(c, _) | Self::Magazine(c, _, _) => *c = class,
}
}
#[must_use]
pub fn count(&self) -> u32 {
match self {
Self::Item(_, c) | Self::Magazine(_, c, _) => c.to_owned(),
}
}
pub fn set_count(&mut self, count: u32) {
match self {
Self::Item(_, c) | Self::Magazine(_, c, _) => *c = count,
}
}
#[must_use]
pub fn ammo(&self) -> Option<u32> {
match self {
Self::Item(..) => None,
Self::Magazine(_, _, a) => Some(a.to_owned()),
}
}
pub fn set_ammo(&mut self, ammo: u32) -> bool {
match self {
Self::Magazine(_, _, a) => {
*a = ammo;
true
}
Self::Item(..) => false,
}
}
}
impl FromArma for InventoryItem {
fn from_arma(s: String) -> Result<Self, FromArmaError> {
let commas = s.matches(',').count();
match commas {
1 => <(String, u32)>::from_arma(s).map(|(name, count)| Self::Item(name, count)),
2 => <(String, u32, u32)>::from_arma(s)
.map(|(name, count, ammo)| Self::Magazine(name, count, ammo)),
_ => Err(FromArmaError::custom(format!(
"Invalid inventory item: {s}"
))),
}
}
}
impl IntoArma for InventoryItem {
fn to_arma(&self) -> Value {
match self {
Self::Item(name, count) => Value::Array(vec![
Value::String(name.clone()),
Value::Number(f64::from(*count)),
]),
Self::Magazine(name, count, ammo) => Value::Array(vec![
Value::String(name.clone()),
Value::Number(f64::from(*count)),
Value::Number(f64::from(*ammo)),
]),
}
}
}
#[cfg(test)]
mod tests {
use crate::{FromArma, IntoArma, Value};
use super::InventoryItem;
#[test]
fn is() {
let item = InventoryItem::new_item("test".to_owned(), 1);
assert_eq!(item.class(), "test");
assert_eq!(item.count(), 1);
assert_eq!(item.ammo(), None);
assert!(!item.is_magazine());
let item = InventoryItem::new_magazine("test".to_owned(), 1, 1);
assert_eq!(item.class(), "test");
assert_eq!(item.count(), 1);
assert_eq!(item.ammo(), Some(1));
assert!(item.is_magazine());
}
#[test]
fn class() {
let mut item = InventoryItem::new_item("test".to_owned(), 1);
assert_eq!(item.class(), "test");
item.set_class("test2".to_owned());
assert_eq!(item.class(), "test2");
}
#[test]
fn count() {
let mut item = InventoryItem::new_item("test".to_owned(), 1);
assert_eq!(item.count(), 1);
item.set_count(2);
assert_eq!(item.count(), 2);
}
#[test]
fn ammo() {
let item = InventoryItem::new_magazine("test".to_owned(), 1, 1);
assert_eq!(item.ammo(), Some(1));
assert!(item.is_magazine());
let item = InventoryItem::new_item("test".to_owned(), 1);
assert_eq!(item.ammo(), None);
assert!(!item.is_magazine());
}
#[test]
fn from_arma() {
let item = InventoryItem::from_arma("[\"test\",1]".to_owned()).unwrap();
assert_eq!(item.class(), "test");
assert_eq!(item.count(), 1);
assert_eq!(item.ammo(), None);
assert!(!item.is_magazine());
let item = InventoryItem::from_arma("[\"test\",1,1]".to_owned()).unwrap();
assert_eq!(item.class(), "test");
assert_eq!(item.count(), 1);
assert_eq!(item.ammo(), Some(1));
assert!(item.is_magazine());
}
#[test]
fn to_arma() {
let item = InventoryItem::new_item("test".to_owned(), 1);
assert_eq!(
item.to_arma(),
Value::Array(vec![Value::String("test".to_owned()), Value::Number(1.0),])
);
let item = InventoryItem::new_magazine("test".to_owned(), 1, 1);
assert_eq!(
item.to_arma(),
Value::Array(vec![
Value::String("test".to_owned()),
Value::Number(1.0),
Value::Number(1.0),
])
);
}
}