Skip to content

Rewrite serialization to use generators #9145

Closed
@erickt

Description

@erickt

This is a placeholder bug to track potentially converting the serialization api to use generators (#7746). Once we have generators, We'll be able to write a serializer like this:

struct A {
    a: int,
    b: B,
}

Struct B {
    c: ~str,
    d: ~[int],
}

impl serialize::Encodable for A {
    fn encode_iter<'a>(&'a self) -> Option<Value<'a>> {
        yield StructStart("A");
        yield StructField("a", 0);
        yield Int(self.a);
        yield StructField("b", 1);
        for value in self.b.encode_iter() { yield value; }
        yield StructEnd;
    }
}

impl serialize::Encodable for B {
    fn encode_iter<'a>(&'a self) -> Option<Value<'a>> {
        yield StructStart("B");
        yield StructField("c", 0);
        yield String(self.c);
        yield StructField("d", 1);
        for value in self.d.encode_iter() { yield value; }
        yield StructEnd;
    }
}

A Deserializer would also be pretty simple:

struct PrettyPrinter<T> {
    it: T
}

impl<T: Iterator<Value>> serialize::Decoder<()> for PrettyPrinter {
    fn decode(&mut self) -> () {
        match self.it.next() {
            None => fail!(),
            Some(Int(x)) => printfln!("%?", x),
            Some(Str(x)) => printfln!("%?", x),
            Some(StructStart(name)) => {
                printfln!("%s {", name);
                self.decode_struct()
            }
            ...
        }
    }
    fn decode_struct(&mut self) {
        match self.it.next() {
            Some(StructField(name, idx)) => {
                if idx != 0 { printfln!(","); }
                printfln!("%s:", name);
                self.decode();
            }
            Some(StructEnd) => printfln!("}"),
            _ => fail!(),
        }
    }
    ...
} 

There are two advantages to this conversion. First, it's easier for rustc to optimize iterator-based code instead of recursive-closure-based code. Second, it allows for a serializer like extra::json::Encoder peek into the iterator stream to validate that a map key is actually a string. This would fix #8883.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions