smart_pointer/
lib.rs

1//! Traits for smart pointer functionality.
2//!
3//! The basic traits are `SmartPointer` and `SmartPointerMut` for basic creation,
4//! obtaining ownership, borrowing and dereferencing. Further subtraits expose more specialized
5//! functionality which is nonetheless applicable to any sort of smart pointer.
6//!
7//! These additional, specialized traits are being added to this crate as consumers need them. If
8//! you would like to see traits for additional features, e.g. conversion with raw pointers,
9//! [efficient borrows](https://docs.rs/triomphe/0.1.1/triomphe/struct.ArcBorrow.html),
10//! [pointers directly to the data](https://docs.rs/triomphe/0.1.1/triomphe/struct.OffsetArc.html)
11//! or [thin DST pointers](https://docs.rs/triomphe/0.1.1/triomphe/struct.ThinArc.html), open an
12//! issue.
13
14#![no_std]
15// #![cfg_attr(feature = "unstable", coerce_unsized, dispatch_from_dyn)]
16extern crate maybe_std as base;
17
18use base::borrow::{Borrow, BorrowMut};
19use base::ops::{Deref, DerefMut};
20use base::fmt::Pointer;
21
22/// The minimum amount of functionality common to all smart pointer types pointing to a
23/// value of type `T`. This trait only grants immutable access to the stored value, see
24/// `SmartPointerMut` for mutable access and `TryIntoMut` for fallible conversion into a mutable
25/// variant.
26///
27/// Note that most of the actual pointer functionality comes from the prerequisite traits.
28///
29/// Also note that this trait omits some functionality because it can only be expressed with
30/// higher-kinded types, such as working with uninitialized memory, conversions to slices,
31/// downcasting of `Any` values.
32pub trait SmartPointer<T: ?Sized>: Sized + AsRef<T> + Borrow<T> + Deref<Target = T> + Pointer
33// + CoerceUnsized<Ptr<U>> + DispatchFromDyn<Rc<U>> where T: Unsize<U>, U: ?Sized
34{
35    /// Construct a new smart pointer, containing the given value.
36    fn new(t: T) -> Self where T: Sized;
37
38    /// Try to obtain ownership of the wrapped value.
39    ///
40    /// This fails if there are other smart pointers wrapping the exact same value.
41    fn try_unwrap(this: Self) -> Result<T, Self> where T: Sized;
42
43    /// Returns whether two smart pointers point to the same location in memory.
44    ///
45    /// The default implementation borrows the inner values and compares their locations.
46    fn ptr_eq(a: &Self, b: &Self) -> bool {
47        base::ptr::eq(a.borrow(), b.borrow())
48    }
49}
50
51/// A `SmartPointer` which beyond immutable access to the wrapped value also provides mutable
52/// access via the `AsMut`, `BorrowMut` and `DerefMut` traits.
53pub trait SmartPointerMut<T: ?Sized>: SmartPointer<T> + AsMut<T> + BorrowMut<T> + DerefMut<Target = T> {}
54
55/// A `SmartPointer` which might grant mutable access, depending on run-time checks.
56pub trait IntoMut<T: ?Sized>: SmartPointer<T> {
57    type MutablePointer: SmartPointerMut<T> + Into<Self>;
58
59    /// Check whether converting into a mutable version would succeed.
60    fn can_make_mut(this: &Self) -> bool;
61
62    /// Convert into a mutable version without performing runtime checks for upholding any
63    /// invariants.
64    ///
65    /// Safety: Calling this is safe if and only if `can_make_mut` returns true.
66    unsafe fn into_mut_unchecked(this: Self) -> Self::MutablePointer;
67
68    /// Try converting into a mutable version of the pointer.
69    fn into_mut(this: Self) -> Result<Self::MutablePointer, Self> {
70        if IntoMut::can_make_mut(&this) {
71            Ok(unsafe { IntoMut::into_mut_unchecked(this) })
72        } else {
73            Err(this)
74        }
75    }
76
77    /// Obtain a mutable reference to the wrapped value without performing runtime checks for
78    /// upholding any invariants.
79    ///
80    /// Safety: Calling this is safe if and only if `can_make_mut` returns true.
81    unsafe fn get_mut_unchecked(this: &Self) -> &mut T;
82
83    /// Try obtaining a mutable reference to the wrapped value.
84    fn get_mut(this: &Self) -> Option<&mut T> {
85        if IntoMut::can_make_mut(this) {
86            Some(unsafe { IntoMut::get_mut_unchecked(this) })
87        } else {
88            None
89        }
90    }
91}
92
93// Might become trait:
94//
95// // fn as_ptr(this: &Self) -> *const T;
96// fn into_raw(this: Self) -> *const T;
97// unsafe fn from_raw(ptr: *const T) -> Self;
98
99#[cfg(test)]
100mod tests {
101    #[test]
102    fn it_works() {
103        assert_eq!(2 + 2, 4);
104    }
105}