pub struct UniqueSrc<T: SrcTarget + ?Sized> { /* private fields */ }Expand description
A uniquely owned Src.
This represents an Src that is known to be uniquely owned - that is, have exactly one strong reference.
Multiple weak pointers can be created, but attempts to upgrade those to strong references will fail unless the UniqueSrc has been converted to a regular shared Src.
Because they are uniquely owned, the contents of a UniqueSrc can be freely mutated.
This could be used as an initialization step (that is the suggested usage of UniqueRc),
but I find UninitSrc to be better for initialization, as there is no intermediate step with dangling weak pointers.
Still, the ability to mutably access the contents of an Src can be useful, hence this type’s inclusion in the crate.
(Also, Src::into_unique and Src::make_unique are currently this crate’s substitutes for Rc::get_mut and Rc::make_mut respectively;
since I made that decision, I have since realized that they are not equivalent, and will therefore probably add get_mut and make_mut methods to Src at some point.
In the mean time, this is the next best thing.)
Note that, while this struct currently has no methods to explicitly support non-root UniqueSrcs,
it is technically possible to construct them by making a non-root Src and turning into a UniqueSrc via Src::into_unique or Src::make_unique;
The behavior of these non-root UniqueSrcs has not been thoroughly considered and may be changed or removed.
Many of the inherent methods of UniqueSrc are associated functions, which means that you have to call them as e.g.,
UniqueSrc::downgrade(&value) instead of value.downgrade();
this avoids conflicts with methods of the inner type T.
However, some methods, e.g. Src::len, intentionally shadow a known method of the inner type because they use a more efficient computation for the same result,
and there may be some in the future (e.g. the hypothetical UniqueSrc::slice), which will be permitted to remain as methods because their inner type will be known not to have a conflicting method.
Implementations§
Source§impl<T: SrcTarget + ?Sized> UniqueSrc<T>
impl<T: SrcTarget + ?Sized> UniqueSrc<T>
Turns this UniqueSrc into an Src.
Because UniqueSrc has strictly stronger guarantees, this conversion is not fallible.
use slice_rc::UniqueSrc;
let x = UniqueSrc::single(3);
assert_eq!(*UniqueSrc::into_shared(x), 3);See also Src::into_unique and Src::make_unique.
Source§impl<T: SrcSlice + ?Sized> UniqueSrc<T>
impl<T: SrcSlice + ?Sized> UniqueSrc<T>
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of elements in this UniqueSrc.
This method deliberately shadows <[T]>::len and str::len because this method provides a (slightly) simpler and more efficient implementation.
This method only returns the length of the whole allocation if self is a root UniqueSrc.
use slice_rc::UniqueSrc;
let s = UniqueSrc::from_array([1, 2, 3]);
assert_eq!(s.len(), 3);Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if this UniqueSrc has a length of 0.
This method deliberately shadows <[T]>::is_empty and str::is_empty because this method provides a (slightly) simpler and more efficient implementation.
Note that this method does not imply that this UniqueSrc was constructed via UniqueSrc::empty.
Similarly, it does not imply that the entire allocation is empty, unless self is a root UniqueSrc.
use slice_rc::UniqueSrc;
let a = UniqueSrc::from_array([1, 2, 3]);
assert!(!a.is_empty());
let b = UniqueSrc::<[i32]>::from_array([]);
assert!(b.is_empty());Source§impl<T: Sized> UniqueSrc<T>
impl<T: Sized> UniqueSrc<T>
Sourcepub fn single(value: T) -> UniqueSrc<T>
pub fn single(value: T) -> UniqueSrc<T>
Constructs a new root UniqueSrc that contains only the given value.
use slice_rc::UniqueSrc;
let s = UniqueSrc::single(42);
assert_eq!(*s, 42);Sourcepub fn single_cyclic<F: FnOnce(&WeakSrc<T>) -> T>(f: F) -> UniqueSrc<T>
pub fn single_cyclic<F: FnOnce(&WeakSrc<T>) -> T>(f: F) -> UniqueSrc<T>
Constructs a new root UniqueSrc that contains only the value returned from the given function f.
The WeakSrc that f is given will be a weak reference to this allocation, which allows constructing a self-referential value;
it will return None from WeakSrc::upgrade until after single_cyclic has returned.
This is a convienience method for a specific subset of behavior that can be obtained via UninitSrc.
use slice_rc::{Src, UniqueSrc, WeakSrc};
struct S {
me: WeakSrc<S>,
}
let s = UniqueSrc::single_cyclic(|me| S { me: me.clone() });
assert!(s.me.upgrade().is_none());
let s = UniqueSrc::into_shared(s);
assert!(Src::ptr_eq(&s, &s.me.upgrade().unwrap()));Sourcepub fn single_uninit() -> UniqueSrc<MaybeUninit<T>>
pub fn single_uninit() -> UniqueSrc<MaybeUninit<T>>
Constructs a new root UniqueSrc of length 1 with uninitialized contents.
use slice_rc::{UniqueSrc};
let mut five = UniqueSrc::<i32>::single_uninit();
five.write(5);
let five = unsafe { five.assume_init() };
assert_eq!(*five, 5);Sourcepub fn single_zeroed() -> UniqueSrc<MaybeUninit<T>>
pub fn single_zeroed() -> UniqueSrc<MaybeUninit<T>>
Constructs a new root UniqueSrc of length 1 with uninitialized contents, with the memory being filled with 0 bytes.
See MaybeUninit::zeroed for examples of correct and incorrect usage of this method.
use slice_rc::UniqueSrc;
let zero = UniqueSrc::<i32>::single_zeroed();
let zero = unsafe { zero.assume_init() };
assert_eq!(*zero, 0);Sourcepub fn as_slice(this: UniqueSrc<T>) -> UniqueSrc<[T]>
pub fn as_slice(this: UniqueSrc<T>) -> UniqueSrc<[T]>
Returns a UniqueSrc 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, UniqueSrc};
use std::ptr;
let single = UniqueSrc::single(42);
let single_weak = UniqueSrc::downgrade(&single);
let slice = UniqueSrc::as_slice(single);
let slice = UniqueSrc::into_shared(slice);
let single = single_weak.upgrade().unwrap();
assert!(Src::ptr_eq(&single, &slice));
assert!(ptr::eq(&*single, &slice[0]));Source§impl<T> UniqueSrc<[T]>
impl<T> UniqueSrc<[T]>
Sourcepub fn new_uninit(len: usize) -> UniqueSrc<[MaybeUninit<T>]>
pub fn new_uninit(len: usize) -> UniqueSrc<[MaybeUninit<T>]>
Constructs a new root UniqueSrc of the given length with uninitialized contents.
use slice_rc::{Src, UniqueSrc};
let mut fives = UniqueSrc::<[i32]>::new_uninit(3);
fives[0].write(5);
fives[1].write(5);
fives[2].write(5);
let fives = unsafe { fives.assume_init() };
assert_eq!(*fives, [5, 5, 5]);Sourcepub fn new_zeroed(len: usize) -> UniqueSrc<[MaybeUninit<T>]>
pub fn new_zeroed(len: usize) -> UniqueSrc<[MaybeUninit<T>]>
Constructs a new root UniqueSrc of the given length with uninitialized contents, with the memory being filled with 0 bytes.
See MaybeUninit::zeroed for examples of correct and incorrect usage of this method.
use slice_rc::UniqueSrc;
let zeroes = UniqueSrc::<[i32]>::new_zeroed(3);
let zeroes = unsafe { zeroes.assume_init() };
assert_eq!(*zeroes, [0, 0, 0]);Sourcepub fn from_fn<F: FnMut(usize) -> T>(len: usize, f: F) -> UniqueSrc<[T]>
pub fn from_fn<F: FnMut(usize) -> T>(len: usize, f: F) -> UniqueSrc<[T]>
Constructs a new root UniqueSrc of the given length where each element is produced by calling f with that element’s index while walking forward through the slice.
This essentially the same as writing
UniqueSrc::from_array([f(0), f(1), f(2), ..., f(len - 2), f(len - 1)])and is similar to (0..len).map(f), just for UniqueSrcs rather than iterators.
If len == 0, this produces an empty UniqueSrc without ever calling f.
use slice_rc::UniqueSrc;
let slice = UniqueSrc::from_fn(5, |i| i);
assert_eq!(*slice, [0, 1, 2, 3, 4]);
let slice2 = UniqueSrc::from_fn(8, |i| i * 2);
assert_eq!(*slice2, [0, 2, 4, 6, 8, 10, 12, 14]);
let bool_slice = UniqueSrc::from_fn(5, |i| i % 2 == 0);
assert_eq!(*bool_slice, [true, false, true, false, true]);You can also capture things, so you can use closures with mutable state. The slice is generated in ascending index order, starting from the front and going towards the back.
let mut state = 1;
let s = UniqueSrc::from_fn(6, |_| { let x = state; state *= 2; x });
assert_eq!(*s, [1, 2, 4, 8, 16, 32]);§Panics
Panics if f panics; in this event, any elements that have been initialized will be properly dropped.
thread_local! {
static DROPPED: Cell<usize> = Cell::new(0);
}
struct Droppable;
impl Drop for Droppable {
fn drop(&mut self) {
DROPPED.with(|dropped| dropped.update(|x| x + 1));
}
}
let _ = std::panic::catch_unwind(|| {
UniqueSrc::from_fn(10, |i| {
if i >= 5 { panic!() }
Droppable
})
});
assert_eq!(DROPPED.get(), 5);Sourcepub fn cyclic_from_fn<F: FnMut(&WeakSrc<[T]>, usize) -> T>(
len: usize,
f: F,
) -> UniqueSrc<[T]>
pub fn cyclic_from_fn<F: FnMut(&WeakSrc<[T]>, usize) -> T>( len: usize, f: F, ) -> UniqueSrc<[T]>
Constructs a new root UniqueSrc of the given length where each element is produced by calling f with a root WeakSrc pointer to the new allocation and that element’s index while walking forward through the slice.
This method is like UniqueSrc::from_fn, but in this the function f is passed a root WeakSrc pointer to the allocation to allow constructing self-referential elements.
This is a convienience method for a specific subset of behavior that can be obtained via UninitSrc.
use slice_rc::{Src, UniqueSrc, WeakSrc};
struct S {
val: usize,
root: WeakSrc<[S]>,
}
let root = UniqueSrc::cyclic_from_fn(5, |root, i| S {
val: i * 2,
root: root.clone(),
});
assert_eq!(root.iter().map(|s| s.val).collect::<Vec<_>>(), vec![0, 2, 4, 6, 8]);
let root = UniqueSrc::into_shared(root);
assert!(root.iter().all(|s| Src::ptr_eq(&root, &s.root.upgrade().unwrap())));It is possible to obtain a WeakSrc to the individual element that is being initialized via WeakSrc::slice:
struct S {
val: usize,
me: WeakSrc<S>,
}
let root = UniqueSrc::cyclic_from_fn(5, |root, i| S {
val: i * 2,
me: root.slice(i),
});
let root = UniqueSrc::into_shared(root);
assert!(root.iter().enumerate().all(|(i, s)| Src::ptr_eq(&root.slice(i), &s.me.upgrade().unwrap())));Sourcepub fn from_iter<I: IntoIterator<Item = T, IntoIter: ExactSizeIterator>>(
iter: I,
) -> UniqueSrc<[T]>
pub fn from_iter<I: IntoIterator<Item = T, IntoIter: ExactSizeIterator>>( iter: I, ) -> UniqueSrc<[T]>
Constructs a new root UniqueSrc from the given iterator.
This method is essentially shorthand for
use slice_rc::UniqueSrc;
let mut iter = iter.into_iter();
UniqueSrc::from_fn(iter.len(), |_| iter.next().unwrap())The iterator must be ExactSizeIterator because UniqueSrcs cannot be resized,
so the number of elements must be known at allocation-time, i.e., before any of the elements are initialized.
If you want to use a non-ExactSizeIterator, use iter.collect::<Vec<_>>().
Sourcepub fn from_array<const N: usize>(values: [T; N]) -> UniqueSrc<[T]>
pub fn from_array<const N: usize>(values: [T; N]) -> UniqueSrc<[T]>
Constructs a new root UniqueSrc from the given array.
This method is effectively equivalent to passing an array to UniqueSrc::from_iter, but it is more efficient.
As such, it is effectively shorthand for UniqueSrc::from_fn(N, |i| values[i]), but again, more efficient
(though not by enough to make UniqueSrc::from_array(array::from_fn::<_, N, _>(f)) any better than UniqueSrc::from_fn(N, f)).
Note that the my assertions about efficiency are not based any kind of benchmarking,
just the fact that this method uses a single ptr::write where UniqueSrc::from_fn and UniqueSrc::from_iter use N arbitrary function calls and N ptr::writes.
As array::from_fn re-introduces at least the N arbitrary function calls, its difference (again, without benchmarking) is negligible.
Sourcepub fn from_default(len: usize) -> UniqueSrc<[T]>where
T: Default,
pub fn from_default(len: usize) -> UniqueSrc<[T]>where
T: Default,
Constructs a new root UniqueSrc of the given length where each element is the type’s default.
This method is essentially equivalent to UniqueSrc::from_fn(len, |_| Default::default()).
Sourcepub fn filled_cyclic<F: FnOnce(&WeakSrc<[T]>) -> T>(
len: usize,
f: F,
) -> UniqueSrc<[T]>where
T: Clone,
pub fn filled_cyclic<F: FnOnce(&WeakSrc<[T]>) -> T>(
len: usize,
f: F,
) -> UniqueSrc<[T]>where
T: Clone,
Constructs a new root UniqueSrc of the given length where each element is a clone of the value returned from f.
f is passed a root WeakSrc pointer to the allocation; this can be used to make self-referential structures.
use slice_rc::{Src, UniqueSrc, WeakSrc};
#[derive(Clone)]
struct S {
val: i32,
root: WeakSrc<[S]>,
}
let root = UniqueSrc::filled_cyclic(5, |root| S { val: 42, root: root.clone() });
assert!(root.iter().all(|s| s.val == 42));
let root = UniqueSrc::into_shared(root);
assert!(root.iter().all(|s| Src::ptr_eq(&root, &s.root.upgrade().unwrap())));Sourcepub fn copied(values: &[T]) -> UniqueSrc<[T]>where
T: Copy,
pub fn copied(values: &[T]) -> UniqueSrc<[T]>where
T: Copy,
Constructs a new root UniqueSrc as a copy of the given slice.
This method is functionally shorthand for UniqueSrc::from_fn(values.len(), |i| values[i]),
but without the implicit bounds checking for slice indexing.
This method is fairly efficient, as it is basically just an allocation (requisite for any UniqueSrc constructor) and a memcpy.
Source§impl<T> UniqueSrc<MaybeUninit<T>>
impl<T> UniqueSrc<MaybeUninit<T>>
Sourcepub unsafe fn assume_init(self) -> UniqueSrc<T>
pub unsafe fn assume_init(self) -> UniqueSrc<T>
Converts to UniqueSrc<T>.
§Safety
As with MaybeUninit::assume_init, it is up to the caller to guarantee that the inner value really is in an initialized state.
Calling this when the content is not yet fully initialized causes immediate undefined behavior.
§Examples
use slice_rc::UniqueSrc;
let zero = UniqueSrc::<i32>::single_zeroed();
let zero = unsafe { zero.assume_init() };
assert_eq!(*zero, 0);Source§impl<T> UniqueSrc<[MaybeUninit<T>]>
impl<T> UniqueSrc<[MaybeUninit<T>]>
Sourcepub unsafe fn assume_init(self) -> UniqueSrc<[T]>
pub unsafe fn assume_init(self) -> UniqueSrc<[T]>
Converts to UniqueSrc<[T]>.
§Safety
As with MaybeUninit::assume_init, it is up to the caller to guarantee that the inner value really is in an initialized state.
Calling this when the content is not yet fully initialized causes immediate undefined behavior.
§Examples
use slice_rc::UniqueSrc;
let zeroes = UniqueSrc::<[i32]>::new_zeroed(3);
let zeroes = unsafe { zeroes.assume_init() };
assert_eq!(*zeroes, [0, 0, 0]);Source§impl UniqueSrc<str>
impl UniqueSrc<str>
Sourcepub fn new(s: impl AsRef<str>) -> UniqueSrc<str>
pub fn new(s: impl AsRef<str>) -> UniqueSrc<str>
Constructs a new root UniqueSrc as a copy of the given string.
use slice_rc::UniqueSrc;
let hello = UniqueSrc::new("Hello World!");
assert_eq!(&*hello, "Hello World!");Sourcepub fn from_utf8(v: UniqueSrc<[u8]>) -> Result<UniqueSrc<str>, Utf8Error>
pub fn from_utf8(v: UniqueSrc<[u8]>) -> Result<UniqueSrc<str>, Utf8Error>
Converts an UniqueSrc of bytes to a string UniqueSrc.
str and [u8] are both slices of bytes, so this function converts between the two.
Not all byte slices are valid string slices, however: str must be valid UTF-8.
This method checks to ensure that the bytes are valid UTF-8, and then does the conversion.
If you are sure that the byte slice is valid UTF-8, and you don’t want to incur the overhead of the validity check,
there is an unsafe version of this method, from_utf8_unchecked,
which has the same behavior but skips the check.
§Errors
Returns Err if the slice is not UTF-8 with a description as to why the provided slice is not UTF-8.
§Examples
Basic usage:
use slice_rc::UniqueSrc;
let sparkle_heart = UniqueSrc::from_array([240, 159, 146, 150]);
let sparkle_heart = UniqueSrc::from_utf8(sparkle_heart)?;
assert_eq!("💖", &*sparkle_heart);Incorrect bytes:
let sparkle_heart = UniqueSrc::from_array([0, 159, 146, 150]);
assert!(UniqueSrc::from_utf8(sparkle_heart).is_err());Sourcepub unsafe fn from_utf8_unchecked(v: UniqueSrc<[u8]>) -> UniqueSrc<str>
pub unsafe fn from_utf8_unchecked(v: UniqueSrc<[u8]>) -> UniqueSrc<str>
Converts an UniqueSrc of bytes to a string UniqueSrc without checking that the string contains valid UTF-8.
See the safe version, from_utf8, for more information.
§Safety
The bytes passed in must be valid UTF-8.
§Examples
use slice_rc::UniqueSrc;
let sparkle_heart = UniqueSrc::from_array([240, 159, 146, 150]);
let sparkle_heart = unsafe { UniqueSrc::from_utf8_unchecked(sparkle_heart) };
assert_eq!("💖", &*sparkle_heart);