static_rc/
rc.rs

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