diff --git a/Cargo.toml b/Cargo.toml index 876891a..c73e478 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "veccell" -version = "0.1.1" +version = "0.2.0" edition = "2021" authors = [ "Shad Amethyst " ] description = "Provides VecCell, a variant of Vec with interior mutability." diff --git a/README.md b/README.md index 00df822..02db5ea 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ You would use this crate if: - You need a `Vec` with interior mutability - You only want mutable access to one element at a time - You want immutable access to all other elements while an element is borrowed mutably -- You need a constant memory cost +- You need a constant memory cost for the aliasing checks You would need something else if: @@ -39,14 +39,14 @@ arr.push(48); arr.push(2); let mut third = arr.borrow_mut(2).unwrap(); // Borrow the third element mutably -let first = arr.get(0).unwrap(); // Borrow the first element immutably +let first = arr.borrow(0).unwrap(); // Borrow the first element immutably *third *= *first; // Multiply the third element by the first element println!("{}", third.get()); // Prints 64 std::mem::drop(third); // Drop the mutable borrow -println!("{}", arr.get(2).unwrap().get()); // Also prints 64 +println!("{}", arr.borrow(2).unwrap().get()); // Also prints 64 ``` However, to prevent aliasing, while an element is borrowed mutably, it cannot be borrowed immutably: @@ -62,9 +62,9 @@ arr.push(8); let mut third = arr.borrow_mut(2).unwrap(); // Borrow the third element mutably -// Here, arr.get(2) returns None, +// Here, arr.borrow(2) returns None, // because the third element is already borrowed mutably. -let third2 = arr.get(2); +let third2 = arr.borrow(2); assert!(third2.is_none()); @@ -89,7 +89,7 @@ arr.push(32); arr.push(48); arr.push(8); -let second = arr.get(1).unwrap(); +let second = arr.borrow(1).unwrap(); let third = arr.borrow_mut(2); diff --git a/src/lib.rs b/src/lib.rs index ba65bc1..52e1821 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,7 @@ pub use vecrefmut::VecRefMut; /// New mutable references may only be created if there are no active mutable *or immutable* references. /// New immutable references may only be created for indices that aren't mutably borrowed. /// -/// - To borrow an item immutably, use [`get()`](VecCell::get). +/// - To borrow an item immutably, use [`borrow()`](VecCell::borrow). /// - To borrow an item mutably, use [`borrow_mut()`](VecCell::borrow_mut). /// - If you have a mutable reference to the `VecCell`, then you may also use [`get_mut()`](VecCell::get_mut). /// - You may access the internal `Vec>` using [`inner()`](VecCell::inner) and [`inner_mut()`](VecCell::inner_mut). @@ -62,7 +62,7 @@ pub use vecrefmut::VecRefMut; /// // Get a mutable reference *then* an immutable reference /// // (would fail if the order was reversed) /// let mut current = vec.borrow_mut(index).unwrap(); -/// let prev = vec.get(index - 1).unwrap(); +/// let prev = vec.borrow(index - 1).unwrap(); /// /// // Give both references to update /// update(current.get_mut(), prev.get()); @@ -221,7 +221,7 @@ impl VecCell { /// // There are no borrows at this point /// assert_eq!(vec.borrows(), 0); /// - /// let x = vec.get(1); + /// let x = vec.borrow(1); /// /// // There is exactly one borrow at this point /// assert_eq!(vec.borrows(), 1); @@ -270,11 +270,11 @@ impl VecCell { /// /// vec.push(32); /// assert_eq!(vec.len(), 1); - /// assert_eq!(vec.get(0).unwrap(), 32); + /// assert_eq!(vec.borrow(0).unwrap(), 32); /// /// vec.push(127); /// assert_eq!(vec.len(), 2); - /// assert_eq!(vec.get(1).unwrap(), 127); + /// assert_eq!(vec.borrow(1).unwrap(), 127); /// ``` pub fn push(&mut self, value: T) { self.inner.push(UnsafeCell::new(value)); @@ -319,11 +319,11 @@ impl VecCell { /// vec.push(2); /// vec.push(3); /// - /// let x = vec.get(1).unwrap(); + /// let x = vec.borrow(1).unwrap(); /// /// assert_eq!(*x, 2); /// - /// let y = vec.get(1).unwrap(); + /// let y = vec.borrow(1).unwrap(); /// /// assert_eq!(x, y); /// @@ -331,7 +331,7 @@ impl VecCell { /// std::mem::drop(x); /// std::mem::drop(y); /// ``` - pub fn get<'b>(&'b self, index: usize) -> Option> { + pub fn borrow<'b>(&'b self, index: usize) -> Option> { VecRef::new(self, index) } @@ -351,7 +351,7 @@ impl VecCell { /// vec.push(2); /// vec.push(3); /// - /// let s = vec.borrow_range(0..2); // Gets elements 0 and 1 + /// let s = vec.borrow_range(0..2).unwrap(); // Gets elements 0 and 1 /// ``` pub fn borrow_range<'b, R: std::ops::RangeBounds>(&'b self, range: R) -> Option> { VecRange::new(self, range) @@ -375,7 +375,7 @@ impl VecCell { /// vec.push(3); /// /// let mut x = vec.borrow_mut(1).unwrap(); - /// let y = vec.get(2).unwrap(); + /// let y = vec.borrow(2).unwrap(); /// /// *x = *y; /// @@ -383,7 +383,7 @@ impl VecCell { /// std::mem::drop(x); /// std::mem::drop(y); /// - /// assert_eq!(vec.get(1).unwrap(), 3); + /// assert_eq!(vec.borrow(1).unwrap(), 3); /// ``` pub fn borrow_mut<'b>(&'b self, index: usize) -> Option> { VecRefMut::new(self, index) @@ -405,7 +405,7 @@ impl VecCell { /// let x = vec.get_mut(1).unwrap(); /// *x = 5; /// - /// assert_eq!(vec.get(1).unwrap(), 5); + /// assert_eq!(vec.borrow(1).unwrap(), 5); /// ``` pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { self.inner.get_mut(index).map(UnsafeCell::get_mut) @@ -489,7 +489,7 @@ impl VecCell { /// ``` pub fn try_iter<'b>(&'b self) -> impl Iterator>> { (0..self.len()).map(|index| { - self.get(index) + self.borrow(index) }) } @@ -509,7 +509,7 @@ impl VecCell { /// vec.push(2); /// /// let x = vec.borrow_mut(1); - /// let y = vec.get(2); + /// let y = vec.borrow(2); /// /// std::mem::forget(x); /// std::mem::forget(y); @@ -622,6 +622,7 @@ impl<'a, T: 'a> IntoIterator for &'a VecCell { } // TODO: remove once https://github.com/rust-lang/rust/issues/63063 is merged +/// Iterator returned by [`VecCell::iter`] #[derive(Clone)] pub struct VecCellRefIter<'a, T> { vec: &'a VecCell, @@ -636,7 +637,7 @@ impl<'a, T> Iterator for VecCellRefIter<'a, T> { return None } - let res = match self.vec.get(self.index) { + let res = match self.vec.borrow(self.index) { Some(x) => x, None => panic!("Error while borrowing immutably element {} of VecCell: already mutably borrowed", self.index), }; @@ -644,8 +645,30 @@ impl<'a, T> Iterator for VecCellRefIter<'a, T> { Some(res) } + + fn size_hint(&self) -> (usize, Option) { + if self.index >= self.vec.len() { + return (0, Some(0)); + } + + let remaining = self.vec.len() - self.index; + + (remaining, Some(remaining)) + } +} + +impl<'a, T> ExactSizeIterator for VecCellRefIter<'a, T> { + fn len(&self) -> usize { + if self.index >= self.vec.len() { + 0 + } else { + self.vec.len() - self.index + } + } } +impl<'a, T> std::iter::FusedIterator for VecCellRefIter<'a, T> {} + impl IntoIterator for VecCell { type Item = T; type IntoIter = VecCellIntoIter; @@ -661,6 +684,7 @@ impl IntoIterator for VecCell { } // TODO: remove once https://github.com/rust-lang/rust/issues/63063 is merged +/// Iterator returned by [`VecCell::into_iter`] pub struct VecCellIntoIter { iter: std::vec::IntoIter>, } @@ -671,8 +695,20 @@ impl Iterator for VecCellIntoIter { fn next(&mut self) -> Option { self.iter.next().map(|x| x.into_inner()) } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl ExactSizeIterator for VecCellIntoIter { + fn len(&self) -> usize { + self.iter.len() + } } +impl std::iter::FusedIterator for VecCellIntoIter {} + impl Clone for VecCell { /// # Panics /// @@ -734,6 +770,12 @@ impl From> for VecCell { } } +impl From> for Vec { + fn from(veccell: VecCell) -> Vec { + veccell.into_iter().collect::>() + } +} + #[cfg(test)] mod test; diff --git a/src/test.rs b/src/test.rs index e4bec00..cb220d5 100644 --- a/src/test.rs +++ b/src/test.rs @@ -66,14 +66,14 @@ fn test_borrow() { let mut x = vec.borrow_mut(1).unwrap(); - assert_eq!(vec.get(0).unwrap(), 1); - assert_eq!(vec.get(1), None); + assert_eq!(vec.borrow(0).unwrap(), 1); + assert_eq!(vec.borrow(1), None); *x = 3; std::mem::drop(x); - assert_eq!(vec.get(1).unwrap(), 3); + assert_eq!(vec.borrow(1).unwrap(), 3); } #[test] @@ -90,8 +90,8 @@ fn test_double_borrow() { assert!(vec.borrow_mut(1).is_none()); assert_eq!(vec.mut_borrow(), Some(1)); - assert_eq!(vec.get(0).unwrap(), 1); - assert_eq!(vec.get(1), None); + assert_eq!(vec.borrow(0).unwrap(), 1); + assert_eq!(vec.borrow(1), None); *x = 3; @@ -99,19 +99,19 @@ fn test_double_borrow() { std::mem::drop(y); assert_eq!(vec.mut_borrow(), None); - assert_eq!(vec.get(1).unwrap(), 3); + assert_eq!(vec.borrow(1).unwrap(), 3); } #[test] fn test_out_of_bounds() { let mut vec: VecCell = VecCell::new(); - assert!(vec.get(0).is_none()); + assert!(vec.borrow(0).is_none()); vec.push(1); - assert!(vec.get(0).is_some()); - assert!(vec.get(1).is_none()); + assert!(vec.borrow(0).is_some()); + assert!(vec.borrow(1).is_none()); } #[test] @@ -121,7 +121,7 @@ fn test_borrow_clone() { vec.push(1); vec.push(2); - let x = vec.get(0); + let x = vec.borrow(0); assert_eq!(vec.borrows(), 1); assert_eq!(vec.borrows(), 1); assert_eq!(vec.mut_borrow(), None); @@ -139,9 +139,9 @@ fn test_borrow_clone() { std::mem::drop(y); assert_eq!(vec.borrows(), 0); - let x = vec.get(0); + let x = vec.borrow(0); assert_eq!(vec.borrows(), 1); - let y = vec.get(0); + let y = vec.borrow(0); assert_eq!(vec.borrows(), 2); let z = x.clone(); assert_eq!(vec.borrows(), 3); @@ -161,7 +161,7 @@ fn test_borrow_mut() { vec.push(1); vec.push(2); - let x = vec.get(0); + let x = vec.borrow(0); assert!(x.is_some()); let y = vec.borrow_mut(0); diff --git a/src/vecref.rs b/src/vecref.rs index bc3f1ba..5d029da 100644 --- a/src/vecref.rs +++ b/src/vecref.rs @@ -48,6 +48,8 @@ impl<'a, T: ?Sized> VecRef<'a, T> { } /// Returns a reference to the borrowed value. + /// Equivalent to `&*vec_ref`. + /// /// The reference may not outlive this `VecRef` instance. /// /// # Example @@ -59,7 +61,7 @@ impl<'a, T: ?Sized> VecRef<'a, T> { /// vec.push(String::from("hello")); /// vec.push(String::from("world")); /// - /// let guard = vec.get(0).unwrap(); + /// let guard = vec.borrow(0).unwrap(); /// assert_eq!(guard.get(), "hello"); /// ``` pub fn get(&self) -> &T { @@ -87,7 +89,7 @@ impl<'a, T: ?Sized> VecRef<'a, T> { /// ``` /// # use veccell::*; /// fn return_favorite_value<'a>(array: &'a VecCell>) -> VecRef<'a, u8> { - /// VecRef::map(array.get(42).unwrap(), |vec| &vec[7]) + /// VecRef::map(array.borrow(42).unwrap(), |vec| &vec[7]) /// } /// ``` pub fn map<'b, U: ?Sized, F>(original: VecRef<'b, T>, f: F) -> VecRef<'b, U> @@ -222,6 +224,7 @@ impl<'a, T> VecRange<'a, T> { } } +// TODO: use std::mem::transmute to implement From> for VecRef<'a, [T]>? impl<'a, T> From> for VecRef<'a, [UnsafeCell]> { fn from(range: VecRange<'a, T>) -> Self { Self {