Skip to content

Commit c952c04

Browse files
committed
re-special-case Option in JSON encoding
1 parent f91160b commit c952c04

File tree

1 file changed

+64
-9
lines changed

1 file changed

+64
-9
lines changed

src/libstd/json.rs

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -126,16 +126,42 @@ pub impl Encoder: serialize::Encoder {
126126
}
127127

128128
fn emit_enum_variant(&self, name: &str, _id: uint, _cnt: uint, f: fn()) {
129-
// emitting enums as arrays where the first
130-
// element provides the enum variant name
131-
self.wr.write_char('[');
132-
self.wr.write_str(escape_str(name));
133-
f();
134-
self.wr.write_char(']');
129+
// encoding of enums is special-cased for Option. Specifically:
130+
// Some(34) => 34
131+
// None => null
132+
133+
// other enums are encoded as vectors:
134+
// Kangaroo(34,"William") => ["Kangaroo",[34,"William"]]
135+
136+
// the default expansion for enums is more verbose than I'd like;
137+
// specifically, the inner pair of brackets seems superfluous,
138+
// BUT the design of the enumeration framework and the requirements
139+
// of the special-case for Option mean that a first argument must
140+
// be encoded "naked"--with no commas--and that the option name
141+
// can't be followed by just a comma, because there might not
142+
// be any elements in the tuple.
143+
144+
// FIXME : this would be more precise and less frightening
145+
// with fully-qualified option names. To get that information,
146+
// we'd have to change the expansion of auto-encode to pass those along.
147+
148+
if (name == ~"Some") {
149+
f();
150+
} else if (name == ~"None") {
151+
self.wr.write_str(~"null");
152+
} else {
153+
self.wr.write_char('[');
154+
self.wr.write_str(escape_str(name));
155+
self.wr.write_char(',');
156+
self.wr.write_char('[');
157+
f();
158+
self.wr.write_char(']');
159+
self.wr.write_char(']');
160+
}
135161
}
136162

137-
fn emit_enum_variant_arg(&self, _idx: uint, f: fn()) {
138-
self.wr.write_char(',');
163+
fn emit_enum_variant_arg(&self, idx: uint, f: fn()) {
164+
if (idx != 0) {self.wr.write_char(',');}
139165
f();
140166
}
141167

@@ -1286,7 +1312,36 @@ mod tests {
12861312
}
12871313
}
12881314
check_equal(str::from_bytes(bw.bytes.data),
1289-
~"[\"frog\",\"Henry\",349]");
1315+
~"[\"frog\",[\"Henry\",349]]");
1316+
}
1317+
1318+
#[test]
1319+
fn test_write_some () {
1320+
let bw = @io::BytesWriter {bytes: dvec::DVec(), pos: 0};
1321+
let bww : @io::Writer = (bw as @io::Writer);
1322+
let encoder = (@Encoder(bww) as @serialize::Encoder);
1323+
do encoder.emit_enum(~"Option") {
1324+
do encoder.emit_enum_variant (~"Some",37,1242) {
1325+
do encoder.emit_enum_variant_arg (0) {
1326+
encoder.emit_owned_str(~"jodhpurs")
1327+
}
1328+
}
1329+
}
1330+
check_equal(str::from_bytes(bw.bytes.data),
1331+
~"\"jodhpurs\"");
1332+
}
1333+
1334+
#[test]
1335+
fn test_write_none () {
1336+
let bw = @io::BytesWriter {bytes: dvec::DVec(), pos: 0};
1337+
let bww : @io::Writer = (bw as @io::Writer);
1338+
let encoder = (@Encoder(bww) as @serialize::Encoder);
1339+
do encoder.emit_enum(~"Option") {
1340+
do encoder.emit_enum_variant (~"None",37,1242) {
1341+
}
1342+
}
1343+
check_equal(str::from_bytes(bw.bytes.data),
1344+
~"null");
12901345
}
12911346
12921347
#[test]

0 commit comments

Comments
 (0)