当trait不满足对象安全性要求时,我该如何在两个Results中调用trait方法?

4

我希望有一个变量model,它可以是Model1或者Model2,这取决于bytes中所编码的实际模型。如何合并这两个模型的Result,其中只有一个是Ok()

let model1 = Model1::from_reader(&mut reader, &bytes);
let model2 = Model2::from_reader(&mut reader, &bytes);
let model = /* ??? */;
write_file(model).unwrap();

他们都实现了MessageWrite,这是我从现在开始唯一需要的特性。以下是write_file()的原型。
fn write_file<M: MessageWrite>(msg: M) -> io::Result<()>

我正在使用quick-protobuf库进行模型构建。其中from_reader的原型:

impl<'a> MessageRead<'a> for Model1<'a> {
    fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
        // ...
    }
}

还有 MessageWrite 特性。请注意,它有一个 Sized 约束。

pub trait MessageWrite: Sized {
     // ...
}

2
谢谢,我更新了我的问题,希望现在更清楚了。 - JuNijland
是的,好多了。谢谢! :) - Lukas Kalbertodt
1个回答

4
您可以使用模式匹配。看这个例子:

您可以使用模式匹配。看这个例子:

trait MessageWrite: Sized {}

struct Foo;
struct Bar;

impl MessageWrite for Foo {}
impl MessageWrite for Bar {}

fn main() {
    let f: Result<Foo, ()> = Ok(Foo{});
    let b: Result<Bar, ()> = Err(());

    match (f, b) {
        (Ok(f), _) => write_file(f),
        (_, Ok(b)) => write_file(b),
        _ => panic!(),
    };
}

fn write_file<M: MessageWrite>(msg: M) -> std::io::Result<()> { Ok(()) }

这就是我一直在寻找的!唯一剩下的问题是MessageWrite有一个“Sized”限制,因此无法使用Box :: new()将其转换为对象。有解决方案吗? - JuNijland
@JuNijland 然后你可以直接调用 write_file - Boiethios

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接