diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 387322431..77d611a09 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,10 +106,6 @@ jobs: steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@miri - - run: sudo apt-get install gcc-powerpc-linux-gnu - if: matrix.target == 'powerpc64-unknown-linux-gnu' - - run: sudo apt-get install gcc-mips-linux-gnu - if: matrix.target == 'mips-unknown-linux-gnu' - run: cargo miri setup - run: cargo miri test --target ${{matrix.target}} - run: cargo miri test --target ${{matrix.target}} --features preserve_order,float_roundtrip,arbitrary_precision,raw_value diff --git a/.gitignore b/.gitignore index 165eb22d0..e9e21997b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ -target/ -**/*.rs.bk -*.sw[po] -Cargo.lock +/target/ +/Cargo.lock diff --git a/Cargo.toml b/Cargo.toml index 242f05b6c..866c31318 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_json" -version = "1.0.137" +version = "1.0.140" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["encoding", "parser-implementations", "no-std"] description = "A JSON serialization file format" @@ -29,13 +29,15 @@ serde_derive = "1.0.166" serde_stacker = "0.1.8" trybuild = { version = "1.0.81", features = ["diff"] } -[lib] -doc-scrape-examples = false - [package.metadata.docs.rs] features = ["preserve_order", "raw_value", "unbounded_depth"] targets = ["x86_64-unknown-linux-gnu"] -rustdoc-args = ["--generate-link-to-definition"] +rustdoc-args = [ + "--generate-link-to-definition", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", +] [package.metadata.playground] features = ["float_roundtrip", "raw_value", "unbounded_depth"] diff --git a/fuzz/.gitignore b/fuzz/.gitignore index f83457aec..4bc31dc39 100644 --- a/fuzz/.gitignore +++ b/fuzz/.gitignore @@ -1,4 +1,5 @@ -artifacts/ -corpus/ -coverage/ -target/ +/artifacts/ +/corpus/ +/coverage/ +/target/ +/Cargo.lock diff --git a/src/de.rs b/src/de.rs index 5b64138d8..4080c54ac 100644 --- a/src/de.rs +++ b/src/de.rs @@ -45,11 +45,17 @@ where /// Create a JSON deserializer from one of the possible serde_json input /// sources. /// + /// When reading from a source against which short reads are not efficient, such + /// as a [`File`], you will want to apply your own buffering because serde_json + /// will not buffer the input. See [`std::io::BufReader`]. + /// /// Typically it is more convenient to use one of these methods instead: /// /// - Deserializer::from_str /// - Deserializer::from_slice /// - Deserializer::from_reader + /// + /// [`File`]: std::fs::File pub fn new(read: R) -> Self { Deserializer { read, @@ -362,7 +368,7 @@ impl<'de, R: Read<'de>> Deserializer { None => { return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); } - }; + } tri!(self.scan_integer128(&mut buf)); @@ -2517,10 +2523,7 @@ where /// reading a file completely into memory and then applying [`from_str`] /// or [`from_slice`] on it. See [issue #160]. /// -/// [`File`]: https://doc.rust-lang.org/std/fs/struct.File.html -/// [`std::io::BufReader`]: https://doc.rust-lang.org/std/io/struct.BufReader.html -/// [`from_str`]: ./fn.from_str.html -/// [`from_slice`]: ./fn.from_slice.html +/// [`File`]: std::fs::File /// [issue #160]: https://github.com/serde-rs/json/issues/160 /// /// # Example @@ -2567,6 +2570,7 @@ where /// use serde::Deserialize; /// /// use std::error::Error; +/// use std::io::BufReader; /// use std::net::{TcpListener, TcpStream}; /// /// #[derive(Deserialize, Debug)] @@ -2575,8 +2579,8 @@ where /// location: String, /// } /// -/// fn read_user_from_stream(tcp_stream: TcpStream) -> Result> { -/// let mut de = serde_json::Deserializer::from_reader(tcp_stream); +/// fn read_user_from_stream(stream: &mut BufReader) -> Result> { +/// let mut de = serde_json::Deserializer::from_reader(stream); /// let u = User::deserialize(&mut de)?; /// /// Ok(u) @@ -2587,8 +2591,9 @@ where /// # fn fake_main() { /// let listener = TcpListener::bind("127.0.0.1:4000").unwrap(); /// -/// for stream in listener.incoming() { -/// println!("{:#?}", read_user_from_stream(stream.unwrap())); +/// for tcp_stream in listener.incoming() { +/// let mut buffered = BufReader::new(tcp_stream.unwrap()); +/// println!("{:#?}", read_user_from_stream(&mut buffered)); /// } /// } /// ``` diff --git a/src/lib.rs b/src/lib.rs index 07090dd0c..a9f82f2b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -299,13 +299,14 @@ //! [macro]: crate::json //! [`serde-json-core`]: https://github.com/rust-embedded-community/serde-json-core -#![doc(html_root_url = "https://docs.rs/serde_json/1.0.137")] +#![doc(html_root_url = "https://docs.rs/serde_json/1.0.140")] // Ignored clippy lints #![allow( clippy::collapsible_else_if, clippy::comparison_chain, clippy::deprecated_cfg_attr, clippy::doc_markdown, + clippy::elidable_lifetime_names, clippy::excessive_precision, clippy::explicit_auto_deref, clippy::float_cmp, @@ -317,6 +318,7 @@ clippy::needless_lifetimes, clippy::return_self_not_must_use, clippy::transmute_ptr_to_ptr, + clippy::unbuffered_bytes, clippy::unconditional_recursion, // https://github.com/rust-lang/rust-clippy/issues/12133 clippy::unnecessary_wraps )] diff --git a/src/map.rs b/src/map.rs index 126e8001a..be60f22db 100644 --- a/src/map.rs +++ b/src/map.rs @@ -3,8 +3,8 @@ //! By default the map is backed by a [`BTreeMap`]. Enable the `preserve_order` //! feature of serde_json to use [`IndexMap`] instead. //! -//! [`BTreeMap`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html -//! [`IndexMap`]: https://docs.rs/indexmap/*/indexmap/map/struct.IndexMap.html +//! [`BTreeMap`]: std::collections::BTreeMap +//! [`IndexMap`]: indexmap::IndexMap use crate::error::Error; use crate::value::Value; @@ -619,8 +619,7 @@ impl<'de> de::IntoDeserializer<'de, Error> for &'de Map { /// A view into a single entry in a map, which may either be vacant or occupied. /// This enum is constructed from the [`entry`] method on [`Map`]. /// -/// [`entry`]: struct.Map.html#method.entry -/// [`Map`]: struct.Map.html +/// [`entry`]: Map::entry pub enum Entry<'a> { /// A vacant Entry. Vacant(VacantEntry<'a>), @@ -629,15 +628,11 @@ pub enum Entry<'a> { } /// A vacant Entry. It is part of the [`Entry`] enum. -/// -/// [`Entry`]: enum.Entry.html pub struct VacantEntry<'a> { vacant: VacantEntryImpl<'a>, } /// An occupied Entry. It is part of the [`Entry`] enum. -/// -/// [`Entry`]: enum.Entry.html pub struct OccupiedEntry<'a> { occupied: OccupiedEntryImpl<'a>, } diff --git a/src/raw.rs b/src/raw.rs index f81d943a5..be4dad44d 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -99,9 +99,9 @@ use serde::ser::{Serialize, SerializeStruct, Serializer}; /// the boxed form of `RawValue` instead. This is almost as efficient but /// involves buffering the raw value from the I/O stream into memory. /// -/// [`serde_json::from_str`]: ../fn.from_str.html -/// [`serde_json::from_slice`]: ../fn.from_slice.html -/// [`serde_json::from_reader`]: ../fn.from_reader.html +/// [`serde_json::from_str`]: crate::from_str +/// [`serde_json::from_slice`]: crate::from_slice +/// [`serde_json::from_reader`]: crate::from_reader /// /// ``` /// # use serde::Deserialize; diff --git a/src/read.rs b/src/read.rs index b4128467b..0748af44c 100644 --- a/src/read.rs +++ b/src/read.rs @@ -191,6 +191,12 @@ where R: io::Read, { /// Create a JSON input source to read from a std::io input stream. + /// + /// When reading from a source against which short reads are not efficient, such + /// as a [`File`], you will want to apply your own buffering because serde_json + /// will not buffer the input. See [`std::io::BufReader`]. + /// + /// [`File`]: std::fs::File pub fn new(reader: R) -> Self { IoRead { iter: LineColIterator::new(reader.bytes()), diff --git a/src/ser.rs b/src/ser.rs index 6956671b4..9b14389c8 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -1688,6 +1688,20 @@ pub trait Formatter { } /// Writes a floating point value like `-31.26e+12` to the specified writer. + /// + /// # Special cases + /// + /// This function **does not** check for NaN or infinity. If the input + /// number is not a finite float, the printed representation will be some + /// correctly formatted but unspecified numerical value. + /// + /// Please check [`is_finite`] yourself before calling this function, or + /// check [`is_nan`] and [`is_infinite`] and handle those cases yourself + /// with a different `Formatter` method. + /// + /// [`is_finite`]: f32::is_finite + /// [`is_nan`]: f32::is_nan + /// [`is_infinite`]: f32::is_infinite #[inline] fn write_f32(&mut self, writer: &mut W, value: f32) -> io::Result<()> where @@ -1699,6 +1713,20 @@ pub trait Formatter { } /// Writes a floating point value like `-31.26e+12` to the specified writer. + /// + /// # Special cases + /// + /// This function **does not** check for NaN or infinity. If the input + /// number is not a finite float, the printed representation will be some + /// correctly formatted but unspecified numerical value. + /// + /// Please check [`is_finite`] yourself before calling this function, or + /// check [`is_nan`] and [`is_infinite`] and handle those cases yourself + /// with a different `Formatter` method. + /// + /// [`is_finite`]: f64::is_finite + /// [`is_nan`]: f64::is_nan + /// [`is_infinite`]: f64::is_infinite #[inline] fn write_f64(&mut self, writer: &mut W, value: f64) -> io::Result<()> where diff --git a/src/value/index.rs b/src/value/index.rs index 4e41a39be..7b0011004 100644 --- a/src/value/index.rs +++ b/src/value/index.rs @@ -12,9 +12,9 @@ use core::ops; /// trait is implemented for strings which are used as the index into a JSON /// map, and for `usize` which is used as the index into a JSON array. /// -/// [`get`]: ../enum.Value.html#method.get -/// [`get_mut`]: ../enum.Value.html#method.get_mut -/// [square-bracket indexing operator]: ../enum.Value.html#impl-Index%3CI%3E-for-Value +/// [`get`]: Value::get +/// [`get_mut`]: Value::get_mut +/// [square-bracket indexing operator]: Value#impl-Index%3CI%3E-for-Value /// /// This trait is sealed and cannot be implemented for types outside of /// `serde_json`. diff --git a/tests/crate/.gitignore b/tests/crate/.gitignore new file mode 100644 index 000000000..e9e21997b --- /dev/null +++ b/tests/crate/.gitignore @@ -0,0 +1,2 @@ +/target/ +/Cargo.lock diff --git a/tests/regression.rs b/tests/regression.rs index 22cca8243..315bb1545 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -1,4 +1,4 @@ -#![allow(clippy::needless_lifetimes)] +#![allow(clippy::elidable_lifetime_names, clippy::needless_lifetimes)] mod regression { automod::dir!("tests/regression");