Expand description
The compiler code necessary to implement the #[derive(RustcEncodable)]
(and RustcDecodable
, in decodable.rs
) extension. The idea here is that
type-defining items may be tagged with
#[derive(RustcEncodable, RustcDecodable)]
.
For example, a type like:
ⓘ
#[derive(RustcEncodable, RustcDecodable)]
struct Node { id: usize }
would generate two implementations like:
ⓘ
impl<S: Encoder<E>, E> Encodable<S, E> for Node {
fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_struct("Node", 1, |this| {
this.emit_struct_field("id", 0, |this| {
Encodable::encode(&self.id, this)
/* this.emit_usize(self.id) can also be used */
})
})
}
}
impl<D: Decoder<E>, E> Decodable<D, E> for Node {
fn decode(d: &mut D) -> Result<Node, E> {
d.read_struct("Node", 1, |this| {
match this.read_struct_field("id", 0, |this| Decodable::decode(this)) {
Ok(id) => Ok(Node { id: id }),
Err(e) => Err(e),
}
})
}
}
Other interesting scenarios are when the item has type parameters or references other non-built-in types. A type definition like:
ⓘ
#[derive(RustcEncodable, RustcDecodable)]
struct Spanned<T> { node: T, span: Span }
would yield functions like:
ⓘ
impl<
S: Encoder<E>,
E,
T: Encodable<S, E>
> Encodable<S, E> for Spanned<T> {
fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_struct("Spanned", 2, |this| {
this.emit_struct_field("node", 0, |this| self.node.encode(this))
.unwrap();
this.emit_struct_field("span", 1, |this| self.span.encode(this))
})
}
}
impl<
D: Decoder<E>,
E,
T: Decodable<D, E>
> Decodable<D, E> for Spanned<T> {
fn decode(d: &mut D) -> Result<Spanned<T>, E> {
d.read_struct("Spanned", 2, |this| {
Ok(Spanned {
node: this.read_struct_field("node", 0, |this| Decodable::decode(this))
.unwrap(),
span: this.read_struct_field("span", 1, |this| Decodable::decode(this))
.unwrap(),
})
})
}
}