Compare commits

...

26 Commits

Author SHA1 Message Date
Jeffrey Griffin
d79b0c67f6 add std feature for no-std compatibility 2019-09-21 18:01:10 -07:00
David Tolnay
efe3dc184c
Release 1.0.40 2019-06-30 11:03:42 -07:00
David Tolnay
b415671e70
Move raw_value feature note above the example code
Closes #529.
2019-06-30 11:01:41 -07:00
David Tolnay
8259b11f5f
Suppress integer_division pedantic lint 2019-06-14 23:59:40 -07:00
David Tolnay
10132f800f
Update to ryu 1.0 2019-06-11 14:43:49 -07:00
David Tolnay
607de4d8ec
Ignore old inclusive range syntax to support old compilers 2019-06-01 23:07:57 -07:00
David Tolnay
c15bec566e
Suppress a new pedantic lint 2019-06-01 23:07:07 -07:00
David Tolnay
c4fb4f3996
Ignore bare_trait_objects lint to support old compilers 2019-05-31 17:01:22 -07:00
David Tolnay
1f63f6b9fd
Smaller format for license section 2019-05-18 17:34:44 -07:00
David Tolnay
9b8a662347
Switch to SPDX 2.1 license expression 2019-05-09 15:23:34 -07:00
David Tolnay
d1423a6fec
Remove old instructions intended for compiletest 2019-05-06 16:16:41 -07:00
David Tolnay
6b15f48393
Run ui tests on nightly only
Where the nightly and other compiler stderr messages differ, nightly is
the one that makes sense to test.
2019-05-06 10:22:54 -07:00
David Tolnay
6efaa0d3d6
Remove old compiletest step from appveyor build 2019-05-06 10:07:52 -07:00
David Tolnay
8d7f731c2d
Switch ui tests to trybuild 2019-05-06 09:57:57 -07:00
David Tolnay
7c20916f53
Remove serde_derive from doc tests 2019-05-04 14:56:37 -07:00
David Tolnay
5b5f95831d
Update serde_bytes dependency to 0.11 2019-04-07 16:32:43 -07:00
David Tolnay
bb58e6c4e8
Merge pull request #525 from 17dec/eof-numbers
Return EOF on truncated numbers
2019-03-19 13:42:17 -07:00
Yorhel
69bfbfc71f Return EOF error on cut-off negative sign or exponent 2019-03-19 10:10:34 +01:00
Yorhel
367a1de69e Return EOF error on cut-off decimal number
Fixes #524
2019-03-18 14:08:13 +01:00
David Tolnay
e6b02d1b53
Use non-preview name of Clippy rustup component 2019-03-01 23:16:54 -08:00
David Tolnay
741f6dd9ea
Remove references to macro_use 2019-02-28 22:08:13 -08:00
David Tolnay
72e22e5b6d
Release 1.0.39 2019-02-28 01:08:14 -08:00
David Tolnay
82c5182bfa
Merge pull request #521 from dtolnay/f
Fix adjacently tagged f32 roundtrip regression
2019-02-28 01:07:20 -08:00
David Tolnay
d79c8e5f1e
Fix adjacently tagged f32 roundtrip regression 2019-02-28 00:57:55 -08:00
David Tolnay
6ac689b2b3
Format with rustfmt 2019-02-14 2019-02-27 22:51:08 -08:00
David Tolnay
d6ff3de39c
Simplify running update-references.sh 2019-02-17 11:12:26 -08:00
36 changed files with 288 additions and 221 deletions

View File

@ -4,8 +4,6 @@ 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
@ -25,7 +23,7 @@ matrix:
- rust: nightly
name: Clippy
script:
- rustup component add clippy-preview || travis_terminate 0
- rustup component add clippy || travis_terminate 0
- cargo clippy
script:

View File

@ -1,12 +1,12 @@
[package]
name = "serde_json"
version = "1.0.38" # remember to update html_root_url
version = "1.0.40" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
license = "MIT OR 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"]
keywords = ["json", "serde", "serialization", "no-std"]
categories = ["encoding"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
@ -16,16 +16,18 @@ travis-ci = { repository = "serde-rs/json" }
appveyor = { repository = "serde-rs/json" }
[dependencies]
serde = "1.0.60"
serde = { version = "1.0.60", default-features = false, features = ["alloc"] }
indexmap = { version = "1.0", optional = true }
itoa = "0.4.3"
ryu = "0.2"
itoa = { version = "0.4.3", default-features = false }
ryu = "1.0"
[dev-dependencies]
compiletest_rs = { version = "0.3", features = ["stable"] }
serde_bytes = "0.10"
automod = "0.1"
select-rustc = "0.1"
serde_bytes = "0.11"
serde_derive = "1.0"
serde_stacker = "0.1"
trybuild = "1.0"
[package.metadata.docs.rs]
features = ["raw_value", "unbounded_depth"]
@ -37,12 +39,14 @@ features = ["raw_value"]
### FEATURES #################################################################
[features]
default = []
default = ["std"]
std = []
# 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"]
preserve_order = ["indexmap", "std"]
# 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,8 +199,7 @@ 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. In order to use this macro,
`serde_json` needs to be imported with the `#[macro_use]` attribute.
objects with very natural JSON syntax.
<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">
@ -327,23 +326,6 @@ 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
@ -352,3 +334,20 @@ be dual licensed as above, without any additional terms or conditions.
[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,7 +27,6 @@ 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,10 +1,13 @@
//! 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};
@ -12,7 +15,9 @@ use super::error::{Error, ErrorCode, Result};
use read::{self, Reference};
pub use read::{IoRead, Read, SliceRead, StrRead};
#[cfg(feature = "std")]
pub use read::IoRead;
pub use read::{Read, SliceRead, StrRead};
use number::Number;
#[cfg(feature = "arbitrary_precision")]
@ -63,6 +68,7 @@ where
}
}
#[cfg(feature = "std")]
impl<R> Deserializer<read::IoRead<R>>
where
R: io::Read,
@ -380,7 +386,14 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
fn parse_integer(&mut self, positive: bool) -> Result<ParserNumber> {
match try!(self.next_char_or_null()) {
let next = match try!(self.next_char()) {
Some(b) => b,
None => {
return Err(self.error(ErrorCode::EofWhileParsingValue));
}
};
match next {
b'0' => {
// There can be only one leading '0'.
match try!(self.peek_or_null()) {
@ -496,7 +509,10 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
if !at_least_one_digit {
return Err(self.peek_error(ErrorCode::InvalidNumber));
match try!(self.peek()) {
Some(_) => return Err(self.peek_error(ErrorCode::InvalidNumber)),
None => return Err(self.peek_error(ErrorCode::EofWhileParsingValue)),
}
}
match try!(self.peek_or_null()) {
@ -525,8 +541,15 @@ 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 try!(self.next_char_or_null()) {
let mut exp = match next {
c @ b'0'...b'9' => (c - b'0') as i32,
_ => {
return Err(self.error(ErrorCode::InvalidNumber));
@ -623,19 +646,19 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
#[cfg(feature = "arbitrary_precision")]
fn scan_or_null(&mut self, buf: &mut String) -> Result<u8> {
fn scan_or_eof(&mut self, buf: &mut String) -> Result<u8> {
match try!(self.next_char()) {
Some(b) => {
buf.push(b as char);
Ok(b)
}
None => Ok(b'\x00'),
None => Err(self.error(ErrorCode::EofWhileParsingValue))
}
}
#[cfg(feature = "arbitrary_precision")]
fn scan_integer(&mut self, buf: &mut String) -> Result<()> {
match try!(self.scan_or_null(buf)) {
match try!(self.scan_or_eof(buf)) {
b'0' => {
// There can be only one leading '0'.
match try!(self.peek_or_null()) {
@ -680,7 +703,10 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
if !at_least_one_digit {
return Err(self.peek_error(ErrorCode::InvalidNumber));
match try!(self.peek()) {
Some(_) => return Err(self.peek_error(ErrorCode::InvalidNumber)),
None => return Err(self.peek_error(ErrorCode::EofWhileParsingValue)),
}
}
match try!(self.peek_or_null()) {
@ -706,7 +732,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
// Make sure a digit follows the exponent place.
match try!(self.scan_or_null(buf)) {
match try!(self.scan_or_eof(buf)) {
b'0'...b'9' => {}
_ => {
return Err(self.error(ErrorCode::InvalidNumber));
@ -2179,7 +2205,6 @@ where
/// # Example
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// use serde::Deserialize;
///
/// use std::error::Error;
@ -2222,6 +2247,7 @@ 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,
@ -2235,7 +2261,6 @@ where
/// # Example
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// use serde::Deserialize;
///
/// #[derive(Deserialize, Debug)]
@ -2278,7 +2303,6 @@ where
/// # Example
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// use serde::Deserialize;
///
/// #[derive(Deserialize, Debug)]

View File

@ -1,10 +1,16 @@
//! When serializing or deserializing JSON goes wrong.
use std::error;
use std::fmt::{self, Debug, Display};
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::io;
use std::str::FromStr;
use std::result;
use serde::de;
use serde::ser;
@ -50,6 +56,7 @@ 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
@ -131,6 +138,7 @@ 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`.
///
@ -185,6 +193,7 @@ 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.
@ -273,6 +282,7 @@ 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 {
@ -302,6 +312,7 @@ 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"),
@ -333,10 +344,11 @@ impl Display for ErrorCode {
}
}
impl error::Error for Error {
impl StdError for Error {
#[cfg(feature = "std")]
fn description(&self) -> &str {
match self.err.code {
ErrorCode::Io(ref err) => error::Error::description(err),
ErrorCode::Io(ref err) => StdError::description(err),
_ => {
// If you want a better message, use Display::fmt or to_string().
"JSON error"
@ -344,7 +356,8 @@ impl error::Error for Error {
}
}
fn cause(&self) -> Option<&error::Error> {
#[cfg(feature = "std")]
fn cause(&self) -> Option<&StdError> {
match self.err.code {
ErrorCode::Io(ref err) => Some(err),
_ => None,

View File

@ -119,7 +119,6 @@
//! largely automatically.
//!
//! ```edition2018
//! # use serde_derive::{Deserialize, Serialize};
//! use serde::{Deserialize, Serialize};
//! use serde_json::Result;
//!
@ -179,8 +178,7 @@
//! # Constructing JSON values
//!
//! Serde JSON provides a [`json!` macro][macro] to build `serde_json::Value`
//! objects with very natural JSON syntax. In order to use this macro,
//! `serde_json` needs to be imported with the `#[macro_use]` attribute.
//! objects with very natural JSON syntax.
//!
//! ```edition2018
//! use serde_json::json;
@ -243,7 +241,6 @@
//! such as a File or a TCP stream.
//!
//! ```edition2018
//! # use serde_derive::{Deserialize, Serialize};
//! use serde::{Deserialize, Serialize};
//! use serde_json::Result;
//!
@ -294,7 +291,8 @@
//! [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.38")]
#![doc(html_root_url = "https://docs.rs/serde_json/1.0.40")]
#![allow(unknown_lints, bare_trait_objects, ellipsis_inclusive_range_patterns)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy lints
@ -307,6 +305,8 @@
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,10 +315,20 @@
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")]
@ -326,11 +336,15 @@ extern crate indexmap;
extern crate itoa;
extern crate ryu;
#[cfg(feature = "std")]
#[doc(inline)]
pub use self::de::{from_reader, from_slice, from_str, Deserializer, StreamDeserializer};
pub use self::de::{from_reader};
#[doc(inline)]
pub use self::de::{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,
};
@ -342,8 +356,8 @@ pub use self::value::{from_value, to_value, Map, Number, Value};
macro_rules! try {
($e:expr) => {
match $e {
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(err) => return ::std::result::Result::Err(err),
::core::result::Result::Ok(val) => val,
::core::result::Result::Err(err) => return ::core::result::Result::Err(err),
}
};
}
@ -354,9 +368,11 @@ 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,15 +7,16 @@
//! [`IndexMap`]: https://docs.rs/indexmap/*/indexmap/map/struct.IndexMap.html
use serde::{de, ser};
use std::borrow::Borrow;
use std::fmt::{self, Debug};
use std::hash::Hash;
use std::iter::FromIterator;
use std::ops;
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 value::Value;
#[cfg(not(feature = "preserve_order"))]
use std::collections::{btree_map, BTreeMap};
use alloc::collections::{btree_map, BTreeMap};
#[cfg(feature = "preserve_order")]
use indexmap::{self, IndexMap};
@ -138,7 +139,7 @@ impl Map<String, Value> {
#[cfg(feature = "preserve_order")]
use indexmap::map::Entry as EntryImpl;
#[cfg(not(feature = "preserve_order"))]
use std::collections::btree_map::Entry as EntryImpl;
use alloc::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 std::fmt::{self, Debug, Display};
use core::fmt::{self, Debug, Display};
#[cfg(feature = "arbitrary_precision")]
use itoa;
@ -237,7 +237,7 @@ impl Number {
}
#[cfg(feature = "arbitrary_precision")]
{
ryu::Buffer::new().format(f).to_owned()
ryu::Buffer::new().format_finite(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 f.to_string() == self.n {
if ryu::Buffer::new().format_finite(f) == self.n || f.to_string() == self.n {
return visitor.visit_f64(f);
}
}

View File

@ -20,10 +20,19 @@ 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};
///
@ -70,7 +79,7 @@ use error::Error;
/// The typical usage of `RawValue` will be in the borrowed form:
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// # use serde::Deserialize;
/// # use serde_json::value::RawValue;
/// #
/// #[derive(Deserialize)]
@ -93,7 +102,7 @@ use error::Error;
/// [`serde_json::from_reader`]: ../fn.from_reader.html
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// # use serde::Deserialize;
/// # use serde_json::value::RawValue;
/// #
/// #[derive(Deserialize)]
@ -101,16 +110,6 @@ 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,
@ -185,7 +184,6 @@ impl RawValue {
/// # Example
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// use serde::Deserialize;
/// use serde_json::{Result, value::RawValue};
///

View File

@ -1,9 +1,13 @@
use std::ops::Deref;
use std::{char, cmp, io, str};
use alloc::vec::Vec;
use core::ops::Deref;
use core::{char, cmp, str};
#[cfg(feature = "std")]
use std::io;
#[cfg(feature = "raw_value")]
use serde::de::Visitor;
#[cfg(feature = "std")]
use iter::LineColIterator;
use error::{Error, ErrorCode, Result};
@ -118,6 +122,7 @@ 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,
@ -157,6 +162,7 @@ mod private {
//////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl<R> IoRead<R>
where
R: io::Read,
@ -181,8 +187,10 @@ 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,
@ -221,6 +229,7 @@ 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(value);
let s = buffer.format_finite(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(value);
let s = buffer.format_finite(value);
writer.write_all(s.as_bytes())
}

View File

@ -1,8 +1,10 @@
use std::borrow::Cow;
use std::fmt;
use std::slice;
use std::str;
use std::vec;
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 serde;
use serde::de::{

View File

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

View File

@ -1,5 +1,7 @@
use std::fmt;
use std::ops;
use alloc::borrow::ToOwned;
use alloc::string::String;
use core::fmt;
use core::ops;
use super::Value;
use map::Map;
@ -132,6 +134,8 @@ 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,8 +3,7 @@
//! # Constructing JSON
//!
//! Serde JSON provides a [`json!` macro][macro] to build `serde_json::Value`
//! objects with very natural JSON syntax. In order to use this macro,
//! `serde_json` needs to be imported with the `#[macro_use]` attribute.
//! objects with very natural JSON syntax.
//!
//! ```edition2018
//! use serde_json::json;
@ -93,10 +92,13 @@
//! [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 std::fmt::{self, Debug};
use alloc::string::String;
use alloc::vec::Vec;
use core::fmt::{self, Debug};
use core::mem;
use core::str;
#[cfg(feature = "std")]
use std::io;
use std::mem;
use std::str;
use serde::de::DeserializeOwned;
use serde::ser::Serialize;
@ -191,10 +193,12 @@ 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 {
@ -212,6 +216,7 @@ impl<'a, 'b> io::Write for WriterFormatter<'a, 'b> {
}
}
#[cfg(feature = "std")]
impl fmt::Display for Value {
/// Display a JSON value as a string.
///
@ -865,7 +870,7 @@ impl Value {
/// # Examples
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// # use serde::Deserialize;
/// use serde_json::Value;
///
/// #[derive(Deserialize)]
@ -907,7 +912,6 @@ mod ser;
/// # Example
///
/// ```edition2018
/// # use serde_derive::Serialize;
/// use serde::Serialize;
/// use serde_json::json;
///
@ -972,7 +976,6 @@ where
/// # Example
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// use serde::Deserialize;
/// use serde_json::json;
///

View File

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

View File

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

View File

@ -1,18 +1,6 @@
extern crate compiletest_rs as compiletest;
#[rustc::attr(not(nightly), ignore)]
#[test]
fn ui() {
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()
});
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/*.rs");
}

View File

@ -1,13 +0,0 @@
[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 = "../.." }

View File

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

6
tests/regression.rs Normal file
View File

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

View File

@ -0,0 +1,18 @@
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),
}
}

1
tests/regression/mod.rs Normal file
View File

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

View File

@ -23,6 +23,7 @@ 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);
@ -81,6 +82,36 @@ 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,9 +31,14 @@ use serde::ser::{self, Serialize, Serializer};
use serde_bytes::{ByteBuf, Bytes};
#[cfg(feature = "std")]
use serde_json::{
from_reader, from_slice, from_str, from_value, to_string, to_string_pretty, to_value, to_vec,
to_writer, Deserializer, Number, Value,
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,
};
macro_rules! treemap {
@ -72,6 +77,7 @@ struct Outer {
inner: Vec<Inner>,
}
#[cfg(feature = "std")]
fn test_encode_ok<T>(errors: &[(T, &str)])
where
T: PartialEq + Debug + ser::Serialize,
@ -88,6 +94,7 @@ where
}
}
#[cfg(feature = "std")]
fn test_pretty_encode_ok<T>(errors: &[(T, &str)])
where
T: PartialEq + Debug + ser::Serialize,
@ -105,6 +112,7 @@ where
}
#[test]
#[cfg(feature = "std")]
fn test_write_null() {
let tests = &[((), "null")];
test_encode_ok(tests);
@ -112,6 +120,7 @@ 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);
@ -119,6 +128,7 @@ fn test_write_u64() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_i64() {
let tests = &[
(3i64, "3"),
@ -131,6 +141,7 @@ fn test_write_i64() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_f64() {
let tests = &[
(3.0, "3.0"),
@ -146,6 +157,7 @@ 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());
@ -161,6 +173,7 @@ fn test_encode_nonfinite_float_yields_null() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_str() {
let tests = &[("", "\"\""), ("foo", "\"foo\"")];
test_encode_ok(tests);
@ -168,6 +181,7 @@ fn test_write_str() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_bool() {
let tests = &[(true, "true"), (false, "false")];
test_encode_ok(tests);
@ -175,6 +189,7 @@ fn test_write_bool() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_char() {
let tests = &[
('n', "\"n\""),
@ -194,6 +209,7 @@ fn test_write_char() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_list() {
test_encode_ok(&[
(vec![], "[]"),
@ -244,6 +260,7 @@ fn test_write_list() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_object() {
test_encode_ok(&[
(treemap!(), "{}"),
@ -456,6 +473,7 @@ fn test_write_object() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_tuple() {
test_encode_ok(&[((5,), "[5]")]);
@ -467,6 +485,7 @@ fn test_write_tuple() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_enum() {
test_encode_ok(&[
(Animal::Dog, "\"Dog\""),
@ -533,6 +552,7 @@ fn test_write_enum() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_option() {
test_encode_ok(&[(None, "null"), (Some("jodhpurs"), "\"jodhpurs\"")]);
@ -550,6 +570,7 @@ fn test_write_option() {
}
#[test]
#[cfg(feature = "std")]
fn test_write_newtype_struct() {
#[derive(Serialize, PartialEq, Debug)]
struct Newtype(BTreeMap<String, i32>);
@ -737,15 +758,15 @@ fn test_parse_number_errors() {
test_parse_err::<f64>(&[
("+", "expected value at line 1 column 1"),
(".", "expected value at line 1 column 1"),
("-", "invalid number at line 1 column 1"),
("-", "EOF while parsing a value 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.", "invalid number at line 1 column 2"),
("1.", "EOF while parsing a value at line 1 column 2"),
("1.a", "invalid number at line 1 column 3"),
("1.e1", "invalid number at line 1 column 3"),
("1e", "invalid number at line 1 column 2"),
("1e+", "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"),
("1a", "trailing characters at line 1 column 2"),
(
"100e777777777777777777777777777",
@ -1374,6 +1395,7 @@ 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>);
@ -1460,6 +1482,7 @@ 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>);
@ -1553,6 +1576,7 @@ fn test_serialize_map_with_no_len() {
}
#[test]
#[cfg(feature = "std")]
fn test_deserialize_from_stream() {
use serde::Deserialize;
use std::net;
@ -1593,6 +1617,7 @@ fn test_deserialize_from_stream() {
}
#[test]
#[cfg(feature = "std")]
fn test_serialize_rejects_bool_keys() {
let map = treemap!(
true => 2,
@ -1604,6 +1629,7 @@ fn test_serialize_rejects_bool_keys() {
}
#[test]
#[cfg(feature = "std")]
fn test_serialize_rejects_adt_keys() {
let map = treemap!(
Some("a") => 2,
@ -1616,6 +1642,7 @@ fn test_serialize_rejects_adt_keys() {
}
#[test]
#[cfg(feature = "std")]
fn test_bytes_ser() {
let buf = vec![];
let bytes = Bytes::new(&buf);
@ -1627,6 +1654,8 @@ 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());
@ -1778,6 +1807,7 @@ fn test_disable_recursion_limit() {
}
#[test]
#[cfg(feature = "std")]
fn test_integer_key() {
// map with integer keys
let map = treemap!(
@ -1796,6 +1826,7 @@ fn test_integer_key() {
}
#[test]
#[cfg(feature = "std")]
fn test_integer128_key() {
let map = treemap! {
100000000000000000000000000000000000000u128 => ()
@ -1806,6 +1837,7 @@ fn test_integer128_key() {
}
#[test]
#[cfg(feature = "std")]
fn test_deny_float_key() {
#[derive(Eq, PartialEq, Ord, PartialOrd)]
struct Float;
@ -1838,6 +1870,7 @@ fn test_borrowed_key() {
}
#[test]
#[cfg(feature = "std")]
fn test_effectively_string_keys() {
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Serialize, Deserialize)]
enum Enum {
@ -1864,6 +1897,7 @@ 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.
@ -1961,6 +1995,7 @@ impl io::Read for FailReader {
}
#[test]
#[cfg(feature = "std")]
fn test_category() {
assert!(from_str::<String>("123").unwrap_err().is_data());
@ -2001,6 +2036,7 @@ 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()
@ -2037,6 +2073,7 @@ 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,6 +5,3 @@ 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,6 +5,3 @@ 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,6 +4,4 @@ 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,6 +5,3 @@ 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,6 +4,4 @@ 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,6 +3,3 @@ 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,6 +3,3 @@ 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,6 +3,3 @@ 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,6 +3,3 @@ 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

View File

@ -1,50 +0,0 @@
#!/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