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