std: add option type directly to serialize::{En,De}code
This commit is contained in:
parent
4d995e66a2
commit
478e4498b7
5 changed files with 138 additions and 48 deletions
|
@ -399,8 +399,20 @@ pub mod reader {
|
|||
debug!("read_tup_elt(idx=%u)", idx);
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
|
||||
debug!("read_option()");
|
||||
do self.read_enum("Option") || {
|
||||
do self.read_enum_variant |idx| {
|
||||
match idx {
|
||||
0 => None,
|
||||
1 => Some(f()),
|
||||
_ => fail!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod writer {
|
||||
|
@ -666,9 +678,19 @@ pub mod writer {
|
|||
|
||||
fn emit_tup(&self, _len: uint, f: &fn()) { f() }
|
||||
fn emit_tup_elt(&self, _idx: uint, f: &fn()) { f() }
|
||||
|
||||
fn emit_option(&self, f: &fn()) {
|
||||
self.emit_enum("Option", f);
|
||||
}
|
||||
fn emit_option_none(&self) {
|
||||
self.emit_enum_variant("None", 0, 0, || ())
|
||||
}
|
||||
fn emit_option_some(&self, f: &fn()) {
|
||||
self.emit_enum_variant("Some", 1, 1, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// ___________________________________________________________________________
|
||||
// Testing
|
||||
|
||||
|
|
|
@ -120,24 +120,11 @@ impl serialize::Encoder for Encoder {
|
|||
}
|
||||
|
||||
fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
|
||||
// encoding of enums is special-cased for Option. Specifically:
|
||||
// Some(34) => 34
|
||||
// None => null
|
||||
|
||||
// other enums are encoded as strings or vectors:
|
||||
// enums are encoded as strings or vectors:
|
||||
// Bunny => "Bunny"
|
||||
// Kangaroo(34,"William") => ["Kangaroo",[34,"William"]]
|
||||
|
||||
// FIXME #4872: this would be more precise and less frightening
|
||||
// with fully-qualified option names. To get that information,
|
||||
// we'd have to change the expansion of auto-encode to pass
|
||||
// those along.
|
||||
|
||||
if name == ~"Some" {
|
||||
f();
|
||||
} else if name == ~"None" {
|
||||
self.wr.write_str(~"null");
|
||||
} else if cnt == 0 {
|
||||
if cnt == 0 {
|
||||
self.wr.write_str(escape_str(name));
|
||||
} else {
|
||||
self.wr.write_char('[');
|
||||
|
@ -193,6 +180,10 @@ impl serialize::Encoder for Encoder {
|
|||
fn emit_tup_elt(&self, idx: uint, f: &fn()) {
|
||||
self.emit_vec_elt(idx, f)
|
||||
}
|
||||
|
||||
fn emit_option(&self, f: &fn()) { f(); }
|
||||
fn emit_option_none(&self) { self.emit_nil(); }
|
||||
fn emit_option_some(&self, f: &fn()) { f(); }
|
||||
}
|
||||
|
||||
pub struct PrettyEncoder {
|
||||
|
@ -245,11 +236,7 @@ impl serialize::Encoder for PrettyEncoder {
|
|||
|
||||
fn emit_enum(&self, _name: &str, f: &fn()) { f() }
|
||||
fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
|
||||
if name == ~"Some" {
|
||||
f();
|
||||
} else if name == ~"None" {
|
||||
self.emit_nil();
|
||||
} else if cnt == 0 {
|
||||
if cnt == 0 {
|
||||
self.wr.write_str(escape_str(name));
|
||||
} else {
|
||||
self.wr.write_char('[');
|
||||
|
@ -335,6 +322,10 @@ impl serialize::Encoder for PrettyEncoder {
|
|||
fn emit_tup_elt(&self, idx: uint, f: &fn()) {
|
||||
self.emit_vec_elt(idx, f)
|
||||
}
|
||||
|
||||
fn emit_option(&self, f: &fn()) { f(); }
|
||||
fn emit_option_none(&self) { self.emit_nil(); }
|
||||
fn emit_option_some(&self, f: &fn()) { f(); }
|
||||
}
|
||||
|
||||
impl<S:serialize::Encoder> serialize::Encodable<S> for Json {
|
||||
|
@ -966,6 +957,13 @@ impl<'self> serialize::Decoder for Decoder<'self> {
|
|||
_ => fail!(~"not a list")
|
||||
}
|
||||
}
|
||||
|
||||
fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
|
||||
match *self.peek() {
|
||||
Null => { self.pop(); None }
|
||||
_ => Some(f()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Json {
|
||||
|
|
|
@ -182,4 +182,18 @@ impl serialize::Encoder for Serializer {
|
|||
if idx > 0u { self.wr.write_str(~", "); }
|
||||
f();
|
||||
}
|
||||
|
||||
fn emit_option(&self, f: &fn()) {
|
||||
f();
|
||||
}
|
||||
|
||||
fn emit_option_none(&self) {
|
||||
self.wr.write_str("None");
|
||||
}
|
||||
|
||||
fn emit_option_some(&self, f: &fn()) {
|
||||
self.wr.write_str("Some(");
|
||||
f();
|
||||
self.wr.write_char(')');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,11 @@ pub trait Encoder {
|
|||
|
||||
fn emit_tup(&self, len: uint, f: &fn());
|
||||
fn emit_tup_elt(&self, idx: uint, f: &fn());
|
||||
|
||||
// Specialized types:
|
||||
fn emit_option(&self, f: &fn());
|
||||
fn emit_option_none(&self);
|
||||
fn emit_option_some(&self, f: &fn());
|
||||
}
|
||||
|
||||
pub trait Decoder {
|
||||
|
@ -103,6 +108,9 @@ pub trait Decoder {
|
|||
|
||||
fn read_tup<T>(&self, sz: uint, f: &fn() -> T) -> T;
|
||||
fn read_tup_elt<T>(&self, idx: uint, f: &fn() -> T) -> T;
|
||||
|
||||
// Specialized types:
|
||||
fn read_option<T>(&self, f: &fn() -> T) -> Option<T>;
|
||||
}
|
||||
|
||||
pub trait Encodable<S:Encoder> {
|
||||
|
@ -368,14 +376,10 @@ impl<D:Decoder,T:Decodable<D>> Decodable<D> for @[T] {
|
|||
|
||||
impl<S:Encoder,T:Encodable<S>> Encodable<S> for Option<T> {
|
||||
fn encode(&self, s: &S) {
|
||||
do s.emit_enum(~"Option") {
|
||||
do s.emit_option {
|
||||
match *self {
|
||||
None => do s.emit_enum_variant(~"None", 0u, 0u) {
|
||||
},
|
||||
|
||||
Some(ref v) => do s.emit_enum_variant(~"Some", 1u, 1u) {
|
||||
s.emit_enum_variant_arg(0u, || v.encode(s))
|
||||
}
|
||||
None => s.emit_option_none(),
|
||||
Some(ref v) => s.emit_option_some(|| v.encode(s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -383,16 +387,7 @@ impl<S:Encoder,T:Encodable<S>> Encodable<S> for Option<T> {
|
|||
|
||||
impl<D:Decoder,T:Decodable<D>> Decodable<D> for Option<T> {
|
||||
fn decode(d: &D) -> Option<T> {
|
||||
do d.read_enum(~"Option") {
|
||||
do d.read_enum_variant |i| {
|
||||
match i {
|
||||
0 => None,
|
||||
1 => Some(d.read_enum_variant_arg(
|
||||
0u, || Decodable::decode(d))),
|
||||
_ => fail!(fmt!("Bad variant for option: %u", i))
|
||||
}
|
||||
}
|
||||
}
|
||||
d.read_option(|| Decodable::decode(d))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1177,6 +1177,7 @@ fn mk_enum_deser_body(
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use core::option::{None, Some};
|
||||
use std::serialize::Encodable;
|
||||
use std::serialize::Encoder;
|
||||
|
||||
|
@ -1190,6 +1191,9 @@ mod test {
|
|||
CallToEmitNil,
|
||||
CallToEmitStruct(~str,uint),
|
||||
CallToEmitField(~str,uint),
|
||||
CallToEmitOption,
|
||||
CallToEmitOptionNone,
|
||||
CallToEmitOptionSome,
|
||||
// all of the ones I was too lazy to handle:
|
||||
CallToOther
|
||||
}
|
||||
|
@ -1281,6 +1285,18 @@ mod test {
|
|||
fn emit_tup_elt(&self, +_idx: uint, f: &fn()) {
|
||||
self.add_unknown_to_log(); f();
|
||||
}
|
||||
|
||||
fn emit_option(&self, f: &fn()) {
|
||||
self.add_to_log(CallToEmitOption);
|
||||
f();
|
||||
}
|
||||
fn emit_option_none(&self) {
|
||||
self.add_to_log(CallToEmitOptionNone);
|
||||
}
|
||||
fn emit_option_some(&self, f: &fn()) {
|
||||
self.add_to_log(CallToEmitOptionSome);
|
||||
f();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1296,13 +1312,58 @@ mod test {
|
|||
Magazine(~str)
|
||||
}
|
||||
|
||||
#[test] fn encode_enum_test () {
|
||||
assert_eq!(to_call_log(Book(34,44)),
|
||||
~[CallToEmitEnum (~"Written"),
|
||||
#[test]
|
||||
fn test_encode_enum() {
|
||||
assert_eq!(
|
||||
to_call_log(Book(34,44)),
|
||||
~[
|
||||
CallToEmitEnum(~"Written"),
|
||||
CallToEmitEnumVariant(~"Book",0,2),
|
||||
CallToEmitEnumVariantArg(0),
|
||||
CallToEmitUint(34),
|
||||
CallToEmitEnumVariantArg(1),
|
||||
CallToEmitUint (44)]);
|
||||
CallToEmitUint(44),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
pub struct BPos(uint);
|
||||
|
||||
#[auto_encode]
|
||||
pub struct HasPos { pos : BPos }
|
||||
|
||||
#[test]
|
||||
fn test_encode_newtype() {
|
||||
assert_eq!(
|
||||
to_call_log(HasPos { pos:BPos(48) }),
|
||||
~[
|
||||
CallToEmitStruct(~"HasPos",1),
|
||||
CallToEmitField(~"pos",0),
|
||||
CallToEmitUint(48),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_option() {
|
||||
let mut v = None;
|
||||
|
||||
assert_eq!(
|
||||
to_call_log(v),
|
||||
~[
|
||||
CallToEmitOption,
|
||||
CallToEmitOptionNone,
|
||||
]
|
||||
);
|
||||
|
||||
v = Some(54u);
|
||||
assert_eq!(
|
||||
to_call_log(v),
|
||||
~[
|
||||
CallToEmitOption,
|
||||
CallToEmitOptionSome,
|
||||
CallToEmitUint(54)
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue