Reject serializing maps to JSON with non-string keys

Closes #122. This is a breaking change since it modifies the
return type of serde_json::to_vec{,pretty}, so it'll require a major
version bump of serde_json.
This commit is contained in:
Erick Tryzelaar 2015-08-13 22:29:13 -07:00
parent fc58ea7487
commit fe20852b2c
4 changed files with 205 additions and 125 deletions

View File

@ -2,6 +2,7 @@ use std::error;
use std::fmt;
use std::io;
use std::result;
use std::string::FromUtf8Error;
use serde::de;
@ -44,7 +45,6 @@ impl fmt::Debug for ErrorCode {
use std::fmt::Debug;
match *self {
//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),
@ -61,7 +61,6 @@ 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::InvalidEscape => "invalid escape".fmt(f),
ErrorCode::InvalidNumber => "invalid number".fmt(f),
ErrorCode::InvalidUnicodeCodePoint => "invalid unicode code point".fmt(f),
@ -73,7 +72,6 @@ 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::UnknownVariant => "unknown variant".fmt(f),
ErrorCode::UnrecognizedHex => "invalid \\u escape (unrecognized hex)".fmt(f),
}
@ -85,13 +83,8 @@ pub enum Error {
/// msg, line, col
SyntaxError(ErrorCode, usize, usize),
IoError(io::Error),
/*
ExpectedError(String, String),
*/
MissingFieldError(&'static str),
/*
UnknownVariantError(String),
*/
FromUtf8Error(FromUtf8Error),
}
impl error::Error for Error {
@ -99,19 +92,15 @@ impl error::Error for Error {
match *self {
Error::SyntaxError(..) => "syntax error",
Error::IoError(ref error) => error::Error::description(error),
/*
Error::ExpectedError(ref expected, _) => &expected,
*/
Error::MissingFieldError(_) => "missing field",
/*
Error::UnknownVariantError(_) => "unknown variant",
*/
Error::FromUtf8Error(ref error) => error.description(),
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
Error::IoError(ref error) => Some(error),
Error::FromUtf8Error(ref error) => Some(error),
_ => None,
}
}
@ -125,19 +114,10 @@ impl fmt::Display for Error {
write!(fmt, "{:?} at line {} column {}", code, line, col)
}
Error::IoError(ref error) => fmt::Display::fmt(error, fmt),
/*
Error::ExpectedError(ref expected, ref found) => {
Some(format!("expected {}, found {}", expected, found))
}
*/
Error::FromUtf8Error(ref error) => fmt::Display::fmt(error, fmt),
Error::MissingFieldError(ref field) => {
write!(fmt, "missing field {}", field)
}
/*
Error::UnknownVariantError(ref variant) => {
Some(format!("unknown variant {}", variant))
}
*/
}
}
}
@ -148,6 +128,12 @@ impl From<io::Error> for Error {
}
}
impl From<FromUtf8Error> for Error {
fn from(error: FromUtf8Error) -> Error {
Error::FromUtf8Error(error)
}
}
impl From<de::value::Error> for Error {
fn from(error: de::value::Error) -> Error {
match error {

View File

@ -1,8 +1,8 @@
use std::io;
use std::num::FpCategory;
use std::string::FromUtf8Error;
use serde::ser;
use super::error::{Error, ErrorCode, Result};
/// A structure for implementing serialization to JSON.
pub struct Serializer<W, F=CompactFormatter> {
@ -60,109 +60,109 @@ impl<W, F> ser::Serializer for Serializer<W, F>
where W: io::Write,
F: Formatter,
{
type Error = io::Error;
type Error = Error;
#[inline]
fn visit_bool(&mut self, value: bool) -> io::Result<()> {
fn visit_bool(&mut self, value: bool) -> Result<()> {
if value {
self.writer.write_all(b"true")
self.writer.write_all(b"true").map_err(From::from)
} else {
self.writer.write_all(b"false")
self.writer.write_all(b"false").map_err(From::from)
}
}
#[inline]
fn visit_isize(&mut self, value: isize) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
fn visit_isize(&mut self, value: isize) -> Result<()> {
write!(&mut self.writer, "{}", value).map_err(From::from)
}
#[inline]
fn visit_i8(&mut self, value: i8) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
fn visit_i8(&mut self, value: i8) -> Result<()> {
write!(&mut self.writer, "{}", value).map_err(From::from)
}
#[inline]
fn visit_i16(&mut self, value: i16) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
fn visit_i16(&mut self, value: i16) -> Result<()> {
write!(&mut self.writer, "{}", value).map_err(From::from)
}
#[inline]
fn visit_i32(&mut self, value: i32) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
fn visit_i32(&mut self, value: i32) -> Result<()> {
write!(&mut self.writer, "{}", value).map_err(From::from)
}
#[inline]
fn visit_i64(&mut self, value: i64) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
fn visit_i64(&mut self, value: i64) -> Result<()> {
write!(&mut self.writer, "{}", value).map_err(From::from)
}
#[inline]
fn visit_usize(&mut self, value: usize) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
fn visit_usize(&mut self, value: usize) -> Result<()> {
write!(&mut self.writer, "{}", value).map_err(From::from)
}
#[inline]
fn visit_u8(&mut self, value: u8) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
fn visit_u8(&mut self, value: u8) -> Result<()> {
write!(&mut self.writer, "{}", value).map_err(From::from)
}
#[inline]
fn visit_u16(&mut self, value: u16) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
fn visit_u16(&mut self, value: u16) -> Result<()> {
write!(&mut self.writer, "{}", value).map_err(From::from)
}
#[inline]
fn visit_u32(&mut self, value: u32) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
fn visit_u32(&mut self, value: u32) -> Result<()> {
write!(&mut self.writer, "{}", value).map_err(From::from)
}
#[inline]
fn visit_u64(&mut self, value: u64) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
fn visit_u64(&mut self, value: u64) -> Result<()> {
write!(&mut self.writer, "{}", value).map_err(From::from)
}
#[inline]
fn visit_f32(&mut self, value: f32) -> io::Result<()> {
fmt_f32_or_null(&mut self.writer, value)
fn visit_f32(&mut self, value: f32) -> Result<()> {
fmt_f32_or_null(&mut self.writer, value).map_err(From::from)
}
#[inline]
fn visit_f64(&mut self, value: f64) -> io::Result<()> {
fmt_f64_or_null(&mut self.writer, value)
fn visit_f64(&mut self, value: f64) -> Result<()> {
fmt_f64_or_null(&mut self.writer, value).map_err(From::from)
}
#[inline]
fn visit_char(&mut self, value: char) -> io::Result<()> {
escape_char(&mut self.writer, value)
fn visit_char(&mut self, value: char) -> Result<()> {
escape_char(&mut self.writer, value).map_err(From::from)
}
#[inline]
fn visit_str(&mut self, value: &str) -> io::Result<()> {
escape_str(&mut self.writer, value)
fn visit_str(&mut self, value: &str) -> Result<()> {
escape_str(&mut self.writer, value).map_err(From::from)
}
#[inline]
fn visit_none(&mut self) -> io::Result<()> {
fn visit_none(&mut self) -> Result<()> {
self.visit_unit()
}
#[inline]
fn visit_some<V>(&mut self, value: V) -> io::Result<()>
fn visit_some<V>(&mut self, value: V) -> Result<()>
where V: ser::Serialize
{
value.serialize(self)
}
#[inline]
fn visit_unit(&mut self) -> io::Result<()> {
self.writer.write_all(b"null")
fn visit_unit(&mut self) -> Result<()> {
self.writer.write_all(b"null").map_err(From::from)
}
/// Override `visit_newtype_struct` to serialize newtypes without an object wrapper.
#[inline]
fn visit_newtype_struct<T>(&mut self,
_name: &'static str,
value: T) -> Result<(), Self::Error>
value: T) -> Result<()>
where T: ser::Serialize,
{
value.serialize(self)
@ -172,7 +172,7 @@ impl<W, F> ser::Serializer for Serializer<W, F>
fn visit_unit_variant(&mut self,
_name: &str,
_variant_index: usize,
variant: &str) -> io::Result<()> {
variant: &str) -> Result<()> {
try!(self.formatter.open(&mut self.writer, b'{'));
try!(self.formatter.comma(&mut self.writer, true));
try!(self.visit_str(variant));
@ -186,7 +186,7 @@ impl<W, F> ser::Serializer for Serializer<W, F>
_name: &str,
_variant_index: usize,
variant: &str,
value: T) -> io::Result<()>
value: T) -> Result<()>
where T: ser::Serialize,
{
try!(self.formatter.open(&mut self.writer, b'{'));
@ -198,12 +198,12 @@ impl<W, F> ser::Serializer for Serializer<W, F>
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> io::Result<()>
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<()>
where V: ser::SeqVisitor,
{
match visitor.len() {
Some(len) if len == 0 => {
self.writer.write_all(b"[]")
self.writer.write_all(b"[]").map_err(From::from)
}
_ => {
try!(self.formatter.open(&mut self.writer, b'['));
@ -212,7 +212,7 @@ impl<W, F> ser::Serializer for Serializer<W, F>
while let Some(()) = try!(visitor.visit(self)) { }
self.formatter.close(&mut self.writer, b']')
self.formatter.close(&mut self.writer, b']').map_err(From::from)
}
}
@ -223,7 +223,7 @@ impl<W, F> ser::Serializer for Serializer<W, F>
_name: &str,
_variant_index: usize,
variant: &str,
visitor: V) -> io::Result<()>
visitor: V) -> Result<()>
where V: ser::SeqVisitor,
{
try!(self.formatter.open(&mut self.writer, b'{'));
@ -235,7 +235,7 @@ impl<W, F> ser::Serializer for Serializer<W, F>
}
#[inline]
fn visit_seq_elt<T>(&mut self, value: T) -> io::Result<()>
fn visit_seq_elt<T>(&mut self, value: T) -> Result<()>
where T: ser::Serialize,
{
try!(self.formatter.comma(&mut self.writer, self.first));
@ -247,12 +247,12 @@ impl<W, F> ser::Serializer for Serializer<W, F>
}
#[inline]
fn visit_map<V>(&mut self, mut visitor: V) -> io::Result<()>
fn visit_map<V>(&mut self, mut visitor: V) -> Result<()>
where V: ser::MapVisitor,
{
match visitor.len() {
Some(len) if len == 0 => {
self.writer.write_all(b"{}")
self.writer.write_all(b"{}").map_err(From::from)
}
_ => {
try!(self.formatter.open(&mut self.writer, b'{'));
@ -271,7 +271,7 @@ impl<W, F> ser::Serializer for Serializer<W, F>
_name: &str,
_variant_index: usize,
variant: &str,
visitor: V) -> io::Result<()>
visitor: V) -> Result<()>
where V: ser::MapVisitor,
{
try!(self.formatter.open(&mut self.writer, b'{'));
@ -284,13 +284,13 @@ impl<W, F> ser::Serializer for Serializer<W, F>
}
#[inline]
fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> io::Result<()>
fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<()>
where K: ser::Serialize,
V: ser::Serialize,
{
try!(self.formatter.comma(&mut self.writer, self.first));
try!(key.serialize(self));
try!(key.serialize(&mut MapKeySerializer { ser: self }));
try!(self.formatter.colon(&mut self.writer));
try!(value.serialize(self));
@ -305,49 +305,120 @@ impl<W, F> ser::Serializer for Serializer<W, F>
}
}
struct MapKeySerializer<'a, W: 'a, F: 'a> {
ser: &'a mut Serializer<W, F>,
}
impl<'a, W, F> ser::Serializer for MapKeySerializer<'a, W, F>
where W: io::Write,
F: Formatter,
{
type Error = Error;
#[inline]
fn visit_str(&mut self, value: &str) -> Result<()> {
self.ser.visit_str(value)
}
fn visit_bool(&mut self, _value: bool) -> Result<()> {
Err(Error::SyntaxError(ErrorCode::KeyMustBeAString, 0, 0))
}
fn visit_i64(&mut self, _value: i64) -> Result<()> {
Err(Error::SyntaxError(ErrorCode::KeyMustBeAString, 0, 0))
}
fn visit_u64(&mut self, _value: u64) -> Result<()> {
Err(Error::SyntaxError(ErrorCode::KeyMustBeAString, 0, 0))
}
fn visit_f64(&mut self, _value: f64) -> Result<()> {
Err(Error::SyntaxError(ErrorCode::KeyMustBeAString, 0, 0))
}
fn visit_unit(&mut self) -> Result<()> {
Err(Error::SyntaxError(ErrorCode::KeyMustBeAString, 0, 0))
}
fn visit_none(&mut self) -> Result<()> {
Err(Error::SyntaxError(ErrorCode::KeyMustBeAString, 0, 0))
}
fn visit_some<V>(&mut self, _value: V) -> Result<()>
where V: ser::Serialize
{
Err(Error::SyntaxError(ErrorCode::KeyMustBeAString, 0, 0))
}
fn visit_seq<V>(&mut self, _visitor: V) -> Result<()>
where V: ser::SeqVisitor,
{
Err(Error::SyntaxError(ErrorCode::KeyMustBeAString, 0, 0))
}
fn visit_seq_elt<T>(&mut self, _value: T) -> Result<()>
where T: ser::Serialize,
{
Err(Error::SyntaxError(ErrorCode::KeyMustBeAString, 0, 0))
}
fn visit_map<V>(&mut self, _visitor: V) -> Result<()>
where V: ser::MapVisitor,
{
Err(Error::SyntaxError(ErrorCode::KeyMustBeAString, 0, 0))
}
fn visit_map_elt<K, V>(&mut self, _key: K, _value: V) -> Result<()>
where K: ser::Serialize,
V: ser::Serialize,
{
Err(Error::SyntaxError(ErrorCode::KeyMustBeAString, 0, 0))
}
}
pub trait Formatter {
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
fn open<W>(&mut self, writer: &mut W, ch: u8) -> Result<()>
where W: io::Write;
fn comma<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
fn comma<W>(&mut self, writer: &mut W, first: bool) -> Result<()>
where W: io::Write;
fn colon<W>(&mut self, writer: &mut W) -> io::Result<()>
fn colon<W>(&mut self, writer: &mut W) -> Result<()>
where W: io::Write;
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
fn close<W>(&mut self, writer: &mut W, ch: u8) -> Result<()>
where W: io::Write;
}
pub struct CompactFormatter;
impl Formatter for CompactFormatter {
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
fn open<W>(&mut self, writer: &mut W, ch: u8) -> Result<()>
where W: io::Write,
{
writer.write_all(&[ch])
writer.write_all(&[ch]).map_err(From::from)
}
fn comma<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
fn comma<W>(&mut self, writer: &mut W, first: bool) -> Result<()>
where W: io::Write,
{
if first {
Ok(())
} else {
writer.write_all(b",")
writer.write_all(b",").map_err(From::from)
}
}
fn colon<W>(&mut self, writer: &mut W) -> io::Result<()>
fn colon<W>(&mut self, writer: &mut W) -> Result<()>
where W: io::Write,
{
writer.write_all(b":")
writer.write_all(b":").map_err(From::from)
}
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
fn close<W>(&mut self, writer: &mut W, ch: u8) -> Result<()>
where W: io::Write,
{
writer.write_all(&[ch])
writer.write_all(&[ch]).map_err(From::from)
}
}
@ -370,14 +441,14 @@ impl<'a> PrettyFormatter<'a> {
}
impl<'a> Formatter for PrettyFormatter<'a> {
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
fn open<W>(&mut self, writer: &mut W, ch: u8) -> Result<()>
where W: io::Write,
{
self.current_indent += 1;
writer.write_all(&[ch])
writer.write_all(&[ch]).map_err(From::from)
}
fn comma<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
fn comma<W>(&mut self, writer: &mut W, first: bool) -> Result<()>
where W: io::Write,
{
if first {
@ -389,25 +460,25 @@ impl<'a> Formatter for PrettyFormatter<'a> {
indent(writer, self.current_indent, self.indent)
}
fn colon<W>(&mut self, writer: &mut W) -> io::Result<()>
fn colon<W>(&mut self, writer: &mut W) -> Result<()>
where W: io::Write,
{
writer.write_all(b": ")
writer.write_all(b": ").map_err(From::from)
}
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
fn close<W>(&mut self, writer: &mut W, ch: u8) -> Result<()>
where W: io::Write,
{
self.current_indent -= 1;
try!(writer.write(b"\n"));
try!(indent(writer, self.current_indent, self.indent));
writer.write_all(&[ch])
writer.write_all(&[ch]).map_err(From::from)
}
}
#[inline]
pub fn escape_bytes<W>(wr: &mut W, bytes: &[u8]) -> io::Result<()>
pub fn escape_bytes<W>(wr: &mut W, bytes: &[u8]) -> Result<()>
where W: io::Write
{
try!(wr.write_all(b"\""));
@ -444,14 +515,14 @@ pub fn escape_bytes<W>(wr: &mut W, bytes: &[u8]) -> io::Result<()>
}
#[inline]
pub fn escape_str<W>(wr: &mut W, value: &str) -> io::Result<()>
pub fn escape_str<W>(wr: &mut W, value: &str) -> Result<()>
where W: io::Write
{
escape_bytes(wr, value.as_bytes())
}
#[inline]
fn escape_char<W>(wr: &mut W, value: char) -> io::Result<()>
fn escape_char<W>(wr: &mut W, value: char) -> Result<()>
where W: io::Write
{
// FIXME: this allocation is required in order to be compatible with stable
@ -459,31 +530,39 @@ fn escape_char<W>(wr: &mut W, value: char) -> io::Result<()>
escape_bytes(wr, value.to_string().as_bytes())
}
fn fmt_f32_or_null<W>(wr: &mut W, value: f32) -> io::Result<()>
fn fmt_f32_or_null<W>(wr: &mut W, value: f32) -> Result<()>
where W: io::Write
{
match value.classify() {
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
FpCategory::Nan | FpCategory::Infinite => {
try!(wr.write_all(b"null"))
}
_ => {
write!(wr, "{:?}", value)
try!(write!(wr, "{:?}", value))
}
}
Ok(())
}
fn fmt_f64_or_null<W>(wr: &mut W, value: f64) -> io::Result<()>
fn fmt_f64_or_null<W>(wr: &mut W, value: f64) -> Result<()>
where W: io::Write
{
match value.classify() {
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
FpCategory::Nan | FpCategory::Infinite => {
try!(wr.write_all(b"null"))
}
_ => {
write!(wr, "{:?}", value)
try!(write!(wr, "{:?}", value))
}
}
Ok(())
}
/// Encode the specified struct into a json `[u8]` writer.
#[inline]
pub fn to_writer<W, T>(writer: &mut W, value: &T) -> io::Result<()>
pub fn to_writer<W, T>(writer: &mut W, value: &T) -> Result<()>
where W: io::Write,
T: ser::Serialize,
{
@ -494,7 +573,7 @@ pub fn to_writer<W, T>(writer: &mut W, value: &T) -> io::Result<()>
/// Encode the specified struct into a json `[u8]` writer.
#[inline]
pub fn to_writer_pretty<W, T>(writer: &mut W, value: &T) -> io::Result<()>
pub fn to_writer_pretty<W, T>(writer: &mut W, value: &T) -> Result<()>
where W: io::Write,
T: ser::Serialize,
{
@ -505,47 +584,49 @@ pub fn to_writer_pretty<W, T>(writer: &mut W, value: &T) -> io::Result<()>
/// Encode the specified struct into a json `[u8]` buffer.
#[inline]
pub fn to_vec<T>(value: &T) -> Vec<u8>
pub fn to_vec<T>(value: &T) -> Result<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
try!(to_writer(&mut writer, value));
Ok(writer)
}
/// Encode the specified struct into a json `[u8]` buffer.
#[inline]
pub fn to_vec_pretty<T>(value: &T) -> Vec<u8>
pub fn to_vec_pretty<T>(value: &T) -> Result<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
try!(to_writer_pretty(&mut writer, value));
Ok(writer)
}
/// Encode the specified struct into a json `String` buffer.
#[inline]
pub fn to_string<T>(value: &T) -> Result<String, FromUtf8Error>
pub fn to_string<T>(value: &T) -> Result<String>
where T: ser::Serialize
{
let vec = to_vec(value);
String::from_utf8(vec)
let vec = try!(to_vec(value));
let string = try!(String::from_utf8(vec));
Ok(string)
}
/// Encode the specified struct into a json `String` buffer.
#[inline]
pub fn to_string_pretty<T>(value: &T) -> Result<String, FromUtf8Error>
pub fn to_string_pretty<T>(value: &T) -> Result<String>
where T: ser::Serialize
{
let vec = to_vec_pretty(value);
String::from_utf8(vec)
let vec = try!(to_vec_pretty(value));
let string = try!(String::from_utf8(vec));
Ok(string)
}
fn indent<W>(wr: &mut W, n: usize, s: &[u8]) -> io::Result<()>
fn indent<W>(wr: &mut W, n: usize, s: &[u8]) -> Result<()>
where W: io::Write,
{
for _ in 0 .. n {

View File

@ -1123,18 +1123,18 @@ fn bench_encoder(b: &mut Bencher) {
#[test]
fn test_serializer() {
let log = Log::new();
let json = serde_json::to_vec(&log);
let json = serde_json::to_vec(&log).unwrap();
assert_eq!(json, JSON_STR.as_bytes());
}
#[bench]
fn bench_serializer(b: &mut Bencher) {
let log = Log::new();
let json = serde_json::to_vec(&log);
let json = serde_json::to_vec(&log).unwrap();
b.bytes = json.len() as u64;
b.iter(|| {
let _ = serde_json::to_vec(&log);
serde_json::to_vec(&log).unwrap();
});
}
@ -1152,7 +1152,7 @@ fn test_serializer_vec() {
#[bench]
fn bench_serializer_vec(b: &mut Bencher) {
let log = Log::new();
let json = serde_json::to_vec(&log);
let json = serde_json::to_vec(&log).unwrap();
b.bytes = json.len() as u64;
let mut wr = Vec::with_capacity(1024);
@ -1169,7 +1169,7 @@ fn bench_serializer_vec(b: &mut Bencher) {
#[bench]
fn bench_serializer_slice(b: &mut Bencher) {
let log = Log::new();
let json = serde_json::to_vec(&log);
let json = serde_json::to_vec(&log).unwrap();
b.bytes = json.len() as u64;
let mut buf = [0; 1024];
@ -1202,7 +1202,7 @@ fn test_serializer_my_mem_writer0() {
#[bench]
fn bench_serializer_my_mem_writer0(b: &mut Bencher) {
let log = Log::new();
let json = serde_json::to_vec(&log);
let json = serde_json::to_vec(&log).unwrap();
b.bytes = json.len() as u64;
let mut wr = MyMemWriter0::with_capacity(1024);
@ -1234,7 +1234,7 @@ fn test_serializer_my_mem_writer1() {
#[bench]
fn bench_serializer_my_mem_writer1(b: &mut Bencher) {
let log = Log::new();
let json = serde_json::to_vec(&log);
let json = serde_json::to_vec(&log).unwrap();
b.bytes = json.len() as u64;
let mut wr = MyMemWriter1::with_capacity(1024);

View File

@ -1348,3 +1348,16 @@ fn test_deserialize_from_stream() {
assert_eq!(request, response);
}
#[test]
fn test_serialize_rejects_non_key_maps() {
let map = treemap!(
1 => 2,
3 => 4
);
match serde_json::to_vec(&map).unwrap_err() {
serde_json::Error::SyntaxError(serde_json::ErrorCode::KeyMustBeAString, 0, 0) => {}
_ => panic!("integers used as keys"),
}
}