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}