How to build an Rc or Rc<[T]>?

前端 未结 2 997
粉色の甜心
粉色の甜心 2020-12-10 11:23

I\'d like to create an Rc because I want reduce the indirection from following the 2 pointers that accessing an Rc require

相关标签:
2条回答
  • 2020-12-10 12:04

    Creating an Rc<[T]> can be done via coercions and as-casts from fixed sized arrays, e.g. coercions can be done as follows:

    use std::rc::Rc;
    
    fn main() {
        let x: Rc<[i32; 4]> = Rc::new([1, 2, 3, 4]);
    
        let y: Rc<[i32]> = x;
    
        println!("{:?}", y);
    }
    

    However, this doesn't work for strings, since they have no raw fixed-sized equivalent to create the first value. It is possible to do unsafely, e.g. by creating a UTF-8 encoded Rc<[u8]> and transmuting that to Rc<str>. Theoretically there could be a crate on crates.io for it, but I can't find one at the moment.

    An alternative is owning_ref, which isn't quite std::rc::Rc itself, but should allow, for example, getting an RcRef<..., str> pointing into an Rc<String>. (This approach will work best if one uses RcRef uniformly in place of Rc, except for construction.)

    extern crate owning_ref;
    use owning_ref::RcRef;
    use std::rc::Rc;
    
    fn main() {
        let some_string = "foo".to_owned();
    
        let val: RcRef<String> = RcRef::new(Rc::new(some_string));
    
        let borrowed: RcRef<String, str> = val.map(|s| &**s);
    
        let erased: RcRef<owning_ref::Erased, str> = borrowed.erase_owner();
    }
    

    The erasing means that RcRef<..., str>s can come from multiple different sources, e.g. a RcRef<Erased, str> can come from a string literal too.

    NB. at the time of writing, the erasure with RcRef requires a nightly compiler, and depending on owning_ref with the nightly feature:

    [dependencies]
    owning_ref = { version = "0.1", features = ["nightly"] }
    
    0 讨论(0)
  • 2020-12-10 12:11

    As of Rust 1.21.0 and as mandated by RFC 1845, creating an Rc<str> or Arc<str> is now possible:

    use std::rc::Rc;
    use std::sync::Arc;
    
    fn main() {
        let a: &str = "hello world";
        let b: Rc<str> = Rc::from(a);
        println!("{}", b);
    
        // or equivalently:
        let b: Rc<str> = a.into();
        println!("{}", b);
    
        // we can also do this for Arc,
        let a: &str = "hello world";
        let b: Arc<str> = Arc::from(a);
        println!("{}", b);
    }
    

    (Playground)

    See <Rc as From<&str>> and <Arc as From<&str>>.

    0 讨论(0)
提交回复
热议问题