|
@@ -1,25 +1,17 @@
|
|
|
-use core::cell::RefCell;
|
|
|
-
|
|
|
-extern crate alloc;
|
|
|
use alloc::vec::Vec;
|
|
|
+use core::cell::RefCell;
|
|
|
|
|
|
pub struct ImmutVecItem<T> {
|
|
|
prev: Option<usize>,
|
|
|
data: T,
|
|
|
}
|
|
|
+
|
|
|
+#[derive(Copy, Clone)]
|
|
|
pub struct ImmutVec<'a, T> {
|
|
|
inner: &'a RefCell<Vec<ImmutVecItem<T>>>,
|
|
|
id: Option<usize>,
|
|
|
}
|
|
|
-impl<'a, T> Copy for ImmutVec<'a, T> {}
|
|
|
-impl<'a, T> Clone for ImmutVec<'a, T> {
|
|
|
- fn clone(&self) -> Self {
|
|
|
- Self {
|
|
|
- inner: self.inner,
|
|
|
- id: self.id,
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
+
|
|
|
impl<'a, T> ImmutVec<'a, T> {
|
|
|
pub fn new(inner: &'a RefCell<Vec<ImmutVecItem<T>>>) -> Self {
|
|
|
Self { inner, id: None }
|
|
@@ -38,7 +30,8 @@ impl<'a, T> ImmutVec<'a, T> {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-impl<'a, T: Clone> ImmutVec<'a, T> {
|
|
|
+
|
|
|
+impl<'a, T: Copy> ImmutVec<'a, T> {
|
|
|
#[must_use = "pop does nothing to the original vector"]
|
|
|
pub fn pop(self) -> (Self, Option<T>) {
|
|
|
let inner = self.inner.borrow();
|
|
@@ -52,7 +45,7 @@ impl<'a, T: Clone> ImmutVec<'a, T> {
|
|
|
id: item.prev,
|
|
|
..self
|
|
|
},
|
|
|
- Some(item.data.clone()),
|
|
|
+ Some(item.data),
|
|
|
)
|
|
|
}
|
|
|
pub fn iter_rev(self) -> ImmutVecIter<'a, T> {
|
|
@@ -60,8 +53,8 @@ impl<'a, T: Clone> ImmutVec<'a, T> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-pub struct ImmutVecIter<'a, T: Clone>(ImmutVec<'a, T>);
|
|
|
-impl<'a, T: Clone> Iterator for ImmutVecIter<'a, T> {
|
|
|
+pub struct ImmutVecIter<'a, T: Copy>(ImmutVec<'a, T>);
|
|
|
+impl<T: Copy> Iterator for ImmutVecIter<'_, T> {
|
|
|
type Item = T;
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
@@ -70,3 +63,52 @@ impl<'a, T: Clone> Iterator for ImmutVecIter<'a, T> {
|
|
|
item
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+#[cfg(test)]
|
|
|
+mod tests {
|
|
|
+ use alloc::vec::Vec;
|
|
|
+ use core::cell::RefCell;
|
|
|
+
|
|
|
+ use super::ImmutVec;
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn immutvec_iter_works() {
|
|
|
+ let cell = RefCell::new(Vec::new());
|
|
|
+ let mut iv = ImmutVec::new(&cell);
|
|
|
+
|
|
|
+ for i in 0..=100 {
|
|
|
+ iv = iv.push(i);
|
|
|
+ }
|
|
|
+ assert_eq!(Some(100), iv.id);
|
|
|
+
|
|
|
+ for (i, j) in iv.iter_rev().zip(100..=0) {
|
|
|
+ assert_eq!(i, j);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn push_to_rewound_vec_sets_correct_id() {
|
|
|
+ let cell = RefCell::new(Vec::new());
|
|
|
+ let mut iv = ImmutVec::new(&cell);
|
|
|
+
|
|
|
+ for i in 0..10 {
|
|
|
+ iv = iv.push(i);
|
|
|
+ }
|
|
|
+ assert_eq!(Some(9), iv.id);
|
|
|
+
|
|
|
+ for _ in 0..10 {
|
|
|
+ (iv, _) = iv.pop();
|
|
|
+ }
|
|
|
+ assert_eq!(
|
|
|
+ 10,
|
|
|
+ iv.inner.borrow().len(),
|
|
|
+ "Length shouldn't change from popping items"
|
|
|
+ );
|
|
|
+
|
|
|
+ // Pushing an item should append to the end regardless of where we are in the vector
|
|
|
+ assert_eq!(None, iv.id);
|
|
|
+ iv = iv.push(10);
|
|
|
+ assert_eq!(11, iv.inner.borrow().len());
|
|
|
+ assert_eq!(Some(10), iv.id);
|
|
|
+ }
|
|
|
+}
|