1use crate::{FromArma, FromArmaError, IntoArma, Value};
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub enum InventoryItem {
6 Item(String, u32),
8 Magazine(String, u32, u32),
10}
11impl InventoryItem {
12 #[must_use]
14 pub const fn new_item(class: String, count: u32) -> Self {
15 Self::Item(class, count)
16 }
17
18 #[must_use]
20 pub const fn new_magazine(class: String, count: u32, ammo: u32) -> Self {
21 Self::Magazine(class, count, ammo)
22 }
23
24 #[must_use]
26 pub const fn is_magazine(&self) -> bool {
27 matches!(self, Self::Magazine(_, _, _))
28 }
29
30 #[must_use]
32 pub fn class(&self) -> &str {
33 match self {
34 Self::Item(c, _) | Self::Magazine(c, _, _) => c.as_str(),
35 }
36 }
37
38 pub fn set_class(&mut self, class: String) {
40 match self {
41 Self::Item(c, _) | Self::Magazine(c, _, _) => *c = class,
42 }
43 }
44
45 #[must_use]
47 pub fn count(&self) -> u32 {
48 match self {
49 Self::Item(_, c) | Self::Magazine(_, c, _) => c.to_owned(),
50 }
51 }
52
53 pub fn set_count(&mut self, count: u32) {
55 match self {
56 Self::Item(_, c) | Self::Magazine(_, c, _) => *c = count,
57 }
58 }
59
60 #[must_use]
62 pub fn ammo(&self) -> Option<u32> {
63 match self {
64 Self::Item(..) => None,
65 Self::Magazine(_, _, a) => Some(a.to_owned()),
66 }
67 }
68
69 pub fn set_ammo(&mut self, ammo: u32) -> bool {
72 match self {
73 Self::Magazine(_, _, a) => {
74 *a = ammo;
75 true
76 }
77 Self::Item(..) => false,
78 }
79 }
80}
81impl FromArma for InventoryItem {
82 fn from_arma(s: String) -> Result<Self, FromArmaError> {
83 let commas = s.matches(',').count();
84 match commas {
85 1 => <(String, u32)>::from_arma(s).map(|(name, count)| Self::Item(name, count)),
86 2 => <(String, u32, u32)>::from_arma(s)
87 .map(|(name, count, ammo)| Self::Magazine(name, count, ammo)),
88 _ => Err(FromArmaError::custom(format!(
89 "Invalid inventory item: {s}"
90 ))),
91 }
92 }
93}
94impl IntoArma for InventoryItem {
95 fn to_arma(&self) -> Value {
96 match self {
97 Self::Item(name, count) => Value::Array(vec![
98 Value::String(name.clone()),
99 Value::Number(f64::from(*count)),
100 ]),
101 Self::Magazine(name, count, ammo) => Value::Array(vec![
102 Value::String(name.clone()),
103 Value::Number(f64::from(*count)),
104 Value::Number(f64::from(*ammo)),
105 ]),
106 }
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use crate::{FromArma, IntoArma, Value};
113
114 use super::InventoryItem;
115
116 #[test]
117 fn is() {
118 let item = InventoryItem::new_item("test".to_owned(), 1);
119 assert_eq!(item.class(), "test");
120 assert_eq!(item.count(), 1);
121 assert_eq!(item.ammo(), None);
122 assert!(!item.is_magazine());
123 let item = InventoryItem::new_magazine("test".to_owned(), 1, 1);
124 assert_eq!(item.class(), "test");
125 assert_eq!(item.count(), 1);
126 assert_eq!(item.ammo(), Some(1));
127 assert!(item.is_magazine());
128 }
129
130 #[test]
131 fn class() {
132 let mut item = InventoryItem::new_item("test".to_owned(), 1);
133 assert_eq!(item.class(), "test");
134 item.set_class("test2".to_owned());
135 assert_eq!(item.class(), "test2");
136 }
137
138 #[test]
139 fn count() {
140 let mut item = InventoryItem::new_item("test".to_owned(), 1);
141 assert_eq!(item.count(), 1);
142 item.set_count(2);
143 assert_eq!(item.count(), 2);
144 }
145
146 #[test]
147 fn ammo() {
148 let item = InventoryItem::new_magazine("test".to_owned(), 1, 1);
149 assert_eq!(item.ammo(), Some(1));
150 assert!(item.is_magazine());
151 let item = InventoryItem::new_item("test".to_owned(), 1);
152 assert_eq!(item.ammo(), None);
153 assert!(!item.is_magazine());
154 }
155
156 #[test]
157 fn from_arma() {
158 let item = InventoryItem::from_arma("[\"test\",1]".to_owned()).unwrap();
159 assert_eq!(item.class(), "test");
160 assert_eq!(item.count(), 1);
161 assert_eq!(item.ammo(), None);
162 assert!(!item.is_magazine());
163 let item = InventoryItem::from_arma("[\"test\",1,1]".to_owned()).unwrap();
164 assert_eq!(item.class(), "test");
165 assert_eq!(item.count(), 1);
166 assert_eq!(item.ammo(), Some(1));
167 assert!(item.is_magazine());
168 }
169
170 #[test]
171 fn to_arma() {
172 let item = InventoryItem::new_item("test".to_owned(), 1);
173 assert_eq!(
174 item.to_arma(),
175 Value::Array(vec![Value::String("test".to_owned()), Value::Number(1.0),])
176 );
177 let item = InventoryItem::new_magazine("test".to_owned(), 1, 1);
178 assert_eq!(
179 item.to_arma(),
180 Value::Array(vec![
181 Value::String("test".to_owned()),
182 Value::Number(1.0),
183 Value::Number(1.0),
184 ])
185 );
186 }
187}