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        const { 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    /// #   Safety
179    ///
180    /// The raw pointer must have been previously returned by a call to `StaticRcRef<'a, U, N, D>::into_raw`:
181    ///
182    /// -   If `U` is different from `T`, then specific restrictions on size and alignment apply. See `mem::transmute`
183    ///     for the restrictions applying to transmuting references.
184    /// -   If `N / D` is different from `NUM / DEN`, then specific restrictions apply. The user is responsible for
185    ///     ensuring proper management of the ratio of shares, and ultimately that the value is not dropped twice.
186    //  Internal comment: Internally, calling `from_raw` in the specific case of `StaticRc::as_rcref`
187    //  is allowed. This isn't allowed as an external user of the library.
188    #[inline(always)]
189    pub unsafe fn from_raw(pointer: NonNull<T>) -> Self
190    where
191        AssertLeType!(1, NUM): Sized,
192    {
193        #[cfg(not(feature = "compile-time-ratio"))]
194        const { assert!(NUM > 0); }
195
196        Self { pointer, _marker: PhantomData, }
197    }
198
199    /// Returns true if the two `StaticRcRef` point to the same allocation.
200    ///
201    /// #   Example
202    ///
203    /// ```rust
204    /// use static_rc::StaticRcRef;
205    ///
206    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
207    ///
208    /// let mut value = 42;
209    /// let rc = Full::new(&mut value);
210    /// let (one, two) = Full::split::<1, 1>(rc);
211    ///
212    /// assert!(StaticRcRef::ptr_eq(&one, &two));
213    /// ```
214    #[inline(always)]
215    pub fn ptr_eq<const N: usize, const D: usize>(this: &Self, other: &StaticRcRef<'a, T, N, D>) -> bool {
216        ptr::eq(StaticRcRef::as_ptr(this).as_ptr(), StaticRcRef::as_ptr(other).as_ptr())
217    }
218
219    /// Adjusts the NUMerator and DENumerator of the ratio of the instance, preserving the ratio.
220    ///
221    /// #   Example
222    ///
223    /// ```rust
224    /// use static_rc::StaticRcRef;
225    ///
226    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
227    ///
228    /// let mut value = 42;
229    /// let rc = Full::new(&mut value);
230    /// let rc = Full::adjust::<1, 1>(rc);
231    ///
232    /// assert_eq!(42, *rc);
233    /// ```
234    #[inline(always)]
235    pub fn adjust<const N: usize, const D: usize>(this: Self) -> StaticRcRef<'a, T, N, D>
236    where
237        AssertLeType!(1, N): Sized,
238        AssertEqType!(N * DEN, NUM * D): Sized,
239    {
240        #[cfg(not(feature = "compile-time-ratio"))]
241        const {
242            assert!(N > 0);
243            assert!(NUM * D == N * DEN);
244        }
245
246        StaticRcRef { pointer: this.pointer, _marker: PhantomData }
247    }
248
249    /// Reborrows into another [`StaticRcRef`].
250    ///
251    /// The current instance is mutably borrowed for the duration the result can be used.
252    ///
253    /// #   Example
254    ///
255    /// ```rust
256    /// use static_rc::StaticRcRef;
257    /// let mut x = 5;
258    /// let rc_full: StaticRcRef<i32, 2, 2> = StaticRcRef::new(&mut x);
259    /// let (mut rc1, mut rc2) = StaticRcRef::split::<1, 1>(rc_full);
260    /// {
261    ///     // Modify without moving `rc1`, `rc2`.
262    ///     let rc_borrow1 = StaticRcRef::reborrow(&mut rc1);
263    ///     let rc_borrow2 = StaticRcRef::reborrow(&mut rc2);
264    ///     let mut rcref_full: StaticRcRef<_, 2, 2> = StaticRcRef::join(rc_borrow1, rc_borrow2);
265    ///     *rcref_full = 9;
266    ///     // Reborrow ends, can use the original refs again
267    /// }
268    /// let rc_full: StaticRcRef<_, 2, 2> = StaticRcRef::join(rc1, rc2);
269    /// assert_eq!(*rc_full, 9);
270    /// assert_eq!(x, 9);
271    /// ```
272    #[inline(always)]
273    pub fn reborrow<'reborrow>(this: &'reborrow mut Self) -> StaticRcRef<'reborrow, T, NUM, DEN> {
274        //  Safety (even though this doesn't use the `unsafe` keyword):
275        //  -  `this.pointer` is a valid aligned pointer into a valid value of `T`.
276        //  -   The result is only usable for lifetime `'a`, and for the duration
277        //      of the lifetime `'a` `this` is mutably borrowed.
278        //  -   `this` has NUM/DEN of the right to mutate the value. So it can lend NUM/DEN
279        //      of the right to mutate the value. Therefore, this is semantically sound
280        //      according to the general principle of this library.
281        StaticRcRef {
282            pointer: this.pointer,
283            _marker: PhantomData,
284        }
285    }
286
287    /// Splits the current instance into two instances with the specified NUMerators.
288    ///
289    /// #   Example
290    ///
291    /// ```rust
292    /// use static_rc::StaticRcRef;
293    ///
294    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
295    ///
296    /// let mut value = 42;
297    /// let rc = Full::new(&mut value);
298    /// let (one, two) = Full::split::<1, 1>(rc);
299    ///
300    /// assert_eq!(42, *one);
301    /// assert_eq!(42, *two);
302    /// ```
303    #[inline(always)]
304    pub fn split<const A: usize, const B: usize>(this: Self) -> (StaticRcRef<'a, T, A, DEN>, StaticRcRef<'a, T, B, DEN>)
305    where
306        AssertLeType!(1, A): Sized,
307        AssertLeType!(1, B): Sized,
308        AssertEqType!(A + B, NUM): Sized,
309    {
310        #[cfg(not(feature = "compile-time-ratio"))]
311        const {
312            assert!(A > 0);
313            assert!(B > 0);
314            assert!(NUM == A + B);
315        }
316
317        let pointer = this.pointer;
318        let _marker = PhantomData;
319
320        (StaticRcRef { pointer, _marker, }, StaticRcRef { pointer, _marker, })
321    }
322
323    /// Splits the current instance into DIM instances with the specified Numerators.
324    ///
325    /// #   Example
326    ///
327    /// ```rust
328    /// use static_rc::StaticRcRef;
329    ///
330    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
331    ///
332    /// let mut value = 42;
333    /// let rc = Full::new(&mut value);
334    /// let array = Full::split_array::<1, 2>(rc);
335    ///
336    /// assert_eq!(42, *array[0]);
337    /// assert_eq!(42, *array[1]);
338    /// ```
339    #[inline(always)]
340    pub fn split_array<const N: usize, const DIM: usize>(this: Self) -> [StaticRcRef<'a, T, N, DEN>; DIM]
341    where
342        T: 'a,
343        AssertEqType!(N * DIM, NUM): Sized,
344        AssertLeType!(mem::size_of::<[StaticRcRef<'a, T, N, DEN>; DIM]>(), usize::MAX / 2 + 1): Sized,
345    {
346        #[cfg(not(feature = "compile-time-ratio"))]
347        const {
348            assert!(NUM == N * DIM);
349
350            assert!(mem::size_of::<[StaticRcRef<T, N, DEN>; DIM]>() <= (isize::MAX as usize));
351        }
352
353        let pointer = this.pointer;
354        let _marker = PhantomData;
355
356        let mut array = MaybeUninit::uninit();
357
358        for i in 0..DIM {
359            //  Safety:
360            //  -   `destination` within bounds of allocated array (< DIM).
361            //  -   Offset doesn't overflow `isize`, as per array-size assertion.
362            //  -   Offset doesn't wrap around, as per array-size assertion.
363            let destination = unsafe { (array.as_mut_ptr() as *mut StaticRcRef<T, N, DEN>).add(i) };
364
365            //  Safety:
366            //  -   `destination` is valid for writes.
367            //  -   `destination` is correctly aligned.
368            unsafe { ptr::write(destination, StaticRcRef { pointer, _marker, }); }
369        }
370
371        //  Safety:
372        //  -   Every element of the array is now initialized.
373        unsafe { array.assume_init() }
374    }
375
376    /// Joins two instances into a single instance.
377    ///
378    /// #   Panics
379    ///
380    /// If the two instances do no point to the same allocation, as determined by `StaticRcRef::ptr_eq`.
381    ///
382    /// #   Example
383    ///
384    /// ```rust
385    /// use static_rc::StaticRcRef;
386    ///
387    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
388    ///
389    /// let mut value = 42;
390    /// let rc = Full::new(&mut value);
391    /// let (one, two) = Full::split::<1, 1>(rc);
392    /// let rc = Full::join(one, two);
393    ///
394    /// assert_eq!(42, *rc);
395    /// ```
396    #[inline(always)]
397    pub fn join<const A: usize, const B: usize>(left: StaticRcRef<'a, T, A, DEN>, right: StaticRcRef<'a, T, B, DEN>) -> Self
398    where
399        AssertEqType!(NUM, A + B): Sized,
400    {
401        assert!(StaticRcRef::ptr_eq(&left, &right), "{:?} != {:?}", left.pointer.as_ptr(), right.pointer.as_ptr());
402
403        //  Safety:
404        //  -   `left` and `right` point to the same pointer.
405        unsafe { Self::join_unchecked(left, right) }
406    }
407
408    /// Joins two instances into a single instance without checking whether they point to the same allocation.
409    ///
410    /// Unless `compile-time-ratio` is activated, the ratios are checked nevertheless.
411    ///
412    /// # Safety
413    ///
414    /// The caller must guarantee that those instances point to the same allocation.
415    ///
416    /// #   Panics
417    ///
418    /// In debug, if the two instances do no point to the same allocation, as determined by `StaticRcRef::ptr_eq`.
419    ///
420    /// #   Example
421    ///
422    /// ```rust
423    /// use static_rc::StaticRcRef;
424    ///
425    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
426    ///
427    /// let mut value = 42;
428    /// let rc = Full::new(&mut value);
429    /// let (one, two) = Full::split::<1, 1>(rc);
430    /// let rc = unsafe { Full::join_unchecked(one, two) };
431    ///
432    /// assert_eq!(42, *rc);
433    /// ```
434    #[inline(always)]
435    pub unsafe fn join_unchecked<const A: usize, const B: usize>(
436        left: StaticRcRef<'a, T, A, DEN>,
437        _right: StaticRcRef<'a, T, B, DEN>,
438    ) -> Self
439    where
440        AssertEqType!(NUM, A + B): Sized,
441    {
442        #[cfg(not(feature = "compile-time-ratio"))]
443        const { assert!(NUM == A + B); }
444
445        debug_assert!(StaticRcRef::ptr_eq(&left, &_right), "{:?} != {:?}", left.pointer.as_ptr(), _right.pointer.as_ptr());
446
447        Self { pointer: left.pointer, _marker: PhantomData, }
448    }
449
450    /// Joins DIM instances into a single instance.
451    ///
452    /// #   Panics
453    ///
454    /// If all instances do not point to the same allocation, as determined by `StaticRcRef::ptr_eq`.
455    ///
456    /// #   Example
457    ///
458    /// ```rust
459    /// use static_rc::StaticRcRef;
460    ///
461    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
462    ///
463    /// let mut value = 42;
464    /// let rc = Full::new(&mut value);
465    /// let array = Full::split_array::<1, 2>(rc);
466    /// let rc = Full::join_array(array);
467    ///
468    /// assert_eq!(42, *rc);
469    /// ```
470    #[inline(always)]
471    pub fn join_array<const N: usize, const DIM: usize>(array: [StaticRcRef<'a, T, N, DEN>; DIM]) -> Self
472    where
473        AssertLeType!(1, NUM): Sized,
474        AssertEqType!(N * DIM, NUM): Sized,
475    {
476        let first = &array[0];
477        for successive in &array[1..] {
478            assert!(StaticRcRef::ptr_eq(first, successive),
479                "{:?} != {:?}", first.pointer.as_ptr(), successive.pointer.as_ptr());
480        }
481
482        //  Safety:
483        //  -   All instances point to the same allocation, as checked in the above loop.
484        unsafe { Self::join_array_unchecked(array) }
485    }
486
487    /// Joins DIM instances into a single instance.
488    ///
489    /// #   Safety
490    ///
491    /// All `StaticRcRef` joined must point to the same allocation, as determined by `StaticRcRef::ptr_eq`.
492    ///
493    /// #   Panics
494    ///
495    /// In debug, if all instances do not point to the same allocation, as determined by `StaticRcRef::ptr_eq`.
496    ///
497    /// #   Example
498    ///
499    /// ```rust
500    /// use static_rc::StaticRcRef;
501    ///
502    /// type Full<'a> = StaticRcRef<'a, i32, 2, 2>;
503    ///
504    /// let mut value = 42;
505    /// let rc = Full::new(&mut value);
506    /// let array = Full::split_array::<1, 2>(rc);
507    /// let rc = unsafe { Full::join_array_unchecked(array) };
508    ///
509    /// assert_eq!(42, *rc);
510    /// ```
511    #[inline(always)]
512    pub unsafe fn join_array_unchecked<const N: usize, const DIM: usize>(array: [StaticRcRef<'a, T, N, DEN>; DIM])
513        -> Self
514    where
515        AssertLeType!(1, NUM): Sized,
516        AssertEqType!(N * DIM, NUM): Sized,
517    {
518        #[cfg(not(feature = "compile-time-ratio"))]
519        const {
520            assert!(NUM > 0);
521            assert!(NUM == N * DIM);
522        }
523
524        let _first = &array[0];
525        for _successive in &array[1..] {
526            debug_assert!(StaticRcRef::ptr_eq(_first, _successive),
527                "{:?} != {:?}", _first.pointer.as_ptr(), _successive.pointer.as_ptr());
528        }
529
530        Self { pointer: array[0].pointer, _marker: PhantomData, }
531    }
532
533
534}
535
536impl<'a, const NUM: usize, const DEN: usize> StaticRcRef<'a, dyn any::Any, NUM, DEN> {
537    /// Attempts to downcast `Self` to a concrete type.
538    pub fn downcast<T: any::Any>(self) -> Result<StaticRcRef<'a, T, NUM, DEN>, Self> {
539        if Self::get_ref(&self).is::<T>() {
540            let pointer = Self::into_raw(self).cast::<T>();
541            Ok(StaticRcRef { pointer, _marker: PhantomData, })
542        } else {
543            Err(self)
544        }
545    }
546}
547
548impl<'a, T: ?Sized, const N: usize> convert::AsMut<T> for StaticRcRef<'a, T, N, N> {
549    #[inline(always)]
550    fn as_mut(&mut self) -> &mut T { Self::get_mut(self) }
551}
552
553impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> convert::AsRef<T> for StaticRcRef<'a, T, NUM, DEN> {
554    #[inline(always)]
555    fn as_ref(&self) -> &T { Self::get_ref(self) }
556}
557
558impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> borrow::Borrow<T> for StaticRcRef<'a, T, NUM, DEN> {
559    #[inline(always)]
560    fn borrow(&self) -> &T { Self::get_ref(self) }
561}
562
563impl<'a, T: ?Sized, const N: usize> borrow::BorrowMut<T> for StaticRcRef<'a, T, N, N> {
564    #[inline(always)]
565    fn borrow_mut(&mut self) -> &mut T { Self::get_mut(self) }
566}
567
568#[cfg(feature = "nightly-coerce-unsized")]
569impl<'a, T, U, const NUM: usize, const DEN: usize> CoerceUnsized<StaticRcRef<'a, U, NUM, DEN>> for StaticRcRef<'a, T, NUM, DEN>
570where
571    T: ?Sized + marker::Unsize<U>,
572    U: ?Sized,
573{}
574
575impl<'a, T: ?Sized + fmt::Debug, const NUM: usize, const DEN: usize> fmt::Debug for StaticRcRef<'a, T, NUM, DEN> {
576    #[inline(always)]
577    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
578        fmt::Debug::fmt(Self::get_ref(self), f)
579    }
580}
581
582impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> ops::Deref for StaticRcRef<'a, T, NUM, DEN> {
583    type Target = T;
584
585    #[inline(always)]
586    fn deref(&self) -> &T { Self::get_ref(self) }
587}
588
589impl<'a, T: ?Sized, const N: usize> ops::DerefMut for StaticRcRef<'a, T, N, N> {
590    #[inline(always)]
591    fn deref_mut(&mut self) -> &mut T { Self::get_mut(self) }
592}
593
594impl<'a, T: ?Sized + fmt::Display, const NUM: usize, const DEN: usize> fmt::Display for StaticRcRef<'a, T, NUM, DEN> {
595    #[inline(always)]
596    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
597        fmt::Display::fmt(Self::get_ref(self), f)
598    }
599}
600
601#[cfg(feature = "nightly-dispatch-from-dyn")]
602impl<'a, T, U, const NUM: usize, const DEN: usize> DispatchFromDyn<StaticRcRef<'a, U, NUM, DEN>> for StaticRcRef<'a, T, NUM, DEN>
603where
604    T: ?Sized + marker::Unsize<U>,
605    U: ?Sized,
606{}
607
608impl<'a, I: iter::DoubleEndedIterator + ?Sized, const N: usize> iter::DoubleEndedIterator for StaticRcRef<'a, I, N, N> {
609    #[inline(always)]
610    fn next_back(&mut self) -> Option<I::Item> { Self::get_mut(self).next_back() }
611
612    #[inline(always)]
613    fn nth_back(&mut self, n: usize) -> Option<I::Item> { Self::get_mut(self).nth_back(n) }
614}
615
616impl<'a, T: ?Sized + cmp::Eq, const NUM: usize, const DEN: usize> cmp::Eq for StaticRcRef<'a, T, NUM, DEN> {}
617
618impl<'a, I: iter::ExactSizeIterator + ?Sized, const N: usize> iter::ExactSizeIterator for StaticRcRef<'a, I, N, N> {
619    #[inline(always)]
620    fn len(&self) -> usize { Self::get_ref(self).len() }
621}
622
623impl<'a, const NUM: usize, const DEN: usize> From<StaticRcRef<'a, str, NUM, DEN>> for StaticRcRef<'a, [u8], NUM, DEN> {
624    #[inline(always)]
625    fn from(value: StaticRcRef<'a, str, NUM, DEN>) -> Self {
626        let pointer = value.pointer.as_ptr() as *mut [u8];
627
628        //  Safety:
629        //  -   `value.pointer` was not null, hence `pointer` is not null.
630        debug_assert!(!pointer.is_null());
631        let pointer = unsafe { NonNull::new_unchecked(pointer) };
632
633        Self { pointer, _marker: PhantomData, }
634    }
635}
636
637impl<'a, I: iter::FusedIterator + ?Sized, const N: usize> iter::FusedIterator for StaticRcRef<'a, I, N, N> {}
638
639impl<'a, F: ?Sized + future::Future + marker::Unpin, const N: usize> future::Future for StaticRcRef<'a, F, N, N> {
640    type Output = F::Output;
641
642    fn poll(mut self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
643        F::poll(pin::Pin::new(&mut *self), cx)
644    }
645}
646
647#[cfg(feature = "nightly-generator-trait")]
648impl<'a, G: ?Sized + ops::Generator<R> + marker::Unpin, R, const N: usize> ops::Generator<R> for StaticRcRef<'a, G, N, N> {
649    type Yield = G::Yield;
650    type Return = G::Return;
651
652        fn resume(mut self: pin::Pin<&mut Self>, arg: R) -> ops::GeneratorState<Self::Yield, Self::Return> {
653            G::resume(pin::Pin::new(&mut *self), arg)
654        }
655}
656
657#[cfg(feature = "nightly-generator-trait")]
658impl<'a, G: ?Sized + ops::Generator<R>, R, const N: usize> ops::Generator<R> for pin::Pin<StaticRcRef<'a, G, N, N>> {
659    type Yield = G::Yield;
660    type Return = G::Return;
661
662        fn resume(mut self: pin::Pin<&mut Self>, arg: R) -> ops::GeneratorState<Self::Yield, Self::Return> {
663            G::resume((*self).as_mut(), arg)
664        }
665}
666
667impl<'a, T: ?Sized + hash::Hash, const NUM: usize, const DEN: usize> hash::Hash for StaticRcRef<'a, T, NUM, DEN> {
668    #[inline(always)]
669    fn hash<H: hash::Hasher>(&self, state: &mut H) {
670        Self::get_ref(self).hash(state);
671    }
672}
673
674impl<'a, I: iter::Iterator + ?Sized, const N: usize> iter::Iterator for StaticRcRef<'a, I, N, N> {
675    type Item = I::Item;
676
677    #[inline(always)]
678    fn next(&mut self) -> Option<I::Item> { Self::get_mut(self).next() }
679
680    #[inline(always)]
681    fn size_hint(&self) -> (usize, Option<usize>) { Self::get_ref(self).size_hint() }
682
683    #[inline(always)]
684    fn nth(&mut self, n: usize) -> Option<I::Item> { Self::get_mut(self).nth(n) }
685
686    #[inline(always)]
687    fn last(mut self) -> Option<I::Item> { Self::get_mut(&mut self).last() }
688}
689
690impl<'a, T: ?Sized + cmp::Ord, const NUM: usize, const DEN: usize> cmp::Ord for StaticRcRef<'a, T, NUM, DEN> {
691    #[inline(always)]
692    fn cmp(&self, other: &Self) -> cmp::Ordering {
693        if Self::ptr_eq(self, other) {
694            cmp::Ordering::Equal
695        } else {
696            Self::get_ref(self).cmp(Self::get_ref(other))
697        }
698    }
699}
700
701impl<'a, T, const NUM: usize, const DEN: usize, const N: usize, const D: usize> cmp::PartialEq<StaticRcRef<'a, T, N, D>>
702    for StaticRcRef<'a, T, NUM, DEN>
703where
704    T: ?Sized + PartialEq<T>
705{
706    #[inline(always)]
707    fn eq(&self, other: &StaticRcRef<'a, T, N, D>) -> bool { Self::get_ref(self).eq(StaticRcRef::get_ref(other)) }
708
709    #[inline(always)]
710    #[allow(clippy::partialeq_ne_impl)]
711    fn ne(&self, other: &StaticRcRef<'a, T, N, D>) -> bool { Self::get_ref(self).ne(StaticRcRef::get_ref(other)) }
712}
713
714impl<'a, T, const NUM: usize, const DEN: usize, const N: usize, const D: usize> cmp::PartialOrd<StaticRcRef<'a, T, N, D>>
715    for StaticRcRef<'a, T, NUM, DEN>
716where
717    T: ?Sized + PartialOrd<T>
718{
719    #[inline(always)]
720    fn partial_cmp(&self, other: &StaticRcRef<'a, T, N, D>) -> Option<cmp::Ordering> {
721        Self::get_ref(self).partial_cmp(StaticRcRef::get_ref(other))
722    }
723
724    #[inline(always)]
725    fn lt(&self, other: &StaticRcRef<'a, T, N, D>) -> bool {
726        Self::get_ref(self).lt(StaticRcRef::get_ref(other))
727    }
728
729    #[inline(always)]
730    fn le(&self, other: &StaticRcRef<'a, T, N, D>) -> bool {
731        Self::get_ref(self).le(StaticRcRef::get_ref(other))
732    }
733
734    #[inline(always)]
735    fn gt(&self, other: &StaticRcRef<'a, T, N, D>) -> bool {
736        Self::get_ref(self).gt(StaticRcRef::get_ref(other))
737    }
738
739    #[inline(always)]
740    fn ge(&self, other: &StaticRcRef<'a, T, N, D>) -> bool {
741        Self::get_ref(self).ge(StaticRcRef::get_ref(other))
742    }
743}
744
745impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> fmt::Pointer for StaticRcRef<'a, T, NUM, DEN> {
746    #[inline(always)]
747    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
748        fmt::Pointer::fmt(&Self::as_ptr(self).as_ptr(), f)
749    }
750}
751
752#[cfg(feature = "nightly-async-iterator")]
753impl<'a, S: ?Sized + async_iter::AsyncIterator + marker::Unpin, const N: usize> async_iter::AsyncIterator for StaticRcRef<'a, S, N, N> {
754    type Item = S::Item;
755
756    fn poll_next(mut self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Option<Self::Item>> {
757        pin::Pin::new(&mut **self).poll_next(cx)
758    }
759
760    fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
761}
762
763impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> marker::Unpin for StaticRcRef<'a, T, NUM, DEN> {}
764
765unsafe impl<'a, T: ?Sized + marker::Send, const NUM: usize, const DEN: usize> marker::Send for StaticRcRef<'a, T, NUM, DEN> {}
766
767unsafe impl<'a, T: ?Sized + marker::Sync, const NUM: usize, const DEN: usize> marker::Sync for StaticRcRef<'a, T, NUM, DEN> {}
768
769#[doc(hidden)]
770pub mod compile_tests {
771
772/// ```compile_fail,E0597
773/// let a = String::from("foo");
774/// let mut a_ref = &a;
775/// let mut rc = static_rc::StaticRcRef::<'_, _,1,1>::new(&mut a_ref);
776/// {
777///     let b = String::from("bar");
778///     *rc = &b; // a_ref now points to b
779/// }
780/// // b is now dropped
781/// assert_ne!(a_ref, "bar");  // This should fail to compile.
782/// ```
783pub fn rcref_prevent_use_after_free() {}
784
785/// ```compile_fail,E0505
786/// let mut a = String::from("foo");
787/// let mut rc = static_rc::StaticRcRef::<'_, _,1,1>::new(&mut a);
788///
789/// let mut reborrow = static_rc::StaticRcRef::reborrow(&mut rc);
790/// std::mem::drop(rc);
791/// assert_eq!(*reborrow, "foo"); // This should fail to compile.
792/// ```
793pub fn rcref_reborrow_and_move() {}
794
795/// ```compile_fail,E0502
796/// let mut a = String::from("foo");
797/// let mut rc = static_rc::StaticRcRef::<'_, _,1,1>::new(&mut a);
798///
799/// let mut reborrow = static_rc::StaticRcRef::reborrow(&mut rc);
800/// assert_eq!(*rc, "foo");
801/// assert_eq!(*reborrow, "foo"); // This should fail to compile.
802/// ```
803pub fn rcref_reborrow_and_use() {}
804
805} // mod compile_tests
806
807#[doc(hidden)]
808pub mod compile_ratio_tests {
809
810/// ```compile_fail,E0080
811/// type Zero<'a> = static_rc::StaticRcRef<'a, i32, 0, 0>;
812///
813/// let mut value = 42;
814///
815/// Zero::new(&mut value);
816/// ```
817pub fn rcref_new_zero() {}
818
819/// ```compile_fail,E0080
820/// type Zero<'a> = static_rc::StaticRcRef<'a, i32, 0, 0>;
821///
822/// let pointer = core::ptr::NonNull::dangling();
823///
824/// unsafe { Zero::from_raw(pointer) };
825/// ```
826pub fn rcref_from_raw_zero() {}
827
828/// ```compile_fail,E0080
829/// type One<'a> = static_rc::StaticRcRef<'a, i32, 1, 1>;
830///
831/// let mut value = 42;
832/// let rc = One::new(&mut value);
833///
834/// One::adjust::<0, 0>(rc);
835/// ```
836pub fn rcref_adjust_zero() {}
837
838/// ```compile_fail,E0080
839/// type One<'a> = static_rc::StaticRcRef<'a, i32, 1, 1>;
840///
841/// let mut value = 42;
842/// let rc = One::new(&mut value);
843///
844/// One::adjust::<2, 3>(rc);
845/// ```
846pub fn rcref_adjust_ratio() {}
847
848/// ```compile_fail,E0080
849/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
850///
851/// let mut value = 42;
852/// let rc = Two::new(&mut value);
853///
854/// Two::split::<0, 2>(rc);
855/// ```
856pub fn rcref_split_zero_first() {}
857
858/// ```compile_fail,E0080
859/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
860///
861/// let mut value = 42;
862/// let rc = Two::new(&mut value);
863///
864/// Two::split::<2, 0>(rc);
865/// ```
866pub fn rcref_split_zero_second() {}
867
868/// ```compile_fail,E0080
869/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
870///
871/// let mut value = 42;
872/// let rc = Two::new(&mut value);
873///
874/// Two::split::<1, 2>(rc);
875/// ```
876pub fn rcref_split_sum() {}
877
878/// ```compile_fail,E0080
879/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
880///
881/// let mut value = 42;
882/// let rc = Two::new(&mut value);
883///
884/// Two::split_array::<2, 2>(rc);
885/// ```
886pub fn rcref_split_array_ratio() {}
887
888/// ```compile_fail,E0080
889/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
890///
891/// let mut value = 42;
892/// let rc = Two::new(&mut value);
893/// let (one, two) = Two::split::<1, 1>(rc);
894///
895/// static_rc::StaticRcRef::<'_, _, 1, 2>::join(one, two);
896/// ```
897pub fn rcref_join_ratio() {}
898
899/// ```compile_fail,E0080
900/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
901///
902/// let mut value = 42;
903/// let rc = Two::new(&mut value);
904/// let (one, two) = Two::split::<1, 1>(rc);
905///
906/// unsafe { static_rc::StaticRcRef::<'_, _, 1, 2>::join_unchecked(one, two) };
907/// ```
908pub fn rcref_join_unchecked_ratio() {}
909
910/// ```compile_fail,E0080
911/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
912///
913/// let mut value = 42;
914/// let rc = Two::new(&mut value);
915/// let array: [_; 2] = Two::split_array::<1, 2>(rc);
916///
917/// static_rc::StaticRcRef::<'_, _, 1, 2>::join_array(array);
918/// ```
919pub fn rcref_join_array_ratio() {}
920
921/// ```compile_fail,E0080
922/// type Two<'a> = static_rc::StaticRcRef<'a, i32, 2, 2>;
923///
924/// let mut value = 42;
925/// let rc = Two::new(&mut value);
926/// let array: [_; 2] = Two::split_array::<1, 2>(rc);
927///
928/// unsafe { static_rc::StaticRcRef::<'_, _, 1, 2>::join_array_unchecked(array) };
929/// ```
930pub fn rcref_join_array_unchecked_ratio() {}
931
932} // mod compile_ratio_tests