arma_rs/value/loadout/
container.rs

1use crate::{FromArma, FromArmaError, IntoArma, Value};
2
3use super::InventoryItem;
4
5#[derive(Debug, Default, Clone, PartialEq, Eq)]
6/// A uniform, vest, or backpack
7pub struct Container(Option<(String, Vec<InventoryItem>)>);
8impl Container {
9    /// Create a new container
10    #[must_use]
11    pub const fn new(class: String) -> Self {
12        Self(Some((class, vec![])))
13    }
14
15    /// The container exists
16    #[must_use]
17    pub const fn exists(&self) -> bool {
18        self.0.is_some()
19    }
20
21    /// The class name of the container
22    #[must_use]
23    pub fn class(&self) -> Option<&str> {
24        self.0.as_ref().map(|(class, _)| class.as_str())
25    }
26
27    /// Set the class name of the container
28    pub fn set_class(&mut self, class: String) {
29        if let Some(container) = self.0.as_mut() {
30            container.0 = class;
31        } else {
32            self.0 = Some((class, vec![]));
33        }
34    }
35
36    /// The items in the container
37    #[must_use]
38    pub fn items(&self) -> Option<&Vec<InventoryItem>> {
39        self.0.as_ref().map(|(_, items)| items)
40    }
41
42    /// The items in the container
43    pub fn items_mut(&mut self) -> Option<&mut Vec<InventoryItem>> {
44        self.0.as_mut().map(|(_, items)| items)
45    }
46
47    /// Get all classes and their quantities, including the container itself
48    #[must_use]
49    pub fn classes(&self) -> Vec<(String, u32)> {
50        let mut classes = vec![];
51        if let Some((class, items)) = &self.0 {
52            classes.push((class.clone(), 1));
53            for item in items {
54                classes.push((item.class().to_string(), item.count()));
55            }
56        }
57        classes
58    }
59}
60impl FromArma for Container {
61    fn from_arma(s: String) -> Result<Self, FromArmaError> {
62        if s == "[]" {
63            return Ok(Self(None));
64        }
65        <(String, Vec<InventoryItem>)>::from_arma(s).map(|(name, items)| Self(Some((name, items))))
66    }
67}
68impl IntoArma for Container {
69    fn to_arma(&self) -> Value {
70        self.0.as_ref().map_or_else(
71            || Value::Array(vec![]),
72            |container| {
73                Value::Array(vec![
74                    Value::String(container.0.clone()),
75                    Value::Array(container.1.iter().map(IntoArma::to_arma).collect()),
76                ])
77            },
78        )
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use crate::{loadout::InventoryItem, FromArma, IntoArma, Value};
85
86    use super::Container;
87
88    #[test]
89    fn exists() {
90        let container = Container::default();
91        assert!(!container.exists());
92        let container = Container::new("container".to_string());
93        assert!(container.exists());
94    }
95
96    #[test]
97    fn class() {
98        let container = Container::default();
99        assert!(container.class().is_none());
100        let mut container = Container::new("container".to_string());
101        assert_eq!(container.class().unwrap(), "container");
102        container.set_class("container2".to_string());
103        assert_eq!(container.class().unwrap(), "container2");
104    }
105
106    #[test]
107    fn items() {
108        let container = Container::default();
109        assert!(container.items().is_none());
110        let mut container = Container::new("container".to_string());
111        assert!(container.items().is_some());
112        let items = vec![
113            InventoryItem::new_item("item1".to_string(), 1),
114            InventoryItem::new_item("item2".to_string(), 2),
115        ];
116        container.0.as_mut().unwrap().1 = items.clone();
117        assert_eq!(container.items().unwrap(), &items);
118    }
119
120    #[test]
121    fn from_arma() {
122        let container = Container::from_arma("[]".to_string()).unwrap();
123        assert!(!container.exists());
124        let container =
125            Container::from_arma("[\"container\",[[\"item1\",1],[\"item2\",2]]]".to_string())
126                .unwrap();
127        assert!(container.exists());
128        assert_eq!(container.class().unwrap(), "container");
129        assert_eq!(
130            container.items().unwrap(),
131            &vec![
132                InventoryItem::new_item("item1".to_string(), 1),
133                InventoryItem::new_item("item2".to_string(), 2),
134            ]
135        );
136    }
137
138    #[test]
139    fn to_arma() {
140        let container = Container::default();
141        assert_eq!(container.to_arma(), Value::Array(vec![]));
142        let mut container = Container::new("container".to_string());
143        assert_eq!(
144            container.to_arma(),
145            Value::Array(vec![
146                Value::String("container".to_string()),
147                Value::Array(vec![]),
148            ])
149        );
150        let items = vec![
151            InventoryItem::new_item("item1".to_string(), 1),
152            InventoryItem::new_item("item2".to_string(), 2),
153        ];
154        container.0.as_mut().unwrap().1 = items;
155        assert_eq!(
156            container.to_arma(),
157            Value::Array(vec![
158                Value::String("container".to_string()),
159                Value::Array(vec![
160                    Value::Array(vec![Value::String("item1".to_string()), Value::Number(1.0),]),
161                    Value::Array(vec![Value::String("item2".to_string()), Value::Number(2.0),]),
162                ]),
163            ])
164        );
165    }
166
167    #[test]
168    fn classes() {
169        let container = Container::from_arma("[]".to_string()).unwrap();
170        assert!(!container.exists());
171        let container =
172            Container::from_arma("[\"container\",[[\"item1\",1],[\"item2\",2]]]".to_string())
173                .unwrap();
174        assert_eq!(
175            container.classes(),
176            vec![
177                ("container".to_string(), 1),
178                ("item1".to_string(), 1),
179                ("item2".to_string(), 2)
180            ]
181        );
182    }
183}