From 65cfcd03f8551e629cef5248f7a6f499f1aa9925 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 16 Feb 2015 18:17:50 -0800 Subject: [PATCH] Port serde2 to std::io, which cuts the speed by 26% :( --- benches/bench_log.rs | 36 ++-- serde2/benches/bench_log.rs | 205 ++++++++++----------- serde2/src/json/ser.rs | 221 +++++++++++++---------- serde2/src/json/value.rs | 15 +- serde2/src/lib.rs | 2 +- serde2/src/ser.rs | 5 +- src/json/ser.rs | 343 ++++++++++++++++++------------------ 7 files changed, 440 insertions(+), 387 deletions(-) diff --git a/benches/bench_log.rs b/benches/bench_log.rs index f29f2b4c..9e18bd26 100644 --- a/benches/bench_log.rs +++ b/benches/bench_log.rs @@ -50,7 +50,7 @@ impl rustc_serialize::Decodable for HttpProtocol { fn decode(d: &mut D) -> Result { match FromPrimitive::from_uint(try!(d.read_usize())) { Some(value) => Ok(value), - None => Err(d.error("cannot convert from uint")), + None => Err(d.error("cannot convert from usize")), } } } @@ -58,7 +58,7 @@ impl rustc_serialize::Decodable for HttpProtocol { impl, E> ser::Serialize for HttpProtocol { #[inline] fn serialize(&self, s: &mut S) -> Result<(), E> { - s.serialize_usize(*self as usize) + s.serialize_u8(*self as u8) } } @@ -102,7 +102,7 @@ impl rustc_serialize::Decodable for HttpMethod { impl, E> ser::Serialize for HttpMethod { #[inline] fn serialize(&self, s: &mut S) -> Result<(), E> { - s.serialize_usize(*self as usize) + s.serialize_u8(*self as u8) } } @@ -123,15 +123,15 @@ enum CacheStatus { impl rustc_serialize::Encodable for CacheStatus { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - (*self as usize).encode(s) + (*self as u8).encode(s) } } impl rustc_serialize::Decodable for CacheStatus { fn decode(d: &mut D) -> Result { - match FromPrimitive::from_uint(try!(d.read_usize())) { + match FromPrimitive::from_u8(try!(d.read_u8())) { Some(value) => Ok(value), - None => Err(d.error("cannot convert from usize")), + None => Err(d.error("cannot convert from u8")), } } } @@ -169,15 +169,15 @@ enum OriginProtocol { impl rustc_serialize::Encodable for OriginProtocol { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - (*self as usize).encode(s) + (*self as u8).encode(s) } } impl rustc_serialize::Decodable for OriginProtocol { fn decode(d: &mut D) -> Result { - match FromPrimitive::from_uint(try!(d.read_usize())) { + match FromPrimitive::from_u8(try!(d.read_u8())) { Some(value) => Ok(value), - None => Err(d.error("cannot convert from usize")), + None => Err(d.error("cannot convert from u8")), } } } @@ -185,7 +185,7 @@ impl rustc_serialize::Decodable for OriginProtocol { impl, E> ser::Serialize for OriginProtocol { #[inline] fn serialize(&self, s: &mut S) -> Result<(), E> { - s.serialize_usize(*self as usize) + s.serialize_u8(*self as u8) } } @@ -207,15 +207,15 @@ enum ZonePlan { impl rustc_serialize::Encodable for ZonePlan { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - (*self as usize).encode(s) + (*self as u8).encode(s) } } impl rustc_serialize::Decodable for ZonePlan { fn decode(d: &mut D) -> Result { - match FromPrimitive::from_uint(try!(d.read_usize())) { + match FromPrimitive::from_u8(try!(d.read_u8())) { Some(value) => Ok(value), - None => Err(d.error("cannot convert from usize")), + None => Err(d.error("cannot convert from u8")), } } } @@ -223,7 +223,7 @@ impl rustc_serialize::Decodable for ZonePlan { impl, E> ser::Serialize for ZonePlan { #[inline] fn serialize(&self, s: &mut S) -> Result<(), E> { - s.serialize_usize(*self as usize) + s.serialize_u8(*self as u8) } } @@ -496,15 +496,15 @@ enum Country { impl rustc_serialize::Encodable for Country { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - (*self as usize).encode(s) + (*self as u8).encode(s) } } impl rustc_serialize::Decodable for Country { fn decode(d: &mut D) -> Result { - match FromPrimitive::from_uint(try!(d.read_usize())) { + match FromPrimitive::from_u8(try!(d.read_u8())) { Some(value) => Ok(value), - None => Err(d.error("cannot convert from usize")), + None => Err(d.error("cannot convert from u8")), } } } @@ -512,7 +512,7 @@ impl rustc_serialize::Decodable for Country { impl, E> ser::Serialize for Country { #[inline] fn serialize(&self, s: &mut S) -> Result<(), E> { - s.serialize_usize(*self as usize) + s.serialize_u8(*self as u8) } } diff --git a/serde2/benches/bench_log.rs b/serde2/benches/bench_log.rs index ae193216..d4336d6e 100644 --- a/serde2/benches/bench_log.rs +++ b/serde2/benches/bench_log.rs @@ -6,17 +6,16 @@ extern crate serde2; extern crate "rustc-serialize" as rustc_serialize; extern crate test; -use std::old_io; -use std::old_io::ByRefWriter; +use std::io::{self, ReadExt, WriteExt}; use std::num::FromPrimitive; use test::Bencher; +use serde2::de::{Deserialize, Deserializer}; +use serde2::de; use serde2::json::ser::escape_str; use serde2::json; use serde2::ser::{Serialize, Serializer}; use serde2::ser; -use serde2::de::{Deserialize, Deserializer}; -use serde2::de; use rustc_serialize::Encodable; @@ -44,15 +43,15 @@ enum HttpProtocol { impl rustc_serialize::Encodable for HttpProtocol { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - (*self as u8).encode(s) + (*self as usize).encode(s) } } impl rustc_serialize::Decodable for HttpProtocol { fn decode(d: &mut D) -> Result { - match FromPrimitive::from_u8(try!(d.read_u8())) { + match FromPrimitive::from_uint(try!(d.read_usize())) { Some(value) => Ok(value), - None => Err(d.error("cannot convert from u8")), + None => Err(d.error("cannot convert from usize")), } } } @@ -92,15 +91,15 @@ enum HttpMethod { impl rustc_serialize::Encodable for HttpMethod { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - (*self as u8).encode(s) + (*self as usize).encode(s) } } impl rustc_serialize::Decodable for HttpMethod { fn decode(d: &mut D) -> Result { - match FromPrimitive::from_u8(try!(d.read_u8())) { + match FromPrimitive::from_uint(try!(d.read_usize())) { Some(value) => Ok(value), - None => Err(d.error("cannot convert from u8")), + None => Err(d.error("cannot convert from usize")), } } } @@ -141,7 +140,7 @@ impl rustc_serialize::Decodable for CacheStatus { fn decode(d: &mut D) -> Result { match FromPrimitive::from_u8(try!(d.read_u8())) { Some(value) => Ok(value), - None => Err(d.error("cannot convert from uint")), + None => Err(d.error("cannot convert from u8")), } } } @@ -640,10 +639,15 @@ impl MyMemWriter0 { } -impl Writer for MyMemWriter0 { +impl io::Write for MyMemWriter0 { #[inline] - fn write_all(&mut self, buf: &[u8]) -> old_io::IoResult<()> { + fn write(&mut self, buf: &[u8]) -> io::Result { self.buf.push_all(buf); + Ok(buf.len()) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { Ok(()) } } @@ -680,10 +684,15 @@ fn push_all_bytes(dst: &mut Vec, src: &[u8]) { } } -impl Writer for MyMemWriter1 { +impl io::Write for MyMemWriter1 { #[inline] - fn write_all(&mut self, buf: &[u8]) -> old_io::IoResult<()> { + fn write(&mut self, buf: &[u8]) -> io::Result { push_all_bytes(&mut self.buf, buf); + Ok(buf.len()) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { Ok(()) } } @@ -730,14 +739,14 @@ fn bench_encoder(b: &mut Bencher) { #[test] fn test_serializer() { let log = Log::new(); - let json = json::to_vec(&log).unwrap(); + let json = json::to_vec(&log); assert_eq!(json, JSON_STR.as_bytes()); } #[bench] fn bench_serializer(b: &mut Bencher) { let log = Log::new(); - let json = json::to_vec(&log).unwrap(); + let json = json::to_vec(&log); b.bytes = json.len() as u64; b.iter(|| { @@ -759,7 +768,7 @@ fn test_serializer_vec() { #[bench] fn bench_serializer_vec(b: &mut Bencher) { let log = Log::new(); - let json = json::to_vec(&log).unwrap(); + let json = json::to_vec(&log); b.bytes = json.len() as u64; let mut wr = Vec::with_capacity(1024); @@ -776,14 +785,14 @@ fn bench_serializer_vec(b: &mut Bencher) { #[bench] fn bench_serializer_slice(b: &mut Bencher) { let log = Log::new(); - let json = json::to_vec(&log).unwrap(); + let json = json::to_vec(&log); b.bytes = json.len() as u64; let mut buf = [0; 1024]; b.iter(|| { for item in buf.iter_mut(){ *item = 0; } - let mut wr = std::old_io::BufWriter::new(&mut buf); + let mut wr = &mut buf[]; let mut serializer = json::Writer::new(wr.by_ref()); serializer.visit(&log).unwrap(); @@ -809,7 +818,7 @@ fn test_serializer_my_mem_writer0() { #[bench] fn bench_serializer_my_mem_writer0(b: &mut Bencher) { let log = Log::new(); - let json = json::to_vec(&log).unwrap(); + let json = json::to_vec(&log); b.bytes = json.len() as u64; let mut wr = MyMemWriter0::with_capacity(1024); @@ -841,7 +850,7 @@ fn test_serializer_my_mem_writer1() { #[bench] fn bench_serializer_my_mem_writer1(b: &mut Bencher) { let log = Log::new(); - let json = json::to_vec(&log).unwrap(); + let json = json::to_vec(&log); b.bytes = json.len() as u64; let mut wr = MyMemWriter1::with_capacity(1024); @@ -865,166 +874,166 @@ fn bench_copy(b: &mut Bencher) { }); } -fn manual_serialize_no_escape(wr: &mut W, log: &Log) { - wr.write_str("{\"timestamp\":").unwrap(); +fn manual_serialize_no_escape(wr: &mut W, log: &Log) { + wr.write(b"{\"timestamp\":").unwrap(); (write!(wr, "{}", log.timestamp)).unwrap(); - wr.write_str(",\"zone_id\":").unwrap(); + wr.write(b",\"zone_id\":").unwrap(); (write!(wr, "{}", log.zone_id)).unwrap(); - wr.write_str(",\"zone_plan\":").unwrap(); + wr.write(b",\"zone_plan\":").unwrap(); (write!(wr, "{}", log.zone_plan as usize)).unwrap(); - wr.write_str(",\"http\":{\"protocol\":").unwrap(); + wr.write(b",\"http\":{\"protocol\":").unwrap(); (write!(wr, "{}", log.http.protocol as usize)).unwrap(); - wr.write_str(",\"status\":").unwrap(); + wr.write(b",\"status\":").unwrap(); (write!(wr, "{}", log.http.status)).unwrap(); - wr.write_str(",\"host_status\":").unwrap(); + wr.write(b",\"host_status\":").unwrap(); (write!(wr, "{}", log.http.host_status)).unwrap(); - wr.write_str(",\"up_status\":").unwrap(); + wr.write(b",\"up_status\":").unwrap(); (write!(wr, "{}", log.http.up_status)).unwrap(); - wr.write_str(",\"method\":").unwrap(); + wr.write(b",\"method\":").unwrap(); (write!(wr, "{}", log.http.method as usize)).unwrap(); - wr.write_str(",\"content_type\":").unwrap(); + wr.write(b",\"content_type\":").unwrap(); (write!(wr, "\"{}\"", log.http.content_type)).unwrap(); - wr.write_str(",\"user_agent\":").unwrap(); + wr.write(b",\"user_agent\":").unwrap(); (write!(wr, "\"{}\"", log.http.user_agent)).unwrap(); - wr.write_str(",\"referer\":").unwrap(); + wr.write(b",\"referer\":").unwrap(); (write!(wr, "\"{}\"", log.http.referer)).unwrap(); - wr.write_str(",\"request_uri\":").unwrap(); + wr.write(b",\"request_uri\":").unwrap(); (write!(wr, "\"{}\"", log.http.request_uri)).unwrap(); - wr.write_str("},\"origin\":{").unwrap(); + wr.write(b"},\"origin\":{").unwrap(); - wr.write_str("\"ip\":").unwrap(); + wr.write(b"\"ip\":").unwrap(); (write!(wr, "\"{}\"", log.origin.ip)).unwrap(); - wr.write_str(",\"port\":").unwrap(); + wr.write(b",\"port\":").unwrap(); (write!(wr, "{}", log.origin.port)).unwrap(); - wr.write_str(",\"hostname\":").unwrap(); + wr.write(b",\"hostname\":").unwrap(); (write!(wr, "\"{}\"", log.origin.hostname)).unwrap(); - wr.write_str(",\"protocol\":").unwrap(); + wr.write(b",\"protocol\":").unwrap(); (write!(wr, "{}", log.origin.protocol as usize)).unwrap(); - wr.write_str("},\"country\":").unwrap(); + wr.write(b"},\"country\":").unwrap(); (write!(wr, "{}", log.country as usize)).unwrap(); - wr.write_str(",\"cache_status\":").unwrap(); + wr.write(b",\"cache_status\":").unwrap(); (write!(wr, "{}", log.cache_status as usize)).unwrap(); - wr.write_str(",\"server_ip\":").unwrap(); + wr.write(b",\"server_ip\":").unwrap(); (write!(wr, "\"{}\"", log.server_ip)).unwrap(); - wr.write_str(",\"server_name\":").unwrap(); + wr.write(b",\"server_name\":").unwrap(); (write!(wr, "\"{}\"", log.server_name)).unwrap(); - wr.write_str(",\"remote_ip\":").unwrap(); + wr.write(b",\"remote_ip\":").unwrap(); (write!(wr, "\"{}\"", log.remote_ip)).unwrap(); - wr.write_str(",\"bytes_dlv\":").unwrap(); + wr.write(b",\"bytes_dlv\":").unwrap(); (write!(wr, "{}", log.bytes_dlv)).unwrap(); - wr.write_str(",\"ray_id\":").unwrap(); + wr.write(b",\"ray_id\":").unwrap(); (write!(wr, "\"{}\"", log.ray_id)).unwrap(); - wr.write_str("}").unwrap(); + wr.write(b"}").unwrap(); } -fn manual_serialize_escape(wr: &mut W, log: &Log) { - wr.write_str("{").unwrap(); +fn manual_serialize_escape(wr: &mut W, log: &Log) { + wr.write_all(b"{").unwrap(); escape_str(wr, "timestamp").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); (write!(wr, "{}", log.timestamp)).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "zone_id").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); (write!(wr, "{}", log.zone_id)).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "zone_plan").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); (write!(wr, "{}", log.zone_plan as isize)).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "http").unwrap(); - wr.write_str(":{").unwrap(); + wr.write_all(b":{").unwrap(); escape_str(wr, "protocol").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); (write!(wr, "{}", log.http.protocol as usize)).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "status").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); (write!(wr, "{}", log.http.status)).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "host_status").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); (write!(wr, "{}", log.http.host_status)).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "up_status").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); (write!(wr, "{}", log.http.up_status)).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "method").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); (write!(wr, "{}", log.http.method as usize)).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "content_type").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); escape_str(wr, &log.http.content_type).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "user_agent").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); escape_str(wr, &log.http.user_agent).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "referer").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); escape_str(wr, &log.http.referer).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "request_uri").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); escape_str(wr, &log.http.request_uri).unwrap(); - wr.write_str("},").unwrap(); + wr.write_all(b"},").unwrap(); escape_str(wr, "origin").unwrap(); - wr.write_str(":{").unwrap(); + wr.write_all(b":{").unwrap(); escape_str(wr, "ip").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); escape_str(wr, &log.origin.ip).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "port").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); (write!(wr, "{}", log.origin.port)).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "hostname").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); escape_str(wr, &log.origin.hostname).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "protocol").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); (write!(wr, "{}", log.origin.protocol as usize)).unwrap(); - wr.write_str("},").unwrap(); + wr.write_all(b"},").unwrap(); escape_str(wr, "country").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); (write!(wr, "{}", log.country as usize)).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "cache_status").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); (write!(wr, "{}", log.cache_status as usize)).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "server_ip").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); escape_str(wr, &log.server_ip).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "server_name").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); escape_str(wr, &log.server_name).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "remote_ip").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); escape_str(wr, &log.remote_ip).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "bytes_dlv").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); (write!(wr, "{}", log.bytes_dlv)).unwrap(); - wr.write_str(",").unwrap(); + wr.write_all(b",").unwrap(); escape_str(wr, "ray_id").unwrap(); - wr.write_str(":").unwrap(); + wr.write_all(b":").unwrap(); escape_str(wr, &log.ray_id).unwrap(); - wr.write_str("}").unwrap(); + wr.write_all(b"}").unwrap(); } #[test] diff --git a/serde2/src/json/ser.rs b/serde2/src/json/ser.rs index 47e9c1ec..96e4604d 100644 --- a/serde2/src/json/ser.rs +++ b/serde2/src/json/ser.rs @@ -1,17 +1,16 @@ -use std::f64; -use std::old_io::{self, ByRefWriter, IoError}; +use std::{f32, f64}; +use std::io; use std::num::{Float, FpCategory}; use std::string::FromUtf8Error; -use ser; -use ser::Serializer; +use ser::{self, Serializer}; /// A structure for implementing serialization to JSON. pub struct Writer { writer: W, } -impl Writer { +impl Writer { /// Creates a new JSON visitr whose output will be written to the writer /// specified. #[inline] @@ -28,14 +27,14 @@ impl Writer { } } -impl ser::Serializer for Writer { +impl ser::Serializer for Writer { type Value = (); - type Error = IoError; + type Error = io::Error; #[inline] fn visit< T: ser::Serialize, - >(&mut self, value: &T) -> Result<(), IoError> { + >(&mut self, value: &T) -> io::Result<()> { value.visit(&mut Visitor { writer: &mut self.writer }) } } @@ -44,225 +43,263 @@ struct Visitor<'a, W: 'a> { writer: &'a mut W, } -impl<'a, W: old_io::Writer> ser::Visitor for Visitor<'a, W> { +impl<'a, W: io::Write> ser::Visitor for Visitor<'a, W> { type Value = (); - type Error = IoError; + type Error = io::Error; #[inline] - fn visit_unit(&mut self) -> Result<(), IoError> { - self.writer.write_str("null") + fn visit_unit(&mut self) -> io::Result<()> { + try!(self.writer.write(b"null")); + Ok(()) } #[inline] - fn visit_bool(&mut self, value: bool) -> Result<(), IoError> { + fn visit_bool(&mut self, value: bool) -> io::Result<()> { if value { - self.writer.write_str("true") + try!(self.writer.write(b"true")); } else { - self.writer.write_str("false") + try!(self.writer.write(b"false")); } + Ok(()) } #[inline] - fn visit_isize(&mut self, value: isize) -> Result<(), IoError> { + fn visit_isize(&mut self, value: isize) -> io::Result<()> { write!(self.writer, "{}", value) } #[inline] - fn visit_i8(&mut self, value: i8) -> Result<(), IoError> { + fn visit_i8(&mut self, value: i8) -> io::Result<()> { write!(self.writer, "{}", value) } #[inline] - fn visit_i16(&mut self, value: i16) -> Result<(), IoError> { + fn visit_i16(&mut self, value: i16) -> io::Result<()> { write!(self.writer, "{}", value) } #[inline] - fn visit_i32(&mut self, value: i32) -> Result<(), IoError> { + fn visit_i32(&mut self, value: i32) -> io::Result<()> { write!(self.writer, "{}", value) } #[inline] - fn visit_i64(&mut self, value: i64) -> Result<(), IoError> { + fn visit_i64(&mut self, value: i64) -> io::Result<()> { write!(self.writer, "{}", value) } #[inline] - fn visit_usize(&mut self, value: usize) -> Result<(), IoError> { + fn visit_usize(&mut self, value: usize) -> io::Result<()> { write!(self.writer, "{}", value) } #[inline] - fn visit_u8(&mut self, value: u8) -> Result<(), IoError> { + fn visit_u8(&mut self, value: u8) -> io::Result<()> { write!(self.writer, "{}", value) } #[inline] - fn visit_u16(&mut self, value: u16) -> Result<(), IoError> { + fn visit_u16(&mut self, value: u16) -> io::Result<()> { write!(self.writer, "{}", value) } #[inline] - fn visit_u32(&mut self, value: u32) -> Result<(), IoError> { + fn visit_u32(&mut self, value: u32) -> io::Result<()> { write!(self.writer, "{}", value) } #[inline] - fn visit_u64(&mut self, value: u64) -> Result<(), IoError> { + fn visit_u64(&mut self, value: u64) -> io::Result<()> { write!(self.writer, "{}", value) } #[inline] - fn visit_f64(&mut self, value: f64) -> Result<(), IoError> { + 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, v: char) -> Result<(), IoError> { - escape_char(self.writer, v) + fn visit_char(&mut self, value: char) -> io::Result<()> { + escape_char(self.writer, value) } #[inline] - fn visit_str(&mut self, value: &str) -> Result<(), IoError> { + fn visit_str(&mut self, value: &str) -> io::Result<()> { escape_str(self.writer, value) } #[inline] - fn visit_none(&mut self) -> Result<(), IoError> { + fn visit_none(&mut self) -> io::Result<()> { self.visit_unit() } #[inline] - fn visit_some(&mut self, value: V) -> Result<(), IoError> + fn visit_some(&mut self, value: V) -> io::Result<()> where V: ser::Serialize { value.visit(self) } #[inline] - fn visit_seq(&mut self, mut visitor: V) -> Result<(), IoError> + fn visit_seq(&mut self, mut visitor: V) -> io::Result<()> where V: ser::SeqVisitor, { - try!(self.writer.write_str("[")); + try!(self.writer.write(b"[")); while let Some(()) = try!(visitor.visit(self)) { } - self.writer.write_str("]") + try!(self.writer.write(b"]")); + Ok(()) } #[inline] - fn visit_seq_elt(&mut self, first: bool, value: T) -> Result<(), IoError> + fn visit_seq_elt(&mut self, first: bool, value: T) -> io::Result<()> where T: ser::Serialize, { if !first { - try!(self.writer.write_str(",")); + try!(self.writer.write(b",")); } value.visit(self) } #[inline] - fn visit_map(&mut self, mut visitor: V) -> Result<(), IoError> + fn visit_map(&mut self, mut visitor: V) -> io::Result<()> where V: ser::MapVisitor, { - try!(self.writer.write_str("{")); + try!(self.writer.write(b"{")); while let Some(()) = try!(visitor.visit(self)) { } - self.writer.write_str("}") + try!(self.writer.write(b"}")); + + Ok(()) } #[inline] - fn visit_map_elt(&mut self, first: bool, key: K, value: V) -> Result<(), IoError> + fn visit_map_elt(&mut self, first: bool, key: K, value: V) -> io::Result<()> where K: ser::Serialize, V: ser::Serialize, { if !first { - try!(self.writer.write_str(",")); + try!(self.writer.write(b",")); } try!(key.visit(self)); - try!(self.writer.write_str(":")); - value.visit(self) + try!(self.writer.write(b":")); + try!(value.visit(self)); + Ok(()) } } #[inline] -pub fn escape_bytes(wr: &mut W, bytes: &[u8]) -> Result<(), IoError> { - try!(wr.write_str("\"")); +pub fn escape_bytes(wr: &mut W, bytes: &[u8]) -> io::Result<()> + where W: io::Write +{ + try!(wr.write(b"\"")); let mut start = 0; for (i, byte) in bytes.iter().enumerate() { let escaped = match *byte { - b'"' => "\\\"", - b'\\' => "\\\\", - b'\x08' => "\\b", - b'\x0c' => "\\f", - b'\n' => "\\n", - b'\r' => "\\r", - b'\t' => "\\t", + b'"' => b"\\\"", + b'\\' => b"\\\\", + b'\x08' => b"\\b", + b'\x0c' => b"\\f", + b'\n' => b"\\n", + b'\r' => b"\\r", + b'\t' => b"\\t", _ => { continue; } }; if start < i { - try!(wr.write_all(&bytes[start..i])); + try!(wr.write(&bytes[start..i])); } - try!(wr.write_str(escaped)); + try!(wr.write(escaped)); start = i + 1; } if start != bytes.len() { - try!(wr.write_all(&bytes[start..])); + try!(wr.write(&bytes[start..])); } - wr.write_str("\"") -} - -#[inline] -pub fn escape_str(wr: &mut W, value: &str) -> Result<(), IoError> { - escape_bytes(wr, value.as_bytes()) -} - -#[inline] -pub fn escape_char(wr: &mut W, value: char) -> Result<(), IoError> { - let mut buf = &mut [0; 4]; - value.encode_utf8(buf); - escape_bytes(wr, buf) -} - -fn fmt_f64_or_null(wr: &mut W, value: f64) -> Result<(), IoError> { - match value.classify() { - FpCategory::Nan | FpCategory::Infinite => wr.write_str("null"), - _ => wr.write_str(&f64::to_str_digits(value, 6)), - } -} - -#[inline] -pub fn to_writer(wr: &mut W, value: &T) -> Result<(), IoError> - where W: old_io::Writer, - T: ser::Serialize, -{ - let mut wr = Writer::new(wr.by_ref()); - try!(wr.visit(value)); + try!(wr.write(b"\"")); Ok(()) } #[inline] -pub fn to_vec(value: &T) -> Result, IoError> - where T: ser::Serialize, +pub fn escape_str(wr: &mut W, value: &str) -> io::Result<()> + where W: io::Write { - let mut wr = Vec::with_capacity(128); - to_writer(&mut wr, value).unwrap(); - Ok(wr) + escape_bytes(wr, value.as_bytes()) } #[inline] -pub fn to_string(value: &T) -> Result, IoError> +fn escape_char(wr: &mut W, value: char) -> io::Result<()> + where W: io::Write +{ + let buf = &mut [0; 4]; + value.encode_utf8(buf); + escape_bytes(wr, buf) +} + +fn fmt_f32_or_null(wr: &mut W, value: f32) -> io::Result<()> + where W: io::Write +{ + match value.classify() { + FpCategory::Nan | FpCategory::Infinite => try!(wr.write(b"null")), + _ => try!(wr.write(f32::to_str_digits(value, 6).as_bytes())), + }; + + Ok(()) +} + +fn fmt_f64_or_null(wr: &mut W, value: f64) -> io::Result<()> + where W: io::Write +{ + match value.classify() { + FpCategory::Nan | FpCategory::Infinite => try!(wr.write(b"null")), + _ => try!(wr.write(f64::to_str_digits(value, 6).as_bytes())), + }; + + Ok(()) +} + +/// Encode the specified struct into a json `[u8]` writer. +#[inline] +pub fn to_writer(writer: &mut W, value: &T) -> io::Result<()> + where W: io::Write, + T: ser::Serialize, +{ + let mut writer = Writer::new(writer); + try!(writer.visit(value)); + Ok(()) +} + +/// Encode the specified struct into a json `[u8]` buffer. +#[inline] +pub fn to_vec(value: &T) -> Vec where T: ser::Serialize, { - let vec = try!(to_vec(value)); - Ok(String::from_utf8(vec)) + // 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 `String` buffer. +#[inline] +pub fn to_string(value: &T) -> Result + where T: ser::Serialize +{ + let vec = to_vec(value); + String::from_utf8(vec) } diff --git a/serde2/src/json/value.rs b/serde2/src/json/value.rs index c5943a76..9ad08589 100644 --- a/serde2/src/json/value.rs +++ b/serde2/src/json/value.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; use std::fmt; -use std::old_io; +use std::io; use std::str; use ser::{self, Serializer}; @@ -51,9 +51,16 @@ struct WriterFormatter<'a, 'b: 'a> { inner: &'a mut fmt::Formatter<'b>, } -impl<'a, 'b> old_io::Writer for WriterFormatter<'a, 'b> { - fn write_all(&mut self, buf: &[u8]) -> old_io::IoResult<()> { - self.inner.write_str(str::from_utf8(buf).unwrap()).map_err(|_| old_io::IoError::last_error()) +impl<'a, 'b> io::Write for WriterFormatter<'a, 'b> { + fn write(&mut self, buf: &[u8]) -> io::Result { + match self.inner.write_str(str::from_utf8(buf).unwrap()) { + Ok(_) => Ok(buf.len()), + Err(_) => Err(io::Error::last_os_error()), + } + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) } } diff --git a/serde2/src/lib.rs b/serde2/src/lib.rs index 59db3601..8e4a2887 100644 --- a/serde2/src/lib.rs +++ b/serde2/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(core, io, std_misc, unicode)] +#![feature(core, hash, io, std_misc, unicode)] extern crate unicode; diff --git a/serde2/src/ser.rs b/serde2/src/ser.rs index 4c4ed8be..3d198909 100644 --- a/serde2/src/ser.rs +++ b/serde2/src/ser.rs @@ -19,9 +19,8 @@ pub trait Serializer { type Value; type Error; - fn visit< - T: Serialize, - >(&mut self, value: &T) -> Result; + fn visit(&mut self, value: &T) -> Result + where T: Serialize; } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/json/ser.rs b/src/json/ser.rs index 08304c51..fa612b74 100644 --- a/src/json/ser.rs +++ b/src/json/ser.rs @@ -4,92 +4,8 @@ use std::num::{Float, FpCategory}; use std::io; use std::string::FromUtf8Error; -use ser::Serialize; use ser; -fn escape_bytes(wr: &mut W, bytes: &[u8]) -> io::Result<()> { - try!(wr.write(b"\"")); - - let mut start = 0; - - for (i, byte) in bytes.iter().enumerate() { - let escaped = match *byte { - b'"' => b"\\\"", - b'\\' => b"\\\\", - b'\x08' => b"\\b", - b'\x0c' => b"\\f", - b'\n' => b"\\n", - b'\r' => b"\\r", - b'\t' => b"\\t", - _ => { continue; } - }; - - if start < i { - try!(wr.write(&bytes[start..i])); - } - - try!(wr.write(escaped)); - - start = i + 1; - } - - if start != bytes.len() { - try!(wr.write_all(&bytes[start..])); - } - - wr.write_all(b"\"") -} - -pub fn escape_str(wr: &mut W, v: &str) -> io::Result<()> { - escape_bytes(wr, v.as_bytes()) -} - -fn escape_char(wr: &mut W, v: char) -> io::Result<()> { - let buf = &mut [0; 4]; - v.encode_utf8(buf); - escape_bytes(wr, buf) -} - -fn fmt_f32_or_null(wr: &mut W, v: f32) -> io::Result<()> { - match v.classify() { - FpCategory::Nan | FpCategory::Infinite => write!(wr, "null"), - _ => write!(wr, "{}", f32::to_str_digits(v, 6)), - } -} - -fn fmt_f64_or_null(wr: &mut W, v: f64) -> io::Result<()> { - match v.classify() { - FpCategory::Nan | FpCategory::Infinite => write!(wr, "null"), - _ => write!(wr, "{}", f64::to_str_digits(v, 6)), - } -} - -fn spaces(wr: &mut W, mut n: usize) -> io::Result<()> { - const LEN: usize = 16; - const BUF: &'static [u8; LEN] = &[b' '; LEN]; - - while n >= LEN { - try!(wr.write_all(BUF)); - n -= LEN; - } - - if n > 0 { - wr.write_all(&BUF[..n]) - } else { - Ok(()) - } -} - -/* -#[derive(Debug)] -enum SerializerState { - ValueState, - TupleState, - StructState, - EnumState, -} -*/ - /// A structure for implementing serialization to JSON. pub struct Serializer { wr: W, @@ -119,8 +35,8 @@ impl ser::Serializer for Serializer { } #[inline] - fn serialize_bool(&mut self, v: bool) -> io::Result<()> { - if v { + fn serialize_bool(&mut self, value: bool) -> io::Result<()> { + if value { self.wr.write_all(b"true") } else { self.wr.write_all(b"false") @@ -128,73 +44,73 @@ impl ser::Serializer for Serializer { } #[inline] - fn serialize_isize(&mut self, v: isize) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_isize(&mut self, value: isize) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_i8(&mut self, v: i8) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_i8(&mut self, value: i8) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_i16(&mut self, v: i16) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_i16(&mut self, value: i16) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_i32(&mut self, v: i32) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_i32(&mut self, value: i32) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_i64(&mut self, v: i64) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_i64(&mut self, value: i64) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_usize(&mut self, v: usize) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_usize(&mut self, value: usize) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_u8(&mut self, v: u8) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_u8(&mut self, value: u8) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_u16(&mut self, v: u16) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_u16(&mut self, value: u16) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_u32(&mut self, v: u32) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_u32(&mut self, value: u32) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_u64(&mut self, v: u64) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_u64(&mut self, value: u64) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_f32(&mut self, v: f32) -> io::Result<()> { - fmt_f32_or_null(&mut self.wr, v) + fn serialize_f32(&mut self, value: f32) -> io::Result<()> { + fmt_f32_or_null(&mut self.wr, value) } #[inline] - fn serialize_f64(&mut self, v: f64) -> io::Result<()> { - fmt_f64_or_null(&mut self.wr, v) + fn serialize_f64(&mut self, value: f64) -> io::Result<()> { + fmt_f64_or_null(&mut self.wr, value) } #[inline] - fn serialize_char(&mut self, v: char) -> io::Result<()> { - escape_char(&mut self.wr, v) + fn serialize_char(&mut self, value: char) -> io::Result<()> { + escape_char(&mut self.wr, value) } #[inline] - fn serialize_str(&mut self, v: &str) -> io::Result<()> { - escape_str(&mut self.wr, v) + fn serialize_str(&mut self, value: &str) -> io::Result<()> { + escape_str(&mut self.wr, value) } #[inline] @@ -205,7 +121,7 @@ impl ser::Serializer for Serializer { #[inline] fn serialize_tuple_elt< - T: Serialize, io::Error> + T: ser::Serialize, io::Error> >(&mut self, value: &T) -> io::Result<()> { if self.first { self.first = false; @@ -228,8 +144,10 @@ impl ser::Serializer for Serializer { #[inline] fn serialize_struct_elt< - T: Serialize, io::Error> + T: ser::Serialize, io::Error> >(&mut self, name: &str, value: &T) -> io::Result<()> { + use ser::Serialize; + if self.first { self.first = false; } else { @@ -255,7 +173,7 @@ impl ser::Serializer for Serializer { #[inline] fn serialize_enum_elt< - T: Serialize, io::Error> + T: ser::Serialize, io::Error> >(&mut self, value: &T) -> io::Result<()> { if self.first { self.first = false; @@ -272,7 +190,7 @@ impl ser::Serializer for Serializer { #[inline] fn serialize_option< - T: Serialize, io::Error> + T: ser::Serialize, io::Error> >(&mut self, v: &Option) -> io::Result<()> { match *v { Some(ref v) => { @@ -286,7 +204,7 @@ impl ser::Serializer for Serializer { #[inline] fn serialize_seq< - T: Serialize, io::Error>, + T: ser::Serialize, io::Error>, Iter: Iterator >(&mut self, iter: Iter) -> io::Result<()> { try!(write!(&mut self.wr, "[")); @@ -305,8 +223,8 @@ impl ser::Serializer for Serializer { #[inline] fn serialize_map< - K: Serialize, io::Error>, - V: Serialize, io::Error>, + K: ser::Serialize, io::Error>, + V: ser::Serialize, io::Error>, Iter: Iterator >(&mut self, iter: Iter) -> io::Result<()> { try!(write!(&mut self.wr, "{{")); @@ -391,73 +309,73 @@ impl ser::Serializer for PrettySerializer { } #[inline] - fn serialize_isize(&mut self, v: isize) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_isize(&mut self, value: isize) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_i8(&mut self, v: i8) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_i8(&mut self, value: i8) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_i16(&mut self, v: i16) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_i16(&mut self, value: i16) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_i32(&mut self, v: i32) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_i32(&mut self, value: i32) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_i64(&mut self, v: i64) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_i64(&mut self, value: i64) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_usize(&mut self, v: usize) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_usize(&mut self, value: usize) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_u8(&mut self, v: u8) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_u8(&mut self, value: u8) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_u16(&mut self, v: u16) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_u16(&mut self, value: u16) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_u32(&mut self, v: u32) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_u32(&mut self, value: u32) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_u64(&mut self, v: u64) -> io::Result<()> { - write!(&mut self.wr, "{}", v) + fn serialize_u64(&mut self, value: u64) -> io::Result<()> { + write!(&mut self.wr, "{}", value) } #[inline] - fn serialize_f32(&mut self, v: f32) -> io::Result<()> { - fmt_f32_or_null(&mut self.wr, v) + fn serialize_f32(&mut self, value: f32) -> io::Result<()> { + fmt_f32_or_null(&mut self.wr, value) } #[inline] - fn serialize_f64(&mut self, v: f64) -> io::Result<()> { - fmt_f64_or_null(&mut self.wr, v) + fn serialize_f64(&mut self, value: f64) -> io::Result<()> { + fmt_f64_or_null(&mut self.wr, value) } #[inline] - fn serialize_char(&mut self, v: char) -> io::Result<()> { - escape_char(&mut self.wr, v) + fn serialize_char(&mut self, value: char) -> io::Result<()> { + escape_char(&mut self.wr, value) } #[inline] - fn serialize_str(&mut self, v: &str) -> io::Result<()> { - escape_str(&mut self.wr, v) + fn serialize_str(&mut self, value: &str) -> io::Result<()> { + escape_str(&mut self.wr, value) } #[inline] @@ -468,7 +386,7 @@ impl ser::Serializer for PrettySerializer { #[inline] fn serialize_tuple_elt< - T: Serialize, io::Error> + T: ser::Serialize, io::Error> >(&mut self, value: &T) -> io::Result<()> { try!(self.serialize_sep()); value.serialize(self) @@ -487,7 +405,7 @@ impl ser::Serializer for PrettySerializer { #[inline] fn serialize_struct_elt< - T: Serialize, io::Error> + T: ser::Serialize, io::Error> >(&mut self, name: &str, value: &T) -> io::Result<()> { try!(self.serialize_sep()); try!(self.serialize_str(name)); @@ -512,7 +430,7 @@ impl ser::Serializer for PrettySerializer { #[inline] fn serialize_enum_elt< - T: Serialize, io::Error> + T: ser::Serialize, io::Error> >(&mut self, value: &T) -> io::Result<()> { try!(self.serialize_sep()); value.serialize(self) @@ -526,7 +444,7 @@ impl ser::Serializer for PrettySerializer { #[inline] fn serialize_option< - T: Serialize, io::Error> + T: ser::Serialize, io::Error> >(&mut self, v: &Option) -> io::Result<()> { match *v { Some(ref v) => { @@ -540,7 +458,7 @@ impl ser::Serializer for PrettySerializer { #[inline] fn serialize_seq< - T: Serialize, io::Error>, + T: ser::Serialize, io::Error>, Iter: Iterator >(&mut self, iter: Iter) -> io::Result<()> { try!(self.wr.write_all(b"[")); @@ -556,8 +474,8 @@ impl ser::Serializer for PrettySerializer { #[inline] fn serialize_map< - K: Serialize, io::Error>, - V: Serialize, io::Error>, + K: ser::Serialize, io::Error>, + V: ser::Serialize, io::Error>, Iter: Iterator >(&mut self, iter: Iter) -> io::Result<()> { try!(self.wr.write_all(b"{")); @@ -574,12 +492,95 @@ impl ser::Serializer for PrettySerializer { } } +fn escape_bytes(wr: &mut W, bytes: &[u8]) -> io::Result<()> + where W: io::Write +{ + try!(wr.write_all(b"\"")); + + let mut start = 0; + + for (i, byte) in bytes.iter().enumerate() { + let escaped = match *byte { + b'"' => b"\\\"", + b'\\' => b"\\\\", + b'\x08' => b"\\b", + b'\x0c' => b"\\f", + b'\n' => b"\\n", + b'\r' => b"\\r", + b'\t' => b"\\t", + _ => { continue; } + }; + + if start < i { + try!(wr.write_all(&bytes[start..i])); + } + + try!(wr.write_all(escaped)); + + start = i + 1; + } + + if start != bytes.len() { + try!(wr.write_all(&bytes[start..])); + } + + wr.write_all(b"\"") +} + +pub fn escape_str(wr: &mut W, value: &str) -> io::Result<()> + where W: io::Write +{ + escape_bytes(wr, value.as_bytes()) +} + +fn escape_char(wr: &mut W, value: char) -> io::Result<()> + where W: io::Write +{ + let buf = &mut [0; 4]; + value.encode_utf8(buf); + escape_bytes(wr, buf) +} + +fn fmt_f32_or_null(wr: &mut W, value: f32) -> io::Result<()> + where W: io::Write +{ + match value.classify() { + FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"), + _ => wr.write_all(f32::to_str_digits(value, 6).as_bytes()), + } +} + +fn fmt_f64_or_null(wr: &mut W, value: f64) -> io::Result<()> + where W: io::Write +{ + match value.classify() { + FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"), + _ => wr.write_all(f64::to_str_digits(value, 6).as_bytes()), + } +} + +fn spaces(wr: &mut W, mut n: usize) -> io::Result<()> { + const LEN: usize = 16; + const BUF: &'static [u8; LEN] = &[b' '; LEN]; + + while n >= LEN { + try!(wr.write_all(BUF)); + n -= LEN; + } + + if n > 0 { + wr.write_all(&BUF[..n]) + } else { + Ok(()) + } +} + /// Encode the specified struct into a json `[u8]` writer. #[inline] -pub fn to_writer< - W: io::Write, - T: Serialize, io::Error> ->(writer: W, value: &T) -> io::Result { +pub fn to_writer(writer: W, value: &T) -> io::Result + where W: io::Write, + T: ser::Serialize, io::Error> +{ let mut serializer = Serializer::new(writer); try!(value.serialize(&mut serializer)); Ok(serializer.unwrap()) @@ -587,9 +588,9 @@ pub fn to_writer< /// Encode the specified struct into a json `[u8]` buffer. #[inline] -pub fn to_vec< - T: Serialize>, io::Error> ->(value: &T) -> Vec { +pub fn to_vec(value: &T) -> Vec + where T: ser::Serialize>, io::Error> +{ // We are writing to a Vec, which doesn't fail. So we can ignore // the error. let writer = Vec::with_capacity(128); @@ -598,18 +599,18 @@ pub fn to_vec< /// Encode the specified struct into a json `String` buffer. #[inline] -pub fn to_string< - T: Serialize>, io::Error> ->(value: &T) -> Result { - let buf = to_vec(value); - String::from_utf8(buf) +pub fn to_string(value: &T) -> Result + where T: ser::Serialize>, 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: Serialize, io::Error> + T: ser::Serialize, io::Error> >(writer: W, value: &T) -> io::Result { let mut serializer = PrettySerializer::new(writer); try!(value.serialize(&mut serializer)); @@ -618,7 +619,7 @@ pub fn to_pretty_writer< /// Encode the specified struct into a json `[u8]` buffer. pub fn to_pretty_vec< - T: Serialize>, io::Error> + T: ser::Serialize>, io::Error> >(value: &T) -> Vec { // We are writing to a Vec, which doesn't fail. So we can ignore // the error. @@ -628,7 +629,7 @@ pub fn to_pretty_vec< /// Encode the specified struct into a json `String` buffer. pub fn to_pretty_string< - T: Serialize>, io::Error> + T: ser::Serialize>, io::Error> >(value: &T) -> Result { let buf = to_pretty_vec(value); String::from_utf8(buf)