mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-23 12:58:01 +00:00
+20
-71
@@ -10,7 +10,8 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use json::value::{ToJson, Value};
|
||||
use ser::{self, Serialize};
|
||||
use json::value::{self, Value};
|
||||
|
||||
pub struct ArrayBuilder {
|
||||
array: Vec<Value>,
|
||||
@@ -25,24 +26,25 @@ impl ArrayBuilder {
|
||||
Value::Array(self.array)
|
||||
}
|
||||
|
||||
pub fn push<T: ToJson>(self, value: T) -> ArrayBuilder {
|
||||
let mut builder = self;
|
||||
builder.array.push(value.to_json());
|
||||
builder
|
||||
pub fn push<T: ser::Serialize>(mut self, v: T) -> ArrayBuilder {
|
||||
self.array.push(value::to_value(&v));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn push_array<F>(self, f: F) -> ArrayBuilder where
|
||||
pub fn push_array<F>(mut self, f: F) -> ArrayBuilder where
|
||||
F: FnOnce(ArrayBuilder) -> ArrayBuilder
|
||||
{
|
||||
let builder = ArrayBuilder::new();
|
||||
self.push(f(builder).unwrap())
|
||||
self.array.push(f(builder).unwrap());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn push_object<F>(self, f: F) -> ArrayBuilder where
|
||||
pub fn push_object<F>(mut self, f: F) -> ArrayBuilder where
|
||||
F: FnOnce(ObjectBuilder) -> ObjectBuilder
|
||||
{
|
||||
let builder = ObjectBuilder::new();
|
||||
self.push(f(builder).unwrap())
|
||||
self.array.push(f(builder).unwrap());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,77 +61,24 @@ impl ObjectBuilder {
|
||||
Value::Object(self.object)
|
||||
}
|
||||
|
||||
pub fn insert<V: ToJson>(self, key: String, value: V) -> ObjectBuilder {
|
||||
let mut builder = self;
|
||||
builder.object.insert(key, value.to_json());
|
||||
builder
|
||||
pub fn insert<V: ser::Serialize>(mut self, k: String, v: V) -> ObjectBuilder {
|
||||
self.object.insert(k, value::to_value(&v));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn insert_array<F>(self, key: String, f: F) -> ObjectBuilder where
|
||||
pub fn insert_array<F>(mut self, key: String, f: F) -> ObjectBuilder where
|
||||
F: FnOnce(ArrayBuilder) -> ArrayBuilder
|
||||
{
|
||||
let builder = ArrayBuilder::new();
|
||||
self.insert(key, f(builder).unwrap())
|
||||
self.object.insert(key, f(builder).unwrap());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn insert_object<F>(self, key: String, f: F) -> ObjectBuilder where
|
||||
pub fn insert_object<F>(mut self, key: String, f: F) -> ObjectBuilder where
|
||||
F: FnOnce(ObjectBuilder) -> ObjectBuilder
|
||||
{
|
||||
let builder = ObjectBuilder::new();
|
||||
self.insert(key, f(builder).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use json::value::Value;
|
||||
use super::{ArrayBuilder, ObjectBuilder};
|
||||
|
||||
#[test]
|
||||
fn test_array_builder() {
|
||||
let value = ArrayBuilder::new().unwrap();
|
||||
assert_eq!(value, Value::Array(Vec::new()));
|
||||
|
||||
let value = ArrayBuilder::new()
|
||||
.push(1is)
|
||||
.push(2is)
|
||||
.push(3is)
|
||||
.unwrap();
|
||||
assert_eq!(value, Value::Array(vec!(Value::Integer(1), Value::Integer(2), Value::Integer(3))));
|
||||
|
||||
let value = ArrayBuilder::new()
|
||||
.push_array(|bld| bld.push(1is).push(2is).push(3is))
|
||||
.unwrap();
|
||||
assert_eq!(value, Value::Array(vec!(Value::Array(vec!(Value::Integer(1), Value::Integer(2), Value::Integer(3))))));
|
||||
|
||||
let value = ArrayBuilder::new()
|
||||
.push_object(|bld|
|
||||
bld
|
||||
.insert("a".to_string(), 1is)
|
||||
.insert("b".to_string(), 2is))
|
||||
.unwrap();
|
||||
|
||||
let mut map = BTreeMap::new();
|
||||
map.insert("a".to_string(), Value::Integer(1));
|
||||
map.insert("b".to_string(), Value::Integer(2));
|
||||
assert_eq!(value, Value::Array(vec!(Value::Object(map))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_object_builder() {
|
||||
let value = ObjectBuilder::new().unwrap();
|
||||
assert_eq!(value, Value::Object(BTreeMap::new()));
|
||||
|
||||
let value = ObjectBuilder::new()
|
||||
.insert("a".to_string(), 1is)
|
||||
.insert("b".to_string(), 2is)
|
||||
.unwrap();
|
||||
|
||||
let mut map = BTreeMap::new();
|
||||
map.insert("a".to_string(), Value::Integer(1));
|
||||
map.insert("b".to_string(), Value::Integer(2));
|
||||
assert_eq!(value, Value::Object(map));
|
||||
self.object.insert(key, f(builder).unwrap());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
+288
-316
@@ -1,110 +1,50 @@
|
||||
use std::str;
|
||||
use std::char;
|
||||
use std::num::Float;
|
||||
use unicode::str::Utf16Item;
|
||||
use std::char;
|
||||
use std::str;
|
||||
|
||||
use de;
|
||||
|
||||
use super::error::{Error, ErrorCode};
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
enum State {
|
||||
// Parse a value.
|
||||
Value,
|
||||
// Parse a value or ']'.
|
||||
ListStart,
|
||||
// Parse ',' or ']' after an element in a list.
|
||||
ListCommaOrEnd,
|
||||
// Parse a key:value or an ']'.
|
||||
ObjectStart,
|
||||
// Parse ',' or ']' after an element in an object.
|
||||
ObjectCommaOrEnd,
|
||||
// Parse a key in an object.
|
||||
//ObjectKey,
|
||||
// Parse a value in an object.
|
||||
ObjectValue,
|
||||
}
|
||||
|
||||
/// A streaming JSON parser implemented as an iterator of JsonEvent, consuming
|
||||
/// an iterator of char.
|
||||
pub struct Parser<Iter> {
|
||||
pub struct Deserializer<Iter> {
|
||||
rdr: Iter,
|
||||
ch: Option<u8>,
|
||||
line: usize,
|
||||
col: usize,
|
||||
// A state machine is kept to make it possible to interupt and resume parsing.
|
||||
state_stack: Vec<State>,
|
||||
buf: Vec<u8>,
|
||||
}
|
||||
|
||||
impl<Iter: Iterator<Item=u8>> Iterator for Parser<Iter> {
|
||||
type Item = Result<de::Token, Error>;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Result<de::Token, Error>> {
|
||||
let state = match self.state_stack.pop() {
|
||||
Some(state) => state,
|
||||
None => {
|
||||
// If we have no state left, then we're expecting the structure
|
||||
// to be done, so make sure there are no trailing characters.
|
||||
|
||||
self.parse_whitespace();
|
||||
|
||||
if self.eof() {
|
||||
return None;
|
||||
} else {
|
||||
return Some(Err(self.error(ErrorCode::TrailingCharacters)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match state {
|
||||
State::Value => Some(self.parse_value()),
|
||||
State::ListStart => Some(self.parse_list_start()),
|
||||
State::ListCommaOrEnd => Some(self.parse_list_comma_or_end()),
|
||||
State::ObjectStart => {
|
||||
match self.parse_object_start() {
|
||||
Ok(Some(s)) => Some(Ok(de::Token::String(s.to_string()))),
|
||||
Ok(None) => Some(Ok(de::Token::End)),
|
||||
Err(err) => Some(Err(err)),
|
||||
}
|
||||
}
|
||||
State::ObjectCommaOrEnd => {
|
||||
match self.parse_object_comma_or_end() {
|
||||
Ok(Some(s)) => Some(Ok(de::Token::String(s.to_string()))),
|
||||
Ok(None) => Some(Ok(de::Token::End)),
|
||||
Err(err) => Some(Err(err)),
|
||||
}
|
||||
}
|
||||
//State::ObjectKey => Some(self.parse_object_key()),
|
||||
State::ObjectValue => Some(self.parse_object_value()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
impl<Iter> Deserializer<Iter>
|
||||
where Iter: Iterator<Item=u8>,
|
||||
{
|
||||
/// Creates the JSON parser.
|
||||
#[inline]
|
||||
pub fn new(rdr: Iter) -> Parser<Iter> {
|
||||
let mut p = Parser {
|
||||
pub fn new(rdr: Iter) -> Deserializer<Iter> {
|
||||
let mut p = Deserializer {
|
||||
rdr: rdr,
|
||||
ch: Some(b'\x00'),
|
||||
line: 1,
|
||||
col: 0,
|
||||
state_stack: vec!(State::Value),
|
||||
buf: Vec::with_capacity(128),
|
||||
};
|
||||
p.bump();
|
||||
return p;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn end(&mut self) -> Result<(), Error> {
|
||||
self.parse_whitespace();
|
||||
if self.eof() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(self.error(ErrorCode::TrailingCharacters))
|
||||
}
|
||||
}
|
||||
|
||||
fn eof(&self) -> bool { self.ch.is_none() }
|
||||
|
||||
#[inline]
|
||||
fn ch_or_null(&self) -> u8 { self.ch.unwrap_or(b'\x00') }
|
||||
|
||||
#[inline(always)]
|
||||
fn bump(&mut self) {
|
||||
self.ch = self.rdr.next();
|
||||
|
||||
@@ -116,23 +56,19 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn next_char(&mut self) -> Option<u8> {
|
||||
self.bump();
|
||||
self.ch
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn ch_is(&self, c: u8) -> bool {
|
||||
self.ch == Some(c)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn error(&mut self, reason: ErrorCode) -> Error {
|
||||
Error::SyntaxError(reason, self.line, self.col)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_whitespace(&mut self) {
|
||||
while self.ch_is(b' ') ||
|
||||
self.ch_is(b'\n') ||
|
||||
@@ -140,8 +76,9 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
self.ch_is(b'\r') { self.bump(); }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_value(&mut self) -> Result<de::Token, Error> {
|
||||
fn parse_value<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
self.parse_whitespace();
|
||||
|
||||
if self.eof() {
|
||||
@@ -149,22 +86,31 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
}
|
||||
|
||||
match self.ch_or_null() {
|
||||
b'n' => self.parse_ident(b"ull", de::Token::Null),
|
||||
b't' => self.parse_ident(b"rue", de::Token::Bool(true)),
|
||||
b'f' => self.parse_ident(b"alse", de::Token::Bool(false)),
|
||||
b'0' ... b'9' | b'-' => self.parse_number(),
|
||||
b'n' => {
|
||||
try!(self.parse_ident(b"ull"));
|
||||
visitor.visit_unit()
|
||||
}
|
||||
b't' => {
|
||||
try!(self.parse_ident(b"rue"));
|
||||
visitor.visit_bool(true)
|
||||
}
|
||||
b'f' => {
|
||||
try!(self.parse_ident(b"alse"));
|
||||
visitor.visit_bool(false)
|
||||
}
|
||||
b'0' ... b'9' | b'-' => self.parse_number(visitor),
|
||||
b'"' => {
|
||||
Ok(de::Token::String(try!(self.parse_string()).to_string()))
|
||||
try!(self.parse_string());
|
||||
let s = str::from_utf8(&self.buf).unwrap();
|
||||
visitor.visit_str(s)
|
||||
}
|
||||
b'[' => {
|
||||
self.bump();
|
||||
self.state_stack.push(State::ListStart);
|
||||
Ok(de::Token::SeqStart(0))
|
||||
visitor.visit_seq(SeqVisitor::new(self))
|
||||
}
|
||||
b'{' => {
|
||||
self.bump();
|
||||
self.state_stack.push(State::ObjectStart);
|
||||
Ok(de::Token::MapStart(0))
|
||||
visitor.visit_map(MapVisitor::new(self))
|
||||
}
|
||||
_ => {
|
||||
Err(self.error(ErrorCode::ExpectedSomeValue))
|
||||
@@ -172,18 +118,18 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_ident(&mut self, ident: &[u8], token: de::Token) -> Result<de::Token, Error> {
|
||||
fn parse_ident(&mut self, ident: &[u8]) -> Result<(), Error> {
|
||||
if ident.iter().all(|c| Some(*c) == self.next_char()) {
|
||||
self.bump();
|
||||
Ok(token)
|
||||
Ok(())
|
||||
} else {
|
||||
Err(self.error(ErrorCode::ExpectedSomeIdent))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_number(&mut self) -> Result<de::Token, Error> {
|
||||
fn parse_number<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
let mut neg = 1;
|
||||
|
||||
if self.ch_is(b'-') {
|
||||
@@ -205,13 +151,12 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
res = try!(self.parse_exponent(res));
|
||||
}
|
||||
|
||||
Ok(de::Token::F64(neg * res))
|
||||
visitor.visit_f64(neg * res)
|
||||
} else {
|
||||
Ok(de::Token::I64(neg * res))
|
||||
visitor.visit_i64(neg * res)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_integer(&mut self) -> Result<i64, Error> {
|
||||
let mut res = 0;
|
||||
|
||||
@@ -245,7 +190,6 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_decimal(&mut self, res: f64) -> Result<f64, Error> {
|
||||
self.bump();
|
||||
|
||||
@@ -261,7 +205,7 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
match self.ch_or_null() {
|
||||
c @ b'0' ... b'9' => {
|
||||
dec /= 10.0;
|
||||
res += (((c as isize) - (b'0' as isize)) as f64) * dec;
|
||||
res += (((c as u64) - (b'0' as u64)) as f64) * dec;
|
||||
self.bump();
|
||||
}
|
||||
_ => break,
|
||||
@@ -271,11 +215,10 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_exponent(&mut self, mut res: f64) -> Result<f64, Error> {
|
||||
self.bump();
|
||||
|
||||
let mut exp = 0us;
|
||||
let mut exp = 0;
|
||||
let mut neg_exp = false;
|
||||
|
||||
if self.ch_is(b'+') {
|
||||
@@ -294,7 +237,7 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
match self.ch_or_null() {
|
||||
c @ b'0' ... b'9' => {
|
||||
exp *= 10;
|
||||
exp += (c as usize) - (b'0' as usize);
|
||||
exp += (c as i32) - (b'0' as i32);
|
||||
|
||||
self.bump();
|
||||
}
|
||||
@@ -302,7 +245,7 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
}
|
||||
}
|
||||
|
||||
let exp: f64 = 10_f64.powi(exp as i32);
|
||||
let exp: f64 = 10_f64.powi(exp);
|
||||
if neg_exp {
|
||||
res /= exp;
|
||||
} else {
|
||||
@@ -312,11 +255,10 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_hex_escape(&mut self) -> Result<u16, Error> {
|
||||
let mut i = 0us;
|
||||
let mut i = 0;
|
||||
let mut n = 0u16;
|
||||
while i < 4us && !self.eof() {
|
||||
while i < 4 && !self.eof() {
|
||||
self.bump();
|
||||
n = match self.ch_or_null() {
|
||||
c @ b'0' ... b'9' => n * 16_u16 + ((c as u16) - (b'0' as u16)),
|
||||
@@ -329,19 +271,18 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
_ => { return Err(self.error(ErrorCode::InvalidEscape)); }
|
||||
};
|
||||
|
||||
i += 1us;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// Error out if we didn't parse 4 digits.
|
||||
if i != 4us {
|
||||
if i != 4 {
|
||||
return Err(self.error(ErrorCode::InvalidEscape));
|
||||
}
|
||||
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_string(&mut self) -> Result<&str, Error> {
|
||||
fn parse_string(&mut self) -> Result<(), Error> {
|
||||
self.buf.clear();
|
||||
|
||||
let mut escape = false;
|
||||
@@ -397,7 +338,7 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
}
|
||||
};
|
||||
|
||||
let buf = &mut [0u8; 4];
|
||||
let buf = &mut [0; 4];
|
||||
let len = c.encode_utf8(buf).unwrap_or(0);
|
||||
self.buf.extend(buf[..len].iter().map(|b| *b));
|
||||
}
|
||||
@@ -410,7 +351,7 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
match ch {
|
||||
b'"' => {
|
||||
self.bump();
|
||||
return Ok(str::from_utf8(&self.buf).unwrap());
|
||||
return Ok(());
|
||||
}
|
||||
b'\\' => {
|
||||
escape = true;
|
||||
@@ -423,92 +364,12 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_list_start(&mut self) -> Result<de::Token, Error> {
|
||||
self.parse_whitespace();
|
||||
|
||||
if self.ch_is(b']') {
|
||||
self.bump();
|
||||
Ok(de::Token::End)
|
||||
} else {
|
||||
self.state_stack.push(State::ListCommaOrEnd);
|
||||
self.parse_value()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_list_comma_or_end(&mut self) -> Result<de::Token, Error> {
|
||||
self.parse_whitespace();
|
||||
|
||||
if self.ch_is(b',') {
|
||||
self.bump();
|
||||
self.state_stack.push(State::ListCommaOrEnd);
|
||||
self.parse_value()
|
||||
} else if self.ch_is(b']') {
|
||||
self.bump();
|
||||
Ok(de::Token::End)
|
||||
} else if self.eof() {
|
||||
Err(self.error(ErrorCode::EOFWhileParsingList))
|
||||
} else {
|
||||
Err(self.error(ErrorCode::ExpectedListCommaOrEnd))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_object_start(&mut self) -> Result<Option<&str>, Error> {
|
||||
self.parse_whitespace();
|
||||
|
||||
if self.ch_is(b'}') {
|
||||
self.bump();
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(try!(self.parse_object_key())))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_object_comma_or_end(&mut self) -> Result<Option<&str>, Error> {
|
||||
self.parse_whitespace();
|
||||
|
||||
if self.ch_is(b',') {
|
||||
self.bump();
|
||||
Ok(Some(try!(self.parse_object_key())))
|
||||
} else if self.ch_is(b'}') {
|
||||
self.bump();
|
||||
Ok(None)
|
||||
} else if self.eof() {
|
||||
Err(self.error(ErrorCode::EOFWhileParsingObject))
|
||||
} else {
|
||||
Err(self.error(ErrorCode::ExpectedObjectCommaOrEnd))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_object_key(&mut self) -> Result<&str, Error> {
|
||||
self.parse_whitespace();
|
||||
|
||||
if self.eof() {
|
||||
return Err(self.error(ErrorCode::EOFWhileParsingString));
|
||||
}
|
||||
|
||||
match self.ch_or_null() {
|
||||
b'"' => {
|
||||
self.state_stack.push(State::ObjectValue);
|
||||
|
||||
Ok(try!(self.parse_string()))
|
||||
}
|
||||
_ => Err(self.error(ErrorCode::KeyMustBeAString)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_object_value(&mut self) -> Result<de::Token, Error> {
|
||||
fn parse_object_colon(&mut self) -> Result<(), Error> {
|
||||
self.parse_whitespace();
|
||||
|
||||
if self.ch_is(b':') {
|
||||
self.bump();
|
||||
self.state_stack.push(State::ObjectCommaOrEnd);
|
||||
self.parse_value()
|
||||
Ok(())
|
||||
} else if self.eof() {
|
||||
Err(self.error(ErrorCode::EOFWhileParsingObject))
|
||||
} else {
|
||||
@@ -517,148 +378,259 @@ impl<Iter: Iterator<Item=u8>> Parser<Iter> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Iter: Iterator<Item=u8>> de::Deserializer<Error> for Parser<Iter> {
|
||||
fn end_of_stream_error(&mut self) -> Error {
|
||||
Error::SyntaxError(ErrorCode::EOFWhileParsingValue, self.line, self.col)
|
||||
}
|
||||
impl<Iter> de::Deserializer for Deserializer<Iter>
|
||||
where Iter: Iterator<Item=u8>,
|
||||
{
|
||||
type Error = Error;
|
||||
|
||||
fn syntax_error(&mut self, token: de::Token, expected: &'static [de::TokenKind]) -> Error {
|
||||
Error::SyntaxError(ErrorCode::ExpectedTokens(token, expected), self.line, self.col)
|
||||
}
|
||||
|
||||
fn unexpected_name_error(&mut self, token: de::Token) -> Error {
|
||||
Error::SyntaxError(ErrorCode::UnexpectedName(token), self.line, self.col)
|
||||
}
|
||||
|
||||
fn conversion_error(&mut self, token: de::Token) -> Error {
|
||||
Error::SyntaxError(ErrorCode::ConversionError(token), self.line, self.col)
|
||||
#[inline]
|
||||
fn visit<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
self.parse_value(visitor)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn missing_field<
|
||||
T: de::Deserialize<Parser<Iter>, Error>
|
||||
>(&mut self, _field: &'static str) -> Result<T, Error> {
|
||||
// JSON can represent `null` values as a missing value, so this isn't
|
||||
// necessarily an error.
|
||||
de::Deserialize::deserialize_token(self, de::Token::Null)
|
||||
}
|
||||
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
self.parse_whitespace();
|
||||
|
||||
// Special case treating options as a nullable value.
|
||||
#[inline]
|
||||
fn expect_option<
|
||||
U: de::Deserialize<Parser<Iter>, Error>
|
||||
>(&mut self, token: de::Token) -> Result<Option<U>, Error> {
|
||||
match token {
|
||||
de::Token::Null => Ok(None),
|
||||
token => {
|
||||
let value: U = try!(de::Deserialize::deserialize_token(self, token));
|
||||
Ok(Some(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Special case treating enums as a `{"<variant-name>": [<fields>]}`.
|
||||
#[inline]
|
||||
fn expect_enum_start(&mut self,
|
||||
token: de::Token,
|
||||
_name: &str,
|
||||
variants: &[&str]) -> Result<usize, Error> {
|
||||
match token {
|
||||
de::Token::MapStart(_) => { }
|
||||
_ => { return Err(self.error(ErrorCode::ExpectedEnumMapStart)); }
|
||||
};
|
||||
|
||||
// Enums only have one field in them, which is the variant name.
|
||||
let variant = match try!(self.expect_token()) {
|
||||
de::Token::String(variant) => variant,
|
||||
_ => { return Err(self.error(ErrorCode::ExpectedEnumVariantString)); }
|
||||
};
|
||||
|
||||
// The variant's field is a list of the values.
|
||||
match try!(self.expect_token()) {
|
||||
de::Token::SeqStart(_) => { }
|
||||
_ => { return Err(self.error(ErrorCode::ExpectedEnumToken)); }
|
||||
if self.eof() {
|
||||
return Err(self.error(ErrorCode::EOFWhileParsingValue));
|
||||
}
|
||||
|
||||
match variants.iter().position(|v| *v == &variant[]) {
|
||||
Some(idx) => Ok(idx),
|
||||
None => Err(self.error(ErrorCode::UnknownVariant)),
|
||||
}
|
||||
}
|
||||
|
||||
fn expect_enum_end(&mut self) -> Result<(), Error> {
|
||||
// There will be one `End` for the list, and one for the object.
|
||||
match try!(self.expect_token()) {
|
||||
de::Token::End => {
|
||||
match try!(self.expect_token()) {
|
||||
de::Token::End => Ok(()),
|
||||
_ => Err(self.error(ErrorCode::ExpectedEnumEndToken)),
|
||||
}
|
||||
}
|
||||
_ => Err(self.error(ErrorCode::ExpectedEnumEnd)),
|
||||
if self.ch_is(b'n') {
|
||||
try!(self.parse_ident(b"ull"));
|
||||
visitor.visit_none()
|
||||
} else {
|
||||
visitor.visit_some(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn expect_struct_start(&mut self, token: de::Token, _name: &str) -> Result<(), Error> {
|
||||
match token {
|
||||
de::Token::MapStart(_) => Ok(()),
|
||||
_ => {
|
||||
static EXPECTED_TOKENS: &'static [de::TokenKind] = &[
|
||||
de::TokenKind::MapStartKind,
|
||||
];
|
||||
Err(self.syntax_error(token, EXPECTED_TOKENS))
|
||||
fn visit_enum<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
self.parse_whitespace();
|
||||
|
||||
if self.ch_is(b'{') {
|
||||
self.bump();
|
||||
self.parse_whitespace();
|
||||
|
||||
try!(self.parse_string());
|
||||
try!(self.parse_object_colon());
|
||||
|
||||
let variant = str::from_utf8(&self.buf).unwrap().to_string();
|
||||
|
||||
let value = try!(visitor.visit_variant(&variant, EnumVisitor {
|
||||
de: self,
|
||||
}));
|
||||
|
||||
self.parse_whitespace();
|
||||
|
||||
if self.ch_is(b'}') {
|
||||
self.bump();
|
||||
Ok(value)
|
||||
} else {
|
||||
return Err(self.error(ErrorCode::ExpectedSomeValue));
|
||||
}
|
||||
} else {
|
||||
Err(self.error(ErrorCode::ExpectedSomeValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SeqVisitor<'a, Iter: 'a> {
|
||||
de: &'a mut Deserializer<Iter>,
|
||||
first: bool,
|
||||
}
|
||||
|
||||
impl<'a, Iter> SeqVisitor<'a, Iter> {
|
||||
fn new(de: &'a mut Deserializer<Iter>) -> Self {
|
||||
SeqVisitor {
|
||||
de: de,
|
||||
first: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Iter> de::SeqVisitor for SeqVisitor<'a, Iter>
|
||||
where Iter: Iterator<Item=u8>
|
||||
{
|
||||
type Error = Error;
|
||||
|
||||
fn visit<T>(&mut self) -> Result<Option<T>, Error>
|
||||
where T: de::Deserialize,
|
||||
{
|
||||
self.de.parse_whitespace();
|
||||
|
||||
if self.de.ch_is(b']') {
|
||||
self.de.bump();
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if self.first {
|
||||
self.first = false;
|
||||
} else {
|
||||
if self.de.ch_is(b',') {
|
||||
self.de.bump();
|
||||
} else if self.de.eof() {
|
||||
return Err(self.de.error(ErrorCode::EOFWhileParsingList));
|
||||
} else {
|
||||
return Err(self.de.error(ErrorCode::ExpectedListCommaOrEnd));
|
||||
}
|
||||
}
|
||||
|
||||
let value = try!(de::Deserialize::deserialize(self.de));
|
||||
Ok(Some(value))
|
||||
}
|
||||
|
||||
fn end(&mut self) -> Result<(), Error> {
|
||||
self.de.parse_whitespace();
|
||||
|
||||
if self.de.ch_is(b']') {
|
||||
self.de.bump();
|
||||
Ok(())
|
||||
} else if self.de.eof() {
|
||||
Err(self.de.error(ErrorCode::EOFWhileParsingList))
|
||||
} else {
|
||||
Err(self.de.error(ErrorCode::TrailingCharacters))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct MapVisitor<'a, Iter: 'a> {
|
||||
de: &'a mut Deserializer<Iter>,
|
||||
first: bool,
|
||||
}
|
||||
|
||||
impl<'a, Iter> MapVisitor<'a, Iter> {
|
||||
fn new(de: &'a mut Deserializer<Iter>) -> Self {
|
||||
MapVisitor {
|
||||
de: de,
|
||||
first: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Iter> de::MapVisitor for MapVisitor<'a, Iter>
|
||||
where Iter: Iterator<Item=u8>
|
||||
{
|
||||
type Error = Error;
|
||||
|
||||
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
|
||||
where K: de::Deserialize,
|
||||
{
|
||||
self.de.parse_whitespace();
|
||||
|
||||
if self.de.ch_is(b'}') {
|
||||
self.de.bump();
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if self.first {
|
||||
self.first = false;
|
||||
} else {
|
||||
if self.de.ch_is(b',') {
|
||||
self.de.bump();
|
||||
self.de.parse_whitespace();
|
||||
} else if self.de.eof() {
|
||||
return Err(self.de.error(ErrorCode::EOFWhileParsingObject));
|
||||
} else {
|
||||
return Err(self.de.error(ErrorCode::ExpectedObjectCommaOrEnd));
|
||||
}
|
||||
}
|
||||
|
||||
if self.de.eof() {
|
||||
return Err(self.de.error(ErrorCode::EOFWhileParsingValue));
|
||||
}
|
||||
|
||||
if !self.de.ch_is(b'"') {
|
||||
return Err(self.de.error(ErrorCode::KeyMustBeAString));
|
||||
}
|
||||
|
||||
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
|
||||
}
|
||||
|
||||
fn visit_value<V>(&mut self) -> Result<V, Error>
|
||||
where V: de::Deserialize,
|
||||
{
|
||||
try!(self.de.parse_object_colon());
|
||||
|
||||
Ok(try!(de::Deserialize::deserialize(self.de)))
|
||||
}
|
||||
|
||||
fn end(&mut self) -> Result<(), Error> {
|
||||
self.de.parse_whitespace();
|
||||
|
||||
if self.de.ch_is(b']') {
|
||||
self.de.bump();
|
||||
Ok(())
|
||||
} else if self.de.eof() {
|
||||
Err(self.de.error(ErrorCode::EOFWhileParsingList))
|
||||
} else {
|
||||
Err(self.de.error(ErrorCode::TrailingCharacters))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct EnumVisitor<'a, Iter: 'a> {
|
||||
de: &'a mut Deserializer<Iter>,
|
||||
}
|
||||
|
||||
impl<'a, Iter> de::EnumVisitor for EnumVisitor<'a, Iter>
|
||||
where Iter: Iterator<Item=u8>,
|
||||
{
|
||||
type Error = Error;
|
||||
|
||||
fn visit_unit(&mut self) -> Result<(), Error> {
|
||||
de::Deserialize::deserialize(self.de)
|
||||
}
|
||||
|
||||
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::EnumSeqVisitor,
|
||||
{
|
||||
self.de.parse_whitespace();
|
||||
|
||||
if self.de.ch_is(b'[') {
|
||||
self.de.bump();
|
||||
visitor.visit(SeqVisitor::new(self.de))
|
||||
} else {
|
||||
Err(self.de.error(ErrorCode::ExpectedSomeValue))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn expect_struct_field_or_end(&mut self,
|
||||
fields: &'static [&'static str]
|
||||
) -> Result<Option<Option<usize>>, Error> {
|
||||
let result = match self.state_stack.pop() {
|
||||
Some(State::ObjectStart) => {
|
||||
try!(self.parse_object_start())
|
||||
}
|
||||
Some(State::ObjectCommaOrEnd) => {
|
||||
try!(self.parse_object_comma_or_end())
|
||||
}
|
||||
_ => panic!("invalid internal state"),
|
||||
};
|
||||
fn visit_map<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::EnumMapVisitor,
|
||||
{
|
||||
self.de.parse_whitespace();
|
||||
|
||||
let s = match result {
|
||||
Some(s) => s,
|
||||
None => { return Ok(None); }
|
||||
};
|
||||
|
||||
Ok(Some(fields.iter().position(|field| *field == &s[])))
|
||||
if self.de.ch_is(b'{') {
|
||||
self.de.bump();
|
||||
visitor.visit(MapVisitor::new(self.de))
|
||||
} else {
|
||||
Err(self.de.error(ErrorCode::ExpectedSomeValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Decodes a json value from an `Iterator<u8>`.
|
||||
pub fn from_iter<
|
||||
Iter: Iterator<Item=u8>,
|
||||
T: de::Deserialize<Parser<Iter>, Error>
|
||||
>(iter: Iter) -> Result<T, Error> {
|
||||
let mut parser = Parser::new(iter);
|
||||
let value = try!(de::Deserialize::deserialize(&mut parser));
|
||||
pub fn from_iter<I, T>(iter: I) -> Result<T, Error>
|
||||
where I: Iterator<Item=u8>,
|
||||
T: de::Deserialize
|
||||
{
|
||||
let mut de = Deserializer::new(iter);
|
||||
let value = try!(de::Deserialize::deserialize(&mut de));
|
||||
|
||||
// Make sure the whole stream has been consumed.
|
||||
match parser.next() {
|
||||
Some(Ok(_token)) => Err(parser.error(ErrorCode::TrailingCharacters)),
|
||||
Some(Err(err)) => Err(err),
|
||||
None => Ok(value),
|
||||
}
|
||||
try!(de.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
/// Decodes a json value from a string
|
||||
pub fn from_str<
|
||||
'a,
|
||||
T: de::Deserialize<Parser<str::Bytes<'a>>, Error>
|
||||
>(s: &'a str) -> Result<T, Error> {
|
||||
pub fn from_str<'a, T>(s: &'a str) -> Result<T, Error>
|
||||
where T: de::Deserialize
|
||||
{
|
||||
from_iter(s.bytes())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
}
|
||||
|
||||
+47
-14
@@ -2,12 +2,11 @@ use std::error;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
|
||||
use de::{Token, TokenKind};
|
||||
use de;
|
||||
|
||||
/// The errors that can arise while parsing a JSON stream.
|
||||
#[derive(Clone, PartialEq)]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum ErrorCode {
|
||||
ConversionError(Token),
|
||||
EOFWhileParsingList,
|
||||
EOFWhileParsingObject,
|
||||
EOFWhileParsingString,
|
||||
@@ -24,7 +23,6 @@ pub enum ErrorCode {
|
||||
ExpectedObjectCommaOrEnd,
|
||||
ExpectedSomeIdent,
|
||||
ExpectedSomeValue,
|
||||
ExpectedTokens(Token, &'static [TokenKind]),
|
||||
InvalidEscape,
|
||||
InvalidNumber,
|
||||
InvalidUnicodeCodePoint,
|
||||
@@ -35,15 +33,16 @@ pub enum ErrorCode {
|
||||
NotUtf8,
|
||||
TrailingCharacters,
|
||||
UnexpectedEndOfHexEscape,
|
||||
UnexpectedName(Token),
|
||||
UnknownVariant,
|
||||
UnrecognizedHex,
|
||||
}
|
||||
|
||||
impl fmt::Debug for ErrorCode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use std::fmt::Debug;
|
||||
|
||||
match *self {
|
||||
ErrorCode::ConversionError(ref token) => write!(f, "failed to convert {:?}", token),
|
||||
//ErrorCode::ConversionError(ref token) => write!(f, "failed to convert {}", token),
|
||||
ErrorCode::EOFWhileParsingList => "EOF While parsing list".fmt(f),
|
||||
ErrorCode::EOFWhileParsingObject => "EOF While parsing object".fmt(f),
|
||||
ErrorCode::EOFWhileParsingString => "EOF While parsing string".fmt(f),
|
||||
@@ -60,7 +59,7 @@ impl fmt::Debug for ErrorCode {
|
||||
ErrorCode::ExpectedObjectCommaOrEnd => "expected `,` or `}`".fmt(f),
|
||||
ErrorCode::ExpectedSomeIdent => "expected ident".fmt(f),
|
||||
ErrorCode::ExpectedSomeValue => "expected value".fmt(f),
|
||||
ErrorCode::ExpectedTokens(ref token, tokens) => write!(f, "expected {:?}, found {:?}", tokens, token),
|
||||
//ErrorCode::ExpectedTokens(ref token, tokens) => write!(f, "expected {}, found {}", tokens, token),
|
||||
ErrorCode::InvalidEscape => "invalid escape".fmt(f),
|
||||
ErrorCode::InvalidNumber => "invalid number".fmt(f),
|
||||
ErrorCode::InvalidUnicodeCodePoint => "invalid unicode code point".fmt(f),
|
||||
@@ -71,7 +70,7 @@ impl fmt::Debug for ErrorCode {
|
||||
ErrorCode::NotUtf8 => "contents not utf-8".fmt(f),
|
||||
ErrorCode::TrailingCharacters => "trailing characters".fmt(f),
|
||||
ErrorCode::UnexpectedEndOfHexEscape => "unexpected end of hex escape".fmt(f),
|
||||
ErrorCode::UnexpectedName(ref name) => write!(f, "unexpected name {:?}", name),
|
||||
//ErrorCode::UnexpectedName(ref name) => write!(f, "unexpected name {}", name),
|
||||
ErrorCode::UnknownVariant => "unknown variant".fmt(f),
|
||||
ErrorCode::UnrecognizedHex => "invalid \\u escape (unrecognized hex)".fmt(f),
|
||||
}
|
||||
@@ -83,39 +82,59 @@ pub enum Error {
|
||||
/// msg, line, col
|
||||
SyntaxError(ErrorCode, usize, usize),
|
||||
IoError(io::Error),
|
||||
/*
|
||||
ExpectedError(String, String),
|
||||
MissingFieldError(String),
|
||||
*/
|
||||
MissingFieldError(&'static str),
|
||||
/*
|
||||
UnknownVariantError(String),
|
||||
*/
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
Error::SyntaxError(..) => "syntax error",
|
||||
Error::IoError(_) => "Input/Output error",
|
||||
Error::IoError(ref error) => error.description(),
|
||||
/*
|
||||
Error::ExpectedError(ref expected, _) => &expected,
|
||||
*/
|
||||
Error::MissingFieldError(_) => "missing field",
|
||||
/*
|
||||
Error::UnknownVariantError(_) => "unknown variant",
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&error::Error> {
|
||||
match *self {
|
||||
Error::IoError(ref error) => Some(error),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Error::SyntaxError(ref code, line, col) => {
|
||||
write!(fmt, "{:?} at line {:?} column {:?}", code, line, col)
|
||||
write!(fmt, "{:?} at line {} column {}", code, line, col)
|
||||
}
|
||||
Error::IoError(ref error) => fmt::Display::fmt(error, fmt),
|
||||
/*
|
||||
Error::ExpectedError(ref expected, ref found) => {
|
||||
write!(fmt, "expected {:?}, found {:?}", expected, found)
|
||||
Some(format!("expected {}, found {}", expected, found))
|
||||
}
|
||||
*/
|
||||
Error::MissingFieldError(ref field) => {
|
||||
write!(fmt, "missing field {:?}", field)
|
||||
write!(fmt, "missing field {}", field)
|
||||
}
|
||||
/*
|
||||
Error::UnknownVariantError(ref variant) => {
|
||||
write!(fmt, "unknown variant {:?}", variant)
|
||||
Some(format!("unknown variant {}", variant))
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,3 +144,17 @@ impl error::FromError<io::Error> for Error {
|
||||
Error::IoError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl de::Error for Error {
|
||||
fn syntax_error() -> Error {
|
||||
Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)
|
||||
}
|
||||
|
||||
fn end_of_stream_error() -> Error {
|
||||
Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 0, 0)
|
||||
}
|
||||
|
||||
fn missing_field_error(field: &'static str) -> Error {
|
||||
Error::MissingFieldError(field)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-305
@@ -1,317 +1,19 @@
|
||||
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Rust JSON serialization library
|
||||
// Copyright (c) 2011 Google Inc.
|
||||
|
||||
#![forbid(non_camel_case_types)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
/*!
|
||||
JSON parsing and serialization
|
||||
|
||||
# What is JSON?
|
||||
|
||||
JSON (JavaScript Object Notation) is a way to write data in Javascript.
|
||||
Like XML it allows one to serialize structured data in a text format that can be read by humans
|
||||
easily.
|
||||
Its native compatibility with JavaScript and its simple syntax make it used widely.
|
||||
|
||||
Json data are serialized in a form of "key":"value".
|
||||
Data types that can be serialized are JavaScript types :
|
||||
boolean (`true` or `false`), number (`f64`), string, array, object, null.
|
||||
An object is a series of string keys mapping to values, in `"key": value` format.
|
||||
Arrays are enclosed in square brackets (&[ ... ]) and objects in curly brackets ({ ... }).
|
||||
A simple JSON document serializing a person, his/her age, address and phone numbers could look like:
|
||||
|
||||
```ignore
|
||||
{
|
||||
"FirstName": "John",
|
||||
"LastName": "Doe",
|
||||
"Age": 43,
|
||||
"Address": {
|
||||
"Street": "Downing Street 10",
|
||||
"City": "London",
|
||||
"Country": "Great Britain"
|
||||
},
|
||||
"PhoneNumbers": [
|
||||
"+44 1234567",
|
||||
"+44 2345678"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
# Rust Type-based Serializing and Deserializing
|
||||
|
||||
Rust provides a mechanism for low boilerplate serializing and deserializing
|
||||
of values to and from JSON via the serialization API.
|
||||
To be able to serialize a piece of data, it must implement the `serde::Serialize` trait.
|
||||
To be able to deserialize a piece of data, it must implement the `serde::Deserialize` trait.
|
||||
The Rust compiler provides an annotation to automatically generate
|
||||
the code for these traits: `#[derive_serialize]` and `#[derive_deserialize]`.
|
||||
|
||||
To serialize using `Serialize`:
|
||||
|
||||
```rust
|
||||
#![feature(plugin)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate serde;
|
||||
|
||||
use std::io::WriteExt;
|
||||
use serde::json;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive_serialize]
|
||||
pub struct TestStruct {
|
||||
data_str: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let to_serialize_object = TestStruct {
|
||||
data_str: "example of string to serialize".to_string()
|
||||
};
|
||||
|
||||
let mut wr = Vec::new();
|
||||
{
|
||||
let mut serializer = json::Serializer::new(wr.by_ref());
|
||||
match to_serialize_object.serialize(&mut serializer) {
|
||||
Ok(()) => (),
|
||||
Err(e) => panic!("json serialization error: {:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Two wrapper functions are provided to serialize a `Serialize` object
|
||||
into a string (String) or buffer (~[u8]): `json::to_string(value)` and
|
||||
`json::to_vec(value)`.
|
||||
|
||||
```rust
|
||||
use serde::json;
|
||||
let to_serialize_object = "example of string to serialize";
|
||||
let serialized_str: String = json::to_string(&to_serialize_object).unwrap();
|
||||
```
|
||||
|
||||
JSON API provide an enum `json::Value` and a trait `ToJson` to serialize
|
||||
object. The trait `ToJson` serialize object into a container `json::Value` and
|
||||
the API provide writer to serialize them into a stream or a string ...
|
||||
|
||||
When using `ToJson` the `Serialize` trait implementation is not mandatory.
|
||||
|
||||
A basic `ToJson` example using a BTreeMap of attribute name / attribute value:
|
||||
|
||||
|
||||
```rust
|
||||
#![feature(plugin)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate serde;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use serde::json::{ToJson, Value};
|
||||
|
||||
pub struct MyStruct {
|
||||
attr1: u8,
|
||||
attr2: String,
|
||||
}
|
||||
|
||||
impl ToJson for MyStruct {
|
||||
fn to_json( &self ) -> Value {
|
||||
let mut d = BTreeMap::new();
|
||||
d.insert("attr1".to_string(), self.attr1.to_json());
|
||||
d.insert("attr2".to_string(), self.attr2.to_json());
|
||||
d.to_json()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let test = MyStruct {attr1: 1, attr2:"test".to_string()};
|
||||
let json: Value = test.to_json();
|
||||
let json_str: String = json.to_string();
|
||||
}
|
||||
```
|
||||
|
||||
Or you can use the helper type `ObjectBuilder`:
|
||||
|
||||
```rust
|
||||
#![feature(plugin)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate serde;
|
||||
|
||||
use serde::json::{ObjectBuilder, ToJson, Value};
|
||||
|
||||
pub struct MyStruct {
|
||||
attr1: u8,
|
||||
attr2: String,
|
||||
}
|
||||
|
||||
impl ToJson for MyStruct {
|
||||
fn to_json( &self ) -> Value {
|
||||
ObjectBuilder::new()
|
||||
.insert("attr1".to_string(), &self.attr1)
|
||||
.insert("attr2".to_string(), &self.attr2)
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let test = MyStruct {attr1: 1, attr2:"test".to_string()};
|
||||
let json: Value = test.to_json();
|
||||
let json_str: String = json.to_string();
|
||||
}
|
||||
```
|
||||
|
||||
To deserialize a JSON string using `Deserialize` trait:
|
||||
|
||||
```rust
|
||||
#![feature(plugin)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate serde;
|
||||
|
||||
use serde::json;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive_deserialize]
|
||||
pub struct MyStruct {
|
||||
attr1: u8,
|
||||
attr2: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let json_str_to_deserialize = "{ \"attr1\": 1, \"attr2\": \"toto\" }";
|
||||
let mut parser = json::Parser::new(json_str_to_deserialize.bytes());
|
||||
let deserialized_object: MyStruct = match Deserialize::deserialize(&mut parser) {
|
||||
Ok(v) => v,
|
||||
Err(e) => panic!("Decoding error: {:?}", e)
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
# Examples of use
|
||||
|
||||
## Using Autoserialization
|
||||
|
||||
Create a struct called `TestStruct1` and serialize and deserialize it to and from JSON
|
||||
using the serialization API, using the derived serialization code.
|
||||
|
||||
```rust
|
||||
#![feature(plugin)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate serde;
|
||||
|
||||
use serde::json;
|
||||
|
||||
#[derive_serialize]
|
||||
#[derive_deserialize]
|
||||
pub struct TestStruct1 {
|
||||
data_int: u8,
|
||||
data_str: String,
|
||||
data_vector: Vec<u8>,
|
||||
}
|
||||
|
||||
// To serialize use the `json::to_string` to serialize an object in a string.
|
||||
// It calls the generated `Serialize` impl.
|
||||
fn main() {
|
||||
let to_serialize_object = TestStruct1 {
|
||||
data_int: 1,
|
||||
data_str: "toto".to_string(),
|
||||
data_vector: vec![2,3,4,5]
|
||||
};
|
||||
let serialized_str: String = json::to_string(&to_serialize_object).unwrap();
|
||||
|
||||
// To deserialize use the `json::from_str` function.
|
||||
|
||||
let deserialized_object: TestStruct1 = match json::from_str(&serialized_str) {
|
||||
Ok(deserialized_object) => deserialized_object,
|
||||
Err(e) => panic!("json deserialization error: {:?}", e),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Using `ToJson`
|
||||
|
||||
This example use the ToJson impl to deserialize the JSON string.
|
||||
Example of `ToJson` trait implementation for TestStruct1.
|
||||
|
||||
```rust
|
||||
#![feature(plugin)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate serde;
|
||||
|
||||
use serde::json::ToJson;
|
||||
use serde::json;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive_serialize] // generate Serialize impl
|
||||
#[derive_deserialize] // generate Deserialize impl
|
||||
pub struct TestStruct1 {
|
||||
data_int: u8,
|
||||
data_str: String,
|
||||
data_vector: Vec<u8>,
|
||||
}
|
||||
|
||||
impl ToJson for TestStruct1 {
|
||||
fn to_json( &self ) -> json::Value {
|
||||
json::builder::ObjectBuilder::new()
|
||||
.insert("data_int".to_string(), &self.data_int)
|
||||
.insert("data_str".to_string(), &self.data_str)
|
||||
.insert("data_vector".to_string(), &self.data_vector)
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Serialization using our impl of to_json
|
||||
|
||||
let test: TestStruct1 = TestStruct1 {
|
||||
data_int: 1,
|
||||
data_str: "toto".to_string(),
|
||||
data_vector: vec![2,3,4,5],
|
||||
};
|
||||
let json: json::Value = test.to_json();
|
||||
let json_str: String = json.to_string();
|
||||
|
||||
// Deserialize like before.
|
||||
|
||||
let mut parser = json::Parser::new(json_str.bytes());
|
||||
let deserialized: TestStruct1 = Deserialize::deserialize(&mut parser).unwrap();
|
||||
}
|
||||
```
|
||||
|
||||
*/
|
||||
|
||||
pub use self::builder::{ArrayBuilder, ObjectBuilder};
|
||||
pub use self::de::{
|
||||
Parser,
|
||||
from_str,
|
||||
};
|
||||
pub use self::de::{Deserializer, from_str};
|
||||
pub use self::error::{Error, ErrorCode};
|
||||
pub use self::ser::{
|
||||
Serializer,
|
||||
PrettySerializer,
|
||||
to_writer,
|
||||
to_writer_pretty,
|
||||
to_vec,
|
||||
to_vec_pretty,
|
||||
to_string,
|
||||
to_pretty_writer,
|
||||
to_pretty_vec,
|
||||
to_pretty_string,
|
||||
to_string_pretty,
|
||||
escape_str,
|
||||
};
|
||||
pub use self::value::{Value, ToJson, from_json};
|
||||
pub use self::value::{Value, to_value, from_value};
|
||||
|
||||
pub mod builder;
|
||||
pub mod de;
|
||||
pub mod error;
|
||||
pub mod ser;
|
||||
pub mod value;
|
||||
pub mod error;
|
||||
|
||||
+337
-516
@@ -1,498 +1,310 @@
|
||||
use std::f32;
|
||||
use std::f64;
|
||||
use std::num::{Float, FpCategory};
|
||||
use std::{f32, f64};
|
||||
use std::io;
|
||||
use std::num::{Float, FpCategory};
|
||||
use std::string::FromUtf8Error;
|
||||
|
||||
use ser;
|
||||
|
||||
/// A structure for implementing serialization to JSON.
|
||||
pub struct Serializer<W> {
|
||||
wr: W,
|
||||
first: bool,
|
||||
writer: W,
|
||||
format: Format,
|
||||
current_indent: usize,
|
||||
indent: usize,
|
||||
}
|
||||
|
||||
#[derive(Copy, PartialEq)]
|
||||
enum Format {
|
||||
Compact,
|
||||
Pretty,
|
||||
}
|
||||
|
||||
impl<W: io::Write> Serializer<W> {
|
||||
/// Creates a new JSON serializer whose output will be written to the writer
|
||||
/// Creates a new JSON visitr whose output will be written to the writer
|
||||
/// specified.
|
||||
pub fn new(wr: W) -> Serializer<W> {
|
||||
#[inline]
|
||||
pub fn new(writer: W) -> Serializer<W> {
|
||||
Serializer {
|
||||
wr: wr,
|
||||
first: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Unwrap the io::Write from the Serializer.
|
||||
pub fn unwrap(self) -> W {
|
||||
self.wr
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: io::Write> ser::Serializer<io::Error> for Serializer<W> {
|
||||
#[inline]
|
||||
fn serialize_null(&mut self) -> io::Result<()> {
|
||||
self.wr.write_all(b"null")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_bool(&mut self, value: bool) -> io::Result<()> {
|
||||
if value {
|
||||
self.wr.write_all(b"true")
|
||||
} else {
|
||||
self.wr.write_all(b"false")
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_isize(&mut self, value: isize) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_i8(&mut self, value: i8) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_i16(&mut self, value: i16) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_i32(&mut self, value: i32) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_i64(&mut self, value: i64) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_usize(&mut self, value: usize) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_u8(&mut self, value: u8) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_u16(&mut self, value: u16) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_u32(&mut self, value: u32) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_u64(&mut self, value: u64) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_f32(&mut self, value: f32) -> io::Result<()> {
|
||||
fmt_f32_or_null(&mut self.wr, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_f64(&mut self, value: f64) -> io::Result<()> {
|
||||
fmt_f64_or_null(&mut self.wr, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_char(&mut self, value: char) -> io::Result<()> {
|
||||
escape_char(&mut self.wr, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_str(&mut self, value: &str) -> io::Result<()> {
|
||||
escape_str(&mut self.wr, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_tuple_start(&mut self, _len: usize) -> io::Result<()> {
|
||||
self.first = true;
|
||||
write!(&mut self.wr, "[")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_tuple_elt<
|
||||
T: ser::Serialize<Serializer<W>, io::Error>
|
||||
>(&mut self, value: &T) -> io::Result<()> {
|
||||
if self.first {
|
||||
self.first = false;
|
||||
} else {
|
||||
try!(write!(&mut self.wr, ","));
|
||||
}
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_tuple_end(&mut self) -> io::Result<()> {
|
||||
write!(&mut self.wr, "]")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_struct_start(&mut self, _name: &str, _len: usize) -> io::Result<()> {
|
||||
self.first = true;
|
||||
write!(&mut self.wr, "{{")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_struct_elt<
|
||||
T: ser::Serialize<Serializer<W>, io::Error>
|
||||
>(&mut self, name: &str, value: &T) -> io::Result<()> {
|
||||
use ser::Serialize;
|
||||
|
||||
if self.first {
|
||||
self.first = false;
|
||||
} else {
|
||||
try!(write!(&mut self.wr, ","));
|
||||
}
|
||||
try!(name.serialize(self));
|
||||
try!(write!(&mut self.wr, ":"));
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_struct_end(&mut self) -> io::Result<()> {
|
||||
write!(&mut self.wr, "}}")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_enum_start(&mut self, _name: &str, variant: &str, _len: usize) -> io::Result<()> {
|
||||
self.first = true;
|
||||
try!(write!(&mut self.wr, "{{"));
|
||||
try!(self.serialize_str(variant));
|
||||
write!(&mut self.wr, ":[")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_enum_elt<
|
||||
T: ser::Serialize<Serializer<W>, io::Error>
|
||||
>(&mut self, value: &T) -> io::Result<()> {
|
||||
if self.first {
|
||||
self.first = false;
|
||||
} else {
|
||||
try!(write!(&mut self.wr, ","));
|
||||
}
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_enum_end(&mut self) -> io::Result<()> {
|
||||
write!(&mut self.wr, "]}}")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_option<
|
||||
T: ser::Serialize<Serializer<W>, io::Error>
|
||||
>(&mut self, v: &Option<T>) -> io::Result<()> {
|
||||
match *v {
|
||||
Some(ref v) => {
|
||||
v.serialize(self)
|
||||
}
|
||||
None => {
|
||||
self.serialize_null()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_seq<
|
||||
T: ser::Serialize<Serializer<W>, io::Error>,
|
||||
Iter: Iterator<Item=T>
|
||||
>(&mut self, iter: Iter) -> io::Result<()> {
|
||||
try!(write!(&mut self.wr, "["));
|
||||
let mut first = true;
|
||||
for elt in iter {
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
try!(write!(&mut self.wr, ","));
|
||||
}
|
||||
try!(elt.serialize(self));
|
||||
|
||||
}
|
||||
write!(&mut self.wr, "]")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_map<
|
||||
K: ser::Serialize<Serializer<W>, io::Error>,
|
||||
V: ser::Serialize<Serializer<W>, io::Error>,
|
||||
Iter: Iterator<Item=(K, V)>
|
||||
>(&mut self, iter: Iter) -> io::Result<()> {
|
||||
try!(write!(&mut self.wr, "{{"));
|
||||
let mut first = true;
|
||||
for (key, value) in iter {
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
try!(write!(&mut self.wr, ","));
|
||||
}
|
||||
try!(key.serialize(self));
|
||||
try!(write!(&mut self.wr, ":"));
|
||||
try!(value.serialize(self));
|
||||
}
|
||||
write!(&mut self.wr, "}}")
|
||||
}
|
||||
}
|
||||
|
||||
/// Another serializer for JSON, but prints out human-readable JSON instead of
|
||||
/// compact data
|
||||
pub struct PrettySerializer<W> {
|
||||
wr: W,
|
||||
indent: usize,
|
||||
first: bool,
|
||||
}
|
||||
|
||||
impl<W: io::Write> PrettySerializer<W> {
|
||||
/// Creates a new serializer whose output will be written to the specified writer
|
||||
pub fn new(wr: W) -> PrettySerializer<W> {
|
||||
PrettySerializer {
|
||||
wr: wr,
|
||||
writer: writer,
|
||||
format: Format::Compact,
|
||||
current_indent: 0,
|
||||
indent: 0,
|
||||
first: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Unwrap the io::Write from the Serializer.
|
||||
pub fn unwrap(self) -> W {
|
||||
self.wr
|
||||
}
|
||||
|
||||
/// Creates a new JSON visitr whose output will be written to the writer
|
||||
/// specified.
|
||||
#[inline]
|
||||
fn serialize_sep(&mut self) -> io::Result<()> {
|
||||
if self.first {
|
||||
self.first = false;
|
||||
self.indent += 2;
|
||||
try!(write!(&mut self.wr, "\n"));
|
||||
} else {
|
||||
try!(write!(&mut self.wr, ",\n"));
|
||||
pub fn new_pretty(writer: W) -> Serializer<W> {
|
||||
Serializer {
|
||||
writer: writer,
|
||||
format: Format::Pretty,
|
||||
current_indent: 0,
|
||||
indent: 2,
|
||||
}
|
||||
|
||||
spaces(&mut self.wr, self.indent)
|
||||
}
|
||||
|
||||
/// Unwrap the `Writer` from the `Serializer`.
|
||||
#[inline]
|
||||
fn serialize_end(&mut self, s: &str) -> io::Result<()> {
|
||||
if !self.first {
|
||||
try!(write!(&mut self.wr, "\n"));
|
||||
self.indent -= 2;
|
||||
try!(spaces(&mut self.wr, self.indent));
|
||||
}
|
||||
|
||||
self.first = false;
|
||||
|
||||
write!(&mut self.wr, "{}", s)
|
||||
pub fn into_inner(self) -> W {
|
||||
self.writer
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: io::Write> ser::Serializer<io::Error> for PrettySerializer<W> {
|
||||
#[inline]
|
||||
fn serialize_null(&mut self) -> io::Result<()> {
|
||||
write!(&mut self.wr, "null")
|
||||
}
|
||||
impl<W: io::Write> ser::Serializer for Serializer<W> {
|
||||
type Value = ();
|
||||
type Error = io::Error;
|
||||
|
||||
#[inline]
|
||||
fn serialize_bool(&mut self, v: bool) -> io::Result<()> {
|
||||
if v {
|
||||
self.wr.write_all(b"true")
|
||||
} else {
|
||||
self.wr.write_all(b"false")
|
||||
}
|
||||
fn visit<T>(&mut self, value: &T) -> io::Result<()>
|
||||
where T: ser::Serialize,
|
||||
{
|
||||
value.visit(&mut Visitor {
|
||||
writer: &mut self.writer,
|
||||
format: self.format,
|
||||
current_indent: self.current_indent,
|
||||
indent: self.indent,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_isize(&mut self, value: isize) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
struct Visitor<'a, W: 'a> {
|
||||
writer: &'a mut W,
|
||||
format: Format,
|
||||
current_indent: usize,
|
||||
indent: usize,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_i8(&mut self, value: i8) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_i16(&mut self, value: i16) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_i32(&mut self, value: i32) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_i64(&mut self, value: i64) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_usize(&mut self, value: usize) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_u8(&mut self, value: u8) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_u16(&mut self, value: u16) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_u32(&mut self, value: u32) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_u64(&mut self, value: u64) -> io::Result<()> {
|
||||
write!(&mut self.wr, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_f32(&mut self, value: f32) -> io::Result<()> {
|
||||
fmt_f32_or_null(&mut self.wr, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_f64(&mut self, value: f64) -> io::Result<()> {
|
||||
fmt_f64_or_null(&mut self.wr, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_char(&mut self, value: char) -> io::Result<()> {
|
||||
escape_char(&mut self.wr, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_str(&mut self, value: &str) -> io::Result<()> {
|
||||
escape_str(&mut self.wr, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_tuple_start(&mut self, _len: usize) -> io::Result<()> {
|
||||
self.first = true;
|
||||
self.wr.write_all(b"[")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_tuple_elt<
|
||||
T: ser::Serialize<PrettySerializer<W>, io::Error>
|
||||
>(&mut self, value: &T) -> io::Result<()> {
|
||||
try!(self.serialize_sep());
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_tuple_end(&mut self) -> io::Result<()> {
|
||||
self.serialize_end("]")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_struct_start(&mut self, _name: &str, _len: usize) -> io::Result<()> {
|
||||
self.first = true;
|
||||
self.wr.write_all(b"{")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_struct_elt<
|
||||
T: ser::Serialize<PrettySerializer<W>, io::Error>
|
||||
>(&mut self, name: &str, value: &T) -> io::Result<()> {
|
||||
try!(self.serialize_sep());
|
||||
try!(self.serialize_str(name));
|
||||
try!(self.wr.write_all(b": "));
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_struct_end(&mut self) -> io::Result<()> {
|
||||
self.serialize_end("}")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_enum_start(&mut self, _name: &str, variant: &str, _len: usize) -> io::Result<()> {
|
||||
self.first = true;
|
||||
try!(self.wr.write_all(b"{"));
|
||||
try!(self.serialize_sep());
|
||||
try!(self.serialize_str(variant));
|
||||
self.first = true;
|
||||
self.wr.write_all(b": [")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_enum_elt<
|
||||
T: ser::Serialize<PrettySerializer<W>, io::Error>
|
||||
>(&mut self, value: &T) -> io::Result<()> {
|
||||
try!(self.serialize_sep());
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_enum_end(&mut self) -> io::Result<()> {
|
||||
try!(self.serialize_tuple_end());
|
||||
self.serialize_struct_end()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_option<
|
||||
T: ser::Serialize<PrettySerializer<W>, io::Error>
|
||||
>(&mut self, v: &Option<T>) -> io::Result<()> {
|
||||
match *v {
|
||||
Some(ref v) => {
|
||||
v.serialize(self)
|
||||
impl<'a, W> Visitor<'a, W> where W: io::Write, {
|
||||
fn serialize_sep(&mut self, first: bool) -> io::Result<()> {
|
||||
match self.format {
|
||||
Format::Compact => {
|
||||
if first {
|
||||
Ok(())
|
||||
} else {
|
||||
self.writer.write_all(b",")
|
||||
}
|
||||
}
|
||||
None => {
|
||||
self.serialize_null()
|
||||
Format::Pretty => {
|
||||
if first {
|
||||
self.current_indent += self.indent;
|
||||
try!(self.writer.write_all(b"\n"));
|
||||
} else {
|
||||
try!(self.writer.write_all(b",\n"));
|
||||
}
|
||||
|
||||
spaces(&mut self.writer, self.current_indent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_seq<
|
||||
T: ser::Serialize<PrettySerializer<W>, io::Error>,
|
||||
Iter: Iterator<Item=T>
|
||||
>(&mut self, iter: Iter) -> io::Result<()> {
|
||||
try!(self.wr.write_all(b"["));
|
||||
|
||||
self.first = true;
|
||||
for elt in iter {
|
||||
try!(self.serialize_sep());
|
||||
try!(elt.serialize(self));
|
||||
fn serialize_colon(&mut self) -> io::Result<()> {
|
||||
match self.format {
|
||||
Format::Compact => self.writer.write_all(b":"),
|
||||
Format::Pretty => self.writer.write_all(b": "),
|
||||
}
|
||||
|
||||
self.serialize_end("]")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_map<
|
||||
K: ser::Serialize<PrettySerializer<W>, io::Error>,
|
||||
V: ser::Serialize<PrettySerializer<W>, io::Error>,
|
||||
Iter: Iterator<Item=(K, V)>
|
||||
>(&mut self, iter: Iter) -> io::Result<()> {
|
||||
try!(self.wr.write_all(b"{"));
|
||||
|
||||
self.first = true;
|
||||
for (key, value) in iter {
|
||||
try!(self.serialize_sep());
|
||||
try!(key.serialize(self));
|
||||
try!(self.wr.write_all(b": "));
|
||||
try!(value.serialize(self));
|
||||
fn serialize_end(&mut self, current_indent: usize, s: &[u8]) -> io::Result<()> {
|
||||
if self.format == Format::Pretty && current_indent != self.current_indent {
|
||||
self.current_indent -= self.indent;
|
||||
try!(self.writer.write(b"\n"));
|
||||
try!(spaces(&mut self.writer, self.current_indent));
|
||||
}
|
||||
|
||||
self.serialize_end("}")
|
||||
self.writer.write_all(s)
|
||||
}
|
||||
}
|
||||
|
||||
fn escape_bytes<W>(wr: &mut W, bytes: &[u8]) -> io::Result<()>
|
||||
impl<'a, W> ser::Visitor for Visitor<'a, W> where W: io::Write, {
|
||||
type Value = ();
|
||||
type Error = io::Error;
|
||||
|
||||
#[inline]
|
||||
fn visit_bool(&mut self, value: bool) -> io::Result<()> {
|
||||
if value {
|
||||
self.writer.write_all(b"true")
|
||||
} else {
|
||||
self.writer.write_all(b"false")
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_isize(&mut self, value: isize) -> io::Result<()> {
|
||||
write!(self.writer, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_i8(&mut self, value: i8) -> io::Result<()> {
|
||||
write!(self.writer, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_i16(&mut self, value: i16) -> io::Result<()> {
|
||||
write!(self.writer, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_i32(&mut self, value: i32) -> io::Result<()> {
|
||||
write!(self.writer, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_i64(&mut self, value: i64) -> io::Result<()> {
|
||||
write!(self.writer, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_usize(&mut self, value: usize) -> io::Result<()> {
|
||||
write!(self.writer, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_u8(&mut self, value: u8) -> io::Result<()> {
|
||||
write!(self.writer, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_u16(&mut self, value: u16) -> io::Result<()> {
|
||||
write!(self.writer, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_u32(&mut self, value: u32) -> io::Result<()> {
|
||||
write!(self.writer, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_u64(&mut self, value: u64) -> io::Result<()> {
|
||||
write!(self.writer, "{}", value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_f32(&mut self, value: f32) -> io::Result<()> {
|
||||
fmt_f32_or_null(self.writer, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_f64(&mut self, value: f64) -> io::Result<()> {
|
||||
fmt_f64_or_null(self.writer, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_char(&mut self, value: char) -> io::Result<()> {
|
||||
escape_char(self.writer, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_str(&mut self, value: &str) -> io::Result<()> {
|
||||
escape_str(self.writer, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_none(&mut self) -> io::Result<()> {
|
||||
self.visit_unit()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_some<V>(&mut self, value: V) -> io::Result<()>
|
||||
where V: ser::Serialize
|
||||
{
|
||||
value.visit(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_unit(&mut self) -> io::Result<()> {
|
||||
self.writer.write_all(b"null")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_enum_unit(&mut self, _name: &str, variant: &str) -> io::Result<()> {
|
||||
let current_indent = self.current_indent;
|
||||
|
||||
try!(self.writer.write_all(b"{"));
|
||||
try!(self.serialize_sep(true));
|
||||
try!(self.visit_str(variant));
|
||||
try!(self.serialize_colon());
|
||||
try!(self.writer.write_all(b"[]"));
|
||||
self.serialize_end(current_indent, b"}")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<V>(&mut self, mut visitor: V) -> io::Result<()>
|
||||
where V: ser::SeqVisitor,
|
||||
{
|
||||
let current_indent = self.current_indent;
|
||||
|
||||
try!(self.writer.write_all(b"["));
|
||||
|
||||
while let Some(()) = try!(visitor.visit(self)) { }
|
||||
|
||||
self.serialize_end(current_indent, b"]")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_enum_seq<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
|
||||
where V: ser::SeqVisitor,
|
||||
{
|
||||
let current_indent = self.current_indent;
|
||||
|
||||
try!(self.writer.write_all(b"{"));
|
||||
try!(self.serialize_sep(true));
|
||||
try!(self.visit_str(variant));
|
||||
try!(self.serialize_colon());
|
||||
try!(self.visit_seq(visitor));
|
||||
self.serialize_end(current_indent, b"}")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq_elt<T>(&mut self, first: bool, value: T) -> io::Result<()>
|
||||
where T: ser::Serialize,
|
||||
{
|
||||
try!(self.serialize_sep(first));
|
||||
|
||||
value.visit(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_map<V>(&mut self, mut visitor: V) -> io::Result<()>
|
||||
where V: ser::MapVisitor,
|
||||
{
|
||||
let current_indent = self.current_indent;
|
||||
|
||||
try!(self.writer.write_all(b"{"));
|
||||
|
||||
while let Some(()) = try!(visitor.visit(self)) { }
|
||||
|
||||
self.serialize_end(current_indent, b"}")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_enum_map<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
|
||||
where V: ser::MapVisitor,
|
||||
{
|
||||
let current_indent = self.current_indent;
|
||||
|
||||
try!(self.writer.write_all(b"{"));
|
||||
try!(self.serialize_sep(true));
|
||||
try!(self.visit_str(variant));
|
||||
try!(self.serialize_colon());
|
||||
try!(self.visit_map(visitor));
|
||||
self.serialize_end(current_indent, b"}")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_map_elt<K, V>(&mut self, first: bool, key: K, value: V) -> io::Result<()>
|
||||
where K: ser::Serialize,
|
||||
V: ser::Serialize,
|
||||
{
|
||||
try!(self.serialize_sep(first));
|
||||
try!(key.visit(self));
|
||||
try!(self.serialize_colon());
|
||||
value.visit(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn escape_bytes<W>(wr: &mut W, bytes: &[u8]) -> io::Result<()>
|
||||
where W: io::Write
|
||||
{
|
||||
try!(wr.write_all(b"\""));
|
||||
@@ -524,15 +336,18 @@ fn escape_bytes<W>(wr: &mut W, bytes: &[u8]) -> io::Result<()>
|
||||
try!(wr.write_all(&bytes[start..]));
|
||||
}
|
||||
|
||||
wr.write_all(b"\"")
|
||||
try!(wr.write_all(b"\""));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn escape_str<W>(wr: &mut W, value: &str) -> io::Result<()>
|
||||
where W: io::Write
|
||||
{
|
||||
escape_bytes(wr, value.as_bytes())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn escape_char<W>(wr: &mut W, value: char) -> io::Result<()>
|
||||
where W: io::Write
|
||||
{
|
||||
@@ -559,9 +374,75 @@ fn fmt_f64_or_null<W>(wr: &mut W, value: f64) -> io::Result<()>
|
||||
}
|
||||
}
|
||||
|
||||
fn spaces<W: io::Write>(wr: &mut W, mut n: usize) -> io::Result<()> {
|
||||
/// Encode the specified struct into a json `[u8]` writer.
|
||||
#[inline]
|
||||
pub fn to_writer<W, T>(writer: &mut W, value: &T) -> io::Result<()>
|
||||
where W: io::Write,
|
||||
T: ser::Serialize,
|
||||
{
|
||||
let mut ser = Serializer::new(writer);
|
||||
try!(ser::Serializer::visit(&mut ser, value));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Encode the specified struct into a json `[u8]` writer.
|
||||
#[inline]
|
||||
pub fn to_writer_pretty<W, T>(writer: &mut W, value: &T) -> io::Result<()>
|
||||
where W: io::Write,
|
||||
T: ser::Serialize,
|
||||
{
|
||||
let mut ser = Serializer::new_pretty(writer);
|
||||
try!(ser::Serializer::visit(&mut ser, value));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Encode the specified struct into a json `[u8]` buffer.
|
||||
#[inline]
|
||||
pub fn to_vec<T>(value: &T) -> Vec<u8>
|
||||
where T: ser::Serialize,
|
||||
{
|
||||
// We are writing to a Vec, which doesn't fail. So we can ignore
|
||||
// the error.
|
||||
let mut writer = Vec::with_capacity(128);
|
||||
to_writer(&mut writer, value).unwrap();
|
||||
writer
|
||||
}
|
||||
|
||||
/// Encode the specified struct into a json `[u8]` buffer.
|
||||
#[inline]
|
||||
pub fn to_vec_pretty<T>(value: &T) -> Vec<u8>
|
||||
where T: ser::Serialize,
|
||||
{
|
||||
// We are writing to a Vec, which doesn't fail. So we can ignore
|
||||
// the error.
|
||||
let mut writer = Vec::with_capacity(128);
|
||||
to_writer_pretty(&mut writer, value).unwrap();
|
||||
writer
|
||||
}
|
||||
|
||||
/// Encode the specified struct into a json `String` buffer.
|
||||
#[inline]
|
||||
pub fn to_string<T>(value: &T) -> Result<String, FromUtf8Error>
|
||||
where T: ser::Serialize
|
||||
{
|
||||
let vec = to_vec(value);
|
||||
String::from_utf8(vec)
|
||||
}
|
||||
|
||||
/// Encode the specified struct into a json `String` buffer.
|
||||
#[inline]
|
||||
pub fn to_string_pretty<T>(value: &T) -> Result<String, FromUtf8Error>
|
||||
where T: ser::Serialize
|
||||
{
|
||||
let vec = to_vec_pretty(value);
|
||||
String::from_utf8(vec)
|
||||
}
|
||||
|
||||
fn spaces<W>(wr: &mut W, mut n: usize) -> io::Result<()>
|
||||
where W: io::Write,
|
||||
{
|
||||
const LEN: usize = 16;
|
||||
const BUF: &'static [u8; LEN] = &[b' '; LEN];
|
||||
const BUF: &'static [u8; LEN] = &[b' '; 16];
|
||||
|
||||
while n >= LEN {
|
||||
try!(wr.write_all(BUF));
|
||||
@@ -574,63 +455,3 @@ fn spaces<W: io::Write>(wr: &mut W, mut n: usize) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode the specified struct into a json `[u8]` writer.
|
||||
#[inline]
|
||||
pub fn to_writer<W, T>(writer: W, value: &T) -> io::Result<W>
|
||||
where W: io::Write,
|
||||
T: ser::Serialize<Serializer<W>, io::Error>
|
||||
{
|
||||
let mut serializer = Serializer::new(writer);
|
||||
try!(value.serialize(&mut serializer));
|
||||
Ok(serializer.unwrap())
|
||||
}
|
||||
|
||||
/// Encode the specified struct into a json `[u8]` buffer.
|
||||
#[inline]
|
||||
pub fn to_vec<T>(value: &T) -> Vec<u8>
|
||||
where T: ser::Serialize<Serializer<Vec<u8>>, io::Error>
|
||||
{
|
||||
// We are writing to a Vec, which doesn't fail. So we can ignore
|
||||
// the error.
|
||||
let writer = Vec::with_capacity(128);
|
||||
to_writer(writer, value).unwrap()
|
||||
}
|
||||
|
||||
/// Encode the specified struct into a json `String` buffer.
|
||||
#[inline]
|
||||
pub fn to_string<T>(value: &T) -> Result<String, FromUtf8Error>
|
||||
where T: ser::Serialize<Serializer<Vec<u8>>, io::Error>
|
||||
{
|
||||
let vec = to_vec(value);
|
||||
String::from_utf8(vec)
|
||||
}
|
||||
|
||||
/// Encode the specified struct into a json `[u8]` writer.
|
||||
#[inline]
|
||||
pub fn to_pretty_writer<
|
||||
W: io::Write,
|
||||
T: ser::Serialize<PrettySerializer<W>, io::Error>
|
||||
>(writer: W, value: &T) -> io::Result<W> {
|
||||
let mut serializer = PrettySerializer::new(writer);
|
||||
try!(value.serialize(&mut serializer));
|
||||
Ok(serializer.unwrap())
|
||||
}
|
||||
|
||||
/// Encode the specified struct into a json `[u8]` buffer.
|
||||
pub fn to_pretty_vec<
|
||||
T: ser::Serialize<PrettySerializer<Vec<u8>>, io::Error>
|
||||
>(value: &T) -> Vec<u8> {
|
||||
// We are writing to a Vec, which doesn't fail. So we can ignore
|
||||
// the error.
|
||||
let writer = Vec::with_capacity(128);
|
||||
to_pretty_writer(writer, value).unwrap()
|
||||
}
|
||||
|
||||
/// Encode the specified struct into a json `String` buffer.
|
||||
pub fn to_pretty_string<
|
||||
T: ser::Serialize<PrettySerializer<Vec<u8>>, io::Error>
|
||||
>(value: &T) -> Result<String, FromUtf8Error> {
|
||||
let buf = to_pretty_vec(value);
|
||||
String::from_utf8(buf)
|
||||
}
|
||||
|
||||
+526
-604
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user