1#![no_std]
2#![doc = include_str!("../README.md")]
3#![allow(
4 clippy::partialeq_ne_impl,
5 clippy::non_canonical_partial_ord_impl,
6 reason = "bulk forwarding to integer methods is faster than handwriting the methods"
7)]
8
9mod conversions;
10
11#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
12#[repr(u8)]
13enum Zero {
14 _0 = 0,
15}
16
17const fn from_str_error(bad_val: &str) -> core::num::ParseIntError {
18 match i8::from_str_radix(bad_val, 10) {
19 Err(err) => err,
20 Ok(_) => unreachable!(),
21 }
22}
23
24const POSITIVE_OVERFLOW: core::num::ParseIntError = from_str_error("999");
25
26const NEGATIVE_OVERFLOW: core::num::ParseIntError = from_str_error("-999");
27
28#[cfg(feature = "bytemuck")]
29unsafe impl bytemuck::Zeroable for Zero {}
30
31#[cfg(feature = "bytemuck")]
32unsafe impl bytemuck::NoUninit for Zero {}
33
34const _: () = match (cfg!(target_endian = "big"), cfg!(target_endian = "little")) {
35 (true, false) | (false, true) => {}
36 (false, false) => panic!("unknown endianness"),
37 (true, true) => panic!("invalid endianness"),
38};
39
40macro_rules! declare_inner_struct {
41 ($name: ident @[$size: expr] { $($fields: tt)* }) => {
42 #[derive(Copy, Clone)]
43 #[repr(C, align($size))]
44 struct $name {
45 $($fields)*
46 }
47
48 #[cfg(feature = "bytemuck")]
52 unsafe impl bytemuck::NoUninit for $name {}
53 #[cfg(feature = "bytemuck")]
54 unsafe impl bytemuck::Zeroable for $name {}
55
56
57 const _: () = assert!(size_of::<$name>() == $size);
58 };
59}
60
61macro_rules! match_signedness {
62 (match I {
63 SIGNED => { $($tt:tt)* },
64 UNSIGNED => { $($_tt:tt)* } $(,)?
65 }) => {
66 $($tt)*
67 };
68
69 (match U {
70 SIGNED => { $($_tt:tt)* },
71 UNSIGNED => { $($tt:tt)* } $(,)?
72 }) => {
73 $($tt)*
74 };
75}
76
77macro_rules! forward_ref_op_assign {
78 (impl $imp:ident, $method:ident for $t:ty) => {
79 impl core::ops::$imp<&$t> for $t {
80 #[inline(always)]
81 fn $method(&mut self, other: &$t) {
82 core::ops::$imp::$method(self, *other);
83 }
84 }
85 };
86}
87
88macro_rules! forward_ref_binop {
89 (impl $imp:ident, $method:ident for $t:ty) => {
90 impl core::ops::$imp<$t> for &$t {
91 type Output = <$t as core::ops::$imp<$t>>::Output;
92
93 #[inline(always)]
94 fn $method(self, other: $t) -> Self::Output {
95 core::ops::$imp::$method(*self, other)
96 }
97 }
98
99 impl core::ops::$imp<&$t> for $t {
100 type Output = <$t as core::ops::$imp<$t>>::Output;
101
102 #[inline(always)]
103 fn $method(self, other: &$t) -> Self::Output {
104 core::ops::$imp::$method(self, *other)
105 }
106 }
107
108 impl core::ops::$imp<&$t> for &$t {
109 type Output = <$t as core::ops::$imp<$t>>::Output;
110
111 #[inline(always)]
112 fn $method(self, other: &$t) -> Self::Output {
113 core::ops::$imp::$method(*self, *other)
114 }
115 }
116 };
117}
118
119macro_rules! impl_wrapping_binop_inner {
120 ($(impl $imp:ident, $method:ident for ($ty:ty as $inner: ty) @ $fetch:ident)+) => {$(
121 impl core::ops::$imp for $ty {
122 type Output = $ty;
123
124 #[inline(always)]
125 fn $method(self, rhs: Self) -> Self::Output {
126 let lhs = self.$fetch();
127 let rhs = rhs.$fetch();
128 let result = pastey::paste!(<$inner>::[<wrapping_ $method>](lhs, rhs));
129 Self::new_truncated(result)
130 }
131 }
132
133 forward_ref_binop! { impl $imp, $method for $ty }
134
135 pastey::paste! {
136 impl core::ops::[<$imp Assign>] for $ty {
137 #[inline(always)]
138 fn [<$method _assign>](&mut self, rhs: Self) {
139 *self = <Self as core::ops::$imp>::$method(*self, rhs);
140 }
141 }
142
143 forward_ref_op_assign! { impl [<$imp Assign>], [<$method _assign>] for $ty }
144 }
145 )+}
146}
147
148macro_rules! impl_wrapping_bits_binop {
149 ($(impl $imp:ident, $method:ident for $t:ty as $inner: ty)+) => {$(
150 impl_wrapping_binop_inner! { impl $imp, $method for ($t as $inner) @ to_bits }
151 )+}
152}
153
154macro_rules! impl_wrapping_inner_binop {
155 ($(impl $imp:ident, $method:ident for $t:ty as $inner: ty)+) => {$(
156 impl_wrapping_binop_inner! { impl $imp, $method for ($t as $inner) @ get }
157 )+}
158}
159
160macro_rules! handle_argument {
161 ($arg_name: ident : Self) => {
162 $arg_name.get()
163 };
164 ($arg_name: ident : &Self) => {
165 &$arg_name.get()
166 };
167 ($arg_name: ident : &mut Self) => {
168 &mut $arg_name.get()
169 };
170 ($arg_name: ident : $arg_ty: ty) => {
171 $arg_name
172 };
173}
174
175macro_rules! defer_basic {
176 (
177 $(impl ($path: path) for $ty: ident as $inner: ty {
178 $(
179 $(#[$meta: meta])*
180 fn $method: ident ($(& $([$has_ref: tt])? $(mut $([$has_mut: tt])? )?)? self $(, $arg_name: ident : [$($arg_ty: tt)*])* $(,)?) -> $ret: ty;
181 )*
182 })*
183 ) => {$(
184 impl $path for $ty {
185 $(#[inline(always)]
186 $(#[$meta])*
187 fn $method($(& $($has_ref)? $(mut $($has_mut)? )?)? self $(, $arg_name : $($arg_ty)*)*) -> $ret {
188 <$inner as $path>::$method($(& $($has_ref)? $(mut $($has_mut)? )?)? self.get() $(, handle_argument!($arg_name: $($arg_ty)*))*)
189 })*
190 }
191 )*};
192}
193
194macro_rules! defer_impl {
195 (@($_sign_prefix: ident) $ty: ident as $inner: ty) => {
196 defer_basic! {
197 impl (core::fmt::Display) for $ty as $inner {
198 fn fmt(&self, f: [&mut core::fmt::Formatter<'_>]) -> core::fmt::Result;
199 }
200
201 impl (core::fmt::Debug) for $ty as $inner {
202 fn fmt(&self, f: [&mut core::fmt::Formatter<'_>]) -> core::fmt::Result;
203 }
204
205 impl (core::cmp::PartialEq) for $ty as $inner {
206 fn eq(&self, other: [&Self]) -> bool;
207
208 fn ne(&self, other: [&Self]) -> bool;
209 }
210
211 impl (core::cmp::Eq) for $ty as $inner {}
212
213
214 impl (core::cmp::PartialOrd) for $ty as $inner {
215 fn partial_cmp(&self, other: [&Self]) -> Option<core::cmp::Ordering>;
216
217
218 fn lt(&self, other: [&Self]) -> bool;
219 fn le(&self, other: [&Self]) -> bool;
220
221 fn gt(&self, other: [&Self]) -> bool;
222 fn ge(&self, other: [&Self]) -> bool;
223 }
224
225 impl (core::cmp::Ord) for $ty as $inner {
226 fn cmp(&self, other: [&Self]) -> core::cmp::Ordering;
227 }
228 }
229
230 impl core::hash::Hash for $ty {
231 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
232 <$inner as core::hash::Hash>::hash(
233 unsafe { &*(self as *const Self as *const $inner) },
235 state,
236 )
237 }
238
239 fn hash_slice<H: core::hash::Hasher>(data: &[Self], state: &mut H)
240 where
241 Self: Sized,
242 {
243 <$inner as core::hash::Hash>::hash_slice(
244 unsafe { &*(data as *const [Self] as *const [$inner]) },
247 state,
248 )
249 }
250 }
251
252 impl_wrapping_bits_binop! {
253 impl Add, add for $ty as $inner
254 impl Sub, sub for $ty as $inner
255 impl Mul, mul for $ty as $inner
256 }
257
258 impl_wrapping_inner_binop! {
259 impl Div, div for $ty as $inner
260 impl Rem, rem for $ty as $inner
261 }
262
263 impl $ty {
264 pub const fn from_str_radix(
265 str: &str,
266 radix: u32,
267 ) -> Result<Self, core::num::ParseIntError> {
268 match <$inner>::from_str_radix(str, radix) {
269 Err(err) => Err(err),
270 Ok(int) => match Self::new(int) {
271 Some(casted_int) => Ok(casted_int),
272 #[allow(unused_comparisons)]
274 None if int < 0 => Err(NEGATIVE_OVERFLOW),
275 None => Err(POSITIVE_OVERFLOW),
276 },
277 }
278 }
279 }
280
281 impl core::str::FromStr for $ty {
282 type Err = core::num::ParseIntError;
283
284 fn from_str(s: &str) -> Result<Self, Self::Err> {
285 Self::from_str_radix(s, 10)
286 }
287 }
288
289 #[cfg(feature = "serde")]
290 impl serde::Serialize for $ty {
291 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
292 where
293 S: serde::Serializer,
294 {
295 match serializer.is_human_readable() {
296 true => <$inner as serde::Serialize>::serialize(&self.get(), serializer),
297 false => <[u8; { (<$ty>::BITS / 8) as usize }] as serde::Serialize>::serialize(
298 &self.to_be_bytes(),
299 serializer,
300 ),
301 }
302 }
303 }
304
305 #[cfg(feature = "serde")]
306 impl<'de> serde::Deserialize<'de> for $ty {
307 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
308 where
309 D: serde::Deserializer<'de>,
310 {
311 match deserializer.is_human_readable() {
312 true => {
313 let int = <$inner as serde::Deserialize>::deserialize(deserializer)?;
314 match $ty::new(int) {
315 Some(int) => Ok(int),
316 None => Err(<D::Error as serde::de::Error>::custom(format_args!(
317 "invalid {int} as {}",
318 stringify!($ty)
319 ))),
320 }
321 }
322 false => {
323 <[u8; { (<$ty>::BITS / 8) as usize }] as serde::Deserialize>::deserialize(
324 deserializer,
325 )
326 .map(<$ty>::from_be_bytes)
327 }
328 }
329 }
330 }
331
332 #[cfg(feature = "num-traits")]
333 impl num_traits::One for $ty {
334 #[inline(always)]
335 fn one() -> Self {
336 <Self as num_traits::ConstOne>::ONE
337 }
338
339 #[inline]
340 fn is_one(&self) -> bool {
341 *self == <Self as num_traits::ConstOne>::ONE
342 }
343 }
344
345 #[cfg(feature = "num-traits")]
346 impl num_traits::ConstOne for $ty {
347 const ONE: Self = const_macro::$ty!(1);
348 }
349
350 #[cfg(feature = "num-traits")]
351 impl num_traits::Zero for $ty {
352 #[inline(always)]
353 fn zero() -> Self {
354 <Self as num_traits::ConstZero>::ZERO
355 }
356
357 #[inline(always)]
358 fn is_zero(&self) -> bool {
359 *self == <Self as num_traits::ConstZero>::ZERO
360 }
361 }
362
363 #[cfg(feature = "num-traits")]
364 impl num_traits::ConstZero for $ty {
365 const ZERO: Self = const_macro::$ty!(0);
366 }
367
368 #[cfg(feature = "num-traits")]
369 impl num_traits::Num for $ty {
370 type FromStrRadixErr = core::num::ParseIntError;
371
372 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
373 Self::from_str_radix(str, radix)
374 }
375 }
376 };
377}
378
379macro_rules! nbyte_int_inner {
380 (
381 $($backing_ty: ident @($signed_prefix: ident $size: expr) [$($byte_count: tt @ $bit_count: tt),+])*
382 ) => {
383 pastey::paste! {
384 pub mod types {
385 use super::*;
386
387 $(const _: () = {
388 let min = $size / 2;
389 let max = size_of::<$backing_ty>();
390 assert!($size == max, "invalid backing type size");
391 $(
392 assert!(
393 $bit_count == $byte_count * 8,
394 concat!(
395 "invalid nbyte bit count for ",
396 stringify!($byte_count),
397 " bytes",
398 )
399 );
400 assert!(min < $byte_count && $byte_count < max, "invalid nbyte int");
401 )*
402 let len = <[_]>::len(&[$($byte_count),*]);
403 assert!(len == max - min - 1, "not all byte integers implemented");
406 };
407
408 $(
409 declare_inner_struct! {
410 [<$signed_prefix $bit_count LittleEndian Inner>] @[$size] {
411 bytes: [u8; $byte_count],
412 zeros: [Zero; { $size - $byte_count }],
413 }
414 }
415
416 declare_inner_struct! {
417 [<$signed_prefix $bit_count BigEndian Inner>] @[$size] {
418 zeros: [Zero; { $size - $byte_count }],
419 bytes: [u8; $byte_count]
420 }
421 }
422
423
424 cfg_select! {
425 target_endian = "little" => {
426 type [<$signed_prefix $bit_count Inner>] = [<$signed_prefix $bit_count LittleEndian Inner>];
427 type [<Flipped $signed_prefix $bit_count Inner>] = [<$signed_prefix $bit_count BigEndian Inner>];
428 }
429 target_endian = "big" => {
430 type [<$signed_prefix $bit_count Inner>] = [<$signed_prefix $bit_count BigEndian Inner>];
431 type [<Flipped $signed_prefix $bit_count Inner>] = [<$signed_prefix $bit_count LittleEndian Inner>];
432 }
433 }
434
435
436 #[allow(non_camel_case_types)]
437 #[derive(Copy, Clone)]
438 #[repr(transparent)]
439 pub struct [<$signed_prefix:lower $bit_count>]([<$signed_prefix $bit_count Inner>]);
440
441 #[cfg(feature = "bytemuck")]
443 unsafe impl bytemuck::NoUninit for [<$signed_prefix:lower $bit_count>] {}
444 #[cfg(feature = "bytemuck")]
445 unsafe impl bytemuck::Zeroable for [<$signed_prefix:lower $bit_count>] {}
446
447 impl [<$signed_prefix:lower $bit_count>] {
448 const DATA_BITS_MASK: $backing_ty = (1 as $backing_ty)
449 .strict_shl($bit_count)
450 .strict_sub(1);
451
452 const MIN_INNER: $backing_ty = match_signedness! {
453 match $signed_prefix {
454 SIGNED => {
455 {
456 let abs_value = Self::DATA_BITS_MASK.isolate_highest_one();
457 abs_value.strict_neg()
460 }
461 },
462 UNSIGNED => { 0 },
463 }
464 };
465
466 const MAX_INNER: $backing_ty = match_signedness! {
467 match $signed_prefix {
468 SIGNED => { Self::DATA_BITS_MASK >> 1 },
469 UNSIGNED => { Self::DATA_BITS_MASK },
470 }
471 };
472
473
474 pub const BITS: u32 = $bit_count;
475
476 pub const MIN: Self = Self::new(Self::MIN_INNER).unwrap();
477 pub const MAX: Self = Self::new(Self::MAX_INNER).unwrap();
478
479 #[doc = concat!(
480 "Creates a [`", stringify!([<$signed_prefix:lower $bit_count>]), "`](struct@",
481 stringify!([<$signed_prefix:lower $bit_count>]), ") from a `",
482 stringify!($backing_ty), "`, returning [`None`] if the value does not fit in ",
483 stringify!($bit_count), " bits.\n\n",
484 "The valid range is [`MIN`](Self::MIN)`..=`[`MAX`](Self::MAX).\n\n",
485 "This is the checked counterpart of [`new_unchecked`](Self::new_unchecked) ",
486 "and [`new_truncated`](Self::new_truncated). It is `const`, so it can be used ",
487 "to build constants; the type's constant macro does exactly that and panics ",
488 "at compile time on failure.\n\n",
489 "# Examples\n\n",
490 "```\n",
491 "use nbyte_int::prelude::*;\n\n",
492 "assert_eq!(", stringify!([<$signed_prefix:lower $bit_count>]), "::new(0).map(|x| x.get()), Some(0));\n",
493 "assert_eq!(", stringify!([<$signed_prefix:lower $bit_count>]), "::new(",
494 stringify!([<$signed_prefix:lower $bit_count>]), "::MAX.get()).map(|x| x.get()), ",
495 "Some(", stringify!([<$signed_prefix:lower $bit_count>]), "::MAX.get()));\n",
496 "// one past the maximum does not fit\n",
497 "assert!(", stringify!([<$signed_prefix:lower $bit_count>]), "::MAX.get().checked_add(1)",
498 ".and_then(", stringify!([<$signed_prefix:lower $bit_count>]), "::new).is_none());\n",
499 "```"
500 )]
501 #[inline(always)]
502 pub const fn new(x: $backing_ty) -> Option<Self> {
503 match x {
504 Self::MIN_INNER..=Self::MAX_INNER => Some(unsafe { Self::new_unchecked(x) }),
505 _ => None
506 }
507 }
508
509 #[doc = concat!(
510 "Creates a [`", stringify!([<$signed_prefix:lower $bit_count>]), "`](struct@",
511 stringify!([<$signed_prefix:lower $bit_count>]), ") from a `",
512 stringify!($backing_ty), "` without checking that it fits in ",
513 stringify!($bit_count), " bits.\n\n",
514 "Prefer [`new`](Self::new) (checked) or [`new_truncated`](Self::new_truncated) ",
515 "(wrapping) unless the range check is provably redundant and measurably matters.\n\n",
516 "# Safety\n\n",
517 "`x` must be within [`MIN`](Self::MIN)`..=`[`MAX`](Self::MAX), i.e. the value ",
518 "[`new`](Self::new) would accept. Violating this is immediate UB",
519 )]
520 #[inline(always)]
521 pub const unsafe fn new_unchecked(x: $backing_ty) -> Self {
522 unsafe {
523 core::hint::assert_unchecked(Self::MIN_INNER <= x);
524 core::hint::assert_unchecked(x <= Self::MAX_INNER);
525 }
526
527 match_signedness! {
528 match $signed_prefix {
529 SIGNED => { Self::new_truncated(x) },
531 UNSIGNED => { unsafe { Self::from_bits(x) } },
533 }
534 }
535 }
536
537 #[doc = concat!(
538 "Creates a ",
539 $byte_count,
540 "-byte integer from its exact raw bit pattern, bypassing all masking."
541 )]
542 #[doc = concat!(
550 "Only the low ",
551 $byte_count,
552 " bytes of `bits` may be non-zero. The upper bytes must all be zero. ",
553 "Violating this is immediate undefined behavior (UB)."
554 )]
555 #[inline(always)]
556 pub const unsafe fn from_bits(bits: $backing_ty) -> Self {
557 unsafe {
559 core::hint::assert_unchecked(bits & const { !Self::DATA_BITS_MASK } == 0);
560 core::mem::transmute(bits)
561 }
562 }
563
564 #[doc = concat!(
565 "Creates a ",
566 $byte_count,
567 "-byte integer by truncating the upper bits of the provided value."
568 )]
569 #[inline(always)]
579 pub const fn new_truncated(bits: $backing_ty) -> Self {
580 unsafe { Self::from_bits(bits & Self::DATA_BITS_MASK) }
581 }
582
583 #[doc = concat!(
584 "Returns the raw bit pattern of the ",
585 $byte_count,
586 "-byte integer as its underlying backing type."
587 )]
588 #[inline(always)]
598 pub const fn to_bits(self) -> $backing_ty {
599 unsafe { core::mem::transmute(self) }
601 }
602
603 #[inline(always)]
604 const fn get_swapped_bytes_inner(self) -> [u8; $byte_count] {
605 let bits = self.to_bits();
606 let swapped = bits.swap_bytes();
607
608 let swapped: [<Flipped $signed_prefix $bit_count Inner>] = unsafe {
612 core::mem::transmute(swapped)
613 };
614
615 swapped.bytes
616 }
617
618 #[inline(always)]
619 pub const fn swap_bytes(self) -> Self {
620 Self::from_ne_bytes(self.get_swapped_bytes_inner())
623 }
624
625 #[inline(always)]
626 pub const fn from_le(x: Self) -> Self {
627 #[cfg(target_endian = "little")]
628 {
629 x
630 }
631
632 #[cfg(target_endian = "big")]
633 {
634 x.swap_bytes()
635 }
636 }
637
638 #[inline(always)]
639 pub const fn from_be(x: Self) -> Self {
640 #[cfg(target_endian = "big")]
641 {
642 x
643 }
644
645 #[cfg(target_endian = "little")]
646 {
647 x.swap_bytes()
648 }
649 }
650
651 #[inline(always)]
652 pub const fn to_le(self) -> Self {
653 Self::from_le(self)
654 }
655
656 #[inline(always)]
657 pub const fn to_be(self) -> Self {
658 Self::from_be(self)
659 }
660
661 #[inline(always)]
662 pub const fn from_ne_bytes(bytes: [u8; $byte_count]) -> Self {
663 Self([<$signed_prefix $bit_count Inner>]{
664 zeros: [Zero::_0; { $size - $byte_count }],
665 bytes
666 })
667 }
668
669 #[inline(always)]
670 pub const fn from_le_bytes(bytes: [u8; $byte_count]) -> Self {
671 Self::from_le(Self::from_ne_bytes(bytes))
672 }
673
674 #[inline(always)]
675 pub const fn from_be_bytes(bytes: [u8; $byte_count]) -> Self {
676 Self::from_be(Self::from_ne_bytes(bytes))
677 }
678
679 #[inline(always)]
680 pub const fn to_ne_bytes(self) -> [u8; $byte_count] {
681 self.0.bytes
682 }
683
684 #[inline(always)]
685 pub const fn to_le_bytes(self) -> [u8; $byte_count] {
686 #[cfg(target_endian = "little")]
687 {
688 self.0.bytes
689 }
690
691 #[cfg(target_endian = "big")]
692 {
693 self.get_swapped_bytes_inner()
694 }
695 }
696
697 #[inline(always)]
698 pub const fn to_be_bytes(self) -> [u8; $byte_count] {
699 #[cfg(target_endian = "big")]
700 {
701 self.0.bytes
702 }
703
704 #[cfg(target_endian = "little")]
705 {
706 self.get_swapped_bytes_inner()
707 }
708 }
709
710 #[doc = concat!(
711 "Returns the logical value of the ",
712 $byte_count,
713 "-byte integer as its underlying `",
714 stringify!($backing_ty),
715 "` backing type."
716 )]
717 #[inline(always)]
726 pub const fn get(self) -> $backing_ty {
727 match_signedness! {
728 match $signed_prefix {
729 SIGNED => {
730 {
731 const OFFSET: u32 = $backing_ty::BITS
732 .strict_sub(<[<$signed_prefix:lower $bit_count>]>::BITS);
733
734 let bits = self.to_bits();
735 unsafe { bits.unchecked_shl(OFFSET).unchecked_shr(OFFSET) }
739 }
740 },
741 UNSIGNED => { self.to_bits() },
743 }
744 }
745 }
746 }
747
748 defer_impl!(@($signed_prefix) [<$signed_prefix:lower $bit_count>] as $backing_ty);
749 )*
750 )*
751 }
752
753
754 pub mod const_macro {
755 $($(
756 #[macro_export]
757 macro_rules! [<$signed_prefix:lower $bit_count>] {
758 ($__inner_expr__: literal) => {
759 const {
760 match $crate::types::[<$signed_prefix:lower $bit_count>]::new($__inner_expr__) {
761 Some(x) => x,
762 None => panic!(concat!(
763 "invalid ",
764 stringify!([<$signed_prefix:lower $bit_count>]),
765 " literal `",
766 $__inner_expr__,
767 "`"
768 ))
769 }
770 }
771 }
772 }
773
774 pub use [<$signed_prefix:lower $bit_count>];
775 )*)*
776 }
777 }
778 };
779}
780
781macro_rules! nbyte_int {
782 (
783 $($backing: tt @($size: expr) [$($byte_count: tt @ $bit_count: tt),+ $(,)?])*
784 ) => {
785 pastey::paste! {
786 nbyte_int_inner! {
787 $(
788 [<i $backing>] @(I $size) [$($byte_count @ $bit_count),+]
789 [<u $backing>] @(U $size) [$($byte_count @ $bit_count),+]
790 )*
791 }
792
793 pub mod prelude {
794 pub use $crate::types::*;
795 pub use $crate::const_macro::*;
796 }
797 }
798 };
799}
800
801nbyte_int! {
802 32 @(4) [3 @ 24]
804 64 @(8) [5 @ 40, 6 @ 48, 7 @ 56]
805 128 @(16) [9 @ 72, 10 @ 80, 11 @ 88, 12 @ 96, 13 @ 104, 14 @ 112, 15 @ 120]
806}