noop_allocator/owning_slice.rs
1//! Functions to produce an [`OwningSlice<'_, T>`][OwningSlice], a.k.a. a
2//! `Vec<T, NoopAllocator<'_>>`, from mutably borrowed `MaybeUninit<T>`s.
3//!
4//! Note that there are no functions which take `&mut ManuallyDrop` here, even
5//! as `unsafe fn`s, since `Vec` may use it's spare capacity in ways that
6//! violate `ManuallyDrop<T>`'s validity invariants, not just it's safety
7//! invariants.
8
9use core::{marker::PhantomData, mem::MaybeUninit};
10
11use crate::NoopAllocator;
12use alloc::vec::Vec;
13
14/// An owning slice reference boorrowing a memory location but owning the value
15/// in it, implemented as `Vec<T, NoopAllocator<'a>>`.
16pub type OwningSlice<'a, T> = Vec<T, NoopAllocator<'a>>;
17
18/// Create an empty `OwningSlice<'a, T>` with a length and capacity of 0.
19///
20/// # Examples:
21///
22/// ```rust
23/// # use std::mem::MaybeUninit;
24/// use noop_allocator::owning_slice;
25/// let mut vec: owning_slice::OwningSlice<'_, String> = owning_slice::new();
26/// assert_eq!(vec, [] as [String; 0]);
27/// assert_eq!(vec.len(), 0);
28/// assert_eq!(vec.capacity(), 0);
29/// assert_eq!(vec.pop().as_deref(), None);
30/// ```
31pub const fn new<'a, T>() -> OwningSlice<'a, T> {
32 Vec::new_in(NoopAllocator(PhantomData))
33}
34
35/// Create a `OwningSlice<'a, T>` with a length and capacity of 1 from a `&'a
36/// mut MaybeUninit<T>>`.
37///
38/// # Safety
39///
40/// The `T` must be initialized, and dropping or removing the element from the
41/// `OwningSlice` leaves the `MaybeUninit` semantically without a value, see
42/// [`MaybeUninit::assume_init_mut`] and [`MaybeUninit::assume_init_drop`].
43///
44/// # Examples:
45///
46/// ```rust
47/// # use std::mem::MaybeUninit;
48/// use noop_allocator::owning_slice;
49/// let mut buf: MaybeUninit<String> = MaybeUninit::new("Hello, world!".to_string());
50/// let mut vec = unsafe { owning_slice::from_maybeuninit(&mut buf) };
51/// assert_eq!(vec, ["Hello, world!"]);
52/// assert_eq!(vec.capacity(), 1);
53/// assert_eq!(vec.pop().as_deref(), Some("Hello, world!"));
54/// vec.push("Hi!".to_string());
55/// assert_eq!(vec, ["Hi!"]);
56/// ```
57pub unsafe fn from_maybeuninit<T>(slot: &mut MaybeUninit<T>) -> OwningSlice<'_, T> {
58 Vec::from_raw_parts_in(
59 slot as *mut MaybeUninit<T> as *mut T,
60 1,
61 1,
62 NoopAllocator(PhantomData),
63 )
64}
65
66/// Create a `OwningSlice<'a, T>` with a given length from a `&'a mut
67/// [MaybeUninit<T>]>`. The capacity is the length of the given slice.
68///
69/// # Safety
70///
71/// All slice elements in `[0..length]` must be initialized, see
72/// [`MaybeUninit::assume_init_mut`] and [`MaybeUninit::assume_init_drop`].
73///
74/// # Examples:
75///
76/// ```rust
77/// # use std::mem::MaybeUninit;
78/// use noop_allocator::owning_slice;
79/// let mut buf: [MaybeUninit<String>; 4] = [const { MaybeUninit::uninit() }; 4];
80/// buf[0] = MaybeUninit::new("Hello, world!".to_string());
81/// let mut vec = unsafe { owning_slice::from_maybeuninit_slice(&mut buf, 1) };
82/// assert_eq!(vec, ["Hello, world!"]);
83/// assert_eq!(vec.capacity(), 4);
84/// assert_eq!(vec.pop().as_deref(), Some("Hello, world!"));
85/// vec.push("Hi!".to_string());
86/// assert_eq!(vec, ["Hi!"]);
87/// ```
88pub unsafe fn from_maybeuninit_slice<T>(
89 slot: &mut [MaybeUninit<T>],
90 length: usize,
91) -> OwningSlice<'_, T> {
92 debug_assert!(length <= slot.len());
93 Vec::from_raw_parts_in(
94 slot as *mut [MaybeUninit<T>] as *mut [T] as *mut T,
95 length,
96 slot.len(),
97 NoopAllocator(PhantomData),
98 )
99}
100
101/// Create a `OwningSlice<'a, T>` with a length of 0 and a capacity of 1 from a
102/// `&'a mut MaybeUninit<T>>`.
103///
104/// The `T` is not assumed to be initialized, so this is not an `unsafe`
105/// function.
106///
107/// # Examples:
108///
109/// ```rust
110/// # use std::mem::MaybeUninit;
111/// use noop_allocator::owning_slice;
112/// let mut buf: MaybeUninit<String> = MaybeUninit::uninit();
113/// let mut vec = owning_slice::empty_from_maybeuninit(&mut buf);
114/// assert!(vec.is_empty());
115/// assert_eq!(vec.capacity(), 1);
116/// vec.push("Hello, world!".to_string());
117/// assert_eq!(vec, ["Hello, world!"]);
118/// ```
119pub fn empty_from_maybeuninit<T>(slot: &mut MaybeUninit<T>) -> OwningSlice<'_, T> {
120 unsafe {
121 Vec::from_raw_parts_in(
122 slot as *mut MaybeUninit<T> as *mut T,
123 0,
124 1,
125 NoopAllocator(PhantomData),
126 )
127 }
128}
129
130/// Create a `OwningSlice<'a, T>` with a length of 0 from a `&'a mut
131/// [MaybeUninit<T>]>`. The capacity is the length of the given slice.
132///
133/// The slice elements are not assumed to be initialized, so this is not an
134/// `unsafe` function.
135///
136/// # Examples
137///
138/// ```rust
139/// # use std::mem::MaybeUninit;
140/// use noop_allocator::owning_slice;
141/// let mut buf: [MaybeUninit<String>; 4] = [const { MaybeUninit::uninit() }; 4];
142/// let mut vec = owning_slice::empty_from_maybeuninit_slice(&mut buf);
143/// assert!(vec.is_empty());
144/// assert_eq!(vec.capacity(), 4);
145/// vec.push("Hello, world!".to_string());
146/// assert_eq!(vec, ["Hello, world!"]);
147/// ```
148pub fn empty_from_maybeuninit_slice<T>(slot: &mut [MaybeUninit<T>]) -> OwningSlice<'_, T> {
149 unsafe {
150 Vec::from_raw_parts_in(
151 slot as *mut [MaybeUninit<T>] as *mut [T] as *mut T,
152 0,
153 slot.len(),
154 NoopAllocator(PhantomData),
155 )
156 }
157}
158
159/// Create a full `OwningSlice<'a, T>` from a raw slice pointer.
160///
161/// # Safety
162///
163/// The memory behind `ptr` must be uniquely borrowed for `'a`.
164///
165/// All slice elements must be initialized, see
166/// [`MaybeUninit::assume_init_mut`] and [`MaybeUninit::assume_init_drop`].
167pub unsafe fn full_from_raw<'a, T>(ptr: *mut [T]) -> OwningSlice<'a, T> {
168 Vec::from_raw_parts_in(
169 ptr as *mut MaybeUninit<T> as *mut T,
170 ptr.len(),
171 ptr.len(),
172 NoopAllocator(PhantomData),
173 )
174}
175
176/// Create a `OwningSlice<'a, T>` with a given length from a raw slice pointer.
177/// The capacity is the length of the given slice.
178///
179/// # Safety
180///
181/// The memory behind `ptr` must be uniquely borrowed for `'a`.
182///
183/// All slice elements in `[0..length]` must be initialized, see
184/// [`MaybeUninit::assume_init_mut`] and [`MaybeUninit::assume_init_drop`].
185pub unsafe fn from_raw<'a, T>(ptr: *mut [T], length: usize) -> OwningSlice<'a, T> {
186 debug_assert!(length <= ptr.len());
187 Vec::from_raw_parts_in(
188 ptr as *mut [MaybeUninit<T>] as *mut [T] as *mut T,
189 length,
190 ptr.len(),
191 NoopAllocator(PhantomData),
192 )
193}
194
195/// Create an empty `OwningSlice<'a, T>` from a raw slice pointer.
196/// The capacity is the length of the given slice.
197///
198/// # Safety
199///
200/// The memory behind `ptr` must be uniquely borrowed for `'a`.
201///
202/// The slice elements are not assumed to be initialized.
203pub unsafe fn empty_from_raw<'a, T>(ptr: *mut [T]) -> OwningSlice<'a, T> {
204 unsafe { Vec::from_raw_parts_in(ptr.cast(), 0, ptr.len(), NoopAllocator(PhantomData)) }
205}