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 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 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}