static_rc/
rcref.rs

1//! `StaticRcRef` is a compile-time referenced counted access to a mutable reference.
2
3use core::{
4    any,
5    borrow,
6    cmp,
7    convert,
8    fmt,
9    future,
10    hash,
11    iter,
12    marker::{self, PhantomData},
13    mem::{self, MaybeUninit},
14    ops,
15    pin,
16    ptr::{self, NonNull},
17    task,
18};
19
20#[cfg(feature = "nightly-async-iterator")]
21use core::async_iter;
22
23#[cfg(feature = "nightly-coerce-unsized")]
24use core::ops::CoerceUnsized;
25
26#[cfg(feature = "nightly-dispatch-from-dyn")]
27use core::ops::DispatchFromDyn;
28
29/// A compile-time reference-counted pointer.
30///
31/// The inherent methods of `StaticRc` are all associated functions to avoid conflicts with the the methods of the
32/// inner type `T` which are brought into scope by the `Deref` implementation.
33///
34/// The parameters `NUM` and `DEN` DENote the ratio (`NUM / DEN`) of ownership of the pointer:
35///
36/// -   The ratio is always in the (0, 1] interval, that is: `NUM > 0` and `NUM <= DEN`.
37/// -   When the ratio is equal to 1, that is when `NUM == DEN`, then the instance has full ownership of the pointee
38///     and extra capabilities are unlocked.
39pub struct StaticRcRef<'a, T: ?Sized, const NUM: usize, const DEN: usize> {
40    pointer: NonNull<T>,
41    _marker: PhantomData<&'a mut T>,
42}
43
44impl<'a, T: ?Sized, const N: usize> StaticRcRef<'a, T, N, N> {
45    /// Constructs a new `StaticRcRef<'a, T, N, N>`.
46    ///
47    /// #   Example
48    ///
49    /// ```rust
50    /// use static_rc::StaticRcRef;
51    ///
52    /// type Full<'a> = StaticRcRef<'a, i32, 1, 1>;
53    ///
54    /// let mut value = 42;
55    /// let rc = Full::new(&mut value);
56    /// assert_eq!(42, *rc);
57    /// ```
58    #[inline(always)]
59    pub fn new(value: &'a mut T) -> Self
60    where
61        AssertLeType!(1, N): Sized,
62    {
63        #[cfg(not(feature = "compile-time-ratio"))]
64        assert!(N > 0);
65
66        let pointer = NonNull::from(value);
67        Self { pointer, _marker: PhantomData }
68    }
69
70    /// Returns the inner value.
71    ///
72    /// #   Example
73    ///
74    /// ```rust
75    /// use static_rc::StaticRcRef;
76    ///
77    /// type Full<'a> = StaticRcRef<'a, i32, 1, 1>;
78    ///
79    /// let mut value = 42;
80    /// let rc = Full::new(&mut value);
81    /// let inner: &mut i32 = Full::into_inner(rc);
82    /// assert_eq!(42, *inner);
83    /// ```
84    #[inline(always)]
85    pub fn into_inner(this: Self) -> &'a mut T {
86        //  Safety:
87        //  -   Ratio = 1, hence full ownership.
88        //  -   Original lifetime is restored.
89        unsafe { &mut *this.pointer.as_ptr() }
90    }
91
92    /// Returns a mutable reference into the given `StaticRcRef`.
93    ///
94    /// #   Example
95    ///
96    /// ```rust
97    /// use static_rc::StaticRcRef;
98    ///
99    /// type Full<'a> = StaticRcRef<'a, i32, 1, 1>;
100    ///
101    /// let mut value = 42;
102    /// let mut rc = Full::new(&mut value);
103    /// assert_eq!(42, *Full::get_mut(&mut rc));
104    /// ```
105    #[inline(always)]
106    pub fn get_mut(this: &mut Self) -> &mut T {
107        //  Safety:
108        //  -   Ratio = 1, hence full ownership.
109        unsafe { this.pointer.as_mut() }
110    }
111}
112
113impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> StaticRcRef<'a, T, NUM, DEN> {
114    /// Consumes the `StaticRcRef`, returning the wrapped pointer.
115    ///
116    /// #   Example
117    ///
118    /// ```rust
119    /// use static_rc::StaticRcRef;
120    ///
121    /// type Full<'a> = StaticRcRef<'a, i32, 1, 1>;
122    ///
123    /// let mut value = 42;
124    /// let rc = Full::new(&mut value);
125    /// let pointer = Full::into_raw(rc);
126    /// assert_eq!(&mut value as *mut _, pointer.as_ptr());
127    /// ```
128    #[inline(always)]
129    pub fn into_raw(this: Self) -> NonNull<T> { this.pointer }
130
131    /// Provides a raw pointer to the data.
132    ///
133    /// `StaticRcRef` is not consumed or affected in any way, the pointer is valid as long as the original value is.
134    ///
135    /// #   Example
136    ///
137    /// ```rust
138    /// use static_rc::StaticRcRef;
139    ///
140    /// type Full<'a> = StaticRcRef<'a, i32, 1, 1>;
141    ///
142    /// let mut value = 42;
143    /// let pointer = &mut value as *mut _;
144    ///
145    /// let rc = Full::new(&mut value);
146    /// let other_pointer = Full::as_ptr(&rc);
147    ///
148    /// assert_eq!(pointer, other_pointer.as_ptr());
149    /// ```
150    #[inline(always)]
151    pub fn as_ptr(this: &Self) -> NonNull<T> { this.pointer }
152
153    /// Provides a reference to the data.
154    ///
155    /// #   Example
156    ///
157    /// ```rust
158    /// use static_rc::StaticRcRef;
159    ///
160    /// type Full<'a> = StaticRcRef<'a, i32, 1, 1>;
161    ///
162    /// let mut value = 42;
163    /// let rc = Full::new(&mut value);
164    ///
165    /// let r = Full::get_ref(&rc);
166    ///
167    /// assert_eq!(42, *r);
168    /// ```
169    #[inline(always)]
170    pub fn get_ref(this: &Self) -> &T {
171        //  Safety:
172        //  -   The data is valid for as long as `this` lives.
173        unsafe { this.pointer.as_ref() }
174    }
175
176    /// Constructs a `StaticRcRef<'a, T, NUM, DEN>` from a raw pointer.
177    ///
178    /// The raw pointer must have been previously returned by a call to `StaticRcRef<'a, U, N, D>::into_raw`:
179    ///
180    /// -   If `U` is different from `T`, then specific restrictions on size and alignment apply. See `mem::transmute`
181    ///     for the restrictions applying to transmuting references.
182    /// -   If `N / D` is different from `NUM / DEN`, then specific restrictions apply. The user is responsible for
183    ///     ensuring proper management of the ratio of shares, and ultimately that the value is not dropped twice.
184    //  Internal comment: Internally, calling `from_raw` in the specific case of `StaticRc::as_rcref`
185    //  is allowed. This isn't allowed as an external user of the library.
186    #[inline(always)]
187    pub unsafe fn from_raw(pointer: NonNull<T>) -> Self
188    where
189        AssertLeType!(1, NUM): Sized,
190    {
191        #[cfg(not(feature = "compile-time-ratio"))]
192        assert!(NUM > 0);
193
194        Self { pointer, _marker: PhantomData, }
195    }
196
197    /// Returns true if the two `StaticRcRef` point to the same allocation.
198    ///
199    /// #   Example
200    ///
201    /// ```rust
202    /// use static_rc::StaticRcRef;
203    ///
204    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
205    ///
206    /// let mut value = 42;
207    /// let rc = Full::new(&mut value);
208    /// let (one, two) = Full::split::<1, 1>(rc);
209    ///
210    /// assert!(StaticRcRef::ptr_eq(&one, &two));
211    /// ```
212    #[inline(always)]
213    pub fn ptr_eq<const N: usize, const D: usize>(this: &Self, other: &StaticRcRef<'a, T, N, D>) -> bool {
214        StaticRcRef::as_ptr(this) == StaticRcRef::as_ptr(other)
215    }
216
217    /// Adjusts the NUMerator and DENumerator of the ratio of the instance, preserving the ratio.
218    ///
219    /// #   Panics
220    ///
221    /// If the compile-time-ratio feature is not used, and the ratio is not preserved; that is `N / D <> NUM / DEN`.
222    ///
223    /// #   Example
224    ///
225    /// ```rust
226    /// use static_rc::StaticRcRef;
227    ///
228    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
229    ///
230    /// let mut value = 42;
231    /// let rc = Full::new(&mut value);
232    /// let rc = Full::adjust::<1, 1>(rc);
233    ///
234    /// assert_eq!(42, *rc);
235    /// ```
236    #[inline(always)]
237    pub fn adjust<const N: usize, const D: usize>(this: Self) -> StaticRcRef<'a, T, N, D>
238    where
239        AssertLeType!(1, N): Sized,
240        AssertEqType!(N * DEN, NUM * D): Sized,
241    {
242        #[cfg(not(feature = "compile-time-ratio"))]
243        {
244            assert!(N > 0);
245            assert_eq!(NUM * D, N * DEN, "{} / {} != {} / {}", NUM, DEN, N, D);
246        }
247
248        StaticRcRef { pointer: this.pointer, _marker: PhantomData }
249    }
250
251    /// Reborrows into another [`StaticRcRef`].
252    /// 
253    /// The current instance is mutably borrowed for the duration the result can be used.
254    /// 
255    /// #   Example
256    /// 
257    /// ```rust
258    /// use static_rc::StaticRcRef;
259    /// let mut x = 5;
260    /// let rc_full: StaticRcRef<i32, 2, 2> = StaticRcRef::new(&mut x);
261    /// let (mut rc1, mut rc2) = StaticRcRef::split::<1, 1>(rc_full);
262    /// {
263    ///     // Modify without moving `rc1`, `rc2`.
264    ///     let rc_borrow1 = StaticRcRef::reborrow(&mut rc1);
265    ///     let rc_borrow2 = StaticRcRef::reborrow(&mut rc2);
266    ///     let mut rcref_full: StaticRcRef<_, 2, 2> = StaticRcRef::join(rc_borrow1, rc_borrow2);
267    ///     *rcref_full = 9;
268    ///     // Reborrow ends, can use the original refs again
269    /// }
270    /// let rc_full: StaticRcRef<_, 2, 2> = StaticRcRef::join(rc1, rc2);
271    /// assert_eq!(*rc_full, 9);
272    /// assert_eq!(x, 9);
273    /// ```
274    #[inline(always)]
275    pub fn reborrow<'reborrow>(this: &'reborrow mut Self) -> StaticRcRef<'reborrow, T, NUM, DEN> {
276        //  Safety (even though this doesn't use the `unsafe` keyword):
277        //  -  `this.pointer` is a valid aligned pointer into a valid value of `T`.
278        //  -   The result is only usable for lifetime `'a`, and for the duration
279        //      of the lifetime `'a` `this` is mutably borrowed.
280        //  -   `this` has NUM/DEN of the right to mutate the value. So it can lend NUM/DEN
281        //      of the right to mutate the value. Therefore, this is semantically sound
282        //      according to the general principle of this library.
283        StaticRcRef {
284            pointer: this.pointer,
285            _marker: PhantomData::default(),
286        }
287    }
288
289    /// Splits the current instance into two instances with the specified NUMerators.
290    ///
291    /// #   Panics
292    ///
293    /// If the compile-time-ratio feature is not used, and the ratio is not preserved; that is `A + B <> NUM`.
294    ///
295    /// #   Example
296    ///
297    /// ```rust
298    /// use static_rc::StaticRcRef;
299    ///
300    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
301    ///
302    /// let mut value = 42;
303    /// let rc = Full::new(&mut value);
304    /// let (one, two) = Full::split::<1, 1>(rc);
305    ///
306    /// assert_eq!(42, *one);
307    /// assert_eq!(42, *two);
308    /// ```
309    #[inline(always)]
310    pub fn split<const A: usize, const B: usize>(this: Self) -> (StaticRcRef<'a, T, A, DEN>, StaticRcRef<'a, T, B, DEN>)
311    where
312        AssertLeType!(1, A): Sized,
313        AssertLeType!(1, B): Sized,
314        AssertEqType!(A + B, NUM): Sized,
315    {
316        #[cfg(not(feature = "compile-time-ratio"))]
317        {
318            assert!(A > 0);
319            assert!(B > 0);
320            assert_eq!(NUM, A + B, "{} != {} + {}", NUM, A, B);
321        }
322
323        let pointer = this.pointer;
324        let _marker = PhantomData;
325
326        (StaticRcRef { pointer, _marker, }, StaticRcRef { pointer, _marker, })
327    }
328
329    /// Splits the current instance into DIM instances with the specified Numerators.
330    ///
331    /// #   Panics
332    ///
333    /// If the compile-time-ratio feature is not used, and the ratio is not preserved; that is `N * DIM <> NUM`.
334    ///
335    /// #   Example
336    ///
337    /// ```rust
338    /// use static_rc::StaticRcRef;
339    ///
340    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
341    ///
342    /// let mut value = 42;
343    /// let rc = Full::new(&mut value);
344    /// let array = Full::split_array::<1, 2>(rc);
345    ///
346    /// assert_eq!(42, *array[0]);
347    /// assert_eq!(42, *array[1]);
348    /// ```
349    #[inline(always)]
350    pub fn split_array<const N: usize, const DIM: usize>(this: Self) -> [StaticRcRef<'a, T, N, DEN>; DIM]
351    where
352        T: 'a,
353        AssertEqType!(N * DIM, NUM): Sized,
354        AssertLeType!(mem::size_of::<[StaticRcRef<'a, T, N, DEN>; DIM]>(), usize::MAX / 2 + 1): Sized,
355    {
356        #[cfg(not(feature = "compile-time-ratio"))]
357        {
358            assert_eq!(NUM, N * DIM, "{} != {} * {}", NUM, N, DIM);
359
360            assert!(mem::size_of::<[StaticRcRef<T, N, DEN>; DIM]>() <= (isize::MAX as usize),
361                "Size of result ({}) exceeeds isize::MAX", mem::size_of::<[StaticRcRef<T, N, DEN>; DIM]>());
362        }
363
364        let pointer = this.pointer;
365        let _marker = PhantomData;
366
367        let mut array = MaybeUninit::uninit();
368
369        for i in 0..DIM {
370            //  Safety:
371            //  -   `destination` within bounds of allocated array (< DIM).
372            //  -   Offset doesn't overflow `isize`, as per array-size assertion.
373            //  -   Offset doesn't wrap around, as per array-size assertion.
374            let destination = unsafe { (array.as_mut_ptr() as *mut StaticRcRef<T, N, DEN>).add(i) };
375
376            //  Safety:
377            //  -   `destination` is valid for writes.
378            //  -   `destination` is correctly aligned.
379            unsafe { ptr::write(destination, StaticRcRef { pointer, _marker, }); }
380        }
381
382        //  Safety:
383        //  -   Every element of the array is now initialized.
384        unsafe { array.assume_init() }
385    }
386
387    /// Joins two instances into a single instance.
388    ///
389    /// #   Panics
390    ///
391    /// If the two instances do no point to the same allocation, as determined by `StaticRcRef::ptr_eq`.
392    ///
393    /// If the compile-time-ratio feature is not used and the ratio is not preserved; that is `A + B <> NUM`.
394    ///
395    /// #   Example
396    ///
397    /// ```rust
398    /// use static_rc::StaticRcRef;
399    ///
400    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
401    ///
402    /// let mut value = 42;
403    /// let rc = Full::new(&mut value);
404    /// let (one, two) = Full::split::<1, 1>(rc);
405    /// let rc = Full::join(one, two);
406    ///
407    /// assert_eq!(42, *rc);
408    /// ```
409    #[inline(always)]
410    pub fn join<const A: usize, const B: usize>(left: StaticRcRef<'a, T, A, DEN>, right: StaticRcRef<'a, T, B, DEN>) -> Self
411    //  FIXME: re-enable when https://github.com/rust-lang/rust/issues/77708 fixed
412    //  where
413    //      AssertEqType!(NUM, A + B): Sized,
414    {
415        assert!(StaticRcRef::ptr_eq(&left, &right), "{:?} != {:?}", left.pointer.as_ptr(), right.pointer.as_ptr());
416
417        //  Safety:
418        //  -   `left` and `right` point to the same pointer.
419        unsafe { Self::join_unchecked(left, right) }
420    }
421
422    /// Joins two instances into a single instance without checking whether they point to the same allocation.
423    ///
424    /// Unless `compile-time-ratio` is activated, the ratios are checked nevertheless.
425    ///
426    /// # Safety
427    ///
428    /// The caller must guarantee that those instances point to the same allocation.
429    ///
430    /// #   Panics
431    ///
432    /// If the compile-time-ratio feature is not used and the ratio is not preserved; that is `A + B <> NUM`.
433    ///
434    /// In debug, if the two instances do no point to the same allocation, as determined by `StaticRcRef::ptr_eq`.
435    ///
436    /// #   Example
437    ///
438    /// ```rust
439    /// use static_rc::StaticRcRef;
440    ///
441    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
442    ///
443    /// let mut value = 42;
444    /// let rc = Full::new(&mut value);
445    /// let (one, two) = Full::split::<1, 1>(rc);
446    /// let rc = unsafe { Full::join_unchecked(one, two) };
447    ///
448    /// assert_eq!(42, *rc);
449    /// ```
450    #[inline(always)]
451    pub unsafe fn join_unchecked<const A: usize, const B: usize>(
452        left: StaticRcRef<'a, T, A, DEN>,
453        _right: StaticRcRef<'a, T, B, DEN>,
454    ) -> Self
455    //  FIXME: re-enable when https://github.com/rust-lang/rust/issues/77708 fixed
456    //  where
457    //      AssertEqType!(NUM, A + B): Sized,
458    {
459        //  FIXME: re-enable when https://github.com/rust-lang/rust/issues/77708 fixed
460        //  #[cfg(not(feature = "compile-time-ratio"))]
461        assert_eq!(NUM, A + B, "{} != {} + {}", NUM, A, B);
462
463        debug_assert!(StaticRcRef::ptr_eq(&left, &_right), "{:?} != {:?}", left.pointer.as_ptr(), _right.pointer.as_ptr());
464
465        Self { pointer: left.pointer, _marker: PhantomData, }
466    }
467
468    /// Joins DIM instances into a single instance.
469    ///
470    /// #   Panics
471    ///
472    /// If all instances do not point to the same allocation, as determined by `StaticRcRef::ptr_eq`.
473    ///
474    /// If the compile-time-ratio feature is not used and the ratio is not preserved; that is `N * DIM <> NUM`.
475    ///
476    /// #   Example
477    ///
478    /// ```rust
479    /// use static_rc::StaticRcRef;
480    ///
481    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
482    ///
483    /// let mut value = 42;
484    /// let rc = Full::new(&mut value);
485    /// let array = Full::split_array::<1, 2>(rc);
486    /// let rc = Full::join_array(array);
487    ///
488    /// assert_eq!(42, *rc);
489    /// ```
490    #[inline(always)]
491    pub fn join_array<const N: usize, const DIM: usize>(array: [StaticRcRef<'a, T, N, DEN>; DIM]) -> Self
492    //  FIXME: re-enable when https://github.com/rust-lang/rust/issues/77708 fixed
493    //  where
494    //      AssertLeType!(1, NUM): Sized,
495    //      AssertEqType!(N * DIM, NUM): Sized,
496    {
497        let first = &array[0];
498        for successive in &array[1..] {
499            assert!(StaticRcRef::ptr_eq(&first, &successive),
500                "{:?} != {:?}", first.pointer.as_ptr(), successive.pointer.as_ptr());
501        }
502
503        unsafe { Self::join_array_unchecked(array) }
504    }
505
506    /// Joins DIM instances into a single instance.
507    ///
508    /// #   Panics
509    ///
510    /// If the compile-time-ratio feature is not used and the ratio is not preserved; that is `N * DIM <> NUM`.
511    ///
512    /// In debug, if all instances do not point to the same allocation, as determined by `StaticRcRef::ptr_eq`.
513    ///
514    /// #   Example
515    ///
516    /// ```rust
517    /// use static_rc::StaticRcRef;
518    ///
519    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
520    ///
521    /// let mut value = 42;
522    /// let rc = Full::new(&mut value);
523    /// let array = Full::split_array::<1, 2>(rc);
524    /// let rc = unsafe { Full::join_array_unchecked(array) };
525    ///
526    /// assert_eq!(42, *rc);
527    /// ```
528    #[inline(always)]
529    pub unsafe fn join_array_unchecked<const N: usize, const DIM: usize>(array: [StaticRcRef<'a, T, N, DEN>; DIM])
530        -> Self
531    //  FIXME: re-enable when https://github.com/rust-lang/rust/issues/77708 fixed
532    //  where
533    //      AssertLeType!(1, NUM): Sized,
534    //      AssertEqType!(N * DIM, NUM): Sized,
535    {
536        //  FIXME: re-enable when https://github.com/rust-lang/rust/issues/77708 fixed
537        //  #[cfg(not(feature = "compile-time-ratio"))]
538        {
539            assert!(NUM > 0);
540            assert_eq!(NUM, N * DIM, "{} != {} * {}", NUM, N, DIM);
541        }
542
543        let _first = &array[0];
544        for _successive in &array[1..] {
545            debug_assert!(StaticRcRef::ptr_eq(&_first, &_successive),
546                "{:?} != {:?}", _first.pointer.as_ptr(), _successive.pointer.as_ptr());
547        }
548
549        Self { pointer: array[0].pointer, _marker: PhantomData, }
550    }
551
552    
553}
554
555impl<'a, const NUM: usize, const DEN: usize> StaticRcRef<'a, dyn any::Any, NUM, DEN> {
556    /// Attempts to downcast `Self` to a concrete type.
557    pub fn downcast<T: any::Any>(self) -> Result<StaticRcRef<'a, T, NUM, DEN>, Self> {
558        if Self::get_ref(&self).is::<T>() {
559            let pointer = Self::into_raw(self).cast::<T>();
560            Ok(StaticRcRef { pointer, _marker: PhantomData, })
561        } else {
562            Err(self)
563        }
564    }
565}
566
567impl<'a, T: ?Sized, const N: usize> convert::AsMut<T> for StaticRcRef<'a, T, N, N> {
568    #[inline(always)]
569    fn as_mut(&mut self) -> &mut T { Self::get_mut(self) }
570}
571
572impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> convert::AsRef<T> for StaticRcRef<'a, T, NUM, DEN> {
573    #[inline(always)]
574    fn as_ref(&self) -> &T { Self::get_ref(self) }
575}
576
577impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> borrow::Borrow<T> for StaticRcRef<'a, T, NUM, DEN> {
578    #[inline(always)]
579    fn borrow(&self) -> &T { Self::get_ref(self) }
580}
581
582impl<'a, T: ?Sized, const N: usize> borrow::BorrowMut<T> for StaticRcRef<'a, T, N, N> {
583    #[inline(always)]
584    fn borrow_mut(&mut self) -> &mut T { Self::get_mut(self) }
585}
586
587#[cfg(feature = "nightly-coerce-unsized")]
588impl<'a, T, U, const NUM: usize, const DEN: usize> CoerceUnsized<StaticRcRef<'a, U, NUM, DEN>> for StaticRcRef<'a, T, NUM, DEN>
589where
590    T: ?Sized + marker::Unsize<U>,
591    U: ?Sized,
592{}
593
594impl<'a, T: ?Sized + fmt::Debug, const NUM: usize, const DEN: usize> fmt::Debug for StaticRcRef<'a, T, NUM, DEN> {
595    #[inline(always)]
596    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
597        fmt::Debug::fmt(Self::get_ref(self), f)
598    }
599}
600
601impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> ops::Deref for StaticRcRef<'a, T, NUM, DEN> {
602    type Target = T;
603
604    #[inline(always)]
605    fn deref(&self) -> &T { Self::get_ref(self) }
606}
607
608impl<'a, T: ?Sized, const N: usize> ops::DerefMut for StaticRcRef<'a, T, N, N> {
609    #[inline(always)]
610    fn deref_mut(&mut self) -> &mut T { Self::get_mut(self) }
611}
612
613impl<'a, T: ?Sized + fmt::Display, const NUM: usize, const DEN: usize> fmt::Display for StaticRcRef<'a, T, NUM, DEN> {
614    #[inline(always)]
615    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
616        fmt::Display::fmt(Self::get_ref(self), f)
617    }
618}
619
620#[cfg(feature = "nightly-dispatch-from-dyn")]
621impl<'a, T, U, const NUM: usize, const DEN: usize> DispatchFromDyn<StaticRcRef<'a, U, NUM, DEN>> for StaticRcRef<'a, T, NUM, DEN>
622where
623    T: ?Sized + marker::Unsize<U>,
624    U: ?Sized,
625{}
626
627impl<'a, I: iter::DoubleEndedIterator + ?Sized, const N: usize> iter::DoubleEndedIterator for StaticRcRef<'a, I, N, N> {
628    #[inline(always)]
629    fn next_back(&mut self) -> Option<I::Item> { Self::get_mut(self).next_back() }
630
631    #[inline(always)]
632    fn nth_back(&mut self, n: usize) -> Option<I::Item> { Self::get_mut(self).nth_back(n) }
633}
634
635impl<'a, T: ?Sized + cmp::Eq, const NUM: usize, const DEN: usize> cmp::Eq for StaticRcRef<'a, T, NUM, DEN> {}
636
637impl<'a, I: iter::ExactSizeIterator + ?Sized, const N: usize> iter::ExactSizeIterator for StaticRcRef<'a, I, N, N> {
638    #[inline(always)]
639    fn len(&self) -> usize { Self::get_ref(self).len() }
640}
641
642impl<'a, const NUM: usize, const DEN: usize> From<StaticRcRef<'a, str, NUM, DEN>> for StaticRcRef<'a, [u8], NUM, DEN> {
643    #[inline(always)]
644    fn from(value: StaticRcRef<'a, str, NUM, DEN>) -> Self {
645        let pointer = value.pointer.as_ptr() as *mut [u8];
646
647        //  Safety:
648        //  -   `value.pointer` was not null, hence `pointer` is not null.
649        debug_assert!(!pointer.is_null());
650        let pointer = unsafe { NonNull::new_unchecked(pointer) };
651
652        Self { pointer, _marker: PhantomData, }
653    }
654}
655
656impl<'a, I: iter::FusedIterator + ?Sized, const N: usize> iter::FusedIterator for StaticRcRef<'a, I, N, N> {}
657
658impl<'a, F: ?Sized + future::Future + marker::Unpin, const N: usize> future::Future for StaticRcRef<'a, F, N, N> {
659    type Output = F::Output;
660
661    fn poll(mut self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
662        F::poll(pin::Pin::new(&mut *self), cx)
663    }
664}
665
666#[cfg(feature = "nightly-generator-trait")]
667impl<'a, G: ?Sized + ops::Generator<R> + marker::Unpin, R, const N: usize> ops::Generator<R> for StaticRcRef<'a, G, N, N> {
668    type Yield = G::Yield;
669    type Return = G::Return;
670
671        fn resume(mut self: pin::Pin<&mut Self>, arg: R) -> ops::GeneratorState<Self::Yield, Self::Return> {
672            G::resume(pin::Pin::new(&mut *self), arg)
673        }
674}
675
676#[cfg(feature = "nightly-generator-trait")]
677impl<'a, G: ?Sized + ops::Generator<R>, R, const N: usize> ops::Generator<R> for pin::Pin<StaticRcRef<'a, G, N, N>> {
678    type Yield = G::Yield;
679    type Return = G::Return;
680
681        fn resume(mut self: pin::Pin<&mut Self>, arg: R) -> ops::GeneratorState<Self::Yield, Self::Return> {
682            G::resume((*self).as_mut(), arg)
683        }
684}
685
686impl<'a, T: ?Sized + hash::Hash, const NUM: usize, const DEN: usize> hash::Hash for StaticRcRef<'a, T, NUM, DEN> {
687    #[inline(always)]
688    fn hash<H: hash::Hasher>(&self, state: &mut H) {
689        Self::get_ref(self).hash(state);
690    }
691}
692
693impl<'a, I: iter::Iterator + ?Sized, const N: usize> iter::Iterator for StaticRcRef<'a, I, N, N> {
694    type Item = I::Item;
695
696    #[inline(always)]
697    fn next(&mut self) -> Option<I::Item> { Self::get_mut(self).next() }
698
699    #[inline(always)]
700    fn size_hint(&self) -> (usize, Option<usize>) { Self::get_ref(self).size_hint() }
701
702    #[inline(always)]
703    fn nth(&mut self, n: usize) -> Option<I::Item> { Self::get_mut(self).nth(n) }
704
705    #[inline(always)]
706    fn last(mut self) -> Option<I::Item> { Self::get_mut(&mut self).last() }
707}
708
709impl<'a, T: ?Sized + cmp::Ord, const NUM: usize, const DEN: usize> cmp::Ord for StaticRcRef<'a, T, NUM, DEN> {
710    #[inline(always)]
711    fn cmp(&self, other: &Self) -> cmp::Ordering {
712        if Self::ptr_eq(self, other) {
713            cmp::Ordering::Equal
714        } else {
715            Self::get_ref(self).cmp(Self::get_ref(other))
716        }
717    }
718}
719
720impl<'a, T, const NUM: usize, const DEN: usize, const N: usize, const D: usize> cmp::PartialEq<StaticRcRef<'a, T, N, D>>
721    for StaticRcRef<'a, T, NUM, DEN>
722where
723    T: ?Sized + PartialEq<T>
724{
725    #[inline(always)]
726    fn eq(&self, other: &StaticRcRef<'a, T, N, D>) -> bool { Self::get_ref(self).eq(StaticRcRef::get_ref(other)) }
727
728    #[inline(always)]
729    fn ne(&self, other: &StaticRcRef<'a, T, N, D>) -> bool { Self::get_ref(self).ne(StaticRcRef::get_ref(other)) }
730}
731
732impl<'a, T, const NUM: usize, const DEN: usize, const N: usize, const D: usize> cmp::PartialOrd<StaticRcRef<'a, T, N, D>>
733    for StaticRcRef<'a, T, NUM, DEN>
734where
735    T: ?Sized + PartialOrd<T>
736{
737    #[inline(always)]
738    fn partial_cmp(&self, other: &StaticRcRef<'a, T, N, D>) -> Option<cmp::Ordering> {
739        Self::get_ref(self).partial_cmp(StaticRcRef::get_ref(other))
740    }
741
742    #[inline(always)]
743    fn lt(&self, other: &StaticRcRef<'a, T, N, D>) -> bool {
744        Self::get_ref(self).lt(StaticRcRef::get_ref(other))
745    }
746
747    #[inline(always)]
748    fn le(&self, other: &StaticRcRef<'a, T, N, D>) -> bool {
749        Self::get_ref(self).le(StaticRcRef::get_ref(other))
750    }
751
752    #[inline(always)]
753    fn gt(&self, other: &StaticRcRef<'a, T, N, D>) -> bool {
754        Self::get_ref(self).gt(StaticRcRef::get_ref(other))
755    }
756
757    #[inline(always)]
758    fn ge(&self, other: &StaticRcRef<'a, T, N, D>) -> bool {
759        Self::get_ref(self).ge(StaticRcRef::get_ref(other))
760    }
761}
762
763impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> fmt::Pointer for StaticRcRef<'a, T, NUM, DEN> {
764    #[inline(always)]
765    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
766        fmt::Pointer::fmt(&Self::as_ptr(self).as_ptr(), f)
767    }
768}
769
770#[cfg(feature = "nightly-async-iterator")]
771impl<'a, S: ?Sized + async_iter::AsyncIterator + marker::Unpin, const N: usize> async_iter::AsyncIterator for StaticRcRef<'a, S, N, N> {
772    type Item = S::Item;
773
774    fn poll_next(mut self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Option<Self::Item>> {
775        pin::Pin::new(&mut **self).poll_next(cx)
776    }
777
778    fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
779}
780
781impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> marker::Unpin for StaticRcRef<'a, T, NUM, DEN> {}
782
783unsafe impl<'a, T: ?Sized + marker::Send, const NUM: usize, const DEN: usize> marker::Send for StaticRcRef<'a, T, NUM, DEN> {}
784
785unsafe impl<'a, T: ?Sized + marker::Sync, const NUM: usize, const DEN: usize> marker::Sync for StaticRcRef<'a, T, NUM, DEN> {}
786
787#[doc(hidden)]
788pub mod compile_tests {
789
790/// ```compile_fail,E0597
791/// let a = String::from("foo");
792/// let mut a_ref = &a;
793/// let mut rc = static_rc::StaticRcRef::<'_, _,1,1>::new(&mut a_ref);
794/// {
795///     let b = String::from("bar");
796///     *rc = &b; // a_ref now points to b
797/// }
798/// // b is now dropped
799/// assert_ne!(a_ref, "bar");  // This should fail to compile.
800/// ```
801pub fn rcref_prevent_use_after_free() {}
802
803/// ```compile_fail,E0505
804/// let mut a = String::from("foo");
805/// let mut rc = static_rc::StaticRcRef::<'_, _,1,1>::new(&mut a);
806/// 
807/// let mut reborrow = static_rc::StaticRcRef::reborrow(&mut rc);
808/// std::mem::drop(rc);
809/// assert_eq!(*reborrow, "foo"); // This should fail to compile.
810/// ```
811pub fn rcref_reborrow_and_move() {}
812
813/// ```compile_fail,E0502
814/// let mut a = String::from("foo");
815/// let mut rc = static_rc::StaticRcRef::<'_, _,1,1>::new(&mut a);
816/// 
817/// let mut reborrow = static_rc::StaticRcRef::reborrow(&mut rc);
818/// assert_eq!(*rc, "foo");
819/// assert_eq!(*reborrow, "foo"); // This should fail to compile.
820/// ```
821pub fn rcref_reborrow_and_use() {}
822
823} // mod compile_tests
824
825#[doc(hidden)]
826#[cfg(feature = "compile-time-ratio")]
827pub mod compile_ratio_tests {
828
829/// ```compile_fail,E0080
830/// type Zero<'a> = static_rc::StaticRcRef<'a, i32, 0, 0>;
831///
832/// let mut value = 42;
833///
834/// Zero::new(&mut value);
835/// ```
836pub fn rcref_new_zero() {}
837
838/// ```compile_fail,E0080
839/// type Zero<'a> = static_rc::StaticRcRef<'a, i32, 0, 0>;
840///
841/// let pointer = core::ptr::NonNull::dangling();
842///
843/// unsafe { Zero::from_raw(pointer) };
844/// ```
845pub fn rcref_from_raw_zero() {}
846
847/// ```compile_fail,E0080
848/// type One<'a> = static_rc::StaticRcRef<'a, i32, 1, 1>;
849///
850/// let mut value = 42;
851/// let rc = One::new(&mut value);
852///
853/// One::adjust::<0, 0>(rc);
854/// ```
855pub fn rcref_adjust_zero() {}
856
857/// ```compile_fail,E0080
858/// type One<'a> = static_rc::StaticRcRef<'a, i32, 1, 1>;
859///
860/// let mut value = 42;
861/// let rc = One::new(&mut value);
862///
863/// One::adjust::<2, 3>(rc);
864/// ```
865pub fn rcref_adjust_ratio() {}
866
867/// ```compile_fail,E0080
868/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
869///
870/// let mut value = 42;
871/// let rc = Two::new(&mut value);
872///
873/// Two::split::<0, 2>(rc);
874/// ```
875pub fn rcref_split_zero_first() {}
876
877/// ```compile_fail,E0080
878/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
879///
880/// let mut value = 42;
881/// let rc = Two::new(&mut value);
882///
883/// Two::split::<2, 0>(rc);
884/// ```
885pub fn rcref_split_zero_second() {}
886
887/// ```compile_fail,E0080
888/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
889///
890/// let mut value = 42;
891/// let rc = Two::new(&mut value);
892///
893/// Two::split::<1, 2>(rc);
894/// ```
895pub fn rcref_split_sum() {}
896
897/// ```compile_fail,E0080
898/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
899///
900/// let mut value = 42;
901/// let rc = Two::new(&mut value);
902///
903/// Two::split_array::<2, 2>(rc);
904/// ```
905pub fn rcref_split_array_ratio() {}
906
907//  FIXME: should be "compile_fail,E0080"
908/// ```should_panic
909/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
910///
911/// let mut value = 42;
912/// let rc = Two::new(&mut value);
913/// let (one, two) = Two::split::<1, 1>(rc);
914///
915/// static_rc::StaticRcRef::<'_, _, 1, 2>::join(one, two);
916/// ```
917pub fn rcref_join_ratio() {}
918
919//  FIXME: should be "compile_fail,E0080"
920/// ```should_panic
921/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
922///
923/// let mut value = 42;
924/// let rc = Two::new(&mut value);
925/// let (one, two) = Two::split::<1, 1>(rc);
926///
927/// unsafe { static_rc::StaticRcRef::<'_, _, 1, 2>::join_unchecked(one, two) };
928/// ```
929pub fn rcref_join_unchecked_ratio() {}
930
931//  FIXME: should be "compile_fail,E0080"
932/// ```should_panic
933/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
934///
935/// let mut value = 42;
936/// let rc = Two::new(&mut value);
937/// let array: [_; 2] = Two::split_array::<1, 2>(rc);
938///
939/// static_rc::StaticRcRef::<'_, _, 1, 2>::join_array(array);
940/// ```
941pub fn rcref_join_array_ratio() {}
942
943//  FIXME: should be "compile_fail,E0080"
944/// ```should_panic
945/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
946///
947/// let mut value = 42;
948/// let rc = Two::new(&mut value);
949/// let array: [_; 2] = Two::split_array::<1, 2>(rc);
950///
951/// unsafe { static_rc::StaticRcRef::<'_, _, 1, 2>::join_array_unchecked(array) };
952/// ```
953pub fn rcref_join_array_unchecked_ratio() {}
954
955} // mod compile_ratio_tests
956
957#[cfg(all(test, not(feature = "compile-time-ratio")))]
958mod panic_ratio_tests {
959
960use super::*;
961
962type Zero<'a> = StaticRcRef<'a, i32, 0, 0>;
963type One<'a> = StaticRcRef<'a, i32, 1, 1>;
964type Two<'a> = StaticRcRef<'a, i32, 2, 2>;
965
966#[test]
967#[should_panic]
968fn rcref_new_zero() {
969    let mut value = 42;
970
971    Zero::new(&mut value);
972}
973
974#[test]
975#[should_panic]
976fn rcref_from_raw_zero() {
977    let pointer = NonNull::dangling();
978
979    unsafe { Zero::from_raw(pointer) };
980}
981
982#[test]
983#[should_panic]
984fn rcref_adjust_zero() {
985    let mut value = 42;
986    let rc = One::new(&mut value);
987
988    One::adjust::<0, 0>(rc);
989}
990
991#[test]
992#[should_panic]
993fn rcref_adjust_ratio() {
994    let mut value = 42;
995    let rc = One::new(&mut value);
996
997    One::adjust::<2, 3>(rc);
998}
999
1000#[test]
1001#[should_panic]
1002fn rcref_split_zero_first() {
1003    let mut value = 42;
1004    let rc = Two::new(&mut value);
1005
1006    Two::split::<0, 2>(rc);
1007}
1008
1009#[test]
1010#[should_panic]
1011fn rcref_split_zero_second() {
1012    let mut value = 42;
1013    let rc = Two::new(&mut value);
1014
1015    Two::split::<0, 2>(rc);
1016}
1017
1018#[test]
1019#[should_panic]
1020fn rcref_split_sum() {
1021    let mut value = 42;
1022    let rc = Two::new(&mut value);
1023
1024    Two::split::<1, 2>(rc);
1025}
1026
1027#[test]
1028#[should_panic]
1029fn rcref_split_array_ratio() {
1030    let mut value = 42;
1031    let rc = Two::new(&mut value);
1032
1033    Two::split_array::<2, 2>(rc);
1034}
1035
1036#[test]
1037#[should_panic]
1038fn rcref_join_ratio() {
1039    let mut value = 42;
1040    let rc = Two::new(&mut value);
1041    let (one, two) = Two::split::<1, 1>(rc);
1042
1043    StaticRcRef::<'_, _, 1, 2>::join(one, two);
1044}
1045
1046#[test]
1047#[should_panic]
1048fn rcref_join_different() {
1049    let (mut value, mut other_value) = (42, 33);
1050    let (rc, other) = (Two::new(&mut value), Two::new(&mut other_value));
1051    let (one, _two) = Two::split::<1, 1>(rc);
1052    let (other_one, _other_two) = Two::split::<1, 1>(other);
1053
1054    Two::join(one, other_one);
1055}
1056
1057#[test]
1058#[should_panic]
1059fn rcref_join_unchecked_ratio() {
1060    let mut value = 42;
1061    let rc = Two::new(&mut value);
1062    let (one, two) = Two::split::<1, 1>(rc);
1063
1064    unsafe { StaticRcRef::<'_, _, 1, 2>::join_unchecked(one, two) };
1065}
1066
1067#[test]
1068#[should_panic]
1069fn rcref_join_array_ratio() {
1070    let mut value = 42;
1071    let rc = Two::new(&mut value);
1072    let array: [_; 2] = Two::split_array::<1, 2>(rc);
1073
1074    StaticRcRef::<'_, _, 1, 2>::join_array(array);
1075}
1076
1077#[test]
1078#[should_panic]
1079fn rcref_join_array_different() {
1080    let (mut value, mut other_value) = (42, 33);
1081    let (rc, other) = (Two::new(&mut value), Two::new(&mut other_value));
1082    let (one, _two) = Two::split::<1, 1>(rc);
1083    let (other_one, _other_two) = Two::split::<1, 1>(other);
1084
1085    Two::join_array([one, other_one]);
1086}
1087
1088#[test]
1089#[should_panic]
1090fn rcref_join_array_unchecked_ratio() {
1091    let mut value = 42;
1092    let rc = Two::new(&mut value);
1093    let array = Two::split_array::<1, 2>(rc);
1094
1095    unsafe { StaticRcRef::<'_, _, 1, 2>::join_array_unchecked(array) };
1096}
1097
1098} // mod panic_ratio_tests