Skip to content

Commit 478e449

Browse files
committed
std: add option type directly to serialize::{En,De}code
1 parent 4d995e6 commit 478e449

File tree

5 files changed

+138
-48
lines changed

5 files changed

+138
-48
lines changed

src/libstd/ebml.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,8 +399,20 @@ pub mod reader {
399399
debug!("read_tup_elt(idx=%u)", idx);
400400
f()
401401
}
402-
}
403402
403+
fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
404+
debug!("read_option()");
405+
do self.read_enum("Option") || {
406+
do self.read_enum_variant |idx| {
407+
match idx {
408+
0 => None,
409+
1 => Some(f()),
410+
_ => fail!(),
411+
}
412+
}
413+
}
414+
}
415+
}
404416
}
405417
406418
pub mod writer {
@@ -666,9 +678,19 @@ pub mod writer {
666678
667679
fn emit_tup(&self, _len: uint, f: &fn()) { f() }
668680
fn emit_tup_elt(&self, _idx: uint, f: &fn()) { f() }
669-
}
670681
682+
fn emit_option(&self, f: &fn()) {
683+
self.emit_enum("Option", f);
684+
}
685+
fn emit_option_none(&self) {
686+
self.emit_enum_variant("None", 0, 0, || ())
687+
}
688+
fn emit_option_some(&self, f: &fn()) {
689+
self.emit_enum_variant("Some", 1, 1, f)
690+
}
691+
}
671692
}
693+
672694
// ___________________________________________________________________________
673695
// Testing
674696

src/libstd/json.rs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -120,24 +120,11 @@ impl serialize::Encoder for Encoder {
120120
}
121121

122122
fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
123-
// encoding of enums is special-cased for Option. Specifically:
124-
// Some(34) => 34
125-
// None => null
126-
127-
// other enums are encoded as strings or vectors:
123+
// enums are encoded as strings or vectors:
128124
// Bunny => "Bunny"
129125
// Kangaroo(34,"William") => ["Kangaroo",[34,"William"]]
130126

131-
// FIXME #4872: this would be more precise and less frightening
132-
// with fully-qualified option names. To get that information,
133-
// we'd have to change the expansion of auto-encode to pass
134-
// those along.
135-
136-
if name == ~"Some" {
137-
f();
138-
} else if name == ~"None" {
139-
self.wr.write_str(~"null");
140-
} else if cnt == 0 {
127+
if cnt == 0 {
141128
self.wr.write_str(escape_str(name));
142129
} else {
143130
self.wr.write_char('[');
@@ -193,6 +180,10 @@ impl serialize::Encoder for Encoder {
193180
fn emit_tup_elt(&self, idx: uint, f: &fn()) {
194181
self.emit_vec_elt(idx, f)
195182
}
183+
184+
fn emit_option(&self, f: &fn()) { f(); }
185+
fn emit_option_none(&self) { self.emit_nil(); }
186+
fn emit_option_some(&self, f: &fn()) { f(); }
196187
}
197188

198189
pub struct PrettyEncoder {
@@ -245,11 +236,7 @@ impl serialize::Encoder for PrettyEncoder {
245236

246237
fn emit_enum(&self, _name: &str, f: &fn()) { f() }
247238
fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
248-
if name == ~"Some" {
249-
f();
250-
} else if name == ~"None" {
251-
self.emit_nil();
252-
} else if cnt == 0 {
239+
if cnt == 0 {
253240
self.wr.write_str(escape_str(name));
254241
} else {
255242
self.wr.write_char('[');
@@ -335,6 +322,10 @@ impl serialize::Encoder for PrettyEncoder {
335322
fn emit_tup_elt(&self, idx: uint, f: &fn()) {
336323
self.emit_vec_elt(idx, f)
337324
}
325+
326+
fn emit_option(&self, f: &fn()) { f(); }
327+
fn emit_option_none(&self) { self.emit_nil(); }
328+
fn emit_option_some(&self, f: &fn()) { f(); }
338329
}
339330

340331
impl<S:serialize::Encoder> serialize::Encodable<S> for Json {
@@ -966,6 +957,13 @@ impl<'self> serialize::Decoder for Decoder<'self> {
966957
_ => fail!(~"not a list")
967958
}
968959
}
960+
961+
fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
962+
match *self.peek() {
963+
Null => { self.pop(); None }
964+
_ => Some(f()),
965+
}
966+
}
969967
}
970968
971969
impl Eq for Json {

src/libstd/prettyprint.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,4 +182,18 @@ impl serialize::Encoder for Serializer {
182182
if idx > 0u { self.wr.write_str(~", "); }
183183
f();
184184
}
185+
186+
fn emit_option(&self, f: &fn()) {
187+
f();
188+
}
189+
190+
fn emit_option_none(&self) {
191+
self.wr.write_str("None");
192+
}
193+
194+
fn emit_option_some(&self, f: &fn()) {
195+
self.wr.write_str("Some(");
196+
f();
197+
self.wr.write_char(')');
198+
}
185199
}

src/libstd/serialize.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ pub trait Encoder {
6262

6363
fn emit_tup(&self, len: uint, f: &fn());
6464
fn emit_tup_elt(&self, idx: uint, f: &fn());
65+
66+
// Specialized types:
67+
fn emit_option(&self, f: &fn());
68+
fn emit_option_none(&self);
69+
fn emit_option_some(&self, f: &fn());
6570
}
6671

6772
pub trait Decoder {
@@ -103,6 +108,9 @@ pub trait Decoder {
103108

104109
fn read_tup<T>(&self, sz: uint, f: &fn() -> T) -> T;
105110
fn read_tup_elt<T>(&self, idx: uint, f: &fn() -> T) -> T;
111+
112+
// Specialized types:
113+
fn read_option<T>(&self, f: &fn() -> T) -> Option<T>;
106114
}
107115

108116
pub trait Encodable<S:Encoder> {
@@ -368,31 +376,18 @@ impl<D:Decoder,T:Decodable<D>> Decodable<D> for @[T] {
368376

369377
impl<S:Encoder,T:Encodable<S>> Encodable<S> for Option<T> {
370378
fn encode(&self, s: &S) {
371-
do s.emit_enum(~"Option") {
379+
do s.emit_option {
372380
match *self {
373-
None => do s.emit_enum_variant(~"None", 0u, 0u) {
374-
},
375-
376-
Some(ref v) => do s.emit_enum_variant(~"Some", 1u, 1u) {
377-
s.emit_enum_variant_arg(0u, || v.encode(s))
378-
}
381+
None => s.emit_option_none(),
382+
Some(ref v) => s.emit_option_some(|| v.encode(s)),
379383
}
380384
}
381385
}
382386
}
383387

384388
impl<D:Decoder,T:Decodable<D>> Decodable<D> for Option<T> {
385389
fn decode(d: &D) -> Option<T> {
386-
do d.read_enum(~"Option") {
387-
do d.read_enum_variant |i| {
388-
match i {
389-
0 => None,
390-
1 => Some(d.read_enum_variant_arg(
391-
0u, || Decodable::decode(d))),
392-
_ => fail!(fmt!("Bad variant for option: %u", i))
393-
}
394-
}
395-
}
390+
d.read_option(|| Decodable::decode(d))
396391
}
397392
}
398393

src/libsyntax/ext/auto_encode.rs

Lines changed: 70 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,7 @@ fn mk_enum_deser_body(
11771177
11781178
#[cfg(test)]
11791179
mod test {
1180+
use core::option::{None, Some};
11801181
use std::serialize::Encodable;
11811182
use std::serialize::Encoder;
11821183
@@ -1190,6 +1191,9 @@ mod test {
11901191
CallToEmitNil,
11911192
CallToEmitStruct(~str,uint),
11921193
CallToEmitField(~str,uint),
1194+
CallToEmitOption,
1195+
CallToEmitOptionNone,
1196+
CallToEmitOptionSome,
11931197
// all of the ones I was too lazy to handle:
11941198
CallToOther
11951199
}
@@ -1281,6 +1285,18 @@ mod test {
12811285
fn emit_tup_elt(&self, +_idx: uint, f: &fn()) {
12821286
self.add_unknown_to_log(); f();
12831287
}
1288+
1289+
fn emit_option(&self, f: &fn()) {
1290+
self.add_to_log(CallToEmitOption);
1291+
f();
1292+
}
1293+
fn emit_option_none(&self) {
1294+
self.add_to_log(CallToEmitOptionNone);
1295+
}
1296+
fn emit_option_some(&self, f: &fn()) {
1297+
self.add_to_log(CallToEmitOptionSome);
1298+
f();
1299+
}
12841300
}
12851301
12861302
@@ -1296,13 +1312,58 @@ mod test {
12961312
Magazine(~str)
12971313
}
12981314
1299-
#[test] fn encode_enum_test () {
1300-
assert_eq!(to_call_log(Book(34,44)),
1301-
~[CallToEmitEnum (~"Written"),
1302-
CallToEmitEnumVariant (~"Book",0,2),
1303-
CallToEmitEnumVariantArg (0),
1304-
CallToEmitUint (34),
1305-
CallToEmitEnumVariantArg (1),
1306-
CallToEmitUint (44)]);
1307-
}
1315+
#[test]
1316+
fn test_encode_enum() {
1317+
assert_eq!(
1318+
to_call_log(Book(34,44)),
1319+
~[
1320+
CallToEmitEnum(~"Written"),
1321+
CallToEmitEnumVariant(~"Book",0,2),
1322+
CallToEmitEnumVariantArg(0),
1323+
CallToEmitUint(34),
1324+
CallToEmitEnumVariantArg(1),
1325+
CallToEmitUint(44),
1326+
]
1327+
);
1328+
}
1329+
1330+
pub struct BPos(uint);
1331+
1332+
#[auto_encode]
1333+
pub struct HasPos { pos : BPos }
1334+
1335+
#[test]
1336+
fn test_encode_newtype() {
1337+
assert_eq!(
1338+
to_call_log(HasPos { pos:BPos(48) }),
1339+
~[
1340+
CallToEmitStruct(~"HasPos",1),
1341+
CallToEmitField(~"pos",0),
1342+
CallToEmitUint(48),
1343+
]
1344+
);
1345+
}
1346+
1347+
#[test]
1348+
fn test_encode_option() {
1349+
let mut v = None;
1350+
1351+
assert_eq!(
1352+
to_call_log(v),
1353+
~[
1354+
CallToEmitOption,
1355+
CallToEmitOptionNone,
1356+
]
1357+
);
1358+
1359+
v = Some(54u);
1360+
assert_eq!(
1361+
to_call_log(v),
1362+
~[
1363+
CallToEmitOption,
1364+
CallToEmitOptionSome,
1365+
CallToEmitUint(54)
1366+
]
1367+
);
1368+
}
13081369
}

0 commit comments

Comments
 (0)