Compare commits

..

1 Commits

Author SHA1 Message Date
Jeffrey Griffin
d34b8026d1 require serde/alloc but not serde/std 2019-02-23 16:04:36 -08:00
36 changed files with 220 additions and 287 deletions

View File

@ -4,6 +4,8 @@ matrix:
include:
- rust: nightly
script:
- cargo build
- cargo build --manifest-path tests/deps/Cargo.toml
- cargo test
- cargo test --features preserve_order
- cargo test --features arbitrary_precision
@ -23,7 +25,7 @@ matrix:
- rust: nightly
name: Clippy
script:
- rustup component add clippy || travis_terminate 0
- rustup component add clippy-preview || travis_terminate 0
- cargo clippy
script:

View File

@ -1,12 +1,12 @@
[package]
name = "serde_json"
version = "1.0.40" # remember to update html_root_url
version = "1.0.38" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT OR Apache-2.0"
license = "MIT/Apache-2.0"
description = "A JSON serialization file format"
repository = "https://github.com/serde-rs/json"
documentation = "http://docs.serde.rs/serde_json/"
keywords = ["json", "serde", "serialization", "no-std"]
keywords = ["json", "serde", "serialization"]
categories = ["encoding"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
@ -18,16 +18,14 @@ appveyor = { repository = "serde-rs/json" }
[dependencies]
serde = { version = "1.0.60", default-features = false, features = ["alloc"] }
indexmap = { version = "1.0", optional = true }
itoa = { version = "0.4.3", default-features = false }
ryu = "1.0"
itoa = "0.4.3"
ryu = "0.2"
[dev-dependencies]
automod = "0.1"
select-rustc = "0.1"
serde_bytes = "0.11"
compiletest_rs = { version = "0.3", features = ["stable"] }
serde_bytes = "0.10"
serde_derive = "1.0"
serde_stacker = "0.1"
trybuild = "1.0"
[package.metadata.docs.rs]
features = ["raw_value", "unbounded_depth"]
@ -39,14 +37,12 @@ features = ["raw_value"]
### FEATURES #################################################################
[features]
default = ["std"]
std = []
default = []
# Use a different representation for the map type of serde_json::Value.
# This allows data to be read into a Value and written back to a JSON string
# while preserving the order of map keys in the input.
preserve_order = ["indexmap", "std"]
preserve_order = ["indexmap"]
# Use an arbitrary precision number representation for serde_json::Number. This
# allows JSON numbers of arbitrary size/precision to be read into a Number and

View File

@ -199,7 +199,8 @@ when we write `p.phones[0]`, then `p.phones` is guaranteed to be a
## Constructing JSON values
Serde JSON provides a [`json!` macro][macro] to build `serde_json::Value`
objects with very natural JSON syntax.
objects with very natural JSON syntax. In order to use this macro,
`serde_json` needs to be imported with the `#[macro_use]` attribute.
<a href="https://play.rust-lang.org/?edition=2018&gist=6ccafad431d72b62e77cc34c8e879b24" target="_blank">
<img align="right" width="50" src="https://raw.githubusercontent.com/serde-rs/serde-rs.github.io/master/img/run.png">
@ -326,6 +327,23 @@ Serde without a standard library, please see the [`serde-json-core`] crate.
[`serde-json-core`]: https://japaric.github.io/serde-json-core/serde_json_core/
## License
Serde JSON is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in Serde JSON by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.
[value]: https://docs.serde.rs/serde_json/value/enum.Value.html
[from_str]: https://docs.serde.rs/serde_json/de/fn.from_str.html
[from_slice]: https://docs.serde.rs/serde_json/de/fn.from_slice.html
@ -334,20 +352,3 @@ Serde without a standard library, please see the [`serde-json-core`] crate.
[to_vec]: https://docs.serde.rs/serde_json/ser/fn.to_vec.html
[to_writer]: https://docs.serde.rs/serde_json/ser/fn.to_writer.html
[macro]: https://docs.serde.rs/serde_json/macro.json.html
<br>
#### License
<sup>
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
</sup>
<br>
<sub>
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.
</sub>

View File

@ -27,6 +27,7 @@ for:
- APPVEYOR_RUST_CHANNEL: nightly
test_script:
- cargo build
- cargo build --manifest-path tests/deps/Cargo.toml
- cargo test
- cargo test --features preserve_order
- cargo test --features arbitrary_precision

View File

@ -1,13 +1,10 @@
//! Deserialize JSON data to a Rust data structure.
use alloc::string::String;
use alloc::vec::Vec;
use core::marker::PhantomData;
use core::result;
use core::str::FromStr;
use core::{i32, u64};
#[cfg(feature = "std")]
use std::io;
use std::marker::PhantomData;
use std::result;
use std::str::FromStr;
use std::{i32, u64};
use serde::de::{self, Expected, Unexpected};
@ -15,9 +12,7 @@ use super::error::{Error, ErrorCode, Result};
use read::{self, Reference};
#[cfg(feature = "std")]
pub use read::IoRead;
pub use read::{Read, SliceRead, StrRead};
pub use read::{IoRead, Read, SliceRead, StrRead};
use number::Number;
#[cfg(feature = "arbitrary_precision")]
@ -68,7 +63,6 @@ where
}
}
#[cfg(feature = "std")]
impl<R> Deserializer<read::IoRead<R>>
where
R: io::Read,
@ -386,14 +380,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
fn parse_integer(&mut self, positive: bool) -> Result<ParserNumber> {
let next = match try!(self.next_char()) {
Some(b) => b,
None => {
return Err(self.error(ErrorCode::EofWhileParsingValue));
}
};
match next {
match try!(self.next_char_or_null()) {
b'0' => {
// There can be only one leading '0'.
match try!(self.peek_or_null()) {
@ -509,10 +496,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
if !at_least_one_digit {
match try!(self.peek()) {
Some(_) => return Err(self.peek_error(ErrorCode::InvalidNumber)),
None => return Err(self.peek_error(ErrorCode::EofWhileParsingValue)),
}
return Err(self.peek_error(ErrorCode::InvalidNumber));
}
match try!(self.peek_or_null()) {
@ -541,15 +525,8 @@ impl<'de, R: Read<'de>> Deserializer<R> {
_ => true,
};
let next = match try!(self.next_char()) {
Some(b) => b,
None => {
return Err(self.error(ErrorCode::EofWhileParsingValue));
}
};
// Make sure a digit follows the exponent place.
let mut exp = match next {
let mut exp = match try!(self.next_char_or_null()) {
c @ b'0'...b'9' => (c - b'0') as i32,
_ => {
return Err(self.error(ErrorCode::InvalidNumber));
@ -646,19 +623,19 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
#[cfg(feature = "arbitrary_precision")]
fn scan_or_eof(&mut self, buf: &mut String) -> Result<u8> {
fn scan_or_null(&mut self, buf: &mut String) -> Result<u8> {
match try!(self.next_char()) {
Some(b) => {
buf.push(b as char);
Ok(b)
}
None => Err(self.error(ErrorCode::EofWhileParsingValue))
None => Ok(b'\x00'),
}
}
#[cfg(feature = "arbitrary_precision")]
fn scan_integer(&mut self, buf: &mut String) -> Result<()> {
match try!(self.scan_or_eof(buf)) {
match try!(self.scan_or_null(buf)) {
b'0' => {
// There can be only one leading '0'.
match try!(self.peek_or_null()) {
@ -703,10 +680,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
if !at_least_one_digit {
match try!(self.peek()) {
Some(_) => return Err(self.peek_error(ErrorCode::InvalidNumber)),
None => return Err(self.peek_error(ErrorCode::EofWhileParsingValue)),
}
return Err(self.peek_error(ErrorCode::InvalidNumber));
}
match try!(self.peek_or_null()) {
@ -732,7 +706,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
// Make sure a digit follows the exponent place.
match try!(self.scan_or_eof(buf)) {
match try!(self.scan_or_null(buf)) {
b'0'...b'9' => {}
_ => {
return Err(self.error(ErrorCode::InvalidNumber));
@ -2205,6 +2179,7 @@ where
/// # Example
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// use serde::Deserialize;
///
/// use std::error::Error;
@ -2247,7 +2222,6 @@ where
/// is wrong with the data, for example required struct fields are missing from
/// the JSON map or some number is too big to fit in the expected primitive
/// type.
#[cfg(feature = "std")]
pub fn from_reader<R, T>(rdr: R) -> Result<T>
where
R: io::Read,
@ -2261,6 +2235,7 @@ where
/// # Example
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// use serde::Deserialize;
///
/// #[derive(Deserialize, Debug)]
@ -2303,6 +2278,7 @@ where
/// # Example
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// use serde::Deserialize;
///
/// #[derive(Deserialize, Debug)]

View File

@ -1,16 +1,10 @@
//! When serializing or deserializing JSON goes wrong.
use alloc::boxed::Box;
use alloc::string::{String, ToString};
use core::fmt::{self, Debug, Display};
use core::result;
use core::str::FromStr;
#[cfg(feature = "std")]
use std::error::{Error as StdError};
#[cfg(not(feature = "std"))]
use serde::ser::StdError;
#[cfg(feature = "std")]
use std::error;
use std::fmt::{self, Debug, Display};
use std::io;
use std::str::FromStr;
use std::result;
use serde::de;
use serde::ser;
@ -56,7 +50,6 @@ impl Error {
pub fn classify(&self) -> Category {
match self.err.code {
ErrorCode::Message(_) => Category::Data,
#[cfg(feature = "std")]
ErrorCode::Io(_) => Category::Io,
ErrorCode::EofWhileParsingList
| ErrorCode::EofWhileParsingObject
@ -138,7 +131,6 @@ pub enum Category {
}
#[cfg_attr(feature = "cargo-clippy", allow(fallible_impl_from))]
#[cfg(feature = "std")]
impl From<Error> for io::Error {
/// Convert a `serde_json::Error` into an `io::Error`.
///
@ -193,7 +185,6 @@ pub enum ErrorCode {
Message(Box<str>),
/// Some IO error occurred while serializing or deserializing.
#[cfg(feature = "std")]
Io(io::Error),
/// EOF while parsing a list.
@ -282,7 +273,6 @@ impl Error {
// Update `eager_json` crate when this function changes.
#[doc(hidden)]
#[cold]
#[cfg(feature = "std")]
pub fn io(error: io::Error) -> Self {
Error {
err: Box::new(ErrorImpl {
@ -312,7 +302,6 @@ impl Display for ErrorCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ErrorCode::Message(ref msg) => f.write_str(msg),
#[cfg(feature = "std")]
ErrorCode::Io(ref err) => Display::fmt(err, f),
ErrorCode::EofWhileParsingList => f.write_str("EOF while parsing a list"),
ErrorCode::EofWhileParsingObject => f.write_str("EOF while parsing an object"),
@ -344,11 +333,10 @@ impl Display for ErrorCode {
}
}
impl StdError for Error {
#[cfg(feature = "std")]
impl error::Error for Error {
fn description(&self) -> &str {
match self.err.code {
ErrorCode::Io(ref err) => StdError::description(err),
ErrorCode::Io(ref err) => error::Error::description(err),
_ => {
// If you want a better message, use Display::fmt or to_string().
"JSON error"
@ -356,8 +344,7 @@ impl StdError for Error {
}
}
#[cfg(feature = "std")]
fn cause(&self) -> Option<&StdError> {
fn cause(&self) -> Option<&error::Error> {
match self.err.code {
ErrorCode::Io(ref err) => Some(err),
_ => None,

View File

@ -119,6 +119,7 @@
//! largely automatically.
//!
//! ```edition2018
//! # use serde_derive::{Deserialize, Serialize};
//! use serde::{Deserialize, Serialize};
//! use serde_json::Result;
//!
@ -178,7 +179,8 @@
//! # Constructing JSON values
//!
//! Serde JSON provides a [`json!` macro][macro] to build `serde_json::Value`
//! objects with very natural JSON syntax.
//! objects with very natural JSON syntax. In order to use this macro,
//! `serde_json` needs to be imported with the `#[macro_use]` attribute.
//!
//! ```edition2018
//! use serde_json::json;
@ -241,6 +243,7 @@
//! such as a File or a TCP stream.
//!
//! ```edition2018
//! # use serde_derive::{Deserialize, Serialize};
//! use serde::{Deserialize, Serialize};
//! use serde_json::Result;
//!
@ -291,8 +294,7 @@
//! [macro]: https://docs.serde.rs/serde_json/macro.json.html
//! [`serde-json-core`]: https://japaric.github.io/serde-json-core/serde_json_core/
#![doc(html_root_url = "https://docs.rs/serde_json/1.0.40")]
#![allow(unknown_lints, bare_trait_objects, ellipsis_inclusive_range_patterns)]
#![doc(html_root_url = "https://docs.rs/serde_json/1.0.38")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy lints
@ -305,8 +307,6 @@
cast_possible_wrap,
cast_precision_loss,
cast_sign_loss,
// correctly used
integer_division,
// things are often more readable this way
cast_lossless,
module_name_repetitions,
@ -315,20 +315,10 @@
use_self,
zero_prefixed_literal,
// we support older compilers
checked_conversions,
redundant_field_names,
))]
#![deny(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std as alloc;
#[cfg(feature = "std")]
extern crate core;
#[macro_use]
extern crate serde;
#[cfg(feature = "preserve_order")]
@ -336,15 +326,11 @@ extern crate indexmap;
extern crate itoa;
extern crate ryu;
#[cfg(feature = "std")]
#[doc(inline)]
pub use self::de::{from_reader};
#[doc(inline)]
pub use self::de::{from_slice, from_str, Deserializer, StreamDeserializer};
pub use self::de::{from_reader, from_slice, from_str, Deserializer, StreamDeserializer};
#[doc(inline)]
pub use self::error::{Error, Result};
#[doc(inline)]
#[cfg(feature = "std")]
pub use self::ser::{
to_string, to_string_pretty, to_vec, to_vec_pretty, to_writer, to_writer_pretty, Serializer,
};
@ -356,8 +342,8 @@ pub use self::value::{from_value, to_value, Map, Number, Value};
macro_rules! try {
($e:expr) => {
match $e {
::core::result::Result::Ok(val) => val,
::core::result::Result::Err(err) => return ::core::result::Result::Err(err),
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(err) => return ::std::result::Result::Err(err),
}
};
}
@ -368,11 +354,9 @@ mod macros;
pub mod de;
pub mod error;
pub mod map;
#[cfg(feature = "std")]
pub mod ser;
pub mod value;
#[cfg(feature = "std")]
mod iter;
mod number;
mod read;

View File

@ -7,16 +7,15 @@
//! [`IndexMap`]: https://docs.rs/indexmap/*/indexmap/map/struct.IndexMap.html
use serde::{de, ser};
use alloc::string::String;
use core::borrow::Borrow;
use core::fmt::{self, Debug};
use core::hash::Hash;
use core::iter::FromIterator;
use core::ops;
use std::borrow::Borrow;
use std::fmt::{self, Debug};
use std::hash::Hash;
use std::iter::FromIterator;
use std::ops;
use value::Value;
#[cfg(not(feature = "preserve_order"))]
use alloc::collections::{btree_map, BTreeMap};
use std::collections::{btree_map, BTreeMap};
#[cfg(feature = "preserve_order")]
use indexmap::{self, IndexMap};
@ -139,7 +138,7 @@ impl Map<String, Value> {
#[cfg(feature = "preserve_order")]
use indexmap::map::Entry as EntryImpl;
#[cfg(not(feature = "preserve_order"))]
use alloc::collections::btree_map::Entry as EntryImpl;
use std::collections::btree_map::Entry as EntryImpl;
match self.map.entry(key.into()) {
EntryImpl::Vacant(vacant) => Entry::Vacant(VacantEntry { vacant: vacant }),

View File

@ -1,7 +1,7 @@
use error::Error;
use serde::de::{self, Unexpected, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use core::fmt::{self, Debug, Display};
use std::fmt::{self, Debug, Display};
#[cfg(feature = "arbitrary_precision")]
use itoa;
@ -237,7 +237,7 @@ impl Number {
}
#[cfg(feature = "arbitrary_precision")]
{
ryu::Buffer::new().format_finite(f).to_owned()
ryu::Buffer::new().format(f).to_owned()
}
};
Some(Number { n: n })
@ -473,7 +473,7 @@ macro_rules! deserialize_any {
} else if let Some(i) = self.as_i64() {
return visitor.visit_i64(i);
} else if let Some(f) = self.as_f64() {
if ryu::Buffer::new().format_finite(f) == self.n || f.to_string() == self.n {
if f.to_string() == self.n {
return visitor.visit_f64(f);
}
}

View File

@ -20,19 +20,10 @@ use error::Error;
/// When serializing, a value of this type will retain its original formatting
/// and will not be minified or pretty-printed.
///
/// # Note
///
/// `RawValue` is only available if serde\_json is built with the `"raw_value"`
/// feature.
///
/// ```toml
/// [dependencies]
/// serde_json = { version = "1.0", features = ["raw_value"] }
/// ```
///
/// # Example
///
/// ```edition2018
/// # use serde_derive::{Deserialize, Serialize};
/// use serde::{Deserialize, Serialize};
/// use serde_json::{Result, value::RawValue};
///
@ -79,7 +70,7 @@ use error::Error;
/// The typical usage of `RawValue` will be in the borrowed form:
///
/// ```edition2018
/// # use serde::Deserialize;
/// # use serde_derive::Deserialize;
/// # use serde_json::value::RawValue;
/// #
/// #[derive(Deserialize)]
@ -102,7 +93,7 @@ use error::Error;
/// [`serde_json::from_reader`]: ../fn.from_reader.html
///
/// ```edition2018
/// # use serde::Deserialize;
/// # use serde_derive::Deserialize;
/// # use serde_json::value::RawValue;
/// #
/// #[derive(Deserialize)]
@ -110,6 +101,16 @@ use error::Error;
/// raw_value: Box<RawValue>,
/// }
/// ```
///
/// # Note
///
/// `RawValue` is only available if serde\_json is built with the `"raw_value"`
/// feature.
///
/// ```toml
/// [dependencies]
/// serde_json = { version = "1.0", features = ["raw_value"] }
/// ```
#[repr(C)]
pub struct RawValue {
json: str,
@ -184,6 +185,7 @@ impl RawValue {
/// # Example
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// use serde::Deserialize;
/// use serde_json::{Result, value::RawValue};
///

View File

@ -1,13 +1,9 @@
use alloc::vec::Vec;
use core::ops::Deref;
use core::{char, cmp, str};
#[cfg(feature = "std")]
use std::io;
use std::ops::Deref;
use std::{char, cmp, io, str};
#[cfg(feature = "raw_value")]
use serde::de::Visitor;
#[cfg(feature = "std")]
use iter::LineColIterator;
use error::{Error, ErrorCode, Result};
@ -122,7 +118,6 @@ impl<'b, 'c, T: ?Sized + 'static> Deref for Reference<'b, 'c, T> {
}
/// JSON input source that reads from a std::io input stream.
#[cfg(feature = "std")]
pub struct IoRead<R>
where
R: io::Read,
@ -162,7 +157,6 @@ mod private {
//////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl<R> IoRead<R>
where
R: io::Read,
@ -187,10 +181,8 @@ where
}
}
#[cfg(feature = "std")]
impl<R> private::Sealed for IoRead<R> where R: io::Read {}
#[cfg(feature = "std")]
impl<R> IoRead<R>
where
R: io::Read,
@ -229,7 +221,6 @@ where
}
}
#[cfg(feature = "std")]
impl<'de, R> Read<'de> for IoRead<R>
where
R: io::Read,

View File

@ -1711,7 +1711,7 @@ pub trait Formatter {
W: io::Write,
{
let mut buffer = ryu::Buffer::new();
let s = buffer.format_finite(value);
let s = buffer.format(value);
writer.write_all(s.as_bytes())
}
@ -1722,7 +1722,7 @@ pub trait Formatter {
W: io::Write,
{
let mut buffer = ryu::Buffer::new();
let s = buffer.format_finite(value);
let s = buffer.format(value);
writer.write_all(s.as_bytes())
}

View File

@ -1,10 +1,8 @@
use alloc::borrow::{Cow, ToOwned};
use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
use core::fmt;
use core::slice;
use core::str;
use std::borrow::Cow;
use std::fmt;
use std::slice;
use std::str;
use std::vec;
use serde;
use serde::de::{

View File

@ -1,6 +1,4 @@
use alloc::borrow::Cow;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use std::borrow::Cow;
use super::Value;
use map::Map;
@ -184,7 +182,7 @@ impl<'a, T: Clone + Into<Value>> From<&'a [T]> for Value {
}
}
impl<T: Into<Value>> ::core::iter::FromIterator<T> for Value {
impl<T: Into<Value>> ::std::iter::FromIterator<T> for Value {
/// Convert an iteratable type to a `Value`
///
/// # Examples

View File

@ -1,7 +1,5 @@
use alloc::borrow::ToOwned;
use alloc::string::String;
use core::fmt;
use core::ops;
use std::fmt;
use std::ops;
use super::Value;
use map::Map;
@ -134,8 +132,6 @@ where
// Prevent users from implementing the Index trait.
mod private {
use alloc::string::String;
pub trait Sealed {}
impl Sealed for usize {}
impl Sealed for str {}

View File

@ -3,7 +3,8 @@
//! # Constructing JSON
//!
//! Serde JSON provides a [`json!` macro][macro] to build `serde_json::Value`
//! objects with very natural JSON syntax.
//! objects with very natural JSON syntax. In order to use this macro,
//! `serde_json` needs to be imported with the `#[macro_use]` attribute.
//!
//! ```edition2018
//! use serde_json::json;
@ -92,13 +93,10 @@
//! [from_slice]: https://docs.serde.rs/serde_json/de/fn.from_slice.html
//! [from_reader]: https://docs.serde.rs/serde_json/de/fn.from_reader.html
use alloc::string::String;
use alloc::vec::Vec;
use core::fmt::{self, Debug};
use core::mem;
use core::str;
#[cfg(feature = "std")]
use std::fmt::{self, Debug};
use std::io;
use std::mem;
use std::str;
use serde::de::DeserializeOwned;
use serde::ser::Serialize;
@ -193,12 +191,10 @@ impl Debug for Value {
}
}
#[cfg(feature = "std")]
struct WriterFormatter<'a, 'b: 'a> {
inner: &'a mut fmt::Formatter<'b>,
}
#[cfg(feature = "std")]
impl<'a, 'b> io::Write for WriterFormatter<'a, 'b> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
fn io_error<E>(_: E) -> io::Error {
@ -216,7 +212,6 @@ impl<'a, 'b> io::Write for WriterFormatter<'a, 'b> {
}
}
#[cfg(feature = "std")]
impl fmt::Display for Value {
/// Display a JSON value as a string.
///
@ -870,7 +865,7 @@ impl Value {
/// # Examples
///
/// ```edition2018
/// # use serde::Deserialize;
/// # use serde_derive::Deserialize;
/// use serde_json::Value;
///
/// #[derive(Deserialize)]
@ -912,6 +907,7 @@ mod ser;
/// # Example
///
/// ```edition2018
/// # use serde_derive::Serialize;
/// use serde::Serialize;
/// use serde_json::json;
///
@ -976,6 +972,7 @@ where
/// # Example
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// use serde::Deserialize;
/// use serde_json::json;
///

View File

@ -1,4 +1,3 @@
use alloc::string::String;
use super::Value;
fn eq_i64(value: &Value, other: i64) -> bool {

View File

@ -1,7 +1,3 @@
use alloc::borrow::ToOwned;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use serde::ser::Impossible;
use serde::{self, Serialize};

View File

@ -1,6 +1,18 @@
#[rustc::attr(not(nightly), ignore)]
extern crate compiletest_rs as compiletest;
#[test]
fn ui() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/*.rs");
compiletest::run_tests(&compiletest::Config {
mode: compiletest::common::Mode::Ui,
src_base: std::path::PathBuf::from("tests/ui"),
target_rustcflags: Some(String::from(
"\
--edition=2018 \
-L tests/deps/target/debug/deps \
-Z unstable-options \
--extern serde_json \
",
)),
..Default::default()
});
}

13
tests/deps/Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "serde_test_suite_deps"
version = "0.0.0"
authors = ["David Tolnay <dtolnay@gmail.com>"]
publish = false
[workspace]
[features]
arbitrary_precision = ["serde_json/arbitrary_precision"]
[dependencies]
serde_json = { path = "../.." }

3
tests/deps/src/lib.rs Normal file
View File

@ -0,0 +1,3 @@
#![feature(/*=============================================]
#![=== Serde test suite requires a nightly compiler. ===]
#![====================================================*/)]

View File

@ -1,6 +0,0 @@
extern crate automod;
extern crate serde;
extern crate serde_derive;
#[path = "regression/mod.rs"]
mod regression;

View File

@ -1,18 +0,0 @@
use serde_derive::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "type", content = "data")]
enum E {
Float(f32),
}
#[test]
fn test() {
let e = E::Float(159.1);
let v = serde_json::to_value(e).unwrap();
let e = serde_json::from_value::<E>(v).unwrap();
match e {
E::Float(f) => assert_eq!(f, 159.1),
}
}

View File

@ -1 +0,0 @@
automod::dir!("tests/regression");

View File

@ -23,7 +23,6 @@ macro_rules! test_stream {
assert_eq!($stream.byte_offset(), 0);
$test
}
#[cfg(feature = "std")]
{
let mut bytes = $data.as_bytes();
let de = Deserializer::from_reader(&mut bytes);
@ -82,36 +81,6 @@ fn test_json_stream_truncated() {
});
}
#[test]
fn test_json_stream_truncated_decimal() {
let data = "{\"x\":4.";
test_stream!(data, Value, |stream| {
assert!(stream.next().unwrap().unwrap_err().is_eof());
assert_eq!(stream.byte_offset(), 0);
});
}
#[test]
fn test_json_stream_truncated_negative() {
let data = "{\"x\":-";
test_stream!(data, Value, |stream| {
assert!(stream.next().unwrap().unwrap_err().is_eof());
assert_eq!(stream.byte_offset(), 0);
});
}
#[test]
fn test_json_stream_truncated_exponent() {
let data = "{\"x\":4e";
test_stream!(data, Value, |stream| {
assert!(stream.next().unwrap().unwrap_err().is_eof());
assert_eq!(stream.byte_offset(), 0);
});
}
#[test]
fn test_json_stream_empty() {
let data = "";

View File

@ -31,14 +31,9 @@ use serde::ser::{self, Serialize, Serializer};
use serde_bytes::{ByteBuf, Bytes};
#[cfg(feature = "std")]
use serde_json::{
from_reader, to_string, to_string_pretty, to_vec,
to_writer,
};
use serde_json::{
from_slice, from_str, from_value, to_value,
Deserializer, Number, Value,
from_reader, from_slice, from_str, from_value, to_string, to_string_pretty, to_value, to_vec,
to_writer, Deserializer, Number, Value,
};
macro_rules! treemap {
@ -77,7 +72,6 @@ struct Outer {
inner: Vec<Inner>,
}
#[cfg(feature = "std")]
fn test_encode_ok<T>(errors: &[(T, &str)])
where
T: PartialEq + Debug + ser::Serialize,
@ -94,7 +88,6 @@ where
}
}
#[cfg(feature = "std")]
fn test_pretty_encode_ok<T>(errors: &[(T, &str)])
where
T: PartialEq + Debug + ser::Serialize,
@ -112,7 +105,6 @@ where
}
#[test]
#[cfg(feature = "std")]
fn test_write_null() {
let tests = &[((), "null")];
test_encode_ok(tests);
@ -120,7 +112,6 @@ fn test_write_null() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_u64() {
let tests = &[(3u64, "3"), (u64::MAX, &u64::MAX.to_string())];
test_encode_ok(tests);
@ -128,7 +119,6 @@ fn test_write_u64() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_i64() {
let tests = &[
(3i64, "3"),
@ -141,7 +131,6 @@ fn test_write_i64() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_f64() {
let tests = &[
(3.0, "3.0"),
@ -157,7 +146,6 @@ fn test_write_f64() {
}
#[test]
#[cfg(feature = "std")]
fn test_encode_nonfinite_float_yields_null() {
let v = to_value(::std::f64::NAN).unwrap();
assert!(v.is_null());
@ -173,7 +161,6 @@ fn test_encode_nonfinite_float_yields_null() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_str() {
let tests = &[("", "\"\""), ("foo", "\"foo\"")];
test_encode_ok(tests);
@ -181,7 +168,6 @@ fn test_write_str() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_bool() {
let tests = &[(true, "true"), (false, "false")];
test_encode_ok(tests);
@ -189,7 +175,6 @@ fn test_write_bool() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_char() {
let tests = &[
('n', "\"n\""),
@ -209,7 +194,6 @@ fn test_write_char() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_list() {
test_encode_ok(&[
(vec![], "[]"),
@ -260,7 +244,6 @@ fn test_write_list() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_object() {
test_encode_ok(&[
(treemap!(), "{}"),
@ -473,7 +456,6 @@ fn test_write_object() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_tuple() {
test_encode_ok(&[((5,), "[5]")]);
@ -485,7 +467,6 @@ fn test_write_tuple() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_enum() {
test_encode_ok(&[
(Animal::Dog, "\"Dog\""),
@ -552,7 +533,6 @@ fn test_write_enum() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_option() {
test_encode_ok(&[(None, "null"), (Some("jodhpurs"), "\"jodhpurs\"")]);
@ -570,7 +550,6 @@ fn test_write_option() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_newtype_struct() {
#[derive(Serialize, PartialEq, Debug)]
struct Newtype(BTreeMap<String, i32>);
@ -758,15 +737,15 @@ fn test_parse_number_errors() {
test_parse_err::<f64>(&[
("+", "expected value at line 1 column 1"),
(".", "expected value at line 1 column 1"),
("-", "EOF while parsing a value at line 1 column 1"),
("-", "invalid number at line 1 column 1"),
("00", "invalid number at line 1 column 2"),
("0x80", "trailing characters at line 1 column 2"),
("\\0", "expected value at line 1 column 1"),
("1.", "EOF while parsing a value at line 1 column 2"),
("1.", "invalid number at line 1 column 2"),
("1.a", "invalid number at line 1 column 3"),
("1.e1", "invalid number at line 1 column 3"),
("1e", "EOF while parsing a value at line 1 column 2"),
("1e+", "EOF while parsing a value at line 1 column 3"),
("1e", "invalid number at line 1 column 2"),
("1e+", "invalid number at line 1 column 3"),
("1a", "trailing characters at line 1 column 2"),
(
"100e777777777777777777777777777",
@ -1395,7 +1374,6 @@ fn test_missing_renamed_field() {
}
#[test]
#[cfg(feature = "std")]
fn test_serialize_seq_with_no_len() {
#[derive(Clone, Debug, PartialEq)]
struct MyVec<T>(Vec<T>);
@ -1482,7 +1460,6 @@ fn test_serialize_seq_with_no_len() {
}
#[test]
#[cfg(feature = "std")]
fn test_serialize_map_with_no_len() {
#[derive(Clone, Debug, PartialEq)]
struct MyMap<K, V>(BTreeMap<K, V>);
@ -1576,7 +1553,6 @@ fn test_serialize_map_with_no_len() {
}
#[test]
#[cfg(feature = "std")]
fn test_deserialize_from_stream() {
use serde::Deserialize;
use std::net;
@ -1617,7 +1593,6 @@ fn test_deserialize_from_stream() {
}
#[test]
#[cfg(feature = "std")]
fn test_serialize_rejects_bool_keys() {
let map = treemap!(
true => 2,
@ -1629,7 +1604,6 @@ fn test_serialize_rejects_bool_keys() {
}
#[test]
#[cfg(feature = "std")]
fn test_serialize_rejects_adt_keys() {
let map = treemap!(
Some("a") => 2,
@ -1642,7 +1616,6 @@ fn test_serialize_rejects_adt_keys() {
}
#[test]
#[cfg(feature = "std")]
fn test_bytes_ser() {
let buf = vec![];
let bytes = Bytes::new(&buf);
@ -1654,8 +1627,6 @@ fn test_bytes_ser() {
}
#[test]
#[cfg(feature = "std")]
#[cfg(feature = "std")]
fn test_byte_buf_ser() {
let bytes = ByteBuf::new();
assert_eq!(to_string(&bytes).unwrap(), "[]".to_string());
@ -1807,7 +1778,6 @@ fn test_disable_recursion_limit() {
}
#[test]
#[cfg(feature = "std")]
fn test_integer_key() {
// map with integer keys
let map = treemap!(
@ -1826,7 +1796,6 @@ fn test_integer_key() {
}
#[test]
#[cfg(feature = "std")]
fn test_integer128_key() {
let map = treemap! {
100000000000000000000000000000000000000u128 => ()
@ -1837,7 +1806,6 @@ fn test_integer128_key() {
}
#[test]
#[cfg(feature = "std")]
fn test_deny_float_key() {
#[derive(Eq, PartialEq, Ord, PartialOrd)]
struct Float;
@ -1870,7 +1838,6 @@ fn test_borrowed_key() {
}
#[test]
#[cfg(feature = "std")]
fn test_effectively_string_keys() {
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Serialize, Deserialize)]
enum Enum {
@ -1897,7 +1864,6 @@ fn test_effectively_string_keys() {
}
#[test]
#[cfg(feature = "std")]
fn test_json_macro() {
// This is tricky because the <...> is not a single TT and the comma inside
// looks like an array element separator.
@ -1995,7 +1961,6 @@ impl io::Read for FailReader {
}
#[test]
#[cfg(feature = "std")]
fn test_category() {
assert!(from_str::<String>("123").unwrap_err().is_data());
@ -2036,7 +2001,6 @@ fn test_category() {
#[test]
// Clippy false positive: https://github.com/Manishearth/rust-clippy/issues/292
#[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))]
#[cfg(feature = "std")]
fn test_into_io_error() {
fn io_error<'de, T: Deserialize<'de> + Debug>(j: &'static str) -> io::Error {
from_str::<T>(j).unwrap_err().into()
@ -2073,7 +2037,6 @@ fn null_invalid_type() {
}
#[test]
#[cfg(feature = "std")]
fn test_integer128() {
let signed = &[i128::min_value(), -1, 0, 1, i128::max_value()];
let unsigned = &[0, 1, u128::max_value()];

View File

@ -5,3 +5,6 @@ error: unexpected end of macro invocation
| ^^^^^^^^^^^^^^^ missing tokens in macro arguments
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error

View File

@ -5,3 +5,6 @@ error: unexpected end of macro invocation
| ^^^^^^^^^^^^^^^^^ missing tokens in macro arguments
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error

View File

@ -4,4 +4,6 @@ error[E0425]: cannot find value `x` in this scope
4 | json!({ "a" : x });
| ^ not found in this scope
error: aborting due to previous error
For more information about this error, try `rustc --explain E0425`.

View File

@ -5,3 +5,6 @@ error: unexpected end of macro invocation
| ^^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error

View File

@ -4,4 +4,6 @@ error[E0609]: no field `s` on type `&'static str`
4 | json!({ "".s : true });
| ^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0609`.

View File

@ -3,3 +3,6 @@ error: no rules expected the token `=>`
|
4 | json!([ true => ]);
| ^^ no rules expected this token in macro call
error: aborting due to previous error

View File

@ -3,3 +3,6 @@ error: no rules expected the token `=>`
|
4 | json!({ "k": true => });
| ^^ no rules expected this token in macro call
error: aborting due to previous error

View File

@ -3,3 +3,6 @@ error: no rules expected the token `:`
|
4 | json!({ : true });
| ^ no rules expected this token in macro call
error: aborting due to previous error

View File

@ -3,3 +3,6 @@ error: no rules expected the token `,`
|
4 | json!({ "a" , "b": true });
| ^ no rules expected this token in macro call
error: aborting due to previous error

50
tests/ui/update-references.sh Executable file
View File

@ -0,0 +1,50 @@
#!/bin/bash
#
# Copyright 2015 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.
# A script to update the references for particular tests. The idea is
# that you do a run, which will generate files in the build directory
# containing the (normalized) actual output of the compiler. This
# script will then copy that output and replace the "expected output"
# files. You can then commit the changes.
#
# If you find yourself manually editing a foo.stderr file, you're
# doing it wrong.
if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then
echo "usage: $0 <build-directory> <relative-path-to-rs-files>"
echo ""
echo "For example:"
echo " $0 ../../../build/x86_64-apple-darwin/test/ui *.rs */*.rs"
fi
MYDIR=$(dirname $0)
BUILD_DIR="$1"
shift
while [[ "$1" != "" ]]; do
STDERR_NAME="${1/%.rs/.stderr}"
STDOUT_NAME="${1/%.rs/.stdout}"
shift
if [ -f $BUILD_DIR/$STDOUT_NAME ] && \
! (diff $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME >& /dev/null); then
echo updating $MYDIR/$STDOUT_NAME
cp $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME
fi
if [ -f $BUILD_DIR/$STDERR_NAME ] && \
! (diff $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME >& /dev/null); then
echo updating $MYDIR/$STDERR_NAME
cp $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME
fi
done