diff --git a/src/sync.rs b/src/sync.rs index cfb182b..2f3d435 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -65,6 +65,15 @@ impl FrozenMap { } } +impl From> for FrozenVec { + fn from(vec: Vec) -> Self { + Self { + vec: RwLock::new(vec), + } + } +} + + impl FrozenMap { // these should never return &K or &V // these should never delete any entries @@ -492,6 +501,53 @@ impl FrozenVec { let vec = self.vec.read().unwrap(); unsafe { vec.get(index).map(|x| &*(&**x as *const T::Target)) } } + + /// Returns an iterator over the vector. + pub fn iter(&self) -> Iter<'_, T> { + self.into_iter() + } +} + +/// Iterator over FrozenVec, obtained via `.iter()` +/// +/// It is safe to push to the vector during iteration +#[derive(Debug)] +pub struct Iter<'a, T> { + vec: &'a FrozenVec, + idx: usize, +} + +impl<'a, T: StableDeref> Iterator for Iter<'a, T> { + type Item = &'a T::Target; + fn next(&mut self) -> Option<&'a T::Target> { + if let Some(ret) = self.vec.get(self.idx) { + self.idx += 1; + Some(ret) + } else { + None + } + } +} + +impl<'a, T: StableDeref> IntoIterator for &'a FrozenVec { + type Item = &'a T::Target; + type IntoIter = Iter<'a, T>; + fn into_iter(self) -> Iter<'a, T> { + Iter { vec: self, idx: 0 } + } +} + +#[test] +fn test_iteration() { + let vec = vec!["a", "b", "c", "d"]; + let frozen: FrozenVec<_> = vec.clone().into(); + + assert_eq!(vec, frozen.iter().collect::>()); + for (e1, e2) in vec.iter().zip(frozen.iter()) { + assert_eq!(*e1, e2); + } + + assert_eq!(vec.len(), frozen.iter().count()) } impl FrozenVec {