繁体   English   中英

如何向下转换 Rc <refcell<dyn io::write> > 变成一个具体的类型? </refcell<dyn>

[英]How to downcast Rc<RefCell<dyn io::Write>> into a concrete type?

我想制作一个结构,文本 output 可以显示在控制台上或存储在内部缓冲区中。 如果文本被缓冲,那么我需要一种返回文本内容的方法。

为此,我使用了一个名为writer的属性,它是dyn std::io::Write (包装到Rc<RefCell<>>中,因为我的真实代码需要它)。 然后在结构构造上,我为此属性创建了一个io::stdout()实例或一个Vec::<u8>::new()实例。

use std::rc::Rc;
use std::cell::RefCell;
use std::io;

struct A {
    // Rc<RefCell<>> is needed in my real code
    writer: Rc<RefCell<dyn io::Write>>,
}

impl A {
    pub fn new() -> Self {
        Self { writer: Rc::new(RefCell::new(io::stdout())) }
    }

    pub fn new_buffered() -> Self {
        Self { writer: Rc::new(RefCell::new(Vec::<u8>::new())) }
    }

    pub fn write(&self, s: &str) {
        let mut writer = self.writer.borrow_mut();
        writeln!(writer, "{}", s).unwrap();
    }

    /// Returns None if the struct is not buffered, otherwise a copy of the buffered output.
    pub fn get_buffer(&self) -> Option<String> {
        match GET_VEC_U8() { // <- Unable to implement this line
            Some(vec_u8)  => {
                Some(String::from_utf8(vec_u8.clone()).unwrap())
            },
            None => None,
        }
    }
}

fn main() {
    let a = A::new();
    a.write("foo");
    println!("Buffer: {:?}", a.get_buffer());

    let b = A::new_buffered();
    b.write("bar");
    println!("Buffer: {:?}", b.get_buffer());
}

但是当作者是Vec<u8>时,我不知道如何提取文本内容(方法get_buffer() )。 我该怎么做?

我的尝试

我试图将属性包装到一个Box中:

struct A {
    writer: Rc<RefCell<Box<dyn io::Write>>>,
}

然后在其上使用Box::downcast()

impl A {
    pub fn get_buffer(&self) -> Option<String> {
        let writer = self.writer.borrow();
        match (*writer).downcast::<Vec<u8>>() {
            Ok(vec_u8) => Some(String::from_utf8(vec_u8.clone()).unwrap()),
            Err(_) => None,
        }
    }
}

但我收到此错误:

error[E0599]: no method named `downcast` found for struct `std::boxed::Box<dyn std::io::Write>` in the current scope
  --> src/main.rs:27:25
   |
27 |         match (*writer).downcast::<Vec<u8>>() {
   |                         ^^^^^^^^ method not found in `std::boxed::Box<dyn std::io::Write>`

正如@SvenMarnach 在评论中所写,根据io::Write编写自定义特征可能是一种解决方案

use std::rc::Rc;
use std::cell::RefCell;
use std::io::{self, Stdout};

trait MyWrite: io::Write {
    fn get_buffer(&self) -> Option<String>;
}

impl MyWrite for Stdout {
    fn get_buffer(&self) -> Option<String> {
        None
    }
}

impl MyWrite for Vec<u8> {
    fn get_buffer(&self) -> Option<String> {
        Some(String::from_utf8(self.clone()).unwrap())
    }
}

struct A {
    // Rc<RefCell<>> is needed in my real code
    writer: Rc<RefCell<dyn MyWrite>>,
}

impl A {
    pub fn new() -> Self {
        Self { writer: Rc::new(RefCell::new(io::stdout())) }
    }

    pub fn new_buffered() -> Self {
        Self { writer: Rc::new(RefCell::new(Vec::<u8>::new())) }
    }

    pub fn write(&self, s: &str) {
        let mut writer = self.writer.borrow_mut();
        writeln!(writer, "{}", s).unwrap();
    }

    /// Returns None if the struct is not buffered, otherwise a copy of the buffered output.
    pub fn get_buffer(&self) -> Option<String> {
        let writer = self.writer.borrow();
        writer.get_buffer()
    }
}

fn main() {
    let a = A::new();
    a.write("foo");
    println!("Buffer: {:?}", a.get_buffer());

    let b = A::new_buffered();
    b.write("bar");
    println!("Buffer: {:?}", b.get_buffer());
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM