From 2766e870c0b6a858f61b4c8d97a8d0ee163a12ed Mon Sep 17 00:00:00 2001 From: Adrien Burgun Date: Sun, 10 Jul 2022 22:40:18 +0200 Subject: [PATCH] :sparkles: Stabilize VecRef<[T]>::borrow, impl Display --- Cargo.toml | 2 +- README.md | 4 +-- src/lib.rs | 2 +- src/vecref.rs | 87 +++++++++++++++++++++++++++++++++++------------- src/vecrefmut.rs | 32 +++++------------- 5 files changed, 76 insertions(+), 51 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ea7f3e7..5cdde88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "veccell" -version = "0.2.1" +version = "0.3.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 fee2c6c..2c7b7f3 100644 --- a/README.md +++ b/README.md @@ -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 -println!("{}", &*third); // Prints 64 +println!("{}", third); // Prints 64 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: diff --git a/src/lib.rs b/src/lib.rs index 67d6143..757304b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ //! - You need to share the array across multiple threads *(you may use `Vec>` or `Arc>>` instead)* use std::cell::{Cell, UnsafeCell}; -use std::fmt::{self, Debug}; +use std::fmt::{self, Debug, Display}; use std::ops::{Deref, DerefMut}; mod vecref; diff --git a/src/vecref.rs b/src/vecref.rs index 10f0213..2106de1 100644 --- a/src/vecref.rs +++ b/src/vecref.rs @@ -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. /// 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 = VecCell::new(); +/// vec.push(2); +/// vec.push(15); +/// +/// let vec_ref: VecRef = vec.borrow(0).unwrap(); +/// +/// let value: usize = *vec_ref; // equivalent to `vec_ref.deref()` +/// +/// assert_eq!(value, 2); +/// ``` #[derive(Clone)] pub struct VecRef<'a, T: ?Sized> { 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 = 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`. /// /// 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. /// - /// `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)`. + /// + /// # Example + /// + /// ``` + /// # use veccell::*; + /// let vec: VecCell> = VecCell::from(vec![Some(3), None]); + /// + /// let ref_number: VecRef> = 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::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, E> where F: FnOnce(&T) -> Result<&U, E> @@ -171,6 +184,23 @@ 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 `None` if `index` is out of bounds. + /// + /// This method is only available for `VecRef<[T]>`. + /// + /// # Example + /// + /// ``` + /// # use veccell::*; + /// let mut vec: VecCell = 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> { 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> { 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 { 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 { f.debug_tuple("VecRef") - .field(self.value) + .field(&self.value) .finish() } } +impl<'a, T: Display + ?Sized> Display for VecRef<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ::fmt(&self.value, f) + } +} + impl<'a, T: PartialEq + ?Sized> PartialEq for VecRef<'a, T> { fn eq(&self, other: &Self) -> bool { self.value == other.value diff --git a/src/vecrefmut.rs b/src/vecrefmut.rs index 7c41795..0460ed5 100644 --- a/src/vecrefmut.rs +++ b/src/vecrefmut.rs @@ -60,27 +60,6 @@ impl<'a, T: ?Sized> VecRefMut<'a, 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 = 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)`. @@ -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 { f.debug_tuple("VecRefMut") - .field(self.value) + .field(&self.value) .finish() } } +impl<'a, T: Display + ?Sized> Display for VecRefMut<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ::fmt(&self.value, f) + } +} + impl<'a, T: PartialEq + ?Sized> PartialEq for VecRefMut<'a, T> { fn eq(&self, other: &Self) -> bool { self.get() == other.get()