diff --git a/src/lib.rs b/src/lib.rs
index bf1a0a5..224a8e1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -17,7 +17,13 @@
#![doc = include_str!("../README.md")]
+// Uses unstable features for `docs.rs`.
+// This is okay, `docs.rs` uses a nightly compiler, and doesn't need to re-build documentation later.
+// To avoid broken `docs.rs` pages with new uploads, before publishing a new version to `crates.io`,
+// always check if `cargo docs-rs` (https://crates.io/crates/cargo-docs-rs) still works,
+// (with `rustup override set nightly` set locally to a current nightly).
#![cfg_attr(docsrs, feature(doc_cfg))]
+#![cfg_attr(docsrs, feature(clone_to_uninit))]
#![no_std]
@@ -38,16 +44,25 @@ pub mod features {
//! Enables usage of the `alloc` crate, and a public dependency on
//! [`stable_deref_trait`] at version `1.*`
//!
- #![cfg_attr(not(feature = "alloc"), doc = "Enables the `MutCursorVec` and `MutCursorRootedVec` APIs.")]
- #![cfg_attr(feature = "alloc", doc = "Enables the [`MutCursorVec`] and [`MutCursorRootedVec`] APIs.")]
+ #![cfg_attr(not(feature = "alloc"), doc = "Enables the `MutCursorVec` and `MutCursorRootedVec` APIs,")]
+ #![cfg_attr(not(feature = "alloc"), doc = "as well as the `unique` module.")]
+ #![cfg_attr(feature = "alloc", doc = "Enables the [`MutCursorVec`] and [`MutCursorRootedVec`] APIs,")]
+ # module.")]
//! ## `std`
//! Enables `std` support for [`StableDeref`], so you use std-only stable pointers
//! without needing to depend on [`stable_deref_trait`] yourself.
//!
+ //! Also extends our re-implementation of [`CloneToUninit`] (used for [`make_unique`] in the
+ //! `unique` module) to support `std`-only types (`OsStr`, `Path`).
+ //!
#![cfg_attr(feature = "alloc", doc = "[`stable_deref_trait`]: stable_deref_trait")]
#![cfg_attr(feature = "alloc", doc = "[`StableDeref`]: stable_deref_trait::StableDeref")]
+ #![cfg_attr(feature = "alloc", doc = "[`make_unique`]: crate::unique::UniqueExt::make_unique")]
+ #![cfg_attr(docsrs, doc = "[`CloneToUninit`]: std::clone::CloneToUninit")]
//! [`stable_deref_trait`]: https://docs.rs/stable_deref_trait/1/stable_deref_trait/
//! [`StableDeref`]: https://docs.rs/stable_deref_trait/1/stable_deref_trait/trait.StableDeref.html
+ //! [`make_unique`]: #alloc
+ //! [`CloneToUninit`]: https://doc.rust-lang.org/nightly/std/clone/trait.CloneToUninit.html
use super::*;
}
@@ -61,6 +76,11 @@ mod mut_cursor_vec;
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub use mut_cursor_vec::*;
+
+#[cfg(feature = "alloc")]
+#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
+pub mod unique;
+
#[cfg(feature = "alloc")]
mod rooted_vec;
#[cfg(feature = "alloc")]
diff --git a/src/unique.rs b/src/unique.rs
new file mode 100644
index 0000000..393ee04
--- /dev/null
+++ b/src/unique.rs
@@ -0,0 +1,192 @@
+//! Tools for using [`Rc`] and [`Arc`] to prove a stably-dereferencing level
+//! of indirection in [`MutCursorRootedVec`](super::MutCursorRootedVec)'s API.
+//!
+//! While `Rc` and `Arc` are generally only offering *shared, immutable* access
+//! to their interior, while [`MutCursorRootedVec`](super::MutCursorRootedVec) works
+//! with *mutable* access, the standard library *does* offer a limited mutable-access
+//! API in the form of the {[Arc](Arc::get_mut), [Rc](Rc::get_mut)}::get_mut
+//! and {[Arc](Arc::make_mut), [Rc](Rc::make_mut)}::make_mut
methods.
+//!
+//! These methods succeed when the reference-counted pointer is *unique*; in this
+//! module, we provide an API to encode this uniqueness property into a separate type
+//! which can fit the [DerefMut] + [StableDeref]
+//! interface.
+
+mod polyfill {
+ use core::ffi::CStr;
+
+ #[cfg(feature = "std")]
+ use std::{ffi::OsStr, path::Path};
+
+ use alloc::{rc::Rc, sync::Arc};
+ /// Polyfill for unstable `CloneToUninit` in `std`.
+ ///
+ /// # SAFETY
+ /// the `_make_mut` implementation must ensure uniqueness;
+ /// after the method call without panicking, mutable access through`::as_ptr()`
+ /// must be sound, as long as the Rc/Arc is not cloned or otherwise shared.
+ pub unsafe trait CloneToUninit {
+ fn rc_make_mut(rc: &mut Rc);
+ fn arc_make_mut(rc: &mut Arc);
+ }
+
+ macro_rules! impl_ {
+ ($($({$($t:tt)*})? $Self:ty)*) => {$(
+ unsafe impl$(<$($t)*>)? CloneToUninit for $Self {
+ fn rc_make_mut(rc: &mut Rc) {
+ Rc::make_mut(rc);
+ }
+ fn arc_make_mut(rc: &mut Arc) {
+ Arc::make_mut(rc);
+ }
+ }
+ )*};
+ }
+ impl_! {
+ str CStr
+ {T: Clone} [T]
+ {T: Clone} T
+ }
+ #[cfg(feature = "std")]
+ impl_! {
+ OsStr Path
+ }
+}
+#[cfg(docsrs)]
+use core::clone::CloneToUninit;
+// Use the *real* `CloneToUninit` for `docs.rs`, to make the `T: CloneToUninit` bounds below
+// easier to understand for users (because this way the link becomes clickable).
+#[cfg(not(docsrs))]
+use polyfill::CloneToUninit;
+
+use alloc::{rc::Rc, sync::Arc};
+use stable_deref_trait::StableDeref;
+use core::{
+ ops::{Deref, DerefMut},
+ panic::{RefUnwindSafe, UnwindSafe},
+};
+
+/// Extension trait for creating [`UniqueRc`]/[`UniqueArc`]
+///
+/// Take a look at the implementations below, to see the concrete type signatures
+/// of these methods [for `Rc`](#impl-UniqueExt-for-Rc) and [for `Arc`](#impl-UniqueExt-for-Arc), respectively.
+pub trait UniqueExt: Deref {
+ type Unique;
+ /// This function behaves like [`Rc::get_mut`]/[`Arc::get_mut`], but returns
+ /// a reference that keeps the double-indirection necessary
+ /// for use with [`MutCursorRootedVec`](super::MutCursorRootedVec).
+ fn get_unique(this: &mut Self) -> Option<&mut Self::Unique>;
+ /// This function behaves like [`Rc::make_mut`]/[`Arc::make_mut`], but returns
+ /// a reference that keeps the double-indirection necessary
+ /// for use with [`MutCursorRootedVec`](super::MutCursorRootedVec).
+ fn make_unique(this: &mut Self) -> &mut Self::Unique
+ where
+ Self::Target: CloneToUninit;
+}
+
+impl UniqueExt for Rc {
+ type Unique = UniqueRc;
+
+ /// This function behaves like [`Rc::get_mut`], but returns
+ /// a reference that keeps the double-indirection necessary
+ /// for use with [`MutCursorRootedVec`](super::MutCursorRootedVec).
+ fn get_unique(this: &mut Self) -> Option<&mut UniqueRc> {
+ Rc::get_mut(this)
+ .is_some()
+ .then(|| unsafe { &mut *(this as *mut Rc as *mut UniqueRc) })
+ }
+
+ /// This function behaves like [`Rc::make_mut`], but returns
+ /// a reference that keeps the double-indirection necessary
+ /// for use with [`MutCursorRootedVec`](super::MutCursorRootedVec).
+ fn make_unique(this: &mut Self) -> &mut UniqueRc
+ where
+ T: CloneToUninit,
+ {
+ #[cfg(not(docsrs))]
+ T::rc_make_mut(this);
+ #[cfg(docsrs)]
+ Rc::make_mut(this);
+ unsafe { &mut *(this as *mut Rc as *mut UniqueRc) }
+ }
+}
+
+impl UniqueExt for Arc {
+ type Unique = UniqueArc;
+
+ /// This function behaves like [`Arc::get_mut`], but returns
+ /// a reference that keeps the double-indirection necessary
+ /// for use with [`MutCursorRootedVec`](super::MutCursorRootedVec).
+ fn get_unique(this: &mut Self) -> Option<&mut UniqueArc> {
+ Arc::get_mut(this)
+ .is_some()
+ .then(|| unsafe { &mut *(this as *mut Arc as *mut UniqueArc) })
+ }
+
+ /// This function behaves like [`Arc::make_mut`], but returns
+ /// a reference that keeps the double-indirection necessary
+ /// for use with [`MutCursorRootedVec`](super::MutCursorRootedVec).
+ fn make_unique(this: &mut Self) -> &mut UniqueArc
+ where
+ T: CloneToUninit,
+ {
+ #[cfg(not(docsrs))]
+ T::arc_make_mut(this);
+ #[cfg(docsrs)]
+ Arc::make_mut(this);
+ unsafe { &mut *(this as *mut Arc as *mut UniqueArc) }
+ }
+}
+
+#[repr(transparent)]
+pub struct UniqueRc(Rc);
+
+#[repr(transparent)]
+pub struct UniqueArc(Arc);
+
+// adjust trait impls to match uniquely owned reference (compare e.g. `Box`)
+
+impl UnwindSafe for UniqueRc where T: UnwindSafe {}
+impl RefUnwindSafe for UniqueRc where T: RefUnwindSafe {}
+
+impl UnwindSafe for UniqueArc where T: UnwindSafe {}
+impl RefUnwindSafe for UniqueArc where T: RefUnwindSafe {}
+
+// yes, uniquely-owned Rc is completely thread-safe, too
+unsafe impl Send for UniqueRc where T: Send {}
+unsafe impl Sync for UniqueRc where T: Sync {}
+
+unsafe impl Send for UniqueArc where T: Send {}
+unsafe impl Sync for UniqueArc where T: Sync {}
+
+impl Deref for UniqueRc {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe { &*Rc::as_ptr(&self.0) }
+ }
+}
+
+impl DerefMut for UniqueRc {
+ fn deref_mut(&mut self) -> &mut T {
+ unsafe { &mut *(Rc::as_ptr(&self.0) as *mut T) }
+ }
+}
+
+unsafe impl StableDeref for UniqueRc {}
+
+impl Deref for UniqueArc {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe { &*Arc::as_ptr(&self.0) }
+ }
+}
+
+impl DerefMut for UniqueArc {
+ fn deref_mut(&mut self) -> &mut T {
+ unsafe { &mut *(Arc::as_ptr(&self.0) as *mut T) }
+ }
+}
+
+unsafe impl StableDeref for UniqueArc {}