1#![warn(missing_docs, missing_debug_implementations)]
13#![no_std]
14
15extern crate alloc;
16#[cfg(feature = "std")]
17extern crate std;
18
19#[cfg(feature = "erasable")]
20use erasable::{Erasable, ErasablePtr, ErasedPtr};
21#[cfg(feature = "slice-dst")]
22use slice_dst::{AllocSliceDst, SliceDst, TryAllocSliceDst};
23#[cfg(feature = "std")]
24use std::panic::UnwindSafe;
25use {
26 alloc::{boxed::Box, rc::Rc, string::String, sync::Arc, vec::Vec},
27 core::{
28 any::Any,
29 borrow::{Borrow, BorrowMut},
30 cmp::Ordering,
31 convert::{TryFrom, TryInto},
32 fmt::{self, Debug, Display, Formatter, Pointer},
33 hash::{Hash, Hasher},
34 hint::unreachable_unchecked,
35 iter::{FromIterator, FusedIterator},
36 marker::PhantomData,
37 mem::ManuallyDrop,
38 ops::{Deref, DerefMut},
39 pin::Pin,
40 ptr,
41 },
42};
43
44macro_rules! doc_comment {
45 ($x:expr, $($tt:tt)*) => {
46 #[doc = $x]
47 $($tt)*
48 };
49}
50
51macro_rules! rc_box {
52 ($($(#[$m:meta])* $RcBox:ident = $Rc:ident)*) => {$(
53 $(#[$m])*
54 pub struct $RcBox<T: ?Sized> {
55 raw: ptr::NonNull<T>,
56 marker: PhantomData<$Rc<T>>,
57 }
58
59 unsafe impl<T: ?Sized> Send for $RcBox<T> where Box<T>: Send {}
60 unsafe impl<T: ?Sized> Sync for $RcBox<T> where Box<T>: Sync {}
61
62 impl<T: ?Sized> Drop for $RcBox<T> {
63 fn drop(&mut self) {
64 unsafe { drop($Rc::<T>::from(ptr::read(self))) }
65 }
66 }
67
68 impl<T: ?Sized> From<$RcBox<T>> for $Rc<T> {
69 fn from(v: $RcBox<T>) -> $Rc<T> {
70 unsafe { $Rc::from_raw($RcBox::into_raw(v).as_ptr()) }
71 }
72 }
73
74 impl<T: ?Sized> TryFrom<$Rc<T>> for $RcBox<T> {
75 type Error = $Rc<T>;
76 fn try_from(mut v: $Rc<T>) -> Result<$RcBox<T>, $Rc<T>> {
77 if $Rc::get_mut(&mut v).is_some() {
80 unsafe { Ok($RcBox::from_raw($Rc::into_raw(v))) }
81 } else {
82 Err(v)
83 }
84 }
85 }
86
87 impl<T: ?Sized> TryFrom<Pin<$Rc<T>>> for Pin<$RcBox<T>> {
88 type Error = Pin<$Rc<T>>;
89 fn try_from(v: Pin<$Rc<T>>) -> Result<Pin<$RcBox<T>>, Pin<$Rc<T>>> {
90 unsafe {
91 let v = Pin::into_inner_unchecked(v);
92 match $RcBox::<T>::try_from(v) {
93 Ok(this) => Ok(Pin::new_unchecked(this)),
94 Err(v) => Err(Pin::new_unchecked(v)),
95 }
96 }
97 }
98 }
99
100 impl<T: ?Sized> $RcBox<T> {
101 unsafe fn from_unchecked<V>(v: V) -> Self
102 where
103 V: TryInto<$RcBox<T>>,
104 {
105 v.try_into().unwrap_or_else(|_| unreachable_unchecked())
106 }
107 }
108
109 impl $RcBox<dyn Any + 'static> {
112 doc_comment! {
113 concat!("Attempt to downcast the box to a concrete type.
114
115# Examples
116
117```rust
118# use rc_box::*; use std::convert::TryInto;
119# use std::rc::Rc; use std::sync::Arc;
120use std::any::Any;
121
122fn print_if_string(value: ", stringify!($RcBox), r#"<dyn Any>) {
123 if let Ok(string) = value.downcast::<String>() {
124 println!("String ({}): {}", string.len(), string);
125 }
126}
127
128let my_string = "Hello World".to_string();
129let my_string: "#, stringify!($Rc), "<dyn Any> = ", stringify!($Rc), "::new(my_string);
130print_if_string(my_string.try_into().unwrap());
131let my_number: ", stringify!($Rc), "<dyn Any> = ", stringify!($Rc), "::new(0i8);
132print_if_string(my_number.try_into().unwrap());
133```
134
135The unsizing as `", stringify!($Rc), "` is required until
136[DST coercions](https://github.com/rust-lang/rust/issues/27732) are stabilized. Alternatively,
137activate the `unsize` feature to convert the pointer via an explicit method call."),
138 #[inline]
139 pub fn downcast<T>(self) -> Result<$RcBox<T>, Self>
140 where T: Any,
141 {
142 if self.is::<T>() {
143 unsafe {
144 let raw: *mut dyn Any = Self::into_raw(self).as_ptr();
145 Ok($RcBox::from_raw(raw as *mut T))
146 }
147 } else {
148 Err(self)
149 }
150 }
151 }
152 }
153
154 impl $RcBox<dyn Any + 'static + Send> {
155 doc_comment! {
156 concat!("Attempt to downcast the box to a concrete type.
157
158# Examples
159
160```rust
161# use rc_box::*; use std::convert::TryInto;
162# use std::rc::Rc; use std::sync::Arc;
163use std::any::Any;
164
165fn print_if_string(value: ", stringify!($RcBox), r#"<dyn Any + Send>) {
166 if let Ok(string) = value.downcast::<String>() {
167 println!("String ({}): {}", string.len(), string);
168 }
169}
170
171let my_string = "Hello World".to_string();
172let my_string: "#, stringify!($Rc), "<dyn Any + Send> = ", stringify!($Rc), "::new(my_string);
173print_if_string(my_string.try_into().unwrap());
174let my_number: ", stringify!($Rc), "<dyn Any + Send> = ", stringify!($Rc), "::new(0i8);
175print_if_string(my_number.try_into().unwrap());
176```
177
178The unsizing as `", stringify!($Rc), "` is required until
179[DST coercions](https://github.com/rust-lang/rust/issues/27732) are stabilized. Alternatively,
180activate the `unsize` feature to convert the pointer via an explicit method call."),
181 #[inline]
182 pub fn downcast<T>(self) -> Result<$RcBox<T>, Self>
183 where T: Any + Send
184 {
185 if self.is::<T>() {
186 unsafe {
187 let raw: *mut (dyn Any + Send) = Self::into_raw(self).as_ptr();
188 Ok($RcBox::from_raw(raw as *mut T))
189 }
190 } else {
191 Err(self)
192 }
193 }
194 }
195 }
196
197 impl $RcBox<dyn Any + 'static + Send + Sync> {
198 doc_comment! {
199 concat!("Attempt to downcast the box to a concrete type.
200
201# Examples
202
203```rust
204# use rc_box::*; use std::convert::TryInto;
205# use std::rc::Rc; use std::sync::Arc;
206use std::any::Any;
207
208fn print_if_string(value: ", stringify!($RcBox), r#"<dyn Any + Send + Sync>) {
209 if let Ok(string) = value.downcast::<String>() {
210 println!("String ({}): {}", string.len(), string);
211 }
212}
213
214let my_string = "Hello World".to_string();
215let my_string: "#, stringify!($Rc), "<dyn Any + Send + Sync> = ", stringify!($Rc), "::new(my_string);
216print_if_string(my_string.try_into().unwrap());
217let my_number: ", stringify!($Rc), "<dyn Any + Send + Sync> = ", stringify!($Rc), "::new(0i8);
218print_if_string(my_number.try_into().unwrap());
219```
220
221The unsizing as `", stringify!($Rc), "` is required until
222[DST coercions](https://github.com/rust-lang/rust/issues/27732) are stabilized. Alternatively,
223activate the `unsize` feature to convert the pointer via an explicit method call."),
224 #[inline]
225 pub fn downcast<T>(self) -> Result<$RcBox<T>, Self>
226 where T: Any + Send + Sync
227 {
228 if self.is::<T>() {
229 unsafe {
230 let raw: *mut (dyn Any + Send + Sync) = Self::into_raw(self).as_ptr();
231 Ok($RcBox::from_raw(raw as *mut T))
232 }
233 } else {
234 Err(self)
235 }
236 }
237 }
238 }
239
240 impl<T: ?Sized> $RcBox<T> {
241 doc_comment! {
244 concat!("Construct an ", stringify!($RcBox), " from a raw pointer.
245
246# Safety
247
248The raw pointer must have previously been acquired by a call to [`",
249stringify!($RcBox), "::into_raw`], or [`", stringify!($Rc), "::into_raw`]
250where the `", stringify!($Rc), "` is known unique."),
251 pub unsafe fn from_raw(ptr: *const T) -> Self {
252 $RcBox {
253 raw: ptr::NonNull::new_unchecked(ptr as *mut _),
255 marker: PhantomData,
256 }
257 }
258 }
259
260 doc_comment! {
261 concat!("Get a mutable reference into the `", stringify!($RcBox), "`.
262
263This method exists only for API compatibility with `", stringify!($Rc), "`.
264Use `DerefMut` instead."),
265 #[deprecated(note = "Use [`DerefMut`](#impl-DerefMut) instead")]
266 pub fn get_mut(this: &mut Self) -> Option<&mut T> {
267 Some(&mut **this)
268 }
269 }
270
271 doc_comment! {
272 concat!("Get a mutable reference into the `", stringify!($RcBox), "`.
273
274This method exists only for API compatibility with `", stringify!($Rc), "`.
275Use `DerefMut` instead."),
276 #[deprecated(note = "Use [`DerefMut`](#impl-DerefMut) instead")]
277 pub fn get_mut_unchecked(this: &mut Self) -> &mut T {
278 &mut **this
279 }
280 }
281
282 doc_comment! {
283 concat!("\
284Returns a raw pointer to the object `T` pointed to by this `", stringify!($RcBox), "`.
285
286Note that this returns a [`ptr::NonNull`], not a raw pointer.
287That makes this function equivalent to `as_raw_non_null`."),
288 pub fn as_raw(this: &Self) -> ptr::NonNull<T> {
289 this.raw
290 }
291 }
292
293 doc_comment! {
294 concat!("\
295Consume the `", stringify!($RcBox), "`, returning the wrapped pointer.
296
297To avoid a memory leak, the pointer must be converted back to a `",
298stringify!($RcBox), "`, using [`", stringify!($RcBox), "::from_raw`],
299or directly into a `", stringify!($Rc), "`, using [`", stringify!($Rc), "::from_raw`].
300
301Note that this returns a [`ptr::NonNull`], not a raw pointer.
302That makes this function equivalent to `into_raw_non_null`."),
303 pub fn into_raw(this: Self) -> ptr::NonNull<T> {
304 $RcBox::as_raw(&ManuallyDrop::new(this))
305 }
306 }
307
308 doc_comment! {
309 concat!("Consume and leak the `", stringify!($RcBox), "`."),
310 pub fn leak<'a>(this: Self) -> &'a mut T
311 where
312 T: 'a,
313 {
314 unsafe { &mut *$RcBox::into_raw(this).as_ptr() }
315 }
316 }
317
318 doc_comment! {
319 concat!("Create a new ", stringify!($RcBox), "."),
320 pub fn new(data: T) -> Self
321 where
322 T: Sized,
323 {
324 unsafe { $RcBox::from_unchecked($Rc::new(data)) }
325 }
326 }
327
328 doc_comment! {
331 concat!("\
332Construct a new `Pin<", stringify!($RcBox), "<T>>`. If `T` does not implement [`Unpin`],
333then the data will be pinned in memory and unable to be moved."),
334 pub fn pin(x: T) -> Pin<$RcBox<T>>
335 where
336 T: Sized,
337 {
338 unsafe {
339 Pin::new_unchecked($RcBox::from_unchecked(
340 Pin::into_inner_unchecked($Rc::pin(x))
341 ))
342 }
343 }
344 }
345
346 doc_comment! {
347 concat!("Deconstruct this `", stringify!($RcBox), "`, returning the inner value."),
348 pub fn into_inner(this: Self) -> T
349 where
350 T: Sized,
351 {
352 let rc: $Rc<T> = this.into();
353 $Rc::try_unwrap(rc).unwrap_or_else(|_| unsafe { unreachable_unchecked() })
354 }
355 }
356 }
357
358 #[cfg(feature = "erasable")]
361 unsafe impl<T: ?Sized> ErasablePtr for $RcBox<T>
362 where
363 T: Erasable
364 {
365 fn erase(this: Self) -> ErasedPtr {
366 T::erase($RcBox::into_raw(this))
367 }
368
369 unsafe fn unerase(this: ErasedPtr) -> Self {
370 $RcBox::from_raw(T::unerase(this).as_ptr())
371 }
372 }
373
374 #[cfg(feature = "slice-dst")]
375 unsafe impl<S: ?Sized + SliceDst> AllocSliceDst<S> for $RcBox<S> {
376 unsafe fn new_slice_dst<I>(len: usize, init: I) -> Self
377 where
378 I: FnOnce(ptr::NonNull<S>),
379 {
380 Self::from_unchecked($Rc::new_slice_dst(len, init))
381 }
382 }
383 #[cfg(feature = "slice-dst")]
384 unsafe impl<S: ?Sized + SliceDst> TryAllocSliceDst<S> for $RcBox<S> {
385 unsafe fn try_new_slice_dst<I, E>(len: usize, init: I) -> Result<Self, E>
386 where
387 I: FnOnce(ptr::NonNull<S>) -> Result<(), E>,
388 {
389 $Rc::try_new_slice_dst(len, init).map(|x| Self::from_unchecked(x))
390 }
391 }
392
393 impl<T: ?Sized> AsMut<T> for $RcBox<T> {
394 fn as_mut(&mut self) -> &mut T {
395 &mut **self
396 }
397 }
398
399 impl<T: ?Sized> AsRef<T> for $RcBox<T> {
400 fn as_ref(&self) -> &T {
401 &**self
402 }
403 }
404
405 impl<T: ?Sized> Borrow<T> for $RcBox<T> {
406 fn borrow(&self) -> &T {
407 &**self
408 }
409 }
410
411 impl<T: ?Sized> BorrowMut<T> for $RcBox<T> {
412 fn borrow_mut(&mut self) -> &mut T {
413 &mut **self
414 }
415 }
416
417 impl<T: ?Sized> Debug for $RcBox<T>
420 where
421 T: Debug,
422 {
423 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
424 (**self).fmt(f)
425 }
426 }
427
428 impl<T: ?Sized> Deref for $RcBox<T> {
429 type Target = T;
430 fn deref(&self) -> &T {
431 unsafe { self.raw.as_ref() }
432 }
433 }
434
435 impl<T: ?Sized> DerefMut for $RcBox<T> {
436 fn deref_mut(&mut self) -> &mut T {
437 unsafe { self.raw.as_mut() }
438 }
439 }
440
441 impl<T: ?Sized> Display for $RcBox<T>
444 where
445 T: Display,
446 {
447 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
448 (**self).fmt(f)
449 }
450 }
451
452 impl<T: ?Sized> DoubleEndedIterator for $RcBox<T>
453 where
454 T: DoubleEndedIterator,
455 {
456 fn next_back(&mut self) -> Option<Self::Item> {
457 (**self).next_back()
458 }
459
460 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
461 (**self).nth_back(n)
462 }
463 }
464
465 impl<T: ?Sized> Eq for $RcBox<T> where T: Eq {}
466
467 impl<T: ?Sized> ExactSizeIterator for $RcBox<T> where T: ExactSizeIterator {}
468
469 impl<T> From<&'_ [T]> for $RcBox<[T]>
472 where
473 T: Clone
474 {
475 fn from(v: &[T]) -> Self {
476 unsafe { $RcBox::from_unchecked($Rc::from(v)) }
477 }
478 }
479
480 impl From<&'_ str> for $RcBox<str> {
481 fn from(v: &str) -> Self {
482 unsafe { $RcBox::from_unchecked($Rc::from(v)) }
483 }
484 }
485
486 impl<T: ?Sized> From<Box<T>> for $RcBox<T> {
487 fn from(v: Box<T>) -> Self {
488 unsafe { $RcBox::from_unchecked($Rc::from(v)) }
489 }
490 }
491
492 impl From<String> for $RcBox<str> {
493 fn from(v: String) -> Self {
494 unsafe { $RcBox::from_unchecked($Rc::from(v)) }
495 }
496 }
497
498 impl<T> From<T> for $RcBox<T> {
499 fn from(v: T) -> Self {
500 unsafe { $RcBox::from_unchecked($Rc::from(v)) }
501 }
502 }
503
504 impl<T> From<Vec<T>> for $RcBox<[T]> {
505 fn from(v: Vec<T>) -> Self {
506 unsafe { $RcBox::from_unchecked($Rc::from(v)) }
507 }
508 }
509
510 impl<T> FromIterator<T> for $RcBox<[T]> {
511 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
512 unsafe { $RcBox::from_unchecked($Rc::from_iter(iter)) }
513 }
514 }
515
516 impl<T: ?Sized> FusedIterator for $RcBox<T> where T: FusedIterator {}
517
518 impl<T: ?Sized> Hash for $RcBox<T>
521 where
522 T: Hash,
523 {
524 fn hash<H: Hasher>(&self, state: &mut H) {
525 (**self).hash(state)
526 }
527 }
528
529 impl<T: ?Sized> Hasher for $RcBox<T>
530 where
531 T: Hasher,
532 {
533 fn finish(&self) -> u64 {
534 (**self).finish()
535 }
536
537 fn write(&mut self, bytes: &[u8]) {
538 (**self).write(bytes)
539 }
540
541 fn write_u8(&mut self, i: u8) {
542 (**self).write_u8(i)
543 }
544
545 fn write_u16(&mut self, i: u16) {
546 (**self).write_u16(i)
547 }
548
549 fn write_u32(&mut self, i: u32) {
550 (**self).write_u32(i)
551 }
552
553 fn write_u64(&mut self, i: u64) {
554 (**self).write_u64(i)
555 }
556
557 fn write_u128(&mut self, i: u128) {
558 (**self).write_u128(i)
559 }
560
561 fn write_usize(&mut self, i: usize) {
562 (**self).write_usize(i)
563 }
564
565 fn write_i8(&mut self, i: i8) {
566 (**self).write_i8(i)
567 }
568
569 fn write_i16(&mut self, i: i16) {
570 (**self).write_i16(i)
571 }
572
573 fn write_i32(&mut self, i: i32) {
574 (**self).write_i32(i)
575 }
576
577 fn write_i64(&mut self, i: i64) {
578 (**self).write_i64(i)
579 }
580
581 fn write_i128(&mut self, i: i128) {
582 (**self).write_i128(i)
583 }
584
585 fn write_isize(&mut self, i: isize) {
586 (**self).write_isize(i)
587 }
588 }
589
590 impl<T: ?Sized> Iterator for $RcBox<T>
591 where
592 T: Iterator
593 {
594 type Item = T::Item;
595
596 fn next(&mut self) -> Option<Self::Item> {
597 (**self).next()
598 }
599
600 fn size_hint(&self) -> (usize, Option<usize>) {
601 (**self).size_hint()
602 }
603
604 fn nth(&mut self, n: usize) -> Option<Self::Item> {
605 (**self).nth(n)
606 }
607 }
608
609 impl<T: ?Sized> Ord for $RcBox<T>
610 where
611 T: Ord,
612 {
613 fn cmp(&self, other: &Self) -> Ordering {
614 (**self).cmp(other)
615 }
616 }
617
618 impl<T: ?Sized, O> PartialEq<O> for $RcBox<T>
619 where
620 O: Deref,
621 T: PartialEq<O::Target>,
622 {
623 fn eq(&self, other: &O) -> bool {
624 (**self).eq(&*other)
625 }
626 }
627
628 impl<T: ?Sized, O> PartialOrd<O> for $RcBox<T>
629 where
630 O: Deref,
631 T: PartialOrd<O::Target>,
632 {
633 fn partial_cmp(&self, other: &O) -> Option<Ordering> {
634 (**self).partial_cmp(other)
635 }
636 }
637
638 impl<T: ?Sized> Pointer for $RcBox<T> {
639 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
640 fmt::Pointer::fmt(&&**self, f)
641 }
642 }
643
644 impl<T: ?Sized> Unpin for $RcBox<T> {}
648
649 #[cfg(feature = "std")]
650 impl<T: ?Sized> UnwindSafe for $RcBox<T> where Box<T>: UnwindSafe {}
651
652 #[cfg(feature = "unsize")]
653 doc_comment! {
654 concat!("Unsizes a pointer using the `unsize` crate.
655
656# Usage
657
658```
659# use rc_box::*;
660use unsize::{Coercion, CoerceUnsize};
661
662let unique = ", stringify!($RcBox), "::new(|| 42u32);
663let unique:", stringify!($RcBox), r"<dyn Fn() -> u32> =
664 unique.unsize(Coercion::<_, dyn Fn() -> u32>::to_fn());
665
666let value = (*unique)();
667assert_eq!(value, 42);
668```
669
670Another common usage would be to create a `dyn Any`.
671
672fn print_if_string(value: ", stringify!($RcBox), r#"<dyn Any>) {
673 if let Ok(string) = value.downcast::<String>() {
674 println!("String ({}): {}", string.len(), string);
675 }
676}
677
678let my_string = "Hello World".to_string();
679let my_string: "#, stringify!($RcBox), "<dyn Any> = ", stringify!($RcBox), "::new(my_string).unsize(Coercion::to_any());
680print_if_string(my_string);
681let my_number: ", stringify!($RcBox), "<dyn Any> = ", stringify!($RcBox), "::new(0i8).unsize(Coercion::to_any());
682print_if_string(my_number);
683```"),
684 unsafe impl<T, U: ?Sized> unsize::CoerciblePtr<U> for $RcBox<T> {
685 type Pointee = T;
686 type Output = $RcBox<U>;
687 fn as_sized_ptr(&mut self) -> *mut T {
688 $RcBox::as_raw(self).as_ptr()
689 }
690 unsafe fn replace_ptr(self, new: *mut U) -> $RcBox<U> {
691 let new = $RcBox::into_raw(self).replace_ptr(new);
692 $RcBox::from_raw(new.as_ptr() as *const U)
693 }
694 }
695 }
696 )*};
697}
698
699rc_box! {
700 #[repr(transparent)]
705 ArcBox = Arc
706 #[repr(transparent)]
711 RcBox = Rc
712}