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