🚚 Move structures into different files

pull/1/head
Shad Amethyst 2 years ago
parent 18ef956a91
commit 2a1fbd7ca3
Signed by: amethyst
GPG Key ID: D970C8DD1D6DEE36

@ -19,6 +19,12 @@ use std::cell::{Cell, UnsafeCell};
use std::fmt::{self, Debug}; use std::fmt::{self, Debug};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
mod vecref;
pub use vecref::VecRef;
mod vecrefmut;
pub use vecrefmut::VecRefMut;
/// A contiguous, growable array type with interior mutability. /// A contiguous, growable array type with interior mutability.
/// ///
/// This type allows to get a mutable reference ([`VecRefMut`]) to an index `i`, while letting you access immutably ([`VecRef`]) elements at indices `j != i`. /// This type allows to get a mutable reference ([`VecRefMut`]) to an index `i`, while letting you access immutably ([`VecRef`]) elements at indices `j != i`.
@ -706,506 +712,8 @@ impl<T> From<Vec<T>> for VecCell<T> {
} }
} }
/// Wraps a borrowed reference from a [`VecCell`].
pub struct VecRef<'a, T: ?Sized> {
borrows: &'a Cell<usize>,
value: &'a T,
}
impl<'a, T: ?Sized> VecRef<'a, T> {
fn new(vec: &'a VecCell<T>, index: usize) -> Option<Self>
where
T: Sized
{
if vec.mut_borrow.get() == Some(index) {
return None
}
if index >= vec.len() {
return None
}
vec.borrows.set(vec.borrows.get().checked_add(1)?);
Some(Self {
borrows: &vec.borrows,
value: unsafe {
// SAFETY: there are no mutable borrows of vec.inner[index]
vec.get_unchecked(index)
}
})
}
fn from(value: &'a T, borrows: &'a Cell<usize>) -> Option<Self> {
borrows.set(borrows.get().checked_add(1)?);
Some(Self {
borrows,
value
})
}
/// Returns a reference to the borrowed value.
/// The reference may not outlive this `VecRef` instance.
///
/// # Example
///
/// ```
/// # use veccell::*;
/// let mut vec: VecCell<String> = VecCell::new();
///
/// vec.push(String::from("hello"));
/// vec.push(String::from("world"));
///
/// let guard = vec.get(0).unwrap();
/// assert_eq!(guard.get(), "hello");
/// ```
pub fn get(&self) -> &T {
&*self.value
}
/// Transforms a `VecRef<'_, T>` into a `VecRef<'_, U>` from a function that maps `&T` to `&U`.
///
/// This function does not use `self` and must be called explicitly via `VecRef::map(value, function)`.
///
/// # Examples
///
/// This function comes in hand when you need to return a reference to a value in a [`VecCell`] from within a function/scope.
/// For instance, the following is disallowed:
///
/// ```compile_fail
/// # use veccell::*;
/// fn return_favorite_value<'a>(array: &'a VecCell<Vec<u8>>) -> &'a u8 {
/// &array.get(42).unwrap().get()[7]
/// }
/// ```
///
/// Instead, you would write it as follows:
///
/// ```
/// # use veccell::*;
/// fn return_favorite_value<'a>(array: &'a VecCell<Vec<u8>>) -> VecRef<'a, u8> {
/// VecRef::map(array.get(42).unwrap(), |vec| &vec[7])
/// }
/// ```
pub fn map<'b, U: ?Sized, F>(original: VecRef<'b, T>, f: F) -> VecRef<'b, U>
where
F: FnOnce(&T) -> &U
{
VecRef::from(f(original.value), original.borrows).expect("Error creating a new VecRef: integer overflow")
// original is dropped here
}
}
impl<'a, T: ?Sized> Deref for VecRef<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.value
}
}
impl<'a, T: ?Sized> Drop for VecRef<'a, T> {
#[inline]
fn drop(&mut self) {
debug_assert!(self.borrows.get() > 0, "Borrow count was null yet there was still a borrow!");
self.borrows.set(self.borrows.get() - 1);
}
}
impl<'a, T: Debug + Sized> Debug for VecRef<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VecRef")
.field(self.value)
.finish()
}
}
impl<'a, T: PartialEq + ?Sized> PartialEq for VecRef<'a, T> {
fn eq(&self, other: &Self) -> bool {
self.get() == other.get()
}
}
impl<'a, T: PartialEq + ?Sized> PartialEq<T> for VecRef<'a, T> {
fn eq(&self, other: &T) -> bool {
self.get() == other
}
}
impl<'a, T: ?Sized> Clone for VecRef<'a, T> {
fn clone(&self) -> Self {
Self::from(self.value, self.borrows).expect("Error creating a new VecRef: integer overflow")
}
}
// Lets us safely destructure VecRefMut while implementing the Drop logic
struct VecRefMutBorrow<'a>(&'a Cell<Option<usize>>);
/// Wraps a mutably borrowed value from a [`VecCell`].
pub struct VecRefMut<'a, T: ?Sized> {
mut_borrow: VecRefMutBorrow<'a>,
value: &'a mut T,
}
impl<'a, T: ?Sized> VecRefMut<'a, T> {
/// # Safety
///
/// If this function returns Some(ref), then there are no mutable borrows of ∀x, vec.inner[x]:
/// by contradiction, let `B: 'b` be a mutable borrow of lifetime `'b`. By conjunction on (IV):
/// - either `B` had exclusive access, in which case calling `VecCell::borrow_mut` is UB
/// - either `B` was obtained from a guard `VecRefMut<'c>`, in which case `'c: 'b` and `vec.mut_borrow.is_some()`, which contradicts our assertion
///
/// - The invariant (I) is upheld by the first assertion.
/// - The invariant (II) is upheld by this function, as it sets `vec.mut_borrow` to `Some(index)`.
fn new(vec: &'a VecCell<T>, index: usize) -> Option<Self>
where
T: Sized
{
if vec.borrows.get() > 0 || vec.mut_borrow.get().is_some() {
return None
}
if index >= vec.len() {
return None
}
vec.mut_borrow.set(Some(index));
Some(Self {
mut_borrow: VecRefMutBorrow(&vec.mut_borrow),
value: unsafe {
vec.get_mut_unchecked(index)
}
})
}
/// Returns an immutable reference to the borrowed value.
/// The reference may not outlive this `VecRefMut` instance.
///
/// # Example
///
/// ```
/// # use veccell::*;
/// let mut vec: VecCell<String> = VecCell::new();
///
/// vec.push(String::from("hello"));
/// vec.push(String::from("world"));
///
/// let guard = vec.borrow_mut(0).unwrap();
/// assert_eq!(guard.get(), "hello");
/// ```
pub fn get(&self) -> &T {
&*self.value
}
/// Returns a mutable reference to the borrowed value.
/// The reference may not outlive this `VecRefMut` instance.
///
/// # Example
///
/// ```
/// # use veccell::*;
/// let mut vec: VecCell<String> = VecCell::new();
///
/// vec.push(String::from("hello"));
/// vec.push(String::from("world"));
///
/// let mut guard = vec.borrow_mut(0).unwrap();
/// let hello = std::mem::replace(guard.get_mut(), String::from("potato"));
/// assert_eq!(guard.get(), "potato");
/// assert_eq!(hello, "hello");
/// ```
pub fn get_mut(&mut self) -> &mut T {
&mut *self.value
}
/// Transforms a `VecRefMut<'_, T>` into a `VecRefMut<'_, U>` from a function that maps `&mut T` to `&mut U`.
///
/// This function does not use `self` and must be called explicitly via `VecRefMut::map(value, function)`.
///
/// # Examples
///
/// ```
/// # use veccell::*;
/// fn return_favorite_value_mut<'a>(array: &'a VecCell<Vec<u8>>) -> VecRefMut<'a, u8> {
/// VecRefMut::map(array.borrow_mut(42).unwrap(), |vec| &mut vec[7])
/// }
/// ```
pub fn map<'b, U: ?Sized, F>(original: VecRefMut<'b, T>, f: F) -> VecRefMut<'b, U>
where
F: FnOnce(&mut T) -> &mut U
{
let VecRefMut { value, mut_borrow } = original;
VecRefMut {
value: f(value),
mut_borrow
}
}
}
impl<'a, T: ?Sized> Deref for VecRefMut<'a, T> {
type Target = T;
// SAFETY: Upholds invariant (IV)
fn deref(&self) -> &Self::Target {
self.value
}
}
impl<'a, T: ?Sized> DerefMut for VecRefMut<'a, T> {
// SAFETY: Upholds invariant (IV)
fn deref_mut(&mut self) -> &mut Self::Target {
self.value
}
}
impl<'a> Drop for VecRefMutBorrow<'a> {
#[inline]
fn drop(&mut self) {
debug_assert!(self.0.get().is_some());
self.0.set(None);
}
}
impl<'a, T: Debug + Sized> Debug for VecRefMut<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VecRefMut")
.field(self.value)
.finish()
}
}
impl<'a, T: PartialEq + ?Sized> PartialEq for VecRefMut<'a, T> {
fn eq(&self, other: &Self) -> bool {
self.get() == other.get()
}
}
impl<'a, T: PartialEq + ?Sized> PartialEq<T> for VecRefMut<'a, T> {
fn eq(&self, other: &T) -> bool {
self.get() == other
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test;
use super::*;
#[test]
fn test_create_vec() {
let vec: VecCell<usize> = VecCell::new();
assert_eq!(vec.len(), 0);
let vec: VecCell<i8> = VecCell::new();
assert_eq!(vec.len(), 0);
let vec: VecCell<()> = VecCell::new();
assert_eq!(vec.len(), 0);
let vec: VecCell<usize> = VecCell::with_capacity(16);
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), 16);
let vec: VecCell<i8> = VecCell::with_capacity(16);
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), 16);
let vec: VecCell<()> = VecCell::with_capacity(16);
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), usize::MAX);
let vec: VecCell<usize> = VecCell::with_capacity(0);
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), 0);
let vec: VecCell<i8> = VecCell::with_capacity(0);
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), 0);
let vec: VecCell<()> = VecCell::with_capacity(0);
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), usize::MAX);
}
#[test]
fn test_push() {
let mut vec: VecCell<usize> = VecCell::with_capacity(1);
vec.push(0);
assert_eq!(vec.len(), 1);
vec.push(1);
assert_eq!(vec.len(), 2);
vec.push(2);
assert_eq!(vec.len(), 3);
assert_eq!(vec, vec![0, 1, 2]);
}
#[test]
fn test_pop() {
let mut vec: VecCell<usize> = VecCell::new();
vec.push(1);
assert_eq!(vec.len(), 1);
vec.push(2);
assert_eq!(vec.len(), 2);
assert_eq!(vec.pop(), Some(2));
assert_eq!(vec.len(), 1);
assert_eq!(vec.pop(), Some(1));
assert_eq!(vec.len(), 0);
}
#[test]
fn test_borrow() {
let mut vec: VecCell<usize> = VecCell::new();
vec.push(1);
vec.push(2);
let mut x = vec.borrow_mut(1).unwrap();
assert_eq!(vec.get(0).unwrap(), 1);
assert_eq!(vec.get(1), None);
*x = 3;
std::mem::drop(x);
assert_eq!(vec.get(1).unwrap(), 3);
}
#[test]
fn test_double_borrow() {
let mut vec: VecCell<usize> = VecCell::new();
vec.push(1);
vec.push(2);
let mut x = vec.borrow_mut(1).unwrap();
let y = vec.borrow_mut(0);
assert!(y.is_none());
assert_eq!(vec.mut_borrow(), Some(1));
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);
*x = 3;
std::mem::drop(x);
std::mem::drop(y);
assert_eq!(vec.mut_borrow(), None);
assert_eq!(vec.get(1).unwrap(), 3);
}
#[test]
fn test_out_of_bounds() {
let mut vec: VecCell<usize> = VecCell::new();
assert!(vec.get(0).is_none());
vec.push(1);
assert!(vec.get(0).is_some());
assert!(vec.get(1).is_none());
}
#[test]
fn test_borrow_clone() {
let mut vec: VecCell<usize> = VecCell::new();
vec.push(1);
vec.push(2);
let x = vec.get(0);
assert_eq!(vec.borrows(), 1);
assert_eq!(vec.borrows(), 1);
assert_eq!(vec.mut_borrow(), None);
let y = x.clone();
assert_eq!(vec.borrows(), 2);
assert_eq!(vec.borrows(), 2);
assert_eq!(vec.mut_borrow(), None);
assert_eq!(x, y);
std::mem::drop(x);
assert_eq!(vec.borrows(), 1);
std::mem::drop(y);
assert_eq!(vec.borrows(), 0);
let x = vec.get(0);
assert_eq!(vec.borrows(), 1);
let y = vec.get(0);
assert_eq!(vec.borrows(), 2);
let z = x.clone();
assert_eq!(vec.borrows(), 3);
std::mem::drop(z);
assert_eq!(vec.borrows(), 2);
std::mem::drop(y);
assert_eq!(vec.borrows(), 1);
std::mem::drop(x);
assert_eq!(vec.borrows(), 0);
}
#[test]
fn test_borrow_mut() {
let mut vec: VecCell<usize> = VecCell::new();
vec.push(1);
vec.push(2);
let x = vec.get(0);
assert!(x.is_some());
let y = vec.borrow_mut(0);
assert!(y.is_none());
let y = vec.borrow_mut(1);
assert!(y.is_none());
std::mem::drop(x);
let y = vec.borrow_mut(0);
assert!(y.is_some());
let z = vec.borrow_mut(1);
assert!(z.is_none());
std::mem::drop(y);
}
#[test]
fn test_iter() {
let mut vec: Vec<usize> = Vec::new();
let mut vec2: VecCell<usize> = VecCell::new();
for x in 0..10 {
vec.push(x);
vec2.push(x);
}
let vec3 = vec2.iter().map(|x| *x).collect::<Vec<_>>();
assert_eq!(vec, vec3);
}
#[test]
#[should_panic]
fn test_iter_panic() {
let mut vec: VecCell<usize> = VecCell::new();
for x in 0..10 {
vec.push(x);
}
let y = vec.borrow_mut(3);
for _x in vec.iter() {
// noop
}
std::mem::drop(y);
}
}
#[doc = include_str!("../README.md")] #[doc = include_str!("../README.md")]
#[cfg(doctest)] #[cfg(doctest)]

@ -0,0 +1,215 @@
use super::*;
#[test]
fn test_create_vec() {
let vec: VecCell<usize> = VecCell::new();
assert_eq!(vec.len(), 0);
let vec: VecCell<i8> = VecCell::new();
assert_eq!(vec.len(), 0);
let vec: VecCell<()> = VecCell::new();
assert_eq!(vec.len(), 0);
let vec: VecCell<usize> = VecCell::with_capacity(16);
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), 16);
let vec: VecCell<i8> = VecCell::with_capacity(16);
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), 16);
let vec: VecCell<()> = VecCell::with_capacity(16);
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), usize::MAX);
let vec: VecCell<usize> = VecCell::with_capacity(0);
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), 0);
let vec: VecCell<i8> = VecCell::with_capacity(0);
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), 0);
let vec: VecCell<()> = VecCell::with_capacity(0);
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), usize::MAX);
}
#[test]
fn test_push() {
let mut vec: VecCell<usize> = VecCell::with_capacity(1);
vec.push(0);
assert_eq!(vec.len(), 1);
vec.push(1);
assert_eq!(vec.len(), 2);
vec.push(2);
assert_eq!(vec.len(), 3);
assert_eq!(vec, vec![0, 1, 2]);
}
#[test]
fn test_pop() {
let mut vec: VecCell<usize> = VecCell::new();
vec.push(1);
assert_eq!(vec.len(), 1);
vec.push(2);
assert_eq!(vec.len(), 2);
assert_eq!(vec.pop(), Some(2));
assert_eq!(vec.len(), 1);
assert_eq!(vec.pop(), Some(1));
assert_eq!(vec.len(), 0);
}
#[test]
fn test_borrow() {
let mut vec: VecCell<usize> = VecCell::new();
vec.push(1);
vec.push(2);
let mut x = vec.borrow_mut(1).unwrap();
assert_eq!(vec.get(0).unwrap(), 1);
assert_eq!(vec.get(1), None);
*x = 3;
std::mem::drop(x);
assert_eq!(vec.get(1).unwrap(), 3);
}
#[test]
fn test_double_borrow() {
let mut vec: VecCell<usize> = VecCell::new();
vec.push(1);
vec.push(2);
let mut x = vec.borrow_mut(1).unwrap();
let y = vec.borrow_mut(0);
assert!(y.is_none());
assert_eq!(vec.mut_borrow(), Some(1));
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);
*x = 3;
std::mem::drop(x);
std::mem::drop(y);
assert_eq!(vec.mut_borrow(), None);
assert_eq!(vec.get(1).unwrap(), 3);
}
#[test]
fn test_out_of_bounds() {
let mut vec: VecCell<usize> = VecCell::new();
assert!(vec.get(0).is_none());
vec.push(1);
assert!(vec.get(0).is_some());
assert!(vec.get(1).is_none());
}
#[test]
fn test_borrow_clone() {
let mut vec: VecCell<usize> = VecCell::new();
vec.push(1);
vec.push(2);
let x = vec.get(0);
assert_eq!(vec.borrows(), 1);
assert_eq!(vec.borrows(), 1);
assert_eq!(vec.mut_borrow(), None);
let y = x.clone();
assert_eq!(vec.borrows(), 2);
assert_eq!(vec.borrows(), 2);
assert_eq!(vec.mut_borrow(), None);
assert_eq!(x, y);
std::mem::drop(x);
assert_eq!(vec.borrows(), 1);
std::mem::drop(y);
assert_eq!(vec.borrows(), 0);
let x = vec.get(0);
assert_eq!(vec.borrows(), 1);
let y = vec.get(0);
assert_eq!(vec.borrows(), 2);
let z = x.clone();
assert_eq!(vec.borrows(), 3);
std::mem::drop(z);
assert_eq!(vec.borrows(), 2);
std::mem::drop(y);
assert_eq!(vec.borrows(), 1);
std::mem::drop(x);
assert_eq!(vec.borrows(), 0);
}
#[test]
fn test_borrow_mut() {
let mut vec: VecCell<usize> = VecCell::new();
vec.push(1);
vec.push(2);
let x = vec.get(0);
assert!(x.is_some());
let y = vec.borrow_mut(0);
assert!(y.is_none());
let y = vec.borrow_mut(1);
assert!(y.is_none());
std::mem::drop(x);
let y = vec.borrow_mut(0);
assert!(y.is_some());
let z = vec.borrow_mut(1);
assert!(z.is_none());
std::mem::drop(y);
}
#[test]
fn test_iter() {
let mut vec: Vec<usize> = Vec::new();
let mut vec2: VecCell<usize> = VecCell::new();
for x in 0..10 {
vec.push(x);
vec2.push(x);
}
let vec3 = vec2.iter().map(|x| *x).collect::<Vec<_>>();
assert_eq!(vec, vec3);
}
#[test]
#[should_panic]
fn test_iter_panic() {
let mut vec: VecCell<usize> = VecCell::new();
for x in 0..10 {
vec.push(x);
}
let y = vec.borrow_mut(3);
for _x in vec.iter() {
// noop
}
std::mem::drop(y);
}

@ -0,0 +1,134 @@
use super::*;
/// Wraps a borrowed reference from a [`VecCell`].
pub struct VecRef<'a, T: ?Sized> {
borrows: &'a Cell<usize>,
value: &'a T,
}
impl<'a, T: ?Sized> VecRef<'a, T> {
pub(crate) fn new(vec: &'a VecCell<T>, index: usize) -> Option<Self>
where
T: Sized
{
if vec.mut_borrow.get() == Some(index) {
return None
}
if index >= vec.len() {
return None
}
vec.borrows.set(vec.borrows.get().checked_add(1)?);
Some(Self {
borrows: &vec.borrows,
value: unsafe {
// SAFETY: there are no mutable borrows of vec.inner[index]
vec.get_unchecked(index)
}
})
}
fn from(value: &'a T, borrows: &'a Cell<usize>) -> Option<Self> {
borrows.set(borrows.get().checked_add(1)?);
Some(Self {
borrows,
value
})
}
/// Returns a reference to the borrowed value.
/// The reference may not outlive this `VecRef` instance.
///
/// # Example
///
/// ```
/// # use veccell::*;
/// let mut vec: VecCell<String> = VecCell::new();
///
/// vec.push(String::from("hello"));
/// vec.push(String::from("world"));
///
/// let guard = vec.get(0).unwrap();
/// assert_eq!(guard.get(), "hello");
/// ```
pub fn get(&self) -> &T {
&*self.value
}
/// Transforms a `VecRef<'_, T>` into a `VecRef<'_, U>` from a function that maps `&T` to `&U`.
///
/// This function does not use `self` and must be called explicitly via `VecRef::map(value, function)`.
///
/// # Examples
///
/// This function comes in hand when you need to return a reference to a value in a [`VecCell`] from within a function/scope.
/// For instance, the following is disallowed:
///
/// ```compile_fail
/// # use veccell::*;
/// fn return_favorite_value<'a>(array: &'a VecCell<Vec<u8>>) -> &'a u8 {
/// &array.get(42).unwrap().get()[7]
/// }
/// ```
///
/// Instead, you would write it as follows:
///
/// ```
/// # use veccell::*;
/// fn return_favorite_value<'a>(array: &'a VecCell<Vec<u8>>) -> VecRef<'a, u8> {
/// VecRef::map(array.get(42).unwrap(), |vec| &vec[7])
/// }
/// ```
pub fn map<'b, U: ?Sized, F>(original: VecRef<'b, T>, f: F) -> VecRef<'b, U>
where
F: FnOnce(&T) -> &U
{
VecRef::from(f(original.value), original.borrows).expect("Error creating a new VecRef: integer overflow")
// original is dropped here
}
}
impl<'a, T: ?Sized> Deref for VecRef<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.value
}
}
impl<'a, T: ?Sized> Drop for VecRef<'a, T> {
#[inline]
fn drop(&mut self) {
debug_assert!(self.borrows.get() > 0, "Borrow count was null yet there was still a borrow!");
self.borrows.set(self.borrows.get() - 1);
}
}
impl<'a, T: Debug + Sized> Debug for VecRef<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VecRef")
.field(self.value)
.finish()
}
}
impl<'a, T: PartialEq + ?Sized> PartialEq for VecRef<'a, T> {
fn eq(&self, other: &Self) -> bool {
self.get() == other.get()
}
}
impl<'a, T: PartialEq + ?Sized> PartialEq<T> for VecRef<'a, T> {
fn eq(&self, other: &T) -> bool {
self.get() == other
}
}
impl<'a, T: ?Sized> Clone for VecRef<'a, T> {
fn clone(&self) -> Self {
Self::from(self.value, self.borrows).expect("Error creating a new VecRef: integer overflow")
}
}

@ -0,0 +1,150 @@
use super::*;
// Lets us safely destructure VecRefMut while implementing the Drop logic
struct VecRefMutBorrow<'a>(&'a Cell<Option<usize>>);
/// Wraps a mutably borrowed value from a [`VecCell`].
pub struct VecRefMut<'a, T: ?Sized> {
mut_borrow: VecRefMutBorrow<'a>,
value: &'a mut T,
}
impl<'a, T: ?Sized> VecRefMut<'a, T> {
/// # Safety
///
/// If this function returns Some(ref), then there are no mutable borrows of ∀x, vec.inner[x]:
/// by contradiction, let `B: 'b` be a mutable borrow of lifetime `'b`. By conjunction on (IV):
/// - either `B` had exclusive access, in which case calling `VecCell::borrow_mut` is UB
/// - either `B` was obtained from a guard `VecRefMut<'c>`, in which case `'c: 'b` and `vec.mut_borrow.is_some()`, which contradicts our assertion
///
/// - The invariant (I) is upheld by the first assertion.
/// - The invariant (II) is upheld by this function, as it sets `vec.mut_borrow` to `Some(index)`.
pub(crate) fn new(vec: &'a VecCell<T>, index: usize) -> Option<Self>
where
T: Sized
{
if vec.borrows.get() > 0 || vec.mut_borrow.get().is_some() {
return None
}
if index >= vec.len() {
return None
}
vec.mut_borrow.set(Some(index));
Some(Self {
mut_borrow: VecRefMutBorrow(&vec.mut_borrow),
value: unsafe {
vec.get_mut_unchecked(index)
}
})
}
/// Returns an immutable reference to the borrowed value.
/// The reference may not outlive this `VecRefMut` instance.
///
/// # Example
///
/// ```
/// # use veccell::*;
/// let mut vec: VecCell<String> = VecCell::new();
///
/// vec.push(String::from("hello"));
/// vec.push(String::from("world"));
///
/// let guard = vec.borrow_mut(0).unwrap();
/// assert_eq!(guard.get(), "hello");
/// ```
pub fn get(&self) -> &T {
&*self.value
}
/// Returns a mutable reference to the borrowed value.
/// The reference may not outlive this `VecRefMut` instance.
///
/// # Example
///
/// ```
/// # use veccell::*;
/// let mut vec: VecCell<String> = VecCell::new();
///
/// vec.push(String::from("hello"));
/// vec.push(String::from("world"));
///
/// let mut guard = vec.borrow_mut(0).unwrap();
/// let hello = std::mem::replace(guard.get_mut(), String::from("potato"));
/// assert_eq!(guard.get(), "potato");
/// assert_eq!(hello, "hello");
/// ```
pub fn get_mut(&mut self) -> &mut T {
&mut *self.value
}
/// Transforms a `VecRefMut<'_, T>` into a `VecRefMut<'_, U>` from a function that maps `&mut T` to `&mut U`.
///
/// This function does not use `self` and must be called explicitly via `VecRefMut::map(value, function)`.
///
/// # Examples
///
/// ```
/// # use veccell::*;
/// fn return_favorite_value_mut<'a>(array: &'a VecCell<Vec<u8>>) -> VecRefMut<'a, u8> {
/// VecRefMut::map(array.borrow_mut(42).unwrap(), |vec| &mut vec[7])
/// }
/// ```
pub fn map<'b, U: ?Sized, F>(original: VecRefMut<'b, T>, f: F) -> VecRefMut<'b, U>
where
F: FnOnce(&mut T) -> &mut U
{
let VecRefMut { value, mut_borrow } = original;
VecRefMut {
value: f(value),
mut_borrow
}
}
}
impl<'a, T: ?Sized> Deref for VecRefMut<'a, T> {
type Target = T;
// SAFETY: Upholds invariant (IV)
fn deref(&self) -> &Self::Target {
self.value
}
}
impl<'a, T: ?Sized> DerefMut for VecRefMut<'a, T> {
// SAFETY: Upholds invariant (IV)
fn deref_mut(&mut self) -> &mut Self::Target {
self.value
}
}
impl<'a> Drop for VecRefMutBorrow<'a> {
#[inline]
fn drop(&mut self) {
debug_assert!(self.0.get().is_some());
self.0.set(None);
}
}
impl<'a, T: Debug + Sized> Debug for VecRefMut<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VecRefMut")
.field(self.value)
.finish()
}
}
impl<'a, T: PartialEq + ?Sized> PartialEq for VecRefMut<'a, T> {
fn eq(&self, other: &Self) -> bool {
self.get() == other.get()
}
}
impl<'a, T: PartialEq + ?Sized> PartialEq<T> for VecRefMut<'a, T> {
fn eq(&self, other: &T) -> bool {
self.get() == other
}
}
Loading…
Cancel
Save