tf2_enum/
strange_part_set.rs

1//! Set for holding up to 3 strange parts.
2
3use crate::{
4    Attributes,
5    AttributeSet,
6    ItemAttribute,
7    StrangePart,
8    TryFromIntAttributeValue,
9};
10use crate::error::InsertError;
11use crate::serialize;
12use std::collections::HashSet;
13use std::fmt;
14use std::hash::{Hash, Hasher};
15use std::ops::{BitAnd, Sub};
16use serde::{Deserialize, Deserializer, Serialize, Serializer};
17use serde::de::{self, SeqAccess, Visitor};
18
19const STRANGE_PART_COUNT: usize = 3;
20
21/// Contains up to 3 strange parts. Although the underlying data structure is an array, this
22/// structure behaves like a set. Most methods mimic those of
23/// [`HashSet`](std::collections::HashSet), with a few differences.
24/// 
25/// This struct solves the following problems:
26/// - An item can only hold up to 3 strange parts.
27/// - An item cannot have duplicate strange parts.
28/// - Comparing strange parts for equality is order-agnostic.
29/// - Hashing is order-agnostic.
30/// - The type is `Copy`, allowing for cheap and easy duplication.
31/// 
32/// Most methods are implemented under the [`AttributeSet`] trait, make sure to import it to make
33/// use of them.
34/// 
35/// # Examples
36/// ```
37/// use tf2_enum::{StrangePartSet, StrangePart, AttributeSet};
38/// 
39/// // Create a set for strange parts with two strange parts.
40/// let mut strange_parts = StrangePartSet::double(
41///     StrangePart::CriticalKills,
42///     StrangePart::DamageDealt,
43/// );
44/// 
45/// // Check that strange parts contains Damage Dealt.
46/// assert!(strange_parts.contains(&StrangePart::DamageDealt));
47/// assert_eq!(strange_parts.len(), 2);
48/// 
49/// // Add a strange part.
50/// strange_parts.insert(StrangePart::EngineersKilled);
51/// 
52/// assert_eq!(strange_parts.len(), 3);
53/// 
54/// // If a strange part is added when strange parts are full, the insert will fail.
55/// assert!(!strange_parts.insert(StrangePart::MedicsKilled));
56/// assert!(!strange_parts.contains(&StrangePart::MedicsKilled));
57/// 
58/// // Iterate over strange parts.
59/// for strange_part in strange_parts {
60///     println!("{}", strange_part.strange_part_name());
61/// }
62/// ```
63#[derive(Default, Clone, Copy, Eq, PartialOrd, Ord)]
64pub struct StrangePartSet {
65    inner: [Option<StrangePart>; STRANGE_PART_COUNT],
66}
67
68impl StrangePartSet {
69    /// Creates a set for strange parts.
70    /// 
71    /// # Examples
72    /// ```
73    /// use tf2_enum::StrangePartSet;
74    /// 
75    /// let strange_parts = StrangePartSet::new();
76    /// ```
77    pub fn new() -> Self {
78        Self::default()
79    }
80    
81    /// Creates a set for strange parts with one strange part.
82    /// 
83    /// # Examples
84    /// ```
85    /// use tf2_enum::{StrangePartSet, StrangePart, AttributeSet};
86    /// 
87    /// let strange_parts = StrangePartSet::single(
88    ///     StrangePart::DamageDealt,
89    /// );
90    /// 
91    /// assert_eq!(strange_parts.len(), 1);
92    /// ```
93    pub fn single(strange_part: StrangePart) -> Self {
94        Self::from([
95            Some(strange_part),
96            None,
97            None,
98        ])
99    }
100    
101    /// Creates a set for strange parts with two strange parts.
102    /// 
103    /// If the same strange part is added multiple times, only one will be kept.
104    /// 
105    /// # Examples
106    /// ```
107    /// use tf2_enum::{StrangePartSet, StrangePart, AttributeSet};
108    /// 
109    /// let strange_parts = StrangePartSet::double(
110    ///     StrangePart::DamageDealt,
111    ///     StrangePart::CriticalKills,
112    /// );
113    /// 
114    /// assert_eq!(strange_parts.len(), 2);
115    /// ```
116    pub fn double(
117        strange_part1: StrangePart,
118        strange_part2: StrangePart,
119    ) -> Self {
120        Self::from([
121            Some(strange_part1),
122            Some(strange_part2),
123            None,
124        ])
125    }
126    
127    /// Creates a set for strange parts with two strange parts.
128    /// 
129    /// If the same strange part is added multiple times, only one will be kept.
130    /// 
131    /// # Examples
132    /// ```
133    /// use tf2_enum::{StrangePartSet, StrangePart, AttributeSet};
134    /// 
135    /// let strange_parts = StrangePartSet::triple(
136    ///     StrangePart::DamageDealt,
137    ///     StrangePart::CriticalKills,
138    ///     StrangePart::EngineersKilled,
139    /// );
140    /// 
141    /// assert_eq!(strange_parts.len(), 3);
142    /// ```
143    pub fn triple(
144        strange_part1: StrangePart,
145        strange_part2: StrangePart,
146        strange_part3: StrangePart,
147    ) -> Self {
148        Self::from([
149            Some(strange_part1),
150            Some(strange_part2),
151            Some(strange_part3),
152        ])
153    }
154}
155
156impl AttributeSet for StrangePartSet {
157    /// Max number of items.
158    const MAX_COUNT: usize = STRANGE_PART_COUNT;
159    /// An empty [`StrangePartSet`].
160    const NONE: Self = Self {
161        inner: [None, None, None],
162    };
163    /// The item type.
164    type Item = StrangePart;
165    
166    /// Clears the set, removing all strange parts.
167    /// 
168    /// # Examples
169    /// ```
170    /// use tf2_enum::{StrangePartSet, StrangePart, AttributeSet};
171    /// 
172    /// let mut strange_parts = StrangePartSet::double(
173    ///     StrangePart::CriticalKills,
174    ///     StrangePart::DamageDealt,
175    /// );
176    /// 
177    /// strange_parts.clear();
178    /// 
179    /// assert_eq!(strange_parts.len(), 0);
180    /// ```
181    fn clear(&mut self) {
182        self.inner = [None, None, None];
183    }
184    
185    /// Adds a strange part to the first available slot. If no slots are available, the new strange 
186    /// part will be ignored.
187    /// 
188    /// Returns `false` if:
189    /// - The strange part is already in the set.
190    /// - The set is full.
191    /// 
192    /// # Examples
193    /// ```
194    /// use tf2_enum::{StrangePartSet, StrangePart, AttributeSet};
195    /// 
196    /// let mut strange_parts = StrangePartSet::double(
197    ///     StrangePart::CriticalKills,
198    ///     StrangePart::DamageDealt,
199    /// );
200    /// 
201    /// assert_eq!(strange_parts.len(), 2);
202    /// 
203    /// strange_parts.insert(StrangePart::EngineersKilled);
204    /// 
205    /// assert_eq!(strange_parts.len(), 3);
206    /// 
207    /// // Strange parts are full.
208    /// assert!(!strange_parts.insert(StrangePart::MedicsKilled));
209    /// ```
210    fn insert(&mut self, strange_part: StrangePart) -> bool {
211        self.try_insert(strange_part).is_ok()
212    }
213    
214    fn try_insert(&mut self, strange_part: StrangePart) -> Result<(), InsertError> {
215        if self.contains(&strange_part) {
216            return Err(InsertError::Duplicate);
217        }
218        
219        if let Some(slot) = self.inner.iter_mut().find(|slot| slot.is_none()) {
220            *slot = Some(strange_part);
221            return Ok(());
222        }
223        
224        // full set, insertion failed
225        Err(InsertError::Full)
226    }
227    
228    fn insert_or_replace_last(&mut self, strange_part: StrangePart) -> bool {
229        if self.contains(&strange_part) {
230            return false;
231        }
232        
233        if let Some(slot) = self.inner.iter_mut().find(|slot| slot.is_none()) {
234            *slot = Some(strange_part);
235            return true;
236        }
237        
238        // replace the last item
239        self.inner[Self::MAX_COUNT - 1] = Some(strange_part);
240        true
241    }
242    
243    /// Removes a strange part.
244    /// 
245    /// # Examples
246    /// ```
247    /// use tf2_enum::{StrangePartSet, StrangePart, AttributeSet};
248    /// 
249    /// let mut strange_parts = StrangePartSet::single(StrangePart::CriticalKills);
250    /// 
251    /// assert!(strange_parts.remove(&StrangePart::CriticalKills));
252    /// assert!(!strange_parts.contains(&StrangePart::CriticalKills));
253    /// ```
254    fn remove(&mut self, strange_part: &StrangePart) -> bool {
255        for s in self.inner.iter_mut() {
256            if *s == Some(*strange_part) {
257                *s = None;
258                return true;
259            }
260        }
261        
262        false
263    }
264    
265    /// Removes and returns the strange part in the set, if any, that is equal to the given one.
266    fn take(&mut self, strange_part: &StrangePart) -> Option<StrangePart> {
267        for s in self.inner.iter_mut() {
268            if *s == Some(*strange_part) {
269                *s = None;
270                return Some(*strange_part);
271            }
272        }
273        
274        None
275    }
276    
277    /// Replaces a strange part in the set with a new strange part. `false` if the strange part was
278    /// not present.
279    fn replace(&mut self, strange_part: &StrangePart, new_strange_part: StrangePart) -> bool {
280        if !self.contains(strange_part) {
281            return false;
282        }
283        
284        for s in self.inner.iter_mut() {
285            if *s == Some(*strange_part) {
286                *s = Some(new_strange_part);
287                return true;
288            }
289        }
290        
291        false
292    }
293    
294    /// Converts each element to an [`ItemAttribute`]. This doesn't include attributes for the
295    /// score counters, only the score types.
296    fn iter_attributes(&self) -> impl Iterator<Item = ItemAttribute> {
297        self
298            .into_iter()
299            .zip(StrangePart::DEFINDEX.iter())
300            .map(|(part, defindex)| ItemAttribute {
301                defindex: *defindex,
302                value: part.attribute_value(),
303                float_value: part.attribute_float_value(),
304            })
305    }
306    
307    /// Returns the inner storage as a slice.
308    fn as_slice(&self) -> &[Option<StrangePart>] {
309        &self.inner
310    }
311    
312    /// Returns the inner storage as a mutable slice.
313    fn as_mut_slice(&mut self) -> &mut [Option<StrangePart>] {
314        &mut self.inner
315    }
316}
317
318// Only Sub is implemented because Add wouldn't make much sense with strange parts being limited 
319// to 3.
320impl Sub for StrangePartSet {
321    type Output = Self;
322    
323    fn sub(self, other: Self) -> Self::Output {
324        self.difference(&other)
325    }
326}
327
328impl Sub for &StrangePartSet {
329    type Output = StrangePartSet;
330    
331    fn sub(self, other: &StrangePartSet) -> Self::Output {
332        self.difference(other)
333    }
334}
335
336impl BitAnd for StrangePartSet {
337    type Output = Self;
338    
339    fn bitand(self, other: Self) -> Self::Output {
340        self.intersection(&other)
341    }
342}
343
344impl BitAnd for &StrangePartSet {
345    type Output = StrangePartSet;
346    
347    fn bitand(self, other: &StrangePartSet) -> Self::Output {
348        self.intersection(other)
349    }
350}
351
352impl PartialEq<Self> for StrangePartSet {
353    fn eq(&self, other: &Self) -> bool {
354        let mut a = self.inner;
355        let mut b = other.inner;
356        
357        a.sort_unstable();
358        b.sort_unstable();
359        
360        a == b
361    }
362}
363
364impl Hash for StrangePartSet {
365    fn hash<H: Hasher>(&self, state: &mut H) {
366        let mut values = self.inner;
367        
368        values.sort_unstable();
369        
370        for value in values {
371            value.hash(state);
372        }
373    }
374}
375
376impl From<[Option<StrangePart>; STRANGE_PART_COUNT]> for StrangePartSet {
377    fn from(inner: [Option<StrangePart>; STRANGE_PART_COUNT]) -> Self {
378        let mut inner = inner;
379        
380        // remove duplicates
381        for i in 0..STRANGE_PART_COUNT {
382            if let Some(val_i) = inner[i] {
383                // check elements after i for duplicates
384                for j in (i + 1)..STRANGE_PART_COUNT {
385                    if inner[j] == Some(val_i) {
386                        // later occurrence exists, remove current
387                        inner[i] = None;
388                        break;
389                    }
390                }
391            }
392        }
393        
394        Self {
395            inner,
396        }
397    }
398}
399
400impl From<StrangePartSet> for Vec<StrangePart>{
401    fn from(spell_set: StrangePartSet) -> Self {
402        spell_set.into_iter().collect()
403    }
404}
405
406impl From<&StrangePartSet> for Vec<StrangePart> {
407    fn from(spell_set: &StrangePartSet) -> Self {
408        (*spell_set).into()
409    }
410}
411
412impl FromIterator<StrangePart> for StrangePartSet {
413    fn from_iter<I: IntoIterator<Item = StrangePart>>(iter: I) -> Self {
414        let mut strange_parts = Self::new();
415        
416        for strange_part in iter {
417            strange_parts.insert(strange_part);
418        }
419        
420        strange_parts
421    }
422}
423
424impl<'a> FromIterator<&'a StrangePart> for StrangePartSet {
425    fn from_iter<I: IntoIterator<Item = &'a StrangePart>>(iter: I) -> Self {
426        let mut strange_part_set = Self::new();
427        
428        for strange_part in iter {
429            strange_part_set.insert(*strange_part);
430        }
431        
432        strange_part_set
433    }
434}
435
436impl FromIterator<Option<StrangePart>> for StrangePartSet {
437    fn from_iter<I: IntoIterator<Item = Option<StrangePart>>>(iter: I) -> Self {
438        let mut set = Self::new();
439        
440        for val in iter.into_iter().flatten() {
441            set.insert(val);
442        }
443        
444        set
445    }
446}
447
448impl<'a> FromIterator<Option<&'a StrangePart>> for StrangePartSet {
449    fn from_iter<I: IntoIterator<Item = Option<&'a StrangePart>>>(iter: I) -> Self {
450        let mut set = Self::new();
451        
452        for val in iter.into_iter().flatten() {
453            set.insert(*val);
454        }
455        
456        set
457    }
458}
459
460impl IntoIterator for StrangePartSet {
461    type Item = StrangePart;
462    type IntoIter = StrangePartSetIterator;
463    
464    fn into_iter(self) -> Self::IntoIter {
465        StrangePartSetIterator {
466            inner: self.inner.into_iter(),
467        }
468    }
469}
470
471impl IntoIterator for &StrangePartSet {
472    type Item = StrangePart;
473    type IntoIter = StrangePartSetIterator;
474    
475    fn into_iter(self) -> Self::IntoIter {
476        (*self).into_iter()
477    }
478}
479
480/// Iterator for strange parts.
481#[derive(Debug, Clone)]
482pub struct StrangePartSetIterator {
483    inner: std::array::IntoIter<Option<StrangePart>, STRANGE_PART_COUNT>,
484}
485
486impl Iterator for StrangePartSetIterator {
487    type Item = StrangePart;
488
489    fn next(&mut self) -> Option<Self::Item> {
490        let iter = self.inner.by_ref();
491        
492        for opt in iter {
493            if opt.is_some() {
494                return opt;
495            }
496        }
497        
498        None
499    }
500}
501
502impl fmt::Display for StrangePartSet {
503    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
504        let mut iter = self.into_iter();
505        
506        if let Some(first) = iter.next() {
507            write!(f, "{first}")?;
508            
509            for s in iter {
510                write!(f, ", {s}")?;
511            }
512        }
513        
514        Ok(())
515    }
516}
517
518impl fmt::Debug for StrangePartSet {
519    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
520        f.write_str("{")?;
521        let mut first = true;
522        for part in self {
523            if !first {
524                f.write_str(", ")?;
525            }
526            write!(f, "{:?}", part as u32)?;
527            first = false;
528        }
529        f.write_str("}")
530    }
531}
532
533impl Serialize for StrangePartSet {
534    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
535    where
536        S: Serializer,
537    {
538        serialize::serialize_attribute_set(self, serializer)
539    }
540}
541
542impl<'de> Deserialize<'de> for StrangePartSet {
543    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
544    where
545        D: Deserializer<'de>,
546    {
547        struct StrangePartSetVisitor;
548        
549        impl<'de> Visitor<'de> for StrangePartSetVisitor {
550            type Value = StrangePartSet;
551
552            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
553                formatter.write_str("an array of maps with defindex, float_value")
554            }
555            
556            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
557            where
558                A: SeqAccess<'de>,
559            {
560                let mut set = Self::Value::new();
561                let mut defindex_map = HashSet::new();
562                
563                while let Some(map) = seq.next_element::<ItemAttribute>()? {
564                    if !<Self::Value as AttributeSet>::Item::DEFINDEX.contains(&map.defindex) {
565                        // Skip if defindex is not for a score type
566                        continue;
567                    }
568                    
569                    if defindex_map.contains(&map.defindex) {
570                        // Skip if defindex is already in the set
571                        continue;
572                    }
573                    
574                    defindex_map.insert(map.defindex);
575                    
576                    let float_value = map.float_value
577                        .ok_or_else(|| de::Error::missing_field(
578                            "float_value"
579                        ))?;
580                    let part = <Self::Value as AttributeSet>::Item::try_from_attribute_float_value(
581                            float_value
582                        )
583                        .ok_or_else(|| de::Error::custom(
584                            "cannot convert from float_value"
585                        ))?;
586                    
587                    set.insert(part);
588                }
589                
590                Ok(set)
591            }
592        }
593        
594        deserializer.deserialize_seq(StrangePartSetVisitor)
595    }
596}
597
598#[cfg(test)]
599mod tests {
600    use super::*;
601    use crate::traits::Attributes;
602    
603    #[test]
604    fn serializes() {
605        let strange_parts = StrangePartSet::from([
606            Some(StrangePart::TauntKills),
607            None,
608            None,
609        ]);
610        let json = serde_json::to_string(&strange_parts).unwrap();
611        let expected = r#"[{"defindex":380,"value":1117388800,"float_value":77}]"#;
612        
613        assert_eq!(json, expected);
614    }
615    
616    #[test]
617    fn deserializes() {
618        // It doesn't need the "value" field to deserialize.
619        let raw = r#"[{"defindex":380,"float_value":77},{"defindex":382,"float_value":34},{"defindex":384,"float_value":33}]"#;
620        let strange_parts: StrangePartSet = serde_json::from_str(raw).unwrap();
621        let expected = StrangePartSet::from([
622            Some(StrangePart::TauntKills),
623            Some(StrangePart::KillsWhileExplosiveJumping),
624            Some(StrangePart::CriticalKills),
625        ]);
626        
627        assert_eq!(strange_parts, expected);
628    }
629    
630    #[test]
631    fn deserializes_backpack() {
632        // These are attributes from a Strange Flame Thrower with 3 parts.
633        // The deserializer extracts these while ignoring all other attributes.
634        let raw = r#"[
635            {
636                "defindex": 189,
637                "value": 1093664768,
638                "float_value": 11
639            },
640            {
641                "defindex": 214,
642                "value": 1847,
643                "float_value": 2.58819826360793713e-42
644            },
645            {
646                "defindex": 379,
647                "value": 1085,
648                "float_value": 1.52040883379242652e-42
649            },
650            {
651                "defindex": 380,
652                "value": 1101004800,
653                "float_value": 20
654            },
655            {
656                "defindex": 381,
657                "value": 91,
658                "float_value": 1.27518160253558353e-43
659            },
660            {
661                "defindex": 382,
662                "value": 1106771968,
663                "float_value": 31
664            },
665            {
666                "defindex": 383,
667                "value": 457,
668                "float_value": 6.40393398196441401e-43
669            },
670            {
671                "defindex": 384,
672                "value": 1107296256,
673                "float_value": 32
674            },
675            {
676                "defindex": 719,
677                "value": "models/weapons/c_models/stattrack.mdl"
678            },
679            {
680                "defindex": 731,
681                "value": 1065353216,
682                "float_value": 1
683            },
684            {
685                "defindex": 841,
686                "value": 0,
687                "float_value": 0
688            },
689            {
690                "defindex": 843,
691                "value": 1091043328,
692                "float_value": 8.5
693            },
694            {
695                "defindex": 865,
696                "value": 1112014848,
697                "float_value": 50
698            },
699            {
700                "defindex": 844,
701                "value": 1159274496,
702                "float_value": 2450
703            },
704            {
705                "defindex": 839,
706                "value": 1077097267,
707                "float_value": 2.79999995231628418
708            },
709            {
710                "defindex": 862,
711                "value": 1058642330,
712                "float_value": 0.60000002384185791
713            },
714            {
715                "defindex": 863,
716                "value": 1036831949,
717                "float_value": 0.100000001490116119
718            },
719            {
720                "defindex": 783,
721                "value": 1101004800,
722                "float_value": 20
723            },
724            {
725                "defindex": 724,
726                "value": 1065353216,
727                "float_value": 1
728            },
729            {
730                "defindex": 796,
731                "value": "10 0 -10"
732            }
733        ]"#;
734        let strange_parts = serde_json::from_str::<StrangePartSet>(raw).unwrap();
735        
736        assert_eq!(
737            strange_parts.to_string(),
738            "Projectiles Reflected, Posthumous Kills, Teammates Extinguished"
739        );
740    }
741    
742    #[test]
743    fn iterates_strange_parts() {
744        let strange_parts = StrangePartSet::from([
745            Some(StrangePart::TauntKills),
746            Some(StrangePart::KillsWhileExplosiveJumping),
747            Some(StrangePart::CriticalKills),
748        ]);
749        let mut iter = strange_parts.into_iter();
750        
751        assert_eq!(iter.next(), Some(StrangePart::TauntKills));
752        assert_eq!(iter.next(), Some(StrangePart::KillsWhileExplosiveJumping));
753        assert_eq!(iter.next(), Some(StrangePart::CriticalKills));
754        assert_eq!(iter.next(), None);
755        
756        let mut count = 0;
757        
758        for _strange_part in &strange_parts {
759            count += 1;
760        }
761        
762        assert_eq!(count, 3);
763    }
764    
765    #[test]
766    fn mutates_strange_parts() {
767        let mut strange_parts = StrangePartSet::from([
768            Some(StrangePart::TauntKills),
769            Some(StrangePart::KillsWhileExplosiveJumping),
770            Some(StrangePart::CriticalKills),
771        ]);
772        
773        assert_eq!(strange_parts.len(), 3);
774        assert!(strange_parts.contains(&StrangePart::CriticalKills));
775        
776        strange_parts.remove(&StrangePart::CriticalKills);
777        
778        assert!(!strange_parts.contains(&StrangePart::CriticalKills));
779        assert_eq!(strange_parts.len(), 2);
780        
781        strange_parts.insert(StrangePart::DamageDealt);
782        
783        assert!(strange_parts.contains(&StrangePart::DamageDealt));
784        assert_eq!(strange_parts.len(), 3);
785    }
786    
787    #[test]
788    fn strange_parts_no_duplicates() {
789        assert_eq!(StrangePartSet::from([
790            Some(StrangePart::CriticalKills),
791            Some(StrangePart::CriticalKills),
792            Some(StrangePart::CriticalKills),
793        ]), StrangePartSet::from([
794            Some(StrangePart::CriticalKills),
795            None,
796            None,
797        ]));
798    }
799    
800    #[test]
801    fn is_empty() {
802        assert!(StrangePartSet::from([
803            None,
804            None,
805            None,
806        ]).is_empty());
807    }
808    
809    #[test]
810    fn iter_zip() {
811        let strange_parts = StrangePartSet::from([
812            Some(StrangePart::TauntKills),
813            Some(StrangePart::KillsWhileExplosiveJumping),
814            Some(StrangePart::CriticalKills),
815        ]);
816        let with_attribute_defindex = strange_parts.into_iter()
817            .zip(StrangePart::DEFINDEX.to_owned())
818            .collect::<Vec<_>>();
819        
820        assert_eq!(with_attribute_defindex, vec![
821            (StrangePart::TauntKills, 380),
822            (StrangePart::KillsWhileExplosiveJumping, 382),
823            (StrangePart::CriticalKills, 384),
824        ]);
825    }
826    
827    #[test]
828    fn gets_first_and_last() {
829        let strange_parts = StrangePartSet::from([
830            Some(StrangePart::TauntKills),
831            Some(StrangePart::KillsWhileExplosiveJumping),
832            Some(StrangePart::CriticalKills),
833        ]);
834
835        assert_eq!(strange_parts.first(), Some(&StrangePart::TauntKills));
836        assert_eq!(strange_parts.last(), Some(&StrangePart::CriticalKills));
837    }
838    
839    #[test]
840    fn stringify() {
841        let strange_parts = StrangePartSet::from([
842            Some(StrangePart::TauntKills),
843            Some(StrangePart::KillsWhileExplosiveJumping),
844            Some(StrangePart::CriticalKills),
845        ]);
846        
847        assert_eq!(strange_parts.to_string(), "Taunt Kills, Kills While Explosive-Jumping, Critical Kills");
848    }
849    
850    #[test]
851    fn retains() {
852        let mut strange_parts = StrangePartSet::from([
853            Some(StrangePart::TauntKills),
854            Some(StrangePart::KillsWhileExplosiveJumping),
855            Some(StrangePart::Assists),
856        ]);
857        
858        strange_parts.retain(|part| part.is_cosmetic_part());
859        
860        assert_eq!(strange_parts.first(), Some(&StrangePart::Assists));
861    }
862    
863    #[test]
864    fn bit_and() {
865        let set1 = StrangePartSet::from([
866            Some(StrangePart::TauntKills),
867            Some(StrangePart::KillsWhileExplosiveJumping),
868            Some(StrangePart::CriticalKills),
869        ]);
870        let set2 = StrangePartSet::from([
871            Some(StrangePart::TauntKills),
872            Some(StrangePart::DamageDealt),
873            None,
874        ]);
875        let intersection = set1 & set2;
876        assert_eq!(intersection, StrangePartSet::from([
877            Some(StrangePart::TauntKills),
878            None,
879            None,
880        ]));
881    }
882    
883    #[test]
884    fn iterate_borrowed() {
885        let strange_parts = StrangePartSet::from([
886            Some(StrangePart::TauntKills),
887            Some(StrangePart::KillsWhileExplosiveJumping),
888            Some(StrangePart::CriticalKills),
889        ]);
890        
891        for strange_part in &strange_parts {
892            assert!(strange_parts.contains(&strange_part));
893        }
894    }
895}