Skip to main content

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, Clone, Copy, PartialEq, Eq)]
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    /// Iterator over wrapper types from outermost to innermost
46    pub fn iter(&self) -> TypeWrappersIter {
47        let current_wrappers = self.num_list_wrappers();
48        TypeWrappersIter {
49            encoded: self.0,
50            mask: (1 << (4 + current_wrappers)),
51            next: None,
52            last: ((INNER_NULLABILITY_MASK & self.0) == INNER_NULLABILITY_MASK)
53                .then_some(WrappingType::NonNull),
54        }
55    }
56
57    fn num_list_wrappers(&self) -> u32 {
58        (self.0 & NUM_LISTS_MASK) >> 1
59    }
60}
61
62impl FromIterator<WrappingType> for TypeWrappers {
63    fn from_iter<T: IntoIterator<Item = WrappingType>>(iter: T) -> Self {
64        iter.into_iter()
65            .fold(TypeWrappers::none(), |wrappers, wrapping| match wrapping {
66                WrappingType::NonNull => wrappers.wrap_non_null(),
67                WrappingType::List => wrappers.wrap_list(),
68            })
69    }
70}
71
72#[derive(Clone)]
73/// Iterator over wrapper types from outermost to innermost
74pub struct TypeWrappersIter {
75    encoded: u32,
76    mask: u32,
77    next: Option<WrappingType>,
78    last: Option<WrappingType>,
79}
80
81impl TypeWrappersIter {
82    /// Reverses this iterator
83    pub fn rev(
84        self,
85    ) -> impl ExactSizeIterator<Item = WrappingType> + DoubleEndedIterator<Item = WrappingType>
86    {
87        self.collect::<Vec<_>>().into_iter().rev()
88    }
89}
90
91impl Iterator for TypeWrappersIter {
92    type Item = WrappingType;
93
94    fn next(&mut self) -> Option<Self::Item> {
95        if let Some(next) = self.next.take() {
96            return Some(next);
97        }
98        if (self.mask & NUM_LISTS_MASK) != 0 {
99            if let Some(last) = self.last.take() {
100                return Some(last);
101            }
102            return None;
103        }
104
105        // Otherwise we still have list wrappers
106        let current_is_non_null = (self.encoded & self.mask) != 0;
107        self.mask >>= 1;
108
109        if current_is_non_null {
110            self.next = Some(WrappingType::List);
111            Some(WrappingType::NonNull)
112        } else {
113            Some(WrappingType::List)
114        }
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::{TypeWrappers, WrappingType};
121
122    #[test]
123    fn test_wrappers() {
124        assert_eq!(TypeWrappers::none().iter().collect::<Vec<_>>(), vec![]);
125        assert_eq!(
126            TypeWrappers::none()
127                .wrap_non_null()
128                .iter()
129                .collect::<Vec<_>>(),
130            vec![WrappingType::NonNull]
131        );
132
133        assert_eq!(
134            TypeWrappers::none().wrap_list().iter().collect::<Vec<_>>(),
135            vec![WrappingType::List]
136        );
137
138        assert_eq!(
139            TypeWrappers::none()
140                .wrap_non_null()
141                .wrap_list()
142                .iter()
143                .collect::<Vec<_>>(),
144            vec![WrappingType::List, WrappingType::NonNull]
145        );
146
147        assert_eq!(
148            TypeWrappers::none()
149                .wrap_non_null()
150                .wrap_list()
151                .wrap_non_null()
152                .iter()
153                .collect::<Vec<_>>(),
154            vec![
155                WrappingType::NonNull,
156                WrappingType::List,
157                WrappingType::NonNull
158            ]
159        );
160
161        assert_eq!(
162            TypeWrappers::none()
163                .wrap_list()
164                .wrap_list()
165                .wrap_list()
166                .wrap_non_null()
167                .iter()
168                .collect::<Vec<_>>(),
169            vec![
170                WrappingType::NonNull,
171                WrappingType::List,
172                WrappingType::List,
173                WrappingType::List,
174            ]
175        );
176
177        assert_eq!(
178            TypeWrappers::none()
179                .wrap_non_null()
180                .wrap_list()
181                .wrap_non_null()
182                .wrap_list()
183                .iter()
184                .collect::<Vec<_>>(),
185            vec![
186                WrappingType::List,
187                WrappingType::NonNull,
188                WrappingType::List,
189                WrappingType::NonNull
190            ]
191        );
192    }
193}