1mod big_small;
2mod int_data;
3
4use crate::ion_data::{IonDataHash, IonDataOrd, IonEq};
5use crate::result::IonFailure;
6use crate::types::CountDecimalDigits;
7use crate::{IonError, IonResult};
8use big_small::AsBigOrSmallValue;
9pub(crate) use int_data::{IntData, UIntData};
10use num_bigint::BigInt;
11use std::cmp::Ordering;
12use std::fmt::{Display, Formatter};
13use std::hash::{Hash, Hasher};
14use std::mem;
15use std::ops::{Add, Neg};
16
17#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub struct UInt {
20 pub(crate) data: UIntData,
21}
22
23impl UInt {
24 pub const ZERO: UInt = UInt {
25 data: UIntData::ZERO,
26 };
27
28 #[inline]
29 pub(crate) fn new(data: impl Into<u128>) -> Self {
30 Self {
31 data: UIntData::from(data.into()),
32 }
33 }
34
35 pub(crate) fn from_str_radix(s: &str, radix: u32) -> IonResult<Self> {
36 let data = UIntData::from_str_radix(s, radix)?;
37 Ok(Self { data })
38 }
39
40 pub(crate) fn from_be_bytes(bytes: &[u8]) -> UInt {
41 let data = UIntData::from_be_bytes(bytes);
42 Self { data }
43 }
44
45 pub fn as_usize(&self) -> Option<usize> {
48 usize::try_from(self).ok()
49 }
50
51 pub fn as_u64(&self) -> Option<u64> {
54 u64::try_from(self).ok()
55 }
56
57 pub fn as_u128(&self) -> Option<u128> {
60 u128::try_from(self).ok()
61 }
62
63 pub fn expect_usize(&self) -> IonResult<usize> {
66 usize::try_from(self)
67 .map_err(|_| IonError::decoding_error("UInt was too large to convert to a usize"))
68 }
69
70 pub fn expect_u64(&self) -> IonResult<u64> {
73 u64::try_from(self)
74 .map_err(|_| IonError::decoding_error("UInt was too large to convert to a u64"))
75 }
76
77 pub fn expect_u128(&self) -> IonResult<u128> {
80 u128::try_from(self)
81 .map_err(|_| IonError::decoding_error("UInt was too large to convert to a u128"))
82 }
83
84 pub fn number_of_decimal_digits(&self) -> u32 {
86 self.data.count_decimal_digits()
87 }
88
89 pub fn from_le_bytes(bytes: &[u8]) -> UInt {
90 UInt {
91 data: UIntData::from_le_bytes(bytes),
92 }
93 }
94
95 pub fn to_le_bytes(&self) -> Vec<u8> {
96 self.data.to_le_bytes()
97 }
98
99 pub fn is_zero(&self) -> bool {
101 self.data == UIntData::ZERO
102 }
103}
104
105impl From<UIntData> for UInt {
106 fn from(value: UIntData) -> Self {
107 UInt { data: value }
108 }
109}
110
111macro_rules! impl_uint_from_unsigned_int_types {
115 ($($t:ty),*) => ($(
116 impl From<$t> for UInt {
117 #[inline]
118 fn from(value: $t) -> UInt {
119 UInt::new(value)
120 }
121 }
122 )*)
123}
124
125impl_uint_from_unsigned_int_types!(u8, u16, u32, u64, u128);
126
127impl From<usize> for UInt {
128 #[inline]
129 fn from(value: usize) -> Self {
130 debug_assert!(
131 mem::size_of::<usize>() <= mem::size_of::<u128>(),
132 "usize cannot be cast to u128 safely on this platform"
133 );
134 UInt::new(value as u128)
135 }
136}
137
138macro_rules! impl_uint_try_from_signed_int_types {
139 ($($t:ty),*) => ($(
140 impl TryFrom<$t> for UInt {
141 type Error = IonError;
142 fn try_from(value: $t) -> Result<Self, Self::Error> {
143 if value.is_negative() {
144 return IonResult::decoding_error("cannot convert a negative number to a UInt");
145 }
146 Ok(UInt::from(value.unsigned_abs()))
147 }
148 }
149 )*)
150}
151
152impl_uint_try_from_signed_int_types!(i8, i16, i32, i64, i128, isize);
153
154macro_rules! impl_int_types_try_from_uint {
155 ($($t:ty),*) => ($(
156 impl TryFrom<&UInt> for $t {
157 type Error = IonError;
158
159 fn try_from(value: &UInt) -> Result<Self, Self::Error> {
160 <$t>::try_from(value.clone().data).map_err(|_| {
161 IonError::decoding_error(
162 concat!("UInt was too large to fit in a ", stringify!($t))
163 )
164 })
165 }
166 }
167 )*)
168}
169
170impl_int_types_try_from_uint!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize);
171
172impl TryFrom<Int> for UInt {
173 type Error = IonError;
175
176 fn try_from(value: Int) -> Result<Self, Self::Error> {
177 if value.data.is_negative() {
178 return IonResult::decoding_error("cannot convert negative Int to a UInt");
179 }
180 Ok(value.data.unsigned_abs().into())
181 }
182}
183
184impl TryFrom<&Int> for UInt {
185 type Error = IonError;
186
187 fn try_from(value: &Int) -> Result<Self, Self::Error> {
188 value.clone().try_into()
189 }
190}
191
192impl From<&UInt> for UInt {
193 fn from(value: &UInt) -> Self {
194 value.clone()
195 }
196}
197
198impl From<&Int> for Int {
199 fn from(value: &Int) -> Self {
200 value.clone()
201 }
202}
203
204macro_rules! impl_small_int_try_from_int {
205 ($($t:ty),*) => ($(
206 impl TryFrom<Int> for $t {
207 type Error = IonError;
208
209 fn try_from(value: Int) -> Result<Self, Self::Error> {
210 <$t>::try_from(value.data).map_err(|_| {
211 IonError::decoding_error(concat!("Int was outside the range of a(n) ", stringify!($t)))
212 })
213 }
214 }
215 )*)
216}
217
218impl_small_int_try_from_int!(i8, i16, i32, i64, i128, isize);
219impl_small_int_try_from_int!(u8, u16, u32, u64, u128, usize);
220
221macro_rules! impl_small_unsigned_int_try_from_uint {
222 ($($t:ty),*) => ($(
223 impl TryFrom<UInt> for $t {
224 type Error = IonError;
225
226 fn try_from(value: UInt) -> Result<Self, Self::Error> {
227 <$t>::try_from(value.data).map_err(|_| {
228 IonError::decoding_error(concat!("UInt was outside the range of a(n) ", stringify!($t)))
229 })
230 }
231 }
232 )*)
233}
234
235impl_small_unsigned_int_try_from_uint!(u8, u16, u32, u64, u128, usize);
236
237#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
238pub struct Int {
259 pub(crate) data: IntData,
260}
261
262impl Int {
263 pub const ZERO: Int = Int {
264 data: IntData::ZERO,
265 };
266
267 #[allow(unused)]
268 pub(crate) fn new(data: impl Into<i128>) -> Self {
269 Self {
270 data: IntData::from(data.into()),
271 }
272 }
273
274 pub fn unsigned_abs(&self) -> UInt {
276 self.data.unsigned_abs().into()
277 }
278
279 pub fn is_negative(&self) -> bool {
282 self.data.is_negative()
283 }
284
285 #[inline]
288 pub fn expect_i64(&self) -> IonResult<i64> {
289 self.as_i64().ok_or_else(
290 #[inline(never)]
291 || IonError::decoding_error(format!("Int {self} was not in the range of an i64.")),
292 )
293 }
294
295 #[inline(always)]
296 pub fn as_u32(&self) -> Option<u32> {
297 u32::try_from(&self.data).ok()
298 }
299
300 #[inline]
301 pub fn expect_u32(&self) -> IonResult<u32> {
302 self.as_u32().ok_or_else(
303 #[inline(never)]
304 || IonError::decoding_error(format!("Int {self} was not in the range of a u32.")),
305 )
306 }
307
308 #[inline(always)]
309 pub fn as_u64(&self) -> Option<u64> {
310 u64::try_from(&self.data).ok()
311 }
312
313 #[inline]
314 pub fn expect_u64(&self) -> IonResult<u64> {
315 self.as_u64().ok_or_else(
316 #[inline(never)]
317 || IonError::decoding_error(format!("Int {self} was not in the range of a u64.")),
318 )
319 }
320
321 #[inline(always)]
322 pub fn as_usize(&self) -> Option<usize> {
323 usize::try_from(&self.data).ok()
324 }
325
326 #[inline]
327 pub fn expect_usize(&self) -> IonResult<usize> {
328 self.as_usize().ok_or_else(
329 #[inline(never)]
330 || IonError::decoding_error(format!("Int {self} was not in the range of a usize.")),
331 )
332 }
333
334 pub fn expect_i128(&self) -> IonResult<i128> {
337 self.as_i128().ok_or_else(|| {
338 IonError::decoding_error(format!("Int {self} was not in the range of an i128."))
339 })
340 }
341
342 pub fn as_i64(&self) -> Option<i64> {
345 i64::try_from(&self.data).ok()
346 }
347
348 pub fn as_i128(&self) -> Option<i128> {
351 i128::try_from(&self.data).ok()
352 }
353
354 pub fn from_le_signed_bytes(bytes: &[u8]) -> Int {
355 Int {
356 data: IntData::from_le_signed_bytes(bytes),
357 }
358 }
359
360 pub fn to_le_signed_bytes(&self) -> Vec<u8> {
361 self.data.to_le_bytes()
362 }
363
364 #[cfg_attr(not(feature = "bigdecimal"), allow(dead_code))]
365 pub(crate) fn to_bigint(&self) -> BigInt {
367 self.data.as_big_value().into_owned()
368 }
369
370 pub fn is_zero(&self) -> bool {
372 self.data == IntData::ZERO
373 }
374
375 #[allow(clippy::should_implement_trait)]
377 pub fn neg(self) -> Self {
378 self.data.neg().into()
379 }
380
381 pub(crate) fn add(self, rhs: Self) -> Self {
383 self.data.add(rhs.data).into()
384 }
385}
386
387impl IonEq for Int {
388 fn ion_eq(&self, other: &Self) -> bool {
389 self == other
390 }
391}
392
393impl IonDataOrd for Int {
394 fn ion_cmp(&self, other: &Self) -> Ordering {
395 self.cmp(other)
396 }
397}
398
399impl IonDataHash for Int {
400 fn ion_data_hash<H: Hasher>(&self, state: &mut H) {
401 self.hash(state)
402 }
403}
404
405impl CountDecimalDigits for Int {
406 fn count_decimal_digits(self) -> u32 {
407 self.data.count_decimal_digits()
408 }
409}
410
411impl CountDecimalDigits for UInt {
412 fn count_decimal_digits(self) -> u32 {
413 self.data.count_decimal_digits()
414 }
415}
416
417impl Display for UInt {
418 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
419 write!(f, "{}", self.data)
420 }
421}
422
423impl<T> From<T> for Int
424where
425 T: Into<IntData>,
426{
427 fn from(value: T) -> Self {
428 Self { data: value.into() }
429 }
430}
431
432impl From<UInt> for IntData {
433 fn from(value: UInt) -> Self {
434 value.data.into()
435 }
436}
437
438impl From<&UInt> for Int {
439 fn from(value: &UInt) -> Self {
440 IntData::from(value.data.clone()).into()
441 }
442}
443
444impl Display for Int {
445 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
446 write!(f, "{}", self.data)
447 }
448}
449
450#[cfg(test)]
451mod integer_tests {
452 use std::io::Write;
453
454 use super::*;
455 use crate::types::UInt;
456 use rstest::*;
457 use std::cmp::Ordering;
458
459 #[test]
460 fn is_zero() {
461 assert!(Int::from(0).is_zero());
462 assert!(Int::from(0i128).is_zero());
463 assert!(!Int::from(55).is_zero());
464 assert!(!Int::from(55i128).is_zero());
465 assert!(!Int::from(-55).is_zero());
466 assert!(!Int::from(-55i128).is_zero());
467 }
468
469 #[test]
470 fn zero() {
471 assert!(Int::ZERO.is_zero());
472 }
473
474 #[rstest]
475 #[case::i64(5.into(), 4.into(), Ordering::Greater)]
476 #[case::i64_equal(Int::from(-5), Int::from(-5), Ordering::Equal)]
477 #[case::i64_gt_big_int(Int::from(4), Int::from(3i128), Ordering::Greater)]
478 #[case::i64_eq_big_int(Int::from(3), Int::from(3i128), Ordering::Equal)]
479 #[case::i64_lt_big_int(Int::from(-3), Int::from(5i128), Ordering::Less)]
480 #[case::big_int(
481 Int::from(1100i128),
482 Int::from(-1005i128),
483 Ordering::Greater
484 )]
485 #[case::big_int(Int::from(1100i128), Int::from(1100i128), Ordering::Equal)]
486 #[case::big_int_lt_i64(Int::from(-9223372036854775809i128), Int::from(0), Ordering::Less)]
487 #[case::big_int_gt_i64(Int::from(9223372036854775809i128), Int::from(0), Ordering::Greater)]
488 #[case::i64_gt_big_int_i128(Int::from(0), Int::from(9223372036854775809i128), Ordering::Less)]
489 #[case::i64_lt_big_int_i128(Int::from(0), Int::from(-9223372036854775809i128), Ordering::Greater)]
490 fn integer_ordering_tests(#[case] this: Int, #[case] other: Int, #[case] expected: Ordering) {
491 assert_eq!(this.cmp(&other), expected)
492 }
493
494 #[rstest]
495 #[case::u64(UInt::from(5u64), UInt::from(4u64), Ordering::Greater)]
496 #[case::u64_equal(UInt::from(5u64), UInt::from(5u64), Ordering::Equal)]
497 #[case::u64_gt_big_uint(UInt::from(4u64), UInt::from(3u128), Ordering::Greater)]
498 #[case::u64_lt_big_uint(UInt::from(3u64), UInt::from(5u128), Ordering::Less)]
499 #[case::u64_eq_big_uint(UInt::from(3u64), UInt::from(3u128), Ordering::Equal)]
500 #[case::big_uint(UInt::from(1100u128), UInt::from(1005u128), Ordering::Greater)]
501 #[case::big_uint(UInt::from(1005u128), UInt::from(1005u128), Ordering::Equal)]
502 fn unsigned_integer_ordering_tests(
503 #[case] this: UInt,
504 #[case] other: UInt,
505 #[case] expected: Ordering,
506 ) {
507 assert_eq!(this.cmp(&other), expected)
508 }
509
510 #[rstest]
511 #[case(UInt::from(1u64), 1)] #[case(UInt::from(0u128), 1)]
513 #[case(UInt::from(1u128), 1)]
514 #[case(UInt::from(10u128), 2)]
515 #[case(UInt::from(3117u128), 4)]
516 fn uint_decimal_digits_test(#[case] uint: UInt, #[case] expected: u32) {
517 assert_eq!(uint.number_of_decimal_digits(), expected)
518 }
519
520 #[rstest]
521 #[case(Int::from(5), "5")]
522 #[case(Int::from(-5), "-5")]
523 #[case(Int::from(0), "0")]
524 #[case(Int::from(1100i128), "1100")]
525 #[case(Int::from(-1100i128), "-1100")]
526 fn int_display_test(#[case] value: Int, #[case] expect: String) {
527 let mut buf = Vec::new();
528 write!(&mut buf, "{value}").unwrap();
529 assert_eq!(expect, String::from_utf8(buf).unwrap());
530 }
531
532 #[rstest]
533 #[case(UInt::from(5u64), "5")]
534 #[case(UInt::from(0u64), "0")]
535 #[case(UInt::from(0u128), "0")]
536 #[case(UInt::from(1100u128), "1100")]
537 fn uint_display_test(#[case] value: UInt, #[case] expect: String) {
538 let mut buf = Vec::new();
539 write!(&mut buf, "{value}").unwrap();
540 assert_eq!(expect, String::from_utf8(buf).unwrap());
541 }
542
543 #[test]
544 fn u8_from_uint() {
545 assert_eq!(u8::try_from(UInt::from(0u64)), Ok(0u8));
546 assert_eq!(u8::try_from(UInt::from(21u64)), Ok(21u8));
547 assert_eq!(u8::try_from(UInt::from(255u64)), Ok(255u8));
548 assert_eq!(u8::try_from(UInt::from(255u128)), Ok(255u8));
549 assert!(u8::try_from(UInt::from(999u64)).is_err())
550 }
551
552 #[test]
553 fn u16_from_uint() {
554 assert_eq!(u16::try_from(UInt::from(0u64)), Ok(0u16));
555 assert_eq!(u16::try_from(UInt::from(999u64)), Ok(999u16));
556 assert_eq!(u16::try_from(UInt::from(16500u64)), Ok(16500u16));
557 assert_eq!(u16::try_from(UInt::from(16500u128)), Ok(16500u16));
558 assert!(u16::try_from(UInt::from(128_000u64)).is_err())
559 }
560
561 #[test]
562 fn u32_from_uint() {
563 assert_eq!(u32::try_from(UInt::from(0u64)), Ok(0u32));
564 assert_eq!(u32::try_from(UInt::from(16500u64)), Ok(16500u32));
565 assert_eq!(u32::try_from(UInt::from(128_000u64)), Ok(128_000u32));
566 assert_eq!(u32::try_from(UInt::from(128_000u128)), Ok(128_000u32));
567 assert!(u32::try_from(UInt::from(5_000_000_000u64)).is_err())
568 }
569
570 #[test]
571 fn u64_from_uint() {
572 assert_eq!(u64::try_from(UInt::from(0u64)), Ok(0u64));
573 assert_eq!(u64::try_from(UInt::from(128_000u64)), Ok(128_000u64));
574 assert_eq!(
575 u64::try_from(UInt::from(5_000_000_000u64)),
576 Ok(5_000_000_000u64)
577 );
578 assert!(u64::try_from(UInt::from(u128::MAX)).is_err())
579 }
580
581 #[test]
582 fn usize_from_uint() {
583 assert_eq!(usize::try_from(UInt::from(0u64)), Ok(0usize));
584 assert_eq!(usize::try_from(UInt::from(16500u64)), Ok(16500usize));
585 assert_eq!(usize::try_from(UInt::from(128_000u64)), Ok(128_000usize));
586 assert_eq!(usize::try_from(UInt::from(128_000u128)), Ok(128_000usize));
587 assert!(usize::try_from(UInt::from(u128::MAX)).is_err())
588 }
589
590 #[test]
591 fn as_usize() {
592 assert_eq!(UInt::from(128_000u64).as_usize(), Some(128_000usize));
593 assert_eq!(UInt::from(128_000u128).as_usize(), Some(128_000usize));
594 assert!(UInt::from(u128::MAX).as_usize().is_none())
595 }
596
597 #[test]
598 fn expect_usize() {
599 assert_eq!(UInt::from(128_000u64).expect_usize(), Ok(128_000usize));
600 assert_eq!(UInt::from(128_000u128).expect_usize(), Ok(128_000usize));
601 assert!(UInt::from(u128::MAX).expect_usize().is_err())
602 }
603
604 #[test]
605 fn as_u64() {
606 assert_eq!(UInt::from(128_000u64).as_u64(), Some(128_000u64));
607 assert_eq!(UInt::from(128_000u128).as_u64(), Some(128_000u64));
608 assert!(UInt::from(u128::MAX).as_u64().is_none())
609 }
610
611 #[test]
612 fn expect_u64() {
613 assert_eq!(UInt::from(128_000u64).expect_u64(), Ok(128_000u64));
614 assert_eq!(UInt::from(128_000u128).expect_u64(), Ok(128_000u64));
615 assert!(UInt::from(u128::MAX).expect_u64().is_err())
616 }
617
618 #[test]
619 fn int_as_u64() {
620 assert_eq!(Int::from(128_000i64).as_u64(), Some(128_000u64));
621 assert_eq!(Int::from(0i64).as_u64(), Some(0u64));
622 assert!(Int::from(-1i64).as_u64().is_none());
623 assert!(Int::from(i128::MAX).as_u64().is_none());
624 }
625
626 #[test]
627 fn int_expect_u64() {
628 assert_eq!(Int::from(128_000i64).expect_u64(), Ok(128_000u64));
629 assert_eq!(Int::from(0i64).expect_u64(), Ok(0u64));
630 assert!(Int::from(-1i64).expect_u64().is_err());
631 assert!(Int::from(i128::MAX).expect_u64().is_err());
632 }
633
634 #[test]
637 fn int_from_signed_bytes_le_big() {
638 let mut bytes = vec![0u8; 17];
640 bytes[16] = 1;
641 let big = Int::from_le_signed_bytes(&bytes);
642 assert!(big.as_i128().is_none());
643 assert!(!big.is_negative());
644 assert!(!big.is_zero());
645 assert_eq!(big.to_string(), "340282366920938463463374607431768211456");
646 }
647
648 #[test]
649 fn uint_from_bytes_le_big() {
650 let mut bytes = vec![0u8; 17];
651 bytes[16] = 1;
652 let big = UInt::from_le_bytes(&bytes);
653 assert!(big.as_u128().is_none());
654 assert!(!big.is_zero());
655 assert_eq!(big.to_string(), "340282366920938463463374607431768211456");
656 }
657
658 #[test]
659 fn int_neg_big() {
660 let mut bytes = vec![0u8; 17];
661 bytes[16] = 1;
662 let big = Int::from_le_signed_bytes(&bytes);
663 let neg = big.neg();
664 assert!(neg.is_negative());
665 assert_eq!(neg.to_string(), "-340282366920938463463374607431768211456");
666 }
667
668 #[test]
669 fn int_from_bytes_roundtrip() {
670 for v in [0i128, 1, -1, 42, -42, i128::MAX, i128::MIN] {
671 let int = Int::from(v);
672 let bytes = int.data.to_le_bytes();
673 let roundtripped = Int::from_le_signed_bytes(&bytes);
674 assert_eq!(int, roundtripped, "roundtrip failed for {v}");
675 }
676 }
677
678 #[test]
681 fn int_cross_repr_eq() {
682 let inline = Int::from(42i64);
683 let also_inline = Int::from(42i64);
684 assert_eq!(inline, also_inline);
685
686 let mut bytes = vec![0u8; 17];
688 bytes[16] = 1;
689 let big1 = Int::from_le_signed_bytes(&bytes);
690 let big2 = Int::from_le_signed_bytes(&bytes);
691 assert_eq!(big1, big2);
692
693 assert_ne!(inline, big1);
695 }
696
697 #[test]
698 fn int_cross_repr_ord() {
699 let small = Int::from(42i64);
700 let mut bytes = vec![0u8; 17];
701 bytes[16] = 1;
702 let big = Int::from_le_signed_bytes(&bytes);
703
704 assert!(small < big);
706 assert!(big > small);
707
708 let neg_big = Int::from_le_signed_bytes(&bytes).neg();
710 assert!(neg_big < small);
711 assert!(small > neg_big);
712 }
713
714 #[test]
715 fn int_cross_repr_hash_consistent() {
716 use std::collections::hash_map::DefaultHasher;
717 use std::hash::{Hash, Hasher};
718
719 let hash = |v: &Int| {
720 let mut h = DefaultHasher::new();
721 v.hash(&mut h);
722 h.finish()
723 };
724
725 let a = Int::from(42i64);
727 let b = Int::from(42i64);
728 assert_eq!(hash(&a), hash(&b));
729
730 let mut bytes = vec![0u8; 17];
731 bytes[16] = 1;
732 let c = Int::from_le_signed_bytes(&bytes);
733 let d = Int::from_le_signed_bytes(&bytes);
734 assert_eq!(hash(&c), hash(&d));
735 }
736
737 #[test]
738 fn int_ion_eq_and_ion_data_hash() {
739 use crate::ion_data::{IonDataHash, IonEq};
740 use std::collections::hash_map::DefaultHasher;
741 use std::hash::Hasher;
742
743 let a = Int::from(42i64);
744 let b = Int::from(42i64);
745 assert!(a.ion_eq(&b));
746
747 let ion_hash = |v: &Int| {
748 let mut h = DefaultHasher::new();
749 v.ion_data_hash(&mut h);
750 h.finish()
751 };
752 assert_eq!(ion_hash(&a), ion_hash(&b));
753 }
754
755 #[test]
756 fn uint_cross_repr_ord() {
757 let small = UInt::from(42u64);
758 let mut bytes = vec![0u8; 17];
759 bytes[16] = 1;
760 let big = UInt::from_le_bytes(&bytes);
761 assert!(small < big);
762 assert!(big > small);
763 }
764}