about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorBrendan Zabarauskas <bjzaba@yahoo.com.au>2014-06-16 11:25:47 -0700
committerAlex Crichton <alex@alexcrichton.com>2014-06-18 17:01:34 -0700
commitff9f92ce5224f5e27b8dc39ffc02eb9481f7cff1 (patch)
treef56ac5a3288101c49c4cc5c2e85b18dd4c2c6ff7 /src/libcore
parent4c0f8f49f6fe860efa268efa2f4fa0b5f00a4b07 (diff)
downloadrust-ff9f92ce5224f5e27b8dc39ffc02eb9481f7cff1.tar.gz
rust-ff9f92ce5224f5e27b8dc39ffc02eb9481f7cff1.zip
Merge the Bitwise and ByteOrder traits into the Int trait
This reduces the complexity of the trait hierarchy.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/mem.rs220
-rw-r--r--src/libcore/num/int_macros.rs69
-rw-r--r--src/libcore/num/mod.rs305
-rw-r--r--src/libcore/num/uint_macros.rs69
4 files changed, 318 insertions, 345 deletions
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index b64ee9bf4f7..eab344ac7a7 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<T>(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 8a1bd66aa1a..84744b3f5d7 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 696abc05ed2..ed0c24e7fa0 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<Self>
-                 + BitAnd<Self,Self>
-                 + BitOr<Self,Self>
-                 + BitXor<Self,Self>
-                 + Shl<Self,Self>
-                 + Shr<Self,Self> {
-    /// 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<Self>
+             + BitAnd<Self,Self>
+             + BitOr<Self,Self>
+             + BitXor<Self,Self>
+             + Shl<Self,Self>
+             + Shr<Self,Self> {
+    /// 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 8548b141053..1fe3c4cf1f1 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]