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);
|
debug!("read_tup_elt(idx=%u)", idx);
|
||||||
f()
|
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 {
|
pub mod writer {
|
||||||
|
@ -666,9 +678,19 @@ pub mod writer {
|
||||||
|
|
||||||
fn emit_tup(&self, _len: uint, f: &fn()) { f() }
|
fn emit_tup(&self, _len: uint, f: &fn()) { f() }
|
||||||
fn emit_tup_elt(&self, _idx: 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
|
// Testing
|
||||||
|
|
||||||
|
|
|
@ -120,24 +120,11 @@ impl serialize::Encoder for Encoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
|
fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
|
||||||
// encoding of enums is special-cased for Option. Specifically:
|
// enums are encoded as strings or vectors:
|
||||||
// Some(34) => 34
|
|
||||||
// None => null
|
|
||||||
|
|
||||||
// other enums are encoded as strings or vectors:
|
|
||||||
// Bunny => "Bunny"
|
// Bunny => "Bunny"
|
||||||
// Kangaroo(34,"William") => ["Kangaroo",[34,"William"]]
|
// Kangaroo(34,"William") => ["Kangaroo",[34,"William"]]
|
||||||
|
|
||||||
// FIXME #4872: this would be more precise and less frightening
|
if cnt == 0 {
|
||||||
// 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 {
|
|
||||||
self.wr.write_str(escape_str(name));
|
self.wr.write_str(escape_str(name));
|
||||||
} else {
|
} else {
|
||||||
self.wr.write_char('[');
|
self.wr.write_char('[');
|
||||||
|
@ -193,6 +180,10 @@ impl serialize::Encoder for Encoder {
|
||||||
fn emit_tup_elt(&self, idx: uint, f: &fn()) {
|
fn emit_tup_elt(&self, idx: uint, f: &fn()) {
|
||||||
self.emit_vec_elt(idx, f)
|
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 {
|
pub struct PrettyEncoder {
|
||||||
|
@ -245,11 +236,7 @@ impl serialize::Encoder for PrettyEncoder {
|
||||||
|
|
||||||
fn emit_enum(&self, _name: &str, f: &fn()) { f() }
|
fn emit_enum(&self, _name: &str, f: &fn()) { f() }
|
||||||
fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
|
fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
|
||||||
if name == ~"Some" {
|
if cnt == 0 {
|
||||||
f();
|
|
||||||
} else if name == ~"None" {
|
|
||||||
self.emit_nil();
|
|
||||||
} else if cnt == 0 {
|
|
||||||
self.wr.write_str(escape_str(name));
|
self.wr.write_str(escape_str(name));
|
||||||
} else {
|
} else {
|
||||||
self.wr.write_char('[');
|
self.wr.write_char('[');
|
||||||
|
@ -335,6 +322,10 @@ impl serialize::Encoder for PrettyEncoder {
|
||||||
fn emit_tup_elt(&self, idx: uint, f: &fn()) {
|
fn emit_tup_elt(&self, idx: uint, f: &fn()) {
|
||||||
self.emit_vec_elt(idx, f)
|
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 {
|
impl<S:serialize::Encoder> serialize::Encodable<S> for Json {
|
||||||
|
@ -966,6 +957,13 @@ impl<'self> serialize::Decoder for Decoder<'self> {
|
||||||
_ => fail!(~"not a list")
|
_ => 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 {
|
impl Eq for Json {
|
||||||
|
|
|
@ -182,4 +182,18 @@ impl serialize::Encoder for Serializer {
|
||||||
if idx > 0u { self.wr.write_str(~", "); }
|
if idx > 0u { self.wr.write_str(~", "); }
|
||||||
f();
|
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(&self, len: uint, f: &fn());
|
||||||
fn emit_tup_elt(&self, idx: 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 {
|
pub trait Decoder {
|
||||||
|
@ -103,6 +108,9 @@ pub trait Decoder {
|
||||||
|
|
||||||
fn read_tup<T>(&self, sz: uint, f: &fn() -> T) -> T;
|
fn read_tup<T>(&self, sz: uint, f: &fn() -> T) -> T;
|
||||||
fn read_tup_elt<T>(&self, idx: 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> {
|
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> {
|
impl<S:Encoder,T:Encodable<S>> Encodable<S> for Option<T> {
|
||||||
fn encode(&self, s: &S) {
|
fn encode(&self, s: &S) {
|
||||||
do s.emit_enum(~"Option") {
|
do s.emit_option {
|
||||||
match *self {
|
match *self {
|
||||||
None => do s.emit_enum_variant(~"None", 0u, 0u) {
|
None => s.emit_option_none(),
|
||||||
},
|
Some(ref v) => s.emit_option_some(|| v.encode(s)),
|
||||||
|
|
||||||
Some(ref v) => do s.emit_enum_variant(~"Some", 1u, 1u) {
|
|
||||||
s.emit_enum_variant_arg(0u, || 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> {
|
impl<D:Decoder,T:Decodable<D>> Decodable<D> for Option<T> {
|
||||||
fn decode(d: &D) -> Option<T> {
|
fn decode(d: &D) -> Option<T> {
|
||||||
do d.read_enum(~"Option") {
|
d.read_option(|| Decodable::decode(d))
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1177,6 +1177,7 @@ fn mk_enum_deser_body(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use core::option::{None, Some};
|
||||||
use std::serialize::Encodable;
|
use std::serialize::Encodable;
|
||||||
use std::serialize::Encoder;
|
use std::serialize::Encoder;
|
||||||
|
|
||||||
|
@ -1190,6 +1191,9 @@ mod test {
|
||||||
CallToEmitNil,
|
CallToEmitNil,
|
||||||
CallToEmitStruct(~str,uint),
|
CallToEmitStruct(~str,uint),
|
||||||
CallToEmitField(~str,uint),
|
CallToEmitField(~str,uint),
|
||||||
|
CallToEmitOption,
|
||||||
|
CallToEmitOptionNone,
|
||||||
|
CallToEmitOptionSome,
|
||||||
// all of the ones I was too lazy to handle:
|
// all of the ones I was too lazy to handle:
|
||||||
CallToOther
|
CallToOther
|
||||||
}
|
}
|
||||||
|
@ -1281,6 +1285,18 @@ mod test {
|
||||||
fn emit_tup_elt(&self, +_idx: uint, f: &fn()) {
|
fn emit_tup_elt(&self, +_idx: uint, f: &fn()) {
|
||||||
self.add_unknown_to_log(); f();
|
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)
|
Magazine(~str)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test] fn encode_enum_test () {
|
#[test]
|
||||||
assert_eq!(to_call_log(Book(34,44)),
|
fn test_encode_enum() {
|
||||||
~[CallToEmitEnum (~"Written"),
|
assert_eq!(
|
||||||
CallToEmitEnumVariant (~"Book",0,2),
|
to_call_log(Book(34,44)),
|
||||||
CallToEmitEnumVariantArg (0),
|
~[
|
||||||
CallToEmitUint (34),
|
CallToEmitEnum(~"Written"),
|
||||||
CallToEmitEnumVariantArg (1),
|
CallToEmitEnumVariant(~"Book",0,2),
|
||||||
CallToEmitUint (44)]);
|
CallToEmitEnumVariantArg(0),
|
||||||
}
|
CallToEmitUint(34),
|
||||||
|
CallToEmitEnumVariantArg(1),
|
||||||
|
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