diff --git a/.travis.yml b/.travis.yml index efec028..d9ae89a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,8 +20,10 @@ rust: before_script: - export PATH=$HOME/.cargo/bin:$PATH # for cargo subcommands + - rustup component add rustfmt-preview script: + - cargo fmt -- --check - cargo build - cargo test # - cargo bench diff --git a/src/bit_index.rs b/src/bit_index.rs index 8ed720c..fe0f8ca 100644 --- a/src/bit_index.rs +++ b/src/bit_index.rs @@ -1,7 +1,7 @@ #![allow(unused_comparisons)] -use std::ops::RangeBounds; use crate::{BitMask, BitSize}; +use std::ops::RangeBounds; /// Provides bit indexing operations. /// @@ -36,11 +36,12 @@ pub trait BitIndex: BitSize + BitMask { macro_rules! bit_index_impl { ($type:ty) => { - impl BitIndex for $type - { + impl BitIndex for $type { fn bit(&self, index: usize) -> bool { self.checked_shr(index as _) - .unwrap_or_else(|| if *self < 0 { 1 } else { 0 }) & 1 == 1 + .unwrap_or_else(|| if *self < 0 { 1 } else { 0 }) + & 1 + == 1 } fn bits>(&self, index: Idx) -> Self { @@ -73,18 +74,29 @@ macro_rules! bit_index_impl { }; match (shift, mask) { - (Some(s), Some(m)) => self.checked_shr(s as _).unwrap_or_else(|| { - if *self < 0 { (0 as Self).wrapping_sub(1) } else { 0 } - }).mask_to(m), + (Some(s), Some(m)) => self + .checked_shr(s as _) + .unwrap_or_else(|| { + if *self < 0 { + (0 as Self).wrapping_sub(1) + } else { + 0 + } + }) + .mask_to(m), (Some(s), None) => self.checked_shr(s as _).unwrap_or_else(|| { - if *self < 0 { (0 as Self).wrapping_sub(1) } else { 0 } + if *self < 0 { + (0 as Self).wrapping_sub(1) + } else { + 0 + } }), (None, Some(m)) => self.mask_to(m), (None, None) => *self, } } } - } + }; } bit_index_impl!(u8); @@ -102,25 +114,37 @@ bit_index_impl!(isize); #[cfg(test)] mod test { - use spectral::prelude::*; use super::*; + use spectral::prelude::*; struct RangeEE(usize, usize); impl RangeBounds for RangeEE { - fn start_bound(&self) -> std::ops::Bound<&usize> { std::ops::Bound::Excluded(&self.0) } - fn end_bound(&self) -> std::ops::Bound<&usize> { std::ops::Bound::Excluded(&self.1) } + fn start_bound(&self) -> std::ops::Bound<&usize> { + std::ops::Bound::Excluded(&self.0) + } + fn end_bound(&self) -> std::ops::Bound<&usize> { + std::ops::Bound::Excluded(&self.1) + } } struct RangeEI(usize, usize); impl RangeBounds for RangeEI { - fn start_bound(&self) -> std::ops::Bound<&usize> { std::ops::Bound::Excluded(&self.0) } - fn end_bound(&self) -> std::ops::Bound<&usize> { std::ops::Bound::Included(&self.1) } + fn start_bound(&self) -> std::ops::Bound<&usize> { + std::ops::Bound::Excluded(&self.0) + } + fn end_bound(&self) -> std::ops::Bound<&usize> { + std::ops::Bound::Included(&self.1) + } } struct RangeEU(usize); impl RangeBounds for RangeEU { - fn start_bound(&self) -> std::ops::Bound<&usize> { std::ops::Bound::Excluded(&self.0) } - fn end_bound(&self) -> std::ops::Bound<&usize> { std::ops::Bound::Unbounded } + fn start_bound(&self) -> std::ops::Bound<&usize> { + std::ops::Bound::Excluded(&self.0) + } + fn end_bound(&self) -> std::ops::Bound<&usize> { + std::ops::Bound::Unbounded + } } #[test] @@ -128,56 +152,56 @@ mod test { let byte: u8 = 90; asserting!("bit() looks up the correct bit") - .that( &[byte.bit(2), byte.bit(3), byte.bit(4), byte.bit(5)] ) - .is_equal_to( &[false, true, true, false] ); + .that(&[byte.bit(2), byte.bit(3), byte.bit(4), byte.bit(5)]) + .is_equal_to(&[false, true, true, false]); asserting!("bits(RangeFull) returns the whole value") - .that( &byte.bits(..) ) - .is_equal_to( 90 ); + .that(&byte.bits(..)) + .is_equal_to(90); asserting!("bits(RangeTo) excludes the end bit") - .that( &byte.bits(..4) ) - .is_equal_to( 10 ); + .that(&byte.bits(..4)) + .is_equal_to(10); asserting!("bits(RangeToInclusive) includes the end bit") - .that( &byte.bits(..=4) ) - .is_equal_to( 26 ); + .that(&byte.bits(..=4)) + .is_equal_to(26); asserting!("bits(RangeFrom) includes the start bit") - .that( &byte.bits(4..) ) - .is_equal_to( 5 ); + .that(&byte.bits(4..)) + .is_equal_to(5); asserting!("bits(Range) includes the start bit") - .that( &byte.bits(4..8) ) - .is_equal_to( 5 ); + .that(&byte.bits(4..8)) + .is_equal_to(5); asserting!("bits(Range) excludes the end bit") - .that( &byte.bits(0..4) ) - .is_equal_to( 10 ); + .that(&byte.bits(0..4)) + .is_equal_to(10); asserting!("bits(RangeInclusive) includes the start bit") - .that( &byte.bits(4..=7) ) - .is_equal_to( 5 ); + .that(&byte.bits(4..=7)) + .is_equal_to(5); asserting!("bits(RangeInclusive) includes the end bit") - .that( &byte.bits(0..=4) ) - .is_equal_to( 26 ); + .that(&byte.bits(0..=4)) + .is_equal_to(26); asserting!("bits(RangeEU) excludes the start bit") - .that( &byte.bits(RangeEU(4)) ) - .is_equal_to( 2 ); + .that(&byte.bits(RangeEU(4))) + .is_equal_to(2); asserting!("bits(RangeEE) excludes the start bit") - .that( &byte.bits(RangeEE(4, 8)) ) - .is_equal_to( 2 ); + .that(&byte.bits(RangeEE(4, 8))) + .is_equal_to(2); asserting!("bits(RangeEE) excludes the end bit") - .that( &byte.bits(RangeEE(0, 4)) ) - .is_equal_to( 5 ); + .that(&byte.bits(RangeEE(0, 4))) + .is_equal_to(5); asserting!("bits(RangeEI) excludes the start bit") - .that( &byte.bits(RangeEI(4, 7)) ) - .is_equal_to( 2 ); + .that(&byte.bits(RangeEI(4, 7))) + .is_equal_to(2); asserting!("bits(RangeEI) includes the end bit") - .that( &byte.bits(RangeEI(0, 4)) ) - .is_equal_to( 13 ); + .that(&byte.bits(RangeEI(0, 4))) + .is_equal_to(13); } #[test] @@ -185,58 +209,58 @@ mod test { let byte: u8 = 90; asserting!("bit() returns 0 when indexing past the last bit") - .that( &[byte.bit(8), byte.bit(9), byte.bit(10)] ) - .is_equal_to( &[false, false, false] ); + .that(&[byte.bit(8), byte.bit(9), byte.bit(10)]) + .is_equal_to(&[false, false, false]); asserting!("bits(RangeTo) can index past the last bit") - .that( &byte.bits(..16) ) - .is_equal_to( 90 ); + .that(&byte.bits(..16)) + .is_equal_to(90); asserting!("bits(RangeToInclusive) can index past the last bit") - .that( &byte.bits(..=15) ) - .is_equal_to( 90 ); + .that(&byte.bits(..=15)) + .is_equal_to(90); asserting!("bits(RangeFrom) can index past the last bit") - .that( &byte.bits(4..) ) - .is_equal_to( 5 ); + .that(&byte.bits(4..)) + .is_equal_to(5); asserting!("bits(RangeFrom) is 0 when completely past the last bit") - .that( &byte.bits(8..) ) - .is_equal_to( 0 ); + .that(&byte.bits(8..)) + .is_equal_to(0); asserting!("bits(Range) can index past the last bit") - .that( &byte.bits(4..16) ) - .is_equal_to( 5 ); + .that(&byte.bits(4..16)) + .is_equal_to(5); asserting!("bits(Range) is 0 when completely past the last bit") - .that( &byte.bits(8..16) ) - .is_equal_to( 0 ); + .that(&byte.bits(8..16)) + .is_equal_to(0); asserting!("bits(RangeInclusive) can index past the last bit") - .that( &byte.bits(4..=15) ) - .is_equal_to( 5 ); + .that(&byte.bits(4..=15)) + .is_equal_to(5); asserting!("bits(RangeInclusive) is 0 when completely past the last bit") - .that( &byte.bits(8..=15) ) - .is_equal_to( 0 ); + .that(&byte.bits(8..=15)) + .is_equal_to(0); asserting!("bits(RangeEU) can index past the last bit") - .that( &byte.bits(RangeEU(4)) ) - .is_equal_to( 2 ); + .that(&byte.bits(RangeEU(4))) + .is_equal_to(2); asserting!("bits(RangeEU) is 0 when completely past the last bit") - .that( &byte.bits(RangeEU(8)) ) - .is_equal_to( 0 ); + .that(&byte.bits(RangeEU(8))) + .is_equal_to(0); asserting!("bits(RangeEE) can index past the last bit") - .that( &byte.bits(RangeEE(4, 16)) ) - .is_equal_to( 2 ); + .that(&byte.bits(RangeEE(4, 16))) + .is_equal_to(2); asserting!("bits(RangeEE) is 0 when completely past the last bit") - .that( &byte.bits(RangeEE(8, 16)) ) - .is_equal_to( 0 ); + .that(&byte.bits(RangeEE(8, 16))) + .is_equal_to(0); asserting!("bits(RangeEI) can index past the last bit") - .that( &byte.bits(RangeEI(4, 15)) ) - .is_equal_to( 2 ); + .that(&byte.bits(RangeEI(4, 15))) + .is_equal_to(2); asserting!("bits(RangeEI) is 0 when completely past the last bit") - .that( &byte.bits(RangeEI(8, 15)) ) - .is_equal_to( 0 ); + .that(&byte.bits(RangeEI(8, 15))) + .is_equal_to(0); } #[test] @@ -244,63 +268,63 @@ mod test { let byte: i8 = -90; asserting!("bit() looks up the correct bit") - .that( &[byte.bit(2), byte.bit(3), byte.bit(4), byte.bit(5)] ) - .is_equal_to( &[true, false, false, true] ); + .that(&[byte.bit(2), byte.bit(3), byte.bit(4), byte.bit(5)]) + .is_equal_to(&[true, false, false, true]); asserting!("bits(Range) is equal to the equivalent shift and mask") - .that( &byte.bits(2..6) ) - .is_equal_to( byte >> 2 & 0xf ); + .that(&byte.bits(2..6)) + .is_equal_to(byte >> 2 & 0xf); asserting!("bits(RangeFrom) is equal to the equivalent shift and mask") - .that( &byte.bits(2..) ) - .is_equal_to( byte >> 2 ); + .that(&byte.bits(2..)) + .is_equal_to(byte >> 2); asserting!("bits(RangeFull) returns the whole value") - .that( &byte.bits(..) ) - .is_equal_to( -90 ); + .that(&byte.bits(..)) + .is_equal_to(-90); asserting!("bits(RangeTo) excludes the end bit") - .that( &byte.bits(..5) ) - .is_equal_to( 6 ); + .that(&byte.bits(..5)) + .is_equal_to(6); asserting!("bits(RangeToInclusive) includes the end bit") - .that( &byte.bits(..=5) ) - .is_equal_to( 38 ); + .that(&byte.bits(..=5)) + .is_equal_to(38); asserting!("bits(RangeFrom) includes the start bit") - .that( &byte.bits(4..) ) - .is_equal_to( -6 ); + .that(&byte.bits(4..)) + .is_equal_to(-6); asserting!("bits(Range) includes the start bit") - .that( &byte.bits(4..8) ) - .is_equal_to( 10 ); + .that(&byte.bits(4..8)) + .is_equal_to(10); asserting!("bits(Range) excludes the end bit") - .that( &byte.bits(0..5) ) - .is_equal_to( 6 ); + .that(&byte.bits(0..5)) + .is_equal_to(6); asserting!("bits(RangeInclusive) includes the start bit") - .that( &byte.bits(4..=7) ) - .is_equal_to( 10 ); + .that(&byte.bits(4..=7)) + .is_equal_to(10); asserting!("bits(RangeInclusive) includes the end bit") - .that( &byte.bits(0..=5) ) - .is_equal_to( 38 ); + .that(&byte.bits(0..=5)) + .is_equal_to(38); asserting!("bits(RangeEU) excludes the start bit") - .that( &byte.bits(RangeEU(4)) ) - .is_equal_to( -3 ); + .that(&byte.bits(RangeEU(4))) + .is_equal_to(-3); asserting!("bits(RangeEE) excludes the start bit") - .that( &byte.bits(RangeEE(4, 8)) ) - .is_equal_to( 5 ); + .that(&byte.bits(RangeEE(4, 8))) + .is_equal_to(5); asserting!("bits(RangeEE) excludes the end bit") - .that( &byte.bits(RangeEE(0, 2)) ) - .is_equal_to( 1 ); + .that(&byte.bits(RangeEE(0, 2))) + .is_equal_to(1); asserting!("bits(RangeEI) excludes the start bit") - .that( &byte.bits(RangeEI(2, 4)) ) - .is_equal_to( 0 ); + .that(&byte.bits(RangeEI(2, 4))) + .is_equal_to(0); asserting!("bits(RangeEI) includes the end bit") - .that( &byte.bits(RangeEI(2, 5)) ) - .is_equal_to( 4 ); + .that(&byte.bits(RangeEI(2, 5))) + .is_equal_to(4); } #[test] @@ -308,57 +332,57 @@ mod test { let byte: i8 = -90; asserting!("bit() returns 1 when indexing past the last bit") - .that( &[byte.bit(8), byte.bit(9), byte.bit(10)] ) - .is_equal_to( &[true, true, true] ); + .that(&[byte.bit(8), byte.bit(9), byte.bit(10)]) + .is_equal_to(&[true, true, true]); asserting!("bits(RangeTo) can index past the last bit") - .that( &byte.bits(..16) ) - .is_equal_to( -90 ); + .that(&byte.bits(..16)) + .is_equal_to(-90); asserting!("bits(RangeToInclusive) can index past the last bit") - .that( &byte.bits(..=15) ) - .is_equal_to( -90 ); + .that(&byte.bits(..=15)) + .is_equal_to(-90); asserting!("bits(RangeFrom) can index past the last bit") - .that( &byte.bits(4..) ) - .is_equal_to( -6 ); + .that(&byte.bits(4..)) + .is_equal_to(-6); asserting!("bits(RangeFrom) is -1 (0xff) when completely past the last bit") - .that( &byte.bits(8..) ) - .is_equal_to( -1 ); + .that(&byte.bits(8..)) + .is_equal_to(-1); asserting!("bits(Range) can index past the last bit") - .that( &byte.bits(4..16) ) - .is_equal_to( -6 ); + .that(&byte.bits(4..16)) + .is_equal_to(-6); asserting!("bits(Range) is -1 (0xff) when completely past the last bit") - .that( &byte.bits(8..16) ) - .is_equal_to( -1 ); + .that(&byte.bits(8..16)) + .is_equal_to(-1); asserting!("bits(RangeInclusive) can index past the last bit") - .that( &byte.bits(4..=15) ) - .is_equal_to( -6 ); + .that(&byte.bits(4..=15)) + .is_equal_to(-6); asserting!("bits(RangeInclusive) is -1 (0xff) when completely past the last bit") - .that( &byte.bits(8..=15) ) - .is_equal_to( -1 ); + .that(&byte.bits(8..=15)) + .is_equal_to(-1); asserting!("bits(RangeEU) can index past the last bit") - .that( &byte.bits(RangeEU(4)) ) - .is_equal_to( -3 ); + .that(&byte.bits(RangeEU(4))) + .is_equal_to(-3); asserting!("bits(RangeEU) is -1 (0xff) when completely past the last bit") - .that( &byte.bits(RangeEU(8)) ) - .is_equal_to( -1 ); + .that(&byte.bits(RangeEU(8))) + .is_equal_to(-1); asserting!("bits(RangeEE) can index past the last bit") - .that( &byte.bits(RangeEE(4, 16)) ) - .is_equal_to( -3 ); + .that(&byte.bits(RangeEE(4, 16))) + .is_equal_to(-3); asserting!("bits(RangeEE) is -1 (0xff) when completely past the last bit") - .that( &byte.bits(RangeEE(8, 17)) ) - .is_equal_to( -1 ); + .that(&byte.bits(RangeEE(8, 17))) + .is_equal_to(-1); asserting!("bits(RangeEI) can index past the last bit") - .that( &byte.bits(RangeEI(4, 15)) ) - .is_equal_to( -3 ); + .that(&byte.bits(RangeEI(4, 15))) + .is_equal_to(-3); asserting!("bits(RangeEI) is -1 (0xff) when completely past the last bit") - .that( &byte.bits(RangeEI(8, 16)) ) - .is_equal_to( -1 ); + .that(&byte.bits(RangeEI(8, 16))) + .is_equal_to(-1); } } diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 7fb14ec..107aa90 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -25,15 +25,21 @@ pub trait BitMask: BitSize { } macro_rules! bit_mask_impl { - ($type:ty, _, $s_ty:ty) => { bit_mask_impl!($type, $type, $s_ty); }; - ($type:ty, $u_ty:ty, _) => { bit_mask_impl!($type, $u_ty, $type); }; + ($type:ty, _, $s_ty:ty) => { + bit_mask_impl!($type, $type, $s_ty); + }; + ($type:ty, $u_ty:ty, _) => { + bit_mask_impl!($type, $u_ty, $type); + }; ($type:ty, $u_ty:ty, $s_ty:ty) => { impl BitMask for $type { fn mask(size: usize) -> Self { let high_bit = ((1 as $u_ty) << (Self::BIT_SIZE - 1)) as $s_ty; match size { 0 => 0, - s if s < Self::BIT_SIZE => (((high_bit >> s) as $u_ty) >> Self::BIT_SIZE - s) as Self, + s if s < Self::BIT_SIZE => { + (((high_bit >> s) as $u_ty) >> Self::BIT_SIZE - s) as Self + } _ => (high_bit >> Self::BIT_SIZE - 1) as Self, } } @@ -60,43 +66,43 @@ bit_mask_impl!(isize, usize, _); #[cfg(test)] mod test { - use spectral::prelude::*; use super::*; + use spectral::prelude::*; #[test] fn calculating_masks() { asserting!("masks of length 0 have no bits set") - .that( &u8::mask(0) ) - .is_equal_to( 0 ); - + .that(&u8::mask(0)) + .is_equal_to(0); + asserting!("masks have the correct number of bits set") - .that( &[u8::mask(7), u8::mask(4), u8::mask(3)] ) - .is_equal_to( &[0x07f, 0x0f, 0x07] ); + .that(&[u8::mask(7), u8::mask(4), u8::mask(3)]) + .is_equal_to(&[0x07f, 0x0f, 0x07]); asserting!("masks longer than the bit length have all bits set") - .that( &u8::mask(10) ) - .is_equal_to( 0xff ); + .that(&u8::mask(10)) + .is_equal_to(0xff); } #[test] fn masking_values() { asserting!("masking to 0 bits returns 0") - .that( &145u8.mask_to(0) ) - .is_equal_to( 0 ); + .that(&145u8.mask_to(0)) + .is_equal_to(0); asserting!("masking to a number truncates the value") - .that( &255u8.mask_to(4) ) - .is_equal_to( 15 ); + .that(&255u8.mask_to(4)) + .is_equal_to(15); asserting!("masking to more bits than the bit length returns the number") - .that( &204u8.mask_to(10) ) - .is_equal_to( 204 ); + .that(&204u8.mask_to(10)) + .is_equal_to(204); } #[test] fn signed_masks() { asserting!("signed masks are the same as unsigned masks") - .that( &(u8::mask(4), i8::mask(4)) ) - .is_equal_to( (0x0f, 0x0f) ); + .that(&(u8::mask(4), i8::mask(4))) + .is_equal_to((0x0f, 0x0f)); } -} \ No newline at end of file +} diff --git a/src/bit_size.rs b/src/bit_size.rs index 365ae21..8b3ff0e 100644 --- a/src/bit_size.rs +++ b/src/bit_size.rs @@ -21,7 +21,7 @@ macro_rules! bit_size_impl { impl BitSize for $type { const BIT_SIZE: usize = $sz; } - } + }; } bit_size_impl!(u8, 8); @@ -29,12 +29,16 @@ bit_size_impl!(u16, 16); bit_size_impl!(u32, 32); bit_size_impl!(u64, 64); bit_size_impl!(u128, 128); -#[cfg(target_pointer_width = "32")] bit_size_impl!(usize, 32); -#[cfg(target_pointer_width = "64")] bit_size_impl!(usize, 64); +#[cfg(target_pointer_width = "32")] +bit_size_impl!(usize, 32); +#[cfg(target_pointer_width = "64")] +bit_size_impl!(usize, 64); bit_size_impl!(i8, 8); bit_size_impl!(i16, 16); bit_size_impl!(i32, 32); bit_size_impl!(i64, 64); bit_size_impl!(i128, 128); -#[cfg(target_pointer_width = "32")] bit_size_impl!(isize, 32); -#[cfg(target_pointer_width = "64")] bit_size_impl!(isize, 64); \ No newline at end of file +#[cfg(target_pointer_width = "32")] +bit_size_impl!(isize, 32); +#[cfg(target_pointer_width = "64")] +bit_size_impl!(isize, 64); diff --git a/src/lib.rs b/src/lib.rs index 37afa4e..c49a0ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,7 @@ //! //! Accessing a bit or range of bits in a numeric primitive can be awkward and less than readable //! using shifts and masks: -//! +//! //! ``` //! # let big: u16 = 0x35; //! let small = big >> 2 & 0x1f;