Skip to main content

json_web_tolkien/util/
one_or_more.rs

1use serde::{Deserialize, Serialize};
2
3/// Represents a deserialized value that can legally be either a single string or
4/// an array of strings.
5#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
6#[serde(untagged)]
7pub enum OneOrMore {
8    One(Box<str>),
9    More(Box<[Box<str>]>),
10}
11
12pub struct OneOrMoreIterator<'a> {
13    inner: &'a OneOrMore,
14    index: usize,
15}
16
17impl OneOrMore {
18    /// This iterates over &str, in the case of `OneOrMore::One`, it will
19    /// return the value if index is 0, and `Option::None` otherwise.
20    pub fn iter(&self) -> OneOrMoreIterator<'_> {
21        OneOrMoreIterator {
22            inner: self,
23            index: 0,
24        }
25    }
26}
27
28impl<'a> IntoIterator for &'a OneOrMore {
29    type Item = &'a str;
30    type IntoIter = OneOrMoreIterator<'a>;
31
32    fn into_iter(self) -> Self::IntoIter {
33        self.iter()
34    }
35}
36
37impl<'a> Iterator for OneOrMoreIterator<'a> {
38    type Item = &'a str;
39
40    fn next(&mut self) -> Option<Self::Item> {
41        let len: usize = match self.inner {
42            OneOrMore::One(_) => 1,
43            OneOrMore::More(list) => list.len(),
44        };
45
46        if self.index < len {
47            let result: Self::Item = match self.inner {
48                OneOrMore::One(one) => one,
49                OneOrMore::More(more) => (more[self.index]).as_ref(),
50            };
51
52            self.index += 1;
53
54            Some(result)
55        } else {
56            None
57        }
58    }
59}
60
61#[cfg(test)]
62mod test {
63    use super::*;
64
65    #[test]
66    fn it_will_match_any_against_one() {
67        let v1 = OneOrMore::One("one".into());
68        let v2 = {
69            let v: Box<[Box<str>]> = ["one".into(), "two".into()].into();
70
71            OneOrMore::More(v)
72        };
73
74        assert!(v1.iter().any(|x| x == "one"));
75        assert!(v2.iter().any(|x| x == "one"));
76        assert!(v2.iter().any(|x| x == "two"));
77        assert_eq!(v1.iter().any(|x| x == "two"), false);
78    }
79}