slice_rc/uninit.rs
1use std::{fmt::{self, Debug, Formatter, Pointer}, marker::PhantomData, mem::forget, ptr::NonNull};
2
3use crate::{inner::AllocUninit, InnerHeader, Src, SrcSlice, SrcTarget, UniqueSrc, WeakSrc};
4
5/// `UninitSrc` is a version of [`Src`] that uniquely owns a new allocation before its body is initialized.
6/// This is primarily used to construct self-referential data structures:
7/// the [`downgrade`](UninitSrc::downgrade) method allows aquiring [weak references](WeakSrc) to this allocation before its body is initialized.
8///
9/// There are several helper methods for [`Src`] and [`UniqueSrc`] such as [`cyclic_from_fn`](Src::cyclic_from_fn) that may be simpler than `UninitSrc` for specific use cases.
10///
11/// `UninitSrc` pointers are always [root](crate#root)s,
12/// because there is (at least at present) no way to track which elements are initialized and which are not,
13/// and a non-[root](crate#root) `UninitSrc` would be useless if you couldn't initialize it.
14///
15/// Note that there is no way to construct or initialize an <code>UninitSrc\<[str]></code>;
16/// however, as a [`str`] cannot contain a <code>[WeakSrc]\<[str]></code>, this type is useless with [`str`] anyway.
17pub struct UninitSrc<T: SrcTarget + ?Sized> {
18
19 // SAFETY:
20 // requires:
21 // * initialized from InnerHeader::new_inner::<T::Item>(_)
22 pub(crate) header: NonNull<InnerHeader>,
23 // SAFETY:
24 // requires when T: SrcSlice:
25 // * self.start.add(self.len) <= InnerHeader::get_body_ptr::<T::Item>(self.header).add(InnerHeader::get_header(self.header).len())
26 // requires when T: Sized:
27 // * self.start < InnerHeader::get_body_ptr::<T::Item>(self.header).add(InnerHeader::get_header(self.header).len())
28 pub(crate) len: T::Len,
29 pub(crate) _phantom: PhantomData<*const T>,
30
31}
32
33impl<T: SrcTarget + ?Sized> UninitSrc<T> {
34
35 fn header(&self) -> &InnerHeader {
36 // SAFETY:
37 // * all constructor fns for Src initialize header from InnerHeader::new_inner::<T::Item>
38 // * the header is only accessed from InnerHeader::get_header
39 unsafe { InnerHeader::get_header(self.header) }
40 }
41
42 /// Creates a [root](crate#root) [`WeakSrc`] pointer to this allocation.
43 ///
44 /// ```rust
45 /// use slice_rc::{Src, UninitSrc, WeakSrc};
46 ///
47 /// struct S {
48 ///
49 /// me: WeakSrc<S>,
50 ///
51 /// }
52 ///
53 /// let uninit = UninitSrc::single();
54 /// let s = S { me: uninit.downgrade() };
55 /// let s = uninit.init(s);
56 /// assert!(Src::ptr_eq(&s, &s.me.upgrade().unwrap()));
57 /// ```
58 pub fn downgrade(&self) -> WeakSrc<T> {
59 // safety note: the strong count is 0 until this UninitSrc is initialized into a Src, so the WeakSrc will never read or write from the body during the lifetime of the UninitSrc
60 self.header().inc_weak_count();
61 // SAFETY:
62 // * all constructor fns for UninitSrc<T> initialize self.header from InnerHeader::new_inner::<T>
63 // * the header is only accessed from InnerHeader::get_header
64 let start = unsafe { InnerHeader::get_body_ptr::<T::Item>(self.header) };
65 WeakSrc {
66 // SAFETY: the safety invariant for self.header implies that of _.header
67 header: self.header,
68 // SAFETY: the start we just calculated meets the safety invariant by definition
69 start,
70 // SAFETY: the safety invariant for self.len implies tha tof _.len
71 len: self.len,
72 _phantom: PhantomData,
73 }
74 }
75
76}
77
78impl<T: SrcSlice + ?Sized> UninitSrc<T> {
79
80 /// Returns the number of (uninitialized) elements in this `UninitSrc`.
81 /// Because `UninitSrc` pointers are always [root](crate#root),
82 /// this is also the total number of elements in this allocation.
83 ///
84 /// ```rust
85 /// use slice_rc::UninitSrc;
86 ///
87 /// let uninit = UninitSrc::<[i32]>::new(3);
88 /// assert_eq!(uninit.len(), 3);
89 /// ```
90 #[inline]
91 pub fn len(&self) -> usize {
92 self.len
93 }
94
95 /// Returns `true` if this `UninitSrc` has a length of `0`.
96 ///
97 /// ```rust
98 /// use slice_rc::UninitSrc;
99 ///
100 /// let a = UninitSrc::<[i32]>::new(3);
101 /// assert!(!a.is_empty());
102 ///
103 /// let b = UninitSrc::<[i32]>::new(0);
104 /// assert!(b.is_empty());
105 /// ```
106 #[inline]
107 pub fn is_empty(&self) -> bool {
108 self.len == 0
109 }
110
111}
112
113impl<T: Sized> UninitSrc<T> {
114
115 /// Constructs a new `UninitSrc` for a single value.
116 ///
117 /// ```rust
118 /// use slice_rc::{Src, UninitSrc};
119 ///
120 /// let uninit = UninitSrc::<i32>::single();
121 /// assert_eq!(uninit.as_slice().len(), 1);
122 /// ```
123 #[inline]
124 pub fn single() -> UninitSrc<T> {
125 let this = UninitSrc::<[T]>::new(1);
126 debug_assert_eq!(this.len, 1);
127 let this2 = UninitSrc {
128 // SAFETY: the safety invariant of this.header is the same as this2.header
129 header: this.header,
130 // SAFETY: the safety invariant of this.len is implies that of this2.len
131 len: (),
132 _phantom: PhantomData,
133 };
134 forget(this);
135 this2
136 }
137
138 /// Initializes this `UninitSrc` into an [`Src`] with the given value.
139 ///
140 /// ```rust
141 /// use slice_rc::{Src, UninitSrc};
142 ///
143 /// let uninit = UninitSrc::single();
144 /// let s: Src<_> = uninit.init(42);
145 /// assert_eq!(*s, 42);
146 /// assert_eq!(Src::root(&s).len(), 1);
147 /// ```
148 #[inline]
149 pub fn init(self, value: T) -> Src<T> {
150 UniqueSrc::into_shared(self.init_unique(value))
151 }
152
153 /// Initializes this `UninitSrc` into a [`UniqueSrc`] with the given value.
154 ///
155 /// ```rust
156 /// use slice_rc::{UninitSrc, UniqueSrc};
157 ///
158 /// let uninit = UninitSrc::single();
159 /// let s: UniqueSrc<_> = uninit.init_unique(42);
160 /// assert_eq!(*s, 42);
161 /// ```
162 pub fn init_unique(self, value: T) -> UniqueSrc<T> {
163 // SAFETY:
164 // * all constructor fns for UninitSrc<T> initialize self.header from InnerHeader::new_inner::<T>
165 // * the header is only accessed from InnerHeader::get_header
166 let start = unsafe { InnerHeader::get_body_ptr::<T>(self.header) };
167 // SAFETY: no one else has seen the body of the allocation (because the weaks only look at the header after the strong count has been initialized), so this write is okay
168 unsafe { start.write(value); }
169 let this = UniqueSrc {
170 // SAFETY: the safety invariant of self.header implies that of this.header
171 header: self.header,
172 // SAFETY: after being initialized by start.write(_), the safety invariant of this.start is fulfilled by definition
173 start,
174 // SAFETY: the safety invariant of self.len implies that of this.len
175 len: self.len,
176 _phantom: PhantomData,
177 };
178 forget(self); // don't drop the weak held by the UninitSrc; it logically transfers to the Src
179 this
180 }
181
182 /// Returns a `UninitSrc` equivalent to this one, but typed as a slice rather than a single element.
183 /// 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.
184 ///
185 /// ```rust
186 /// use slice_rc::{UninitSrc, WeakSrc};
187 ///
188 /// let single = UninitSrc::<i32>::single();
189 /// let single_weak: WeakSrc<i32> = single.downgrade();
190 /// let slice = single.as_slice();
191 /// let slice_weak: WeakSrc<[i32]> = slice.downgrade();
192 /// assert!(WeakSrc::ptr_eq(&single_weak, &slice_weak));
193 /// ```
194 #[inline]
195 pub fn as_slice(self) -> UninitSrc<[T]> {
196 let this = UninitSrc {
197 // SAFETY: the safety invariant of self.header is the same as this.header
198 header: self.header,
199 // SAFETY: the safety invariant of self.len implies that of this.len
200 len: 1,
201 _phantom: PhantomData,
202 };
203 forget(self); // don't modify the weak count because this is logically the same UninitSrc
204 this
205 }
206
207}
208
209impl<T> UninitSrc<[T]> {
210
211 /// Constructs a new `UninitSrc` for a slice of `len` values.
212 ///
213 /// ```rust
214 /// use slice_rc::UninitSrc;
215 ///
216 /// let uninit = UninitSrc::<[i32]>::new(3);
217 /// assert_eq!(uninit.len(), 3);
218 /// ```
219 #[inline]
220 pub fn new(len: usize) -> UninitSrc<[T]> {
221 let header = InnerHeader::new_inner::<T, AllocUninit>(len);
222 Self {
223 // SAFETY: the safety invariant of _.header is fulfilled by definition
224 header,
225 // SAFETY: the safety invariant of _.len is fulfilled by definition
226 len,
227 _phantom: PhantomData,
228 }
229 }
230
231 /// Initializes this `UninitSrc` into an [`Src`] where each element is produced by calling `f` with that element's index while walking forward through the slice.
232 ///
233 /// If `len == 0`, this produces an empty [`Src`] without ever calling `f`.
234 ///
235 /// ```rust
236 /// use slice_rc::UninitSrc;
237 ///
238 /// let uninit = UninitSrc::new(5);
239 /// let slice = uninit.init_from_fn(|i| i);
240 /// assert_eq!(*slice, [0, 1, 2, 3, 4]);
241 ///
242 /// let uninit2 = UninitSrc::new(8);
243 /// let slice2 = uninit2.init_from_fn(|i| i * 2);
244 /// assert_eq!(*slice2, [0, 2, 4, 6, 8, 10, 12, 14]);
245 ///
246 /// let bool_uninit = UninitSrc::new(5);
247 /// let bool_slice = bool_uninit.init_from_fn(|i| i % 2 == 0);
248 /// assert_eq!(*bool_slice, [true, false, true, false, true]);
249 /// ```
250 ///
251 /// You can also capture things, so you can use closures with mutable state.
252 /// The slice is generated in ascending index order, starting from the front and going towards the back.
253 /// ```rust
254 /// # use slice_rc::UninitSrc;
255 /// let uninit = UninitSrc::new(6);
256 /// let mut state = 1;
257 /// let s = uninit.init_from_fn(|_| { let x = state; state *= 2; x });
258 /// assert_eq!(*s, [1, 2, 4, 8, 16, 32]);
259 /// ```
260 ///
261 /// # Panics
262 ///
263 /// Panics if `f` panics; in this event, any elements that have been initialized will be properly dropped.
264 /// ```rust
265 /// # use slice_rc::UninitSrc;
266 /// # use std::cell::Cell;
267 /// thread_local! {
268 /// static DROPPED: Cell<usize> = Cell::new(0);
269 /// }
270 ///
271 /// struct Droppable;
272 ///
273 /// impl Drop for Droppable {
274 /// fn drop(&mut self) {
275 /// DROPPED.with(|dropped| dropped.update(|x| x + 1));
276 /// }
277 /// }
278 ///
279 /// let _ = std::panic::catch_unwind(move || {
280 /// let uninit = UninitSrc::new(10);
281 /// uninit.init_from_fn(|i| {
282 /// if i >= 5 { panic!() }
283 /// Droppable
284 /// })
285 /// });
286 ///
287 /// assert_eq!(DROPPED.get(), 5);
288 /// ```
289 #[inline]
290 pub fn init_from_fn<F: FnMut(usize) -> T>(self, f: F) -> Src<[T]> {
291 UniqueSrc::into_shared(self.init_unique_from_fn(f))
292 }
293
294 /// Initializes this `UninitSrc` into a [`UniqueSrc`] where each element is produced by calling `f` with that element's index while walking forward through the slice.
295 ///
296 /// If `len == 0`, this produces an empty [`UniqueSrc`] without ever calling `f`.
297 ///
298 /// ```rust
299 /// use slice_rc::UninitSrc;
300 ///
301 /// let uninit = UninitSrc::new(5);
302 /// let slice = uninit.init_unique_from_fn(|i| i);
303 /// assert_eq!(*slice, [0, 1, 2, 3, 4]);
304 ///
305 /// let uninit2 = UninitSrc::new(8);
306 /// let slice2 = uninit2.init_unique_from_fn(|i| i * 2);
307 /// assert_eq!(*slice2, [0, 2, 4, 6, 8, 10, 12, 14]);
308 ///
309 /// let bool_uninit = UninitSrc::new(5);
310 /// let bool_slice = bool_uninit.init_unique_from_fn(|i| i % 2 == 0);
311 /// assert_eq!(*bool_slice, [true, false, true, false, true]);
312 /// ```
313 ///
314 /// You can also capture things, so you can use closures with mutable state.
315 /// The slice is generated in ascending index order, starting from the front and going towards the back.
316 /// ```rust
317 /// # use slice_rc::UninitSrc;
318 /// let uninit = UninitSrc::new(6);
319 /// let mut state = 1;
320 /// let s = uninit.init_unique_from_fn(|_| { let x = state; state *= 2; x });
321 /// assert_eq!(*s, [1, 2, 4, 8, 16, 32]);
322 /// ```
323 ///
324 /// # Panics
325 ///
326 /// Panics if `f` panics; in this event, any elements that have been initialized will be properly dropped.
327 /// ```rust
328 /// # use slice_rc::UninitSrc;
329 /// # use std::cell::Cell;
330 /// thread_local! {
331 /// static DROPPED: Cell<usize> = Cell::new(0);
332 /// }
333 ///
334 /// struct Droppable;
335 ///
336 /// impl Drop for Droppable {
337 /// fn drop(&mut self) {
338 /// DROPPED.with(|dropped| dropped.update(|x| x + 1));
339 /// }
340 /// }
341 ///
342 /// let _ = std::panic::catch_unwind(move || {
343 /// let uninit = UninitSrc::new(10);
344 /// uninit.init_unique_from_fn(|i| {
345 /// if i >= 5 { panic!() }
346 /// Droppable
347 /// })
348 /// });
349 ///
350 /// assert_eq!(DROPPED.get(), 5);
351 /// ```
352 pub fn init_unique_from_fn<F: FnMut(usize) -> T>(self, mut f: F) -> UniqueSrc<[T]> {
353 let header = self.header();
354 // SAFETY:
355 // * all constructor fns for UninitSrc<T> initialize self.header from InnerHeader::new_inner::<T>
356 // * the header is only accessed from InnerHeader::get_header
357 let start = unsafe { InnerHeader::get_body_ptr::<T>(self.header) };
358 let mut guard = PartialInitGuard::<T> { header: self.header, initialized: 0, _phantom: PhantomData };
359 for i in 0..header.len() {
360 // SAFETY:
361 // * all constructor fns for UninitSrc<T> initialize self.header from InnerHeader::new_inner::<T>
362 // * the header is only accessed from InnerHeader::get_header
363 let ptr = unsafe { InnerHeader::get_elem_ptr::<T>(self.header, i) };
364 let val = f(i);
365 // SAFETY: no one else has seen the body of the allocation (because the weaks only look at the header after the strong count has been initialized), so this write is okay
366 unsafe { ptr.write(val) };
367 guard.initialized += 1;
368 }
369 // if all elements are successfully initialized, then forget the drop guard; in other words, the guard only drops the contents if a panic occurs part way through initialization
370 forget(guard);
371 let this = UniqueSrc {
372 // SAFETY: the safety invariant of self.header is the same as this.header
373 header: self.header,
374 // SAFETY: after a successful initialization, the safety invariant of this.start is fulfilled by definition
375 start,
376 // SAFETY: the safety invariant of self.len is the same as this.len
377 len: self.len,
378 _phantom: PhantomData,
379 };
380 forget(self); // don't drop the weak held by the UninitSrc; it logically transfers to the Src
381 this
382 }
383
384 /// Initializes this `UninitSrc` into an [`Src`] where each element is the type's [default](Default::default).
385 ///
386 /// This method is essentially equivalent to <code>self.[init_from_fn](UninitSrc::init_from_fn)(|_| [Default::default]\())</code>.
387 #[inline]
388 pub fn init_from_default(self) -> Src<[T]> where T: Default {
389 self.init_from_fn(|_| T::default())
390 }
391
392 /// Initializes this `UninitSrc` into a [`UniqueSrc`] where each element is the type's [default](Default::default).
393 ///
394 /// This method is essentially equivalent to <code>self.[init_unique_from_fn](UninitSrc::init_unique_from_fn)(|_| [Default::default]\())</code>.
395 #[inline]
396 pub fn init_unique_from_default(self) -> UniqueSrc<[T]> where T: Default {
397 self.init_unique_from_fn(|_| T::default())
398 }
399
400 /// Initializes this `UninitSrc` into an [`Src`] where each element is a clone of `value`.
401 ///
402 /// This method is essentially equivalent to <code>self.[init_from_fn](UninitSrc::init_from_fn)(|_| value.[Clone::clone]\())</code>.
403 #[inline]
404 pub fn init_filled(self, value: &T) -> Src<[T]> where T: Clone {
405 self.init_from_fn(|_| value.clone())
406 }
407
408 /// Initializes this `UninitSrc` into an [`UniqueSrc`] where each element is a clone of `value`.
409 ///
410 /// This method is essentially equivalent to <code>self.[init_unique_from_fn](UninitSrc::init_unique_from_fn)(|_| value.[Clone::clone]\())</code>.
411 #[inline]
412 pub fn init_unique_filled(self, value: &T) -> UniqueSrc<[T]> where T: Clone {
413 self.init_unique_from_fn(|_| value.clone())
414 }
415
416}
417
418impl<T: SrcTarget + ?Sized> Debug for UninitSrc<T> {
419
420 #[inline]
421 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
422 write!(f, "(UninitSrc)")
423 }
424
425}
426
427impl<T: SrcTarget + ?Sized> Pointer for UninitSrc<T> {
428
429 #[inline]
430 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
431 // SAFETY:
432 // * all constructor fns for Src initialize header from InnerHeader::new_inner::<T::Item>
433 // * the header is only accessed from InnerHeader::get_header
434 // NOTE: the body is not expected to be initialized, but it is also not used
435 let start = unsafe { InnerHeader::get_body_ptr::<T::Item>(self.header) };
436 Pointer::fmt(&start, f)
437 }
438
439}
440
441impl<T: SrcTarget + ?Sized> Drop for UninitSrc<T> {
442
443 fn drop(&mut self) {
444 // SAFETY:
445 // * all constructor fns for UninitSrc initialize header from InnerHeader::new_inner::<T::Item>
446 // * the header is only accessed from InnerHeader::get_header
447 // NOTE: the UninitSrc logically holds one weak reference
448 unsafe { InnerHeader::drop_weak::<T::Item>(self.header); }
449 }
450
451}
452
453struct PartialInitGuard<T> {
454
455 header: NonNull<InnerHeader>,
456 initialized: usize,
457 _phantom: PhantomData<*const T>,
458
459}
460
461impl<T> Drop for PartialInitGuard<T> {
462
463 fn drop(&mut self) {
464 // SAFETY:
465 // * by the contract of this type, self.header is from an initialization fn from UninitSrc; all constructor fns for UninitSrc<T> initialize self.header from InnerHeader::new_inner::<T>
466 // * by the contract of this type, the first self.initialized elements have been initialized
467 // * the header is only accessed from InnerHeader::get_header
468 // * by the contract of this type, self.header is from an initialization fn from UninitSrc that is panicking; therefore, no one else has seen or will see the body
469 unsafe { InnerHeader::drop_body_up_to::<T>(self.header, self.initialized); }
470 }
471
472}
473
474#[cfg(test)]
475mod tests {
476
477 use std::{cell::Cell, ops::Deref, panic::{catch_unwind, AssertUnwindSafe}};
478 use crate::*;
479
480 #[test]
481 fn downgrade() {
482 let u: UninitSrc<[u8]> = UninitSrc::new(3);
483 let w: WeakSrc<[u8]> = u.downgrade();
484 assert!(w.upgrade().is_none());
485 let s1: Src<[u8]> = u.init_from_default();
486 let s2: Src<[u8]> = w.upgrade().unwrap();
487 assert_eq!(s1, s2);
488 assert!(Src::ptr_eq(&s1, &s2));
489 }
490
491 #[test]
492 fn len() {
493 let u: UninitSrc<[u8]> = UninitSrc::new(0);
494 assert_eq!(u.len(), 0);
495 let u: UninitSrc<[u8]> = UninitSrc::new(1);
496 assert_eq!(u.len(), 1);
497 let u: UninitSrc<[u8]> = UninitSrc::new(17);
498 assert_eq!(u.len(), 17);
499 }
500
501 #[test]
502 fn is_empty() {
503 let u: UninitSrc<[u8]> = UninitSrc::new(0);
504 assert!(u.is_empty());
505 let u: UninitSrc<[u8]> = UninitSrc::new(1);
506 assert!(!u.is_empty());
507 let u: UninitSrc<[u8]> = UninitSrc::new(17);
508 assert!(!u.is_empty());
509 }
510
511 #[test]
512 fn single() {
513 let u: UninitSrc<u8> = UninitSrc::single();
514 let s: Src<u8> = u.init(42);
515 assert!(Src::is_root(&s));
516 let s: Src<[u8]> = Src::as_slice(&s);
517 assert_eq!(s.len(), 1);
518 }
519
520 #[test]
521 fn init() {
522 let u: UninitSrc<u8> = UninitSrc::single();
523 let s: Src<u8> = u.init(42);
524 assert_eq!(*s, 42);
525 }
526
527 #[test]
528 fn init_unique() {
529 let u: UninitSrc<u8> = UninitSrc::single();
530 let u: UniqueSrc<u8> = u.init_unique(42);
531 assert_eq!(*u, 42);
532 }
533
534 #[test]
535 fn as_slice() {
536 let u: UninitSrc<u8> = UninitSrc::single();
537 let u: UninitSrc<[u8]> = u.as_slice();
538 assert_eq!(u.len(), 1);
539 }
540
541 #[test]
542 fn new() {
543 let u: UninitSrc<[u8]> = UninitSrc::new(3);
544 let s: Src<[u8]> = u.init_from_fn(|i| i as _);
545 assert!(Src::is_root(&s));
546 assert_eq!(s.len(), 3);
547 }
548
549 #[test]
550 fn init_from_fn() {
551 { // normal
552 let u: UninitSrc<[u8]> = UninitSrc::new(3);
553 let s: Src<[u8]> = u.init_from_fn(|i| i as _);
554 assert_eq!(*s, [0, 1, 2]);
555 }
556 { // panic
557 let drop_flags: [_; 6] = std::array::from_fn(|_| AssertUnwindSafe(Cell::new(false)));
558 struct DropFlagger<'a>(&'a Cell<bool>);
559 impl Drop for DropFlagger<'_> {
560
561 fn drop(&mut self) {
562 self.0.update(|v| !v)
563 }
564
565 }
566 let _: Result<_, _> = catch_unwind(|| {
567 let u: UninitSrc<[DropFlagger<'_>]> = UninitSrc::new(drop_flags.len());
568 let _: Src<[DropFlagger<'_>]> = u.init_from_fn(|i| {
569 if i >= 3 { panic!() }
570 DropFlagger(&drop_flags[i])
571 });
572 });
573 assert!(drop_flags[..3].iter().map(Deref::deref).all(Cell::get));
574 assert!(!drop_flags[3..].iter().map(Deref::deref).any(Cell::get));
575 }
576 }
577
578 #[test]
579 fn init_unique_from_fn() {
580 { // normal
581 let u: UninitSrc<[u8]> = UninitSrc::new(3);
582 let u: UniqueSrc<[u8]> = u.init_unique_from_fn(|i| i as _);
583 assert_eq!(*u, [0, 1, 2]);
584 }
585 { // panic
586 let drop_flags: [_; 6] = std::array::from_fn(|_| AssertUnwindSafe(Cell::new(false)));
587 struct DropFlagger<'a>(&'a Cell<bool>);
588 impl Drop for DropFlagger<'_> {
589
590 fn drop(&mut self) {
591 self.0.update(|v| !v)
592 }
593
594 }
595 let _: Result<_, _> = catch_unwind(|| {
596 let u: UninitSrc<[DropFlagger<'_>]> = UninitSrc::new(drop_flags.len());
597 let _: UniqueSrc<[DropFlagger<'_>]> = u.init_unique_from_fn(|i| {
598 if i >= 3 { panic!() }
599 DropFlagger(&drop_flags[i])
600 });
601 });
602 assert!(drop_flags[..3].iter().map(Deref::deref).all(Cell::get));
603 assert!(!drop_flags[3..].iter().map(Deref::deref).any(Cell::get));
604 }
605 }
606
607 #[test]
608 fn init_from_default() {
609 let u: UninitSrc<[u8]> = UninitSrc::new(3);
610 let s: Src<[u8]> = u.init_from_default();
611 assert_eq!(*s, [0, 0, 0]);
612 }
613
614 #[test]
615 fn init_unique_from_default() {
616 let u: UninitSrc<[u8]> = UninitSrc::new(3);
617 let u: UniqueSrc<[u8]> = u.init_unique_from_default();
618 assert_eq!(*u, [0, 0, 0]);
619 }
620
621 #[test]
622 fn init_filled() {
623 let u: UninitSrc<[u8]> = UninitSrc::new(3);
624 let s: Src<[u8]> = u.init_filled(&42);
625 assert_eq!(*s, [42, 42, 42]);
626 }
627
628 #[test]
629 fn init_unique_filled() {
630 let u: UninitSrc<[u8]> = UninitSrc::new(3);
631 let u: UniqueSrc<[u8]> = u.init_unique_filled(&42);
632 assert_eq!(*u, [42, 42, 42]);
633 }
634
635 #[test]
636 fn drop() {
637 let u: UninitSrc<[u8]> = UninitSrc::new(3);
638 let w: WeakSrc<[u8]> = u.downgrade();
639 assert!(w.upgrade().is_none());
640 std::mem::drop(u);
641 assert!(w.upgrade().is_none());
642 }
643
644}