🔥 Rename VecCell::get to VecCell::borrow

pull/1/head
Shad Amethyst 2 years ago
parent 54349d1d26
commit 4c1cae2537
Signed by: amethyst
GPG Key ID: D970C8DD1D6DEE36

@ -1,6 +1,6 @@
[package] [package]
name = "veccell" name = "veccell"
version = "0.1.1" version = "0.2.0"
edition = "2021" edition = "2021"
authors = [ "Shad Amethyst <adrien.burgun@orange.fr>" ] authors = [ "Shad Amethyst <adrien.burgun@orange.fr>" ]
description = "Provides VecCell, a variant of Vec with interior mutability." description = "Provides VecCell, a variant of Vec with interior mutability."

@ -7,7 +7,7 @@ You would use this crate if:
- You need a `Vec` with interior mutability - You need a `Vec` with interior mutability
- You only want mutable access to one element at a time - 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 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: You would need something else if:
@ -39,14 +39,14 @@ arr.push(48);
arr.push(2); arr.push(2);
let mut third = arr.borrow_mut(2).unwrap(); // Borrow the third element mutably 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 *third *= *first; // Multiply the third element by the first element
println!("{}", third.get()); // Prints 64 println!("{}", third.get()); // Prints 64
std::mem::drop(third); // Drop the mutable borrow 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: 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 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. // because the third element is already borrowed mutably.
let third2 = arr.get(2); let third2 = arr.borrow(2);
assert!(third2.is_none()); assert!(third2.is_none());
@ -89,7 +89,7 @@ arr.push(32);
arr.push(48); arr.push(48);
arr.push(8); arr.push(8);
let second = arr.get(1).unwrap(); let second = arr.borrow(1).unwrap();
let third = arr.borrow_mut(2); let third = arr.borrow_mut(2);

@ -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 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. /// 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). /// - 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). /// - 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<UnsafeCell<T>>` using [`inner()`](VecCell::inner) and [`inner_mut()`](VecCell::inner_mut). /// - You may access the internal `Vec<UnsafeCell<T>>` 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 /// // Get a mutable reference *then* an immutable reference
/// // (would fail if the order was reversed) /// // (would fail if the order was reversed)
/// let mut current = vec.borrow_mut(index).unwrap(); /// 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 /// // Give both references to update
/// update(current.get_mut(), prev.get()); /// update(current.get_mut(), prev.get());
@ -221,7 +221,7 @@ impl<T> VecCell<T> {
/// // There are no borrows at this point /// // There are no borrows at this point
/// assert_eq!(vec.borrows(), 0); /// assert_eq!(vec.borrows(), 0);
/// ///
/// let x = vec.get(1); /// let x = vec.borrow(1);
/// ///
/// // There is exactly one borrow at this point /// // There is exactly one borrow at this point
/// assert_eq!(vec.borrows(), 1); /// assert_eq!(vec.borrows(), 1);
@ -270,11 +270,11 @@ impl<T> VecCell<T> {
/// ///
/// vec.push(32); /// vec.push(32);
/// assert_eq!(vec.len(), 1); /// assert_eq!(vec.len(), 1);
/// assert_eq!(vec.get(0).unwrap(), 32); /// assert_eq!(vec.borrow(0).unwrap(), 32);
/// ///
/// vec.push(127); /// vec.push(127);
/// assert_eq!(vec.len(), 2); /// 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) { pub fn push(&mut self, value: T) {
self.inner.push(UnsafeCell::new(value)); self.inner.push(UnsafeCell::new(value));
@ -319,11 +319,11 @@ impl<T> VecCell<T> {
/// vec.push(2); /// vec.push(2);
/// vec.push(3); /// vec.push(3);
/// ///
/// let x = vec.get(1).unwrap(); /// let x = vec.borrow(1).unwrap();
/// ///
/// assert_eq!(*x, 2); /// assert_eq!(*x, 2);
/// ///
/// let y = vec.get(1).unwrap(); /// let y = vec.borrow(1).unwrap();
/// ///
/// assert_eq!(x, y); /// assert_eq!(x, y);
/// ///
@ -331,7 +331,7 @@ impl<T> VecCell<T> {
/// std::mem::drop(x); /// std::mem::drop(x);
/// std::mem::drop(y); /// std::mem::drop(y);
/// ``` /// ```
pub fn get<'b>(&'b self, index: usize) -> Option<VecRef<'b, T>> { pub fn borrow<'b>(&'b self, index: usize) -> Option<VecRef<'b, T>> {
VecRef::new(self, index) VecRef::new(self, index)
} }
@ -351,7 +351,7 @@ impl<T> VecCell<T> {
/// vec.push(2); /// vec.push(2);
/// vec.push(3); /// 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<usize>>(&'b self, range: R) -> Option<VecRange<'b, T>> { pub fn borrow_range<'b, R: std::ops::RangeBounds<usize>>(&'b self, range: R) -> Option<VecRange<'b, T>> {
VecRange::new(self, range) VecRange::new(self, range)
@ -375,7 +375,7 @@ impl<T> VecCell<T> {
/// vec.push(3); /// vec.push(3);
/// ///
/// let mut x = vec.borrow_mut(1).unwrap(); /// let mut x = vec.borrow_mut(1).unwrap();
/// let y = vec.get(2).unwrap(); /// let y = vec.borrow(2).unwrap();
/// ///
/// *x = *y; /// *x = *y;
/// ///
@ -383,7 +383,7 @@ impl<T> VecCell<T> {
/// std::mem::drop(x); /// std::mem::drop(x);
/// std::mem::drop(y); /// 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<'b, T>> { pub fn borrow_mut<'b>(&'b self, index: usize) -> Option<VecRefMut<'b, T>> {
VecRefMut::new(self, index) VecRefMut::new(self, index)
@ -405,7 +405,7 @@ impl<T> VecCell<T> {
/// let x = vec.get_mut(1).unwrap(); /// let x = vec.get_mut(1).unwrap();
/// *x = 5; /// *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> { pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
self.inner.get_mut(index).map(UnsafeCell::get_mut) self.inner.get_mut(index).map(UnsafeCell::get_mut)
@ -489,7 +489,7 @@ impl<T> VecCell<T> {
/// ``` /// ```
pub fn try_iter<'b>(&'b self) -> impl Iterator<Item = Option<VecRef<'b, T>>> { pub fn try_iter<'b>(&'b self) -> impl Iterator<Item = Option<VecRef<'b, T>>> {
(0..self.len()).map(|index| { (0..self.len()).map(|index| {
self.get(index) self.borrow(index)
}) })
} }
@ -509,7 +509,7 @@ impl<T> VecCell<T> {
/// vec.push(2); /// vec.push(2);
/// ///
/// let x = vec.borrow_mut(1); /// let x = vec.borrow_mut(1);
/// let y = vec.get(2); /// let y = vec.borrow(2);
/// ///
/// std::mem::forget(x); /// std::mem::forget(x);
/// std::mem::forget(y); /// std::mem::forget(y);
@ -622,6 +622,7 @@ impl<'a, T: 'a> IntoIterator for &'a VecCell<T> {
} }
// TODO: remove once https://github.com/rust-lang/rust/issues/63063 is merged // TODO: remove once https://github.com/rust-lang/rust/issues/63063 is merged
/// Iterator returned by [`VecCell::iter`]
#[derive(Clone)] #[derive(Clone)]
pub struct VecCellRefIter<'a, T> { pub struct VecCellRefIter<'a, T> {
vec: &'a VecCell<T>, vec: &'a VecCell<T>,
@ -636,7 +637,7 @@ impl<'a, T> Iterator for VecCellRefIter<'a, T> {
return None return None
} }
let res = match self.vec.get(self.index) { let res = match self.vec.borrow(self.index) {
Some(x) => x, Some(x) => x,
None => panic!("Error while borrowing immutably element {} of VecCell: already mutably borrowed", self.index), 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) Some(res)
} }
fn size_hint(&self) -> (usize, Option<usize>) {
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<T> IntoIterator for VecCell<T> { impl<T> IntoIterator for VecCell<T> {
type Item = T; type Item = T;
type IntoIter = VecCellIntoIter<T>; type IntoIter = VecCellIntoIter<T>;
@ -661,6 +684,7 @@ impl<T> IntoIterator for VecCell<T> {
} }
// TODO: remove once https://github.com/rust-lang/rust/issues/63063 is merged // TODO: remove once https://github.com/rust-lang/rust/issues/63063 is merged
/// Iterator returned by [`VecCell::into_iter`]
pub struct VecCellIntoIter<T> { pub struct VecCellIntoIter<T> {
iter: std::vec::IntoIter<UnsafeCell<T>>, iter: std::vec::IntoIter<UnsafeCell<T>>,
} }
@ -671,8 +695,20 @@ impl<T> Iterator for VecCellIntoIter<T> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|x| x.into_inner()) self.iter.next().map(|x| x.into_inner())
} }
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<T> ExactSizeIterator for VecCellIntoIter<T> {
fn len(&self) -> usize {
self.iter.len()
}
} }
impl<T> std::iter::FusedIterator for VecCellIntoIter<T> {}
impl<T: Clone> Clone for VecCell<T> { impl<T: Clone> Clone for VecCell<T> {
/// # Panics /// # Panics
/// ///
@ -734,6 +770,12 @@ impl<T> From<Vec<T>> for VecCell<T> {
} }
} }
impl<T> From<VecCell<T>> for Vec<T> {
fn from(veccell: VecCell<T>) -> Vec<T> {
veccell.into_iter().collect::<Vec<_>>()
}
}
#[cfg(test)] #[cfg(test)]
mod test; mod test;

@ -66,14 +66,14 @@ fn test_borrow() {
let mut x = vec.borrow_mut(1).unwrap(); let mut x = vec.borrow_mut(1).unwrap();
assert_eq!(vec.get(0).unwrap(), 1); assert_eq!(vec.borrow(0).unwrap(), 1);
assert_eq!(vec.get(1), None); assert_eq!(vec.borrow(1), None);
*x = 3; *x = 3;
std::mem::drop(x); std::mem::drop(x);
assert_eq!(vec.get(1).unwrap(), 3); assert_eq!(vec.borrow(1).unwrap(), 3);
} }
#[test] #[test]
@ -90,8 +90,8 @@ fn test_double_borrow() {
assert!(vec.borrow_mut(1).is_none()); assert!(vec.borrow_mut(1).is_none());
assert_eq!(vec.mut_borrow(), Some(1)); assert_eq!(vec.mut_borrow(), Some(1));
assert_eq!(vec.get(0).unwrap(), 1); assert_eq!(vec.borrow(0).unwrap(), 1);
assert_eq!(vec.get(1), None); assert_eq!(vec.borrow(1), None);
*x = 3; *x = 3;
@ -99,19 +99,19 @@ fn test_double_borrow() {
std::mem::drop(y); std::mem::drop(y);
assert_eq!(vec.mut_borrow(), None); assert_eq!(vec.mut_borrow(), None);
assert_eq!(vec.get(1).unwrap(), 3); assert_eq!(vec.borrow(1).unwrap(), 3);
} }
#[test] #[test]
fn test_out_of_bounds() { fn test_out_of_bounds() {
let mut vec: VecCell<usize> = VecCell::new(); let mut vec: VecCell<usize> = VecCell::new();
assert!(vec.get(0).is_none()); assert!(vec.borrow(0).is_none());
vec.push(1); vec.push(1);
assert!(vec.get(0).is_some()); assert!(vec.borrow(0).is_some());
assert!(vec.get(1).is_none()); assert!(vec.borrow(1).is_none());
} }
#[test] #[test]
@ -121,7 +121,7 @@ fn test_borrow_clone() {
vec.push(1); vec.push(1);
vec.push(2); 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.borrows(), 1); assert_eq!(vec.borrows(), 1);
assert_eq!(vec.mut_borrow(), None); assert_eq!(vec.mut_borrow(), None);
@ -139,9 +139,9 @@ fn test_borrow_clone() {
std::mem::drop(y); std::mem::drop(y);
assert_eq!(vec.borrows(), 0); assert_eq!(vec.borrows(), 0);
let x = vec.get(0); let x = vec.borrow(0);
assert_eq!(vec.borrows(), 1); assert_eq!(vec.borrows(), 1);
let y = vec.get(0); let y = vec.borrow(0);
assert_eq!(vec.borrows(), 2); assert_eq!(vec.borrows(), 2);
let z = x.clone(); let z = x.clone();
assert_eq!(vec.borrows(), 3); assert_eq!(vec.borrows(), 3);
@ -161,7 +161,7 @@ fn test_borrow_mut() {
vec.push(1); vec.push(1);
vec.push(2); vec.push(2);
let x = vec.get(0); let x = vec.borrow(0);
assert!(x.is_some()); assert!(x.is_some());
let y = vec.borrow_mut(0); let y = vec.borrow_mut(0);

@ -48,6 +48,8 @@ impl<'a, T: ?Sized> VecRef<'a, T> {
} }
/// Returns a reference to the borrowed value. /// Returns a reference to the borrowed value.
/// Equivalent to `&*vec_ref`.
///
/// The reference may not outlive this `VecRef` instance. /// The reference may not outlive this `VecRef` instance.
/// ///
/// # Example /// # Example
@ -59,7 +61,7 @@ impl<'a, T: ?Sized> VecRef<'a, T> {
/// vec.push(String::from("hello")); /// vec.push(String::from("hello"));
/// vec.push(String::from("world")); /// vec.push(String::from("world"));
/// ///
/// let guard = vec.get(0).unwrap(); /// let guard = vec.borrow(0).unwrap();
/// assert_eq!(guard.get(), "hello"); /// assert_eq!(guard.get(), "hello");
/// ``` /// ```
pub fn get(&self) -> &T { pub fn get(&self) -> &T {
@ -87,7 +89,7 @@ impl<'a, T: ?Sized> VecRef<'a, T> {
/// ``` /// ```
/// # use veccell::*; /// # use veccell::*;
/// fn return_favorite_value<'a>(array: &'a VecCell<Vec<u8>>) -> VecRef<'a, u8> { /// fn return_favorite_value<'a>(array: &'a VecCell<Vec<u8>>) -> 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> 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<VecRange<'a, T>> for VecRef<'a, [T]>?
impl<'a, T> From<VecRange<'a, T>> for VecRef<'a, [UnsafeCell<T>]> { impl<'a, T> From<VecRange<'a, T>> for VecRef<'a, [UnsafeCell<T>]> {
fn from(range: VecRange<'a, T>) -> Self { fn from(range: VecRange<'a, T>) -> Self {
Self { Self {

Loading…
Cancel
Save