From db3fd0f6711f67f97eb0b70ef869144c7ec50190 Mon Sep 17 00:00:00 2001 From: Dan Kaplun Date: Sat, 7 Apr 2018 20:53:17 -0400 Subject: [PATCH 1/3] fn range(&self, range: Range) -> VecRange --- src/lib.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/tests.rs | 16 ++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 0b15c34..1990cfd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -416,6 +416,17 @@ impl SmallBitVec { Iter { vec: self, range: 0..self.len() } } + /// 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 { + 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(); @@ -783,3 +794,46 @@ 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> Iterator for VecRange<'a> { + type Item = bool; + + #[inline] + fn next(&mut self) -> Option { + self.range.next().and_then(|i| self.vec.get(i)) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } +} + +impl<'a> DoubleEndedIterator for VecRange<'a> { + #[inline] + fn next_back(&mut self) -> Option { + self.range.next_back().and_then(|i| self.vec.get(i)) + } +} + +impl<'a> ExactSizeIterator for VecRange<'a> {} + +impl<'a> Index for VecRange<'a> { + type Output = bool; + + #[inline] + fn index(&self, i: usize) -> &bool { + &self.vec[i + self.range.start] + } +} diff --git a/src/tests.rs b/src/tests.rs index d93621c..ae4b7fd 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -181,6 +181,22 @@ 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 mut r = v.range(0..3); + assert_eq!(r.next(), Some(true)); + assert_eq!(r.next(), Some(false)); + assert_eq!(r.next(), Some(false)); + assert_eq!(r.next(), None); + assert_eq!(r[0], true); +} + #[test] fn debug() { let mut v = SmallBitVec::new(); From 9fbde4531f5289bf1610f63617c5259e0d9c8b43 Mon Sep 17 00:00:00 2001 From: Dan Kaplun Date: Tue, 17 Apr 2018 19:19:51 -0400 Subject: [PATCH 2/3] Panic if range is out of bounds --- src/lib.rs | 1 + src/tests.rs | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 24c2768..0fe80bc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -431,6 +431,7 @@ impl SmallBitVec { /// 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 } } diff --git a/src/tests.rs b/src/tests.rs index ac463a6..7f1f216 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -203,6 +203,15 @@ fn range() { 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] fn debug() { let mut v = SmallBitVec::new(); From 6e4e85baa249228e258cad5d63082ecc8af3850d Mon Sep 17 00:00:00 2001 From: Dan Kaplun Date: Tue, 17 Apr 2018 19:29:33 -0400 Subject: [PATCH 3/3] Add iter method, remove impl Iterator from VecRange --- src/lib.rs | 30 +++++++++--------------------- src/tests.rs | 22 +++++++++++++++++----- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0fe80bc..edad273 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -830,34 +830,22 @@ pub struct VecRange<'a> { range: Range, } -impl<'a> Iterator for VecRange<'a> { - type Item = bool; - - #[inline] - fn next(&mut self) -> Option { - self.range.next().and_then(|i| self.vec.get(i)) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.range.size_hint() - } -} - -impl<'a> DoubleEndedIterator for VecRange<'a> { - #[inline] - fn next_back(&mut self) -> Option { - self.range.next_back().and_then(|i| self.vec.get(i)) +impl<'a> VecRange<'a> { + pub fn iter(&self) -> Iter<'a> { + Iter { + vec: self.vec, + range: self.range.clone(), + } } } -impl<'a> ExactSizeIterator for VecRange<'a> {} - impl<'a> Index for VecRange<'a> { type Output = bool; #[inline] fn index(&self, i: usize) -> &bool { - &self.vec[i + self.range.start] + 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 7f1f216..6a13ea8 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -195,11 +195,11 @@ fn range() { v.push(false); v.push(true); - let mut r = v.range(0..3); - assert_eq!(r.next(), Some(true)); - assert_eq!(r.next(), Some(false)); - assert_eq!(r.next(), Some(false)); - assert_eq!(r.next(), None); + 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); } @@ -212,6 +212,18 @@ fn range_oob() { 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();