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)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Ae<T>(pub T);
14#[derive(ParseAsInline, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub struct Le<T>(pub T);
17#[derive(ParseAsInline, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub struct Be<T>(pub T);
20#[derive(ParseAsInline, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22pub struct Nz<T: NonZeroable>(pub T::Nz);
23
24pub trait NonZeroable {
25 type Nz: Send + Sync;
26 fn to_nz(&self) -> Option<Self::Nz>;
27 fn from_nz(nz: &Self::Nz) -> Self;
28}
29
30impl<T> From<T> for Ae<T> {
31 fn from(n: T) -> Self {
32 Self(n)
33 }
34}
35
36impl<T> From<T> for Be<T> {
37 fn from(n: T) -> Self {
38 Self(n)
39 }
40}
41
42impl<T> From<T> for Le<T> {
43 fn from(n: T) -> Self {
44 Self(n)
45 }
46}
47
48impl<T> Deref for Ae<T> {
49 type Target = T;
50
51 fn deref(&self) -> &Self::Target {
52 &self.0
53 }
54}
55
56impl<T> Deref for Le<T> {
57 type Target = T;
58
59 fn deref(&self) -> &Self::Target {
60 &self.0
61 }
62}
63
64impl<T> Deref for Be<T> {
65 type Target = T;
66
67 fn deref(&self) -> &Self::Target {
68 &self.0
69 }
70}
71
72pub trait AsLe {
73 type Le;
74 fn construct(self) -> Self::Le;
75}
76
77pub trait AsBe {
78 type Be;
79 fn construct(self) -> Self::Be;
80}
81
82macro_rules! signs {
83 ($u:ty, $i:ty) => {
84 impl HasOtherSign for $u {
85 type OtherSign = $i;
86 }
87 impl HasOtherSign for $i {
88 type OtherSign = $u;
89 }
90 };
91}
92
93macro_rules! ae {
94 ($n:ty) => {
95 impl UsizeTag for $n {
96 fn from_usize(n: usize) -> Self {
97 n.try_into().expect("discriminant out of range")
98 }
99 fn to_usize(&self) -> usize {
100 (*self).try_into().expect("discriminant out of range")
101 }
102 fn try_to_usize(&self) -> Option<usize> {
103 (*self).try_into().ok()
104 }
105 }
106
107 impl UsizeTag for NonZero<$n> {
108 fn from_usize(n: usize) -> Self {
109 Self::new(
110 n.checked_add(1)
111 .expect("discriminant out of range")
112 .try_into()
113 .expect("discriminant out of range"),
114 )
115 .unwrap()
116 }
117 fn to_usize(&self) -> usize {
118 usize::try_from(self.get())
119 .expect("discriminant out of range")
120 .checked_sub(1)
121 .unwrap()
122 }
123 fn try_to_usize(&self) -> Option<usize> {
124 usize::try_from(self.get()).ok()?.checked_sub(1)
125 }
126 }
127
128 impl AsLe for $n {
129 type Le = Ae<$n>;
130 fn construct(self) -> Self::Le {
131 Ae(self)
132 }
133 }
134
135 impl AsLe for NonZero<$n> {
136 type Le = Nz<Ae<$n>>;
137 fn construct(self) -> Self::Le {
138 Nz(self)
139 }
140 }
141
142 impl AsBe for $n {
143 type Be = Ae<$n>;
144 fn construct(self) -> Self::Be {
145 Ae(self)
146 }
147 }
148
149 impl AsBe for NonZero<$n> {
150 type Be = Nz<Ae<$n>>;
151 fn construct(self) -> Self::Be {
152 Nz(self)
153 }
154 }
155
156 impl From<NonZero<$n>> for Nz<Ae<$n>> {
157 fn from(nz: NonZero<$n>) -> Self {
158 Self(nz)
159 }
160 }
161
162 impl NonZeroable for Ae<$n> {
163 type Nz = NonZero<$n>;
164 fn to_nz(&self) -> Option<Self::Nz> {
165 NonZero::new(self.0)
166 }
167 fn from_nz(nz: &Self::Nz) -> Self {
168 Self(nz.get())
169 }
170 }
171
172 impl ToOutput for Ae<$n> {
173 fn to_output(&self, output: &mut dyn Output) {
174 output.write(&self.0.to_le_bytes());
175 }
176 }
177
178 impl InlineOutput for Ae<$n> {}
179
180 impl<I: ParseInput> ParseInline<I> for Ae<$n> {
181 fn parse_inline(input: &mut I) -> crate::Result<Self> {
182 Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
183 }
184 }
185
186 impl Size for Ae<$n> {
187 const SIZE: usize = std::mem::size_of::<$n>();
188 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
189 }
190
191 impl MaybeHasNiche for Ae<$n> {
192 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
193 }
194
195 impl ListHashes for Ae<$n> {}
196 impl Topological for Ae<$n> {}
197 impl Tagged for Ae<$n> {}
198 impl Tagged for Ae<NonZero<$n>> {}
199
200 impl Equivalent<Ae<$n>> for Option<Ae<NonZero<$n>>> {
201 fn into_equivalent(self) -> Ae<$n> {
202 Ae(self.map(|object| object.0.get()).unwrap_or_default())
203 }
204 fn from_equivalent(object: Ae<$n>) -> Self {
205 NonZero::new(object.0).map(Ae)
206 }
207 }
208
209 impl Equivalent<Ae<Os<$n>>> for Ae<$n> {
210 fn into_equivalent(self) -> Ae<Os<$n>> {
211 Ae(self.0 as _)
212 }
213 fn from_equivalent(object: Ae<Os<$n>>) -> Self {
214 Ae(object.0 as _)
215 }
216 }
217
218 impl Equivalent<Ae<NonZero<Os<$n>>>> for Ae<NonZero<$n>> {
219 fn into_equivalent(self) -> Ae<NonZero<Os<$n>>> {
220 Ae(NonZero::new(self.0.get() as _).unwrap())
221 }
222 fn from_equivalent(object: Ae<NonZero<Os<$n>>>) -> Self {
223 Ae(NonZero::new(object.0.get() as _).unwrap())
224 }
225 }
226 };
227}
228
229macro_rules! lebe {
230 ($n:ty) => {
231 impl UsizeTag for $n {
232 fn from_usize(n: usize) -> Self {
233 n.try_into().expect("discriminant out of range")
234 }
235 fn to_usize(&self) -> usize {
236 (*self).try_into().expect("discriminant out of range")
237 }
238 fn try_to_usize(&self) -> Option<usize> {
239 (*self).try_into().ok()
240 }
241 }
242
243 impl UsizeTag for NonZero<$n> {
244 fn from_usize(n: usize) -> Self {
245 Self::new(
246 n.checked_add(1)
247 .expect("discriminant out of range")
248 .try_into()
249 .expect("discriminant out of range"),
250 )
251 .unwrap()
252 }
253 fn to_usize(&self) -> usize {
254 usize::try_from(self.get())
255 .expect("discriminant out of range")
256 .checked_sub(1)
257 .unwrap()
258 }
259 fn try_to_usize(&self) -> Option<usize> {
260 usize::try_from(self.get()).ok()?.checked_sub(1)
261 }
262 }
263
264 impl AsLe for $n {
265 type Le = Le<$n>;
266 fn construct(self) -> Self::Le {
267 Le(self)
268 }
269 }
270
271 impl AsLe for NonZero<$n> {
272 type Le = Nz<Le<$n>>;
273 fn construct(self) -> Self::Le {
274 Nz(self)
275 }
276 }
277
278 impl AsBe for $n {
279 type Be = Be<$n>;
280 fn construct(self) -> Self::Be {
281 Be(self)
282 }
283 }
284
285 impl AsBe for NonZero<$n> {
286 type Be = Nz<Be<$n>>;
287 fn construct(self) -> Self::Be {
288 Nz(self)
289 }
290 }
291
292 impl NonZeroable for Le<$n> {
293 type Nz = NonZero<$n>;
294 fn to_nz(&self) -> Option<Self::Nz> {
295 NonZero::new(self.0)
296 }
297 fn from_nz(nz: &Self::Nz) -> Self {
298 Self(nz.get())
299 }
300 }
301
302 impl NonZeroable for Be<$n> {
303 type Nz = NonZero<$n>;
304 fn to_nz(&self) -> Option<Self::Nz> {
305 NonZero::new(self.0)
306 }
307 fn from_nz(nz: &Self::Nz) -> Self {
308 Self(nz.get())
309 }
310 }
311
312 impl From<NonZero<$n>> for Nz<Le<$n>> {
313 fn from(nz: NonZero<$n>) -> Self {
314 Self(nz)
315 }
316 }
317
318 impl From<NonZero<$n>> for Nz<Be<$n>> {
319 fn from(nz: NonZero<$n>) -> Self {
320 Self(nz)
321 }
322 }
323
324 impl ToOutput for Le<$n> {
325 fn to_output(&self, output: &mut dyn Output) {
326 output.write(&self.0.to_le_bytes());
327 }
328 }
329
330 impl ToOutput for Be<$n> {
331 fn to_output(&self, output: &mut dyn Output) {
332 output.write(&self.0.to_be_bytes());
333 }
334 }
335
336 impl InlineOutput for Le<$n> {}
337 impl InlineOutput for Be<$n> {}
338
339 impl<I: ParseInput> ParseInline<I> for Le<$n> {
340 fn parse_inline(input: &mut I) -> crate::Result<Self> {
341 Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
342 }
343 }
344
345 impl<I: ParseInput> ParseInline<I> for Be<$n> {
346 fn parse_inline(input: &mut I) -> crate::Result<Self> {
347 Ok(Self(<$n>::from_be_bytes(*input.parse_chunk()?)))
348 }
349 }
350
351 impl Size for Le<$n> {
352 const SIZE: usize = std::mem::size_of::<$n>();
353 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
354 }
355
356 impl Size for Be<$n> {
357 const SIZE: usize = std::mem::size_of::<$n>();
358 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
359 }
360
361 impl MaybeHasNiche for Le<$n> {
362 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
363 }
364
365 impl MaybeHasNiche for Be<$n> {
366 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
367 }
368
369 impl ListHashes for Le<$n> {}
370 impl ListHashes for Be<$n> {}
371 impl Topological for Le<$n> {}
372 impl Topological for Be<$n> {}
373 impl Tagged for Le<$n> {}
374 impl Tagged 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 InlineOutput for Le<$n> {}
461 impl InlineOutput for Be<$n> {}
462
463 impl<I: ParseInput> ParseInline<I> for Le<$n> {
464 fn parse_inline(input: &mut I) -> crate::Result<Self> {
465 Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
466 }
467 }
468
469 impl<I: ParseInput> ParseInline<I> for Be<$n> {
470 fn parse_inline(input: &mut I) -> crate::Result<Self> {
471 Ok(Self(<$n>::from_be_bytes(*input.parse_chunk()?)))
472 }
473 }
474
475 impl Size for Le<$n> {
476 const SIZE: usize = std::mem::size_of::<$n>();
477 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
478 }
479
480 impl Size for Be<$n> {
481 const SIZE: usize = std::mem::size_of::<$n>();
482 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
483 }
484
485 impl MaybeHasNiche for Le<$n> {
486 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
487 }
488
489 impl MaybeHasNiche for Be<$n> {
490 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
491 }
492
493 impl ListHashes for Le<$n> {}
494 impl ListHashes for Be<$n> {}
495 impl Topological for Le<$n> {}
496 impl Topological for Be<$n> {}
497 impl Tagged for Le<$n> {}
498 impl Tagged for Be<$n> {}
499 };
500}
501
502signs!(u8, i8);
503signs!(u16, i16);
504signs!(u32, i32);
505signs!(u64, i64);
506signs!(u128, i128);
507
508ae!(u8);
509ae!(i8);
510
511lebe!(u16);
512lebe!(i16);
513
514lebe!(u32);
515lebe!(i32);
516
517lebe!(u64);
518lebe!(i64);
519
520lebe!(u128);
521lebe!(i128);
522
523float!(f32);
524float!(f64);
525
526impl<T: NonZeroable> Deref for Nz<T> {
527 type Target = T::Nz;
528
529 fn deref(&self) -> &Self::Target {
530 &self.0
531 }
532}
533
534impl<T: NonZeroable + ToOutput> ToOutput for Nz<T> {
535 fn to_output(&self, output: &mut dyn Output) {
536 T::from_nz(&self.0).to_output(output);
537 }
538}
539
540impl<T: NonZeroable + InlineOutput> InlineOutput for Nz<T> {}
541
542impl<T: NonZeroable + ParseInline<I>, I: ParseInput> ParseInline<I> for Nz<T> {
543 fn parse_inline(input: &mut I) -> crate::Result<Self> {
544 Ok(Self(T::parse_inline(input)?.to_nz().ok_or(Error::Zero)?))
545 }
546}
547
548impl<T: NonZeroable + Size> Size for Nz<T> {
549 type Size = T::Size;
550}
551
552impl<T: NonZeroable + Size> MaybeHasNiche for Nz<T> {
553 type MnArray = SomeNiche<ZeroNiche<T::Size>>;
554}
555
556impl<T: NonZeroable> ListHashes for Nz<T> {}
557impl<T: NonZeroable> Topological for Nz<T> {}
558impl<T: NonZeroable> Tagged for Nz<T> {}
559
560#[test]
561fn nonzero() {
562 assert_eq!(Option::<Ae<u8>>::SIZE, 2);
563 assert_eq!(Option::<Nz<Ae<u8>>>::SIZE, 1);
564 assert_eq!(Option::<Le<u16>>::SIZE, 3);
565 assert_eq!(Option::<Nz<Le<u16>>>::SIZE, 2);
566}
567
568impl<T: UsizeTag> UsizeTag for Ae<T> {
569 fn from_usize(n: usize) -> Self {
570 Self(UsizeTag::from_usize(n))
571 }
572
573 fn to_usize(&self) -> usize {
574 self.0.to_usize()
575 }
576
577 fn try_to_usize(&self) -> Option<usize> {
578 self.0.try_to_usize()
579 }
580}
581
582impl<T: UsizeTag> UsizeTag for Le<T> {
583 fn from_usize(n: usize) -> Self {
584 Self(UsizeTag::from_usize(n))
585 }
586
587 fn to_usize(&self) -> usize {
588 self.0.to_usize()
589 }
590
591 fn try_to_usize(&self) -> Option<usize> {
592 self.0.try_to_usize()
593 }
594}
595
596impl<T: UsizeTag> UsizeTag for Be<T> {
597 fn from_usize(n: usize) -> Self {
598 Self(UsizeTag::from_usize(n))
599 }
600
601 fn to_usize(&self) -> usize {
602 self.0.to_usize()
603 }
604
605 fn try_to_usize(&self) -> Option<usize> {
606 self.0.try_to_usize()
607 }
608}
609
610impl<T: NonZeroable<Nz: UsizeTag>> UsizeTag for Nz<T> {
611 fn from_usize(n: usize) -> Self {
612 Self(UsizeTag::from_usize(n))
613 }
614
615 fn to_usize(&self) -> usize {
616 self.0.to_usize()
617 }
618
619 fn try_to_usize(&self) -> Option<usize> {
620 self.0.try_to_usize()
621 }
622}