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:
parent
478e4498b7
commit
4d6dcefcbb
5 changed files with 116 additions and 5 deletions
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ______________________________________________________________________
|
||||
|
|
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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};
|
||||
|
|
Loading…
Add table
Reference in a new issue