Merge the Bitwise and ByteOrder traits into the Int trait

This reduces the complexity of the trait hierarchy.
This commit is contained in:
Brendan Zabarauskas 2014-06-16 11:25:47 -07:00 committed by Alex Crichton
parent 4c0f8f49f6
commit ff9f92ce52
14 changed files with 391 additions and 430 deletions

View file

@ -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<E> {

View file

@ -103,7 +103,6 @@ macro_rules! impl_hash {
impl<S: Writer> Hash<S> 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)
};

View file

@ -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)

View file

@ -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]

View file

@ -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<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.
///
/// # 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<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
/// 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]

View file

@ -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]

View file

@ -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) => {

View file

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

View file

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

View file

@ -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::<libc::sockaddr_in>()

View file

@ -154,8 +154,6 @@ pub mod reader {
}
pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult<Res> {
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];

View file

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

View file

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

View file

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