From ef9c152205143424ad2471a04ddf145fdb51c56a Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 14 Jun 2014 22:53:55 -0700 Subject: [PATCH 1/7] Add a ByteOrder trait for abstracting over endian conversions The `Bitwise::swap_bytes` method was also moved into the `ByteOrder` trait. This was because it works on the byte level rather than the bit level. --- src/libcore/mem.rs | 336 +++++++++++++++++++++++---------- src/libcore/num/int_macros.rs | 11 -- src/libcore/num/mod.rs | 72 +++---- src/libcore/num/uint_macros.rs | 11 -- 4 files changed, 263 insertions(+), 167 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 237efcd0096d0..6b08a32944c96 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -13,6 +13,7 @@ //! This module contains functions for querying the size and alignment of //! types, initializing and manipulating memory. +use clone::Clone; use ptr; use intrinsics; use intrinsics::{bswap16, bswap32, bswap64}; @@ -169,151 +170,238 @@ pub unsafe fn move_val_init(dst: &mut T, src: T) { ptr::write(dst, src) } -/// Convert an u16 to little endian from the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn to_le16(x: u16) -> u16 { x } +/// A type that can have its bytes re-ordered. +pub trait ByteOrder: Clone { + /// Reverses the byte order of the value. + /// + /// # Example + /// + /// ```rust + /// use std::mem::ByteOrder; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xEFCDAB8967452301u64; + /// + /// assert_eq!(n.swap_bytes(), m); + /// ``` + fn swap_bytes(&self) -> Self; + + /// Convert a value from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// use std::mem::ByteOrder; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(ByteOrder::from_big_endian(n), n) + /// } else { + /// assert_eq!(ByteOrder::from_big_endian(n), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn from_big_endian(x: Self) -> Self { + if cfg!(target_endian = "big") { x } else { x.swap_bytes() } + } -/// Convert an u16 to little endian from the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn to_le16(x: u16) -> u16 { unsafe { bswap16(x) } } + /// Convert a value from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// use std::mem::ByteOrder; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(ByteOrder::from_little_endian(n), n) + /// } else { + /// assert_eq!(ByteOrder::from_little_endian(n), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn from_little_endian(x: Self) -> Self { + if cfg!(target_endian = "little") { x } else { x.swap_bytes() } + } -/// Convert an u32 to little endian from the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn to_le32(x: u32) -> u32 { x } + /// Convert the value to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// use std::mem::ByteOrder; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_big_endian(), n) + /// } else { + /// assert_eq!(n.to_big_endian(), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn to_big_endian(&self) -> Self { + if cfg!(target_endian = "big") { self.clone() } else { self.swap_bytes() } + } -/// Convert an u32 to little endian from the target's endianness. + /// Convert the value to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// use std::mem::ByteOrder; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_little_endian(), n) + /// } else { + /// assert_eq!(n.to_little_endian(), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn to_little_endian(&self) -> Self { + if cfg!(target_endian = "little") { self.clone() } else { self.swap_bytes() } + } +} + +impl ByteOrder for u8 { + #[inline] + fn swap_bytes(&self) -> u8 { + *self // swapping a single byte does nothing + } +} + +impl ByteOrder for u16 { + #[inline] + fn swap_bytes(&self) -> u16 { + unsafe { intrinsics::bswap16(*self) } + } +} + +impl ByteOrder for u32 { + #[inline] + fn swap_bytes(&self) -> u32 { + unsafe { intrinsics::bswap32(*self) } + } +} + +impl ByteOrder for u64 { + #[inline] + fn swap_bytes(&self) -> u64 { + unsafe { intrinsics::bswap64(*self) } + } +} + +#[cfg(target_word_size = "32")] +impl ByteOrder for uint { + #[inline] + fn swap_bytes(&self) -> uint { + (*self as u32).swap_bytes() as uint + } +} + +#[cfg(target_word_size = "64")] +impl ByteOrder for uint { + #[inline] + fn swap_bytes(&self) -> uint { + (*self as u64).swap_bytes() as uint + } +} + +/// Convert an u16 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn to_le32(x: u32) -> u32 { unsafe { bswap32(x) } } +#[inline] +#[stable] +pub fn to_le16(x: u16) -> u16 { x.to_little_endian() } -/// Convert an u64 to little endian from the target's endianness. +/// Convert an u32 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn to_le64(x: u64) -> u64 { x } +#[inline] +#[stable] +pub fn to_le32(x: u32) -> u32 { x.to_little_endian() } /// Convert an u64 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn to_le64(x: u64) -> u64 { unsafe { bswap64(x) } } - - -/// Convert an u16 to big endian from the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn to_be16(x: u16) -> u16 { unsafe { bswap16(x) } } +#[inline] +#[stable] +pub fn to_le64(x: u64) -> u64 { x.to_little_endian() } /// Convert an u16 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn to_be16(x: u16) -> u16 { x } - -/// Convert an u32 to big endian from the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn to_be32(x: u32) -> u32 { unsafe { bswap32(x) } } +#[inline] +#[stable] +pub fn to_be16(x: u16) -> u16 { x.to_big_endian() } /// Convert an u32 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn to_be32(x: u32) -> u32 { x } - -/// Convert an u64 to big endian from the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn to_be64(x: u64) -> u64 { unsafe { bswap64(x) } } +#[inline] +#[stable] +pub fn to_be32(x: u32) -> u32 { x.to_big_endian() } /// Convert an u64 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn to_be64(x: u64) -> u64 { x } - - -/// Convert an u16 from little endian to the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn from_le16(x: u16) -> u16 { x } +#[inline] +#[stable] +pub fn to_be64(x: u64) -> u64 { x.to_big_endian() } /// Convert an u16 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn from_le16(x: u16) -> u16 { unsafe { bswap16(x) } } - -/// Convert an u32 from little endian to the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn from_le32(x: u32) -> u32 { x } +#[inline] +#[stable] +pub fn from_le16(x: u16) -> u16 { ByteOrder::from_little_endian(x) } /// Convert an u32 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn from_le32(x: u32) -> u32 { unsafe { bswap32(x) } } - -/// Convert an u64 from little endian to the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn from_le64(x: u64) -> u64 { x } +#[inline] +#[stable] +pub fn from_le32(x: u32) -> u32 { ByteOrder::from_little_endian(x) } /// Convert an u64 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn from_le64(x: u64) -> u64 { unsafe { bswap64(x) } } - - -/// Convert an u16 from big endian to the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn from_be16(x: u16) -> u16 { unsafe { bswap16(x) } } +#[inline] +#[stable] +pub fn from_le64(x: u64) -> u64 { ByteOrder::from_little_endian(x) } /// Convert an u16 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn from_be16(x: u16) -> u16 { x } - -/// Convert an u32 from big endian to the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn from_be32(x: u32) -> u32 { unsafe { bswap32(x) } } +#[inline] +#[stable] +pub fn from_be16(x: u16) -> u16 { ByteOrder::from_big_endian(x) } /// Convert an u32 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn from_be32(x: u32) -> u32 { x } - -/// Convert an u64 from big endian to the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn from_be64(x: u64) -> u64 { unsafe { bswap64(x) } } +#[inline] +#[stable] +pub fn from_be32(x: u32) -> u32 { ByteOrder::from_big_endian(x) } /// Convert an u64 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn from_be64(x: u64) -> u64 { x } +#[inline] +#[stable] +pub fn from_be64(x: u64) -> u64 { ByteOrder::from_big_endian(x) } /** * Swap the values at two mutable locations of the same type, without @@ -558,6 +646,60 @@ mod tests { assert!(Vec::from_slice([76u8]) == transmute("L".to_string())); } } + + macro_rules! test_byte_order { + ($T:ident) => { + mod $T { + use mem::ByteOrder; + + static A: $T = 0b0101100; + static B: $T = 0b0100001; + static C: $T = 0b1111001; + + static _0: $T = 0; + static _1: $T = !0; + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_little_endian() { + assert_eq!(ByteOrder::from_little_endian(A.to_little_endian()), A); + assert_eq!(ByteOrder::from_little_endian(B.to_little_endian()), B); + assert_eq!(ByteOrder::from_little_endian(C.to_little_endian()), C); + assert_eq!(ByteOrder::from_little_endian(_0), _0); + assert_eq!(ByteOrder::from_little_endian(_1), _1); + assert_eq!(_0.to_little_endian(), _0); + assert_eq!(_1.to_little_endian(), _1); + } + + #[test] + fn test_big_endian() { + assert_eq!(ByteOrder::from_big_endian(A.to_big_endian()), A); + assert_eq!(ByteOrder::from_big_endian(B.to_big_endian()), B); + assert_eq!(ByteOrder::from_big_endian(C.to_big_endian()), C); + assert_eq!(ByteOrder::from_big_endian(_0), _0); + assert_eq!(ByteOrder::from_big_endian(_1), _1); + assert_eq!(_0.to_big_endian(), _0); + assert_eq!(_1.to_big_endian(), _1); + } + } + } + } + + test_byte_order!(u8) + test_byte_order!(u16) + test_byte_order!(u32) + test_byte_order!(u64) + test_byte_order!(uint) } // FIXME #13642 (these benchmarks should be in another place) diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 20bb12db694c0..8a1bd66aa1acc 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -113,17 +113,6 @@ mod tests { assert!((0b1111001 as $T).count_zeros() == BITS as $T - 5); } - #[test] - fn test_swap_bytes() { - let n: $T = 0b0101100; assert_eq!(n.swap_bytes().swap_bytes(), n); - let n: $T = 0b0100001; assert_eq!(n.swap_bytes().swap_bytes(), n); - let n: $T = 0b1111001; assert_eq!(n.swap_bytes().swap_bytes(), n); - - // Swapping these should make no difference - let n: $T = 0; assert_eq!(n.swap_bytes(), n); - let n: $T = -1; assert_eq!(n.swap_bytes(), n); - } - #[test] fn test_rotate() { let n: $T = 0b0101100; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index eaa632be6d04c..696abc05ed275 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -437,19 +437,6 @@ pub trait Bitwise: Bounded /// ``` fn trailing_zeros(&self) -> Self; - /// Reverses the byte order of a binary number. - /// - /// # Example - /// - /// ```rust - /// use std::num::Bitwise; - /// - /// let n = 0x0123456789ABCDEFu64; - /// let m = 0xEFCDAB8967452301u64; - /// assert_eq!(n.swap_bytes(), m); - /// ``` - fn swap_bytes(&self) -> Self; - /// Shifts the bits to the left by a specified amount amount, `r`, wrapping /// the truncated bits to the end of the resulting value. /// @@ -479,25 +466,17 @@ pub trait Bitwise: Bounded fn rotate_right(&self, r: uint) -> Self; } -/// Swapping a single byte does nothing. This is unsafe to be consistent with -/// the other `bswap` intrinsics. -#[inline] -unsafe fn bswap8(x: u8) -> u8 { x } - -macro_rules! bitwise_impl( - ($t:ty, $bits:expr, $co:ident, $lz:ident, $tz:ident, $bs:path) => { +macro_rules! bitwise_impl { + ($t:ty, $bits:expr, $co:path, $lz:path, $tz:path) => { impl Bitwise for $t { #[inline] - fn count_ones(&self) -> $t { unsafe { intrinsics::$co(*self) } } - - #[inline] - fn leading_zeros(&self) -> $t { unsafe { intrinsics::$lz(*self) } } + fn count_ones(&self) -> $t { unsafe { $co(*self) } } #[inline] - fn trailing_zeros(&self) -> $t { unsafe { intrinsics::$tz(*self) } } + fn leading_zeros(&self) -> $t { unsafe { $lz(*self) } } #[inline] - fn swap_bytes(&self) -> $t { unsafe { $bs(*self) } } + fn trailing_zeros(&self) -> $t { unsafe { $tz(*self) } } #[inline] fn rotate_left(&self, r: uint) -> $t { @@ -514,22 +493,19 @@ macro_rules! bitwise_impl( } } } -) +} -macro_rules! bitwise_cast_impl( - ($t:ty, $t_cast:ty, $bits:expr, $co:ident, $lz:ident, $tz:ident, $bs:path) => { +macro_rules! bitwise_cast_impl { + ($t:ty, $t_cast:ty, $bits:expr, $co:path, $lz:path, $tz:path) => { impl Bitwise for $t { #[inline] - fn count_ones(&self) -> $t { unsafe { intrinsics::$co(*self as $t_cast) as $t } } + fn count_ones(&self) -> $t { unsafe { $co(*self as $t_cast) as $t } } #[inline] - fn leading_zeros(&self) -> $t { unsafe { intrinsics::$lz(*self as $t_cast) as $t } } + fn leading_zeros(&self) -> $t { unsafe { $lz(*self as $t_cast) as $t } } #[inline] - fn trailing_zeros(&self) -> $t { unsafe { intrinsics::$tz(*self as $t_cast) as $t } } - - #[inline] - fn swap_bytes(&self) -> $t { unsafe { $bs(*self as $t_cast) as $t } } + fn trailing_zeros(&self) -> $t { unsafe { $tz(*self as $t_cast) as $t } } #[inline] fn rotate_left(&self, r: uint) -> $t { @@ -544,27 +520,27 @@ macro_rules! bitwise_cast_impl( } } } -) +} #[cfg(target_word_size = "32")] -bitwise_cast_impl!(uint, u32, 32, ctpop32, ctlz32, cttz32, intrinsics::bswap32) +bitwise_cast_impl!(uint, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) #[cfg(target_word_size = "64")] -bitwise_cast_impl!(uint, u64, 64, ctpop64, ctlz64, cttz64, intrinsics::bswap64) +bitwise_cast_impl!(uint, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) -bitwise_impl!(u8, 8, ctpop8, ctlz8, cttz8, bswap8) -bitwise_impl!(u16, 16, ctpop16, ctlz16, cttz16, intrinsics::bswap16) -bitwise_impl!(u32, 32, ctpop32, ctlz32, cttz32, intrinsics::bswap32) -bitwise_impl!(u64, 64, ctpop64, ctlz64, cttz64, intrinsics::bswap64) +bitwise_impl!(u8, 8, intrinsics::ctpop8, intrinsics::ctlz8, intrinsics::cttz8) +bitwise_impl!(u16, 16, intrinsics::ctpop16, intrinsics::ctlz16, intrinsics::cttz16) +bitwise_impl!(u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) +bitwise_impl!(u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) #[cfg(target_word_size = "32")] -bitwise_cast_impl!(int, u32, 32, ctpop32, ctlz32, cttz32, intrinsics::bswap32) +bitwise_cast_impl!(int, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) #[cfg(target_word_size = "64")] -bitwise_cast_impl!(int, u64, 64, ctpop64, ctlz64, cttz64, intrinsics::bswap64) +bitwise_cast_impl!(int, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) -bitwise_cast_impl!(i8, u8, 8, ctpop8, ctlz8, cttz8, bswap8) -bitwise_cast_impl!(i16, u16, 16, ctpop16, ctlz16, cttz16, intrinsics::bswap16) -bitwise_cast_impl!(i32, u32, 32, ctpop32, ctlz32, cttz32, intrinsics::bswap32) -bitwise_cast_impl!(i64, u64, 64, ctpop64, ctlz64, cttz64, intrinsics::bswap64) +bitwise_cast_impl!(i8, u8, 8, intrinsics::ctpop8, intrinsics::ctlz8, intrinsics::cttz8) +bitwise_cast_impl!(i16, u16, 16, intrinsics::ctpop16, intrinsics::ctlz16, intrinsics::cttz16) +bitwise_cast_impl!(i32, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) +bitwise_cast_impl!(i64, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) /// Specifies the available operations common to all of Rust's core numeric primitives. /// These may not always make sense from a purely mathematical point of view, but diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index 8e4ba10154244..8548b14105394 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -64,17 +64,6 @@ mod tests { assert!((0b1111001 as $T).count_zeros() == BITS as $T - 5); } - #[test] - fn test_swap_bytes() { - let n: $T = 0b0101100; assert_eq!(n.swap_bytes().swap_bytes(), n); - let n: $T = 0b0100001; assert_eq!(n.swap_bytes().swap_bytes(), n); - let n: $T = 0b1111001; assert_eq!(n.swap_bytes().swap_bytes(), n); - - // Swapping these should make no difference - let n: $T = 0; assert_eq!(n.swap_bytes(), n); - let n: $T = MAX; assert_eq!(n.swap_bytes(), n); - } - #[test] fn test_rotate() { let n: $T = 0b0101100; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); From a2045b2a2827a6c1e9a0f297e43e94624c5f07a9 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 14 Jun 2014 23:11:33 -0700 Subject: [PATCH 2/7] Use ByteOrder methods instead of free-standing functions --- src/libcollections/hash/mod.rs | 61 +++++++++++++--------------------- src/libnative/io/net.rs | 9 ++--- src/librustuv/net.rs | 10 +++--- src/libserialize/ebml.rs | 4 +-- src/libuuid/lib.rs | 16 ++++----- 5 files changed, 44 insertions(+), 56 deletions(-) diff --git a/src/libcollections/hash/mod.rs b/src/libcollections/hash/mod.rs index bd7bab456ba01..80417e2a57986 100644 --- a/src/libcollections/hash/mod.rs +++ b/src/libcollections/hash/mod.rs @@ -98,46 +98,31 @@ pub trait Writer { ////////////////////////////////////////////////////////////////////////////// -fn id(t: T) -> T { t } - -macro_rules! impl_hash( - ( $($ty:ident, $uty:ident, $f:path;)* ) => ( - $( - impl Hash for $ty { - #[inline] - fn hash(&self, state: &mut S) { - let a: [u8, ..::core::$ty::BYTES] = unsafe { - mem::transmute($f(*self as $uty) as $ty) - }; - state.write(a.as_slice()) - } +macro_rules! impl_hash { + ($ty:ident, $uty:ident) => { + impl Hash for $ty { + #[inline] + fn hash(&self, state: &mut S) { + use core::mem::ByteOrder; + let a: [u8, ..::core::$ty::BYTES] = unsafe { + mem::transmute((*self as $uty).to_little_endian() as $ty) + }; + state.write(a.as_slice()) } - )* - ) -) - -impl_hash!( - u8, u8, id; - u16, u16, mem::to_le16; - u32, u32, mem::to_le32; - u64, u64, mem::to_le64; - i8, u8, id; - i16, u16, mem::to_le16; - i32, u32, mem::to_le32; - i64, u64, mem::to_le64; -) - -#[cfg(target_word_size = "32")] -impl_hash!( - uint, u32, mem::to_le32; - int, u32, mem::to_le32; -) + } + } +} -#[cfg(target_word_size = "64")] -impl_hash!( - uint, u64, mem::to_le64; - int, u64, mem::to_le64; -) +impl_hash!(u8, u8) +impl_hash!(u16, u16) +impl_hash!(u32, u32) +impl_hash!(u64, u64) +impl_hash!(uint, uint) +impl_hash!(i8, u8) +impl_hash!(i16, u16) +impl_hash!(i32, u32) +impl_hash!(i64, u64) +impl_hash!(int, uint) impl Hash for bool { #[inline] diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index 1c33114dc7173..0e83514454f19 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -11,6 +11,7 @@ use alloc::arc::Arc; use libc; use std::mem; +use std::mem::ByteOrder; use std::rt::mutex; use std::rt::rtio; use std::rt::rtio::{IoResult, IoError}; @@ -27,10 +28,10 @@ use super::util; #[cfg(unix)] pub type sock_t = super::file::fd_t; pub fn htons(u: u16) -> u16 { - mem::to_be16(u) + u.to_big_endian() } pub fn ntohs(u: u16) -> u16 { - mem::from_be16(u) + ByteOrder::from_big_endian(u) } enum InAddr { @@ -46,7 +47,7 @@ fn ip_to_inaddr(ip: rtio::IpAddr) -> InAddr { (c as u32 << 8) | (d as u32 << 0); InAddr(libc::in_addr { - s_addr: mem::from_be32(ip) + s_addr: ByteOrder::from_big_endian(ip) }) } rtio::Ipv6Addr(a, b, c, d, e, f, g, h) => { @@ -180,7 +181,7 @@ pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, let storage: &libc::sockaddr_in = unsafe { mem::transmute(storage) }; - let ip = mem::to_be32(storage.sin_addr.s_addr as u32); + let ip = (storage.sin_addr.s_addr as u32).to_big_endian(); let a = (ip >> 24) as u8; let b = (ip >> 16) as u8; let c = (ip >> 8) as u8; diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs index 47b321b068b36..2d9b50f72a99b 100644 --- a/src/librustuv/net.rs +++ b/src/librustuv/net.rs @@ -11,6 +11,7 @@ use libc::{size_t, ssize_t, c_int, c_void, c_uint}; use libc; use std::mem; +use std::mem::ByteOrder; use std::ptr; use std::rt::rtio; use std::rt::rtio::IoError; @@ -30,8 +31,8 @@ use uvll; /// Generic functions related to dealing with sockaddr things //////////////////////////////////////////////////////////////////////////////// -pub fn htons(u: u16) -> u16 { mem::to_be16(u) } -pub fn ntohs(u: u16) -> u16 { mem::from_be16(u) } +pub fn htons(u: u16) -> u16 { u.to_big_endian() } +pub fn ntohs(u: u16) -> u16 { ByteOrder::from_big_endian(u) } pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, len: uint) -> rtio::SocketAddr { @@ -41,7 +42,7 @@ pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, let storage: &libc::sockaddr_in = unsafe { mem::transmute(storage) }; - let ip = mem::to_be32(storage.sin_addr.s_addr as u32); + let ip = (storage.sin_addr.s_addr as u32).to_big_endian(); let a = (ip >> 24) as u8; let b = (ip >> 16) as u8; let c = (ip >> 8) as u8; @@ -89,7 +90,8 @@ fn addr_to_sockaddr(addr: rtio::SocketAddr) -> (libc::sockaddr_storage, uint) { (*storage).sin_family = libc::AF_INET as libc::sa_family_t; (*storage).sin_port = htons(addr.port); (*storage).sin_addr = libc::in_addr { - s_addr: mem::from_be32(ip) + s_addr: ByteOrder::from_big_endian(ip), + }; mem::size_of::() } diff --git a/src/libserialize/ebml.rs b/src/libserialize/ebml.rs index 9ba2c2cd258ed..a1c79bc0b757c 100644 --- a/src/libserialize/ebml.rs +++ b/src/libserialize/ebml.rs @@ -154,7 +154,7 @@ pub mod reader { } pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult { - use std::mem::from_be32; + use std::mem::ByteOrder; if data.len() - start < 4 { return vuint_at_slow(data, start); @@ -185,7 +185,7 @@ pub mod reader { unsafe { let ptr = data.as_ptr().offset(start as int) as *u32; - let val = from_be32(*ptr); + let val = ByteOrder::from_big_endian(*ptr); let i = (val >> 28u) as uint; let (shift, mask) = SHIFT_MASK_TABLE[i]; diff --git a/src/libuuid/lib.rs b/src/libuuid/lib.rs index bace30e3f6ffd..1140f023d43fd 100644 --- a/src/libuuid/lib.rs +++ b/src/libuuid/lib.rs @@ -209,7 +209,7 @@ impl Uuid { /// * `d3` A 16-bit word /// * `d4` Array of 8 octets pub fn from_fields(d1: u32, d2: u16, d3: u16, d4: &[u8]) -> Uuid { - use std::mem::{to_be16, to_be32}; + use std::mem::ByteOrder; // First construct a temporary field-based struct let mut fields = UuidFields { @@ -219,9 +219,9 @@ impl Uuid { data4: [0, ..8] }; - fields.data1 = to_be32(d1); - fields.data2 = to_be16(d2); - fields.data3 = to_be16(d3); + fields.data1 = d1.to_big_endian(); + fields.data2 = d2.to_big_endian(); + fields.data3 = d3.to_big_endian(); slice::bytes::copy_memory(fields.data4, d4); unsafe { @@ -335,16 +335,16 @@ impl Uuid { /// /// Example: `550e8400-e29b-41d4-a716-446655440000` pub fn to_hyphenated_str(&self) -> String { - use std::mem::{to_be16, to_be32}; + use std::mem::ByteOrder; // Convert to field-based struct as it matches groups in output. // Ensure fields are in network byte order, as per RFC. let mut uf: UuidFields; unsafe { uf = transmute_copy(&self.bytes); } - uf.data1 = to_be32(uf.data1); - uf.data2 = to_be16(uf.data2); - uf.data3 = to_be16(uf.data3); + uf.data1 = uf.data1.to_big_endian(); + uf.data2 = uf.data2.to_big_endian(); + uf.data3 = uf.data3.to_big_endian(); let s = format!("{:08x}-{:04x}-{:04x}-{:02x}{:02x}-\ {:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", uf.data1, From 57cfe5b598ce211ba6e3b7b1c6be8310bc92b8d7 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 16 Jun 2014 00:22:51 -0700 Subject: [PATCH 3/7] Fix comment formatting --- src/libcore/mem.rs | 76 ++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 6b08a32944c96..b64ee9bf4f702 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -403,10 +403,8 @@ pub fn from_be32(x: u32) -> u32 { ByteOrder::from_big_endian(x) } #[stable] pub fn from_be64(x: u64) -> u64 { ByteOrder::from_big_endian(x) } -/** - * Swap the values at two mutable locations of the same type, without - * deinitialising or copying either one. - */ +/// Swap the values at two mutable locations of the same type, without +/// deinitialising or copying either one. #[inline] #[stable] pub fn swap(x: &mut T, y: &mut T) { @@ -425,42 +423,40 @@ pub fn swap(x: &mut T, y: &mut T) { } } -/** - * Replace the value at a mutable location with a new one, returning the old - * value, without deinitialising or copying either one. - * - * This is primarily used for transferring and swapping ownership of a value - * in a mutable location. For example, this function allows consumption of - * one field of a struct by replacing it with another value. The normal approach - * doesn't always work: - * - * ```rust,ignore - * struct Buffer { buf: Vec } - * - * impl Buffer { - * fn get_and_reset(&mut self) -> Vec { - * // error: cannot move out of dereference of `&mut`-pointer - * let buf = self.buf; - * self.buf = Vec::new(); - * buf - * } - * } - * ``` - * - * Note that `T` does not necessarily implement `Clone`, so it can't even - * clone and reset `self.buf`. But `replace` can be used to disassociate - * the original value of `self.buf` from `self`, allowing it to be returned: - * - * ```rust - * # struct Buffer { buf: Vec } - * impl Buffer { - * fn get_and_reset(&mut self) -> Vec { - * use std::mem::replace; - * replace(&mut self.buf, Vec::new()) - * } - * } - * ``` - */ +/// Replace the value at a mutable location with a new one, returning the old +/// value, without deinitialising or copying either one. +/// +/// This is primarily used for transferring and swapping ownership of a value +/// in a mutable location. For example, this function allows consumption of +/// one field of a struct by replacing it with another value. The normal approach +/// doesn't always work: +/// +/// ```rust,ignore +/// struct Buffer { buf: Vec } +/// +/// impl Buffer { +/// fn get_and_reset(&mut self) -> Vec { +/// // error: cannot move out of dereference of `&mut`-pointer +/// let buf = self.buf; +/// self.buf = Vec::new(); +/// buf +/// } +/// } +/// ``` +/// +/// Note that `T` does not necessarily implement `Clone`, so it can't even +/// clone and reset `self.buf`. But `replace` can be used to disassociate +/// the original value of `self.buf` from `self`, allowing it to be returned: +/// +/// ```rust +/// # struct Buffer { buf: Vec } +/// impl Buffer { +/// fn get_and_reset(&mut self) -> Vec { +/// use std::mem::replace; +/// replace(&mut self.buf, Vec::new()) +/// } +/// } +/// ``` #[inline] #[stable] pub fn replace(dest: &mut T, mut src: T) -> T { From 077813512f3722e8159dcc637efba3700b58018d Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 16 Jun 2014 11:25:47 -0700 Subject: [PATCH 4/7] Merge the Bitwise and ByteOrder traits into the Int trait This reduces the complexity of the trait hierarchy. --- src/libcollections/enum_set.rs | 2 - src/libcollections/hash/mod.rs | 1 - src/libcore/mem.rs | 220 +--------------------- src/libcore/num/int_macros.rs | 69 +++++-- src/libcore/num/mod.rs | 305 ++++++++++++++++++++----------- src/libcore/num/uint_macros.rs | 69 +++++-- src/libnative/io/net.rs | 5 +- src/libnum/bigint.rs | 2 +- src/librustc/middle/trans/adt.rs | 1 - src/librustuv/net.rs | 5 +- src/libserialize/ebml.rs | 4 +- src/libstd/num/mod.rs | 2 +- src/libuuid/lib.rs | 3 - src/test/bench/sudoku.rs | 1 - 14 files changed, 325 insertions(+), 364 deletions(-) diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 34514fde9dbd1..1360b412c2370 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -15,8 +15,6 @@ use core::prelude::*; -use core::num::Bitwise; - #[deriving(Clone, PartialEq, Eq, Hash, Show)] /// A specialized Set implementation to use enum types. pub struct EnumSet { diff --git a/src/libcollections/hash/mod.rs b/src/libcollections/hash/mod.rs index 80417e2a57986..07c768d0c7916 100644 --- a/src/libcollections/hash/mod.rs +++ b/src/libcollections/hash/mod.rs @@ -103,7 +103,6 @@ macro_rules! impl_hash { impl Hash for $ty { #[inline] fn hash(&self, state: &mut S) { - use core::mem::ByteOrder; let a: [u8, ..::core::$ty::BYTES] = unsafe { mem::transmute((*self as $uty).to_little_endian() as $ty) }; diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index b64ee9bf4f702..eab344ac7a701 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -13,10 +13,9 @@ //! This module contains functions for querying the size and alignment of //! types, initializing and manipulating memory. -use clone::Clone; -use ptr; use intrinsics; -use intrinsics::{bswap16, bswap32, bswap64}; +use num::Int; +use ptr; pub use intrinsics::transmute; @@ -170,155 +169,6 @@ pub unsafe fn move_val_init(dst: &mut T, src: T) { ptr::write(dst, src) } -/// A type that can have its bytes re-ordered. -pub trait ByteOrder: Clone { - /// Reverses the byte order of the value. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// let m = 0xEFCDAB8967452301u64; - /// - /// assert_eq!(n.swap_bytes(), m); - /// ``` - fn swap_bytes(&self) -> Self; - - /// Convert a value from big endian to the target's endianness. - /// - /// On big endian this is a no-op. On little endian the bytes are swapped. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "big") { - /// assert_eq!(ByteOrder::from_big_endian(n), n) - /// } else { - /// assert_eq!(ByteOrder::from_big_endian(n), n.swap_bytes()) - /// } - /// ``` - #[inline] - fn from_big_endian(x: Self) -> Self { - if cfg!(target_endian = "big") { x } else { x.swap_bytes() } - } - - /// Convert a value from little endian to the target's endianness. - /// - /// On little endian this is a no-op. On big endian the bytes are swapped. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "little") { - /// assert_eq!(ByteOrder::from_little_endian(n), n) - /// } else { - /// assert_eq!(ByteOrder::from_little_endian(n), n.swap_bytes()) - /// } - /// ``` - #[inline] - fn from_little_endian(x: Self) -> Self { - if cfg!(target_endian = "little") { x } else { x.swap_bytes() } - } - - /// Convert the value to big endian from the target's endianness. - /// - /// On big endian this is a no-op. On little endian the bytes are swapped. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "big") { - /// assert_eq!(n.to_big_endian(), n) - /// } else { - /// assert_eq!(n.to_big_endian(), n.swap_bytes()) - /// } - /// ``` - #[inline] - fn to_big_endian(&self) -> Self { - if cfg!(target_endian = "big") { self.clone() } else { self.swap_bytes() } - } - - /// Convert the value to little endian from the target's endianness. - /// - /// On little endian this is a no-op. On big endian the bytes are swapped. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "little") { - /// assert_eq!(n.to_little_endian(), n) - /// } else { - /// assert_eq!(n.to_little_endian(), n.swap_bytes()) - /// } - /// ``` - #[inline] - fn to_little_endian(&self) -> Self { - if cfg!(target_endian = "little") { self.clone() } else { self.swap_bytes() } - } -} - -impl ByteOrder for u8 { - #[inline] - fn swap_bytes(&self) -> u8 { - *self // swapping a single byte does nothing - } -} - -impl ByteOrder for u16 { - #[inline] - fn swap_bytes(&self) -> u16 { - unsafe { intrinsics::bswap16(*self) } - } -} - -impl ByteOrder for u32 { - #[inline] - fn swap_bytes(&self) -> u32 { - unsafe { intrinsics::bswap32(*self) } - } -} - -impl ByteOrder for u64 { - #[inline] - fn swap_bytes(&self) -> u64 { - unsafe { intrinsics::bswap64(*self) } - } -} - -#[cfg(target_word_size = "32")] -impl ByteOrder for uint { - #[inline] - fn swap_bytes(&self) -> uint { - (*self as u32).swap_bytes() as uint - } -} - -#[cfg(target_word_size = "64")] -impl ByteOrder for uint { - #[inline] - fn swap_bytes(&self) -> uint { - (*self as u64).swap_bytes() as uint - } -} - /// Convert an u16 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. @@ -366,42 +216,42 @@ pub fn to_be64(x: u64) -> u64 { x.to_big_endian() } /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] #[stable] -pub fn from_le16(x: u16) -> u16 { ByteOrder::from_little_endian(x) } +pub fn from_le16(x: u16) -> u16 { Int::from_little_endian(x) } /// Convert an u32 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] #[stable] -pub fn from_le32(x: u32) -> u32 { ByteOrder::from_little_endian(x) } +pub fn from_le32(x: u32) -> u32 { Int::from_little_endian(x) } /// Convert an u64 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] #[stable] -pub fn from_le64(x: u64) -> u64 { ByteOrder::from_little_endian(x) } +pub fn from_le64(x: u64) -> u64 { Int::from_little_endian(x) } /// Convert an u16 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] #[stable] -pub fn from_be16(x: u16) -> u16 { ByteOrder::from_big_endian(x) } +pub fn from_be16(x: u16) -> u16 { Int::from_big_endian(x) } /// Convert an u32 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] #[stable] -pub fn from_be32(x: u32) -> u32 { ByteOrder::from_big_endian(x) } +pub fn from_be32(x: u32) -> u32 { Int::from_big_endian(x) } /// Convert an u64 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] #[stable] -pub fn from_be64(x: u64) -> u64 { ByteOrder::from_big_endian(x) } +pub fn from_be64(x: u64) -> u64 { Int::from_big_endian(x) } /// Swap the values at two mutable locations of the same type, without /// deinitialising or copying either one. @@ -642,60 +492,6 @@ mod tests { assert!(Vec::from_slice([76u8]) == transmute("L".to_string())); } } - - macro_rules! test_byte_order { - ($T:ident) => { - mod $T { - use mem::ByteOrder; - - static A: $T = 0b0101100; - static B: $T = 0b0100001; - static C: $T = 0b1111001; - - static _0: $T = 0; - static _1: $T = !0; - - #[test] - fn test_swap_bytes() { - assert_eq!(A.swap_bytes().swap_bytes(), A); - assert_eq!(B.swap_bytes().swap_bytes(), B); - assert_eq!(C.swap_bytes().swap_bytes(), C); - - // Swapping these should make no difference - assert_eq!(_0.swap_bytes(), _0); - assert_eq!(_1.swap_bytes(), _1); - } - - #[test] - fn test_little_endian() { - assert_eq!(ByteOrder::from_little_endian(A.to_little_endian()), A); - assert_eq!(ByteOrder::from_little_endian(B.to_little_endian()), B); - assert_eq!(ByteOrder::from_little_endian(C.to_little_endian()), C); - assert_eq!(ByteOrder::from_little_endian(_0), _0); - assert_eq!(ByteOrder::from_little_endian(_1), _1); - assert_eq!(_0.to_little_endian(), _0); - assert_eq!(_1.to_little_endian(), _1); - } - - #[test] - fn test_big_endian() { - assert_eq!(ByteOrder::from_big_endian(A.to_big_endian()), A); - assert_eq!(ByteOrder::from_big_endian(B.to_big_endian()), B); - assert_eq!(ByteOrder::from_big_endian(C.to_big_endian()), C); - assert_eq!(ByteOrder::from_big_endian(_0), _0); - assert_eq!(ByteOrder::from_big_endian(_1), _1); - assert_eq!(_0.to_big_endian(), _0); - assert_eq!(_1.to_big_endian(), _1); - } - } - } - } - - test_byte_order!(u8) - test_byte_order!(u16) - test_byte_order!(u32) - test_byte_order!(u64) - test_byte_order!(uint) } // FIXME #13642 (these benchmarks should be in another place) diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 8a1bd66aa1acc..84744b3f5d701 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -35,7 +35,6 @@ mod tests { use int; use num; - use num::Bitwise; use num::CheckedDiv; #[test] @@ -90,7 +89,7 @@ mod tests { } #[test] - fn test_bitwise() { + fn test_bitwise_operators() { assert!(0b1110 as $T == (0b1100 as $T).bitor(&(0b1010 as $T))); assert!(0b1000 as $T == (0b1100 as $T).bitand(&(0b1010 as $T))); assert!(0b0110 as $T == (0b1100 as $T).bitxor(&(0b1010 as $T))); @@ -99,34 +98,74 @@ mod tests { assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not()); } + static A: $T = 0b0101100; + static B: $T = 0b0100001; + static C: $T = 0b1111001; + + static _0: $T = 0; + static _1: $T = !0; + #[test] fn test_count_ones() { - assert!((0b0101100 as $T).count_ones() == 3); - assert!((0b0100001 as $T).count_ones() == 2); - assert!((0b1111001 as $T).count_ones() == 5); + assert!(A.count_ones() == 3); + assert!(B.count_ones() == 2); + assert!(C.count_ones() == 5); } #[test] fn test_count_zeros() { - assert!((0b0101100 as $T).count_zeros() == BITS as $T - 3); - assert!((0b0100001 as $T).count_zeros() == BITS as $T - 2); - assert!((0b1111001 as $T).count_zeros() == BITS as $T - 5); + assert!(A.count_zeros() == BITS as $T - 3); + assert!(B.count_zeros() == BITS as $T - 2); + assert!(C.count_zeros() == BITS as $T - 5); } #[test] fn test_rotate() { - let n: $T = 0b0101100; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); - let n: $T = 0b0100001; assert_eq!(n.rotate_left(3).rotate_left(2).rotate_right(5), n); - let n: $T = 0b1111001; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); // Rotating these should make no difference // // We test using 124 bits because to ensure that overlong bit shifts do // not cause undefined behaviour. See #10183. - let n: $T = 0; assert_eq!(n.rotate_left(124), n); - let n: $T = -1; assert_eq!(n.rotate_left(124), n); - let n: $T = 0; assert_eq!(n.rotate_right(124), n); - let n: $T = -1; assert_eq!(n.rotate_right(124), n); + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + } + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_little_endian() { + assert_eq!(Int::from_little_endian(A.to_little_endian()), A); + assert_eq!(Int::from_little_endian(B.to_little_endian()), B); + assert_eq!(Int::from_little_endian(C.to_little_endian()), C); + assert_eq!(Int::from_little_endian(_0), _0); + assert_eq!(Int::from_little_endian(_1), _1); + assert_eq!(_0.to_little_endian(), _0); + assert_eq!(_1.to_little_endian(), _1); + } + + #[test] + fn test_big_endian() { + assert_eq!(Int::from_big_endian(A.to_big_endian()), A); + assert_eq!(Int::from_big_endian(B.to_big_endian()), B); + assert_eq!(Int::from_big_endian(C.to_big_endian()), C); + assert_eq!(Int::from_big_endian(_0), _0); + assert_eq!(Int::from_big_endian(_1), _1); + assert_eq!(_0.to_big_endian(), _0); + assert_eq!(_1.to_big_endian(), _1); } #[test] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 696abc05ed275..ed0c24e7fa008 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -376,193 +376,292 @@ bounded_impl!(i64, i64::MIN, i64::MAX) bounded_impl!(f32, f32::MIN_VALUE, f32::MAX_VALUE) bounded_impl!(f64, f64::MIN_VALUE, f64::MAX_VALUE) -/// Numbers with a fixed binary representation. -pub trait Bitwise: Bounded - + Not - + BitAnd - + BitOr - + BitXor - + Shl - + Shr { - /// Returns the number of ones in the binary representation of the number. +/// Specifies the available operations common to all of Rust's core numeric primitives. +/// These may not always make sense from a purely mathematical point of view, but +/// may be useful for systems programming. +pub trait Primitive: Copy + + Clone + + Num + + NumCast + + PartialOrd + + Bounded {} + +trait_impl!(Primitive for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64) + +/// A collection of traits relevant to primitive signed and unsigned integers +pub trait Int: Primitive + + CheckedAdd + + CheckedSub + + CheckedMul + + CheckedDiv + + Bounded + + Not + + BitAnd + + BitOr + + BitXor + + Shl + + Shr { + /// Returns the number of ones in the binary representation of the integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0b01001100u8; + /// /// assert_eq!(n.count_ones(), 3); /// ``` - fn count_ones(&self) -> Self; + fn count_ones(self) -> Self; - /// Returns the number of zeros in the binary representation of the number. + /// Returns the number of zeros in the binary representation of the integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0b01001100u8; + /// /// assert_eq!(n.count_zeros(), 5); /// ``` #[inline] - fn count_zeros(&self) -> Self { - (!*self).count_ones() + fn count_zeros(self) -> Self { + (!self).count_ones() } /// Returns the number of leading zeros in the in the binary representation - /// of the number. + /// of the integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0b0101000u16; + /// /// assert_eq!(n.leading_zeros(), 10); /// ``` - fn leading_zeros(&self) -> Self; + fn leading_zeros(self) -> Self; /// Returns the number of trailing zeros in the in the binary representation - /// of the number. + /// of the integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0b0101000u16; + /// /// assert_eq!(n.trailing_zeros(), 3); /// ``` - fn trailing_zeros(&self) -> Self; + fn trailing_zeros(self) -> Self; - /// Shifts the bits to the left by a specified amount amount, `r`, wrapping - /// the truncated bits to the end of the resulting value. + /// Shifts the bits to the left by a specified amount amount, `n`, wrapping + /// the truncated bits to the end of the resulting integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0x0123456789ABCDEFu64; /// let m = 0x3456789ABCDEF012u64; + /// /// assert_eq!(n.rotate_left(12), m); /// ``` - fn rotate_left(&self, r: uint) -> Self; + fn rotate_left(self, n: uint) -> Self; - /// Shifts the bits to the right by a specified amount amount, `r`, wrapping - /// the truncated bits to the beginning of the resulting value. + /// Shifts the bits to the right by a specified amount amount, `n`, wrapping + /// the truncated bits to the beginning of the resulting integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0x0123456789ABCDEFu64; /// let m = 0xDEF0123456789ABCu64; + /// /// assert_eq!(n.rotate_right(12), m); /// ``` - fn rotate_right(&self, r: uint) -> Self; + fn rotate_right(self, n: uint) -> Self; + + /// Reverses the byte order of the integer. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xEFCDAB8967452301u64; + /// + /// assert_eq!(n.swap_bytes(), m); + /// ``` + fn swap_bytes(self) -> Self; + + /// Convert a integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(Int::from_big_endian(n), n) + /// } else { + /// assert_eq!(Int::from_big_endian(n), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn from_big_endian(x: Self) -> Self { + if cfg!(target_endian = "big") { x } else { x.swap_bytes() } + } + + /// Convert a integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(Int::from_little_endian(n), n) + /// } else { + /// assert_eq!(Int::from_little_endian(n), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn from_little_endian(x: Self) -> Self { + if cfg!(target_endian = "little") { x } else { x.swap_bytes() } + } + + /// Convert the integer to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_big_endian(), n) + /// } else { + /// assert_eq!(n.to_big_endian(), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn to_big_endian(self) -> Self { + if cfg!(target_endian = "big") { self } else { self.swap_bytes() } + } + + /// Convert the integer to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_little_endian(), n) + /// } else { + /// assert_eq!(n.to_little_endian(), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn to_little_endian(self) -> Self { + if cfg!(target_endian = "little") { self } else { self.swap_bytes() } + } } -macro_rules! bitwise_impl { - ($t:ty, $bits:expr, $co:path, $lz:path, $tz:path) => { - impl Bitwise for $t { +macro_rules! int_impl { + ($T:ty, $BITS:expr, $ctpop:path, $ctlz:path, $cttz:path, $bswap:path) => { + impl Int for $T { #[inline] - fn count_ones(&self) -> $t { unsafe { $co(*self) } } + fn count_ones(self) -> $T { unsafe { $ctpop(self) } } #[inline] - fn leading_zeros(&self) -> $t { unsafe { $lz(*self) } } + fn leading_zeros(self) -> $T { unsafe { $ctlz(self) } } #[inline] - fn trailing_zeros(&self) -> $t { unsafe { $tz(*self) } } + fn trailing_zeros(self) -> $T { unsafe { $cttz(self) } } #[inline] - fn rotate_left(&self, r: uint) -> $t { - // Protect against undefined behaviour for overlong bit shifts - let r = r % $bits; - (*self << r) | (*self >> ($bits - r)) + fn rotate_left(self, n: uint) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self << n) | (self >> ($BITS - n)) } #[inline] - fn rotate_right(&self, r: uint) -> $t { - // Protect against undefined behaviour for overlong bit shifts - let r = r % $bits; - (*self >> r) | (*self << ($bits - r)) + fn rotate_right(self, n: uint) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self >> n) | (self << ($BITS - n)) } + + #[inline] + fn swap_bytes(self) -> $T { unsafe { $bswap(self) } } } } } -macro_rules! bitwise_cast_impl { - ($t:ty, $t_cast:ty, $bits:expr, $co:path, $lz:path, $tz:path) => { - impl Bitwise for $t { +/// Swapping a single byte is a no-op. This is marked as `unsafe` for +/// consistency with the other `bswap` intrinsics. +unsafe fn bswap8(x: u8) -> u8 { x } + +int_impl!(u8, 8, + intrinsics::ctpop8, + intrinsics::ctlz8, + intrinsics::cttz8, + bswap8) + +int_impl!(u16, 16, + intrinsics::ctpop16, + intrinsics::ctlz16, + intrinsics::cttz16, + intrinsics::bswap16) + +int_impl!(u32, 32, + intrinsics::ctpop32, + intrinsics::ctlz32, + intrinsics::cttz32, + intrinsics::bswap32) + +int_impl!(u64, 64, + intrinsics::ctpop64, + intrinsics::ctlz64, + intrinsics::cttz64, + intrinsics::bswap64) + +macro_rules! int_cast_impl { + ($T:ty, $U:ty) => { + impl Int for $T { #[inline] - fn count_ones(&self) -> $t { unsafe { $co(*self as $t_cast) as $t } } + fn count_ones(self) -> $T { (self as $U).count_ones() as $T } #[inline] - fn leading_zeros(&self) -> $t { unsafe { $lz(*self as $t_cast) as $t } } + fn leading_zeros(self) -> $T { (self as $U).leading_zeros() as $T } #[inline] - fn trailing_zeros(&self) -> $t { unsafe { $tz(*self as $t_cast) as $t } } + fn trailing_zeros(self) -> $T { (self as $U).trailing_zeros() as $T } #[inline] - fn rotate_left(&self, r: uint) -> $t { - // cast to prevent the sign bit from being corrupted - (*self as $t_cast).rotate_left(r) as $t - } + fn rotate_left(self, n: uint) -> $T { (self as $U).rotate_left(n) as $T } #[inline] - fn rotate_right(&self, r: uint) -> $t { - // cast to prevent the sign bit from being corrupted - (*self as $t_cast).rotate_right(r) as $t - } + fn rotate_right(self, n: uint) -> $T { (self as $U).rotate_right(n) as $T } + + #[inline] + fn swap_bytes(self) -> $T { (self as $U).swap_bytes() as $T } } } } -#[cfg(target_word_size = "32")] -bitwise_cast_impl!(uint, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) -#[cfg(target_word_size = "64")] -bitwise_cast_impl!(uint, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) - -bitwise_impl!(u8, 8, intrinsics::ctpop8, intrinsics::ctlz8, intrinsics::cttz8) -bitwise_impl!(u16, 16, intrinsics::ctpop16, intrinsics::ctlz16, intrinsics::cttz16) -bitwise_impl!(u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) -bitwise_impl!(u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) - -#[cfg(target_word_size = "32")] -bitwise_cast_impl!(int, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) -#[cfg(target_word_size = "64")] -bitwise_cast_impl!(int, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) - -bitwise_cast_impl!(i8, u8, 8, intrinsics::ctpop8, intrinsics::ctlz8, intrinsics::cttz8) -bitwise_cast_impl!(i16, u16, 16, intrinsics::ctpop16, intrinsics::ctlz16, intrinsics::cttz16) -bitwise_cast_impl!(i32, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) -bitwise_cast_impl!(i64, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) - -/// Specifies the available operations common to all of Rust's core numeric primitives. -/// These may not always make sense from a purely mathematical point of view, but -/// may be useful for systems programming. -pub trait Primitive: Copy - + Clone - + Num - + NumCast - + PartialOrd - + Bounded {} - -trait_impl!(Primitive for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64) - -/// A collection of traits relevant to primitive signed and unsigned integers -pub trait Int: Primitive - + Bitwise - + CheckedAdd - + CheckedSub - + CheckedMul - + CheckedDiv {} +int_cast_impl!(i8, u8) +int_cast_impl!(i16, u16) +int_cast_impl!(i32, u32) +int_cast_impl!(i64, u64) -trait_impl!(Int for uint u8 u16 u32 u64 int i8 i16 i32 i64) +#[cfg(target_word_size = "32")] int_cast_impl!(uint, u32) +#[cfg(target_word_size = "64")] int_cast_impl!(uint, u64) +#[cfg(target_word_size = "32")] int_cast_impl!(int, u32) +#[cfg(target_word_size = "64")] int_cast_impl!(int, u64) /// Returns the smallest power of 2 greater than or equal to `n`. #[inline] diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index 8548b14105394..1fe3c4cf1f1cf 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -26,7 +26,6 @@ mod tests { use num; use num::CheckedDiv; - use num::Bitwise; #[test] fn test_overflows() { @@ -41,7 +40,7 @@ mod tests { } #[test] - fn test_bitwise() { + fn test_bitwise_operators() { assert!(0b1110 as $T == (0b1100 as $T).bitor(&(0b1010 as $T))); assert!(0b1000 as $T == (0b1100 as $T).bitand(&(0b1010 as $T))); assert!(0b0110 as $T == (0b1100 as $T).bitxor(&(0b1010 as $T))); @@ -50,34 +49,74 @@ mod tests { assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not()); } + static A: $T = 0b0101100; + static B: $T = 0b0100001; + static C: $T = 0b1111001; + + static _0: $T = 0; + static _1: $T = !0; + #[test] fn test_count_ones() { - assert!((0b0101100 as $T).count_ones() == 3); - assert!((0b0100001 as $T).count_ones() == 2); - assert!((0b1111001 as $T).count_ones() == 5); + assert!(A.count_ones() == 3); + assert!(B.count_ones() == 2); + assert!(C.count_ones() == 5); } #[test] fn test_count_zeros() { - assert!((0b0101100 as $T).count_zeros() == BITS as $T - 3); - assert!((0b0100001 as $T).count_zeros() == BITS as $T - 2); - assert!((0b1111001 as $T).count_zeros() == BITS as $T - 5); + assert!(A.count_zeros() == BITS as $T - 3); + assert!(B.count_zeros() == BITS as $T - 2); + assert!(C.count_zeros() == BITS as $T - 5); } #[test] fn test_rotate() { - let n: $T = 0b0101100; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); - let n: $T = 0b0100001; assert_eq!(n.rotate_left(3).rotate_left(2).rotate_right(5), n); - let n: $T = 0b1111001; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); // Rotating these should make no difference // // We test using 124 bits because to ensure that overlong bit shifts do // not cause undefined behaviour. See #10183. - let n: $T = 0; assert_eq!(n.rotate_left(124), n); - let n: $T = MAX; assert_eq!(n.rotate_left(124), n); - let n: $T = 0; assert_eq!(n.rotate_right(124), n); - let n: $T = MAX; assert_eq!(n.rotate_right(124), n); + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + } + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_little_endian() { + assert_eq!(Int::from_little_endian(A.to_little_endian()), A); + assert_eq!(Int::from_little_endian(B.to_little_endian()), B); + assert_eq!(Int::from_little_endian(C.to_little_endian()), C); + assert_eq!(Int::from_little_endian(_0), _0); + assert_eq!(Int::from_little_endian(_1), _1); + assert_eq!(_0.to_little_endian(), _0); + assert_eq!(_1.to_little_endian(), _1); + } + + #[test] + fn test_big_endian() { + assert_eq!(Int::from_big_endian(A.to_big_endian()), A); + assert_eq!(Int::from_big_endian(B.to_big_endian()), B); + assert_eq!(Int::from_big_endian(C.to_big_endian()), C); + assert_eq!(Int::from_big_endian(_0), _0); + assert_eq!(Int::from_big_endian(_1), _1); + assert_eq!(_0.to_big_endian(), _0); + assert_eq!(_1.to_big_endian(), _1); } #[test] diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index 0e83514454f19..6822398fc08bb 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -11,7 +11,6 @@ use alloc::arc::Arc; use libc; use std::mem; -use std::mem::ByteOrder; use std::rt::mutex; use std::rt::rtio; use std::rt::rtio::{IoResult, IoError}; @@ -31,7 +30,7 @@ pub fn htons(u: u16) -> u16 { u.to_big_endian() } pub fn ntohs(u: u16) -> u16 { - ByteOrder::from_big_endian(u) + Int::from_big_endian(u) } enum InAddr { @@ -47,7 +46,7 @@ fn ip_to_inaddr(ip: rtio::IpAddr) -> InAddr { (c as u32 << 8) | (d as u32 << 0); InAddr(libc::in_addr { - s_addr: ByteOrder::from_big_endian(ip) + s_addr: Int::from_big_endian(ip) }) } rtio::Ipv6Addr(a, b, c, d, e, f, g, h) => { diff --git a/src/libnum/bigint.rs b/src/libnum/bigint.rs index 0933301970d19..e9153f89e04ee 100644 --- a/src/libnum/bigint.rs +++ b/src/libnum/bigint.rs @@ -23,7 +23,7 @@ use std::{cmp, fmt}; use std::default::Default; use std::from_str::FromStr; use std::num::CheckedDiv; -use std::num::{Bitwise, ToPrimitive, FromPrimitive}; +use std::num::{ToPrimitive, FromPrimitive}; use std::num::{Zero, One, ToStrRadix, FromStrRadix}; use std::string::String; use std::{uint, i64, u64}; diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 1b530ea342491..082dce4ea473d 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -46,7 +46,6 @@ #![allow(unsigned_negate)] use libc::c_ulonglong; -use std::num::{Bitwise}; use std::rc::Rc; use lib::llvm::{ValueRef, True, IntEQ, IntNE}; diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs index 2d9b50f72a99b..8217989d00e61 100644 --- a/src/librustuv/net.rs +++ b/src/librustuv/net.rs @@ -11,7 +11,6 @@ use libc::{size_t, ssize_t, c_int, c_void, c_uint}; use libc; use std::mem; -use std::mem::ByteOrder; use std::ptr; use std::rt::rtio; use std::rt::rtio::IoError; @@ -32,7 +31,7 @@ use uvll; //////////////////////////////////////////////////////////////////////////////// pub fn htons(u: u16) -> u16 { u.to_big_endian() } -pub fn ntohs(u: u16) -> u16 { ByteOrder::from_big_endian(u) } +pub fn ntohs(u: u16) -> u16 { Int::from_big_endian(u) } pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, len: uint) -> rtio::SocketAddr { @@ -90,7 +89,7 @@ fn addr_to_sockaddr(addr: rtio::SocketAddr) -> (libc::sockaddr_storage, uint) { (*storage).sin_family = libc::AF_INET as libc::sa_family_t; (*storage).sin_port = htons(addr.port); (*storage).sin_addr = libc::in_addr { - s_addr: ByteOrder::from_big_endian(ip), + s_addr: Int::from_big_endian(ip), }; mem::size_of::() diff --git a/src/libserialize/ebml.rs b/src/libserialize/ebml.rs index a1c79bc0b757c..7d0c82fc9a2d5 100644 --- a/src/libserialize/ebml.rs +++ b/src/libserialize/ebml.rs @@ -154,8 +154,6 @@ pub mod reader { } pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult { - use std::mem::ByteOrder; - if data.len() - start < 4 { return vuint_at_slow(data, start); } @@ -185,7 +183,7 @@ pub mod reader { unsafe { let ptr = data.as_ptr().offset(start as int) as *u32; - let val = ByteOrder::from_big_endian(*ptr); + let val = Int::from_big_endian(*ptr); let i = (val >> 28u) as uint; let (shift, mask) = SHIFT_MASK_TABLE[i]; diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 602a2240f3908..7301f9b08e9dc 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -22,7 +22,7 @@ use string::String; pub use core::num::{Num, div_rem, Zero, zero, One, one}; pub use core::num::{Signed, abs, abs_sub, signum}; -pub use core::num::{Unsigned, pow, Bounded, Bitwise}; +pub use core::num::{Unsigned, pow, Bounded}; pub use core::num::{Primitive, Int, Saturating}; pub use core::num::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv}; pub use core::num::{cast, FromPrimitive, NumCast, ToPrimitive}; diff --git a/src/libuuid/lib.rs b/src/libuuid/lib.rs index 1140f023d43fd..bbd461e3dde0d 100644 --- a/src/libuuid/lib.rs +++ b/src/libuuid/lib.rs @@ -209,8 +209,6 @@ impl Uuid { /// * `d3` A 16-bit word /// * `d4` Array of 8 octets pub fn from_fields(d1: u32, d2: u16, d3: u16, d4: &[u8]) -> Uuid { - use std::mem::ByteOrder; - // First construct a temporary field-based struct let mut fields = UuidFields { data1: 0, @@ -335,7 +333,6 @@ impl Uuid { /// /// Example: `550e8400-e29b-41d4-a716-446655440000` pub fn to_hyphenated_str(&self) -> String { - use std::mem::ByteOrder; // Convert to field-based struct as it matches groups in output. // Ensure fields are in network byte order, as per RFC. let mut uf: UuidFields; diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index c0ea6f8617d87..af51157bba564 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -16,7 +16,6 @@ use std::io; use std::io::stdio::StdReader; use std::io::BufferedReader; -use std::num::Bitwise; use std::os; // Computes a single solution to a given 9x9 sudoku From ee7e0b8dab0739701c69112998b5ceedd2329388 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 16 Jun 2014 14:33:45 -0700 Subject: [PATCH 5/7] Remove `#[stable]` attribute from free-standing endian conversions and mark them as deprecated --- src/libcore/mem.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index eab344ac7a701..1032b820b2751 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -173,84 +173,84 @@ pub unsafe fn move_val_init(dst: &mut T, src: T) { /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::to_little_endian` instead"] pub fn to_le16(x: u16) -> u16 { x.to_little_endian() } /// Convert an u32 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::to_little_endian` instead"] pub fn to_le32(x: u32) -> u32 { x.to_little_endian() } /// Convert an u64 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::to_little_endian` instead"] pub fn to_le64(x: u64) -> u64 { x.to_little_endian() } /// Convert an u16 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::to_big_endian` instead"] pub fn to_be16(x: u16) -> u16 { x.to_big_endian() } /// Convert an u32 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::to_big_endian` instead"] pub fn to_be32(x: u32) -> u32 { x.to_big_endian() } /// Convert an u64 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::to_big_endian` instead"] pub fn to_be64(x: u64) -> u64 { x.to_big_endian() } /// Convert an u16 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::from_little_endian` instead"] pub fn from_le16(x: u16) -> u16 { Int::from_little_endian(x) } /// Convert an u32 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::from_little_endian` instead"] pub fn from_le32(x: u32) -> u32 { Int::from_little_endian(x) } /// Convert an u64 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::from_little_endian` instead"] pub fn from_le64(x: u64) -> u64 { Int::from_little_endian(x) } /// Convert an u16 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::from_big_endian` instead"] pub fn from_be16(x: u16) -> u16 { Int::from_big_endian(x) } /// Convert an u32 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::from_big_endian` instead"] pub fn from_be32(x: u32) -> u32 { Int::from_big_endian(x) } /// Convert an u64 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::from_big_endian` instead"] pub fn from_be64(x: u64) -> u64 { Int::from_big_endian(x) } /// Swap the values at two mutable locations of the same type, without From 59cd6f0cd2792060848cee5da439b3533cd6a9f0 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 17 Jun 2014 15:47:31 -0700 Subject: [PATCH 6/7] Shorten endian conversion method names The consensus on #14917 was that the proposed names were too long. --- src/libcollections/hash/mod.rs | 2 +- src/libcore/mem.rs | 48 +++++++++++++++++----------------- src/libcore/num/int_macros.rs | 32 +++++++++++------------ src/libcore/num/mod.rs | 24 ++++++++--------- src/libcore/num/uint_macros.rs | 32 +++++++++++------------ src/libnative/io/net.rs | 8 +++--- src/librustuv/net.rs | 8 +++--- src/libserialize/ebml.rs | 2 +- src/libuuid/lib.rs | 12 ++++----- 9 files changed, 84 insertions(+), 84 deletions(-) diff --git a/src/libcollections/hash/mod.rs b/src/libcollections/hash/mod.rs index 07c768d0c7916..a0c0c9f973578 100644 --- a/src/libcollections/hash/mod.rs +++ b/src/libcollections/hash/mod.rs @@ -104,7 +104,7 @@ macro_rules! impl_hash { #[inline] fn hash(&self, state: &mut S) { let a: [u8, ..::core::$ty::BYTES] = unsafe { - mem::transmute((*self as $uty).to_little_endian() as $ty) + mem::transmute((*self as $uty).to_le() as $ty) }; state.write(a.as_slice()) } diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 1032b820b2751..5280ac0d64fb2 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -173,85 +173,85 @@ pub unsafe fn move_val_init(dst: &mut T, src: T) { /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::to_little_endian` instead"] -pub fn to_le16(x: u16) -> u16 { x.to_little_endian() } +#[deprecated = "use `Int::to_le` instead"] +pub fn to_le16(x: u16) -> u16 { x.to_le() } /// Convert an u32 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::to_little_endian` instead"] -pub fn to_le32(x: u32) -> u32 { x.to_little_endian() } +#[deprecated = "use `Int::to_le` instead"] +pub fn to_le32(x: u32) -> u32 { x.to_le() } /// Convert an u64 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::to_little_endian` instead"] -pub fn to_le64(x: u64) -> u64 { x.to_little_endian() } +#[deprecated = "use `Int::to_le` instead"] +pub fn to_le64(x: u64) -> u64 { x.to_le() } /// Convert an u16 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::to_big_endian` instead"] -pub fn to_be16(x: u16) -> u16 { x.to_big_endian() } +#[deprecated = "use `Int::to_be` instead"] +pub fn to_be16(x: u16) -> u16 { x.to_be() } /// Convert an u32 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::to_big_endian` instead"] -pub fn to_be32(x: u32) -> u32 { x.to_big_endian() } +#[deprecated = "use `Int::to_be` instead"] +pub fn to_be32(x: u32) -> u32 { x.to_be() } /// Convert an u64 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::to_big_endian` instead"] -pub fn to_be64(x: u64) -> u64 { x.to_big_endian() } +#[deprecated = "use `Int::to_be` instead"] +pub fn to_be64(x: u64) -> u64 { x.to_be() } /// Convert an u16 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::from_little_endian` instead"] -pub fn from_le16(x: u16) -> u16 { Int::from_little_endian(x) } +#[deprecated = "use `Int::from_le` instead"] +pub fn from_le16(x: u16) -> u16 { Int::from_le(x) } /// Convert an u32 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::from_little_endian` instead"] -pub fn from_le32(x: u32) -> u32 { Int::from_little_endian(x) } +#[deprecated = "use `Int::from_le` instead"] +pub fn from_le32(x: u32) -> u32 { Int::from_le(x) } /// Convert an u64 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::from_little_endian` instead"] -pub fn from_le64(x: u64) -> u64 { Int::from_little_endian(x) } +#[deprecated = "use `Int::from_le` instead"] +pub fn from_le64(x: u64) -> u64 { Int::from_le(x) } /// Convert an u16 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::from_big_endian` instead"] -pub fn from_be16(x: u16) -> u16 { Int::from_big_endian(x) } +#[deprecated = "use `Int::from_be` instead"] +pub fn from_be16(x: u16) -> u16 { Int::from_be(x) } /// Convert an u32 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::from_big_endian` instead"] -pub fn from_be32(x: u32) -> u32 { Int::from_big_endian(x) } +#[deprecated = "use `Int::from_be` instead"] +pub fn from_be32(x: u32) -> u32 { Int::from_be(x) } /// Convert an u64 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::from_big_endian` instead"] -pub fn from_be64(x: u64) -> u64 { Int::from_big_endian(x) } +#[deprecated = "use `Int::from_be` instead"] +pub fn from_be64(x: u64) -> u64 { Int::from_be(x) } /// Swap the values at two mutable locations of the same type, without /// deinitialising or copying either one. diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 84744b3f5d701..79734324706b2 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -147,25 +147,25 @@ mod tests { } #[test] - fn test_little_endian() { - assert_eq!(Int::from_little_endian(A.to_little_endian()), A); - assert_eq!(Int::from_little_endian(B.to_little_endian()), B); - assert_eq!(Int::from_little_endian(C.to_little_endian()), C); - assert_eq!(Int::from_little_endian(_0), _0); - assert_eq!(Int::from_little_endian(_1), _1); - assert_eq!(_0.to_little_endian(), _0); - assert_eq!(_1.to_little_endian(), _1); + fn test_le() { + assert_eq!(Int::from_le(A.to_le()), A); + assert_eq!(Int::from_le(B.to_le()), B); + assert_eq!(Int::from_le(C.to_le()), C); + assert_eq!(Int::from_le(_0), _0); + assert_eq!(Int::from_le(_1), _1); + assert_eq!(_0.to_le(), _0); + assert_eq!(_1.to_le(), _1); } #[test] - fn test_big_endian() { - assert_eq!(Int::from_big_endian(A.to_big_endian()), A); - assert_eq!(Int::from_big_endian(B.to_big_endian()), B); - assert_eq!(Int::from_big_endian(C.to_big_endian()), C); - assert_eq!(Int::from_big_endian(_0), _0); - assert_eq!(Int::from_big_endian(_1), _1); - assert_eq!(_0.to_big_endian(), _0); - assert_eq!(_1.to_big_endian(), _1); + fn test_be() { + assert_eq!(Int::from_be(A.to_be()), A); + assert_eq!(Int::from_be(B.to_be()), B); + assert_eq!(Int::from_be(C.to_be()), C); + assert_eq!(Int::from_be(_0), _0); + assert_eq!(Int::from_be(_1), _1); + assert_eq!(_0.to_be(), _0); + assert_eq!(_1.to_be(), _1); } #[test] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index ed0c24e7fa008..dd32a6da1063b 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -498,13 +498,13 @@ pub trait Int: Primitive /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "big") { - /// assert_eq!(Int::from_big_endian(n), n) + /// assert_eq!(Int::from_be(n), n) /// } else { - /// assert_eq!(Int::from_big_endian(n), n.swap_bytes()) + /// assert_eq!(Int::from_be(n), n.swap_bytes()) /// } /// ``` #[inline] - fn from_big_endian(x: Self) -> Self { + fn from_be(x: Self) -> Self { if cfg!(target_endian = "big") { x } else { x.swap_bytes() } } @@ -518,13 +518,13 @@ pub trait Int: Primitive /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "little") { - /// assert_eq!(Int::from_little_endian(n), n) + /// assert_eq!(Int::from_le(n), n) /// } else { - /// assert_eq!(Int::from_little_endian(n), n.swap_bytes()) + /// assert_eq!(Int::from_le(n), n.swap_bytes()) /// } /// ``` #[inline] - fn from_little_endian(x: Self) -> Self { + fn from_le(x: Self) -> Self { if cfg!(target_endian = "little") { x } else { x.swap_bytes() } } @@ -538,13 +538,13 @@ pub trait Int: Primitive /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "big") { - /// assert_eq!(n.to_big_endian(), n) + /// assert_eq!(n.to_be(), n) /// } else { - /// assert_eq!(n.to_big_endian(), n.swap_bytes()) + /// assert_eq!(n.to_be(), n.swap_bytes()) /// } /// ``` #[inline] - fn to_big_endian(self) -> Self { + fn to_be(self) -> Self { // or not to be? if cfg!(target_endian = "big") { self } else { self.swap_bytes() } } @@ -558,13 +558,13 @@ pub trait Int: Primitive /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "little") { - /// assert_eq!(n.to_little_endian(), n) + /// assert_eq!(n.to_le(), n) /// } else { - /// assert_eq!(n.to_little_endian(), n.swap_bytes()) + /// assert_eq!(n.to_le(), n.swap_bytes()) /// } /// ``` #[inline] - fn to_little_endian(self) -> Self { + fn to_le(self) -> Self { if cfg!(target_endian = "little") { self } else { self.swap_bytes() } } } diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index 1fe3c4cf1f1cf..be1f960bcc3df 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -98,25 +98,25 @@ mod tests { } #[test] - fn test_little_endian() { - assert_eq!(Int::from_little_endian(A.to_little_endian()), A); - assert_eq!(Int::from_little_endian(B.to_little_endian()), B); - assert_eq!(Int::from_little_endian(C.to_little_endian()), C); - assert_eq!(Int::from_little_endian(_0), _0); - assert_eq!(Int::from_little_endian(_1), _1); - assert_eq!(_0.to_little_endian(), _0); - assert_eq!(_1.to_little_endian(), _1); + fn test_le() { + assert_eq!(Int::from_le(A.to_le()), A); + assert_eq!(Int::from_le(B.to_le()), B); + assert_eq!(Int::from_le(C.to_le()), C); + assert_eq!(Int::from_le(_0), _0); + assert_eq!(Int::from_le(_1), _1); + assert_eq!(_0.to_le(), _0); + assert_eq!(_1.to_le(), _1); } #[test] - fn test_big_endian() { - assert_eq!(Int::from_big_endian(A.to_big_endian()), A); - assert_eq!(Int::from_big_endian(B.to_big_endian()), B); - assert_eq!(Int::from_big_endian(C.to_big_endian()), C); - assert_eq!(Int::from_big_endian(_0), _0); - assert_eq!(Int::from_big_endian(_1), _1); - assert_eq!(_0.to_big_endian(), _0); - assert_eq!(_1.to_big_endian(), _1); + fn test_be() { + assert_eq!(Int::from_be(A.to_be()), A); + assert_eq!(Int::from_be(B.to_be()), B); + assert_eq!(Int::from_be(C.to_be()), C); + assert_eq!(Int::from_be(_0), _0); + assert_eq!(Int::from_be(_1), _1); + assert_eq!(_0.to_be(), _0); + assert_eq!(_1.to_be(), _1); } #[test] diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index 6822398fc08bb..36acfd5cf8a6b 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -27,10 +27,10 @@ use super::util; #[cfg(unix)] pub type sock_t = super::file::fd_t; pub fn htons(u: u16) -> u16 { - u.to_big_endian() + u.to_be() } pub fn ntohs(u: u16) -> u16 { - Int::from_big_endian(u) + Int::from_be(u) } enum InAddr { @@ -46,7 +46,7 @@ fn ip_to_inaddr(ip: rtio::IpAddr) -> InAddr { (c as u32 << 8) | (d as u32 << 0); InAddr(libc::in_addr { - s_addr: Int::from_big_endian(ip) + s_addr: Int::from_be(ip) }) } rtio::Ipv6Addr(a, b, c, d, e, f, g, h) => { @@ -180,7 +180,7 @@ pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, let storage: &libc::sockaddr_in = unsafe { mem::transmute(storage) }; - let ip = (storage.sin_addr.s_addr as u32).to_big_endian(); + let ip = (storage.sin_addr.s_addr as u32).to_be(); let a = (ip >> 24) as u8; let b = (ip >> 16) as u8; let c = (ip >> 8) as u8; diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs index 8217989d00e61..271e292033265 100644 --- a/src/librustuv/net.rs +++ b/src/librustuv/net.rs @@ -30,8 +30,8 @@ use uvll; /// Generic functions related to dealing with sockaddr things //////////////////////////////////////////////////////////////////////////////// -pub fn htons(u: u16) -> u16 { u.to_big_endian() } -pub fn ntohs(u: u16) -> u16 { Int::from_big_endian(u) } +pub fn htons(u: u16) -> u16 { u.to_be() } +pub fn ntohs(u: u16) -> u16 { Int::from_be(u) } pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, len: uint) -> rtio::SocketAddr { @@ -41,7 +41,7 @@ pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, let storage: &libc::sockaddr_in = unsafe { mem::transmute(storage) }; - let ip = (storage.sin_addr.s_addr as u32).to_big_endian(); + let ip = (storage.sin_addr.s_addr as u32).to_be(); let a = (ip >> 24) as u8; let b = (ip >> 16) as u8; let c = (ip >> 8) as u8; @@ -89,7 +89,7 @@ fn addr_to_sockaddr(addr: rtio::SocketAddr) -> (libc::sockaddr_storage, uint) { (*storage).sin_family = libc::AF_INET as libc::sa_family_t; (*storage).sin_port = htons(addr.port); (*storage).sin_addr = libc::in_addr { - s_addr: Int::from_big_endian(ip), + s_addr: Int::from_be(ip), }; mem::size_of::() diff --git a/src/libserialize/ebml.rs b/src/libserialize/ebml.rs index 7d0c82fc9a2d5..12c5a3493c17b 100644 --- a/src/libserialize/ebml.rs +++ b/src/libserialize/ebml.rs @@ -183,7 +183,7 @@ pub mod reader { unsafe { let ptr = data.as_ptr().offset(start as int) as *u32; - let val = Int::from_big_endian(*ptr); + let val = Int::from_be(*ptr); let i = (val >> 28u) as uint; let (shift, mask) = SHIFT_MASK_TABLE[i]; diff --git a/src/libuuid/lib.rs b/src/libuuid/lib.rs index bbd461e3dde0d..b68b435da4bb0 100644 --- a/src/libuuid/lib.rs +++ b/src/libuuid/lib.rs @@ -217,9 +217,9 @@ impl Uuid { data4: [0, ..8] }; - fields.data1 = d1.to_big_endian(); - fields.data2 = d2.to_big_endian(); - fields.data3 = d3.to_big_endian(); + fields.data1 = d1.to_be(); + fields.data2 = d2.to_be(); + fields.data3 = d3.to_be(); slice::bytes::copy_memory(fields.data4, d4); unsafe { @@ -339,9 +339,9 @@ impl Uuid { unsafe { uf = transmute_copy(&self.bytes); } - uf.data1 = uf.data1.to_big_endian(); - uf.data2 = uf.data2.to_big_endian(); - uf.data3 = uf.data3.to_big_endian(); + uf.data1 = uf.data1.to_be(); + uf.data2 = uf.data2.to_be(); + uf.data3 = uf.data3.to_be(); let s = format!("{:08x}-{:04x}-{:04x}-{:02x}{:02x}-\ {:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", uf.data1, From d66525e1164dfafde3b181906c8519b0859912f7 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 17 Jun 2014 11:09:20 -0700 Subject: [PATCH 7/7] Update doc comment for Int trait --- src/libcore/num/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index dd32a6da1063b..573470c29bcf4 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -388,7 +388,8 @@ pub trait Primitive: Copy trait_impl!(Primitive for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64) -/// A collection of traits relevant to primitive signed and unsigned integers +/// A primitive signed or unsigned integer equipped with various bitwise +/// operators, bit counting methods, and endian conversion functions. pub trait Int: Primitive + CheckedAdd + CheckedSub