Skip to content

Commit 4d6dcef

Browse files
committed
std: Decode::read_enum_variant should pass in the variant names
Because the json::Decoder uses the string variant name, we need a way to correlate the string to the enum index. This passes in a static &[&str] to read_enum_variant, which allows the json::Decoder to know which branch it's trying to process.
1 parent 478e449 commit 4d6dcef

File tree

5 files changed

+116
-5
lines changed

5 files changed

+116
-5
lines changed

src/librustc/middle/astencode.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,7 @@ impl vtable_decoder_helpers for reader::Decoder {
681681
@self.read_to_vec(|| self.read_vtable_origin(xcx) )
682682
}
683683
684+
#[cfg(stage0)]
684685
fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext)
685686
-> typeck::vtable_origin {
686687
do self.read_enum(~"vtable_origin") {
@@ -715,6 +716,44 @@ impl vtable_decoder_helpers for reader::Decoder {
715716
}
716717
}
717718
}
719+
720+
#[cfg(stage1)]
721+
#[cfg(stage2)]
722+
#[cfg(stage3)]
723+
fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext)
724+
-> typeck::vtable_origin {
725+
do self.read_enum("vtable_origin") {
726+
do self.read_enum_variant(["vtable_static", "vtable_param"]) |i| {
727+
match i {
728+
0 => {
729+
typeck::vtable_static(
730+
do self.read_enum_variant_arg(0u) {
731+
self.read_def_id(xcx)
732+
},
733+
do self.read_enum_variant_arg(1u) {
734+
self.read_tys(xcx)
735+
},
736+
do self.read_enum_variant_arg(2u) {
737+
self.read_vtable_res(xcx)
738+
}
739+
)
740+
}
741+
1 => {
742+
typeck::vtable_param(
743+
do self.read_enum_variant_arg(0u) {
744+
self.read_uint()
745+
},
746+
do self.read_enum_variant_arg(1u) {
747+
self.read_uint()
748+
}
749+
)
750+
}
751+
// hard to avoid - user input
752+
_ => fail!(~"bad enum variant")
753+
}
754+
}
755+
}
756+
}
718757
}
719758
720759
// ______________________________________________________________________

src/libstd/ebml.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ pub mod reader {
337337
self.push_doc(self.next_doc(EsEnum), f)
338338
}
339339
340+
#[cfg(stage0)]
340341
fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T {
341342
debug!("read_enum_variant()");
342343
let idx = self._next_uint(EsEnumVid);
@@ -346,6 +347,18 @@ pub mod reader {
346347
}
347348
}
348349
350+
#[cfg(stage1)]
351+
#[cfg(stage2)]
352+
#[cfg(stage3)]
353+
fn read_enum_variant<T>(&self, _names: &[&str], f: &fn(uint) -> T) -> T {
354+
debug!("read_enum_variant()");
355+
let idx = self._next_uint(EsEnumVid);
356+
debug!(" idx=%u", idx);
357+
do self.push_doc(self.next_doc(EsEnumBody)) {
358+
f(idx)
359+
}
360+
}
361+
349362
fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T {
350363
debug!("read_enum_variant_arg(idx=%u)", idx);
351364
f()
@@ -400,6 +413,7 @@ pub mod reader {
400413
f()
401414
}
402415
416+
#[cfg(stage0)]
403417
fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
404418
debug!("read_option()");
405419
do self.read_enum("Option") || {
@@ -412,6 +426,22 @@ pub mod reader {
412426
}
413427
}
414428
}
429+
430+
#[cfg(stage1)]
431+
#[cfg(stage2)]
432+
#[cfg(stage3)]
433+
fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
434+
debug!("read_option()");
435+
do self.read_enum("Option") || {
436+
do self.read_enum_variant(["None", "Some"]) |idx| {
437+
match idx {
438+
0 => None,
439+
1 => Some(f()),
440+
_ => fail!(),
441+
}
442+
}
443+
}
444+
}
415445
}
416446
}
417447

src/libstd/json.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,7 @@ impl<'self> serialize::Decoder for Decoder<'self> {
855855
f()
856856
}
857857
858+
#[cfg(stage0)]
858859
fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T {
859860
debug!("read_enum_variant()");
860861
let idx = match *self.peek() {
@@ -864,10 +865,32 @@ impl<'self> serialize::Decoder for Decoder<'self> {
864865
f(idx)
865866
}
866867
868+
#[cfg(stage1)]
869+
#[cfg(stage2)]
870+
#[cfg(stage3)]
871+
fn read_enum_variant<T>(&self, names: &[&str], f: &fn(uint) -> T) -> T {
872+
debug!("read_enum_variant(names=%?)", names);
873+
let name = match *self.peek() {
874+
String(ref s) => s,
875+
List([String(ref s), .. _]) => s,
876+
json => fail!(fmt!("invalid variant: %?", json)),
877+
};
878+
let idx = match vec::position(names, |n| str::eq_slice(*n, *name)) {
879+
Some(idx) => idx,
880+
None => fail!(fmt!("Unknown variant name: %?", name)),
881+
};
882+
f(idx)
883+
}
884+
867885
fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T {
868886
debug!("read_enum_variant_arg(idx=%u)", idx);
869-
if idx != 0 { fail!(~"unknown index") }
870-
f()
887+
match *self.peek() {
888+
List(ref list) => {
889+
self.stack.push(&list[idx + 1]);
890+
f()
891+
}
892+
ref json => fail!(fmt!("not a list: %?", json)),
893+
}
871894
}
872895
873896
fn read_owned_vec<T>(&self, f: &fn(uint) -> T) -> T {

src/libstd/serialize.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,15 @@ pub trait Decoder {
9292

9393
// Compound types:
9494
fn read_enum<T>(&self, name: &str, f: &fn() -> T) -> T;
95+
96+
#[cfg(stage0)]
9597
fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T;
98+
99+
#[cfg(stage1)]
100+
#[cfg(stage2)]
101+
#[cfg(stage3)]
102+
fn read_enum_variant<T>(&self, names: &[&str], f: &fn(uint) -> T) -> T;
103+
96104
fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T;
97105

98106
fn read_owned<T>(&self, f: &fn() -> T) -> T;

src/libsyntax/ext/auto_encode.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,6 +1059,18 @@ fn mk_enum_deser_body(
10591059
name: ast::ident,
10601060
variants: ~[ast::variant]
10611061
) -> @ast::expr {
1062+
let expr_arm_names = build::mk_base_vec_e(
1063+
ext_cx,
1064+
span,
1065+
do variants.map |variant| {
1066+
build::mk_base_str(
1067+
ext_cx,
1068+
span,
1069+
ext_cx.str_of(variant.node.name)
1070+
)
1071+
}
1072+
);
1073+
10621074
let mut arms = do variants.mapi |v_idx, variant| {
10631075
let body = match variant.node.kind {
10641076
ast::tuple_variant_kind(ref args) => {
@@ -1152,13 +1164,13 @@ fn mk_enum_deser_body(
11521164
)
11531165
);
11541166
1155-
// ast for `__d.read_enum_variant($(expr_lambda))`
1167+
// ast for `__d.read_enum_variant($expr_arm_names, $(expr_lambda))`
11561168
let expr_lambda = ext_cx.lambda_expr(
11571169
ext_cx.expr_method_call(
11581170
span,
11591171
ext_cx.expr_var(span, ~"__d"),
11601172
ext_cx.ident_of(~"read_enum_variant"),
1161-
~[expr_lambda]
1173+
~[expr_arm_names, expr_lambda]
11621174
)
11631175
);
11641176
@@ -1174,7 +1186,6 @@ fn mk_enum_deser_body(
11741186
)
11751187
}
11761188
1177-
11781189
#[cfg(test)]
11791190
mod test {
11801191
use core::option::{None, Some};

0 commit comments

Comments
 (0)