@@ -436,57 +436,135 @@ pub trait Bitwise: Bounded
436436 /// assert_eq!(n.trailing_zeros(), 3);
437437 /// ```
438438 fn trailing_zeros ( & self ) -> Self ;
439+
440+ /// Reverses the byte order of a binary number.
441+ ///
442+ /// # Example
443+ ///
444+ /// ```rust
445+ /// use std::num::Bitwise;
446+ ///
447+ /// let n = 0x0123456789ABCDEFu64;
448+ /// let m = 0xEFCDAB8967452301u64;
449+ /// assert_eq!(n.swap_bytes(), m);
450+ /// ```
451+ fn swap_bytes ( & self ) -> Self ;
452+
453+ /// Shifts the bits to the left by a specified amount amount, `r`, wrapping
454+ /// the truncated bits to the end of the resulting value.
455+ ///
456+ /// # Example
457+ ///
458+ /// ```rust
459+ /// use std::num::Bitwise;
460+ ///
461+ /// let n = 0x0123456789ABCDEFu64;
462+ /// let m = 0x3456789ABCDEF012u64;
463+ /// assert_eq!(n.rotate_left(12), m);
464+ /// ```
465+ fn rotate_left ( & self , r : uint ) -> Self ;
466+
467+ /// Shifts the bits to the right by a specified amount amount, `r`, wrapping
468+ /// the truncated bits to the beginning of the resulting value.
469+ ///
470+ /// # Example
471+ ///
472+ /// ```rust
473+ /// use std::num::Bitwise;
474+ ///
475+ /// let n = 0x0123456789ABCDEFu64;
476+ /// let m = 0xDEF0123456789ABCu64;
477+ /// assert_eq!(n.rotate_right(12), m);
478+ /// ```
479+ fn rotate_right ( & self , r : uint ) -> Self ;
439480}
440481
482+ /// Swapping a single byte does nothing. This is unsafe to be consistent with
483+ /// the other `bswap` intrinsics.
484+ #[ inline]
485+ unsafe fn bswap8 ( x : u8 ) -> u8 { x }
486+
441487macro_rules! bitwise_impl(
442- ( $t: ty, $co: path , $lz: path , $tz: path) => {
488+ ( $t: ty, $bits : expr , $ co: ident , $lz: ident , $tz: ident , $bs : path) => {
443489 impl Bitwise for $t {
444490 #[ inline]
445- fn count_ones( & self ) -> $t { unsafe { $co( * self ) } }
491+ fn count_ones( & self ) -> $t { unsafe { intrinsics :: $co( * self ) } }
446492
447493 #[ inline]
448- fn leading_zeros( & self ) -> $t { unsafe { $lz( * self ) } }
494+ fn leading_zeros( & self ) -> $t { unsafe { intrinsics :: $lz( * self ) } }
449495
450496 #[ inline]
451- fn trailing_zeros( & self ) -> $t { unsafe { $tz( * self ) } }
497+ fn trailing_zeros( & self ) -> $t { unsafe { intrinsics:: $tz( * self ) } }
498+
499+ #[ inline]
500+ fn swap_bytes( & self ) -> $t { unsafe { $bs( * self ) } }
501+
502+ #[ inline]
503+ fn rotate_left( & self , r: uint) -> $t {
504+ // Protect against undefined behaviour for overlong bit shifts
505+ let r = r % $bits;
506+ ( * self << r) | ( * self >> ( $bits - r) )
507+ }
508+
509+ #[ inline]
510+ fn rotate_right( & self , r: uint) -> $t {
511+ // Protect against undefined behaviour for overlong bit shifts
512+ let r = r % $bits;
513+ ( * self >> r) | ( * self << ( $bits - r) )
514+ }
452515 }
453516 }
454517)
455518
456519macro_rules! bitwise_cast_impl(
457- ( $t: ty, $t_cast: ty, $co: path , $lz: path , $tz: path) => {
520+ ( $t: ty, $t_cast: ty, $bits : expr , $co: ident , $lz: ident , $tz: ident , $bs : path) => {
458521 impl Bitwise for $t {
459522 #[ inline]
460- fn count_ones( & self ) -> $t { unsafe { $co( * self as $t_cast) as $t } }
523+ fn count_ones( & self ) -> $t { unsafe { intrinsics:: $co( * self as $t_cast) as $t } }
524+
525+ #[ inline]
526+ fn leading_zeros( & self ) -> $t { unsafe { intrinsics:: $lz( * self as $t_cast) as $t } }
527+
528+ #[ inline]
529+ fn trailing_zeros( & self ) -> $t { unsafe { intrinsics:: $tz( * self as $t_cast) as $t } }
461530
462531 #[ inline]
463- fn leading_zeros ( & self ) -> $t { unsafe { $lz ( * self as $t_cast) as $t } }
532+ fn swap_bytes ( & self ) -> $t { unsafe { $bs ( * self as $t_cast) as $t } }
464533
465534 #[ inline]
466- fn trailing_zeros( & self ) -> $t { unsafe { $tz( * self as $t_cast) as $t } }
535+ fn rotate_left( & self , r: uint) -> $t {
536+ // cast to prevent the sign bit from being corrupted
537+ ( * self as $t_cast) . rotate_left( r) as $t
538+ }
539+
540+ #[ inline]
541+ fn rotate_right( & self , r: uint) -> $t {
542+ // cast to prevent the sign bit from being corrupted
543+ ( * self as $t_cast) . rotate_right( r) as $t
544+ }
467545 }
468546 }
469547)
470548
471549#[ cfg( target_word_size = "32" ) ]
472- bitwise_cast_impl ! ( uint, u32 , intrinsics :: ctpop32, intrinsics :: ctlz32, intrinsics:: cttz32 )
550+ bitwise_cast_impl ! ( uint, u32 , 32 , ctpop32, ctlz32, cttz32 , intrinsics:: bswap32 )
473551#[ cfg( target_word_size = "64" ) ]
474- bitwise_cast_impl ! ( uint, u64 , intrinsics :: ctpop64, intrinsics :: ctlz64, intrinsics:: cttz64 )
552+ bitwise_cast_impl ! ( uint, u64 , 64 , ctpop64, ctlz64, cttz64 , intrinsics:: bswap64 )
475553
476- bitwise_impl ! ( u8 , intrinsics :: ctpop8, intrinsics :: ctlz8, intrinsics :: cttz8)
477- bitwise_impl ! ( u16 , intrinsics :: ctpop16, intrinsics :: ctlz16, intrinsics:: cttz16 )
478- bitwise_impl ! ( u32 , intrinsics :: ctpop32, intrinsics :: ctlz32, intrinsics:: cttz32 )
479- bitwise_impl ! ( u64 , intrinsics :: ctpop64, intrinsics :: ctlz64, intrinsics:: cttz64 )
554+ bitwise_impl ! ( u8 , 8 , ctpop8, ctlz8, cttz8, bswap8 )
555+ bitwise_impl ! ( u16 , 16 , ctpop16, ctlz16, cttz16 , intrinsics:: bswap16 )
556+ bitwise_impl ! ( u32 , 32 , ctpop32, ctlz32, cttz32 , intrinsics:: bswap32 )
557+ bitwise_impl ! ( u64 , 64 , ctpop64, ctlz64, cttz64 , intrinsics:: bswap64 )
480558
481559#[ cfg( target_word_size = "32" ) ]
482- bitwise_cast_impl ! ( int, u32 , intrinsics :: ctpop32, intrinsics :: ctlz32, intrinsics:: cttz32 )
560+ bitwise_cast_impl ! ( int, u32 , 32 , ctpop32, ctlz32, cttz32 , intrinsics:: bswap32 )
483561#[ cfg( target_word_size = "64" ) ]
484- bitwise_cast_impl ! ( int, u64 , intrinsics :: ctpop64, intrinsics :: ctlz64, intrinsics:: cttz64 )
562+ bitwise_cast_impl ! ( int, u64 , 64 , ctpop64, ctlz64, cttz64 , intrinsics:: bswap64 )
485563
486- bitwise_cast_impl ! ( i8 , u8 , intrinsics :: ctpop8, intrinsics :: ctlz8, intrinsics :: cttz8)
487- bitwise_cast_impl ! ( i16 , u16 , intrinsics :: ctpop16, intrinsics :: ctlz16, intrinsics:: cttz16 )
488- bitwise_cast_impl ! ( i32 , u32 , intrinsics :: ctpop32, intrinsics :: ctlz32, intrinsics:: cttz32 )
489- bitwise_cast_impl ! ( i64 , u64 , intrinsics :: ctpop64, intrinsics :: ctlz64, intrinsics:: cttz64 )
564+ bitwise_cast_impl ! ( i8 , u8 , 8 , ctpop8, ctlz8, cttz8, bswap8 )
565+ bitwise_cast_impl ! ( i16 , u16 , 16 , ctpop16, ctlz16, cttz16 , intrinsics:: bswap16 )
566+ bitwise_cast_impl ! ( i32 , u32 , 32 , ctpop32, ctlz32, cttz32 , intrinsics:: bswap32 )
567+ bitwise_cast_impl ! ( i64 , u64 , 64 , ctpop64, ctlz64, cttz64 , intrinsics:: bswap64 )
490568
491569/// Specifies the available operations common to all of Rust's core numeric primitives.
492570/// These may not always make sense from a purely mathematical point of view, but
0 commit comments