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, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
12pub struct Ae<T>(pub T);
13#[derive(ParseAsInline, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
14pub struct Le<T>(pub T);
15#[derive(ParseAsInline, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
16pub struct Be<T>(pub T);
17#[derive(ParseAsInline, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
18pub struct Nz<T: NonZeroable>(pub 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<E: 'static> Object<E> for Ae<$n> {}
195 impl<E: 'static> Inline<E> 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<E: 'static> Object<E> for Le<$n> {}
372 impl<E: 'static> Object<E> for Be<$n> {}
373 impl<E: 'static> Inline<E> for Le<$n> {}
374 impl<E: 'static> Inline<E> 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
432macro_rules! float {
433 ($n:ty) => {
434 impl AsLe for $n {
435 type Le = Le<$n>;
436 fn construct(self) -> Self::Le {
437 Le(self)
438 }
439 }
440
441 impl AsBe for $n {
442 type Be = Be<$n>;
443 fn construct(self) -> Self::Be {
444 Be(self)
445 }
446 }
447
448 impl ToOutput for Le<$n> {
449 fn to_output(&self, output: &mut dyn Output) {
450 output.write(&self.0.to_le_bytes());
451 }
452 }
453
454 impl ToOutput for Be<$n> {
455 fn to_output(&self, output: &mut dyn Output) {
456 output.write(&self.0.to_be_bytes());
457 }
458 }
459
460 impl<I: ParseInput> ParseInline<I> for Le<$n> {
461 fn parse_inline(input: &mut I) -> crate::Result<Self> {
462 Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
463 }
464 }
465
466 impl<I: ParseInput> ParseInline<I> for Be<$n> {
467 fn parse_inline(input: &mut I) -> crate::Result<Self> {
468 Ok(Self(<$n>::from_be_bytes(*input.parse_chunk()?)))
469 }
470 }
471
472 impl Size for Le<$n> {
473 const SIZE: usize = std::mem::size_of::<$n>();
474 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
475 }
476
477 impl Size for Be<$n> {
478 const SIZE: usize = std::mem::size_of::<$n>();
479 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
480 }
481
482 impl MaybeHasNiche for Le<$n> {
483 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
484 }
485
486 impl MaybeHasNiche for Be<$n> {
487 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
488 }
489
490 impl Topological for Le<$n> {}
491 impl Topological for Be<$n> {}
492 impl Tagged for Le<$n> {}
493 impl Tagged for Be<$n> {}
494 impl ReflessObject for Le<$n> {}
495 impl ReflessObject for Be<$n> {}
496 impl ReflessInline for Le<$n> {}
497 impl ReflessInline for Be<$n> {}
498 impl<E: 'static> Object<E> for Le<$n> {}
499 impl<E: 'static> Object<E> for Be<$n> {}
500 impl<E: 'static> Inline<E> for Le<$n> {}
501 impl<E: 'static> Inline<E> for Be<$n> {}
502 };
503}
504
505signs!(u8, i8);
506signs!(u16, i16);
507signs!(u32, i32);
508signs!(u64, i64);
509signs!(u128, i128);
510
511ae!(u8);
512ae!(i8);
513
514lebe!(u16);
515lebe!(i16);
516
517lebe!(u32);
518lebe!(i32);
519
520lebe!(u64);
521lebe!(i64);
522
523lebe!(u128);
524lebe!(i128);
525
526float!(f32);
527float!(f64);
528
529impl<T: NonZeroable> Deref for Nz<T> {
530 type Target = T::Nz;
531
532 fn deref(&self) -> &Self::Target {
533 &self.0
534 }
535}
536
537impl<T: NonZeroable + ToOutput> ToOutput for Nz<T> {
538 fn to_output(&self, output: &mut dyn Output) {
539 T::from_nz(&self.0).to_output(output);
540 }
541}
542
543impl<T: NonZeroable + ParseInline<I>, I: ParseInput> ParseInline<I> for Nz<T> {
544 fn parse_inline(input: &mut I) -> crate::Result<Self> {
545 Ok(Self(T::parse_inline(input)?.to_nz().ok_or(Error::Zero)?))
546 }
547}
548
549impl<T: NonZeroable + Size> Size for Nz<T> {
550 type Size = T::Size;
551}
552
553impl<T: NonZeroable + Size> MaybeHasNiche for Nz<T> {
554 type MnArray = SomeNiche<ZeroNiche<T::Size>>;
555}
556
557impl<T: NonZeroable> Topological for Nz<T> {}
558impl<T: NonZeroable> Tagged for Nz<T> {}
559impl<T: NonZeroable + ReflessInline> ReflessObject for Nz<T> {}
560impl<T: NonZeroable + ReflessInline> ReflessInline for Nz<T> {}
561impl<T: NonZeroable + Inline<E>, E: 'static> Object<E> for Nz<T> {}
562impl<T: NonZeroable + Inline<E>, E: 'static> Inline<E> for Nz<T> {}
563
564#[test]
565fn nonzero() {
566 assert_eq!(Option::<Ae<u8>>::SIZE, 2);
567 assert_eq!(Option::<Nz<Ae<u8>>>::SIZE, 1);
568 assert_eq!(Option::<Le<u16>>::SIZE, 3);
569 assert_eq!(Option::<Nz<Le<u16>>>::SIZE, 2);
570}
571
572impl<T: UsizeTag> UsizeTag for Ae<T> {
573 fn from_usize(n: usize) -> Self {
574 Self(UsizeTag::from_usize(n))
575 }
576
577 fn to_usize(&self) -> usize {
578 self.0.to_usize()
579 }
580
581 fn try_to_usize(&self) -> Option<usize> {
582 self.0.try_to_usize()
583 }
584}
585
586impl<T: UsizeTag> UsizeTag for Le<T> {
587 fn from_usize(n: usize) -> Self {
588 Self(UsizeTag::from_usize(n))
589 }
590
591 fn to_usize(&self) -> usize {
592 self.0.to_usize()
593 }
594
595 fn try_to_usize(&self) -> Option<usize> {
596 self.0.try_to_usize()
597 }
598}
599
600impl<T: UsizeTag> UsizeTag for Be<T> {
601 fn from_usize(n: usize) -> Self {
602 Self(UsizeTag::from_usize(n))
603 }
604
605 fn to_usize(&self) -> usize {
606 self.0.to_usize()
607 }
608
609 fn try_to_usize(&self) -> Option<usize> {
610 self.0.try_to_usize()
611 }
612}
613
614impl<T: NonZeroable<Nz: UsizeTag>> UsizeTag for Nz<T> {
615 fn from_usize(n: usize) -> Self {
616 Self(UsizeTag::from_usize(n))
617 }
618
619 fn to_usize(&self) -> usize {
620 self.0.to_usize()
621 }
622
623 fn try_to_usize(&self) -> Option<usize> {
624 self.0.try_to_usize()
625 }
626}