Stabilize VecRef<[T]>::borrow, impl Display

pull/1/head
Shad Amethyst 2 years ago
parent 11aeeaae50
commit 2766e870c0
Signed by: amethyst
GPG Key ID: D970C8DD1D6DEE36

@ -1,6 +1,6 @@
[package] [package]
name = "veccell" name = "veccell"
version = "0.2.1" version = "0.3.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."

@ -43,10 +43,10 @@ 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); // Prints 64 println!("{}", third); // Prints 64
std::mem::drop(third); // Drop the mutable borrow std::mem::drop(third); // Drop the mutable borrow
println!("{}", *arr.borrow(2).unwrap()); // Also prints 64 println!("{}", arr.borrow(2).unwrap()); // 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:

@ -16,7 +16,7 @@
//! - You need to share the array across multiple threads *(you may use `Vec<Mutex<T>>` or `Arc<Vec<Mutex<T>>>` instead)* //! - You need to share the array across multiple threads *(you may use `Vec<Mutex<T>>` or `Arc<Vec<Mutex<T>>>` instead)*
use std::cell::{Cell, UnsafeCell}; use std::cell::{Cell, UnsafeCell};
use std::fmt::{self, Debug}; use std::fmt::{self, Debug, Display};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
mod vecref; mod vecref;

@ -7,6 +7,21 @@ use std::ops::RangeBounds;
/// ///
/// When an instance of `VecRef` is created, the immutable borrow counter of its parent [`VecCell`] is incremented. /// When an instance of `VecRef` is created, the immutable borrow counter of its parent [`VecCell`] is incremented.
/// Once that instance is [`Drop`ped](Drop), the immutable borrow counter is decremented. /// Once that instance is [`Drop`ped](Drop), the immutable borrow counter is decremented.
///
/// This type implements [`Deref`], and this is the main way to access the contained value:
///
/// ```
/// # use veccell::*;
/// let mut vec: VecCell<usize> = VecCell::new();
/// vec.push(2);
/// vec.push(15);
///
/// let vec_ref: VecRef<usize> = vec.borrow(0).unwrap();
///
/// let value: usize = *vec_ref; // equivalent to `vec_ref.deref()`
///
/// assert_eq!(value, 2);
/// ```
#[derive(Clone)] #[derive(Clone)]
pub struct VecRef<'a, T: ?Sized> { pub struct VecRef<'a, T: ?Sized> {
borrows: VecRefBorrow<'a>, borrows: VecRefBorrow<'a>,
@ -103,27 +118,6 @@ 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
// ///
// /// ```
// /// # use veccell::*;
// /// let mut vec: VecCell<String> = VecCell::new();
// ///
// /// vec.push(String::from("hello"));
// /// vec.push(String::from("world"));
// ///
// /// let guard = vec.borrow(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`. /// 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)`. /// This function does not use `self` and must be called explicitly via `VecRef::map(value, function)`.
@ -158,8 +152,27 @@ impl<'a, T: ?Sized> VecRef<'a, T> {
/// Variant of [`VecRef::map`], where the callback (`f`) may fail. /// Variant of [`VecRef::map`], where the callback (`f`) may fail.
/// ///
/// `f` must return a `Result`; if it returns `Ok(x)`, then `try_map` returns `Ok(VecRef(x))`. /// `f` must return a [`Result`]; if it returns `Ok(x)`, then `try_map` returns `Ok(VecRef(x))`.
/// Otherwise, it returns `Err(err)`. /// Otherwise, it returns `Err(err)`.
///
/// # Example
///
/// ```
/// # use veccell::*;
/// let vec: VecCell<Option<usize>> = VecCell::from(vec![Some(3), None]);
///
/// let ref_number: VecRef<Option<usize>> = vec.borrow(0).unwrap();
/// // Note: VecRef::try_map uses `Result`s, but we need `Option`s, so we convert to and from them
/// let ref_number: Option<VecRef<usize>> = VecRef::try_map(
/// ref_number,
/// |option| option.as_ref().ok_or(())
/// ).ok();
/// assert!(ref_number.is_some());
///
/// let ref_none = vec.borrow(1).unwrap();
/// let ref_none = VecRef::try_map(ref_none, |option| option.as_ref().ok_or(())).ok();
/// assert!(ref_none.is_none());
/// ```
pub fn try_map<'b, U: ?Sized, F, E>(original: VecRef<'b, T>, f: F) -> Result<VecRef<'b, U>, E> pub fn try_map<'b, U: ?Sized, F, E>(original: VecRef<'b, T>, f: F) -> Result<VecRef<'b, U>, E>
where where
F: FnOnce(&T) -> Result<&U, E> F: FnOnce(&T) -> Result<&U, E>
@ -171,6 +184,23 @@ impl<'a, T: ?Sized> VecRef<'a, T> {
impl<'a, T: Sized> VecRef<'a, [T]> { impl<'a, T: Sized> VecRef<'a, [T]> {
/// Returns an immutable borrow to the `index`-th element of the array. /// Returns an immutable borrow to the `index`-th element of the array.
/// Returns `None` if `index` is out of bounds. /// Returns `None` if `index` is out of bounds.
///
/// This method is only available for `VecRef<[T]>`.
///
/// # Example
///
/// ```
/// # use veccell::*;
/// let mut vec: VecCell<usize> = VecCell::with_capacity(10);
/// for x in 0..10 {
/// vec.push(x);
/// }
///
/// let range = vec.borrow_range(2..5).unwrap();
/// assert_eq!(range.len(), 3);
/// let elem = range.borrow(2).unwrap(); // Corresponds to element 4 of `vec`
/// assert_eq!(elem, 4);
/// ```
pub fn borrow(&self, index: usize) -> Option<VecRef<'a, T>> { pub fn borrow(&self, index: usize) -> Option<VecRef<'a, T>> {
Some(VecRef::from(self.value.get(index)?, self.borrows.clone())) Some(VecRef::from(self.value.get(index)?, self.borrows.clone()))
} }
@ -179,19 +209,28 @@ impl<'a, T: Sized> VecRef<'a, [T]> {
impl<'a, T: ?Sized> Deref for VecRef<'a, T> { impl<'a, T: ?Sized> Deref for VecRef<'a, T> {
type Target = T; type Target = T;
/// Dereferences the [`VecRef`], returning a reference to the borrowed value.
///
/// This cannot fail, as the borrowed value is already immutably borrowed.
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
self.value self.value
} }
} }
impl<'a, T: Debug + Sized> Debug for VecRef<'a, T> { impl<'a, T: Debug + ?Sized> Debug for VecRef<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VecRef") f.debug_tuple("VecRef")
.field(self.value) .field(&self.value)
.finish() .finish()
} }
} }
impl<'a, T: Display + ?Sized> Display for VecRef<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<T as Display>::fmt(&self.value, f)
}
}
impl<'a, T: PartialEq + ?Sized> PartialEq for VecRef<'a, T> { impl<'a, T: PartialEq + ?Sized> PartialEq for VecRef<'a, T> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.value == other.value self.value == other.value

@ -60,27 +60,6 @@ impl<'a, T: ?Sized> VecRefMut<'a, T> {
&*self.value &*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`. /// 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)`. /// This function does not use `self` and must be called explicitly via `VecRefMut::map(value, function)`.
@ -144,14 +123,21 @@ impl<'a> Drop for VecRefMutBorrow<'a> {
} }
} }
impl<'a, T: Debug + Sized> Debug for VecRefMut<'a, T> {
impl<'a, T: Debug + ?Sized> Debug for VecRefMut<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VecRefMut") f.debug_tuple("VecRefMut")
.field(self.value) .field(&self.value)
.finish() .finish()
} }
} }
impl<'a, T: Display + ?Sized> Display for VecRefMut<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<T as Display>::fmt(&self.value, f)
}
}
impl<'a, T: PartialEq + ?Sized> PartialEq for VecRefMut<'a, T> { impl<'a, T: PartialEq + ?Sized> PartialEq for VecRefMut<'a, T> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.get() == other.get() self.get() == other.get()

Loading…
Cancel
Save