1use crate::{FromArma, FromArmaError, IntoArma, Value};
2
3use super::Magazine;
4
5#[derive(Debug, Default, Clone, PartialEq, Eq)]
6pub struct Weapon(Option<(String, String, String, String, Magazine, Magazine, String)>);
8impl Weapon {
9 #[must_use]
11 pub fn new(class: String) -> Self {
12 Self(Some((
13 class,
14 "".to_string(),
15 "".to_string(),
16 "".to_string(),
17 Magazine::default(),
18 Magazine::default(),
19 "".to_string(),
20 )))
21 }
22
23 #[must_use]
25 pub const fn exists(&self) -> bool {
26 self.0.is_some()
27 }
28
29 #[must_use]
31 pub fn class(&self) -> Option<&str> {
32 self.0
33 .as_ref()
34 .map(|(class, _, _, _, _, _, _)| class.as_str())
35 }
36
37 pub fn set_class(&mut self, class: String) {
39 if let Some(weapon) = self.0.as_mut() {
40 weapon.0 = class;
41 } else {
42 self.0 = Some((
43 class,
44 "".to_owned(),
45 "".to_owned(),
46 "".to_owned(),
47 Magazine::default(),
48 Magazine::default(),
49 "".to_owned(),
50 ));
51 }
52 }
53
54 #[must_use]
56 pub fn suppressor(&self) -> Option<&str> {
57 self.0
58 .as_ref()
59 .map(|(_, suppressor, _, _, _, _, _)| suppressor.as_str())
60 }
61
62 pub fn set_suppressor(&mut self, suppressor: String) -> bool {
65 if let Some(weapon) = self.0.as_mut() {
66 weapon.1 = suppressor;
67 true
68 } else {
69 false
70 }
71 }
72
73 #[must_use]
75 pub fn pointer(&self) -> Option<&str> {
76 self.0
77 .as_ref()
78 .map(|(_, _, pointer, _, _, _, _)| pointer.as_str())
79 }
80
81 pub fn set_pointer(&mut self, pointer: String) -> bool {
84 if let Some(weapon) = self.0.as_mut() {
85 weapon.2 = pointer;
86 true
87 } else {
88 false
89 }
90 }
91
92 #[must_use]
94 pub fn optic(&self) -> Option<&str> {
95 self.0
96 .as_ref()
97 .map(|(_, _, _, optic, _, _, _)| optic.as_str())
98 }
99
100 pub fn set_optic(&mut self, optic: String) -> bool {
103 if let Some(weapon) = self.0.as_mut() {
104 weapon.3 = optic;
105 true
106 } else {
107 false
108 }
109 }
110
111 #[must_use]
113 pub fn primary_magazine(&self) -> Option<&Magazine> {
114 self.0.as_ref().map(|(_, _, _, _, primary, _, _)| primary)
115 }
116
117 pub fn primary_magazine_mut(&mut self) -> Option<&mut Magazine> {
119 self.0.as_mut().map(|(_, _, _, _, primary, _, _)| primary)
120 }
121
122 pub fn set_primary_magazine(&mut self, primary: Magazine) -> bool {
125 if let Some(weapon) = self.0.as_mut() {
126 weapon.4 = primary;
127 true
128 } else {
129 false
130 }
131 }
132
133 #[must_use]
135 pub fn secondary_magazine(&self) -> Option<&Magazine> {
136 self.0
137 .as_ref()
138 .map(|(_, _, _, _, _, secondary, _)| secondary)
139 }
140
141 pub fn secondary_magazine_mut(&mut self) -> Option<&mut Magazine> {
143 self.0
144 .as_mut()
145 .map(|(_, _, _, _, _, secondary, _)| secondary)
146 }
147
148 pub fn set_secondary_magazine(&mut self, secondary: Magazine) -> bool {
151 if let Some(weapon) = self.0.as_mut() {
152 weapon.5 = secondary;
153 true
154 } else {
155 false
156 }
157 }
158
159 #[must_use]
161 pub fn bipod(&self) -> Option<&str> {
162 self.0
163 .as_ref()
164 .map(|(_, _, _, _, _, _, bipod)| bipod.as_str())
165 }
166
167 pub fn set_bipod(&mut self, bipod: String) -> bool {
170 if let Some(weapon) = self.0.as_mut() {
171 weapon.6 = bipod;
172 true
173 } else {
174 false
175 }
176 }
177
178 pub fn classes(&self) -> Vec<&str> {
180 let mut classes = Vec::new();
181 if let Some(weapon) = self.0.as_ref() {
182 classes.push(weapon.0.as_str());
183 if !weapon.1.is_empty() {
184 classes.push(weapon.1.as_str());
185 }
186 if !weapon.2.is_empty() {
187 classes.push(weapon.2.as_str());
188 }
189 if !weapon.3.is_empty() {
190 classes.push(weapon.3.as_str());
191 }
192 if let Some(class) = weapon.4.class() {
193 classes.push(class);
194 }
195 if let Some(class) = weapon.5.class() {
196 classes.push(class);
197 }
198 if !weapon.6.is_empty() {
199 classes.push(weapon.6.as_str());
200 }
201 }
202 classes
203 }
204}
205impl FromArma for Weapon {
206 fn from_arma(s: String) -> Result<Self, FromArmaError> {
207 if s == "[]" {
208 return Ok(Self(None));
209 }
210 <(String, String, String, String, Magazine, Magazine, String)>::from_arma(s).map(
211 |(weapon, suppressor, pointer, optic, primary_mag, secondary_mag, bipod)| {
212 Self(Some((
213 weapon,
214 suppressor,
215 pointer,
216 optic,
217 primary_mag,
218 secondary_mag,
219 bipod,
220 )))
221 },
222 )
223 }
224}
225impl IntoArma for Weapon {
226 fn to_arma(&self) -> Value {
227 self.0.as_ref().map_or_else(
228 || Value::Array(vec![]),
229 |weaon| {
230 Value::Array(vec![
231 Value::String(weaon.0.clone()),
232 Value::String(weaon.1.clone()),
233 Value::String(weaon.2.clone()),
234 Value::String(weaon.3.clone()),
235 weaon.4.to_arma(),
236 weaon.5.to_arma(),
237 Value::String(weaon.6.clone()),
238 ])
239 },
240 )
241 }
242}
243
244#[cfg(test)]
245mod tests {
246 use super::Weapon;
247 use crate::{loadout::Magazine, FromArma, IntoArma, Value};
248
249 #[test]
250 fn exists() {
251 let weapon = Weapon::default();
252 assert!(!weapon.exists());
253 let weapon = Weapon::new("arifle_Mk20_GL_F".to_owned());
254 assert!(weapon.exists());
255 }
256
257 #[test]
258 fn class() {
259 let weapon = Weapon::default();
260 assert_eq!(weapon.class(), None);
261 let mut weapon = Weapon::new("arifle_Mk20_GL_F".to_owned());
262 assert_eq!(weapon.class(), Some("arifle_Mk20_GL_F"));
263 weapon.set_class("arifle_Mk20_F".to_owned());
264 assert_eq!(weapon.class(), Some("arifle_Mk20_F"));
265 }
266
267 #[test]
268 fn suppressor() {
269 let weapon = Weapon::default();
270 assert_eq!(weapon.suppressor(), None);
271 let mut weapon = Weapon::new("arifle_Mk20_GL_F".to_owned());
272 assert_eq!(weapon.suppressor(), Some(""));
273 weapon.set_suppressor("muzzle_snds_H".to_owned());
274 assert_eq!(weapon.suppressor(), Some("muzzle_snds_H"));
275 }
276
277 #[test]
278 fn pointer() {
279 let weapon = Weapon::default();
280 assert_eq!(weapon.pointer(), None);
281 let mut weapon = Weapon::new("arifle_Mk20_GL_F".to_owned());
282 assert_eq!(weapon.pointer(), Some(""));
283 weapon.set_pointer("acc_pointer_IR".to_owned());
284 assert_eq!(weapon.pointer(), Some("acc_pointer_IR"));
285 }
286
287 #[test]
288 fn optic() {
289 let weapon = Weapon::default();
290 assert_eq!(weapon.optic(), None);
291 let mut weapon = Weapon::new("arifle_Mk20_GL_F".to_owned());
292 assert_eq!(weapon.optic(), Some(""));
293 weapon.set_optic("optic_Hamr".to_owned());
294 assert_eq!(weapon.optic(), Some("optic_Hamr"));
295 }
296
297 #[test]
298 fn primary_magazine() {
299 let weapon = Weapon::default();
300 assert_eq!(weapon.primary_magazine(), None);
301 let mut weapon = Weapon::new("arifle_Mk20_GL_F".to_owned());
302 assert_eq!(weapon.primary_magazine(), Some(&Magazine::default()));
303 weapon.set_primary_magazine(Magazine::new("30Rnd_556x45_Stanag".to_string(), 30));
304 assert_eq!(
305 weapon.primary_magazine(),
306 Some(&Magazine::new("30Rnd_556x45_Stanag".to_string(), 30))
307 );
308 }
309
310 #[test]
311 fn secondary_magazine() {
312 let weapon = Weapon::default();
313 assert_eq!(weapon.secondary_magazine(), None);
314 let mut weapon = Weapon::new("arifle_Mk20_GL_F".to_owned());
315 assert_eq!(weapon.secondary_magazine(), Some(&Magazine::default()));
316 weapon.set_secondary_magazine(Magazine::new("1Rnd_HE_Grenade_shell".to_string(), 1));
317 assert_eq!(
318 weapon.secondary_magazine(),
319 Some(&Magazine::new("1Rnd_HE_Grenade_shell".to_string(), 1))
320 );
321 }
322
323 #[test]
324 fn bipod() {
325 let weapon = Weapon::default();
326 assert_eq!(weapon.bipod(), None);
327 let mut weapon = Weapon::new("arifle_Mk20_GL_F".to_owned());
328 assert_eq!(weapon.bipod(), Some(""));
329 weapon.set_bipod("bipod_01_F".to_owned());
330 assert_eq!(weapon.bipod(), Some("bipod_01_F"));
331 }
332
333 #[test]
334 fn from_arma() {
335 let weapon = Weapon::from_arma("[]".to_owned()).unwrap();
336 assert_eq!(weapon, Weapon::default());
337 let weapon = Weapon::from_arma(
338 "[\"arifle_Mk20_GL_F\",\"\",\"\",\"\",[\"30Rnd_556x45_Stanag\",30],[\"1Rnd_HE_Grenade_shell\",1],\"\"]".to_owned(),
339 )
340 .unwrap();
341 assert_eq!(weapon, {
342 let mut weapon = Weapon::new("arifle_Mk20_GL_F".to_owned());
343 weapon.set_primary_magazine(Magazine::new("30Rnd_556x45_Stanag".to_string(), 30));
344 weapon.set_secondary_magazine(Magazine::new("1Rnd_HE_Grenade_shell".to_string(), 1));
345 weapon
346 });
347 }
348
349 #[test]
350 fn to_arma() {
351 let weapon = Weapon::default();
352 assert_eq!(weapon.to_arma(), Value::Array(vec![]));
353 let weapon = Weapon::new("arifle_Mk20_GL_F".to_owned());
354 assert_eq!(
355 weapon.to_arma(),
356 Value::Array(vec![
357 Value::String("arifle_Mk20_GL_F".to_owned()),
358 Value::String("".to_owned()),
359 Value::String("".to_owned()),
360 Value::String("".to_owned()),
361 Value::Array(vec![]),
362 Value::Array(vec![]),
363 Value::String("".to_owned()),
364 ])
365 );
366 }
367
368 #[test]
369 fn classes() {
370 let weapon = Weapon::from_arma("[]".to_owned()).unwrap();
371 assert_eq!(weapon, Weapon::default());
372 let weapon = Weapon::from_arma(
373 "[\"arifle_Mk20_GL_F\",\"fake_optic\",\"\",\"\",[\"30Rnd_556x45_Stanag\",30],[\"1Rnd_HE_Grenade_shell\",1],\"fake_bipod\"]".to_owned(),
374 )
375 .unwrap();
376 assert_eq!(
377 weapon.classes(),
378 vec![
379 "arifle_Mk20_GL_F",
380 "fake_optic",
381 "30Rnd_556x45_Stanag",
382 "1Rnd_HE_Grenade_shell",
383 "fake_bipod"
384 ]
385 );
386 }
387}