从匹配表达式返回任意Encodable?

时间:2014-12-22 02:46:56

标签: serialization rust

我有一个匹配表达式,可以返回几个(内置和自定义)类型,最终将序列化为JSON并从Web请求返回。我宁愿避免重复序列化代码或在每个匹配组中制作字符串副本。

每只手臂返回Encodable;但是,似乎Encodable不是对象安全的,所以我无法指向它。

编辑:由于Rust的变化,问题已经从"这是一个很好的方法吗?"到"我怎么能这样做?" (这是版本rustc 1.0.0-nightly (ed530d7a3 2015-01-16 22:41:16 +0000)

extern crate "rustc-serialize" as rustc_serialize;

use rustc_serialize::{json, Encodable};

#[derive(RustcEncodable)]
struct Valid {
    value: u32
}

#[derive(RustcEncodable)]
struct Error {
    error: &'static str // '
}

fn main() {
    let valid = true;
    let result = match valid {
        true => Box::new(Valid { value: 42 }) as Box<Encodable>,
        false => Box::new(Error { error: "bork" }) as Box<Encodable>
    };
    let mut buf = String::new();
    result.encode(&mut json::Encoder::new(&mut buf)).unwrap();
    println!("{}", buf);
}

error: cannot convert to a trait object because trait `rustc-serialize::serialize::Encodable` is not object-safe [E0038]

1 个答案:

答案 0 :(得分:2)

有两种方法可以在Rust中使用特征:

  1. 作为通用函数的边界(静态调度)
  2. 作为特征对象,指针后面(动态调度)
  3. 由于Encodable不是对象安全的,我们无法使用动态调度,因为编译器不允许我们创建指向Encodable的指针。

    因此,我们必须使用静态调度。为此,我已将适用于Encodable的代码移动到新的通用函数,并从每个臂调用它。

    extern crate "rustc-serialize" as rustc_serialize;
    
    use rustc_serialize::{json, Encodable};
    
    #[derive(RustcEncodable)]
    struct Valid {
        value: u32
    }
    
    #[derive(RustcEncodable)]
    struct Error {
        error: &'static str // '
    }
    
    fn do_encode<E: Encodable>(e: E) -> () {
        let mut buf = String::new();
        e.encode(&mut json::Encoder::new(&mut buf)).unwrap();
        println!("{}", buf);
    }
    
    fn main() {
        let is_valid = true;
        match is_valid {
            true => do_encode(Valid { value: 42 }),
            false => do_encode(Error { error: "bork" }),
        };
    }