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