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) )
}
#[cfg(stage0)]
fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext)
-> typeck::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)
}
#[cfg(stage0)]
fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T {
debug!("read_enum_variant()");
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 {
debug!("read_enum_variant_arg(idx=%u)", idx);
f()
@ -400,6 +413,7 @@ pub mod reader {
f()
}
#[cfg(stage0)]
fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
debug!("read_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()
}
#[cfg(stage0)]
fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T {
debug!("read_enum_variant()");
let idx = match *self.peek() {
@ -864,10 +865,32 @@ impl<'self> serialize::Decoder for Decoder<'self> {
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 {
debug!("read_enum_variant_arg(idx=%u)", idx);
if idx != 0 { fail!(~"unknown index") }
f()
match *self.peek() {
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 {

View file

@ -92,7 +92,15 @@ pub trait Decoder {
// Compound types:
fn read_enum<T>(&self, name: &str, f: &fn() -> T) -> T;
#[cfg(stage0)]
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_owned<T>(&self, f: &fn() -> T) -> T;

View file

@ -1059,6 +1059,18 @@ fn mk_enum_deser_body(
name: ast::ident,
variants: ~[ast::variant]
) -> @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 body = match variant.node.kind {
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(
ext_cx.expr_method_call(
span,
ext_cx.expr_var(span, ~"__d"),
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)]
mod test {
use core::option::{None, Some};