How to implement rustc_serialize::Decodable for struct that has a field value that is another struct?

时间:2016-10-20 20:03:16

标签: struct rust

I need to implement the rustc_serialize::Decoder trait for my Herd struct:

extern crate chrono;
extern crate rustc_serialize;

use chrono::NaiveDate;
use rustc_serialize::Decodable;

struct Herd {
    id: i32,
    breed: String,
    name: String,
    purchase_date: NaiveDate,
}

impl Decodable for Herd {
    fn decode<D: Decoder>(d: &mut D) -> Result<Herd, D::Error> {
        d.read_struct("Herd", 4, |d| {
            let id = try!(d.read_struct_field("id", 0, |d| d.read_i32()));
            let breed = try!(d.read_struct_field("breed", 1, |d| d.read_str()));
            let name = try!(d.read_struct_field("name", 2, |d| d.read_str()));
            let purchase_date = try!(d.read_struct_field("purchase_date", 3, |i| {
                i.read_struct("NaiveDate", 1, |i| {
                    let ymdf = try!(i.read_struct_field("ymdf", 0, |i| i.read_i32()));
                    Ok(NaiveDate { ymdf: ymdf })
                })
            }));

            Ok(Herd {
                id: id,
                breed: breed,
                name: name,
                purchase_date: purchase_date,
            })
        })
    }
}

I'm unable to use #[derive(RustcDecodable)] because the following error occurs:

error[E0277]: the trait bound chrono::NaiveDate: rustc_serialize::Decodable is not satisfied

I'm working on manually implementing Decodable and that's what you see in the code above. NaiveDate from the rust-chrono crate is a struct with one field that is of data type i32.

When I run the code right now, I receive the message:

field ymdf of struct chrono::NaiveDate is private

How do I implement Decoder for NaiveDate? Is there a simpler way to implement Decodable for my Herd struct? I am an all-around beginner programmer; perhaps there is another way to look at this problem.

I am using Rust 1.12 with the following dependencies:

  • nickel = "0.9.0"
  • postgres = { version = "0.12", features = ["with-chrono"]}
  • chrono = "0.2"
  • rustc-serialize = "0.3"

2 个答案:

答案 0 :(得分:5)

NaiveDate确实实施了Decodable,但在可选功能"rustc-serialize"下。

您应该在Cargo.toml中添加此内容以激活它:

chrono = { version = "0.2", features = ["rustc-serialize"]}

答案 1 :(得分:1)

In order to be able to derive Decodable for Herd, NaiveDate would need to be Decodable too. Its ymdf field is private, though, which is an issue if you wanted to implement it manually.

What you could do is define your own wrapper type for ymdf (and use it in Herd) - then you should be able to derive Decodable for it and then for Herd.

Edit: It's not necessarily the way to go with NaiveDate, as there is no easy way to convert ymdf into it (or to import DateImpl, its type), but depending on your needs the following way might be enough:

use std::i32;

pub type DateImpl = i32;
pub const MAX_YEAR: DateImpl = i32::MAX >> 13;
pub const MIN_YEAR: DateImpl = i32::MIN >> 13;

#[derive(RustcDecodable)]
struct YmdfWrapper {
    ymdf: DateImpl
}

#[derive(RustcDecodable)]
struct Herd {
    id: i32,
    breed: String,
    name: String,
    purchase_date: YmdfWrapper,
}
相关问题