diff --git a/src/lib.rs b/src/lib.rs index 3b3ef09..edad273 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -423,6 +423,18 @@ impl SmallBitVec { } } + /// Returns an immutable view of a range of bits from this vec. + /// ``` + /// #[macro_use] extern crate smallbitvec; + /// let v = sbvec![true, false, true]; + /// let r = v.range(1..3); + /// assert_eq!(r[1], true); + /// ``` + pub fn range(&self, range: Range) -> VecRange { + assert!(range.end <= self.len(), "range out of bounds"); + VecRange { vec: &self, range } + } + /// Returns true if all the bits in the vec are set to zero/false. pub fn all_false(&self) -> bool { let mut len = self.len(); @@ -806,3 +818,34 @@ impl<'a> DoubleEndedIterator for Iter<'a> { } impl<'a> ExactSizeIterator for Iter<'a> {} + +/// An immutable view of a range of bits from a borrowed SmallBitVec. +/// +/// Returned from [`SmallBitVec::range`][1]. +/// +/// [1]: struct.SmallBitVec.html#method.range +#[derive(Debug, Clone)] +pub struct VecRange<'a> { + vec: &'a SmallBitVec, + range: Range, +} + +impl<'a> VecRange<'a> { + pub fn iter(&self) -> Iter<'a> { + Iter { + vec: self.vec, + range: self.range.clone(), + } + } +} + +impl<'a> Index for VecRange<'a> { + type Output = bool; + + #[inline] + fn index(&self, i: usize) -> &bool { + let vec_i = i + self.range.start; + assert!(vec_i < self.range.end, "index out of range"); + &self.vec[vec_i] + } +} diff --git a/src/tests.rs b/src/tests.rs index 46b4837..6a13ea8 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -187,6 +187,43 @@ fn iter_back() { assert_eq!(i.next(), None); } +#[test] +fn range() { + let mut v = SmallBitVec::new(); + v.push(true); + v.push(false); + v.push(false); + v.push(true); + + let r = v.range(0..2); + let mut ri = r.iter(); + assert_eq!(ri.next(), Some(true)); + assert_eq!(ri.next(), Some(false)); + assert_eq!(ri.next(), None); + assert_eq!(r[0], true); +} + +#[test] +#[should_panic(expected = "range out of bounds")] +fn range_oob() { + let mut v = SmallBitVec::new(); + v.push(true); + + v.range(0..2); +} + +#[test] +#[should_panic(expected = "index out of range")] +fn range_index_oob() { + let mut v = SmallBitVec::new(); + v.push(true); + v.push(false); + v.push(true); + + let r = v.range(1..2); + r[1]; +} + #[test] fn debug() { let mut v = SmallBitVec::new();