rewrite deserialization to allow for copy-less struct fields
This commit is contained in:
parent
292a820e3a
commit
475fd50564
@ -288,128 +288,57 @@ fn deserialize_struct(
|
||||
deserializer: P<ast::Expr>,
|
||||
token: P<ast::Expr>
|
||||
) -> P<ast::Expr> {
|
||||
let serial_names: Vec<Option<token::InternedString>> =
|
||||
definitions.iter().map(|def|
|
||||
find_serial_name(def.node.attrs.iter())
|
||||
).collect();
|
||||
let type_name_str = cx.expr_str(span, token::get_ident(type_ident));
|
||||
|
||||
let struct_block = deserialize_struct_from_struct(
|
||||
cx,
|
||||
span,
|
||||
type_ident,
|
||||
serial_names.as_slice(),
|
||||
fields,
|
||||
deserializer.clone()
|
||||
);
|
||||
|
||||
let map_block = deserialize_struct_from_map(
|
||||
cx,
|
||||
span,
|
||||
type_ident,
|
||||
serial_names.as_slice(),
|
||||
fields,
|
||||
deserializer.clone()
|
||||
);
|
||||
|
||||
quote_expr!(
|
||||
cx,
|
||||
match $token {
|
||||
::serde::de::StructStart(_, _) => $struct_block,
|
||||
::serde::de::MapStart(_) => $map_block,
|
||||
token => {
|
||||
let expected_tokens = [
|
||||
::serde::de::StructStartKind,
|
||||
::serde::de::MapStartKind,
|
||||
];
|
||||
Err($deserializer.syntax_error(token, expected_tokens))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn deserialize_struct_from_struct(
|
||||
cx: &ExtCtxt,
|
||||
span: Span,
|
||||
type_ident: Ident,
|
||||
serial_names: &[Option<token::InternedString>],
|
||||
fields: &StaticFields,
|
||||
deserializer: P<ast::Expr>
|
||||
) -> P<ast::Expr> {
|
||||
//let expect_struct_field = cx.ident_of("expect_struct_field");
|
||||
|
||||
let call = deserializable_static_fields(
|
||||
cx,
|
||||
span,
|
||||
type_ident,
|
||||
serial_names.as_slice(),
|
||||
fields,
|
||||
|cx, span, name| {
|
||||
let name = cx.expr_str(span, name);
|
||||
quote_expr!(
|
||||
cx,
|
||||
try!($deserializer.expect_struct_field($name))
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
quote_expr!(cx, {
|
||||
let result = $call;
|
||||
try!($deserializer.expect_struct_end());
|
||||
Ok(result)
|
||||
})
|
||||
}
|
||||
|
||||
fn deserialize_struct_from_map(
|
||||
cx: &ExtCtxt,
|
||||
span: Span,
|
||||
type_ident: Ident,
|
||||
serial_names: &[Option<token::InternedString>],
|
||||
fields: &StaticFields,
|
||||
deserializer: P<ast::Expr>
|
||||
) -> P<ast::Expr> {
|
||||
let fields = match *fields {
|
||||
Unnamed(_) => fail!(),
|
||||
Named(ref fields) => fields.as_slice(),
|
||||
};
|
||||
|
||||
// Declare each field.
|
||||
let let_fields: Vec<P<ast::Stmt>> = fields.iter()
|
||||
.map(|&(name, _)| {
|
||||
quote_stmt!(cx, let mut $name = None)
|
||||
// Convert each field into a unique ident.
|
||||
let field_idents: Vec<ast::Ident> = fields.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, _)| {
|
||||
cx.ident_of(format!("field{}", idx).as_slice())
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Convert each field into their string.
|
||||
let field_strs: Vec<P<ast::Expr>> = fields.iter()
|
||||
.zip(definitions.iter())
|
||||
.map(|(&(name, _), def)| {
|
||||
match find_serial_name(def.node.attrs.iter()) {
|
||||
Some(serial) => cx.expr_str(span, serial),
|
||||
None => cx.expr_str(span, token::get_ident(name)),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Declare the static vec slice of field names.
|
||||
let static_fields = cx.expr_vec_slice(span, field_strs.clone());
|
||||
|
||||
// Declare each field.
|
||||
let let_fields: Vec<P<ast::Stmt>> = field_idents.iter()
|
||||
.map(|ident| quote_stmt!(cx, let mut $ident = None))
|
||||
.collect();
|
||||
|
||||
// Declare key arms.
|
||||
let key_arms: Vec<ast::Arm> = serial_names.iter()
|
||||
.zip(fields.iter())
|
||||
.map(|(serial, &(name, span))| {
|
||||
let serial_name = match serial {
|
||||
&Some(ref string) => string.clone(),
|
||||
&None => token::get_ident(name),
|
||||
};
|
||||
let s = cx.expr_str(span, serial_name);
|
||||
let idx_arms: Vec<ast::Arm> = field_idents.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, ident)| {
|
||||
quote_arm!(cx,
|
||||
$s => {
|
||||
$name = Some(
|
||||
try!(::serde::de::Deserializable::deserialize($deserializer))
|
||||
);
|
||||
continue;
|
||||
})
|
||||
Some($idx) => { $ident = Some(try!($deserializer.expect_struct_value())); }
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let extract_fields: Vec<P<ast::Stmt>> = serial_names.iter()
|
||||
.zip(fields.iter())
|
||||
.map(|(serial, &(name, span))| {
|
||||
let serial_name = match serial {
|
||||
&Some(ref string) => string.clone(),
|
||||
&None => token::get_ident(name),
|
||||
};
|
||||
let name_str = cx.expr_str(span, serial_name);
|
||||
let extract_fields: Vec<P<ast::Stmt>> = field_idents.iter()
|
||||
.zip(field_strs.iter())
|
||||
.map(|(ident, field_str)| {
|
||||
quote_stmt!(cx,
|
||||
let $name = match $name {
|
||||
Some($name) => $name,
|
||||
None => try!($deserializer.missing_field($name_str)),
|
||||
let $ident = match $ident {
|
||||
Some($ident) => $ident,
|
||||
None => try!($deserializer.missing_field($field_str)),
|
||||
};
|
||||
)
|
||||
})
|
||||
@ -419,41 +348,34 @@ fn deserialize_struct_from_map(
|
||||
span,
|
||||
type_ident,
|
||||
fields.iter()
|
||||
.map(|&(name, span)| {
|
||||
cx.field_imm(span, name, cx.expr_ident(span, name))
|
||||
.zip(field_idents.iter())
|
||||
.map(|(&(name, _), ident)| {
|
||||
cx.field_imm(span, name, cx.expr_ident(span, *ident))
|
||||
})
|
||||
.collect()
|
||||
);
|
||||
|
||||
quote_expr!(cx, {
|
||||
try!($deserializer.expect_struct_start($token, $type_name_str));
|
||||
|
||||
static FIELDS: &'static [&'static str] = $static_fields;
|
||||
$let_fields
|
||||
|
||||
loop {
|
||||
let token = match try!($deserializer.expect_token()) {
|
||||
::serde::de::End => { break; }
|
||||
token => token,
|
||||
let idx = match try!($deserializer.expect_struct_field_or_end(FIELDS)) {
|
||||
Some(idx) => idx,
|
||||
None => { break; }
|
||||
};
|
||||
|
||||
{
|
||||
let key = match token {
|
||||
::serde::de::Str(s) => s,
|
||||
::serde::de::String(ref s) => s.as_slice(),
|
||||
token => {
|
||||
let expected_tokens = [
|
||||
::serde::de::StrKind,
|
||||
::serde::de::StringKind,
|
||||
];
|
||||
return Err($deserializer.syntax_error(token, expected_tokens));
|
||||
}
|
||||
};
|
||||
|
||||
match key {
|
||||
$key_arms
|
||||
_ => { }
|
||||
match idx {
|
||||
$idx_arms
|
||||
Some(_) => unreachable!(),
|
||||
None => {
|
||||
let _: ::serde::de::IgnoreTokens =
|
||||
try!(::serde::de::Deserializable::deserialize($deserializer));
|
||||
}
|
||||
}
|
||||
|
||||
try!($deserializer.ignore_field(token))
|
||||
//try!($deserializer.ignore_field(token))
|
||||
}
|
||||
|
||||
$extract_fields
|
||||
|
77
src/de.rs
77
src/de.rs
@ -356,25 +356,29 @@ pub trait Deserializer<E>: Iterator<Result<Token, E>> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn expect_struct_field<
|
||||
T: Deserializable<Self, E>
|
||||
>(&mut self, name: &str) -> Result<T, E> {
|
||||
fn expect_struct_field_or_end(&mut self,
|
||||
fields: &'static [&'static str]
|
||||
) -> Result<option::Option<option::Option<uint>>, E> {
|
||||
match try!(self.expect_token()) {
|
||||
End => {
|
||||
Ok(None)
|
||||
}
|
||||
Str(n) => {
|
||||
if name != n {
|
||||
return Err(self.unexpected_name_error(Str(n)));
|
||||
}
|
||||
Ok(Some(fields.iter().position(|field| **field == n)))
|
||||
}
|
||||
String(n) => {
|
||||
if name != n.as_slice() {
|
||||
return Err(self.unexpected_name_error(String(n)));
|
||||
}
|
||||
Ok(Some(fields.iter().position(|field| **field == n.as_slice())))
|
||||
}
|
||||
token => {
|
||||
return Err(self.syntax_error(token, STR_TOKEN_KINDS));
|
||||
Err(self.syntax_error(token, STR_TOKEN_KINDS))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn expect_struct_value<
|
||||
T: Deserializable<Self, E>
|
||||
>(&mut self) -> Result<T, E> {
|
||||
Deserializable::deserialize(self)
|
||||
}
|
||||
|
||||
@ -982,7 +986,7 @@ mod tests {
|
||||
use std::{option, string};
|
||||
use serialize::Decoder;
|
||||
|
||||
use super::{Deserializer, Deserializable, Token, TokenKind};
|
||||
use super::{Deserializer, Deserializable, Token, TokenKind, IgnoreTokens};
|
||||
use super::{
|
||||
Null,
|
||||
Bool,
|
||||
@ -1034,11 +1038,29 @@ mod tests {
|
||||
#[inline]
|
||||
fn deserialize_token(d: &mut D, token: Token) -> Result<Inner, E> {
|
||||
try!(d.expect_struct_start(token, "Inner"));
|
||||
let a = try!(d.expect_struct_field("a"));
|
||||
let b = try!(d.expect_struct_field("b"));
|
||||
let c = try!(d.expect_struct_field("c"));
|
||||
try!(d.expect_struct_end());
|
||||
Ok(Inner { a: a, b: b, c: c })
|
||||
|
||||
let mut a = None;
|
||||
let mut b = None;
|
||||
let mut c = None;
|
||||
|
||||
static FIELDS: &'static [&'static str] = &["a", "b", "c"];
|
||||
|
||||
loop {
|
||||
let idx = match try!(d.expect_struct_field_or_end(FIELDS)) {
|
||||
Some(idx) => idx,
|
||||
None => { break; }
|
||||
};
|
||||
|
||||
match idx {
|
||||
Some(0) => { a = Some(try!(d.expect_struct_value())); }
|
||||
Some(1) => { b = Some(try!(d.expect_struct_value())); }
|
||||
Some(2) => { c = Some(try!(d.expect_struct_value())); }
|
||||
Some(_) => unreachable!(),
|
||||
None => { let _: IgnoreTokens = try!(Deserializable::deserialize(d)); }
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Inner { a: a.unwrap(), b: b.unwrap(), c: c.unwrap() })
|
||||
}
|
||||
}
|
||||
|
||||
@ -1053,9 +1075,25 @@ mod tests {
|
||||
#[inline]
|
||||
fn deserialize_token(d: &mut D, token: Token) -> Result<Outer, E> {
|
||||
try!(d.expect_struct_start(token, "Outer"));
|
||||
let inner = try!(d.expect_struct_field("inner"));
|
||||
try!(d.expect_struct_end());
|
||||
Ok(Outer { inner: inner })
|
||||
|
||||
static FIELDS: &'static [&'static str] = ["inner"];
|
||||
|
||||
let mut inner = None;
|
||||
|
||||
loop {
|
||||
let idx = match try!(d.expect_struct_field_or_end(FIELDS)) {
|
||||
Some(idx) => idx,
|
||||
None => { break; }
|
||||
};
|
||||
|
||||
match idx {
|
||||
Some(0) => { inner = Some(try!(d.expect_struct_value())); }
|
||||
Some(_) => unreachable!(),
|
||||
None => { let _: IgnoreTokens = try!(Deserializable::deserialize(d)); }
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Outer { inner: inner.unwrap() })
|
||||
}
|
||||
}
|
||||
|
||||
@ -1094,7 +1132,6 @@ mod tests {
|
||||
SyntaxError(Vec<TokenKind>),
|
||||
UnexpectedName,
|
||||
ConversionError,
|
||||
IncompleteValue,
|
||||
MissingField(&'static str),
|
||||
}
|
||||
|
||||
|
178
src/json/mod.rs
178
src/json/mod.rs
@ -742,6 +742,14 @@ impl de::Deserializer<ParserError> for JsonDeserializer {
|
||||
None => Err(UnknownVariantError(variant)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn expect_struct_start(&mut self, token: de::Token, _name: &str) -> Result<(), ParserError> {
|
||||
match token {
|
||||
de::MapStart(_) => Ok(()),
|
||||
_ => Err(self.syntax_error(token, [de::MapStartKind])),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The failed expectation of InvalidSyntax
|
||||
@ -1644,6 +1652,7 @@ pub struct Parser<Iter> {
|
||||
col: uint,
|
||||
// A state machine is kept to make it possible to interupt and resume parsing.
|
||||
state_stack: Vec<ParserState>,
|
||||
buf: string::String,
|
||||
}
|
||||
|
||||
impl<Iter: Iterator<char>> Iterator<Result<de::Token, ParserError>> for Parser<Iter> {
|
||||
@ -1669,8 +1678,20 @@ impl<Iter: Iterator<char>> Iterator<Result<de::Token, ParserError>> for Parser<I
|
||||
ParseValue => Some(self.parse_value()),
|
||||
ParseListStart => Some(self.parse_list_start()),
|
||||
ParseListCommaOrEnd => Some(self.parse_list_comma_or_end()),
|
||||
ParseObjectStart => Some(self.parse_object_start()),
|
||||
ParseObjectCommaOrEnd => Some(self.parse_object_comma_or_end()),
|
||||
ParseObjectStart => {
|
||||
match self.parse_object_start() {
|
||||
Ok(Some(s)) => Some(Ok(de::String(s.to_string()))),
|
||||
Ok(None) => Some(Ok(de::End)),
|
||||
Err(err) => Some(Err(err)),
|
||||
}
|
||||
}
|
||||
ParseObjectCommaOrEnd => {
|
||||
match self.parse_object_comma_or_end() {
|
||||
Ok(Some(s)) => Some(Ok(de::String(s.to_string()))),
|
||||
Ok(None) => Some(Ok(de::End)),
|
||||
Err(err) => Some(Err(err)),
|
||||
}
|
||||
}
|
||||
//ParseObjectKey => Some(self.parse_object_key()),
|
||||
ParseObjectValue => Some(self.parse_object_value()),
|
||||
}
|
||||
@ -1679,6 +1700,7 @@ impl<Iter: Iterator<char>> Iterator<Result<de::Token, ParserError>> for Parser<I
|
||||
|
||||
impl<Iter: Iterator<char>> Parser<Iter> {
|
||||
/// Creates the JSON parser.
|
||||
#[inline]
|
||||
pub fn new(rdr: Iter) -> Parser<Iter> {
|
||||
let mut p = Parser {
|
||||
rdr: rdr,
|
||||
@ -1686,6 +1708,7 @@ impl<Iter: Iterator<char>> Parser<Iter> {
|
||||
line: 1,
|
||||
col: 0,
|
||||
state_stack: vec!(ParseValue),
|
||||
buf: string::String::with_capacity(100),
|
||||
};
|
||||
p.bump();
|
||||
return p;
|
||||
@ -1782,6 +1805,7 @@ impl<Iter: Iterator<char>> Parser<Iter> {
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_decimal(&mut self, res: f64) -> Result<f64, ParserError> {
|
||||
self.bump();
|
||||
|
||||
@ -1874,64 +1898,72 @@ impl<Iter: Iterator<char>> Parser<Iter> {
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
fn parse_string(&mut self) -> Result<string::String, ParserError> {
|
||||
fn parse_string(&mut self) -> Result<&str, ParserError> {
|
||||
self.buf.clear();
|
||||
|
||||
let mut escape = false;
|
||||
let mut res = string::String::new();
|
||||
|
||||
|
||||
loop {
|
||||
self.bump();
|
||||
if self.eof() {
|
||||
return self.error(EOFWhileParsingString);
|
||||
}
|
||||
let ch = match self.next_char() {
|
||||
Some(ch) => ch,
|
||||
None => { return self.error(EOFWhileParsingString); }
|
||||
};
|
||||
|
||||
if escape {
|
||||
match self.ch_or_null() {
|
||||
'"' => res.push('"'),
|
||||
'\\' => res.push('\\'),
|
||||
'/' => res.push('/'),
|
||||
'b' => res.push('\x08'),
|
||||
'f' => res.push('\x0c'),
|
||||
'n' => res.push('\n'),
|
||||
'r' => res.push('\r'),
|
||||
't' => res.push('\t'),
|
||||
'u' => match try!(self.decode_hex_escape()) {
|
||||
0xDC00 ... 0xDFFF => return self.error(LoneLeadingSurrogateInHexEscape),
|
||||
match ch {
|
||||
'"' => self.buf.push('"'),
|
||||
'\\' => self.buf.push('\\'),
|
||||
'/' => self.buf.push('/'),
|
||||
'b' => self.buf.push('\x08'),
|
||||
'f' => self.buf.push('\x0c'),
|
||||
'n' => self.buf.push('\n'),
|
||||
'r' => self.buf.push('\r'),
|
||||
't' => self.buf.push('\t'),
|
||||
'u' => {
|
||||
let c = match try!(self.decode_hex_escape()) {
|
||||
0xDC00 ... 0xDFFF => return self.error(LoneLeadingSurrogateInHexEscape),
|
||||
|
||||
// Non-BMP characters are encoded as a sequence of
|
||||
// two hex escapes, representing UTF-16 surrogates.
|
||||
n1 @ 0xD800 ... 0xDBFF => {
|
||||
let c1 = self.next_char();
|
||||
let c2 = self.next_char();
|
||||
match (c1, c2) {
|
||||
(Some('\\'), Some('u')) => (),
|
||||
_ => return self.error(UnexpectedEndOfHexEscape),
|
||||
// Non-BMP characters are encoded as a sequence of
|
||||
// two hex escapes, representing UTF-16 surrogates.
|
||||
n1 @ 0xD800 ... 0xDBFF => {
|
||||
let c1 = self.next_char();
|
||||
let c2 = self.next_char();
|
||||
match (c1, c2) {
|
||||
(Some('\\'), Some('u')) => (),
|
||||
_ => return self.error(UnexpectedEndOfHexEscape),
|
||||
}
|
||||
|
||||
let buf = [n1, try!(self.decode_hex_escape())];
|
||||
match str::utf16_items(buf.as_slice()).next() {
|
||||
Some(ScalarValue(c)) => c,
|
||||
_ => return self.error(LoneLeadingSurrogateInHexEscape),
|
||||
}
|
||||
}
|
||||
|
||||
let buf = [n1, try!(self.decode_hex_escape())];
|
||||
match str::utf16_items(buf.as_slice()).next() {
|
||||
Some(ScalarValue(c)) => res.push(c),
|
||||
_ => return self.error(LoneLeadingSurrogateInHexEscape),
|
||||
n => match char::from_u32(n as u32) {
|
||||
Some(c) => c,
|
||||
None => return self.error(InvalidUnicodeCodePoint),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
n => match char::from_u32(n as u32) {
|
||||
Some(c) => res.push(c),
|
||||
None => return self.error(InvalidUnicodeCodePoint),
|
||||
},
|
||||
},
|
||||
self.buf.push(c);
|
||||
}
|
||||
_ => return self.error(InvalidEscape),
|
||||
}
|
||||
escape = false;
|
||||
} else if self.ch_is('\\') {
|
||||
escape = true;
|
||||
} else {
|
||||
match self.ch {
|
||||
Some('"') => {
|
||||
match ch {
|
||||
'"' => {
|
||||
self.bump();
|
||||
return Ok(res);
|
||||
},
|
||||
Some(c) => res.push(c),
|
||||
None => unreachable!()
|
||||
return Ok(self.buf.as_slice());
|
||||
}
|
||||
'\\' => {
|
||||
escape = true;
|
||||
}
|
||||
ch => {
|
||||
self.buf.push(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1966,26 +1998,26 @@ impl<Iter: Iterator<char>> Parser<Iter> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_object_start(&mut self) -> Result<de::Token, ParserError> {
|
||||
fn parse_object_start(&mut self) -> Result<Option<&str>, ParserError> {
|
||||
self.parse_whitespace();
|
||||
|
||||
if self.ch_is('}') {
|
||||
self.bump();
|
||||
Ok(de::End)
|
||||
Ok(None)
|
||||
} else {
|
||||
self.parse_object_key()
|
||||
Ok(Some(try!(self.parse_object_key())))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_object_comma_or_end(&mut self) -> Result<de::Token, ParserError> {
|
||||
fn parse_object_comma_or_end(&mut self) -> Result<Option<&str>, ParserError> {
|
||||
self.parse_whitespace();
|
||||
|
||||
if self.ch_is(',') {
|
||||
self.bump();
|
||||
self.parse_object_key()
|
||||
Ok(Some(try!(self.parse_object_key())))
|
||||
} else if self.ch_is('}') {
|
||||
self.bump();
|
||||
Ok(de::End)
|
||||
Ok(None)
|
||||
} else if self.eof() {
|
||||
self.error_event(EOFWhileParsingObject)
|
||||
} else {
|
||||
@ -1993,19 +2025,18 @@ impl<Iter: Iterator<char>> Parser<Iter> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_object_key(&mut self) -> Result<de::Token, ParserError> {
|
||||
fn parse_object_key(&mut self) -> Result<&str, ParserError> {
|
||||
self.parse_whitespace();
|
||||
|
||||
self.state_stack.push(ParseObjectValue);
|
||||
|
||||
if self.eof() {
|
||||
return self.error_event(EOFWhileParsingString);
|
||||
}
|
||||
|
||||
match self.ch_or_null() {
|
||||
'"' => {
|
||||
let s = try!(self.parse_string());
|
||||
Ok(de::String(s))
|
||||
self.state_stack.push(ParseObjectValue);
|
||||
|
||||
Ok(try!(self.parse_string()))
|
||||
}
|
||||
_ => self.error_event(KeyMustBeAString),
|
||||
}
|
||||
@ -2038,8 +2069,7 @@ impl<Iter: Iterator<char>> Parser<Iter> {
|
||||
'f' => self.parse_ident("alse", de::Bool(false)),
|
||||
'0' ... '9' | '-' => self.parse_number(),
|
||||
'"' => {
|
||||
let s = try!(self.parse_string());
|
||||
Ok(de::String(s))
|
||||
Ok(de::String(try!(self.parse_string()).to_string()))
|
||||
}
|
||||
'[' => {
|
||||
self.bump();
|
||||
@ -2066,7 +2096,7 @@ impl<Iter: Iterator<char>> Parser<Iter> {
|
||||
}
|
||||
}
|
||||
|
||||
fn error_event(&mut self, reason: ErrorCode) -> Result<de::Token, ParserError> {
|
||||
fn error_event<T>(&mut self, reason: ErrorCode) -> Result<T, ParserError> {
|
||||
self.state_stack.clear();
|
||||
Err(SyntaxError(reason, self.line, self.col))
|
||||
}
|
||||
@ -2153,6 +2183,36 @@ impl<Iter: Iterator<char>> de::Deserializer<ParserError> for Parser<Iter> {
|
||||
_ => self.error(InvalidSyntax(EnumEnd)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn expect_struct_start(&mut self, token: de::Token, _name: &str) -> Result<(), ParserError> {
|
||||
match token {
|
||||
de::MapStart(_) => Ok(()),
|
||||
_ => Err(self.syntax_error(token, [de::MapStartKind])),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn expect_struct_field_or_end(&mut self,
|
||||
fields: &'static [&'static str]
|
||||
) -> Result<Option<Option<uint>>, ParserError> {
|
||||
let result = match self.state_stack.pop() {
|
||||
Some(ParseObjectStart) => {
|
||||
try!(self.parse_object_start())
|
||||
}
|
||||
Some(ParseObjectCommaOrEnd) => {
|
||||
try!(self.parse_object_comma_or_end())
|
||||
}
|
||||
_ => fail!("invalid internal state"),
|
||||
};
|
||||
|
||||
let s = match result {
|
||||
Some(s) => s,
|
||||
None => { return Ok(None); }
|
||||
};
|
||||
|
||||
Ok(Some(fields.iter().position(|field| **field == s.as_slice())))
|
||||
}
|
||||
}
|
||||
|
||||
/// Decodes a json value from an `Iterator<Char>`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user