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 TypeWrappersIter {
80    /// Reverses this iterator
81    pub fn rev(
82        self,
83    ) -> impl ExactSizeIterator<Item = WrappingType> + DoubleEndedIterator<Item = WrappingType>
84    {
85        self.collect::<Vec<_>>().into_iter().rev()
86    }
87}
88
89impl Iterator for TypeWrappersIter {
90    type Item = WrappingType;
91
92    fn next(&mut self) -> Option<Self::Item> {
93        if let Some(next) = self.next.take() {
94            return Some(next);
95        }
96        if (self.mask & NUM_LISTS_MASK) != 0 {
97            if let Some(last) = self.last.take() {
98                return Some(last);
99            }
100            return None;
101        }
102
103        // Otherwise we still have list wrappers
104        let current_is_non_null = (self.encoded & self.mask) != 0;
105        self.mask >>= 1;
106
107        if current_is_non_null {
108            self.next = Some(WrappingType::List);
109            Some(WrappingType::NonNull)
110        } else {
111            Some(WrappingType::List)
112        }
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use super::{TypeWrappers, WrappingType};
119
120    #[test]
121    fn test_wrappers() {
122        assert_eq!(TypeWrappers::none().iter().collect::<Vec<_>>(), vec![]);
123        assert_eq!(
124            TypeWrappers::none()
125                .wrap_non_null()
126                .iter()
127                .collect::<Vec<_>>(),
128            vec![WrappingType::NonNull]
129        );
130
131        assert_eq!(
132            TypeWrappers::none().wrap_list().iter().collect::<Vec<_>>(),
133            vec![WrappingType::List]
134        );
135
136        assert_eq!(
137            TypeWrappers::none()
138                .wrap_non_null()
139                .wrap_list()
140                .iter()
141                .collect::<Vec<_>>(),
142            vec![WrappingType::List, WrappingType::NonNull]
143        );
144
145        assert_eq!(
146            TypeWrappers::none()
147                .wrap_non_null()
148                .wrap_list()
149                .wrap_non_null()
150                .iter()
151                .collect::<Vec<_>>(),
152            vec![
153                WrappingType::NonNull,
154                WrappingType::List,
155                WrappingType::NonNull
156            ]
157        );
158
159        assert_eq!(
160            TypeWrappers::none()
161                .wrap_list()
162                .wrap_list()
163                .wrap_list()
164                .wrap_non_null()
165                .iter()
166                .collect::<Vec<_>>(),
167            vec![
168                WrappingType::NonNull,
169                WrappingType::List,
170                WrappingType::List,
171                WrappingType::List,
172            ]
173        );
174
175        assert_eq!(
176            TypeWrappers::none()
177                .wrap_non_null()
178                .wrap_list()
179                .wrap_non_null()
180                .wrap_list()
181                .iter()
182                .collect::<Vec<_>>(),
183            vec![
184                WrappingType::List,
185                WrappingType::NonNull,
186                WrappingType::List,
187                WrappingType::NonNull
188            ]
189        );
190    }
191}