extract `IntToFromBytes` trait

This commit is contained in:
Flier Lu 2019-03-01 17:18:44 +08:00
parent 45c399ffa7
commit 316120c611
6 changed files with 121 additions and 132 deletions

View File

@ -18,11 +18,7 @@ features = ["std"]
[dependencies] [dependencies]
[build-dependencies]
rustc_version = "0.2"
[features] [features]
default = ["std"] default = ["std"]
std = [] std = []
i128 = [] i128 = []
int_to_from_bytes = []

View File

@ -1,5 +1,3 @@
extern crate rustc_version;
use std::env; use std::env;
use std::io::Write; use std::io::Write;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
@ -11,17 +9,17 @@ fn main() {
panic!("i128 support was not detected!"); panic!("i128 support was not detected!");
} }
match rustc_version::version_meta() { if probe(r#"
Ok(ref meta) if meta.semver.major >= 1 && meta.semver.minor >= 32 => { fn main() {
println!("cargo:rustc-cfg=int_to_from_bytes"); let bytes = 0x1234567890123456u64.to_ne_bytes();
}
Ok(ref meta) assert_eq!(bytes, if cfg!(target_endian = "big") {
if env::var_os("CARGO_FEATURE_INT_TO_FROM_BYTES").is_some() [0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]
&& meta.channel == rustc_version::Channel::Stable => } else {
{ [0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]
panic!("`int_to_from_bytes` support was not stabilizations!"); });
} }"#) {
_ => {} println!("cargo:rustc-cfg=int_to_from_bytes");
} }
} }

View File

@ -2,15 +2,11 @@ use core::mem::transmute;
use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
use bounds::Bounded; use bounds::Bounded;
use ops::bytes::IntToFromBytes;
use ops::checked::*; use ops::checked::*;
use ops::saturating::Saturating; use ops::saturating::Saturating;
use {Num, NumCast}; use {Num, NumCast};
pub trait Layout {
/// The type representation as a byte array.
type Bytes;
}
pub trait PrimInt: pub trait PrimInt:
Sized Sized
+ Copy + Copy
@ -31,7 +27,7 @@ pub trait PrimInt:
+ CheckedMul<Output = Self> + CheckedMul<Output = Self>
+ CheckedDiv<Output = Self> + CheckedDiv<Output = Self>
+ Saturating + Saturating
+ Layout + IntToFromBytes
{ {
/// Returns the number of ones in the binary representation of `self`. /// Returns the number of ones in the binary representation of `self`.
/// ///
@ -285,98 +281,6 @@ pub trait PrimInt:
/// assert_eq!(2i32.pow(4), 16); /// assert_eq!(2i32.pow(4), 16);
/// ``` /// ```
fn pow(self, exp: u32) -> Self; 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 { macro_rules! prim_int_impl {
@ -461,83 +365,77 @@ macro_rules! prim_int_impl {
fn pow(self, exp: u32) -> Self { fn pow(self, exp: u32) -> Self {
<$T>::pow(self, exp) <$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] #[inline]
fn to_be_bytes(self) -> Self::Bytes { fn to_be_bytes(self) -> Self::Bytes {
<$T>::to_be_bytes(self) <$T>::to_be_bytes(self)
} }
#[cfg(feature = "int_to_from_bytes")]
#[inline] #[inline]
fn to_le_bytes(self) -> Self::Bytes { fn to_le_bytes(self) -> Self::Bytes {
<$T>::to_le_bytes(self) <$T>::to_le_bytes(self)
} }
#[cfg(feature = "int_to_from_bytes")]
#[inline] #[inline]
fn to_ne_bytes(self) -> Self::Bytes { fn to_ne_bytes(self) -> Self::Bytes {
<$T>::to_ne_bytes(self) <$T>::to_ne_bytes(self)
} }
#[cfg(feature = "int_to_from_bytes")]
#[inline] #[inline]
fn from_be_bytes(bytes: Self::Bytes) -> Self { fn from_be_bytes(bytes: Self::Bytes) -> Self {
<$T>::from_be_bytes(bytes) <$T>::from_be_bytes(bytes)
} }
#[cfg(feature = "int_to_from_bytes")]
#[inline] #[inline]
fn from_le_bytes(bytes: Self::Bytes) -> Self { fn from_le_bytes(bytes: Self::Bytes) -> Self {
<$T>::from_le_bytes(bytes) <$T>::from_le_bytes(bytes)
} }
#[cfg(feature = "int_to_from_bytes")]
#[inline] #[inline]
fn from_ne_bytes(bytes: Self::Bytes) -> Self { fn from_ne_bytes(bytes: Self::Bytes) -> Self {
<$T>::from_ne_bytes(bytes) <$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] #[inline]
fn to_be_bytes(self) -> Self::Bytes { fn to_be_bytes(self) -> Self::Bytes {
<$T>::to_ne_bytes(<$T>::to_be(self)) <$T>::to_ne_bytes(<$T>::to_be(self))
} }
#[cfg(not(feature = "int_to_from_bytes"))]
#[inline] #[inline]
fn to_le_bytes(self) -> Self::Bytes { fn to_le_bytes(self) -> Self::Bytes {
<$T>::to_ne_bytes(<$T>::to_le(self)) <$T>::to_ne_bytes(<$T>::to_le(self))
} }
#[cfg(not(feature = "int_to_from_bytes"))]
#[inline] #[inline]
fn to_ne_bytes(self) -> Self::Bytes { fn to_ne_bytes(self) -> Self::Bytes {
unsafe { transmute(self) } unsafe { transmute(self) }
} }
#[cfg(not(feature = "int_to_from_bytes"))]
#[inline] #[inline]
fn from_be_bytes(bytes: Self::Bytes) -> Self { fn from_be_bytes(bytes: Self::Bytes) -> Self {
Self::from_be(Self::from_ne_bytes(bytes)) Self::from_be(Self::from_ne_bytes(bytes))
} }
#[cfg(not(feature = "int_to_from_bytes"))]
#[inline] #[inline]
fn from_le_bytes(bytes: Self::Bytes) -> Self { fn from_le_bytes(bytes: Self::Bytes) -> Self {
Self::from_le(Self::from_ne_bytes(bytes)) Self::from_le(Self::from_ne_bytes(bytes))
} }
#[cfg(not(feature = "int_to_from_bytes"))]
#[inline] #[inline]
fn from_ne_bytes(bytes: Self::Bytes) -> Self { fn from_ne_bytes(bytes: Self::Bytes) -> Self {
unsafe { transmute(bytes) } unsafe { transmute(bytes) }
} }
} }
impl Layout for $T {
type Bytes = [u8; $L];
}
}; };
} }

View File

@ -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 real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`.
pub use cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive}; pub use cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive};
pub use identities::{one, zero, One, Zero}; 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::{ pub use ops::checked::{
CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub,
}; };

95
src/ops/bytes.rs Normal file
View File

@ -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;
}

View File

@ -3,3 +3,4 @@ pub mod inv;
pub mod mul_add; pub mod mul_add;
pub mod saturating; pub mod saturating;
pub mod wrapping; pub mod wrapping;
pub mod bytes;