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, SrcIndex, SrcSlice, SrcTarget};
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  /// Returns a `WeakSrc` pointer to an element or subslice depending on the type of index.
428  /// * If given a position (only applicable where `Self = WeakSrc<[U]>`), returns an `WeakSrc<U>` to the element at that position.
429  /// * If given a range, returns the subslice corresponding to that range.
430  /// 
431  /// # Panics
432  /// If the index is in some way out of bounds, or if <code>Self = WeakSrc\<[str]></code> and the indices are not at [char boundaries](str::is_char_boundary).
433  /// 
434  /// Also panics if `self` is un-[upgrade](WeakSrc::upgrade)able;
435  /// this is problematic for [`UniqueSrc`](crate::UniqueSrc) and [`UninitSrc`](crate::UninitSrc), and is intended to be relaxed in the future.
436  /// 
437  /// # Examples
438  /// ```rust
439  /// use slice_rc::Src;
440  /// 
441  /// let v = Src::from_array([10, 40, 30]);
442  /// let weak = Src::downgrade(&v);
443  /// assert_eq!(Src::single(40), weak.slice(1).upgrade().unwrap());
444  /// assert_eq!(Src::from_array([10, 40]), weak.slice(0..2).upgrade().unwrap());
445  /// ```
446  /// Panics:
447  /// ```should_panic
448  /// # use slice_rc::Src;
449  /// let v = Src::from_array([10, 40, 30]);
450  /// let weak = Src::downgrade(&v);
451  /// let _ = weak.slice(3);
452  /// let _ = weak.slice(0..4);
453  /// ```
454  #[inline]
455  pub fn slice<I: SrcIndex<T>>(&self, index: I) -> WeakSrc<I::Output> {
456    index.get_weak(self.clone())
457  }
458  
459  pub(crate) fn into_item(self, index: usize) -> WeakSrc<T::Item> {
460    assert!(!self.is_dangling(), "cannot slice a dangling WeakSrc");
461    // SAFETY: we just checked that this weak is not dangling
462    let header = unsafe { self.header() };
463    assert!(index < header.len(), "index {index} out of range for slice of length {}", header.len());
464    // 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
465    let start_ptr = unsafe { self.start.add(index) };
466    let this = WeakSrc {
467      // SAFETY: the safety invariant of self.header is the same as this.header
468      header: self.header,
469      // 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
470      start: start_ptr,
471      // SAFETY: if this weak is not dangling (which we checked earlier), the safety invariant is checked by the assertion above
472      len: (),
473      _phantom: PhantomData,
474    };
475    forget(self); // don't modify the weak count because this is logically the same WeakSrc
476    this
477  }
478  
479  pub(crate) fn into_slice_from_bounds(self, start: Bound<usize>, end: Bound<usize>) -> WeakSrc<T> {
480    assert!(!self.is_dangling(), "cannot slice a dangling WeakSrc");
481    // SAFETY: we just checked that this weak is not dangling
482    let header = unsafe { self.header() };
483    assert!(header.strong_count() > 0, "cannot slice a WeakSrc whose strong references have been dropped");
484    let start_inc = match start {
485      Bound::Excluded(val) => val + 1,
486      Bound::Included(val) => val,
487      Bound::Unbounded => 0,
488    };
489    let end_exc = match end {
490      Bound::Excluded(val) => val,
491      Bound::Included(val) => val + 1,
492      Bound::Unbounded => header.len(),
493    };
494    assert!(start_inc <= end_exc, "slice index starts at {start_inc} but ends at {end_exc}");
495    assert!(end_exc <= header.len(), "range end index {end_exc} out of range for slice of length {}", header.len());
496    // SAFETY: we just checked that this weak is not dangling and not dropped
497    unsafe { T::validate_range_weak(&self, start_inc..end_exc) };
498    let len = end_exc - start_inc;
499    // 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
500    let start_ptr = unsafe { self.start.add(start_inc) };
501    let this = WeakSrc {
502      // SAFETY: the safety invariant of self.header is the same as this.header
503      header: self.header,
504      // 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
505      start: start_ptr,
506      // SAFETY: if this weak is not dangling (which we checked earlier), the safety invariant is checked by the assertions above
507      len,
508      _phantom: PhantomData,
509    };
510    forget(self); // don't modify the weak count because this is logically the same WeakSrc
511    this
512  }
513  
514  // SAFETY:
515  // requires:
516  // * self is not dangling nor dropped
517  pub(crate) unsafe fn get_slice(&self) -> &[T::Item] {
518    let s = NonNull::slice_from_raw_parts(self.start, self.len);
519    // SAFETY: the safety requirements of this fn combined with the invariants of WeakSrc guarantee that this refers to a properly initialized slice
520    unsafe { s.as_ref() }
521  }
522  
523}
524
525impl<T: Sized> WeakSrc<T> {
526  
527  /// Returns a `WeakSrc` equivalent to this one, but typed as a slice rather than a single element.
528  /// 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.
529  /// 
530  /// ```rust
531  /// use slice_rc::{Src, WeakSrc};
532  /// use std::ptr;
533  /// 
534  /// let strong = Src::single(42);
535  /// let single = Src::downgrade(&strong);
536  /// let slice = single.as_slice();
537  /// 
538  /// assert!(WeakSrc::ptr_eq(&single, &slice));
539  /// assert!(ptr::eq(&*single.upgrade().unwrap(), &slice.upgrade().unwrap()[0]));
540  /// ```
541  #[inline]
542  pub fn as_slice(&self) -> WeakSrc<[T]> {
543    if !self.is_dangling() {
544      // SAFETY: we just checked that this weak is not dangling
545      unsafe { self.header() }.inc_weak_count();
546    }
547    WeakSrc {
548      // SAFETY: the safety invariant of self.header is the same as this.header
549      header: self.header,
550      // SAFETY: the safety invariant of self.start is the same as this.start
551      start: self.start,
552      // 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
553      len: 1,
554      _phantom: PhantomData,
555    }
556  }
557  
558}
559
560impl<T: SrcTarget + ?Sized> Clone for WeakSrc<T> {
561  
562  fn clone(&self) -> Self {
563    if !self.is_dangling() {
564      // SAFETY: we just checked that this weak is not dangling
565      unsafe { self.header() }.inc_weak_count();
566    }
567    Self {
568      // SAFETY: the safety invariant of self.header is the same as _.header
569      header: self.header,
570      // SAFETY: the safety invariant of self.start is the same as _.start
571      start: self.start,
572      // SAFETY: the safety invariant of self.len is the same as _.len
573      len: self.len,
574      _phantom: PhantomData,
575    }
576  }
577  
578}
579
580impl<T: SrcTarget + ?Sized> Debug for WeakSrc<T> {
581  
582  #[inline]
583  fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
584    write!(f, "(WeakSrc)")
585  }
586  
587}
588
589impl<T: SrcTarget + ?Sized> Pointer for WeakSrc<T> {
590  
591  #[inline]
592  fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
593    Pointer::fmt(&self.start, f)
594  }
595  
596}
597
598impl<T: SrcTarget + ?Sized> Default for WeakSrc<T> {
599  
600  #[inline]
601  fn default() -> Self {
602    Self::dangling()
603  }
604  
605}
606
607impl<T: SrcTarget + ?Sized> Drop for WeakSrc<T> {
608  
609  fn drop(&mut self) {
610    if !self.is_dangling() {
611      // SAFETY:
612      // * 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
613      // * the header is only accessed from InnerHeader::get_header
614      unsafe { InnerHeader::drop_weak::<T::Item>(self.header); }
615    }
616  }
617  
618}
619
620#[cfg(test)]
621mod tests {
622  
623  use std::cell::Cell;
624  use crate::*;
625  
626  #[test]
627  fn dangling() {
628    let w: WeakSrc<[u8]> = WeakSrc::dangling();
629    assert!(w.is_dangling());
630    assert!(w.upgrade().is_none());
631  }
632  
633  #[test]
634  fn is_dangling() {
635    { // dangling
636      let w: WeakSrc<[u8]> = WeakSrc::dangling();
637      assert!(w.is_dangling());
638    }
639    { // not dangling
640      let s: Src<[u8]> = Src::from_default(0);
641      let w: WeakSrc<[u8]> = Src::downgrade(&s);
642      assert!(!w.is_dangling());
643      std::mem::drop(s);
644      assert!(!w.is_dangling());
645    }
646  }
647  
648  #[test]
649  fn upgrade() {
650    { // dangling
651      let w: WeakSrc<[u8]> = WeakSrc::dangling();
652      assert!(w.upgrade().is_none());
653    }
654    { // not dangling
655      let s1: Src<[u8]> = Src::from_default(0);
656      let w: WeakSrc<[u8]> = Src::downgrade(&s1);
657      let s2: Src<[u8]> = w.upgrade().unwrap();
658      assert!(Src::ptr_eq(&s1, &s2));
659    }
660  }
661  
662  #[test]
663  fn ptr_eq() {
664    { // dangling
665      let w1: WeakSrc<[u8]> = WeakSrc::dangling();
666      let w2: WeakSrc<[u8]> = WeakSrc::dangling();
667      assert!(w1.ptr_eq(&w2));
668    }
669    { // not dangling, same root
670      let s: Src<[u8]> = Src::from_default(1);
671      let w1: WeakSrc<[u8]> = Src::downgrade(&s);
672      let w2: WeakSrc<[u8]> = w1.clone();
673      assert!(w1.ptr_eq(&w2));
674      let w3: WeakSrc<[u8]> = WeakSrc::dangling();
675      assert!(!w1.ptr_eq(&w3));
676      assert!(!w2.ptr_eq(&w3));
677      let w4: WeakSrc<[u8]> = Src::downgrade(&s).slice(1..);
678      let w5: WeakSrc<[u8]> = Src::downgrade(&s).slice(1..);
679      assert!(w4.ptr_eq(&w5));
680      assert!(!w4.ptr_eq(&w1));
681      assert!(!w4.ptr_eq(&w3));
682    }
683    { // not dangling, different roots
684      let s1: Src<[u8]> = Src::from_default(0);
685      let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
686      let s2: Src<[u8]> = Src::from_default(0);
687      let w2: WeakSrc<[u8]> = Src::downgrade(&s2);
688      assert!(!w1.ptr_eq(&w2));
689      let w3: WeakSrc<[u8]> = WeakSrc::dangling();
690      assert!(!w1.ptr_eq(&w3));
691      assert!(!w2.ptr_eq(&w3));
692      std::mem::drop((s1, s2));
693      assert!(!w1.ptr_eq(&w3));
694      assert!(!w2.ptr_eq(&w3));
695    }
696  }
697  
698  #[test]
699  fn same_root() {
700    { // dangling
701      let w1: WeakSrc<[u8]> = WeakSrc::dangling();
702      let w2: WeakSrc<[u8]> = WeakSrc::dangling();
703      assert!(w1.same_root(&w2));
704    }
705    { // not dangling, same root
706      let s: Src<[u8]> = Src::from_default(1);
707      let w1: WeakSrc<[u8]> = Src::downgrade(&s);
708      let w2: WeakSrc<[u8]> = w1.clone();
709      assert!(w1.same_root(&w2));
710      let w3: WeakSrc<[u8]> = WeakSrc::dangling();
711      assert!(!w1.same_root(&w3));
712      assert!(!w2.same_root(&w3));
713      let w4: WeakSrc<[u8]> = Src::downgrade(&s).slice(1..);
714      assert!(w4.same_root(&w1));
715      assert!(!w4.same_root(&w3));
716    }
717    { // not dangling, different roots
718      let s1: Src<[u8]> = Src::from_default(0);
719      let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
720      let s2: Src<[u8]> = Src::from_default(0);
721      let w2: WeakSrc<[u8]> = Src::downgrade(&s2);
722      assert!(!w1.same_root(&w2));
723      let w3: WeakSrc<[u8]> = WeakSrc::dangling();
724      assert!(!w1.same_root(&w3));
725      assert!(!w2.same_root(&w3));
726      std::mem::drop((s1, s2));
727      assert!(!w1.same_root(&w3));
728      assert!(!w2.same_root(&w3));
729    }
730  }
731  
732  #[test]
733  fn is_root() {
734    { // dangling
735      let w: WeakSrc<[u8]> = WeakSrc::dangling();
736      assert!(w.is_root());
737    }
738    {
739      let s: Src<[u8]> = Src::from_default(1);
740      let w1: WeakSrc<[u8]> = Src::downgrade(&s);
741      assert!(w1.is_root());
742      let w2: WeakSrc<[u8]> = Src::downgrade(&s).slice(1..);
743      assert!(!w2.is_root());
744      std::mem::drop(s);
745      assert!(w1.is_root());
746      assert!(!w2.is_root());
747    }
748  }
749  
750  #[test]
751  fn strong_count() {
752    { // dangling
753      let w: WeakSrc<[u8]> = WeakSrc::dangling();
754      assert_eq!(w.strong_count(), 0);
755    }
756    { // not dangling
757      let s1: Src<[u8]> = Src::from_default(0);
758      let w: WeakSrc<[u8]> = Src::downgrade(&s1);
759      assert_eq!(w.strong_count(), 1);
760      let s2: Src<[u8]> = s1.clone();
761      assert_eq!(w.strong_count(), 2);
762      std::mem::drop(s1);
763      assert_eq!(w.strong_count(), 1);
764      std::mem::drop(s2);
765      assert_eq!(w.strong_count(), 0);
766    }
767  }
768  
769  #[test]
770  fn weak_count() {
771    { // dangling
772      let w: WeakSrc<[u8]> = WeakSrc::dangling();
773      assert_eq!(w.weak_count(), 0);
774    }
775    { // not dangling
776      let s: Src<[u8]> = Src::from_default(0);
777      let w1: WeakSrc<[u8]> = Src::downgrade(&s);
778      assert_eq!(w1.weak_count(), 1);
779      let w2: WeakSrc<[u8]> = w1.clone();
780      assert_eq!(w1.weak_count(), 2);
781      assert_eq!(w2.weak_count(), 2);
782      let w3: WeakSrc<[u8]> = Src::downgrade(&s);
783      assert_eq!(w1.weak_count(), 3);
784      assert_eq!(w2.weak_count(), 3);
785      assert_eq!(w3.weak_count(), 3);
786      std::mem::drop(w1);
787      assert_eq!(w2.weak_count(), 2);
788      assert_eq!(w3.weak_count(), 2);
789      std::mem::drop(s);
790      assert_eq!(w2.weak_count(), 0);
791      assert_eq!(w3.weak_count(), 0);
792    }
793  }
794  
795  #[test]
796  fn len() {
797    { // dangling
798      let w: WeakSrc<[u8]> = WeakSrc::dangling();
799      assert_eq!(w.len(), 0);
800    }
801    { // not dangling
802      let s: Src<[u8]> = Src::from_default(0);
803      let w: WeakSrc<[u8]> = Src::downgrade(&s);
804      assert_eq!(w.len(), 0);
805      let s: Src<[u8]> = Src::from_default(1);
806      let w: WeakSrc<[u8]> = Src::downgrade(&s);
807      assert_eq!(w.len(), 1);
808      let s: Src<[u8]> = Src::from_default(17);
809      let w: WeakSrc<[u8]> = Src::downgrade(&s);
810      assert_eq!(w.len(), 17);
811      let w: WeakSrc<[u8]> = w.slice(3..14);
812      assert_eq!(w.len(), 11);
813      let w: WeakSrc<[u8]> = w.slice(3..3);
814      assert_eq!(w.len(), 0);
815    }
816  }
817  
818  #[test]
819  fn is_empty() {
820    { // dangling
821      let w: WeakSrc<[u8]> = WeakSrc::dangling();
822      assert!(w.is_empty());
823    }
824    { // not dangling
825      let s: Src<[u8]> = Src::from_default(0);
826      let w: WeakSrc<[u8]> = Src::downgrade(&s);
827      assert!(w.is_empty());
828      let s: Src<[u8]> = Src::from_default(1);
829      let w: WeakSrc<[u8]> = Src::downgrade(&s);
830      assert!(!w.is_empty());
831      let s: Src<[u8]> = Src::from_default(17);
832      let w: WeakSrc<[u8]> = Src::downgrade(&s);
833      assert!(!w.is_empty());
834      let w: WeakSrc<[u8]> = w.slice(3..14);
835      assert!(!w.is_empty());
836      let w: WeakSrc<[u8]> = w.slice(3..3);
837      assert!(w.is_empty());
838    }
839  }
840  
841  #[test]
842  fn root() {
843    { // dangling
844      let w1: WeakSrc<[u8]> = WeakSrc::dangling();
845      let w2: WeakSrc<[u8]> = w1.root();
846      assert!(w2.is_root());
847      assert!(w1.ptr_eq(&w2));
848    }
849    { // not dangling
850      let s: Src<[u8]> = Src::from_default(1);
851      let w: WeakSrc<[u8]> = Src::downgrade(&s);
852      assert!(w.is_root());
853      let w: WeakSrc<[u8]> = w.slice(1..);
854      assert!(!w.is_root());
855      let w: WeakSrc<[u8]> = w.root();
856      assert!(w.is_root());
857    }
858  }
859  
860  #[test]
861  #[should_panic]
862  fn slice_dangling() {
863    let w: WeakSrc<[u8]> = WeakSrc::dangling();
864    let _: WeakSrc<[u8]> = w.slice(..);
865  }
866  
867  #[test]
868  fn slice() {
869    { // slice
870      let s1: Src<[u8]> = Src::from_array([1, 2, 3]);
871      let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
872      let s1: Src<[u8]> = w1.upgrade().unwrap();
873      assert_eq!(&*s1, &[1, 2, 3]);
874      let w1: WeakSrc<[u8]> = w1.slice(1..);
875      let s1: Src<[u8]> = w1.upgrade().unwrap();
876      assert_eq!(&*s1, &[2, 3]);
877      let w2: WeakSrc<[u8]> = w1.slice(..1);
878      let s2: Src<[u8]> = w2.upgrade().unwrap();
879      assert_eq!(&*s2, &[2]);
880      assert!(w1.same_root(&w2));
881    }
882    { // item 1
883      let s1: Src<[u8]> = Src::from_array([1, 2, 3]);
884      let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
885      let s1: Src<[u8]> = w1.upgrade().unwrap();
886      assert_eq!(&*s1, &[1, 2, 3]);
887      let w2: WeakSrc<u8> = w1.slice(2);
888      let s2: Src<u8> = w2.upgrade().unwrap();
889      assert_eq!(&*s2, &3);
890      let w2: WeakSrc<[u8]> = w2.as_slice();
891      let s2: Src<[u8]> = w2.upgrade().unwrap();
892      assert_eq!(&*s2, &[3]);
893      assert!(w1.same_root(&w2));
894    }
895    { // item 2
896      let s1: Src<[u8]> = Src::from_array([1, 2, 3]);
897      let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
898      let s1: Src<[u8]> = w1.upgrade().unwrap();
899      assert_eq!(&*s1, &[1, 2, 3]);
900      let w1: WeakSrc<[u8]> = w1.slice(1..);
901      let s1: Src<[u8]> = w1.upgrade().unwrap();
902      assert_eq!(&*s1, &[2, 3]);
903      let w2: WeakSrc<u8> = w1.slice(0);
904      let s2: Src<u8> = w2.upgrade().unwrap();
905      assert_eq!(&*s2, &2);
906      let w2: WeakSrc<[u8]> = w2.as_slice();
907      let s2: Src<[u8]> = w2.upgrade().unwrap();
908      assert_eq!(&*s2, &[2]);
909      assert!(w1.same_root(&w2));
910    }
911  }
912  
913  #[test]
914  fn as_slice() {
915    { // dangling
916      let w: WeakSrc<u8> = WeakSrc::dangling();
917      let w: WeakSrc<[u8]> = w.as_slice();
918      assert!(w.is_dangling());
919    }
920    { // single root
921      let s1: Src<u8> = Src::single(42);
922      let w1: WeakSrc<u8> = Src::downgrade(&s1);
923      let w2: WeakSrc<[u8]> = w1.as_slice();
924      let s2: Src<[u8]> = w2.upgrade().unwrap();
925      assert_eq!([*s1], *s2);
926    }
927    { // from slice
928      let s1: Src<[u8]> = Src::from_array([1, 2, 3]);
929      let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
930      let w2: WeakSrc<u8> = w1.slice(1);
931      let s2: Src<u8> = w2.upgrade().unwrap();
932      let w3: WeakSrc<[u8]> = w2.as_slice();
933      let s3: Src<[u8]> = w3.upgrade().unwrap();
934      assert_eq!(s1[1], *s2);
935      assert_eq!([*s2], *s3);
936    }
937  }
938  
939  #[test]
940  fn clone() {
941    { // dangling
942      let w1: WeakSrc<[u8]> = WeakSrc::dangling();
943      assert_eq!(w1.weak_count(), 0);
944      let w2: WeakSrc<[u8]> = w1.clone();
945      assert_eq!(w1.weak_count(), 0);
946      assert_eq!(w2.weak_count(), 0);
947    }
948    { // not dangling
949      let s1: Src<[u8]> = Src::from_array([1, 2, 3]);
950      let w1: WeakSrc<[u8]> = Src::downgrade(&s1);
951      assert_eq!(w1.weak_count(), 1);
952      let w2: WeakSrc<[u8]> = w1.clone();
953      assert_eq!(w1.weak_count(), 2);
954      let s2: Src<[u8]> = w2.upgrade().unwrap();
955      assert_eq!(*s1, *s2);
956      assert!(w1.ptr_eq(&w2));
957      std::mem::drop((s1, s2));
958      assert_eq!(w1.weak_count(), 0);
959    }
960  }
961  
962  #[test]
963  fn drop() {
964    let drop_flags: [_; 3] = std::array::from_fn(|_| Cell::new(false));
965    struct DropFlagger<'a>(&'a Cell<bool>);
966    impl Drop for DropFlagger<'_> {
967      
968      fn drop(&mut self) {
969        self.0.update(|v| !v)
970      }
971      
972    }
973    assert!(!drop_flags.iter().any(Cell::get));
974    let s: Src<[DropFlagger<'_>]> = Src::from_iter(drop_flags.iter().map(DropFlagger));
975    assert!(!drop_flags.iter().any(Cell::get));
976    let w1: WeakSrc<[DropFlagger<'_>]> = Src::downgrade(&s);
977    assert!(!drop_flags.iter().any(Cell::get));
978    assert_eq!(w1.weak_count(), 1);
979    let w2: WeakSrc<[DropFlagger<'_>]> = w1.clone();
980    assert!(!drop_flags.iter().any(Cell::get));
981    assert_eq!(w1.weak_count(), 2);
982    assert_eq!(w2.weak_count(), 2);
983    std::mem::drop(w1);
984    assert!(!drop_flags.iter().any(Cell::get));
985    assert_eq!(w2.weak_count(), 1);
986    std::mem::drop(s);
987    assert!(drop_flags.iter().all(Cell::get));
988    assert_eq!(w2.weak_count(), 0);
989    std::mem::drop(w2);
990    assert!(drop_flags.iter().all(Cell::get));
991  }
992  
993}