maybe_multiple/
maybe_multiple.rs

1// Copyright 2024 bmc::labs GmbH. All rights reserved.
2
3use crate::Multiple;
4
5#[derive(Debug, PartialEq, Eq)]
6#[cfg_attr(
7    feature = "serde",
8    derive(serde::Serialize, serde::Deserialize),
9    serde(untagged)
10)]
11pub enum MaybeMultiple<T> {
12    None,
13    Some(T),
14    Multiple(Multiple<T>),
15}
16
17////////////////////////////////////////////////////////////////////////////////
18// Type implementations
19////////////////////////////////////////////////////////////////////////////////
20
21impl<T> MaybeMultiple<T> {
22    #[must_use = "to assert that this doesn't have a value, wrap this in an `assert!()` instead"]
23    #[inline]
24    pub fn is_none(&self) -> bool {
25        matches!(self, Self::None)
26    }
27
28    #[must_use = "to assert that this has a value, wrap this in an `assert!()` instead"]
29    #[inline]
30    pub fn is_some(&self) -> bool {
31        matches!(self, Self::Some(_))
32    }
33
34    #[must_use = "to assert that this has a value, wrap this in an `assert!()` instead"]
35    #[inline]
36    pub fn is_multiple(&self) -> bool {
37        matches!(self, Self::Multiple(_))
38    }
39
40    #[inline]
41    pub fn from_vec(v: Vec<T>) -> Self {
42        Self::from(v)
43    }
44}
45
46////////////////////////////////////////////////////////////////////////////////
47// Trait implementations
48////////////////////////////////////////////////////////////////////////////////
49
50impl<T> Default for MaybeMultiple<T> {
51    fn default() -> Self {
52        Self::None
53    }
54}
55
56impl<T> From<T> for MaybeMultiple<T> {
57    fn from(t: T) -> Self {
58        Self::Some(t)
59    }
60}
61
62impl<T> From<Vec<T>> for MaybeMultiple<T> {
63    fn from(mut v: Vec<T>) -> Self {
64        match v.len() {
65            0 => Self::None,
66            1 => Self::Some(v.pop().expect("input vec has one element")),
67            _ => Self::Multiple(v.try_into().expect("input vec has more than one element")),
68        }
69    }
70}
71
72impl<T> From<MaybeMultiple<T>> for Vec<T> {
73    fn from(maybe_multiple: MaybeMultiple<T>) -> Self {
74        match maybe_multiple {
75            MaybeMultiple::None => vec![],
76            MaybeMultiple::Some(v) => vec![v],
77            MaybeMultiple::Multiple(m) => m.into(),
78        }
79    }
80}
81
82////////////////////////////////////////////////////////////////////////////////
83// Tests
84////////////////////////////////////////////////////////////////////////////////
85
86#[cfg(test)]
87mod tests {
88    use super::MaybeMultiple;
89    use pretty_assertions::assert_eq;
90    use proptest::collection::size_range;
91    use test_strategy::proptest;
92
93    #[proptest]
94    fn proptest_conversions(v: Vec<u8>) {
95        match v.len() {
96            0 => assert_eq!(MaybeMultiple::from_vec(v), MaybeMultiple::None),
97            1 => {
98                let e = v[0];
99                assert_eq!(MaybeMultiple::from(v), MaybeMultiple::Some(e));
100            }
101            _ => assert_eq!(
102                MaybeMultiple::from(v.clone()),
103                MaybeMultiple::Multiple(v.try_into().unwrap())
104            ),
105        }
106    }
107
108    #[test]
109    fn serialize_deserialize_none() {
110        assert_eq!(
111            serde_json::to_string(&MaybeMultiple::<u8>::None).unwrap(),
112            "null"
113        );
114        assert_eq!(
115            serde_json::from_str::<MaybeMultiple<u8>>("null").unwrap(),
116            MaybeMultiple::None
117        );
118    }
119
120    #[proptest]
121    fn serialize_deserialize_some(val: u8) {
122        let maybe_multiple = MaybeMultiple::Some(val);
123        assert_eq!(
124            serde_json::to_string(&maybe_multiple).unwrap(),
125            serde_json::to_string(&val).unwrap()
126        );
127
128        let val_str = serde_json::to_string(&val).unwrap();
129        assert_eq!(
130            serde_json::from_str::<MaybeMultiple<_>>(&val_str).unwrap(),
131            maybe_multiple
132        );
133    }
134
135    #[proptest]
136    fn serialize_deserialize_multiple(#[any(size_range(2..128).lift())] vec: Vec<u8>) {
137        let maybe_multiple = MaybeMultiple::from_vec(vec.clone());
138        assert_eq!(
139            serde_json::to_string(&maybe_multiple).unwrap(),
140            serde_json::to_string(&vec).unwrap()
141        );
142
143        let vec_str = serde_json::to_string(&vec).unwrap();
144        assert_eq!(
145            serde_json::from_str::<MaybeMultiple<_>>(&vec_str).unwrap(),
146            maybe_multiple
147        );
148    }
149}