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:
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ______________________________________________________________________
|
// ______________________________________________________________________
|
||||||
|
|||||||
@@ -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!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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};
|
||||||
|
|||||||
Reference in New Issue
Block a user