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