From 316120c6113478abc56831ed0afd872d45a5fc21 Mon Sep 17 00:00:00 2001 From: Flier Lu Date: Fri, 1 Mar 2019 17:18:44 +0800 Subject: [PATCH] extract `IntToFromBytes` trait --- Cargo.toml | 4 -- build.rs | 24 +++++---- src/int.rs | 126 +++++------------------------------------------ src/lib.rs | 3 +- src/ops/bytes.rs | 95 +++++++++++++++++++++++++++++++++++ src/ops/mod.rs | 1 + 6 files changed, 121 insertions(+), 132 deletions(-) create mode 100644 src/ops/bytes.rs diff --git a/Cargo.toml b/Cargo.toml index 179f2e6..672b4c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,11 +18,7 @@ features = ["std"] [dependencies] -[build-dependencies] -rustc_version = "0.2" - [features] default = ["std"] std = [] i128 = [] -int_to_from_bytes = [] diff --git a/build.rs b/build.rs index 138f831..3e425e3 100644 --- a/build.rs +++ b/build.rs @@ -1,5 +1,3 @@ -extern crate rustc_version; - use std::env; use std::io::Write; use std::process::{Command, Stdio}; @@ -11,17 +9,17 @@ fn main() { panic!("i128 support was not detected!"); } - match rustc_version::version_meta() { - Ok(ref meta) if meta.semver.major >= 1 && meta.semver.minor >= 32 => { - println!("cargo:rustc-cfg=int_to_from_bytes"); - } - Ok(ref meta) - if env::var_os("CARGO_FEATURE_INT_TO_FROM_BYTES").is_some() - && meta.channel == rustc_version::Channel::Stable => - { - panic!("`int_to_from_bytes` support was not stabilizations!"); - } - _ => {} + if probe(r#" + fn main() { + let bytes = 0x1234567890123456u64.to_ne_bytes(); + + assert_eq!(bytes, if cfg!(target_endian = "big") { + [0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56] + } else { + [0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12] + }); + }"#) { + println!("cargo:rustc-cfg=int_to_from_bytes"); } } diff --git a/src/int.rs b/src/int.rs index c1d5694..ab9853c 100644 --- a/src/int.rs +++ b/src/int.rs @@ -2,15 +2,11 @@ use core::mem::transmute; use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; use bounds::Bounded; +use ops::bytes::IntToFromBytes; 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 @@ -31,7 +27,7 @@ pub trait PrimInt: + CheckedMul + CheckedDiv + Saturating - + Layout + + IntToFromBytes { /// Returns the number of ones in the binary representation of `self`. /// @@ -285,98 +281,6 @@ 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 { @@ -461,83 +365,77 @@ macro_rules! prim_int_impl { fn pow(self, exp: u32) -> Self { <$T>::pow(self, exp) } + } + + #[cfg(feature = "int_to_from_bytes")] + impl IntToFromBytes for $T { + type Bytes = [u8; $L]; - #[cfg(feature = "int_to_from_bytes")] #[inline] fn to_be_bytes(self) -> Self::Bytes { <$T>::to_be_bytes(self) } - #[cfg(feature = "int_to_from_bytes")] #[inline] fn to_le_bytes(self) -> Self::Bytes { <$T>::to_le_bytes(self) } - #[cfg(feature = "int_to_from_bytes")] #[inline] fn to_ne_bytes(self) -> Self::Bytes { <$T>::to_ne_bytes(self) } - #[cfg(feature = "int_to_from_bytes")] #[inline] fn from_be_bytes(bytes: Self::Bytes) -> Self { <$T>::from_be_bytes(bytes) } - #[cfg(feature = "int_to_from_bytes")] #[inline] fn from_le_bytes(bytes: Self::Bytes) -> Self { <$T>::from_le_bytes(bytes) } - #[cfg(feature = "int_to_from_bytes")] #[inline] fn from_ne_bytes(bytes: Self::Bytes) -> Self { <$T>::from_ne_bytes(bytes) } + } + + #[cfg(not(feature = "int_to_from_bytes"))] + impl IntToFromBytes for $T { + type Bytes = [u8; $L]; - #[cfg(not(feature = "int_to_from_bytes"))] #[inline] fn to_be_bytes(self) -> Self::Bytes { <$T>::to_ne_bytes(<$T>::to_be(self)) } - #[cfg(not(feature = "int_to_from_bytes"))] #[inline] fn to_le_bytes(self) -> Self::Bytes { <$T>::to_ne_bytes(<$T>::to_le(self)) } - #[cfg(not(feature = "int_to_from_bytes"))] #[inline] fn to_ne_bytes(self) -> Self::Bytes { unsafe { transmute(self) } } - #[cfg(not(feature = "int_to_from_bytes"))] #[inline] fn from_be_bytes(bytes: Self::Bytes) -> Self { Self::from_be(Self::from_ne_bytes(bytes)) } - #[cfg(not(feature = "int_to_from_bytes"))] #[inline] fn from_le_bytes(bytes: Self::Bytes) -> Self { Self::from_le(Self::from_ne_bytes(bytes)) } - #[cfg(not(feature = "int_to_from_bytes"))] #[inline] fn from_ne_bytes(bytes: Self::Bytes) -> Self { unsafe { transmute(bytes) } } } - - impl Layout for $T { - type Bytes = [u8; $L]; - } }; } diff --git a/src/lib.rs b/src/lib.rs index 76f4e55..d6bef05 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,7 +32,8 @@ 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::{Layout, PrimInt}; +pub use int::PrimInt; +pub use ops::bytes::IntToFromBytes; pub use ops::checked::{ CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub, }; diff --git a/src/ops/bytes.rs b/src/ops/bytes.rs new file mode 100644 index 0000000..b07d3e0 --- /dev/null +++ b/src/ops/bytes.rs @@ -0,0 +1,95 @@ +pub trait IntToFromBytes { + type Bytes; + + /// Return the memory representation of this integer as a byte array in big-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_traits::IntToFromBytes; + /// + /// 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::IntToFromBytes; + /// + /// 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::IntToFromBytes; + /// + /// 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::IntToFromBytes; + /// + /// 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::IntToFromBytes; + /// + /// 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::IntToFromBytes; + /// + /// 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; +} diff --git a/src/ops/mod.rs b/src/ops/mod.rs index fd1695d..b39dd4a 100644 --- a/src/ops/mod.rs +++ b/src/ops/mod.rs @@ -3,3 +3,4 @@ pub mod inv; pub mod mul_add; pub mod saturating; pub mod wrapping; +pub mod bytes; \ No newline at end of file