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