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.
This commit is contained in:
Erick Tryzelaar
2013-03-26 18:46:48 -07:00
parent 478e4498b7
commit 4d6dcefcbb
5 changed files with 116 additions and 5 deletions

View File

@@ -681,6 +681,7 @@ impl vtable_decoder_helpers for reader::Decoder {
@self.read_to_vec(|| self.read_vtable_origin(xcx) ) @self.read_to_vec(|| self.read_vtable_origin(xcx) )
} }
#[cfg(stage0)]
fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext) fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext)
-> typeck::vtable_origin { -> typeck::vtable_origin {
do self.read_enum(~"vtable_origin") { do self.read_enum(~"vtable_origin") {
@@ -715,6 +716,44 @@ impl vtable_decoder_helpers for reader::Decoder {
} }
} }
} }
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext)
-> typeck::vtable_origin {
do self.read_enum("vtable_origin") {
do self.read_enum_variant(["vtable_static", "vtable_param"]) |i| {
match i {
0 => {
typeck::vtable_static(
do self.read_enum_variant_arg(0u) {
self.read_def_id(xcx)
},
do self.read_enum_variant_arg(1u) {
self.read_tys(xcx)
},
do self.read_enum_variant_arg(2u) {
self.read_vtable_res(xcx)
}
)
}
1 => {
typeck::vtable_param(
do self.read_enum_variant_arg(0u) {
self.read_uint()
},
do self.read_enum_variant_arg(1u) {
self.read_uint()
}
)
}
// hard to avoid - user input
_ => fail!(~"bad enum variant")
}
}
}
}
} }
// ______________________________________________________________________ // ______________________________________________________________________

View File

@@ -337,6 +337,7 @@ pub mod reader {
self.push_doc(self.next_doc(EsEnum), f) self.push_doc(self.next_doc(EsEnum), f)
} }
#[cfg(stage0)]
fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T { fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T {
debug!("read_enum_variant()"); debug!("read_enum_variant()");
let idx = self._next_uint(EsEnumVid); let idx = self._next_uint(EsEnumVid);
@@ -346,6 +347,18 @@ pub mod reader {
} }
} }
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn read_enum_variant<T>(&self, _names: &[&str], f: &fn(uint) -> T) -> T {
debug!("read_enum_variant()");
let idx = self._next_uint(EsEnumVid);
debug!(" idx=%u", idx);
do self.push_doc(self.next_doc(EsEnumBody)) {
f(idx)
}
}
fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T { fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T {
debug!("read_enum_variant_arg(idx=%u)", idx); debug!("read_enum_variant_arg(idx=%u)", idx);
f() f()
@@ -400,6 +413,7 @@ pub mod reader {
f() f()
} }
#[cfg(stage0)]
fn read_option<T>(&self, f: &fn() -> T) -> Option<T> { fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
debug!("read_option()"); debug!("read_option()");
do self.read_enum("Option") || { do self.read_enum("Option") || {
@@ -412,6 +426,22 @@ pub mod reader {
} }
} }
} }
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
debug!("read_option()");
do self.read_enum("Option") || {
do self.read_enum_variant(["None", "Some"]) |idx| {
match idx {
0 => None,
1 => Some(f()),
_ => fail!(),
}
}
}
}
} }
} }

View File

@@ -855,6 +855,7 @@ impl<'self> serialize::Decoder for Decoder<'self> {
f() f()
} }
#[cfg(stage0)]
fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T { fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T {
debug!("read_enum_variant()"); debug!("read_enum_variant()");
let idx = match *self.peek() { let idx = match *self.peek() {
@@ -864,10 +865,32 @@ impl<'self> serialize::Decoder for Decoder<'self> {
f(idx) f(idx)
} }
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn read_enum_variant<T>(&self, names: &[&str], f: &fn(uint) -> T) -> T {
debug!("read_enum_variant(names=%?)", names);
let name = match *self.peek() {
String(ref s) => s,
List([String(ref s), .. _]) => s,
json => fail!(fmt!("invalid variant: %?", json)),
};
let idx = match vec::position(names, |n| str::eq_slice(*n, *name)) {
Some(idx) => idx,
None => fail!(fmt!("Unknown variant name: %?", name)),
};
f(idx)
}
fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T { fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T {
debug!("read_enum_variant_arg(idx=%u)", idx); debug!("read_enum_variant_arg(idx=%u)", idx);
if idx != 0 { fail!(~"unknown index") } match *self.peek() {
f() List(ref list) => {
self.stack.push(&list[idx + 1]);
f()
}
ref json => fail!(fmt!("not a list: %?", json)),
}
} }
fn read_owned_vec<T>(&self, f: &fn(uint) -> T) -> T { fn read_owned_vec<T>(&self, f: &fn(uint) -> T) -> T {

View File

@@ -92,7 +92,15 @@ pub trait Decoder {
// Compound types: // Compound types:
fn read_enum<T>(&self, name: &str, f: &fn() -> T) -> T; fn read_enum<T>(&self, name: &str, f: &fn() -> T) -> T;
#[cfg(stage0)]
fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T; fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T;
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn read_enum_variant<T>(&self, names: &[&str], f: &fn(uint) -> T) -> T;
fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T; fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T;
fn read_owned<T>(&self, f: &fn() -> T) -> T; fn read_owned<T>(&self, f: &fn() -> T) -> T;

View File

@@ -1059,6 +1059,18 @@ fn mk_enum_deser_body(
name: ast::ident, name: ast::ident,
variants: ~[ast::variant] variants: ~[ast::variant]
) -> @ast::expr { ) -> @ast::expr {
let expr_arm_names = build::mk_base_vec_e(
ext_cx,
span,
do variants.map |variant| {
build::mk_base_str(
ext_cx,
span,
ext_cx.str_of(variant.node.name)
)
}
);
let mut arms = do variants.mapi |v_idx, variant| { let mut arms = do variants.mapi |v_idx, variant| {
let body = match variant.node.kind { let body = match variant.node.kind {
ast::tuple_variant_kind(ref args) => { ast::tuple_variant_kind(ref args) => {
@@ -1152,13 +1164,13 @@ fn mk_enum_deser_body(
) )
); );
// ast for `__d.read_enum_variant($(expr_lambda))` // ast for `__d.read_enum_variant($expr_arm_names, $(expr_lambda))`
let expr_lambda = ext_cx.lambda_expr( let expr_lambda = ext_cx.lambda_expr(
ext_cx.expr_method_call( ext_cx.expr_method_call(
span, span,
ext_cx.expr_var(span, ~"__d"), ext_cx.expr_var(span, ~"__d"),
ext_cx.ident_of(~"read_enum_variant"), ext_cx.ident_of(~"read_enum_variant"),
~[expr_lambda] ~[expr_arm_names, expr_lambda]
) )
); );
@@ -1174,7 +1186,6 @@ fn mk_enum_deser_body(
) )
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use core::option::{None, Some}; use core::option::{None, Some};