Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ all-features = true

[dependencies]
indexmap = { version = "2.2.6", optional = true }
rustc-hash = { version = "2", optional = true }
serde = { version = "1.0", optional = true, features = ["derive"] }
serde_json = { version = "1.0", optional = true }
unicode-width = { version = "0.2.0", optional = true }

[features]
cst = []
# use a faster (non-DoS-resistant) hasher for parsed objects
fast_hash = ["dep:rustc-hash"]
preserve_order = ["indexmap"]
serde = ["dep:serde"]
serde_json = ["dep:serde_json"]
Expand Down
15 changes: 15 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,21 @@
//! which will pull in and use the [unicode-width](https://crates.io/crates/unicode-width) dependency internally.
//! Otherwise it will use the character count, which isn't as accurate of a number, but will probably be good enough
//! in most cases.
//!
//! ## Faster hashing
//!
//! Parsed objects are stored in a hash map that uses the standard library's default (DoS-resistant but slower)
//! hasher. When parsing trusted input, enable the `fast_hash` cargo feature to instead use the faster
//! [rustc-hash](https://crates.io/crates/rustc-hash) hasher, which can noticeably speed up parsing of
//! object-heavy documents:
//!
//! ```toml
//! # in Cargo.toml
//! jsonc-parser = { version = "...", features = ["fast_hash"] }
//! ```
//!
//! This hasher is not resistant to hash-collision denial-of-service attacks, so avoid it when parsing
//! untrusted input. It composes with the `preserve_order` feature.

#![deny(clippy::print_stderr)]
#![deny(clippy::print_stdout)]
Expand Down
4 changes: 2 additions & 2 deletions src/parse_to_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn parse_value<'a>(parser: &mut JsoncParser<'a>, token: Token<'a>) -> Result<Jso

fn parse_object<'a>(parser: &mut JsoncParser<'a>) -> Result<JsonValue<'a>, ParseError> {
parser.enter_container()?;
let mut props = Map::new();
let mut props = Map::default();
let mut first = true;

loop {
Expand Down Expand Up @@ -131,7 +131,7 @@ mod tests {
.unwrap()
.unwrap();

let mut object_map = Map::new();
let mut object_map = Map::default();
object_map.insert(Cow::Borrowed("a"), JsonValue::Null);
object_map.insert(
Cow::Borrowed("b"),
Expand Down
14 changes: 9 additions & 5 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ pub enum JsonValue<'a> {
Null,
}

#[cfg(not(feature = "preserve_order"))]
#[cfg(all(not(feature = "preserve_order"), not(feature = "fast_hash")))]
pub type Map<K, V> = std::collections::HashMap<K, V>;
#[cfg(feature = "preserve_order")]
#[cfg(all(not(feature = "preserve_order"), feature = "fast_hash"))]
pub type Map<K, V> = std::collections::HashMap<K, V, rustc_hash::FxBuildHasher>;
#[cfg(all(feature = "preserve_order", not(feature = "fast_hash")))]
pub type Map<K, V> = indexmap::IndexMap<K, V>;
#[cfg(all(feature = "preserve_order", feature = "fast_hash"))]
pub type Map<K, V> = indexmap::IndexMap<K, V, rustc_hash::FxBuildHasher>;

/// A JSON object.
#[derive(Clone, PartialEq, Debug)]
Expand Down Expand Up @@ -82,7 +86,7 @@ impl<'a> JsonObject<'a> {

/// Creates a new JsonObject with the specified capacity.
pub fn with_capacity(capacity: usize) -> JsonObject<'a> {
JsonObject(Map::with_capacity(capacity))
JsonObject(Map::with_capacity_and_hasher(capacity, Default::default()))
}

/// Drops the object returning the inner map.
Expand Down Expand Up @@ -230,7 +234,7 @@ mod test {

#[test]
fn it_should_take() {
let mut inner = Map::new();
let mut inner = Map::default();
inner.insert(Cow::Borrowed("prop"), JsonValue::String(Cow::Borrowed("asdf")));
inner.insert(Cow::Borrowed("other"), JsonValue::String(Cow::Borrowed("text")));
let mut obj = JsonObject::new(inner);
Expand All @@ -250,7 +254,7 @@ mod test {

#[test]
fn it_should_get() {
let mut inner = Map::new();
let mut inner = Map::default();
inner.insert(Cow::Borrowed("prop"), JsonValue::String(Cow::Borrowed("asdf")));
let obj = JsonObject::new(inner);

Expand Down
Loading