cynic_parser/common/
types.rs1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2pub enum WrappingType {
3 NonNull,
4 List,
5}
6
7#[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 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)]
73pub struct TypeWrappersIter {
75 encoded: u32,
76 mask: u32,
77 next: Option<WrappingType>,
78 last: Option<WrappingType>,
79}
80
81impl TypeWrappersIter {
82 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 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}