cynic_parser/common/
types.rs

1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2pub enum WrappingType {
3    NonNull,
4    List,
5}
6
7/// GraphQL wrappers encoded into a single u32
8///
9/// Bit 0: Whether the inner type is null
10/// Bits 1..5: Number of list wrappers
11/// Bits 5..21: List wrappers, where 0 is nullable 1 is non-null
12/// The rest: dead bits
13#[derive(Debug, Default)]
14pub struct TypeWrappers(u32);
15
16static INNER_NULLABILITY_MASK: u32 = 1;
17static NUM_LISTS_MASK: u32 = 32 - 2;
18static NON_NUM_LISTS_MASK: u32 = u32::MAX ^ NUM_LISTS_MASK;
19
20impl TypeWrappers {
21    pub fn none() -> Self {
22        TypeWrappers(0)
23    }
24
25    pub fn wrap_list(&self) -> Self {
26        let current_wrappers = self.num_list_wrappers();
27
28        let new_wrappers = current_wrappers + 1;
29        assert!(new_wrappers < 16, "list wrapper overflow");
30
31        Self((new_wrappers << 1) | (self.0 & NON_NUM_LISTS_MASK))
32    }
33
34    pub fn wrap_non_null(&self) -> Self {
35        let index = self.num_list_wrappers();
36        if index == 0 {
37            return Self(INNER_NULLABILITY_MASK);
38        }
39
40        let new = self.0 | (1 << (4 + index));
41
42        TypeWrappers(new)
43    }
44
45    pub fn iter(&self) -> TypeWrappersIter {
46        let current_wrappers = self.num_list_wrappers();
47        TypeWrappersIter {
48            encoded: self.0,
49            mask: (1 << (4 + current_wrappers)),
50            next: None,
51            last: ((INNER_NULLABILITY_MASK & self.0) == INNER_NULLABILITY_MASK)
52                .then_some(WrappingType::NonNull),
53        }
54    }
55
56    fn num_list_wrappers(&self) -> u32 {
57        (self.0 & NUM_LISTS_MASK) >> 1
58    }
59}
60
61impl FromIterator<WrappingType> for TypeWrappers {
62    fn from_iter<T: IntoIterator<Item = WrappingType>>(iter: T) -> Self {
63        iter.into_iter()
64            .fold(TypeWrappers::none(), |wrappers, wrapping| match wrapping {
65                WrappingType::NonNull => wrappers.wrap_non_null(),
66                WrappingType::List => wrappers.wrap_list(),
67            })
68    }
69}
70
71#[derive(Clone)]
72pub struct TypeWrappersIter {
73    encoded: u32,
74    mask: u32,
75    next: Option<WrappingType>,
76    last: Option<WrappingType>,
77}
78
79impl Iterator for TypeWrappersIter {
80    type Item = WrappingType;
81
82    fn next(&mut self) -> Option<Self::Item> {
83        if let Some(next) = self.next.take() {
84            return Some(next);
85        }
86        if (self.mask & NUM_LISTS_MASK) != 0 {
87            if let Some(last) = self.last.take() {
88                return Some(last);
89            }
90            return None;
91        }
92
93        // Otherwise we still have list wrappers
94        let current_is_non_null = (self.encoded & self.mask) != 0;
95        self.mask >>= 1;
96
97        if current_is_non_null {
98            self.next = Some(WrappingType::List);
99            Some(WrappingType::NonNull)
100        } else {
101            Some(WrappingType::List)
102        }
103    }
104}
105
106#[cfg(test)]
107mod tests {
108    use super::{TypeWrappers, WrappingType};
109
110    #[test]
111    fn test_wrappers() {
112        assert_eq!(TypeWrappers::none().iter().collect::<Vec<_>>(), vec![]);
113        assert_eq!(
114            TypeWrappers::none()
115                .wrap_non_null()
116                .iter()
117                .collect::<Vec<_>>(),
118            vec![WrappingType::NonNull]
119        );
120
121        assert_eq!(
122            TypeWrappers::none().wrap_list().iter().collect::<Vec<_>>(),
123            vec![WrappingType::List]
124        );
125
126        assert_eq!(
127            TypeWrappers::none()
128                .wrap_non_null()
129                .wrap_list()
130                .iter()
131                .collect::<Vec<_>>(),
132            vec![WrappingType::List, WrappingType::NonNull]
133        );
134
135        assert_eq!(
136            TypeWrappers::none()
137                .wrap_non_null()
138                .wrap_list()
139                .wrap_non_null()
140                .iter()
141                .collect::<Vec<_>>(),
142            vec![
143                WrappingType::NonNull,
144                WrappingType::List,
145                WrappingType::NonNull
146            ]
147        );
148
149        assert_eq!(
150            TypeWrappers::none()
151                .wrap_list()
152                .wrap_list()
153                .wrap_list()
154                .wrap_non_null()
155                .iter()
156                .collect::<Vec<_>>(),
157            vec![
158                WrappingType::NonNull,
159                WrappingType::List,
160                WrappingType::List,
161                WrappingType::List,
162            ]
163        );
164
165        assert_eq!(
166            TypeWrappers::none()
167                .wrap_non_null()
168                .wrap_list()
169                .wrap_non_null()
170                .wrap_list()
171                .iter()
172                .collect::<Vec<_>>(),
173            vec![
174                WrappingType::List,
175                WrappingType::NonNull,
176                WrappingType::List,
177                WrappingType::NonNull
178            ]
179        );
180    }
181}