@ -1,9 +1,68 @@
//! # `VecCell`, a variant of `Vec` with interior mutability
//!
//! This crate contains the [`VecCell<T>`](VecCell) type, which implements a contiguous,
//! growable array (similar to [`Vec<T>`](Vec)) with interior mutability (similar to [`RefCell<T>`](std::cell::RefCell)).
//!
//! You would use this crate if:
//! - You need a `Vec` with [interior mutability](std::cell#when-to-choose-interior-mutability)
//! - You only want mutable access to one element at a time
//! - You need a constant memory cost
//!
//! You wouldn't need this crate if:
//! - You don't need interior mutability (use `Vec<T>`)
//! - You want mutable access to multiple elements at a time (use `Vec<RefCell<T>>`)
//! - You need to share the array across multiple threads (use `Vec<Mutex<T>>` or `Arc<Vec<Mutex<T>>>`)
#![ feature(type_alias_impl_trait) ]
#![ feature(type_alias_impl_trait) ]
use std ::cell ::{ Cell , UnsafeCell } ;
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 } ;
/// 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`.
/// 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 [`VecCell::get`].
/// - To borrow an item mutably, use [`VecCell::borrow_mut`].
/// - If you have a mutable reference to the `VecCell`, then you may also use [`VecCell::get_mut`].
/// - You may access the internal `Vec<UnsafeCell<T>>` using [`VecCell::inner`] and [`VecCell::inner_mut`].
///
/// This type is essentially a more restricted version of `Vec<RefCell<T>>`,
/// with the benefit of having a lower memory footprint since we only need
/// `sizeof!(usize)+sizeof!(Option<usize>)` bytes instead of `N*sizeof!(usize)` bytes of memory to prevent aliasing.
///
/// # Examples
///
/// ```
/// use veccell::VecCell;
///
/// fn update(current: &mut usize, prev: &usize) {
/// *current += *prev;
/// }
///
/// // Create an empty vec
/// let mut vec: VecCell<usize> = VecCell::new();
///
/// // Add the numbers from 0 to 9 in vec
/// for n in 0..10 {
/// vec.push(n);
/// }
///
/// for index in 1..10 {
/// // 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();
///
/// // Give both references to update
/// update(current.get_mut(), prev.get());
/// }
///
/// assert_eq!(vec, vec![0, 1, 3, 6, 10, 15, 21, 28, 36, 45]);
/// ```
///
///
/// # Safety
/// # Safety
///
///
@ -15,7 +74,6 @@ use std::ops::{Deref, DerefMut};
/// - (IV) a mutable reference may only be created if:
/// - (IV) a mutable reference may only be created if:
/// - (IV-a) exclusive access to the `VecCell` is guaranteed (`&mut VecCell`)
/// - (IV-a) exclusive access to the `VecCell` is guaranteed (`&mut VecCell`)
/// - (IV-b) it is created from a mutable guard, and the mutable guard's lifetime does not exceed that of the mutable guard
/// - (IV-b) it is created from a mutable guard, and the mutable guard's lifetime does not exceed that of the mutable guard
#[ derive(Debug) ]
pub struct VecCell < T > {
pub struct VecCell < T > {
mut_borrow : Cell < Option < usize > > ,
mut_borrow : Cell < Option < usize > > ,
borrows : Cell < usize > ,
borrows : Cell < usize > ,
@ -23,6 +81,7 @@ pub struct VecCell<T> {
}
}
impl < T > VecCell < T > {
impl < T > VecCell < T > {
/// Creates a new `VecCell`.
pub fn new ( ) -> Self {
pub fn new ( ) -> Self {
Self {
Self {
mut_borrow : Cell ::new ( None ) ,
mut_borrow : Cell ::new ( None ) ,
@ -31,6 +90,7 @@ impl<T> VecCell<T> {
}
}
}
}
/// Creates a new `VecCell` with `capacity` as capacity.
pub fn with_capacity ( capacity : usize ) -> Self {
pub fn with_capacity ( capacity : usize ) -> Self {
Self {
Self {
mut_borrow : Cell ::new ( None ) ,
mut_borrow : Cell ::new ( None ) ,
@ -39,57 +99,109 @@ impl<T> VecCell<T> {
}
}
}
}
/// Returns the raw parts of a `VecCell` in the format `(inner_vec, mut_borrow, borrows)`.
/// If no reference was [forgotten](std::mem::forget), then `mut_borrow == None` and `borrows == 0`.
pub fn into_raw_parts ( self ) -> ( Vec < UnsafeCell < T > > , Option < usize > , usize ) {
pub fn into_raw_parts ( self ) -> ( Vec < UnsafeCell < T > > , Option < usize > , usize ) {
( self . inner , self . mut_borrow . into_inner ( ) , self . borrows . into_inner ( ) )
( self . inner , self . mut_borrow . into_inner ( ) , self . borrows . into_inner ( ) )
}
}
pub unsafe fn from_raw_parts ( inner : Vec < UnsafeCell < T > > , mut_borrow : Option < usize > , borrows : usize ) -> Self {
/// Returns the length of the `VecCell`, ie. the number of elements in the array.
Self {
///
inner ,
/// See [`Vec::len()`] for more information.
borrows : Cell ::new ( borrows ) ,
mut_borrow : Cell ::new ( mut_borrow ) ,
}
}
#[ inline ]
#[ inline ]
pub fn len ( & self ) -> usize {
pub fn len ( & self ) -> usize {
self . inner . len ( )
self . inner . len ( )
}
}
/// Returns the capacity of the `VecCell`, ie. the number of elements that can be added before we need to realloc.
/// The following holds true at any time: `vec.len() <= vec.capacity()`.
///
/// See [`Vec::capacity()`] for more information.
#[ inline ]
#[ inline ]
pub fn capacity ( & self ) -> usize {
pub fn capacity ( & self ) -> usize {
self . inner . capacity ( )
self . inner . capacity ( )
}
}
/// Reserves space in the buffer for at least `additional` more elements.
///
/// See [`Vec::reserve()`] for more information.
#[ inline ]
#[ inline ]
pub fn reserve ( & mut self , additional : usize ) {
pub fn reserve ( & mut self , additional : usize ) {
self . inner . reserve ( additional ) ;
self . inner . reserve ( additional ) ;
}
}
/// Removes the element at index `index`, shifting the elements after it and returning that index.
///
/// See [`Vec::remove()`] for more information.
///
/// # Panics
///
/// Panics if `index >= self.len()`.
#[ inline ]
#[ inline ]
pub fn remove ( & mut self , index : usize ) -> T {
pub fn remove ( & mut self , index : usize ) -> T {
self . inner . remove ( index ) . into_inner ( )
self . inner . remove ( index ) . into_inner ( )
}
}
/// Removes the element at index `index`, replacing it with the last element.
///
/// See [`Vec::swap_remove()`] for more information.
///
/// # Panics
///
/// Panics if `index >= self.len()`.
#[ inline ]
#[ inline ]
pub fn swap_remove ( & mut self , index : usize ) -> T {
pub fn swap_remove ( & mut self , index : usize ) -> T {
self . inner . swap_remove ( index ) . into_inner ( )
self . inner . swap_remove ( index ) . into_inner ( )
}
}
#[ inline ]
/// Returns the number of immutable borrows to elements of the `VecCell`.
pub fn inner ( & self ) -> & Vec < UnsafeCell < T > > {
///
& self . inner
/// # Example
}
///
/// ```
#[ inline ]
/// # use veccell::*;
pub fn inner_mut ( & mut self ) -> & mut Vec < UnsafeCell < T > > {
/// let mut vec: VecCell<usize> = VecCell::new(0);
& mut self . inner
///
}
/// vec.push(2);
/// vec.push(5);
/// vec.push(9);
///
/// // There are no borrows at this point
/// assert_eq!(x.borrows(), 0);
///
/// let x = vec.get(1);
///
/// // There is exactly one borrow at this point
/// assert_eq!(x.borrows(), 1);
///
/// std::mem::drop(x); // x lives up to here
/// ```
pub fn borrows ( & self ) -> usize {
pub fn borrows ( & self ) -> usize {
self . borrows . get ( )
self . borrows . get ( )
}
}
/// Returns the index of the mutable borrows of the `VecCell`, if any.
///
/// # Example
///
/// ```
/// # use veccell::*;
/// let mut vec: VecCell<usize> = VecCell::new(0);
///
/// vec.push(2);
/// vec.push(5);
/// vec.push(9);
///
/// // There is no mutable borrow at this point
/// assert_eq!(x.mut_borrow(), None);
///
/// let x = vec.get_mut(2);
///
/// // There is a mutable borrow of element 2 at this point
/// assert_eq!(x.mut_borrow(), Some(2));
///
/// std::mem::drop(x); // x lives up to here
/// ```
pub fn mut_borrow ( & self ) -> Option < usize > {
pub fn mut_borrow ( & self ) -> Option < usize > {
self . mut_borrow . get ( )
self . mut_borrow . get ( )
}
}
@ -99,7 +211,6 @@ impl<T> VecCell<T> {
}
}
pub fn pop ( & mut self ) -> Option < T > {
pub fn pop ( & mut self ) -> Option < T > {
debug_assert! ( self . mut_borrow . get ( ) . is_none ( ) ) ;
self . inner . pop ( ) . map ( UnsafeCell ::into_inner )
self . inner . pop ( ) . map ( UnsafeCell ::into_inner )
}
}
@ -107,22 +218,16 @@ impl<T> VecCell<T> {
VecRef ::new ( self , index )
VecRef ::new ( self , index )
}
}
pub unsafe fn get_unchecked ( & self , index : usize ) -> & T {
& * self . inner . get_unchecked ( index ) . get ( )
}
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 )
}
}
// TODO: reborrow_mut?
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 )
}
}
pub unsafe fn get_mut_unchecked ( & self , index : usize ) -> & mut T {
& mut * self . inner . get_unchecked ( index ) . get ( )
}
pub fn iter < ' b > ( & ' b self ) -> impl Iterator < Item = VecRef < ' b , T > > {
pub fn iter < ' b > ( & ' b self ) -> impl Iterator < Item = VecRef < ' b , T > > {
self . into_iter ( )
self . into_iter ( )
}
}
@ -130,6 +235,84 @@ impl<T> VecCell<T> {
pub fn iter_mut < ' b > ( & ' b mut self ) -> impl Iterator < Item = & ' b mut T > {
pub fn iter_mut < ' b > ( & ' b mut self ) -> impl Iterator < Item = & ' b mut T > {
self . inner . iter_mut ( ) . map ( UnsafeCell ::get_mut )
self . inner . iter_mut ( ) . map ( UnsafeCell ::get_mut )
}
}
pub fn try_iter < ' b > ( & ' b self ) -> impl Iterator < Item = Option < VecRef < ' b , T > > > {
( 0 .. self . len ( ) ) . map ( | index | {
self . get ( index )
} )
}
/// Returns a reference to the inner buffer.
/// You may safely perform immutable operations on it.
#[ inline ]
pub fn inner ( & self ) -> & Vec < UnsafeCell < T > > {
& self . inner
}
/// Returns a mutable reference to the inner buffer.
/// You may safely perform mutable operations on it.
#[ inline ]
pub fn inner_mut ( & mut self ) -> & mut Vec < UnsafeCell < T > > {
& mut self . inner
}
// == Unsafe functions section ==
/// Alternative to `get`, which skips all checks and returns a mutable reference.
/// Neither the `mut_borrow`, nor the `borrows` buffer will be updated or read,
/// so make sure that no exclusive reference to the element at `index` is made.
///
/// If `index >= len`, then calling this function is undefined behavior.
pub unsafe fn get_unchecked ( & self , index : usize ) -> & T {
& * self . inner . get_unchecked ( index ) . get ( )
}
/// Alternative to `borrow_mut`, which skips all checks and returns a mutable reference.
/// Neither the `mut_borrow`, nor the `borrows` buffer will be updated or read,
/// so make sure that this is the only reference to the element at `index`.
///
/// If `index >= len`, then calling this function is undefined behavior.
pub unsafe fn get_mut_unchecked ( & self , index : usize ) -> & mut T {
& mut * self . inner . get_unchecked ( index ) . get ( )
}
/// Constructs a `VecCell` from its raw parts.
pub unsafe fn from_raw_parts ( inner : Vec < UnsafeCell < T > > , mut_borrow : Option < usize > , borrows : usize ) -> Self {
Self {
inner ,
borrows : Cell ::new ( borrows ) ,
mut_borrow : Cell ::new ( mut_borrow ) ,
}
}
}
impl < T : fmt ::Debug > fmt ::Debug for VecCell < T > {
fn fmt ( & self , f : & mut fmt ::Formatter < ' _ > ) -> fmt ::Result {
enum BorrowStatus < T > {
Ok ( T ) ,
Borrowed ,
}
impl < T : Debug > fmt ::Debug for BorrowStatus < VecRef < ' _ , T > > {
fn fmt ( & self , f : & mut fmt ::Formatter < ' _ > ) -> fmt ::Result {
match self {
BorrowStatus ::Ok ( x ) = > fmt ::Debug ::fmt ( x . get ( ) , f ) ,
BorrowStatus ::Borrowed = > write! ( f , "(borrowed)" ) ,
}
}
}
f . debug_struct ( "VecCell" )
. field ( "borrows" , & self . borrows . get ( ) )
. field ( "mut_borrow" , & self . mut_borrow . get ( ) )
. field ( "inner" , & self . try_iter ( ) . map ( | x | {
match x {
Some ( y ) = > BorrowStatus ::Ok ( y ) ,
None = > BorrowStatus ::Borrowed ,
}
} ) . collect ::< Box < [ _ ] > > ( ) )
. finish ( )
}
}
}
impl < ' a , T : ' a > IntoIterator for & ' a VecCell < T > {
impl < ' a , T : ' a > IntoIterator for & ' a VecCell < T > {
@ -141,7 +324,10 @@ impl<'a, T: 'a> IntoIterator for &'a VecCell<T> {
/// Panics if a value is currently mutably borrowed
/// Panics if a value is currently mutably borrowed
fn into_iter ( self ) -> Self ::IntoIter {
fn into_iter ( self ) -> Self ::IntoIter {
( 0 .. self . len ( ) ) . map ( | index | {
( 0 .. self . len ( ) ) . map ( | index | {
self . get ( index ) . expect ( "An element of VecCell is currently mutably borrowed" )
match self . get ( index ) {
Some ( x ) = > x ,
None = > panic! ( "Error while borrowing immutably element {} of VecCell: already mutably borrowed" , index ) ,
}
} )
} )
}
}
}
}
@ -219,6 +405,7 @@ impl<T> From<Vec<T>> for VecCell<T> {
}
}
}
}
/// Wraps a borrowed reference from a [`VecCell`].
pub struct VecRef < ' a , T : ? Sized > {
pub struct VecRef < ' a , T : ? Sized > {
borrows : & ' a Cell < usize > ,
borrows : & ' a Cell < usize > ,
value : & ' a T ,
value : & ' a T ,
@ -248,6 +435,15 @@ impl<'a, T: ?Sized> VecRef<'a, T> {
} )
} )
}
}
fn from ( value : & ' a T , borrows : & ' a Cell < usize > ) -> Option < Self > {
borrows . set ( borrows . get ( ) . checked_add ( 1 ) ? ) ;
Some ( Self {
borrows ,
value
} )
}
pub fn get ( & self ) -> & T {
pub fn get ( & self ) -> & T {
& * self . value
& * self . value
}
}
@ -256,10 +452,8 @@ impl<'a, T: ?Sized> VecRef<'a, T> {
where
where
F : FnOnce ( & T ) -> & U
F : FnOnce ( & T ) -> & U
{
{
VecRef {
VecRef ::from ( f ( original . value ) , original . borrows ) . expect ( "Error creating a new VecRef: integer overflow" )
value : f ( original . value ) ,
// original is dropped here
borrows : original . borrows
}
}
}
}
}
@ -299,6 +493,13 @@ impl<'a, T: PartialEq + ?Sized> PartialEq<T> for VecRef<'a, T> {
}
}
}
}
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" )
}
}
/// Wraps a mutably borrowed value from a [`VecCell`].
pub struct VecRefMut < ' a , T : ? Sized > {
pub struct VecRefMut < ' a , T : ? Sized > {
mut_borrow : & ' a Cell < Option < usize > > ,
mut_borrow : & ' a Cell < Option < usize > > ,
value : & ' a mut T ,
value : & ' a mut T ,
@ -517,4 +718,104 @@ mod test {
assert! ( vec . get ( 0 ) . is_some ( ) ) ;
assert! ( vec . get ( 0 ) . is_some ( ) ) ;
assert! ( vec . get ( 1 ) . is_none ( ) ) ;
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 ) ;
}
}
}