Skip to content

Commit

Permalink
chore: fix nightly CI
Browse files Browse the repository at this point in the history
* chore(ci): fix a number of new nightly warnings

* deps: updated a number of dependencies

bump clap from 4.5.4 to 4.5.7
bump log from 0.4.21 to 0.4.22
bump thiserror from 1.0.58 to 1.0.61

* chore(ci): update deny.toml according to cargo-deny breaking changes

See EmbarkStudios/cargo-deny#606.

* chore(test): fix tests in quotes that were erroneously disabled

* chore(doc): fix a bunch of documentation whitespace lints
  • Loading branch information
V0ldek authored Jun 29, 2024
1 parent f0256bb commit b4c4ec8
Show file tree
Hide file tree
Showing 17 changed files with 344 additions and 293 deletions.
360 changes: 182 additions & 178 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions crates/rsonpath-lib/src/automaton.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ impl<'q> Automaton<'q> {
///
/// # Errors
/// - [`CompilerError::QueryTooComplex`] raised if the query is too complex
/// and the automaton size was exceeded.
/// and the automaton size was exceeded.
/// - [`CompilerError::NotSupported`] raised if the query contains elements
/// not yet supported by the compiler.
/// not yet supported by the compiler.
#[inline]
pub fn new(query: &'q JsonPathQuery) -> Result<Self, CompilerError> {
let nfa = NondeterministicAutomaton::new(query)?;
Expand Down
1 change: 1 addition & 0 deletions crates/rsonpath-lib/src/automaton/array_transition_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
//! * {prio. 2} over X intersect Y to S+{t}
//! * {prio. 1} over X to S
//! * {prio. 1} over Y to {t}
//!
//! The semantics are correct as long as the transitions are taken in non-increasing order of priorities.
//!
//! Intersection of two linear sets is always a linear set. Finding such intersection is not trivial,
Expand Down
7 changes: 4 additions & 3 deletions crates/rsonpath-lib/src/automaton/minimizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ struct SuperstateTransitionTable<'q> {
* Every state with a self-loop becomes a checkpoint. They have two crucial properties:
* 1. Any path from the initial to the accepting state goes through each checkpoint.
* 2. Each superstate containing
* a) a checkpoint and;
* b) some states on the path from the initial state to that checkpoint,
* is equivalent to a superstate without the b) states.
* a) a checkpoint and;
* b) some states on the path from the initial state to that checkpoint,
* is equivalent to a superstate without the b) states.
*
* This allows on-the-fly minimization with the `normalize` function, vastly reducing
* the number of superstates to consider.
*
Expand Down
4 changes: 3 additions & 1 deletion crates/rsonpath-lib/src/automaton/small_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,9 @@ macro_rules! native_small_set {
};
}

native_small_set!(SmallSet64, SmallSet64Iter, u64, 64);
// If a SmallSet64 is ever needed it can be constructed with the macro.
// native_small_set!(SmallSet64, SmallSet64Iter, u64, 64);
// Currently we only use SmallSet256 which relies on SmallSet128.
native_small_set!(SmallSet128, SmallSet128Iter, u128, 128);

impl<const N: usize> From<[u8; N]> for SmallSet256 {
Expand Down
6 changes: 3 additions & 3 deletions crates/rsonpath-lib/src/classification.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//! Classifiers working on the input stream.
//!
//! - [`quotes`] contains the low-level [`QuoteClassifiedIterator`](`quotes::QuoteClassifiedIterator`)
//! computing basic information on which characters are escaped or within quotes.
//! computing basic information on which characters are escaped or within quotes.
//! - [`structural`] contains the [`StructuralIterator`](`structural::StructuralIterator`)
//! that wraps over a quote classifier to extract a stream of [`Structural`](`structural::Structural`) characters.
//! that wraps over a quote classifier to extract a stream of [`Structural`](`structural::Structural`) characters.
//! - [`depth`] contains the [`DepthIterator`](`depth::DepthIterator`) that works on top of a quote classifier
//! to provide quick fast-forwarding over the stream while keeping track of the depth.
//! to provide quick fast-forwarding over the stream while keeping track of the depth.
//!
//! This base module provides the [`ResumeClassifierState`] struct common between all
//! higher-level classifiers that work on top of a [`QuoteClassifiedIterator`](`quotes::QuoteClassifiedIterator`).
Expand Down
4 changes: 2 additions & 2 deletions crates/rsonpath-lib/src/classification/memmem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ pub trait Memmem<'i, 'b, 'r, I: Input, const N: usize> {
/// Find a member key identified by a given [`JsonString`].
///
/// - `first_block` &ndash; optional first block to search; if not provided,
/// the search will start at the next block returned by the underlying [`Input`] iterator.
/// the search will start at the next block returned by the underlying [`Input`] iterator.
/// - `start_idx` &ndash; index of the start of search, either falling inside `first_block`,
/// or at the start of the next block.
/// or at the start of the next block.
///
/// # Errors
/// Errors when reading the underlying [`Input`] are propagated.
Expand Down
46 changes: 33 additions & 13 deletions crates/rsonpath-lib/src/classification/quotes/avx2_32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,48 @@ impl BlockAvx2Classifier {
}
}

#[cfg(all(test, cfg = "avx_32"))]
#[cfg(test)]
mod tests {
use super::Avx2QuoteClassifier32;
use super::{Constructor, QuotesImpl};
use crate::{
input::{Input, OwnedBytes},
result::empty::EmptyRecorder,
FallibleIterator,
};
use test_case::test_case;

#[test_case("" => None)]
#[test_case("abcd" => Some(0))]
#[test_case(r#""abcd""# => Some(0b01_1111))]
#[test_case(r#""num": 42, "string": "something" "# => Some(0b0_0111_1111_1110_0011_1111_1000_0000_1111))]
#[test_case(r#"abc\"abc\""# => Some(0b00_0000_0000))]
#[test_case(r#"abc\\"abc\\""# => Some(0b0111_1110_0000))]
#[test_case(r#"{"aaa":[{},{"b":{"c":[1,2,3]}}],"# => Some(0b0000_0000_0000_0110_0011_0000_0001_1110))]
fn single_block(str: &str) -> Option<u32> {
#[test_case("", 0)]
#[test_case("abcd", 0)]
#[test_case(r#""abcd""#, 0b01_1111)]
#[test_case(r#""num": 42, "string": "something" "#, 0b0_0111_1111_1110_0011_1111_1000_0000_1111)]
#[test_case(r#"abc\"abc\""#, 0b00_0000_0000)]
#[test_case(r#"abc\\"abc\\""#, 0b0111_1110_0000)]
#[test_case(r#"{"aaa":[{},{"b":{"c":[1,2,3]}}],"#, 0b0000_0000_0000_0110_0011_0000_0001_1110)]
fn single_block(str: &str, expected: u32) {
if !std::arch::is_x86_feature_detected!("avx2") {
return;
}

let owned_str = str.to_owned();
let input = OwnedBytes::new(&owned_str).unwrap();
let input = OwnedBytes::from(owned_str);
let mut leading_padding = input.leading_padding_len() as u32;
let iter = input.iter_blocks::<_, 32>(&EmptyRecorder);
let mut classifier = Avx2QuoteClassifier32::new(iter);
classifier.next().unwrap().map(|x| x.within_quotes_mask)
let mut classifier = Constructor::new(iter);

// Drop padding-only blocks.
while leading_padding >= 32 {
let mask = classifier.next().unwrap().unwrap().within_quotes_mask;
assert_eq!(mask, 0);
leading_padding -= 32;
}

// The actual classification is now either contained in the next block,
// or split between the two next blocks. Combine them.
let first_mask = classifier.next().unwrap().unwrap().within_quotes_mask;
let len_in_first_mask = if leading_padding == 0 { 0 } else { 32 - leading_padding };
let second_mask = classifier.next().unwrap().unwrap().within_quotes_mask;
let combined_mask = (first_mask >> leading_padding) | (second_mask << len_in_first_mask);

assert_eq!(combined_mask, expected);
}
}
46 changes: 33 additions & 13 deletions crates/rsonpath-lib/src/classification/quotes/avx2_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,48 @@ impl BlockAvx2Classifier {
}
}

#[cfg(all(test, cfg = "avx_64"))]
#[cfg(test)]
mod tests {
use super::Avx2QuoteClassifier64;
use super::{Constructor, QuotesImpl};
use crate::{
input::{Input, OwnedBytes},
result::empty::EmptyRecorder,
FallibleIterator,
};
use test_case::test_case;

#[test_case("" => None)]
#[test_case("abcd" => Some(0))]
#[test_case(r#""abcd""# => Some(0b01_1111))]
#[test_case(r#""number": 42, "string": "something" "# => Some(0b0011_1111_1111_0001_1111_1100_0000_0111_1111))]
#[test_case(r#"abc\"abc\""# => Some(0b00_0000_0000))]
#[test_case(r#"abc\\"abc\\""# => Some(0b0111_1110_0000))]
#[test_case(r#"{"aaa":[{},{"b":{"c":[1,2,3]}}],"e":{"a":[[],[1,2,3],"# => Some(0b0_0000_0000_0000_0110_0011_0000_0000_0000_0110_0011_0000_0001_1110))]
fn single_block(str: &str) -> Option<u64> {
#[test_case("", 0)]
#[test_case("abcd", 0)]
#[test_case(r#""abcd""#, 0b01_1111)]
#[test_case(r#""num": 42, "string": "something" "#, 0b0_0111_1111_1110_0011_1111_1000_0000_1111)]
#[test_case(r#"abc\"abc\""#, 0b00_0000_0000)]
#[test_case(r#"abc\\"abc\\""#, 0b0111_1110_0000)]
#[test_case(r#"{"aaa":[{},{"b":{"c":[1,2,3]}}],"#, 0b0000_0000_0000_0110_0011_0000_0001_1110)]
fn single_block(str: &str, expected: u64) {
if !std::arch::is_x86_feature_detected!("avx2") {
return;
}

let owned_str = str.to_owned();
let input = OwnedBytes::new(&owned_str).unwrap();
let input = OwnedBytes::from(owned_str);
let mut leading_padding = input.leading_padding_len() as u64;
let iter = input.iter_blocks::<_, 64>(&EmptyRecorder);
let mut classifier = Avx2QuoteClassifier64::new(iter);
classifier.next().unwrap().map(|x| x.within_quotes_mask)
let mut classifier = Constructor::new(iter);

// Drop padding-only blocks.
while leading_padding >= 64 {
let mask = classifier.next().unwrap().unwrap().within_quotes_mask;
assert_eq!(mask, 0);
leading_padding -= 64;
}

// The actual classification is now either contained in the next block,
// or split between the two next blocks. Combine them.
let first_mask = classifier.next().unwrap().unwrap().within_quotes_mask;
let len_in_first_mask = if leading_padding == 0 { 0 } else { 64 - leading_padding };
let second_mask = classifier.next().unwrap().unwrap().within_quotes_mask;
let combined_mask = (first_mask >> leading_padding) | (second_mask << len_in_first_mask);

assert_eq!(combined_mask, expected);
}
}
46 changes: 33 additions & 13 deletions crates/rsonpath-lib/src/classification/quotes/sse2_32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,48 @@ impl BlockSse2Classifier {
}
}

#[cfg(all(test, cfg = "ssse3_32"))]
#[cfg(test)]
mod tests {
use super::Sse2QuoteClassifier32;
use super::{Constructor, QuotesImpl};
use crate::{
input::{Input, OwnedBytes},
result::empty::EmptyRecorder,
FallibleIterator,
};
use test_case::test_case;

#[test_case("" => None)]
#[test_case("abcd" => Some(0))]
#[test_case(r#""abcd""# => Some(0b01_1111))]
#[test_case(r#""num": 42, "string": "something" "# => Some(0b0_0111_1111_1110_0011_1111_1000_0000_1111))]
#[test_case(r#"abc\"abc\""# => Some(0b00_0000_0000))]
#[test_case(r#"abc\\"abc\\""# => Some(0b0111_1110_0000))]
#[test_case(r#"{"aaa":[{},{"b":{"c":[1,2,3]}}],"# => Some(0b0000_0000_0000_0110_0011_0000_0001_1110))]
fn single_block(str: &str) -> Option<u32> {
#[test_case("", 0)]
#[test_case("abcd", 0)]
#[test_case(r#""abcd""#, 0b01_1111)]
#[test_case(r#""num": 42, "string": "something" "#, 0b0_0111_1111_1110_0011_1111_1000_0000_1111)]
#[test_case(r#"abc\"abc\""#, 0b00_0000_0000)]
#[test_case(r#"abc\\"abc\\""#, 0b0111_1110_0000)]
#[test_case(r#"{"aaa":[{},{"b":{"c":[1,2,3]}}],"#, 0b0000_0000_0000_0110_0011_0000_0001_1110)]
fn single_block(str: &str, expected: u32) {
if !std::arch::is_x86_feature_detected!("sse2") {
return;
}

let owned_str = str.to_owned();
let input = OwnedBytes::new(&owned_str).unwrap();
let input = OwnedBytes::from(owned_str);
let mut leading_padding = input.leading_padding_len() as u32;
let iter = input.iter_blocks::<_, 32>(&EmptyRecorder);
let mut classifier = Sse2QuoteClassifier32::new(iter);
classifier.next().unwrap().map(|x| x.within_quotes_mask)
let mut classifier = Constructor::new(iter);

// Drop padding-only blocks.
while leading_padding >= 32 {
let mask = classifier.next().unwrap().unwrap().within_quotes_mask;
assert_eq!(mask, 0);
leading_padding -= 32;
}

// The actual classification is now either contained in the next block,
// or split between the two next blocks. Combine them.
let first_mask = classifier.next().unwrap().unwrap().within_quotes_mask;
let len_in_first_mask = if leading_padding == 0 { 0 } else { 32 - leading_padding };
let second_mask = classifier.next().unwrap().unwrap().within_quotes_mask;
let combined_mask = (first_mask >> leading_padding) | (second_mask << len_in_first_mask);

assert_eq!(combined_mask, expected);
}
}
45 changes: 32 additions & 13 deletions crates/rsonpath-lib/src/classification/quotes/sse2_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,28 +46,47 @@ impl BlockSse2Classifier {
}
}

#[cfg(all(test, cfg = "ssse3_64"))]
#[cfg(test)]
mod tests {
use super::Sse2QuoteClassifier64;
use super::{Constructor, QuotesImpl};
use crate::{
input::{Input, OwnedBytes},
result::empty::EmptyRecorder,
FallibleIterator,
};
use test_case::test_case;

#[test_case("" => None)]
#[test_case("abcd" => Some(0))]
#[test_case(r#""abcd""# => Some(0b01_1111))]
#[test_case(r#""number": 42, "string": "something" "# => Some(0b0011_1111_1111_0001_1111_1100_0000_0111_1111))]
#[test_case(r#"abc\"abc\""# => Some(0b00_0000_0000))]
#[test_case(r#"abc\\"abc\\""# => Some(0b0111_1110_0000))]
#[test_case(r#"{"aaa":[{},{"b":{"c":[1,2,3]}}],"e":{"a":[[],[1,2,3],"# => Some(0b0_0000_0000_0000_0110_0011_0000_0000_0000_0110_0011_0000_0001_1110))]
fn single_block(str: &str) -> Option<u64> {
#[test_case("", 0)]
#[test_case("abcd", 0)]
#[test_case(r#""abcd""#, 0b01_1111)]
#[test_case(r#""num": 42, "string": "something" "#, 0b0_0111_1111_1110_0011_1111_1000_0000_1111)]
#[test_case(r#"abc\"abc\""#, 0b00_0000_0000)]
#[test_case(r#"abc\\"abc\\""#, 0b0111_1110_0000)]
#[test_case(r#"{"aaa":[{},{"b":{"c":[1,2,3]}}],"#, 0b0000_0000_0000_0110_0011_0000_0001_1110)]
fn single_block(str: &str, expected: u64) {
if !std::arch::is_x86_feature_detected!("sse2") {
return;
}

let owned_str = str.to_owned();
let input = OwnedBytes::new(&owned_str).unwrap();
let input = OwnedBytes::from(owned_str);
let mut leading_padding = input.leading_padding_len() as u64;
let iter = input.iter_blocks::<_, 64>(&EmptyRecorder);
let mut classifier = Sse2QuoteClassifier64::new(iter);
classifier.next().unwrap().map(|x| x.within_quotes_mask)
let mut classifier = Constructor::new(iter);

// Drop padding-only blocks.
while leading_padding >= 64 {
let mask = classifier.next().unwrap().unwrap().within_quotes_mask;
assert_eq!(mask, 0);
leading_padding -= 64;
}
// The actual classification is now either contained in the next block,
// or split between the two next blocks. Combine them.
let first_mask = classifier.next().unwrap().unwrap().within_quotes_mask;
let len_in_first_mask = if leading_padding == 0 { 0 } else { 64 - leading_padding };
let second_mask = classifier.next().unwrap().unwrap().within_quotes_mask;
let combined_mask = (first_mask >> leading_padding) | (second_mask << len_in_first_mask);

assert_eq!(combined_mask, expected);
}
}
2 changes: 1 addition & 1 deletion crates/rsonpath-lib/src/input/borrowed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Choose this implementation if:
//!
//! 1. You already have the data loaded in-memory and can borrow it while
//! using the engine.
//! using the engine.
//!
//! ## Performance characteristics
//!
Expand Down
2 changes: 1 addition & 1 deletion crates/rsonpath-lib/src/input/buffered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//! Choose this implementation if:
//!
//! 1. You have a [`Read`] source that might contain relatively large amounts
//! of data.
//! of data.
//! 2. You want to run the JSONPath query on the input and then discard it.
//!
//! ## Performance characteristics
Expand Down
8 changes: 4 additions & 4 deletions crates/rsonpath-lib/src/input/mmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
//!
//! 1. Your platform supports memory maps.
//! 2. The input data is in a file or comes from standard input:
//! a) if from a file, then you can guarantee that the file is not going to be modified
//! in or out of process while the input is alive;
//! b) if from stdin, then that the input lives in memory (for example comes via a pipe);
//! input from a tty is not memory-mappable.
//! a) if from a file, then you can guarantee that the file is not going to be modified
//! in or out of process while the input is alive;
//! b) if from stdin, then that the input lives in memory (for example comes via a pipe);
//! input from a tty is not memory-mappable.
//!
//! ## Performance characteristics
//!
Expand Down
2 changes: 1 addition & 1 deletion crates/rsonpath-lib/src/input/owned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//!
//! 1. You already have the data loaded in-memory.
//! 2. You don't want to deal with ownership and would rather have the input
//! take ownership of the bytes.
//! take ownership of the bytes.
//!
//! ## Performance characteristics
//!
Expand Down
1 change: 1 addition & 0 deletions crates/rsonpath-syntax/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ impl ParserBuilder {
/// JSONPath queries are inherently recursive, since
/// - [`LogicalExpr`] can be an arbitrarily deep tree of AND/OR operators;
/// - the [`TestExpr`] in a filter can test arbitrary nested JSONPath queries.
///
/// Our parser implementation is recursive, so an excessively nested query could overflow the stack.
///
/// The limit can be relaxed here, or removed entirely by passing [`None`].
Expand Down
Loading

0 comments on commit b4c4ec8

Please sign in to comment.