graphql_wrapping_types/
lib.rs1mod mutable;
2
3pub use mutable::MutableWrapping;
4
5const LIST_WRAPPER_LENGTH_MASK: u16 = 0b0111_1000_0000_0000;
6const LIST_WRAPPER_SHIFT: u32 = LIST_WRAPPER_LENGTH_MASK.trailing_zeros();
7const LIST_WRAPPER_MASK: u16 = 0b0000_0111_1111_1111;
8const MAX_LIST_WRAPINGS: u32 = LIST_WRAPPER_MASK.trailing_ones();
9const INNER_IS_REQUIRED_FLAG: u16 = 0b1000_0000_0000_0000;
10
11#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
27pub struct Wrapping(u16);
28
29impl Wrapping {
30 pub fn inner_is_required(self) -> bool {
39 self.0 & INNER_IS_REQUIRED_FLAG != 0
40 }
41
42 pub fn list_wrappings(
44 self,
45 ) -> impl DoubleEndedIterator<Item = ListWrapping> + ExactSizeIterator<Item = ListWrapping> {
46 (0..self.get_list_length()).map(move |i| {
47 if self.0 & (1 << i) == 0 {
48 ListWrapping::List
49 } else {
50 ListWrapping::ListNonNull
51 }
52 })
53 }
54
55 pub fn iter(self) -> impl Iterator<Item = WrappingType> {
57 [self.inner_is_required().then_some(WrappingType::NonNull)]
58 .into_iter()
59 .chain(self.list_wrappings().flat_map(|lw| match lw {
60 ListWrapping::List => [Some(WrappingType::List), None],
61 ListWrapping::ListNonNull => [Some(WrappingType::List), Some(WrappingType::NonNull)],
62 }))
63 .flatten()
64 }
65
66 const fn get_list_length(&self) -> u8 {
67 ((self.0 & LIST_WRAPPER_LENGTH_MASK) >> LIST_WRAPPER_SHIFT) as u8
68 }
69
70 const fn set_list_length(&mut self, len: u8) {
71 assert!((len as u32) < MAX_LIST_WRAPINGS, "list wrapper overflow");
72 self.0 = (self.0 & INNER_IS_REQUIRED_FLAG) | ((len as u16) << LIST_WRAPPER_SHIFT) | (self.0 & ((1 << len) - 1));
73 }
74
75 pub fn to_mutable(self) -> MutableWrapping {
76 self.into()
77 }
78
79 #[must_use]
80 pub const fn list(mut self) -> Self {
81 let len = self.get_list_length();
82 self.set_list_length(len + 1);
83 self.0 &= !(1 << len);
84 self
85 }
86
87 #[must_use]
88 pub const fn list_non_null(mut self) -> Self {
89 let len = self.get_list_length();
90 self.set_list_length(len + 1);
91 self.0 |= 1 << len;
92 self
93 }
94
95 #[must_use]
96 pub const fn non_null(mut self) -> Self {
97 let len = self.get_list_length();
98 if len == 0 {
99 self.0 |= INNER_IS_REQUIRED_FLAG;
100 } else {
101 self.0 |= 1 << (len - 1);
102 }
103 self
104 }
105
106 pub fn is_equal_or_more_lenient_than(self, other: Wrapping) -> bool {
108 if self.inner_is_required() && !other.inner_is_required() {
109 return false;
110 }
111 if self.get_list_length() != other.get_list_length() {
112 return false;
113 }
114 for (s, o) in self.list_wrappings().zip(other.list_wrappings()) {
115 if s == ListWrapping::ListNonNull && o == ListWrapping::List {
116 return false;
117 }
118 }
119 true
120 }
121
122 pub fn without_list(self) -> Option<Wrapping> {
123 let mut wrapping = self.to_mutable();
124 wrapping.pop_outermost_list_wrapping().map(|_| wrapping.into())
125 }
126
127 pub fn without_non_null(mut self) -> Wrapping {
128 if self.is_nullable() {
129 self
130 } else if self.is_list() {
131 let mut wrapping = self.to_mutable();
132 wrapping.pop_outermost_list_wrapping();
133 wrapping.push_outermost_list_wrapping(ListWrapping::List);
134 wrapping.into()
135 } else {
136 self.0 &= !INNER_IS_REQUIRED_FLAG;
137 self
138 }
139 }
140}
141
142#[derive(Clone, Copy, Debug, PartialEq, Eq)]
143pub enum WrappingType {
144 NonNull,
145 List,
146}
147
148#[derive(Clone, Copy, Debug, PartialEq, Eq)]
149pub enum ListWrapping {
150 ListNonNull,
151 List,
152}
153
154impl Wrapping {
155 pub fn is_nullable(self) -> bool {
156 !self.is_non_null()
157 }
158
159 pub fn is_non_null(self) -> bool {
160 self.list_wrappings()
161 .next_back()
162 .map(|lw| matches!(lw, ListWrapping::ListNonNull))
163 .unwrap_or(self.inner_is_required())
164 }
165
166 pub fn is_list(self) -> bool {
167 self.list_wrappings().next().is_some()
168 }
169
170 pub fn type_display(self, name: &str) -> impl std::fmt::Display {
171 WrappingDisplay { name, wrapping: self }
172 }
173}
174
175struct WrappingDisplay<'a> {
176 name: &'a str,
177 wrapping: Wrapping,
178}
179
180impl std::fmt::Display for WrappingDisplay<'_> {
181 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182 for _ in 0..self.wrapping.get_list_length() {
183 write!(f, "[")?;
184 }
185
186 write!(f, "{}", self.name)?;
187
188 if self.wrapping.inner_is_required() {
189 write!(f, "!")?;
190 }
191
192 for wrapping in self.wrapping.list_wrappings() {
193 match wrapping {
194 ListWrapping::ListNonNull => write!(f, "]!")?,
195 ListWrapping::List => write!(f, "]")?,
196 };
197 }
198
199 Ok(())
200 }
201}
202
203impl std::fmt::Debug for Wrapping {
204 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205 f.debug_struct("Wrapping")
206 .field("inner_is_required", &self.inner_is_required())
207 .field("list_wrappings", &self.list_wrappings().collect::<Vec<_>>())
208 .field("binary", &format!("{:016b}", self.0))
209 .finish()
210 }
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216
217 #[test]
218 fn test_wrapping() {
219 let wrapping = Wrapping::default().non_null();
220 assert!(wrapping.inner_is_required());
221 assert!(wrapping.is_non_null() && !wrapping.is_nullable());
222 assert!(!wrapping.is_list());
223 assert_eq!(wrapping.list_wrappings().collect::<Vec<_>>(), vec![]);
224
225 let mut wrapping = Wrapping::default();
226 assert!(!wrapping.inner_is_required());
227 assert!(wrapping.is_nullable() && !wrapping.is_non_null());
228 assert!(!wrapping.is_list());
229 assert_eq!(wrapping.list_wrappings().collect::<Vec<_>>(), vec![]);
230
231 wrapping = wrapping.list();
232 assert!(!wrapping.inner_is_required());
233 assert!(wrapping.is_nullable() && !wrapping.is_non_null());
234 assert!(wrapping.is_list());
235 assert_eq!(wrapping.list_wrappings().collect::<Vec<_>>(), vec![ListWrapping::List]);
236
237 wrapping = wrapping.list_non_null();
238 assert!(!wrapping.inner_is_required());
239 assert!(wrapping.is_non_null() && !wrapping.is_nullable());
240 assert!(wrapping.is_list());
241 assert_eq!(
242 wrapping.list_wrappings().collect::<Vec<_>>(),
243 vec![ListWrapping::List, ListWrapping::ListNonNull]
244 );
245
246 wrapping = wrapping.list();
247 assert!(!wrapping.inner_is_required());
248 assert!(wrapping.is_nullable() && !wrapping.is_non_null());
249 assert!(wrapping.is_list());
250 assert_eq!(
251 wrapping.list_wrappings().collect::<Vec<_>>(),
252 vec![ListWrapping::List, ListWrapping::ListNonNull, ListWrapping::List]
253 );
254 }
255
256 #[test]
257 fn test_mutable_wrapping() {
258 let mut wrapping = Wrapping::default()
259 .non_null()
260 .list()
261 .list_non_null()
262 .list()
263 .to_mutable();
264
265 assert!(wrapping.is_nullable());
266 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::List));
267
268 assert!(wrapping.is_required());
269 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::ListNonNull));
270
271 assert!(wrapping.is_nullable());
272 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::List));
273
274 assert!(wrapping.is_required());
275 assert_eq!(wrapping.pop_outermost_list_wrapping(), None);
276
277 let mut wrapping = Wrapping::default().list().list_non_null().to_mutable();
278
279 assert!(wrapping.is_required());
280 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::ListNonNull));
281
282 assert!(wrapping.is_nullable());
283 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::List));
284
285 assert!(wrapping.is_nullable());
286 assert_eq!(wrapping.pop_outermost_list_wrapping(), None);
287 }
288
289 #[test]
290 fn test_wrapping_order() {
291 let wrapping = Wrapping::default().non_null().list().list().list_non_null().list();
292 assert!(wrapping.inner_is_required());
293 assert_eq!(
294 wrapping.list_wrappings().collect::<Vec<_>>(),
295 vec![
296 ListWrapping::List,
297 ListWrapping::List,
298 ListWrapping::ListNonNull,
299 ListWrapping::List
300 ]
301 );
302
303 let wrapping = Wrapping::default()
304 .non_null()
305 .list()
306 .list()
307 .list_non_null()
308 .list()
309 .non_null();
310 assert!(wrapping.inner_is_required());
311 assert_eq!(
312 wrapping.list_wrappings().collect::<Vec<_>>(),
313 vec![
314 ListWrapping::List,
315 ListWrapping::List,
316 ListWrapping::ListNonNull,
317 ListWrapping::ListNonNull
318 ]
319 );
320
321 let mut wrapping = Wrapping::default()
322 .non_null()
323 .list()
324 .list()
325 .list_non_null()
326 .list()
327 .to_mutable();
328 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::List));
329 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::ListNonNull));
330 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::List));
331 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::List));
332 }
333
334 #[test]
335 fn back_and_forth() {
336 let original = Wrapping::default().non_null().list_non_null();
337 let mut wrapping = original.to_mutable();
338 let list_wrapping = wrapping.pop_outermost_list_wrapping().unwrap();
339 assert_eq!(Wrapping::from(wrapping.clone()), Wrapping::default().non_null());
340
341 wrapping.push_outermost_list_wrapping(list_wrapping);
342 assert_eq!(Wrapping::from(wrapping), original);
343
344 let original = Wrapping::default().list();
345 let mut wrapping = original.to_mutable();
346 let list_wrapping = wrapping.pop_outermost_list_wrapping().unwrap();
347 assert_eq!(Wrapping::from(wrapping.clone()), Wrapping::default());
348
349 wrapping.push_outermost_list_wrapping(list_wrapping);
350 assert_eq!(Wrapping::from(wrapping), original);
351 }
352
353 #[test]
354 fn test_is_equal_or_more_lenient_than() {
355 let non_null_list = Wrapping::default().non_null().list();
356 let non_null_list_non_null = Wrapping::default().non_null().list_non_null();
357 assert!(non_null_list.is_equal_or_more_lenient_than(non_null_list_non_null));
358 assert!(!non_null_list_non_null.is_equal_or_more_lenient_than(non_null_list));
359
360 let list = Wrapping::default().list();
361 assert!(list.is_equal_or_more_lenient_than(non_null_list));
362 assert!(!non_null_list.is_equal_or_more_lenient_than(list));
363
364 let list_non_null = Wrapping::default().list_non_null();
365 assert!(!non_null_list.is_equal_or_more_lenient_than(list_non_null));
366 assert!(!list_non_null.is_equal_or_more_lenient_than(non_null_list));
367 }
368}