WeakSrc

Struct WeakSrc 

Source
pub struct WeakSrc<T: SrcTarget + ?Sized> { /* private fields */ }
Expand description

WeakSrc is a version of Src that holds a non-owning reference to the managed allocation.

This is this crate’s analog to std::rc::Weak; see the crate-level documentation for a description of how this crate’s types differ from those of std::rc.

The allocation is accessed by calling upgrade on the WeakSrc pointer, which returns an Option<Src<T>>.

Since a WeakSrc pointer does not count toward ownership, it will not prevent the value stored in the allocation from being dropped, and WeakSrc itself makes no guarantees about the value still being present. Thus it may return None when upgraded. Note however that a WeakSrc does prevent the allocation itself (the backing store) from being deallocated.

A WeakSrc pointer is useful for keeping a temporary reference to the allocation managed by Src without preventing its inner value from being dropped. It is also used to prevent circular references between Src pointers, since mutual owning references would never allow either Src to be dropped. For example, a tree could have strong Src pointers from parent nodes to children, and WeakSrc pointers from children back to their parents.

The typical way to obtain a WeakSrc pointer is to call Src::downgrade.

§Dangling

WeakSrc::dangling allows constructing a “dangling” WeakSrc pointer; dangling WeakSrc pointers don’t have a backing allocation, and as such, are guaranteed to return None from WeakSrc::upgrade. Dangling WeakSrcs are considered root and empty.

WeakSrc pointers which are attached to an allocation are not considered dangling, even if that allocation has been dropped or the WeakSrc is otherwise un-upgradeable.

Implementations§

Source§

impl<T: SrcTarget + ?Sized> WeakSrc<T>

Source

pub fn dangling() -> WeakSrc<T>

Constructs a new dangling WeakSrc.

§Examples
use slice_rc::WeakSrc;
 
let dangling = WeakSrc::<i32>::dangling();
 
assert!(dangling.is_dangling());
Source

pub fn is_dangling(&self) -> bool

Returns true if this WeakSrc is dangling. This only returns true for WeakSrcs that were constructed from WeakSrc::dangling; WeakSrcs that are un-upgradeable for other reasons are not considered dangling, and therefore this method returns false for those cases.

§Examples
use slice_rc::WeakSrc;
 
let dangling = WeakSrc::<i32>::dangling();
 
assert!(dangling.is_dangling());

Not dangling:

let s = Src::single(42);
let w = Src::downgrade(&s);
drop(s);
 
assert!(!w.is_dangling());
assert!(w.upgrade().is_none());
Source

pub fn upgrade(&self) -> Option<Src<T>>

Attempts to upgrade the WeakSrc pointer to an Src, delaying dropping the inner value if successful.

Returns None if the inner value has since been dropped, if the inner value is uniquely owned by a UniqueSrc, or if the inner value is uninitialized via UninitSrc or one of the cyclic helper methods, e.g. Src::cyclic_from_fn.

§Examples
use slice_rc::Src;
 
let five = Src::single(5);
 
let weak_five = Src::downgrade(&five);
 
let strong_five = weak_five.upgrade();
assert!(strong_five.is_some());
 
drop(strong_five);
drop(five);
 
assert!(weak_five.upgrade().is_none());
Source

pub fn ptr_eq<U: SrcTarget<Item = T::Item> + ?Sized>( &self, other: &WeakSrc<U>, ) -> bool

Returns true if the two WeakSrcs point to slices starting at the same location in memory or are both dangling, akin to ptr::eq.

use slice_rc::{Src, WeakSrc};
 
let slice = Src::from_array([1, 2, 3]);
let weak_slice = Src::downgrade(&slice);
let same_weak_slice = weak_slice.clone();
let weak_sub_slice = weak_slice.slice(1..);
let other_slice = Src::from_array([1, 2, 3]);
let other_weak_slice = Src::downgrade(&other_slice);
 
assert!(WeakSrc::ptr_eq(&weak_slice, &same_weak_slice));
assert!(!WeakSrc::ptr_eq(&weak_slice, &weak_sub_slice));
assert!(!WeakSrc::ptr_eq(&weak_slice, &other_weak_slice));

If WeakSrc::ptr_eq(&a, &b) returns true, then WeakSrc::same_root(&a, &b) will also be true.

The type parameter, U, is to allow WeakSrcs of different types that could be of the same allocation, and therefore, could be equal by pointer, to be compared, e.g.:

let strong: Src<i32> = Src::single(4);
let single: WeakSrc<i32> = Src::downgrade(&strong);
let slice: WeakSrc<[i32]> = single.as_slice();
 
assert!(WeakSrc::ptr_eq(&single, &slice));

Note that this method currently ignores the length of the slice:

let root_strong = Src::from_array([1, 2, 3]);
let root = Src::downgrade(&root_strong);
let first = root.slice(0);
 
assert!(WeakSrc::ptr_eq(&root, &first));
 
let mid_to_end_slice = root.slice(1..);
let mid_slice = root.slice(1..=1);
 
assert!(WeakSrc::ptr_eq(&mid_to_end_slice, &mid_slice));

It is undecided whether this behavior is desireable, and as such, it may change; notably, Weak::ptr_eq does ignore metadata for ?Sized types (though that’s irrelevant for slices because Weaks can only point to the whole slice, and therefore the length will always be the same for Weaks that point to the same allocation), while ptr::eq does consider the metadata (which causes inconsistent results for trait objects, but that is irrelevant here because WeakSrcs don’t support trait objects).

See also WeakSrc::same_root.

Source

pub fn same_root<U: SrcTarget<Item = T::Item> + ?Sized>( &self, other: &WeakSrc<U>, ) -> bool

Returns true if the two WeakSrcs share the same root (i.e., they point to parts of the same allocation) or are both dangling.

use slice_rc::{Src, WeakSrc};
 
let slice = Src::from_array([1, 2, 3]);
let weak_slice = Src::downgrade(&slice);
let same_weak_slice = weak_slice.clone();
let other_slice = Src::from_array([1, 2, 3]);
let other_weak_slice = Src::downgrade(&other_slice);
 
assert!(WeakSrc::same_root(&weak_slice, &same_weak_slice));
assert!(!WeakSrc::same_root(&weak_slice, &other_weak_slice));

Notably, neither slice has to be the root, nor do they need to overlap at all:

let strong = Src::from_array([1, 2, 3]);
let root = Src::downgrade(&strong);
let a = root.slice(..1);
let b = root.slice(2..);
 
assert!(WeakSrc::same_root(&a, &b));

The type parameter, U, is to allow WeakSrcs of different types that could share the same root, to be compared, e.g.:

let strong: Src<i32> = Src::single(4);
let single: WeakSrc<i32> = Src::downgrade(&strong);
let slice: WeakSrc<[i32]> = single.as_slice();
 
assert!(WeakSrc::same_root(&single, &slice));

This method ignores the length of the slices in question, but unlike WeakSrc::ptr_eq, this will not change, as the roots remains the same regardless of which parts of it are included in these slices.

See also WeakSrc::ptr_eq, WeakSrc::is_root, and WeakSrc::root.

Source

pub fn is_root(&self) -> bool

Returns true if this WeakSrc contains its root (i.e., it references its entire allocation), or is dangling. Notably, this WeakSrc does not have to be the first one that was initialized, it just has to cover the entire allocation.

use slice_rc::Src;
 
let strong = Src::from_array([1, 2, 3]);
let root = Src::downgrade(&strong);
let also_root = root.slice(..);
let slice = root.slice(1..);
 
assert!(root.is_root());
assert!(also_root.is_root());
assert!(!slice.is_root());

See also WeakSrc::same_root and WeakSrc::root.

Source

pub fn strong_count(&self) -> usize

Gets the number of strong (Src) pointers pointing to this allocation.

If self is dangling, this will return 0.

Source

pub fn weak_count(&self) -> usize

Gets the number of WeakSrc pointers pointing to this allocation.

If no strong pointers remain (or this WeakSrc is otherwise un-upgradeable), this will return 0.

Source

pub fn root(&self) -> WeakSrc<[T::Item]>

Returns a WeakSrc pointer that refers to this WeakSrc’s root (i.e., the entire allocation).

use slice_rc::Src;
 
let strong = Src::from_array([1, 2, 3]);
let root = Src::downgrade(&strong);
let slice = root.slice(1..);
drop(root);
 
assert_eq!(*slice.upgrade().unwrap(), [2, 3]);
 
let new_root = slice.root();
 
assert_eq!(*new_root.upgrade().unwrap(), [1, 2, 3]);

This method returns a WeakSrc<[T::Item]> rather than a WeakSrc<T> for two reasons:

  • If T: Sized, then the root can only be a WeakSrc<T> if its total length is is 1, which would prevent situations like this:
let strong = Src::from_array([1, 2, 3]);
let root: WeakSrc<[i32]> = Src::downgrade(&strong);
let slice: WeakSrc<i32> = root.slice(1);
let new_root: WeakSrc<[i32]> = slice.root();
 
assert_eq!(*new_root.upgrade().unwrap(), [1, 2, 3]);
  • If T = str, it could be a UTF-8 slice of a larger allocation that is not entirely UTF-8, which would violate the safety invariant of str:
let root: Src<[u8]> = Src::copied(b"\xFFhello");
let weak_root: WeakSrc<[u8]> = Src::downgrade(&root);
let s: Src<str> = Src::from_utf8(root.slice(1..)).unwrap();
let weak_s: WeakSrc<str> = Src::downgrade(&s);
let new_weak_root: WeakSrc<[u8]> = weak_s.root();
 
assert_eq!(&*weak_s.upgrade().unwrap(), "hello");
assert!(Src::from_utf8(new_weak_root.upgrade().unwrap()).is_err());
Source§

impl<T: SrcSlice + ?Sized> WeakSrc<T>

Source

pub fn len(&self) -> usize

Returns the numeber of elements in this WeakSrc. If self is dangling, returns 0.

This method only returns the length of the whole allocation if self is a root WeakSrc.

use slice_rc::Src;
 
let s = Src::from_array([1, 2, 3]);
let w = Src::downgrade(&s);
assert_eq!(w.len(), 3);
Source

pub fn is_empty(&self) -> bool

Returns true if this WeakSrc has a length of 0 or is dangling.

use slice_rc::Src;
 
let a_strong = Src::from_array([1, 2, 3]);
let a = Src::downgrade(&a_strong);
assert!(!a.is_empty());
 
let b_strong = Src::<[i32]>::from_array([]);
let b = Src::downgrade(&b_strong);
assert!(b.is_empty());
Source§

impl<T: Sized> WeakSrc<T>

Source

pub fn as_slice(&self) -> WeakSrc<[T]>

Returns a WeakSrc equivalent to this one, but typed as a slice rather than a single element. The returned slice will have a length of 1, and its element 0 will be at the same location in memory as self’s value.

use slice_rc::{Src, WeakSrc};
use std::ptr;
 
let strong = Src::single(42);
let single = Src::downgrade(&strong);
let slice = single.as_slice();
 
assert!(WeakSrc::ptr_eq(&single, &slice));
assert!(ptr::eq(&*single.upgrade().unwrap(), &slice.upgrade().unwrap()[0]));
Source§

impl<T> WeakSrc<[T]>

Source

pub fn slice<I: WeakSrcIndex<[T]>>(&self, index: I) -> WeakSrc<I::Output>

Returns a WeakSrc pointer to an element or subslice depending on the type of index.

  • If given a position (only applicable where Self = WeakSrc<[U]>), returns an WeakSrc<U> to the element at that position.
  • If given a range, returns the subslice corresponding to that range.

This method is only provided for WeakSrc<[T]>, not WeakSrc<str>; this is because str requires analyzing the value to validate that the new range is falls on char boundaries, and therefore the WeakStr must be upgraded to slice it. On the other hand, this is an acceptable compromise because the primary use-case of this method is during cyclic initialization, which is meaningless for str.

§Panics

If the index is in some way out of bounds. Note that dangling pointers are considered empty.

§Examples
use slice_rc::Src;
 
let v = Src::from_array([10, 40, 30]);
let weak = Src::downgrade(&v);
assert_eq!(Src::single(40), weak.slice(1).upgrade().unwrap());
assert_eq!(Src::from_array([10, 40]), weak.slice(0..2).upgrade().unwrap());

Panics:

let v = Src::from_array([10, 40, 30]);
let weak = Src::downgrade(&v);
let _ = weak.slice(3);
let _ = weak.slice(0..4);

Trait Implementations§

Source§

impl<T: SrcTarget + ?Sized> Clone for WeakSrc<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: SrcTarget + ?Sized> Debug for WeakSrc<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: SrcTarget + ?Sized> Default for WeakSrc<T>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<T: SrcTarget + ?Sized> Drop for WeakSrc<T>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl<T: SrcTarget + ?Sized> Pointer for WeakSrc<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<T> Freeze for WeakSrc<T>
where <T as SealedSrcTarget>::Len: Freeze, T: ?Sized,

§

impl<T> !RefUnwindSafe for WeakSrc<T>

§

impl<T> !Send for WeakSrc<T>

§

impl<T> !Sync for WeakSrc<T>

§

impl<T> Unpin for WeakSrc<T>
where <T as SealedSrcTarget>::Len: Unpin, T: ?Sized,

§

impl<T> !UnwindSafe for WeakSrc<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> SrcTarget for T

Source§

type Item = T

The type of each element of a Src<Self>. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.