cynic_parser/common/
types.rs1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2pub enum WrappingType {
3 NonNull,
4 List,
5}
6
7#[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 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 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}