object_rainbow/numeric/
private.rs1use std::num::NonZero;
2
3use crate::{enumkind::UsizeTag, *};
4
5pub trait HasOtherSign {
6 type OtherSign;
7}
8
9type Os<T> = <T as HasOtherSign>::OtherSign;
10
11#[derive(ParseAsInline)]
12pub struct Ae<T>(pub T);
13#[derive(ParseAsInline)]
14pub struct Le<T>(pub T);
15#[derive(ParseAsInline)]
16pub struct Be<T>(pub T);
17#[derive(ParseAsInline)]
18pub struct Nz<T: NonZeroable>(T::Nz);
19
20pub trait NonZeroable {
21 type Nz: Send + Sync;
22 fn to_nz(&self) -> Option<Self::Nz>;
23 fn from_nz(nz: &Self::Nz) -> Self;
24}
25
26impl<T> From<T> for Ae<T> {
27 fn from(n: T) -> Self {
28 Self(n)
29 }
30}
31
32impl<T> From<T> for Be<T> {
33 fn from(n: T) -> Self {
34 Self(n)
35 }
36}
37
38impl<T> From<T> for Le<T> {
39 fn from(n: T) -> Self {
40 Self(n)
41 }
42}
43
44impl<T> Deref for Ae<T> {
45 type Target = T;
46
47 fn deref(&self) -> &Self::Target {
48 &self.0
49 }
50}
51
52impl<T> Deref for Le<T> {
53 type Target = T;
54
55 fn deref(&self) -> &Self::Target {
56 &self.0
57 }
58}
59
60impl<T> Deref for Be<T> {
61 type Target = T;
62
63 fn deref(&self) -> &Self::Target {
64 &self.0
65 }
66}
67
68pub trait AsLe {
69 type Le;
70 fn construct(self) -> Self::Le;
71}
72
73pub trait AsBe {
74 type Be;
75 fn construct(self) -> Self::Be;
76}
77
78macro_rules! signs {
79 ($u:ty, $i:ty) => {
80 impl HasOtherSign for $u {
81 type OtherSign = $i;
82 }
83 impl HasOtherSign for $i {
84 type OtherSign = $u;
85 }
86 };
87}
88
89macro_rules! ae {
90 ($n:ty) => {
91 impl UsizeTag for $n {
92 fn from_usize(n: usize) -> Self {
93 n.try_into().expect("discriminant out of range")
94 }
95 fn to_usize(&self) -> usize {
96 (*self).try_into().expect("discriminant out of range")
97 }
98 fn try_to_usize(&self) -> Option<usize> {
99 (*self).try_into().ok()
100 }
101 }
102
103 impl UsizeTag for NonZero<$n> {
104 fn from_usize(n: usize) -> Self {
105 Self::new(
106 n.checked_add(1)
107 .expect("discriminant out of range")
108 .try_into()
109 .expect("discriminant out of range"),
110 )
111 .unwrap()
112 }
113 fn to_usize(&self) -> usize {
114 usize::try_from(self.get())
115 .expect("discriminant out of range")
116 .checked_sub(1)
117 .unwrap()
118 }
119 fn try_to_usize(&self) -> Option<usize> {
120 usize::try_from(self.get()).ok()?.checked_sub(1)
121 }
122 }
123
124 impl AsLe for $n {
125 type Le = Ae<$n>;
126 fn construct(self) -> Self::Le {
127 Ae(self)
128 }
129 }
130
131 impl AsLe for NonZero<$n> {
132 type Le = Nz<Ae<$n>>;
133 fn construct(self) -> Self::Le {
134 Nz(self)
135 }
136 }
137
138 impl AsBe for $n {
139 type Be = Ae<$n>;
140 fn construct(self) -> Self::Be {
141 Ae(self)
142 }
143 }
144
145 impl AsBe for NonZero<$n> {
146 type Be = Nz<Ae<$n>>;
147 fn construct(self) -> Self::Be {
148 Nz(self)
149 }
150 }
151
152 impl From<NonZero<$n>> for Nz<Ae<$n>> {
153 fn from(nz: NonZero<$n>) -> Self {
154 Self(nz)
155 }
156 }
157
158 impl NonZeroable for Ae<$n> {
159 type Nz = NonZero<$n>;
160 fn to_nz(&self) -> Option<Self::Nz> {
161 NonZero::new(self.0)
162 }
163 fn from_nz(nz: &Self::Nz) -> Self {
164 Self(nz.get())
165 }
166 }
167
168 impl ToOutput for Ae<$n> {
169 fn to_output(&self, output: &mut dyn Output) {
170 output.write(&self.0.to_le_bytes());
171 }
172 }
173
174 impl<I: ParseInput> ParseInline<I> for Ae<$n> {
175 fn parse_inline(input: &mut I) -> crate::Result<Self> {
176 Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
177 }
178 }
179
180 impl Size for Ae<$n> {
181 const SIZE: usize = std::mem::size_of::<$n>();
182 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
183 }
184
185 impl MaybeHasNiche for Ae<$n> {
186 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
187 }
188
189 impl Topological for Ae<$n> {}
190 impl Tagged for Ae<$n> {}
191 impl Tagged for Ae<NonZero<$n>> {}
192 impl ReflessObject for Ae<$n> {}
193 impl ReflessInline for Ae<$n> {}
194 impl Object for Ae<$n> {}
195 impl Inline for Ae<$n> {}
196
197 impl Equivalent<Ae<$n>> for Option<Ae<NonZero<$n>>> {
198 fn into_equivalent(self) -> Ae<$n> {
199 Ae(self.map(|object| object.0.get()).unwrap_or_default())
200 }
201 fn from_equivalent(object: Ae<$n>) -> Self {
202 NonZero::new(object.0).map(Ae)
203 }
204 }
205
206 impl Equivalent<Ae<Os<$n>>> for Ae<$n> {
207 fn into_equivalent(self) -> Ae<Os<$n>> {
208 Ae(self.0 as _)
209 }
210 fn from_equivalent(object: Ae<Os<$n>>) -> Self {
211 Ae(object.0 as _)
212 }
213 }
214
215 impl Equivalent<Ae<NonZero<Os<$n>>>> for Ae<NonZero<$n>> {
216 fn into_equivalent(self) -> Ae<NonZero<Os<$n>>> {
217 Ae(NonZero::new(self.0.get() as _).unwrap())
218 }
219 fn from_equivalent(object: Ae<NonZero<Os<$n>>>) -> Self {
220 Ae(NonZero::new(object.0.get() as _).unwrap())
221 }
222 }
223 };
224}
225
226macro_rules! lebe {
227 ($n:ty) => {
228 impl UsizeTag for $n {
229 fn from_usize(n: usize) -> Self {
230 n.try_into().expect("discriminant out of range")
231 }
232 fn to_usize(&self) -> usize {
233 (*self).try_into().expect("discriminant out of range")
234 }
235 fn try_to_usize(&self) -> Option<usize> {
236 (*self).try_into().ok()
237 }
238 }
239
240 impl UsizeTag for NonZero<$n> {
241 fn from_usize(n: usize) -> Self {
242 Self::new(
243 n.checked_add(1)
244 .expect("discriminant out of range")
245 .try_into()
246 .expect("discriminant out of range"),
247 )
248 .unwrap()
249 }
250 fn to_usize(&self) -> usize {
251 usize::try_from(self.get())
252 .expect("discriminant out of range")
253 .checked_sub(1)
254 .unwrap()
255 }
256 fn try_to_usize(&self) -> Option<usize> {
257 usize::try_from(self.get()).ok()?.checked_sub(1)
258 }
259 }
260
261 impl AsLe for $n {
262 type Le = Le<$n>;
263 fn construct(self) -> Self::Le {
264 Le(self)
265 }
266 }
267
268 impl AsLe for NonZero<$n> {
269 type Le = Nz<Le<$n>>;
270 fn construct(self) -> Self::Le {
271 Nz(self)
272 }
273 }
274
275 impl AsBe for $n {
276 type Be = Be<$n>;
277 fn construct(self) -> Self::Be {
278 Be(self)
279 }
280 }
281
282 impl AsBe for NonZero<$n> {
283 type Be = Nz<Be<$n>>;
284 fn construct(self) -> Self::Be {
285 Nz(self)
286 }
287 }
288
289 impl NonZeroable for Le<$n> {
290 type Nz = NonZero<$n>;
291 fn to_nz(&self) -> Option<Self::Nz> {
292 NonZero::new(self.0)
293 }
294 fn from_nz(nz: &Self::Nz) -> Self {
295 Self(nz.get())
296 }
297 }
298
299 impl NonZeroable for Be<$n> {
300 type Nz = NonZero<$n>;
301 fn to_nz(&self) -> Option<Self::Nz> {
302 NonZero::new(self.0)
303 }
304 fn from_nz(nz: &Self::Nz) -> Self {
305 Self(nz.get())
306 }
307 }
308
309 impl From<NonZero<$n>> for Nz<Le<$n>> {
310 fn from(nz: NonZero<$n>) -> Self {
311 Self(nz)
312 }
313 }
314
315 impl From<NonZero<$n>> for Nz<Be<$n>> {
316 fn from(nz: NonZero<$n>) -> Self {
317 Self(nz)
318 }
319 }
320
321 impl ToOutput for Le<$n> {
322 fn to_output(&self, output: &mut dyn Output) {
323 output.write(&self.0.to_le_bytes());
324 }
325 }
326
327 impl ToOutput for Be<$n> {
328 fn to_output(&self, output: &mut dyn Output) {
329 output.write(&self.0.to_be_bytes());
330 }
331 }
332
333 impl<I: ParseInput> ParseInline<I> for Le<$n> {
334 fn parse_inline(input: &mut I) -> crate::Result<Self> {
335 Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
336 }
337 }
338
339 impl<I: ParseInput> ParseInline<I> for Be<$n> {
340 fn parse_inline(input: &mut I) -> crate::Result<Self> {
341 Ok(Self(<$n>::from_be_bytes(*input.parse_chunk()?)))
342 }
343 }
344
345 impl Size for Le<$n> {
346 const SIZE: usize = std::mem::size_of::<$n>();
347 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
348 }
349
350 impl Size for Be<$n> {
351 const SIZE: usize = std::mem::size_of::<$n>();
352 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
353 }
354
355 impl MaybeHasNiche for Le<$n> {
356 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
357 }
358
359 impl MaybeHasNiche for Be<$n> {
360 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
361 }
362
363 impl Topological for Le<$n> {}
364 impl Topological for Be<$n> {}
365 impl Tagged for Le<$n> {}
366 impl Tagged for Be<$n> {}
367 impl ReflessObject for Le<$n> {}
368 impl ReflessObject for Be<$n> {}
369 impl ReflessInline for Le<$n> {}
370 impl ReflessInline for Be<$n> {}
371 impl Object for Le<$n> {}
372 impl Object for Be<$n> {}
373 impl Inline for Le<$n> {}
374 impl Inline for Be<$n> {}
375
376 impl Equivalent<Le<$n>> for Option<Le<NonZero<$n>>> {
377 fn into_equivalent(self) -> Le<$n> {
378 Le(self.map(|object| object.0.get()).unwrap_or_default())
379 }
380 fn from_equivalent(object: Le<$n>) -> Self {
381 NonZero::new(object.0).map(Le)
382 }
383 }
384
385 impl Equivalent<Be<$n>> for Option<Be<NonZero<$n>>> {
386 fn into_equivalent(self) -> Be<$n> {
387 Be(self.map(|object| object.0.get()).unwrap_or_default())
388 }
389 fn from_equivalent(object: Be<$n>) -> Self {
390 NonZero::new(object.0).map(Be)
391 }
392 }
393
394 impl Equivalent<Le<Os<$n>>> for Le<$n> {
395 fn into_equivalent(self) -> Le<Os<$n>> {
396 Le(self.0 as _)
397 }
398 fn from_equivalent(object: Le<Os<$n>>) -> Self {
399 Le(object.0 as _)
400 }
401 }
402
403 impl Equivalent<Be<Os<$n>>> for Be<$n> {
404 fn into_equivalent(self) -> Be<Os<$n>> {
405 Be(self.0 as _)
406 }
407 fn from_equivalent(object: Be<Os<$n>>) -> Self {
408 Be(object.0 as _)
409 }
410 }
411
412 impl Equivalent<Le<NonZero<Os<$n>>>> for Le<NonZero<$n>> {
413 fn into_equivalent(self) -> Le<NonZero<Os<$n>>> {
414 Le(NonZero::new(self.0.get() as _).unwrap())
415 }
416 fn from_equivalent(object: Le<NonZero<Os<$n>>>) -> Self {
417 Le(NonZero::new(object.0.get() as _).unwrap())
418 }
419 }
420
421 impl Equivalent<Be<NonZero<Os<$n>>>> for Be<NonZero<$n>> {
422 fn into_equivalent(self) -> Be<NonZero<Os<$n>>> {
423 Be(NonZero::new(self.0.get() as _).unwrap())
424 }
425 fn from_equivalent(object: Be<NonZero<Os<$n>>>) -> Self {
426 Be(NonZero::new(object.0.get() as _).unwrap())
427 }
428 }
429 };
430}
431
432signs!(u8, i8);
433signs!(u16, i16);
434signs!(u32, i32);
435signs!(u64, i64);
436signs!(u128, i128);
437
438ae!(u8);
439ae!(i8);
440
441lebe!(u16);
442lebe!(i16);
443
444lebe!(u32);
445lebe!(i32);
446
447lebe!(u64);
448lebe!(i64);
449
450lebe!(u128);
451lebe!(i128);
452
453impl<T: NonZeroable> Deref for Nz<T> {
454 type Target = T::Nz;
455
456 fn deref(&self) -> &Self::Target {
457 &self.0
458 }
459}
460
461impl<T: NonZeroable + ToOutput> ToOutput for Nz<T> {
462 fn to_output(&self, output: &mut dyn Output) {
463 T::from_nz(&self.0).to_output(output);
464 }
465}
466
467impl<T: NonZeroable + ParseInline<I>, I: ParseInput> ParseInline<I> for Nz<T> {
468 fn parse_inline(input: &mut I) -> crate::Result<Self> {
469 Ok(Self(T::parse_inline(input)?.to_nz().ok_or(Error::Zero)?))
470 }
471}
472
473impl<T: NonZeroable + Size> Size for Nz<T> {
474 type Size = T::Size;
475}
476
477impl<T: NonZeroable + Size> MaybeHasNiche for Nz<T> {
478 type MnArray = SomeNiche<ZeroNiche<T::Size>>;
479}
480
481impl<T: NonZeroable> Topological for Nz<T> {}
482impl<T: NonZeroable> Tagged for Nz<T> {}
483impl<T: NonZeroable + ReflessInline> ReflessObject for Nz<T> {}
484impl<T: NonZeroable + ReflessInline> ReflessInline for Nz<T> {}
485impl<T: NonZeroable + Inline> Object for Nz<T> {}
486impl<T: NonZeroable + Inline> Inline for Nz<T> {}
487
488#[test]
489fn nonzero() {
490 assert_eq!(Option::<Ae<u8>>::SIZE, 2);
491 assert_eq!(Option::<Nz<Ae<u8>>>::SIZE, 1);
492 assert_eq!(Option::<Le<u16>>::SIZE, 3);
493 assert_eq!(Option::<Nz<Le<u16>>>::SIZE, 2);
494}