@@ -244,6 +244,7 @@ use boxed::Box;
244
244
#[ cfg( test) ]
245
245
use std:: boxed:: Box ;
246
246
247
+ use core:: any:: Any ;
247
248
use core:: borrow;
248
249
use core:: cell:: Cell ;
249
250
use core:: cmp:: Ordering ;
@@ -608,6 +609,46 @@ impl<T: Clone> Rc<T> {
608
609
}
609
610
}
610
611
612
+ impl Rc < Any > {
613
+ #[ inline]
614
+ #[ unstable( feature = "rc_downcast" , issue = "0" ) ]
615
+ /// Attempt to downcast the `Rc<Any>` to a concrete type.
616
+ ///
617
+ /// # Examples
618
+ ///
619
+ /// ```
620
+ /// #![feature(rc_downcast)]
621
+ /// use std::any::Any;
622
+ /// use std::rc::Rc;
623
+ ///
624
+ /// fn print_if_string(value: Rc<Any>) {
625
+ /// if let Ok(string) = value.downcast::<String>() {
626
+ /// println!("String ({}): {}", string.len(), string);
627
+ /// }
628
+ /// }
629
+ ///
630
+ /// fn main() {
631
+ /// let my_string = "Hello World".to_string();
632
+ /// print_if_string(Rc::new(my_string));
633
+ /// print_if_string(Rc::new(0i8));
634
+ /// }
635
+ /// ```
636
+ pub fn downcast < T : Any > ( self ) -> Result < Rc < T > , Rc < Any > > {
637
+ if ( * self ) . is :: < T > ( ) {
638
+ // avoid the pointer arithmetic in from_raw
639
+ unsafe {
640
+ let raw: * const RcBox < Any > = self . ptr . as_ptr ( ) ;
641
+ forget ( self ) ;
642
+ Ok ( Rc {
643
+ ptr : Shared :: new_unchecked ( raw as * const RcBox < T > as * mut _ ) ,
644
+ } )
645
+ }
646
+ } else {
647
+ Err ( self )
648
+ }
649
+ }
650
+ }
651
+
611
652
impl < T : ?Sized > Rc < T > {
612
653
// Allocates an `RcBox<T>` with sufficient space for an unsized value
613
654
unsafe fn allocate_for_ptr ( ptr : * const T ) -> * mut RcBox < T > {
@@ -1696,6 +1737,26 @@ mod tests {
1696
1737
1697
1738
assert_eq ! ( & r[ ..] , [ 1 , 2 , 3 ] ) ;
1698
1739
}
1740
+
1741
+ #[ test]
1742
+ fn test_downcast ( ) {
1743
+ use std:: any:: Any ;
1744
+
1745
+ let r1: Rc < Any > = Rc :: new ( i32:: max_value ( ) ) ;
1746
+ let r2: Rc < Any > = Rc :: new ( "abc" ) ;
1747
+
1748
+ assert ! ( r1. clone( ) . downcast:: <u32 >( ) . is_err( ) ) ;
1749
+
1750
+ let r1i32 = r1. downcast :: < i32 > ( ) ;
1751
+ assert ! ( r1i32. is_ok( ) ) ;
1752
+ assert_eq ! ( r1i32. unwrap( ) , Rc :: new( i32 :: max_value( ) ) ) ;
1753
+
1754
+ assert ! ( r2. clone( ) . downcast:: <i32 >( ) . is_err( ) ) ;
1755
+
1756
+ let r2str = r2. downcast :: < & ' static str > ( ) ;
1757
+ assert ! ( r2str. is_ok( ) ) ;
1758
+ assert_eq ! ( r2str. unwrap( ) , Rc :: new( "abc" ) ) ;
1759
+ }
1699
1760
}
1700
1761
1701
1762
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments