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(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
27pub struct Wrapping(u16);
28
29impl Default for Wrapping {
30 fn default() -> Self {
31 Self::nullable()
32 }
33}
34
35impl Wrapping {
36 pub fn inner_is_required(self) -> bool {
45 self.0 & INNER_IS_REQUIRED_FLAG != 0
46 }
47
48 pub fn list_wrappings(
50 self,
51 ) -> impl DoubleEndedIterator<Item = ListWrapping> + ExactSizeIterator<Item = ListWrapping> {
52 (0..self.get_list_length()).map(move |i| {
53 if self.0 & (1 << i) == 0 {
54 ListWrapping::NullableList
55 } else {
56 ListWrapping::RequiredList
57 }
58 })
59 }
60
61 fn get_list_length(&self) -> u8 {
62 ((self.0 & LIST_WRAPPER_LENGTH_MASK) >> LIST_WRAPPER_SHIFT) as u8
63 }
64
65 fn set_list_length(&mut self, len: u8) {
66 assert!((len as u32) < MAX_LIST_WRAPINGS, "list wrapper overflow");
67 self.0 = (self.0 & !LIST_WRAPPER_LENGTH_MASK) | ((len as u16) << LIST_WRAPPER_SHIFT);
68 }
69
70 pub fn to_mutable(self) -> MutableWrapping {
71 self.into()
72 }
73
74 pub fn nullable() -> Self {
75 Wrapping(0)
76 }
77
78 pub fn required() -> Self {
79 Wrapping(INNER_IS_REQUIRED_FLAG)
80 }
81
82 #[must_use]
83 pub fn wrap_list(mut self) -> Self {
84 let len = self.get_list_length();
85 self.set_list_length(len + 1);
86 self.0 &= !(1 << len);
87 self
88 }
89
90 #[must_use]
91 pub fn wrap_list_non_null(mut self) -> Self {
92 let len = self.get_list_length();
93 self.set_list_length(len + 1);
94 self.0 |= 1 << len;
95 self
96 }
97
98 #[must_use]
99 pub fn wrap_non_null(mut self) -> Self {
100 let len = self.get_list_length();
101 if len == 0 {
102 self.0 |= INNER_IS_REQUIRED_FLAG;
103 } else {
104 self.0 |= 1 << (len - 1);
105 }
106 self
107 }
108}
109
110#[derive(Clone, Copy, Debug, PartialEq, Eq)]
111pub enum ListWrapping {
112 RequiredList,
113 NullableList,
114}
115
116impl Wrapping {
117 pub fn new(required: bool) -> Self {
118 if required {
119 Self::required()
120 } else {
121 Self::nullable()
122 }
123 }
124
125 pub fn is_nullable(self) -> bool {
126 !self.is_required()
127 }
128
129 pub fn is_required(self) -> bool {
130 self.list_wrappings()
131 .next_back()
132 .map(|lw| matches!(lw, ListWrapping::RequiredList))
133 .unwrap_or(self.inner_is_required())
134 }
135
136 pub fn is_list(self) -> bool {
137 self.list_wrappings().next().is_some()
138 }
139
140 pub fn write_type_string(self, name: &str, mut formatter: &mut dyn std::fmt::Write) -> Result<(), std::fmt::Error> {
141 for _ in 0..self.list_wrappings().len() {
142 write!(formatter, "[")?;
143 }
144
145 write!(formatter, "{name}")?;
146
147 if self.inner_is_required() {
148 write!(formatter, "!")?;
149 }
150
151 for wrapping in self.list_wrappings() {
152 match wrapping {
153 ListWrapping::RequiredList => write!(&mut formatter, "]!")?,
154 ListWrapping::NullableList => write!(&mut formatter, "]")?,
155 };
156 }
157
158 Ok(())
159 }
160}
161
162impl std::fmt::Debug for Wrapping {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 f.debug_struct("Wrapping")
165 .field("inner_is_required", &self.inner_is_required())
166 .field("list_wrappings", &self.list_wrappings().collect::<Vec<_>>())
167 .finish()
168 }
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174
175 #[test]
176 fn test_wrapping() {
177 let wrapping = Wrapping::required();
178 assert!(wrapping.inner_is_required());
179 assert!(wrapping.is_required() && !wrapping.is_nullable());
180 assert!(!wrapping.is_list());
181 assert_eq!(wrapping.list_wrappings().collect::<Vec<_>>(), vec![]);
182
183 let mut wrapping = Wrapping::nullable();
184 assert!(!wrapping.inner_is_required());
185 assert!(wrapping.is_nullable() && !wrapping.is_required());
186 assert!(!wrapping.is_list());
187 assert_eq!(wrapping.list_wrappings().collect::<Vec<_>>(), vec![]);
188
189 wrapping = wrapping.wrap_list();
190 assert!(!wrapping.inner_is_required());
191 assert!(wrapping.is_nullable() && !wrapping.is_required());
192 assert!(wrapping.is_list());
193 assert_eq!(
194 wrapping.list_wrappings().collect::<Vec<_>>(),
195 vec![ListWrapping::NullableList]
196 );
197
198 wrapping = wrapping.wrap_list_non_null();
199 assert!(!wrapping.inner_is_required());
200 assert!(wrapping.is_required() && !wrapping.is_nullable());
201 assert!(wrapping.is_list());
202 assert_eq!(
203 wrapping.list_wrappings().collect::<Vec<_>>(),
204 vec![ListWrapping::NullableList, ListWrapping::RequiredList]
205 );
206
207 wrapping = wrapping.wrap_list();
208 assert!(!wrapping.inner_is_required());
209 assert!(wrapping.is_nullable() && !wrapping.is_required());
210 assert!(wrapping.is_list());
211 assert_eq!(
212 wrapping.list_wrappings().collect::<Vec<_>>(),
213 vec![
214 ListWrapping::NullableList,
215 ListWrapping::RequiredList,
216 ListWrapping::NullableList
217 ]
218 );
219 }
220
221 #[test]
222 fn test_mutable_wrapping() {
223 let mut wrapping = Wrapping::default()
224 .wrap_non_null()
225 .wrap_list()
226 .wrap_list_non_null()
227 .wrap_list()
228 .to_mutable();
229
230 assert!(wrapping.is_nullable());
231 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::NullableList));
232
233 assert!(wrapping.is_required());
234 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::RequiredList));
235
236 assert!(wrapping.is_nullable());
237 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::NullableList));
238
239 assert!(wrapping.is_required());
240 assert_eq!(wrapping.pop_outermost_list_wrapping(), None);
241
242 let mut wrapping = Wrapping::default().wrap_list().wrap_list_non_null().to_mutable();
243
244 assert!(wrapping.is_required());
245 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::RequiredList));
246
247 assert!(wrapping.is_nullable());
248 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::NullableList));
249
250 assert!(wrapping.is_nullable());
251 assert_eq!(wrapping.pop_outermost_list_wrapping(), None);
252 }
253
254 #[test]
255 fn test_wrapping_order() {
256 let wrapping = Wrapping::default()
257 .wrap_non_null()
258 .wrap_list()
259 .wrap_list()
260 .wrap_list_non_null()
261 .wrap_list();
262 assert!(wrapping.inner_is_required());
263 assert_eq!(
264 wrapping.list_wrappings().collect::<Vec<_>>(),
265 vec![
266 ListWrapping::NullableList,
267 ListWrapping::NullableList,
268 ListWrapping::RequiredList,
269 ListWrapping::NullableList
270 ]
271 );
272
273 let wrapping = Wrapping::required()
274 .wrap_list()
275 .wrap_list()
276 .wrap_list_non_null()
277 .wrap_list()
278 .wrap_non_null();
279 assert!(wrapping.inner_is_required());
280 assert_eq!(
281 wrapping.list_wrappings().collect::<Vec<_>>(),
282 vec![
283 ListWrapping::NullableList,
284 ListWrapping::NullableList,
285 ListWrapping::RequiredList,
286 ListWrapping::RequiredList
287 ]
288 );
289
290 let mut wrapping = Wrapping::required()
291 .wrap_list()
292 .wrap_list()
293 .wrap_list_non_null()
294 .wrap_list()
295 .to_mutable();
296 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::NullableList));
297 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::RequiredList));
298 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::NullableList));
299 assert_eq!(wrapping.pop_outermost_list_wrapping(), Some(ListWrapping::NullableList));
300 }
301
302 #[test]
303 fn back_and_forth() {
304 let original = Wrapping::required().wrap_list_non_null();
305 let mut wrapping = original.to_mutable();
306 let list_wrapping = wrapping.pop_outermost_list_wrapping().unwrap();
307 wrapping.push_outermost_list_wrapping(list_wrapping);
308 assert_eq!(Wrapping::from(wrapping), original);
309
310 let original = Wrapping::nullable().wrap_list();
311 let mut wrapping = original.to_mutable();
312 let list_wrapping = wrapping.pop_outermost_list_wrapping().unwrap();
313 wrapping.push_outermost_list_wrapping(list_wrapping);
314 assert_eq!(Wrapping::from(wrapping), original);
315 }
316}