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, 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> Le<T> {
19 pub const fn new(value: T) -> Self {
20 Self(value)
21 }
22}
23
24impl<T> Be<T> {
25 pub const fn new(value: T) -> Self {
26 Self(value)
27 }
28}
29
30impl<T> From<T> for Be<T> {
31 fn from(n: T) -> Self {
32 Self(n)
33 }
34}
35
36impl<T> From<T> for Le<T> {
37 fn from(n: T) -> Self {
38 Self(n)
39 }
40}
41
42impl<T> Deref for Le<T> {
43 type Target = T;
44
45 fn deref(&self) -> &Self::Target {
46 &self.0
47 }
48}
49
50impl<T> Deref for Be<T> {
51 type Target = T;
52
53 fn deref(&self) -> &Self::Target {
54 &self.0
55 }
56}
57
58pub trait AsLe {
59 type Le;
60 fn construct(self) -> Self::Le;
61}
62
63pub trait AsBe {
64 type Be;
65 fn construct(self) -> Self::Be;
66}
67
68macro_rules! signs {
69 ($u:ty, $i:ty) => {
70 impl HasOtherSign for $u {
71 type OtherSign = $i;
72 }
73 impl HasOtherSign for $i {
74 type OtherSign = $u;
75 }
76 };
77}
78
79macro_rules! ae {
80 ($n:ty) => {
81 impl UsizeTag for $n {
82 fn from_usize(n: usize) -> Self {
83 n.try_into().expect("discriminant out of range")
84 }
85 fn to_usize(&self) -> usize {
86 (*self).try_into().expect("discriminant out of range")
87 }
88 fn try_to_usize(&self) -> Option<usize> {
89 (*self).try_into().ok()
90 }
91 }
92
93 impl UsizeTag for NonZero<$n> {
94 fn from_usize(n: usize) -> Self {
95 Self::new(
96 n.checked_add(1)
97 .expect("discriminant out of range")
98 .try_into()
99 .expect("discriminant out of range"),
100 )
101 .unwrap()
102 }
103 fn to_usize(&self) -> usize {
104 usize::try_from(self.get())
105 .expect("discriminant out of range")
106 .checked_sub(1)
107 .unwrap()
108 }
109 fn try_to_usize(&self) -> Option<usize> {
110 usize::try_from(self.get()).ok()?.checked_sub(1)
111 }
112 }
113
114 impl AsLe for $n {
115 type Le = Self;
116 fn construct(self) -> Self::Le {
117 self
118 }
119 }
120
121 impl AsLe for NonZero<$n> {
122 type Le = Self;
123 fn construct(self) -> Self::Le {
124 self
125 }
126 }
127
128 impl AsBe for $n {
129 type Be = Self;
130 fn construct(self) -> Self::Be {
131 self
132 }
133 }
134
135 impl AsBe for NonZero<$n> {
136 type Be = Self;
137 fn construct(self) -> Self::Be {
138 self
139 }
140 }
141
142 impl ToOutput for NonZero<$n> {
143 fn to_output(&self, output: &mut dyn crate::Output) {
144 self.get().to_output(output);
145 }
146 }
147
148 impl<I: ParseInput> Parse<I> for NonZero<$n> {
149 fn parse(input: I) -> crate::Result<Self> {
150 ParseInline::parse_as_inline(input)
151 }
152 }
153
154 impl<I: ParseInput> ParseInline<I> for NonZero<$n> {
155 fn parse_inline(input: &mut I) -> crate::Result<Self> {
156 NonZero::new(input.parse_inline::<$n>()?).ok_or(Error::Zero)
157 }
158 }
159
160 impl Size for NonZero<$n> {
161 const SIZE: usize = <$n as Size>::SIZE;
162 type Size = <$n as Size>::Size;
163 }
164
165 impl MaybeHasNiche for $n {
166 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
167 }
168
169 impl MaybeHasNiche for NonZero<$n> {
170 type MnArray = SomeNiche<ZeroNiche<<Self as Size>::Size>>;
171 }
172
173 impl Tagged for $n {}
174 impl Tagged for NonZero<$n> {}
175 impl ListHashes for $n {}
176 impl ListHashes for NonZero<$n> {}
177 impl Topological for $n {}
178 impl Topological for NonZero<$n> {}
179
180 impl Equivalent<$n> for Option<NonZero<$n>> {
181 fn into_equivalent(self) -> $n {
182 self.map(NonZero::get).unwrap_or_default()
183 }
184 fn from_equivalent(object: $n) -> Self {
185 NonZero::new(object)
186 }
187 }
188
189 impl Equivalent<Os<$n>> for $n {
190 fn into_equivalent(self) -> Os<$n> {
191 self as _
192 }
193 fn from_equivalent(object: Os<$n>) -> Self {
194 object as _
195 }
196 }
197
198 impl Equivalent<NonZero<Os<$n>>> for NonZero<$n> {
199 fn into_equivalent(self) -> NonZero<Os<$n>> {
200 NonZero::new(self.get() as _).unwrap()
201 }
202 fn from_equivalent(object: NonZero<Os<$n>>) -> Self {
203 NonZero::new(object.get() as _).unwrap()
204 }
205 }
206 };
207}
208
209macro_rules! lebe {
210 ($n:ty) => {
211 impl UsizeTag for $n {
212 fn from_usize(n: usize) -> Self {
213 n.try_into().expect("discriminant out of range")
214 }
215 fn to_usize(&self) -> usize {
216 (*self).try_into().expect("discriminant out of range")
217 }
218 fn try_to_usize(&self) -> Option<usize> {
219 (*self).try_into().ok()
220 }
221 }
222
223 impl UsizeTag for NonZero<$n> {
224 fn from_usize(n: usize) -> Self {
225 Self::new(
226 n.checked_add(1)
227 .expect("discriminant out of range")
228 .try_into()
229 .expect("discriminant out of range"),
230 )
231 .unwrap()
232 }
233 fn to_usize(&self) -> usize {
234 usize::try_from(self.get())
235 .expect("discriminant out of range")
236 .checked_sub(1)
237 .unwrap()
238 }
239 fn try_to_usize(&self) -> Option<usize> {
240 usize::try_from(self.get()).ok()?.checked_sub(1)
241 }
242 }
243
244 impl AsLe for $n {
245 type Le = Le<$n>;
246 fn construct(self) -> Self::Le {
247 Le(self)
248 }
249 }
250
251 impl AsLe for NonZero<$n> {
252 type Le = Le<NonZero<$n>>;
253 fn construct(self) -> Self::Le {
254 Le(self)
255 }
256 }
257
258 impl AsBe for $n {
259 type Be = Be<$n>;
260 fn construct(self) -> Self::Be {
261 Be(self)
262 }
263 }
264
265 impl AsBe for NonZero<$n> {
266 type Be = Be<NonZero<$n>>;
267 fn construct(self) -> Self::Be {
268 Be(self)
269 }
270 }
271
272 impl ToOutput for Le<$n> {
273 fn to_output(&self, output: &mut dyn Output) {
274 output.write(&self.0.to_le_bytes());
275 }
276 }
277
278 impl ToOutput for Be<$n> {
279 fn to_output(&self, output: &mut dyn Output) {
280 output.write(&self.0.to_be_bytes());
281 }
282 }
283
284 impl ToOutput for Le<NonZero<$n>> {
285 fn to_output(&self, output: &mut dyn Output) {
286 output.write(&self.0.get().to_le_bytes());
287 }
288 }
289
290 impl ToOutput for Be<NonZero<$n>> {
291 fn to_output(&self, output: &mut dyn Output) {
292 output.write(&self.0.get().to_be_bytes());
293 }
294 }
295
296 impl InlineOutput for Le<$n> {}
297 impl InlineOutput for Be<$n> {}
298
299 impl<I: ParseInput> ParseInline<I> for Le<$n> {
300 fn parse_inline(input: &mut I) -> crate::Result<Self> {
301 Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
302 }
303 }
304
305 impl<I: ParseInput> ParseInline<I> for Be<$n> {
306 fn parse_inline(input: &mut I) -> crate::Result<Self> {
307 Ok(Self(<$n>::from_be_bytes(*input.parse_chunk()?)))
308 }
309 }
310
311 impl<I: ParseInput> ParseInline<I> for Le<NonZero<$n>> {
312 fn parse_inline(input: &mut I) -> crate::Result<Self> {
313 NonZero::new(input.parse_inline::<Le<$n>>()?.0)
314 .ok_or(Error::Zero)
315 .map(Le)
316 }
317 }
318
319 impl<I: ParseInput> ParseInline<I> for Be<NonZero<$n>> {
320 fn parse_inline(input: &mut I) -> crate::Result<Self> {
321 NonZero::new(input.parse_inline::<Be<$n>>()?.0)
322 .ok_or(Error::Zero)
323 .map(Be)
324 }
325 }
326
327 impl Size for Le<$n> {
328 const SIZE: usize = std::mem::size_of::<$n>();
329 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
330 }
331
332 impl Size for Be<$n> {
333 const SIZE: usize = std::mem::size_of::<$n>();
334 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
335 }
336
337 impl MaybeHasNiche for Le<$n> {
338 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
339 }
340
341 impl MaybeHasNiche for Be<$n> {
342 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
343 }
344
345 impl MaybeHasNiche for Le<NonZero<$n>> {
346 type MnArray = SomeNiche<ZeroNiche<<Self as Size>::Size>>;
347 }
348
349 impl MaybeHasNiche for Be<NonZero<$n>> {
350 type MnArray = SomeNiche<ZeroNiche<<Self as Size>::Size>>;
351 }
352
353 impl Tagged for Le<$n> {}
354 impl Tagged for Le<NonZero<$n>> {}
355 impl Tagged for Be<$n> {}
356 impl Tagged for Be<NonZero<$n>> {}
357 impl ListHashes for Le<$n> {}
358 impl ListHashes for Le<NonZero<$n>> {}
359 impl ListHashes for Be<$n> {}
360 impl ListHashes for Be<NonZero<$n>> {}
361 impl Topological for Le<$n> {}
362 impl Topological for Le<NonZero<$n>> {}
363 impl Topological for Be<$n> {}
364 impl Topological for Be<NonZero<$n>> {}
365
366 impl Size for Le<NonZero<$n>> {
367 const SIZE: usize = <Le<$n> as Size>::SIZE;
368 type Size = <Le<$n> as Size>::Size;
369 }
370
371 impl Size for Be<NonZero<$n>> {
372 const SIZE: usize = <Be<$n> as Size>::SIZE;
373 type Size = <Be<$n> as Size>::Size;
374 }
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
526#[test]
527fn nonzero() {
528 assert_eq!(Option::<super::Le<u8>>::SIZE, 2);
529 assert_eq!(Option::<super::Le<NonZero<u8>>>::SIZE, 1);
530 assert_eq!(Option::<super::Le<u16>>::SIZE, 3);
531 assert_eq!(Option::<super::Le<NonZero<u16>>>::SIZE, 2);
532}
533
534impl<T: UsizeTag> UsizeTag for Le<T> {
535 fn from_usize(n: usize) -> Self {
536 Self(UsizeTag::from_usize(n))
537 }
538
539 fn to_usize(&self) -> usize {
540 self.0.to_usize()
541 }
542
543 fn try_to_usize(&self) -> Option<usize> {
544 self.0.try_to_usize()
545 }
546}
547
548impl<T: UsizeTag> UsizeTag for Be<T> {
549 fn from_usize(n: usize) -> Self {
550 Self(UsizeTag::from_usize(n))
551 }
552
553 fn to_usize(&self) -> usize {
554 self.0.to_usize()
555 }
556
557 fn try_to_usize(&self) -> Option<usize> {
558 self.0.try_to_usize()
559 }
560}