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}