slice_rc/weak.rs
1use std::{fmt::{self, Debug, Formatter, Pointer}, marker::PhantomData, mem::forget, num::NonZero, ops::Bound, ptr::NonNull};
2
3use crate::{inner::InnerHeader, Src, SrcSlice, SrcTarget, WeakSrcIndex};
4
5const fn non_null_max<T>() -> NonNull<T> {
6 NonNull::without_provenance(NonZero::<usize>::MAX)
7}
8
9/// `WeakSrc` is a version of [`Src`] that holds a non-owning reference to the managed allocation.
10///
11/// 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`].
12///
13/// The allocation is accessed by calling [`upgrade`](WeakSrc::upgrade) on the `WeakSrc` pointer, which returns an <code>[Option]<[Src]\<T>></code>.
14///
15/// Since a `WeakSrc` pointer does not count toward ownership, it will not prevent the value stored in the allocation from being dropped,
16/// and `WeakSrc` itself makes no guarantees about the value still being present. Thus it may return `None` when `upgrade`d.
17/// Note however that a `WeakSrc` *does* prevent the allocation itself (the backing store) from being deallocated.
18///
19/// A `WeakSrc` pointer is useful for keeping a temporary reference to the allocation managed by `Src` without preventing its inner value from being dropped.
20/// It is also used to prevent circular references between `Src` pointers, since mutual owning references would never allow either `Src` to be dropped.
21/// For example, a tree could have strong `Src` pointers from parent nodes to children, and `WeakSrc` pointers from children back to their parents.
22///
23/// The typical way to obtain a `WeakSrc` pointer is to call [`Src::downgrade`].
24///
25/// # Dangling
26///
27/// [`WeakSrc::dangling`] allows constructing a "dangling" `WeakSrc` pointer;
28/// dangling `WeakSrc` pointers don't have a backing allocation, and as such, are guaranteed to return [`None`] from [`WeakSrc::upgrade`].
29/// Dangling `WeakSrc`s are considered [root](crate#root) and [empty](WeakSrc::is_empty).
30///
31/// `WeakSrc` pointers which are attached to an allocation are not considered dangling,
32/// even if that allocation has been dropped or the `WeakSrc` is otherwise un-[upgrade](WeakSrc::upgrade)able.
33///
34/// [crate-level documentation]: crate#how-do-this-crates-types-differ-from-the-stdrc-ones
35pub struct WeakSrc<T: SrcTarget + ?Sized> {
36
37 // SAFETY:
38 // requires:
39 // * initialized from InnerHeader::new_inner::<T::Item>(_) or non_null_max::<ItemHeader>()
40 pub(crate) header: NonNull<InnerHeader>,
41 // SAFETY:
42 // requires:
43 // * either:
44 // * initialized from either InnerHeader::get_body_ptr::<T::Item>(self.header) or InnerHeader::get_elem_ptr::<T::Item>(self.header, i) where 0 <= i <= InnerHeader::get_header(self.header).len()
45 // * all body elements have been properly initialized (e.g., self.start.as_ref() will not cause UB), or strong_count == 0
46 // * or, iff self.header is non_null_max::<ItemHeader>(), then self.start is non_null_max::<T::Item>()
47 pub(crate) start: NonNull<T::Item>,
48 // SAFETY:
49 // only applies if self.header != non_null_max::<ItemHeader>():
50 // requires when T: SrcSlice:
51 // * self.start.add(self.len) <= InnerHeader::get_body_ptr::<T::Item>(self.header).add(InnerHeader::get_header(self.header).len())
52 // requires when T: Sized:
53 // * self.start < InnerHeader::get_body_ptr::<T::Item>(self.header).add(InnerHeader::get_header(self.header).len())
54 pub(crate) len: T::Len,
55 pub(crate) _phantom: PhantomData<*const T>,
56
57}
58
59impl<T: SrcTarget + ?Sized> WeakSrc<T> {
60
61 // SAFETY:
62 // requires:
63 // * this weak is not dangling
64 unsafe fn header(&self) -> &InnerHeader {
65 // SAFETY:
66 // * all constructor fns for Src and UniinitSrc initialize header from InnerHeader::new_inner::<T::Item>; a WeakSrc must be constructed either from a Src, an UninitSrc, or must be dangling; the safety requirement that this is not the lattermost is passed on to the caller
67 // * the header is only accessed from InnerHeader::get_header
68 unsafe { InnerHeader::get_header(self.header) }
69 }
70
71 /// Constructs a new [dangling](WeakSrc#dangling) `WeakSrc`.
72 ///
73 /// # Examples
74 ///
75 /// ```rust
76 /// use slice_rc::WeakSrc;
77 ///
78 /// let dangling = WeakSrc::<i32>::dangling();
79 ///
80 /// assert!(dangling.is_dangling());
81 /// ```
82 #[inline]
83 pub fn dangling() -> WeakSrc<T> {
84 WeakSrc {
85 header: non_null_max(),
86 start: non_null_max(),
87 len: T::Len::default(),
88 _phantom: PhantomData,
89 }
90 }
91
92 /// Returns `true` if this `WeakSrc` is [dangling](WeakSrc#dangling).
93 /// This only returns `true` for `WeakSrc`s that were constructed from [`WeakSrc::dangling`];
94 /// `WeakSrc`s that are un-[upgrade](WeakSrc::upgrade)able for other reasons are not considered dangling,
95 /// and therefore this method returns `false` for those cases.
96 ///
97 /// # Examples
98 ///
99 /// ```rust
100 /// use slice_rc::WeakSrc;
101 ///
102 /// let dangling = WeakSrc::<i32>::dangling();
103 ///
104 /// assert!(dangling.is_dangling());
105 /// ```
106 ///
107 /// Not dangling:
108 ///
109 /// ```rust
110 /// # use slice_rc::Src;
111 /// let s = Src::single(42);
112 /// let w = Src::downgrade(&s);
113 /// drop(s);
114 ///
115 /// assert!(!w.is_dangling());
116 /// assert!(w.upgrade().is_none());
117 /// ```
118 #[inline]
119 pub fn is_dangling(&self) -> bool {
120 self.header == non_null_max()
121 }
122
123 /// Attempts to upgrade the `WeakSrc` pointer to an [`Src`], delaying dropping the inner value if successful.
124 ///
125 /// Returns [`None`] if the inner value has since been dropped,
126 /// if the inner value is uniquely owned by a [`UniqueSrc`](crate::UniqueSrc),
127 /// or if the inner value is uninitialized via [`UninitSrc`](crate::UninitSrc) or one of the cyclic helper methods, e.g. [`Src::cyclic_from_fn`].
128 ///
129 /// # Examples
130 ///
131 /// ```rust
132 /// use slice_rc::Src;
133 ///
134 /// let five = Src::single(5);
135 ///
136 /// let weak_five = Src::downgrade(&five);
137 ///
138 /// let strong_five = weak_five.upgrade();
139 /// assert!(strong_five.is_some());
140 ///
141 /// drop(strong_five);
142 /// drop(five);
143 ///
144 /// assert!(weak_five.upgrade().is_none());
145 /// ```
146 pub fn upgrade(&self) -> Option<Src<T>> {
147 if self.is_dangling() {
148 return None
149 }
150 // SAFETY: we just checked that this weak is not dangling
151 let header = unsafe { self.header() };
152 if header.strong_count() == 0 {
153 return None
154 }
155 header.inc_strong_count();
156 Some(Src {
157 // SAFETY: if this weak is not dangling (which we checked earlier), then this self.header has the same safety invariant as _.header
158 header: self.header,
159 // SAFETY: if this weak is not dangling (which we checked earlier), then this self.start has the same safety invariant as _.start
160 start: self.start,
161 // SAFETY: if this weak is not dangling (which we checked earlier), then this self.len has the same safety invariant as _.len
162 len: self.len,
163 _phantom: PhantomData,
164 })
165 }
166
167 /// Returns `true` if the two `WeakSrc`s point to slices starting at the same location in memory or are both [dangling](WeakSrc#dangling), akin to [`ptr::eq`](std::ptr::eq).
168 ///
169 /// ```rust
170 /// use slice_rc::{Src, WeakSrc};
171 ///
172 /// let slice = Src::from_array([1, 2, 3]);
173 /// let weak_slice = Src::downgrade(&slice);
174 /// let same_weak_slice = weak_slice.clone();
175 /// let weak_sub_slice = weak_slice.slice(1..);
176 /// let other_slice = Src::from_array([1, 2, 3]);
177 /// let other_weak_slice = Src::downgrade(&other_slice);
178 ///
179 /// assert!(WeakSrc::ptr_eq(&weak_slice, &same_weak_slice));
180 /// assert!(!WeakSrc::ptr_eq(&weak_slice, &weak_sub_slice));
181 /// assert!(!WeakSrc::ptr_eq(&weak_slice, &other_weak_slice));
182 /// ```
183 ///
184 /// If `WeakSrc::ptr_eq(&a, &b)` returns true, then <code>WeakSrc::[same_root](WeakSrc::same_root)(&a, &b)</code> will also be true.
185 ///
186 /// The type parameter, `U`, is to allow `WeakSrc`s of different types that _could_ be of the same allocation, and therefore, _could_ be equal by pointer, to be compared, e.g.:
187 /// ```rust
188 /// # use slice_rc::{Src, WeakSrc};
189 /// let strong: Src<i32> = Src::single(4);
190 /// let single: WeakSrc<i32> = Src::downgrade(&strong);
191 /// let slice: WeakSrc<[i32]> = single.as_slice();
192 ///
193 /// assert!(WeakSrc::ptr_eq(&single, &slice));
194 /// ```
195 ///
196 /// Note that this method currently ignores the length of the slice:
197 /// ```rust
198 /// # use slice_rc::{Src, WeakSrc};
199 /// let root_strong = Src::from_array([1, 2, 3]);
200 /// let root = Src::downgrade(&root_strong);
201 /// let first = root.slice(0);
202 ///
203 /// assert!(WeakSrc::ptr_eq(&root, &first));
204 ///
205 /// let mid_to_end_slice = root.slice(1..);
206 /// let mid_slice = root.slice(1..=1);
207 ///
208 /// assert!(WeakSrc::ptr_eq(&mid_to_end_slice, &mid_slice));
209 /// ```
210 /// It is undecided whether this behavior is desireable, and as such, it may change;
211 /// notably, [`Weak::ptr_eq`](std::rc::Weak::ptr_eq) does ignore metadata for `?Sized` types
212 /// (though that's irrelevant for slices because [`Weak`]s can only point to the whole slice, and therefore the length will always be the same for [`Weak`]s that point to the same allocation),
213 /// while [`ptr::eq`](std::ptr::eq) does consider the metadata (which causes inconsistent results for trait objects, but that is irrelevant here because `WeakSrc`s don't support trait objects).
214 ///
215 /// See also [`WeakSrc::same_root`].
216 ///
217 /// [`Weak`]: std::rc::Weak
218 #[inline]
219 pub fn ptr_eq<U: SrcTarget<Item = T::Item> + ?Sized>(&self, other: &WeakSrc<U>) -> bool {
220 self.start == other.start
221 }
222
223 /// Returns `true` if the two `WeakSrc`s share the same [root](crate#root) (i.e., they point to parts of the same allocation) or are both [dangling](WeakSrc#dangling).
224 ///
225 /// ```rust
226 /// use slice_rc::{Src, WeakSrc};
227 ///
228 /// let slice = Src::from_array([1, 2, 3]);
229 /// let weak_slice = Src::downgrade(&slice);
230 /// let same_weak_slice = weak_slice.clone();
231 /// let other_slice = Src::from_array([1, 2, 3]);
232 /// let other_weak_slice = Src::downgrade(&other_slice);
233 ///
234 /// assert!(WeakSrc::same_root(&weak_slice, &same_weak_slice));
235 /// assert!(!WeakSrc::same_root(&weak_slice, &other_weak_slice));
236 /// ```
237 ///
238 /// Notably, neither slice has to be the root, nor do they need to overlap at all:
239 /// ```rust
240 /// # use slice_rc::{Src, WeakSrc};
241 /// let strong = Src::from_array([1, 2, 3]);
242 /// let root = Src::downgrade(&strong);
243 /// let a = root.slice(..1);
244 /// let b = root.slice(2..);
245 ///
246 /// assert!(WeakSrc::same_root(&a, &b));
247 /// ```
248 ///
249 /// The type parameter, `U`, is to allow `WeakSrc`s of different types that _could_ share the same root, to be compared, e.g.:
250 /// ```rust
251 /// # use slice_rc::{Src, WeakSrc};
252 /// let strong: Src<i32> = Src::single(4);
253 /// let single: WeakSrc<i32> = Src::downgrade(&strong);
254 /// let slice: WeakSrc<[i32]> = single.as_slice();
255 ///
256 /// assert!(WeakSrc::same_root(&single, &slice));
257 /// ```
258 ///
259 /// This method ignores the length of the slices in question, but unlike [`WeakSrc::ptr_eq`], this will not change,
260 /// as the roots remains the same regardless of which parts of it are included in these slices.
261 ///
262 /// See also [`WeakSrc::ptr_eq`], [`WeakSrc::is_root`], and [`WeakSrc::root`].
263 #[inline]
264 pub fn same_root<U: SrcTarget<Item = T::Item> + ?Sized>(&self, other: &WeakSrc<U>) -> bool {
265 self.header == other.header
266 }
267
268 /// Returns `true` if this `WeakSrc` contains its [root](crate#root) (i.e., it references its entire allocation), or is [dangling](WeakSrc#dangling).
269 /// Notably, this `WeakSrc` does not have to be the first one that was initialized, it just has to cover the entire allocation.
270 ///
271 /// ```rust
272 /// use slice_rc::Src;
273 ///
274 /// let strong = Src::from_array([1, 2, 3]);
275 /// let root = Src::downgrade(&strong);
276 /// let also_root = root.slice(..);
277 /// let slice = root.slice(1..);
278 ///
279 /// assert!(root.is_root());
280 /// assert!(also_root.is_root());
281 /// assert!(!slice.is_root());
282 /// ```
283 ///
284 /// See also [`WeakSrc::same_root`] and [`WeakSrc::root`].
285 #[inline]
286 pub fn is_root(&self) -> bool {
287 if self.is_dangling() {
288 return true
289 }
290 // SAFETY: we just checked that this weak is not dangling
291 let header = unsafe { self.header() };
292 // SAFETY:
293 // * all constructor fns for Src initialize header from InnerHeader::new_inner::<T::Item>
294 // * the header is only accessed from InnerHeader::get_header
295 let root_start = unsafe { InnerHeader::get_body_ptr(self.header) };
296 self.start == root_start && T::len_as_usize(self.len) == header.len()
297 }
298
299 /// Gets the number of strong ([`Src`]) pointers pointing to this allocation.
300 ///
301 /// If `self` is [dangling](WeakSrc#dangling), this will return `0`.
302 pub fn strong_count(&self) -> usize {
303 if !self.is_dangling() {
304 // SAFETY: we just checked that this weak is not dangling
305 unsafe { self.header() }.strong_count()
306 } else {
307 0
308 }
309 }
310
311 /// Gets the number of `WeakSrc` pointers pointing to this allocation.
312 ///
313 /// If no strong pointers remain (or this `WeakSrc` is otherwise un-[upgrade](WeakSrc::upgrade)able), this will return `0`.
314 pub fn weak_count(&self) -> usize {
315 if !self.is_dangling() {
316 // SAFETY: we just checked that this weak is not dangling
317 let header = unsafe { self.header() };
318 if header.strong_count() > 0 {
319 header.weak_count() - 1 // subtract implicit weak held by strongs
320 } else {
321 0
322 }
323 } else {
324 0
325 }
326 }
327
328 /// Returns a `WeakSrc` pointer that refers to this `WeakSrc`'s [root](crate#root) (i.e., the entire allocation).
329 /// ```rust
330 /// use slice_rc::Src;
331 ///
332 /// let strong = Src::from_array([1, 2, 3]);
333 /// let root = Src::downgrade(&strong);
334 /// let slice = root.slice(1..);
335 /// drop(root);
336 ///
337 /// assert_eq!(*slice.upgrade().unwrap(), [2, 3]);
338 ///
339 /// let new_root = slice.root();
340 ///
341 /// assert_eq!(*new_root.upgrade().unwrap(), [1, 2, 3]);
342 /// ```
343 ///
344 /// This method returns a <code>[WeakSrc]\<\[T::[Item](crate::SrcTarget::Item)]></code> rather than a <code>[WeakSrc]\<T></code> for two reasons:
345 /// * If <code>T: [Sized]</code>, then the root can only be a <code>[WeakSrc]\<T></code> if its total length is is `1`, which would prevent situations like this:
346 /// ```rust
347 /// # use slice_rc::{Src, WeakSrc};
348 /// let strong = Src::from_array([1, 2, 3]);
349 /// let root: WeakSrc<[i32]> = Src::downgrade(&strong);
350 /// let slice: WeakSrc<i32> = root.slice(1);
351 /// let new_root: WeakSrc<[i32]> = slice.root();
352 ///
353 /// assert_eq!(*new_root.upgrade().unwrap(), [1, 2, 3]);
354 /// ```
355 /// * If <code>T = [str]</code>, 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`]:
356 /// ```rust
357 /// # use slice_rc::{Src, WeakSrc};
358 /// let root: Src<[u8]> = Src::copied(b"\xFFhello");
359 /// let weak_root: WeakSrc<[u8]> = Src::downgrade(&root);
360 /// let s: Src<str> = Src::from_utf8(root.slice(1..)).unwrap();
361 /// let weak_s: WeakSrc<str> = Src::downgrade(&s);
362 /// let new_weak_root: WeakSrc<[u8]> = weak_s.root();
363 ///
364 /// assert_eq!(&*weak_s.upgrade().unwrap(), "hello");
365 /// assert!(Src::from_utf8(new_weak_root.upgrade().unwrap()).is_err());
366 /// ```
367 pub fn root(&self) -> WeakSrc<[T::Item]> {
368 if self.is_dangling() {
369 return WeakSrc::dangling()
370 }
371 // SAFETY: we just checked that this weak is not dangling
372 let header = unsafe { self.header() };
373 // SAFETY:
374 // * all constructor fns for Src and UninitSrc initialize header from InnerHeader::new_inner::<T::Item>; a WeakSrc must be constructed either from a Src, an UninitSrc, or must be dangling; we just checked that this weak is not dangling
375 // * the header is only accessed from InnerHeader::get_header
376 let start = unsafe { InnerHeader::get_body_ptr(self.header) };
377 header.inc_weak_count();
378 WeakSrc {
379 // SAFETY: this self.header has the same safety invariant as this.header
380 header: self.header,
381 // SAFETY: if this weak is not dangling (which we checked earlier), the start that we just calculated earlier meets the safety invariant by definition
382 start,
383 // SAFETY: if this weak is not dangling (which we checked earlier), header.len() meets the safety invariant by definition
384 len: header.len(),
385 _phantom: PhantomData,
386 }
387 }
388
389}
390
391impl<T: SrcSlice + ?Sized> WeakSrc<T> {
392
393 /// Returns the numeber of elements in this `WeakSrc`. If `self` is [dangling](WeakSrc#dangling), returns `0`.
394 ///
395 /// This method only returns the length of the whole allocation if `self` is a [root](crate#root) `WeakSrc`.
396 ///
397 /// ```rust
398 /// use slice_rc::Src;
399 ///
400 /// let s = Src::from_array([1, 2, 3]);
401 /// let w = Src::downgrade(&s);
402 /// assert_eq!(w.len(), 3);
403 /// ```
404 #[inline]
405 pub fn len(&self) -> usize {
406 self.len
407 }
408
409 /// Returns `true` if this `WeakSrc` has a length of `0` or is [dangling](WeakSrc#dangling).
410 ///
411 /// ```rust
412 /// use slice_rc::Src;
413 ///
414 /// let a_strong = Src::from_array([1, 2, 3]);
415 /// let a = Src::downgrade(&a_strong);
416 /// assert!(!a.is_empty());
417 ///
418 /// let b_strong = Src::<[i32]>::from_array([]);
419 /// let b = Src::downgrade(&b_strong);
420 /// assert!(b.is_empty());
421 /// ```
422 #[inline]
423 pub fn is_empty(&self) -> bool {
424 self.len == 0
425 }
426
427}
428
429impl<T: Sized> WeakSrc<T> {
430
431 /// Returns a `WeakSrc` equivalent to this one, but typed as a slice rather than a single element.
432 /// 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.
433 ///
434 /// ```rust
435 /// use slice_rc::{Src, WeakSrc};
436 /// use std::ptr;
437 ///
438 /// let strong = Src::single(42);
439 /// let single = Src::downgrade(&strong);
440 /// let slice = single.as_slice();
441 ///
442 /// assert!(WeakSrc::ptr_eq(&single, &slice));
443 /// assert!(ptr::eq(&*single.upgrade().unwrap(), &slice.upgrade().unwrap()[0]));
444 /// ```
445 #[inline]
446 pub fn as_slice(&self) -> WeakSrc<[T]> {
447 if !self.is_dangling() {
448 // SAFETY: we just checked that this weak is not dangling
449 unsafe { self.header() }.inc_weak_count();
450 }
451 WeakSrc {
452 // SAFETY: the safety invariant of self.header is the same as this.header
453 header: self.header,
454 // SAFETY: the safety invariant of self.start is the same as this.start
455 start: self.start,
456 // SAFETY: if this weak is dangling, then self.len has no safety invariant; if it is weak, then the safety invariant of self.len is logically identical to that of this.len
457 len: 1,
458 _phantom: PhantomData,
459 }
460 }
461
462}
463
464impl<T> WeakSrc<[T]> {
465
466 /// Returns a `WeakSrc` pointer to an element or subslice depending on the type of index.
467 /// * If given a position (only applicable where `Self = WeakSrc<[U]>`), returns an `WeakSrc<U>` to the element at that position.
468 /// * If given a range, returns the subslice corresponding to that range.
469 ///
470 /// This method is only provided for <code>WeakSrc\<[\[T\]](prim@slice)></code>, not <code>WeakSrc\<[str]></code>;
471 /// this is because [`str`] requires analyzing the value to validate that the new range is falls on [char boundaries](str::is_char_boundary),
472 /// and therefore the `WeakStr` must be [`upgrade`](WeakSrc::upgrade)d to slice it.
473 /// On the other hand, this is an acceptable compromise because the primary use-case of this method is during cyclic initialization,
474 /// which is meaningless for [`str`].
475 ///
476 /// # Panics
477 /// If the index is in some way out of bounds.
478 /// Note that [dangling](WeakSrc#dangling) pointers are considered [empty](WeakSrc::is_empty).
479 ///
480 /// # Examples
481 /// ```rust
482 /// use slice_rc::Src;
483 ///
484 /// let v = Src::from_array([10, 40, 30]);
485 /// let weak = Src::downgrade(&v);
486 /// assert_eq!(Src::single(40), weak.slice(1).upgrade().unwrap());
487 /// assert_eq!(Src::from_array([10, 40]), weak.slice(0..2).upgrade().unwrap());
488 /// ```
489 /// Panics:
490 /// ```should_panic
491 /// # use slice_rc::Src;
492 /// let v = Src::from_array([10, 40, 30]);
493 /// let weak = Src::downgrade(&v);
494 /// let _ = weak.slice(3);
495 /// let _ = weak.slice(0..4);
496 /// ```
497 #[inline]
498 pub fn slice<I: WeakSrcIndex<[T]>>(&self, index: I) -> WeakSrc<I::Output> {
499 index.get_weak(self.clone())
500 }
501
502 pub(crate) fn into_item(self, index: usize) -> WeakSrc<T> {
503 let len = if self.is_dangling() {
504 0
505 } else {
506 // SAFETY: we just checked that this weak is not dangling
507 let header = unsafe { self.header() };
508 header.len()
509 };
510 assert!(index < len, "index {index} out of range for slice of length {}", len);
511 // SAFETY: the safety invariant of self.start implies this safety requirement, given the assertion that index <= header.len() and that this weak is not dangling
512 let start_ptr = unsafe { self.start.add(index) };
513 let this = WeakSrc {
514 // SAFETY: the safety invariant of self.header is the same as this.header
515 header: self.header,
516 // SAFETY: if this weak is not dangling (which we checked earlier), the start_ptr that we just calculated earlier meets the safety invariant by definition
517 start: start_ptr,
518 // SAFETY: if this weak is not dangling (which we checked earlier), the safety invariant is checked by the assertion above
519 len: (),
520 _phantom: PhantomData,
521 };
522 forget(self); // don't modify the weak count because this is logically the same WeakSrc
523 this
524 }
525
526 pub(crate) fn into_slice_from_bounds(self, start: Bound<usize>, end: Bound<usize>) -> WeakSrc<[T]> {
527 let len = if self.is_dangling() {
528 0
529 } else {
530 // SAFETY: we just checked that this weak is not dangling
531 let header = unsafe { self.header() };
532 header.len()
533 };
534 let start_inc = match start {
535 Bound::Excluded(val) => val + 1,
536 Bound::Included(val) => val,
537 Bound::Unbounded => 0,
538 };
539 let end_exc = match end {
540 Bound::Excluded(val) => val,
541 Bound::Included(val) => val + 1,
542 Bound::Unbounded => len,
543 };
544 assert!(start_inc <= end_exc, "slice index starts at {start_inc} but ends at {end_exc}");
545 assert!(end_exc <= len, "range end index {end_exc} out of range for slice of length {}", len);
546 let len = end_exc - start_inc;
547 // SAFETY: the safety invariant of self.start implies this safety requirement, given the assertion that start_inc <= header.len() and that this weak is not dangling
548 let start_ptr = unsafe { self.start.add(start_inc) };
549 let this = WeakSrc {
550 // SAFETY: the safety invariant of self.header is the same as this.header
551 header: self.header,
552 // SAFETY: if this weak is not dangling (which we checked earlier), the start_ptr that we just calculated earlier meets the safety invariant by definition
553 start: start_ptr,
554 // SAFETY: if this weak is not dangling (which we checked earlier), the safety invariant is checked by the assertions above
555 len,
556 _phantom: PhantomData,
557 };
558 forget(self); // don't modify the weak count because this is logically the same WeakSrc
559 this
560 }
561
562}
563
564impl<T: SrcTarget + ?Sized> Clone for WeakSrc<T> {
565
566 fn clone(&self) -> Self {
567 if !self.is_dangling() {
568 // SAFETY: we just checked that this weak is not dangling
569 unsafe { self.header() }.inc_weak_count();
570 }
571 Self {
572 // SAFETY: the safety invariant of self.header is the same as _.header
573 header: self.header,
574 // SAFETY: the safety invariant of self.start is the same as _.start
575 start: self.start,
576 // SAFETY: the safety invariant of self.len is the same as _.len
577 len: self.len,
578 _phantom: PhantomData,
579 }
580 }
581
582}
583
584impl<T: SrcTarget + ?Sized> Debug for WeakSrc<T> {
585
586 #[inline]
587 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
588 write!(f, "(WeakSrc)")
589 }
590
591}
592
593impl<T: SrcTarget + ?Sized> Pointer for WeakSrc<T> {
594
595 #[inline]
596 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
597 Pointer::fmt(&self.start, f)
598 }
599
600}
601
602impl<T: SrcTarget + ?Sized> Default for WeakSrc<T> {
603
604 #[inline]
605 fn default() -> Self {
606 Self::dangling()
607 }
608
609}
610
611impl<T: SrcTarget + ?Sized> Drop for WeakSrc<T> {
612
613 fn drop(&mut self) {
614 if !self.is_dangling() {
615 // SAFETY:
616 // * all constructor fns for Src initialize header from InnerHeader::new_inner::<T::Item>; WeakSrcs are either constructed from WeakSrc::dangling (which is covered by self.is_dangling()), or from a Src
617 // * the header is only accessed from InnerHeader::get_header
618 unsafe { InnerHeader::drop_weak::<T::Item>(self.header); }
619 }
620 }
621
622}
623
624#[cfg(test)]
625mod tests {
626
627 use std::cell::Cell;
628 use crate::*;
629
630 #[test]
631 fn dangling() {
632 let w: WeakSrc<[u8]> = WeakSrc::dangling();
633 assert!(w.is_dangling());
634 assert!(w.upgrade().is_none());
635 }
636
637 #[test]
638 fn is_dangling() {
639 { // dangling
640 let w: WeakSrc<[u8]> = WeakSrc::dangling();
641 assert!(w.is_dangling());
642 }
643 { // not dangling
644 let s: Src<[u8]> = Src::from_default(0);
645 let w: WeakSrc<[u8]> = Src::downgrade(&s);
646 assert!(!w.is_dangling());
647 std::mem::drop(s);
648 assert!(!w.is_dangling());
649 }
650 }
651
652 #[test]
653 fn upgrade() {
654 { // dangling
655 let w: WeakSrc<[u8]> = WeakSrc::dangling();
656 assert!(w.upgrade().is_none());
657 }
658 { // not dangling
659 let s1: Src<[u8]> = Src::from_default(0);
660 let w: WeakSrc<[u8]> = Src::downgrade(&s1);
661 let s2: Src<[u8]> = w.upgrade().unwrap();
662 assert!(Src::ptr_eq(&s1, &s2));
663 }
664 }
665
666 #[test]
667 fn ptr_eq() {
668 { // dangling
669 let w1: WeakSrc<[u8]> = WeakSrc::dangling();
670 let w2: WeakSrc<[u8]> = WeakSrc::dangling();
671 assert!(w1.ptr_eq(&w2));
672 }
673 { // not dangling, same root
674 let s: Src<[u8]> = Src::from_default(1);
675 let w1: WeakSrc<[u8]> = Src::downgrade(&s);
676 let w2: WeakSrc<[u8]> = w1.clone();
677 assert!(w1.ptr_eq(&w2));
678 let w3: WeakSrc<[u8]> = WeakSrc::dangling();
679 assert!(!w1.ptr_eq(&w3));
680 assert!(!w2.ptr_eq(&w3));
681 let w4: WeakSrc<[u8]> = Src::downgrade(&s).slice(1..);
682 let w5: WeakSrc<[u8]> = Src::downgrade(&s).slice(1..);
683 assert!(w4.ptr_eq(&w5));
684 assert!(!w4.ptr_eq(&w1));
685 assert!(!w4.ptr_eq(&w3));
686 }
687 { // not dangling, different roots
688 let s1: Src<[u8]> = Src::from_default(0);
689 let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
690 let s2: Src<[u8]> = Src::from_default(0);
691 let w2: WeakSrc<[u8]> = Src::downgrade(&s2);
692 assert!(!w1.ptr_eq(&w2));
693 let w3: WeakSrc<[u8]> = WeakSrc::dangling();
694 assert!(!w1.ptr_eq(&w3));
695 assert!(!w2.ptr_eq(&w3));
696 std::mem::drop((s1, s2));
697 assert!(!w1.ptr_eq(&w3));
698 assert!(!w2.ptr_eq(&w3));
699 }
700 }
701
702 #[test]
703 fn same_root() {
704 { // dangling
705 let w1: WeakSrc<[u8]> = WeakSrc::dangling();
706 let w2: WeakSrc<[u8]> = WeakSrc::dangling();
707 assert!(w1.same_root(&w2));
708 }
709 { // not dangling, same root
710 let s: Src<[u8]> = Src::from_default(1);
711 let w1: WeakSrc<[u8]> = Src::downgrade(&s);
712 let w2: WeakSrc<[u8]> = w1.clone();
713 assert!(w1.same_root(&w2));
714 let w3: WeakSrc<[u8]> = WeakSrc::dangling();
715 assert!(!w1.same_root(&w3));
716 assert!(!w2.same_root(&w3));
717 let w4: WeakSrc<[u8]> = Src::downgrade(&s).slice(1..);
718 assert!(w4.same_root(&w1));
719 assert!(!w4.same_root(&w3));
720 }
721 { // not dangling, different roots
722 let s1: Src<[u8]> = Src::from_default(0);
723 let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
724 let s2: Src<[u8]> = Src::from_default(0);
725 let w2: WeakSrc<[u8]> = Src::downgrade(&s2);
726 assert!(!w1.same_root(&w2));
727 let w3: WeakSrc<[u8]> = WeakSrc::dangling();
728 assert!(!w1.same_root(&w3));
729 assert!(!w2.same_root(&w3));
730 std::mem::drop((s1, s2));
731 assert!(!w1.same_root(&w3));
732 assert!(!w2.same_root(&w3));
733 }
734 }
735
736 #[test]
737 fn is_root() {
738 { // dangling
739 let w: WeakSrc<[u8]> = WeakSrc::dangling();
740 assert!(w.is_root());
741 }
742 {
743 let s: Src<[u8]> = Src::from_default(1);
744 let w1: WeakSrc<[u8]> = Src::downgrade(&s);
745 assert!(w1.is_root());
746 let w2: WeakSrc<[u8]> = Src::downgrade(&s).slice(1..);
747 assert!(!w2.is_root());
748 std::mem::drop(s);
749 assert!(w1.is_root());
750 assert!(!w2.is_root());
751 }
752 }
753
754 #[test]
755 fn strong_count() {
756 { // dangling
757 let w: WeakSrc<[u8]> = WeakSrc::dangling();
758 assert_eq!(w.strong_count(), 0);
759 }
760 { // not dangling
761 let s1: Src<[u8]> = Src::from_default(0);
762 let w: WeakSrc<[u8]> = Src::downgrade(&s1);
763 assert_eq!(w.strong_count(), 1);
764 let s2: Src<[u8]> = s1.clone();
765 assert_eq!(w.strong_count(), 2);
766 std::mem::drop(s1);
767 assert_eq!(w.strong_count(), 1);
768 std::mem::drop(s2);
769 assert_eq!(w.strong_count(), 0);
770 }
771 }
772
773 #[test]
774 fn weak_count() {
775 { // dangling
776 let w: WeakSrc<[u8]> = WeakSrc::dangling();
777 assert_eq!(w.weak_count(), 0);
778 }
779 { // not dangling
780 let s: Src<[u8]> = Src::from_default(0);
781 let w1: WeakSrc<[u8]> = Src::downgrade(&s);
782 assert_eq!(w1.weak_count(), 1);
783 let w2: WeakSrc<[u8]> = w1.clone();
784 assert_eq!(w1.weak_count(), 2);
785 assert_eq!(w2.weak_count(), 2);
786 let w3: WeakSrc<[u8]> = Src::downgrade(&s);
787 assert_eq!(w1.weak_count(), 3);
788 assert_eq!(w2.weak_count(), 3);
789 assert_eq!(w3.weak_count(), 3);
790 std::mem::drop(w1);
791 assert_eq!(w2.weak_count(), 2);
792 assert_eq!(w3.weak_count(), 2);
793 std::mem::drop(s);
794 assert_eq!(w2.weak_count(), 0);
795 assert_eq!(w3.weak_count(), 0);
796 }
797 }
798
799 #[test]
800 fn len() {
801 { // dangling
802 let w: WeakSrc<[u8]> = WeakSrc::dangling();
803 assert_eq!(w.len(), 0);
804 }
805 { // not dangling
806 let s: Src<[u8]> = Src::from_default(0);
807 let w: WeakSrc<[u8]> = Src::downgrade(&s);
808 assert_eq!(w.len(), 0);
809 let s: Src<[u8]> = Src::from_default(1);
810 let w: WeakSrc<[u8]> = Src::downgrade(&s);
811 assert_eq!(w.len(), 1);
812 let s: Src<[u8]> = Src::from_default(17);
813 let w: WeakSrc<[u8]> = Src::downgrade(&s);
814 assert_eq!(w.len(), 17);
815 let w: WeakSrc<[u8]> = w.slice(3..14);
816 assert_eq!(w.len(), 11);
817 let w: WeakSrc<[u8]> = w.slice(3..3);
818 assert_eq!(w.len(), 0);
819 }
820 }
821
822 #[test]
823 fn is_empty() {
824 { // dangling
825 let w: WeakSrc<[u8]> = WeakSrc::dangling();
826 assert!(w.is_empty());
827 }
828 { // not dangling
829 let s: Src<[u8]> = Src::from_default(0);
830 let w: WeakSrc<[u8]> = Src::downgrade(&s);
831 assert!(w.is_empty());
832 let s: Src<[u8]> = Src::from_default(1);
833 let w: WeakSrc<[u8]> = Src::downgrade(&s);
834 assert!(!w.is_empty());
835 let s: Src<[u8]> = Src::from_default(17);
836 let w: WeakSrc<[u8]> = Src::downgrade(&s);
837 assert!(!w.is_empty());
838 let w: WeakSrc<[u8]> = w.slice(3..14);
839 assert!(!w.is_empty());
840 let w: WeakSrc<[u8]> = w.slice(3..3);
841 assert!(w.is_empty());
842 }
843 }
844
845 #[test]
846 fn root() {
847 { // dangling
848 let w1: WeakSrc<[u8]> = WeakSrc::dangling();
849 let w2: WeakSrc<[u8]> = w1.root();
850 assert!(w2.is_root());
851 assert!(w1.ptr_eq(&w2));
852 }
853 { // not dangling
854 let s: Src<[u8]> = Src::from_default(1);
855 let w: WeakSrc<[u8]> = Src::downgrade(&s);
856 assert!(w.is_root());
857 let w: WeakSrc<[u8]> = w.slice(1..);
858 assert!(!w.is_root());
859 let w: WeakSrc<[u8]> = w.root();
860 assert!(w.is_root());
861 }
862 }
863
864 #[test]
865 fn slice() {
866 { // dangling
867 let w1: WeakSrc<[u8]> = WeakSrc::dangling();
868 let w2: WeakSrc<[u8]> = w1.slice(..);
869 assert!(WeakSrc::ptr_eq(&w1, &w2));
870 }
871 { // slice
872 let s1: Src<[u8]> = Src::from_array([1, 2, 3]);
873 let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
874 let s1: Src<[u8]> = w1.upgrade().unwrap();
875 assert_eq!(&*s1, &[1, 2, 3]);
876 let w1: WeakSrc<[u8]> = w1.slice(1..);
877 let s1: Src<[u8]> = w1.upgrade().unwrap();
878 assert_eq!(&*s1, &[2, 3]);
879 let w2: WeakSrc<[u8]> = w1.slice(..1);
880 let s2: Src<[u8]> = w2.upgrade().unwrap();
881 assert_eq!(&*s2, &[2]);
882 assert!(w1.same_root(&w2));
883 }
884 { // item 1
885 let s1: Src<[u8]> = Src::from_array([1, 2, 3]);
886 let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
887 let s1: Src<[u8]> = w1.upgrade().unwrap();
888 assert_eq!(&*s1, &[1, 2, 3]);
889 let w2: WeakSrc<u8> = w1.slice(2);
890 let s2: Src<u8> = w2.upgrade().unwrap();
891 assert_eq!(&*s2, &3);
892 let w2: WeakSrc<[u8]> = w2.as_slice();
893 let s2: Src<[u8]> = w2.upgrade().unwrap();
894 assert_eq!(&*s2, &[3]);
895 assert!(w1.same_root(&w2));
896 }
897 { // item 2
898 let s1: Src<[u8]> = Src::from_array([1, 2, 3]);
899 let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
900 let s1: Src<[u8]> = w1.upgrade().unwrap();
901 assert_eq!(&*s1, &[1, 2, 3]);
902 let w1: WeakSrc<[u8]> = w1.slice(1..);
903 let s1: Src<[u8]> = w1.upgrade().unwrap();
904 assert_eq!(&*s1, &[2, 3]);
905 let w2: WeakSrc<u8> = w1.slice(0);
906 let s2: Src<u8> = w2.upgrade().unwrap();
907 assert_eq!(&*s2, &2);
908 let w2: WeakSrc<[u8]> = w2.as_slice();
909 let s2: Src<[u8]> = w2.upgrade().unwrap();
910 assert_eq!(&*s2, &[2]);
911 assert!(w1.same_root(&w2));
912 }
913 }
914
915 #[test]
916 fn as_slice() {
917 { // dangling
918 let w: WeakSrc<u8> = WeakSrc::dangling();
919 let w: WeakSrc<[u8]> = w.as_slice();
920 assert!(w.is_dangling());
921 }
922 { // single root
923 let s1: Src<u8> = Src::single(42);
924 let w1: WeakSrc<u8> = Src::downgrade(&s1);
925 let w2: WeakSrc<[u8]> = w1.as_slice();
926 let s2: Src<[u8]> = w2.upgrade().unwrap();
927 assert_eq!([*s1], *s2);
928 }
929 { // from slice
930 let s1: Src<[u8]> = Src::from_array([1, 2, 3]);
931 let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
932 let w2: WeakSrc<u8> = w1.slice(1);
933 let s2: Src<u8> = w2.upgrade().unwrap();
934 let w3: WeakSrc<[u8]> = w2.as_slice();
935 let s3: Src<[u8]> = w3.upgrade().unwrap();
936 assert_eq!(s1[1], *s2);
937 assert_eq!([*s2], *s3);
938 }
939 }
940
941 #[test]
942 fn clone() {
943 { // dangling
944 let w1: WeakSrc<[u8]> = WeakSrc::dangling();
945 assert_eq!(w1.weak_count(), 0);
946 let w2: WeakSrc<[u8]> = w1.clone();
947 assert_eq!(w1.weak_count(), 0);
948 assert_eq!(w2.weak_count(), 0);
949 }
950 { // not dangling
951 let s1: Src<[u8]> = Src::from_array([1, 2, 3]);
952 let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
953 assert_eq!(w1.weak_count(), 1);
954 let w2: WeakSrc<[u8]> = w1.clone();
955 assert_eq!(w1.weak_count(), 2);
956 let s2: Src<[u8]> = w2.upgrade().unwrap();
957 assert_eq!(*s1, *s2);
958 assert!(w1.ptr_eq(&w2));
959 std::mem::drop((s1, s2));
960 assert_eq!(w1.weak_count(), 0);
961 }
962 }
963
964 #[test]
965 fn drop() {
966 let drop_flags: [_; 3] = std::array::from_fn(|_| Cell::new(false));
967 struct DropFlagger<'a>(&'a Cell<bool>);
968 impl Drop for DropFlagger<'_> {
969
970 fn drop(&mut self) {
971 self.0.update(|v| !v)
972 }
973
974 }
975 assert!(!drop_flags.iter().any(Cell::get));
976 let s: Src<[DropFlagger<'_>]> = Src::from_iter(drop_flags.iter().map(DropFlagger));
977 assert!(!drop_flags.iter().any(Cell::get));
978 let w1: WeakSrc<[DropFlagger<'_>]> = Src::downgrade(&s);
979 assert!(!drop_flags.iter().any(Cell::get));
980 assert_eq!(w1.weak_count(), 1);
981 let w2: WeakSrc<[DropFlagger<'_>]> = w1.clone();
982 assert!(!drop_flags.iter().any(Cell::get));
983 assert_eq!(w1.weak_count(), 2);
984 assert_eq!(w2.weak_count(), 2);
985 std::mem::drop(w1);
986 assert!(!drop_flags.iter().any(Cell::get));
987 assert_eq!(w2.weak_count(), 1);
988 std::mem::drop(s);
989 assert!(drop_flags.iter().all(Cell::get));
990 assert_eq!(w2.weak_count(), 0);
991 std::mem::drop(w2);
992 assert!(drop_flags.iter().all(Cell::get));
993 }
994
995}