From 51df9728ab08465749af8b8e22c78a6372d44562 Mon Sep 17 00:00:00 2001 From: Flier Lu Date: Thu, 28 Feb 2019 18:31:44 +0800 Subject: [PATCH] convert between integer and byte array --- src/int.rs | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 36 ++++----------- 2 files changed, 142 insertions(+), 27 deletions(-) diff --git a/src/int.rs b/src/int.rs index 22f2713..225a3c9 100644 --- a/src/int.rs +++ b/src/int.rs @@ -1,3 +1,4 @@ +use core::mem::size_of; use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; use bounds::Bounded; @@ -5,6 +6,11 @@ use ops::checked::*; use ops::saturating::Saturating; use {Num, NumCast}; +pub trait Layout { + /// The type representation as a byte array. + type Bytes; +} + pub trait PrimInt: Sized + Copy @@ -25,6 +31,7 @@ pub trait PrimInt: + CheckedMul + CheckedDiv + Saturating + + Layout { /// Returns the number of ones in the binary representation of `self`. /// @@ -278,6 +285,98 @@ pub trait PrimInt: /// assert_eq!(2i32.pow(4), 16); /// ``` fn pow(self, exp: u32) -> Self; + + /// Return the memory representation of this integer as a byte array in big-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let bytes = 0x12345678u32.to_be_bytes(); + /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]); + /// ``` + fn to_be_bytes(self) -> Self::Bytes; + + /// Return the memory representation of this integer as a byte array in little-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let bytes = 0x12345678u32.to_le_bytes(); + /// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]); + /// ``` + fn to_le_bytes(self) -> Self::Bytes; + + /// Return the memory representation of this integer as a byte array in native byte order. + /// + /// As the target platform's native endianness is used, + /// portable code should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. + /// + /// [`to_be_bytes`]: #method.to_be_bytes + /// [`to_le_bytes`]: #method.to_le_bytes + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let bytes = 0x12345678u32.to_ne_bytes(); + /// assert_eq!(bytes, if cfg!(target_endian = "big") { + /// [0x12, 0x34, 0x56, 0x78] + /// } else { + /// [0x78, 0x56, 0x34, 0x12] + /// }); + /// ``` + fn to_ne_bytes(self) -> Self::Bytes; + + /// Create an integer value from its representation as a byte array in big endian. + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let value = u32::from_be_bytes([0x12, 0x34, 0x56, 0x78]); + /// assert_eq!(value, 0x12345678); + /// ``` + fn from_be_bytes(bytes: Self::Bytes) -> Self; + + /// Create an integer value from its representation as a byte array in little endian. + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let value = u32::from_le_bytes([0x78, 0x56, 0x34, 0x12]); + /// assert_eq!(value, 0x12345678); + /// ``` + fn from_le_bytes(bytes: Self::Bytes) -> Self; + + /// Create an integer value from its memory representation as a byte array in native endianness. + /// + /// As the target platform's native endianness is used, + /// portable code likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as appropriate instead. + /// + /// [`from_be_bytes`]: #method.from_be_bytes + /// [`from_le_bytes`]: #method.from_le_bytes + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let value = u32::from_ne_bytes(if cfg!(target_endian = "big") { + /// [0x12, 0x34, 0x56, 0x78] + /// } else { + /// [0x78, 0x56, 0x34, 0x12] + /// }); + /// assert_eq!(value, 0x12345678); + /// ``` + fn from_ne_bytes(bytes: Self::Bytes) -> Self; } macro_rules! prim_int_impl { @@ -362,6 +461,40 @@ macro_rules! prim_int_impl { fn pow(self, exp: u32) -> Self { <$T>::pow(self, exp) } + + #[inline] + fn to_be_bytes(self) -> Self::Bytes { + <$T>::to_be_bytes(self) + } + + #[inline] + fn to_le_bytes(self) -> Self::Bytes { + <$T>::to_le_bytes(self) + } + + #[inline] + fn to_ne_bytes(self) -> Self::Bytes { + <$T>::to_ne_bytes(self) + } + + #[inline] + fn from_be_bytes(bytes: Self::Bytes) -> Self { + <$T>::from_be_bytes(bytes) + } + + #[inline] + fn from_le_bytes(bytes: Self::Bytes) -> Self { + <$T>::from_le_bytes(bytes) + } + + #[inline] + fn from_ne_bytes(bytes: Self::Bytes) -> Self { + <$T>::from_ne_bytes(bytes) + } + } + + impl Layout for $T { + type Bytes = [u8; size_of::<$T>()]; } }; } diff --git a/src/lib.rs b/src/lib.rs index 5a25bab..76f4e55 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,7 +32,7 @@ pub use float::FloatConst; // pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`. pub use cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive}; pub use identities::{one, zero, One, Zero}; -pub use int::PrimInt; +pub use int::{Layout, PrimInt}; pub use ops::checked::{ CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub, }; @@ -90,13 +90,12 @@ pub trait NumOps: { } -impl NumOps for T -where +impl NumOps for T where T: Add + Sub + Mul + Div - + Rem, + + Rem { } @@ -105,22 +104,14 @@ where /// /// This is automatically implemented for types which implement the operators. pub trait NumRef: Num + for<'r> NumOps<&'r Self> {} -impl NumRef for T -where - T: Num + for<'r> NumOps<&'r T>, -{ -} +impl NumRef for T where T: Num + for<'r> NumOps<&'r T> {} /// The trait for references which implement numeric operations, taking the /// second operand either by value or by reference. /// /// This is automatically implemented for types which implement the operators. pub trait RefNum: NumOps + for<'r> NumOps<&'r Base, Base> {} -impl RefNum for T -where - T: NumOps + for<'r> NumOps<&'r Base, Base>, -{ -} +impl RefNum for T where T: NumOps + for<'r> NumOps<&'r Base, Base> {} /// The trait for types implementing numeric assignment operators (like `+=`). /// @@ -130,9 +121,8 @@ pub trait NumAssignOps: { } -impl NumAssignOps for T -where - T: AddAssign + SubAssign + MulAssign + DivAssign + RemAssign, +impl NumAssignOps for T where + T: AddAssign + SubAssign + MulAssign + DivAssign + RemAssign { } @@ -140,22 +130,14 @@ where /// /// This is automatically implemented for types which implement the operators. pub trait NumAssign: Num + NumAssignOps {} -impl NumAssign for T -where - T: Num + NumAssignOps, -{ -} +impl NumAssign for T where T: Num + NumAssignOps {} /// The trait for `NumAssign` types which also implement assignment operations /// taking the second operand by reference. /// /// This is automatically implemented for types which implement the operators. pub trait NumAssignRef: NumAssign + for<'r> NumAssignOps<&'r Self> {} -impl NumAssignRef for T -where - T: NumAssign + for<'r> NumAssignOps<&'r T>, -{ -} +impl NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {} macro_rules! int_trait_impl { ($name:ident for $($t:ty)*) => ($(