extract `IntToFromBytes` trait
This commit is contained in:
parent
45c399ffa7
commit
316120c611
|
@ -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 = []
|
|
||||||
|
|
22
build.rs
22
build.rs
|
@ -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,18 +9,18 @@ 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() {
|
||||||
|
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");
|
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!");
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test if a code snippet can be compiled
|
/// Test if a code snippet can be compiled
|
||||||
|
|
122
src/int.rs
122
src/int.rs
|
@ -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")]
|
#[cfg(feature = "int_to_from_bytes")]
|
||||||
|
impl IntToFromBytes for $T {
|
||||||
|
type Bytes = [u8; $L];
|
||||||
|
|
||||||
#[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"))]
|
#[cfg(not(feature = "int_to_from_bytes"))]
|
||||||
|
impl IntToFromBytes for $T {
|
||||||
|
type Bytes = [u8; $L];
|
||||||
|
|
||||||
#[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];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
Loading…
Reference in New Issue