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)]
12pub struct Ae<T>(T);
13#[derive(ParseAsInline)]
14pub struct Le<T>(T);
15#[derive(ParseAsInline)]
16pub struct Be<T>(T);
17#[derive(ParseAsInline)]
18pub struct Nz<T: NonZeroable>(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}
71
72pub trait AsBe {
73 type Be;
74}
75
76macro_rules! signs {
77 ($u:ty, $i:ty) => {
78 impl HasOtherSign for $u {
79 type OtherSign = $i;
80 }
81 impl HasOtherSign for $i {
82 type OtherSign = $u;
83 }
84 };
85}
86
87macro_rules! ae {
88 ($n:ty) => {
89 impl UsizeTag for $n {
90 fn from_usize(n: usize) -> Self {
91 n.try_into().expect("discriminant out of range")
92 }
93 fn to_usize(&self) -> usize {
94 (*self).try_into().expect("discriminant out of range")
95 }
96 fn try_to_usize(&self) -> Option<usize> {
97 (*self).try_into().ok()
98 }
99 }
100
101 impl UsizeTag for NonZero<$n> {
102 fn from_usize(n: usize) -> Self {
103 Self::new(
104 n.checked_add(1)
105 .expect("discriminant out of range")
106 .try_into()
107 .expect("discriminant out of range"),
108 )
109 .unwrap()
110 }
111 fn to_usize(&self) -> usize {
112 usize::try_from(self.get())
113 .expect("discriminant out of range")
114 .checked_sub(1)
115 .unwrap()
116 }
117 fn try_to_usize(&self) -> Option<usize> {
118 usize::try_from(self.get()).ok()?.checked_sub(1)
119 }
120 }
121
122 impl AsLe for $n {
123 type Le = Ae<$n>;
124 }
125
126 impl AsLe for NonZero<$n> {
127 type Le = Nz<Ae<$n>>;
128 }
129
130 impl AsBe for $n {
131 type Be = Ae<$n>;
132 }
133
134 impl AsBe for NonZero<$n> {
135 type Be = Nz<Ae<$n>>;
136 }
137
138 impl From<NonZero<$n>> for Nz<Ae<$n>> {
139 fn from(nz: NonZero<$n>) -> Self {
140 Self(nz)
141 }
142 }
143
144 impl NonZeroable for Ae<$n> {
145 type Nz = NonZero<$n>;
146 fn to_nz(&self) -> Option<Self::Nz> {
147 NonZero::new(self.0)
148 }
149 fn from_nz(nz: &Self::Nz) -> Self {
150 Self(nz.get())
151 }
152 }
153
154 impl ToOutput for Ae<$n> {
155 fn to_output(&self, output: &mut dyn Output) {
156 output.write(&self.0.to_le_bytes());
157 }
158 }
159
160 impl<I: ParseInput> ParseInline<I> for Ae<$n> {
161 fn parse_inline(input: &mut I) -> crate::Result<Self> {
162 Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
163 }
164 }
165
166 impl Size for Ae<$n> {
167 const SIZE: usize = std::mem::size_of::<$n>();
168 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
169 }
170
171 impl MaybeHasNiche for Ae<$n> {
172 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
173 }
174
175 impl Topological for Ae<$n> {
176 fn accept_points(&self, _: &mut impl PointVisitor) {}
177 }
178
179 impl Tagged for Ae<$n> {}
180 impl Tagged for Ae<NonZero<$n>> {}
181 impl ReflessObject for Ae<$n> {}
182 impl ReflessInline for Ae<$n> {}
183 impl Object for Ae<$n> {}
184 impl Inline for Ae<$n> {}
185
186 impl Equivalent<Ae<$n>> for Option<Ae<NonZero<$n>>> {
187 fn into_equivalent(self) -> Ae<$n> {
188 Ae(self.map(|object| object.0.get()).unwrap_or_default())
189 }
190 fn from_equivalent(object: Ae<$n>) -> Self {
191 NonZero::new(object.0).map(Ae)
192 }
193 }
194
195 impl Equivalent<Ae<Os<$n>>> for Ae<$n> {
196 fn into_equivalent(self) -> Ae<Os<$n>> {
197 Ae(self.0 as _)
198 }
199 fn from_equivalent(object: Ae<Os<$n>>) -> Self {
200 Ae(object.0 as _)
201 }
202 }
203
204 impl Equivalent<Ae<NonZero<Os<$n>>>> for Ae<NonZero<$n>> {
205 fn into_equivalent(self) -> Ae<NonZero<Os<$n>>> {
206 Ae(NonZero::new(self.0.get() as _).unwrap())
207 }
208 fn from_equivalent(object: Ae<NonZero<Os<$n>>>) -> Self {
209 Ae(NonZero::new(object.0.get() as _).unwrap())
210 }
211 }
212 };
213}
214
215macro_rules! lebe {
216 ($n:ty) => {
217 impl UsizeTag for $n {
218 fn from_usize(n: usize) -> Self {
219 n.try_into().expect("discriminant out of range")
220 }
221 fn to_usize(&self) -> usize {
222 (*self).try_into().expect("discriminant out of range")
223 }
224 fn try_to_usize(&self) -> Option<usize> {
225 (*self).try_into().ok()
226 }
227 }
228
229 impl UsizeTag for NonZero<$n> {
230 fn from_usize(n: usize) -> Self {
231 Self::new(
232 n.checked_add(1)
233 .expect("discriminant out of range")
234 .try_into()
235 .expect("discriminant out of range"),
236 )
237 .unwrap()
238 }
239 fn to_usize(&self) -> usize {
240 usize::try_from(self.get())
241 .expect("discriminant out of range")
242 .checked_sub(1)
243 .unwrap()
244 }
245 fn try_to_usize(&self) -> Option<usize> {
246 usize::try_from(self.get()).ok()?.checked_sub(1)
247 }
248 }
249
250 impl AsLe for $n {
251 type Le = Le<$n>;
252 }
253
254 impl AsLe for NonZero<$n> {
255 type Le = Nz<Le<$n>>;
256 }
257
258 impl AsBe for $n {
259 type Be = Be<$n>;
260 }
261
262 impl AsBe for NonZero<$n> {
263 type Be = Nz<Be<$n>>;
264 }
265
266 impl NonZeroable for Le<$n> {
267 type Nz = NonZero<$n>;
268 fn to_nz(&self) -> Option<Self::Nz> {
269 NonZero::new(self.0)
270 }
271 fn from_nz(nz: &Self::Nz) -> Self {
272 Self(nz.get())
273 }
274 }
275
276 impl NonZeroable for Be<$n> {
277 type Nz = NonZero<$n>;
278 fn to_nz(&self) -> Option<Self::Nz> {
279 NonZero::new(self.0)
280 }
281 fn from_nz(nz: &Self::Nz) -> Self {
282 Self(nz.get())
283 }
284 }
285
286 impl From<NonZero<$n>> for Nz<Le<$n>> {
287 fn from(nz: NonZero<$n>) -> Self {
288 Self(nz)
289 }
290 }
291
292 impl From<NonZero<$n>> for Nz<Be<$n>> {
293 fn from(nz: NonZero<$n>) -> Self {
294 Self(nz)
295 }
296 }
297
298 impl ToOutput for Le<$n> {
299 fn to_output(&self, output: &mut dyn Output) {
300 output.write(&self.0.to_le_bytes());
301 }
302 }
303
304 impl ToOutput for Be<$n> {
305 fn to_output(&self, output: &mut dyn Output) {
306 output.write(&self.0.to_be_bytes());
307 }
308 }
309
310 impl<I: ParseInput> ParseInline<I> for Le<$n> {
311 fn parse_inline(input: &mut I) -> crate::Result<Self> {
312 Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
313 }
314 }
315
316 impl<I: ParseInput> ParseInline<I> for Be<$n> {
317 fn parse_inline(input: &mut I) -> crate::Result<Self> {
318 Ok(Self(<$n>::from_be_bytes(*input.parse_chunk()?)))
319 }
320 }
321
322 impl Size for Le<$n> {
323 const SIZE: usize = std::mem::size_of::<$n>();
324 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
325 }
326
327 impl Size for Be<$n> {
328 const SIZE: usize = std::mem::size_of::<$n>();
329 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
330 }
331
332 impl MaybeHasNiche for Le<$n> {
333 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
334 }
335
336 impl MaybeHasNiche for Be<$n> {
337 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
338 }
339
340 impl Topological for Le<$n> {
341 fn accept_points(&self, _: &mut impl PointVisitor) {}
342 }
343
344 impl Topological for Be<$n> {
345 fn accept_points(&self, _: &mut impl PointVisitor) {}
346 }
347
348 impl Tagged for Le<$n> {}
349 impl Tagged for Be<$n> {}
350 impl ReflessObject for Le<$n> {}
351 impl ReflessObject for Be<$n> {}
352 impl ReflessInline for Le<$n> {}
353 impl ReflessInline for Be<$n> {}
354 impl Object for Le<$n> {}
355 impl Object for Be<$n> {}
356 impl Inline for Le<$n> {}
357 impl Inline for Be<$n> {}
358
359 impl Equivalent<Le<$n>> for Option<Le<NonZero<$n>>> {
360 fn into_equivalent(self) -> Le<$n> {
361 Le(self.map(|object| object.0.get()).unwrap_or_default())
362 }
363 fn from_equivalent(object: Le<$n>) -> Self {
364 NonZero::new(object.0).map(Le)
365 }
366 }
367
368 impl Equivalent<Be<$n>> for Option<Be<NonZero<$n>>> {
369 fn into_equivalent(self) -> Be<$n> {
370 Be(self.map(|object| object.0.get()).unwrap_or_default())
371 }
372 fn from_equivalent(object: Be<$n>) -> Self {
373 NonZero::new(object.0).map(Be)
374 }
375 }
376
377 impl Equivalent<Le<Os<$n>>> for Le<$n> {
378 fn into_equivalent(self) -> Le<Os<$n>> {
379 Le(self.0 as _)
380 }
381 fn from_equivalent(object: Le<Os<$n>>) -> Self {
382 Le(object.0 as _)
383 }
384 }
385
386 impl Equivalent<Be<Os<$n>>> for Be<$n> {
387 fn into_equivalent(self) -> Be<Os<$n>> {
388 Be(self.0 as _)
389 }
390 fn from_equivalent(object: Be<Os<$n>>) -> Self {
391 Be(object.0 as _)
392 }
393 }
394
395 impl Equivalent<Le<NonZero<Os<$n>>>> for Le<NonZero<$n>> {
396 fn into_equivalent(self) -> Le<NonZero<Os<$n>>> {
397 Le(NonZero::new(self.0.get() as _).unwrap())
398 }
399 fn from_equivalent(object: Le<NonZero<Os<$n>>>) -> Self {
400 Le(NonZero::new(object.0.get() as _).unwrap())
401 }
402 }
403
404 impl Equivalent<Be<NonZero<Os<$n>>>> for Be<NonZero<$n>> {
405 fn into_equivalent(self) -> Be<NonZero<Os<$n>>> {
406 Be(NonZero::new(self.0.get() as _).unwrap())
407 }
408 fn from_equivalent(object: Be<NonZero<Os<$n>>>) -> Self {
409 Be(NonZero::new(object.0.get() as _).unwrap())
410 }
411 }
412 };
413}
414
415signs!(u8, i8);
416signs!(u16, i16);
417signs!(u32, i32);
418signs!(u64, i64);
419signs!(u128, i128);
420
421ae!(u8);
422ae!(i8);
423
424lebe!(u16);
425lebe!(i16);
426
427lebe!(u32);
428lebe!(i32);
429
430lebe!(u64);
431lebe!(i64);
432
433lebe!(u128);
434lebe!(i128);
435
436impl<T: NonZeroable> Deref for Nz<T> {
437 type Target = T::Nz;
438
439 fn deref(&self) -> &Self::Target {
440 &self.0
441 }
442}
443
444impl<T: NonZeroable + ToOutput> ToOutput for Nz<T> {
445 fn to_output(&self, output: &mut dyn Output) {
446 T::from_nz(&self.0).to_output(output);
447 }
448}
449
450impl<T: NonZeroable + ParseInline<I>, I: ParseInput> ParseInline<I> for Nz<T> {
451 fn parse_inline(input: &mut I) -> crate::Result<Self> {
452 Ok(Self(T::parse_inline(input)?.to_nz().ok_or(Error::Zero)?))
453 }
454}
455
456impl<T: NonZeroable + Size> Size for Nz<T> {
457 type Size = T::Size;
458}
459
460impl<T: NonZeroable + Size> MaybeHasNiche for Nz<T> {
461 type MnArray = SomeNiche<ZeroNiche<T::Size>>;
462}
463
464impl<T: NonZeroable> Topological for Nz<T> {
465 fn accept_points(&self, _: &mut impl PointVisitor) {}
466}
467
468impl<T: NonZeroable> Tagged for Nz<T> {}
469impl<T: NonZeroable + ReflessInline> ReflessObject for Nz<T> {}
470impl<T: NonZeroable + ReflessInline> ReflessInline for Nz<T> {}
471impl<T: NonZeroable + Inline> Object for Nz<T> {}
472impl<T: NonZeroable + Inline> Inline for Nz<T> {}
473
474#[test]
475fn nonzero() {
476 assert_eq!(Option::<Ae<u8>>::SIZE, 2);
477 assert_eq!(Option::<Nz<Ae<u8>>>::SIZE, 1);
478 assert_eq!(Option::<Le<u16>>::SIZE, 3);
479 assert_eq!(Option::<Nz<Le<u16>>>::SIZE, 2);
480}