diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 34514fde9dbd..1360b412c237 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 80417e2a5798..07c768d0c791 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 b64ee9bf4f70..eab344ac7a70 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 8a1bd66aa1ac..84744b3f5d70 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 696abc05ed27..ed0c24e7fa00 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -376,172 +376,6 @@ 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. - /// - /// # Example - /// - /// ```rust - /// use std::num::Bitwise; - /// - /// let n = 0b01001100u8; - /// assert_eq!(n.count_ones(), 3); - /// ``` - fn count_ones(&self) -> Self; - - /// Returns the number of zeros in the binary representation of the number. - /// - /// # Example - /// - /// ```rust - /// use std::num::Bitwise; - /// - /// let n = 0b01001100u8; - /// assert_eq!(n.count_zeros(), 5); - /// ``` - #[inline] - fn count_zeros(&self) -> Self { - (!*self).count_ones() - } - - /// Returns the number of leading zeros in the in the binary representation - /// of the number. - /// - /// # Example - /// - /// ```rust - /// use std::num::Bitwise; - /// - /// let n = 0b0101000u16; - /// assert_eq!(n.leading_zeros(), 10); - /// ``` - fn leading_zeros(&self) -> Self; - - /// Returns the number of trailing zeros in the in the binary representation - /// of the number. - /// - /// # Example - /// - /// ```rust - /// use std::num::Bitwise; - /// - /// let n = 0b0101000u16; - /// assert_eq!(n.trailing_zeros(), 3); - /// ``` - 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. - /// - /// # 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; - - /// Shifts the bits to the right by a specified amount amount, `r`, wrapping - /// the truncated bits to the beginning of the resulting value. - /// - /// # 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; -} - -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 { $co(*self) } } - - #[inline] - fn leading_zeros(&self) -> $t { unsafe { $lz(*self) } } - - #[inline] - fn trailing_zeros(&self) -> $t { unsafe { $tz(*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)) - } - - #[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)) - } - } - } -} - -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 { $co(*self as $t_cast) as $t } } - - #[inline] - fn leading_zeros(&self) -> $t { unsafe { $lz(*self as $t_cast) as $t } } - - #[inline] - fn trailing_zeros(&self) -> $t { unsafe { $tz(*self as $t_cast) 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 - } - - #[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 - } - } - } -} - -#[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. @@ -556,13 +390,278 @@ 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 {} + + CheckedDiv + + Bounded + + Not + + BitAnd + + BitOr + + BitXor + + Shl + + Shr { + /// Returns the number of ones in the binary representation of the integer. + /// + /// # Example + /// + /// ```rust + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + fn count_ones(self) -> Self; -trait_impl!(Int for uint u8 u16 u32 u64 int i8 i16 i32 i64) + /// Returns the number of zeros in the binary representation of the integer. + /// + /// # Example + /// + /// ```rust + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_zeros(), 5); + /// ``` + #[inline] + fn count_zeros(self) -> Self { + (!self).count_ones() + } + + /// Returns the number of leading zeros in the in the binary representation + /// of the integer. + /// + /// # Example + /// + /// ```rust + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.leading_zeros(), 10); + /// ``` + fn leading_zeros(self) -> Self; + + /// Returns the number of trailing zeros in the in the binary representation + /// of the integer. + /// + /// # Example + /// + /// ```rust + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + fn trailing_zeros(self) -> Self; + + /// 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 + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0x3456789ABCDEF012u64; + /// + /// assert_eq!(n.rotate_left(12), m); + /// ``` + fn rotate_left(self, n: uint) -> Self; + + /// 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 + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xDEF0123456789ABCu64; + /// + /// assert_eq!(n.rotate_right(12), m); + /// ``` + 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! 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 { $ctpop(self) } } + + #[inline] + fn leading_zeros(self) -> $T { unsafe { $ctlz(self) } } + + #[inline] + fn trailing_zeros(self) -> $T { unsafe { $cttz(self) } } + + #[inline] + 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, 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) } } + } + } +} + +/// 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 { (self as $U).count_ones() as $T } + + #[inline] + fn leading_zeros(self) -> $T { (self as $U).leading_zeros() as $T } + + #[inline] + fn trailing_zeros(self) -> $T { (self as $U).trailing_zeros() as $T } + + #[inline] + fn rotate_left(self, n: uint) -> $T { (self as $U).rotate_left(n) as $T } + + #[inline] + 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 } + } + } +} + +int_cast_impl!(i8, u8) +int_cast_impl!(i16, u16) +int_cast_impl!(i32, u32) +int_cast_impl!(i64, u64) + +#[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 8548b1410539..1fe3c4cf1f1c 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 f0cd2d966cb3..23fd607aafee 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 0933301970d1..e9153f89e04e 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 9f4b11116dbb..e4b28dc7aa7c 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 83beeceb8de3..aa7fab2565d8 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 a1c79bc0b757..7d0c82fc9a2d 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 602a2240f390..7301f9b08e9d 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 1140f023d43f..bbd461e3dde0 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 c0ea6f8617d8..af51157bba56 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