Skip to content

Commit

Permalink
First jab at atomic roots fix.
Browse files Browse the repository at this point in the history
  • Loading branch information
V0ldek committed Sep 21, 2023
1 parent 1fd5a8f commit 4b9400c
Show file tree
Hide file tree
Showing 13 changed files with 5,304 additions and 30 deletions.
49 changes: 23 additions & 26 deletions crates/rsonpath-lib/src/engine/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,34 +148,31 @@ where
I: Input + 'i,
R: Recorder<I::Block<'i, BLOCK_SIZE>>,
{
simd_dispatch!(simd => |simd|
{
let iter = input.iter_blocks(recorder);
let quote_classifier = simd.classify_quoted_sequences(iter);
let mut block_event_source = simd.classify_structural_characters(quote_classifier);

let last_event = block_event_source.next()?;
if let Some(Structural::Opening(_, idx)) = last_event {
let mut depth = Depth::ONE;
recorder.record_match(idx, depth, MatchedNodeType::Complex)?;

while let Some(ev) = block_event_source.next()? {
match ev {
Structural::Closing(_, idx) => {
recorder.record_value_terminator(idx, depth)?;
depth.decrement().map_err(|err| EngineError::DepthBelowZero(idx, err))?;
}
Structural::Colon(_) => (),
Structural::Opening(_, idx) => {
depth
.increment()
.map_err(|err| EngineError::DepthAboveLimit(idx, err))?;
}
Structural::Comma(idx) => recorder.record_value_terminator(idx, depth)?,
let mut iter = input.iter_blocks(recorder);
let mut idx = 0;

loop {
match iter.next()? {
Some(block) => {
let pos = block.iter().position(|&x| x != b' ' && x != b'\n' && x != b'\t' && x != b'\r');
match pos {
Some(in_block_idx) => {
recorder.record_match(idx + in_block_idx, Depth::ONE, MatchedNodeType::Atomic)?;
idx += BLOCK_SIZE;
break;
},
None => idx += BLOCK_SIZE,
}
}
},
None => return Ok(()),
}
});
}

while (iter.next()?).is_some() {
idx += BLOCK_SIZE;
}

recorder.record_value_terminator(idx - 1, Depth::ONE)?;

Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion crates/rsonpath-lib/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ pub(super) mod in_slice {

#[inline]
pub(super) fn pad_last_block(bytes: &[u8]) -> LastBlock {
let mut last_block_buf = [0; MAX_BLOCK_SIZE];
let mut last_block_buf = [b' '; MAX_BLOCK_SIZE];
let last_block_start = (bytes.len() / MAX_BLOCK_SIZE) * MAX_BLOCK_SIZE;
let last_block_slice = &bytes[last_block_start..];

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 @@ -74,7 +74,7 @@ impl<R: Read> InternalBuffer<R> {
}

if self.chunk_idx == self.bytes.len() {
self.bytes.push(BufferedChunk([0; BUF_SIZE]));
self.bytes.push(BufferedChunk([b' '; BUF_SIZE]));
}

let buf = &mut self.bytes[self.chunk_idx].0;
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 @@ -116,7 +116,7 @@ impl OwnedBytes {
// SAFETY:
unsafe {
ptr::copy_nonoverlapping(slice.as_ptr(), ptr.as_ptr(), slice.len());
ptr::write_bytes(ptr.as_ptr().add(slice.len()), 0, pad);
ptr::write_bytes(ptr.as_ptr().add(slice.len()), b' ', pad);
};

// SAFETY: At this point we allocated and initialized exactly `size` bytes.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Define the JSON input for all query test cases.
[input]
# Short description of the input structure.
description = "The root is an empty string."
# Set to true only if your specific test input is fully compressed (no extraneous whitespace).
is_compressed = true

# Inline JSON document.
[input.source]
json_string = '""'

# Define queries to test on the input.
[[queries]]
# Valid JSONPath query string.
query = "$"
# Short descritpion of the query semantics.
description = "select the root"

[queries.results]
# Number of expected matches.
count = 1
# Byte locations of spans of all matches, in order.
spans = [[0, 2]]
# Stringified values of all matches, verbatim as in the input,
# in the same order as above.
nodes = ['""']

[[queries]]
query = "$..*"
description = "select all subdocuments of which there are none"

[queries.results]
count = 0
spans = []
nodes = []

[[queries]]
query = '$[""]'
description = "look for an empty key which should not match the root"

[queries.results]
count = 0
spans = []
nodes = []
35 changes: 35 additions & 0 deletions crates/rsonpath-lib/tests/documents/toml/atomic_root_false.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Define the JSON input for all query test cases.
[input]
# Short description of the input structure.
description = "The root is the atomic value false."
# Set to true only if your specific test input is fully compressed (no extraneous whitespace).
is_compressed = true

# Inline JSON document.
[input.source]
json_string = "false"

# Define queries to test on the input.
[[queries]]
# Valid JSONPath query string.
query = "$"
# Short descritpion of the query semantics.
description = "select the root"

[queries.results]
# Number of expected matches.
count = 1
# Byte locations of spans of all matches, in order.
spans = [[0, 5]]
# Stringified values of all matches, verbatim as in the input,
# in the same order as above.
nodes = ["false"]

[[queries]]
query = "$..*"
description = "select all subdocuments of which there are none"

[queries.results]
count = 0
spans = []
nodes = []
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Define the JSON input for all query test cases.
[input]
# Short description of the input structure.
description = "The root is a non-empty string."
# Set to true only if your specific test input is fully compressed (no extraneous whitespace).
is_compressed = true

# Inline JSON document.
[input.source]
json_string = '"some string"'

# Define queries to test on the input.
[[queries]]
# Valid JSONPath query string.
query = "$"
# Short descritpion of the query semantics.
description = "select the root"

[queries.results]
# Number of expected matches.
count = 1
# Byte locations of spans of all matches, in order.
spans = [[0, 13]]
# Stringified values of all matches, verbatim as in the input,
# in the same order as above.
nodes = ['"some string"']

[[queries]]
query = "$..*"
description = "select all subdocuments of which there are none"

[queries.results]
count = 0
spans = []
nodes = []

[[queries]]
query = '$["some string"]'
description = "look for the key equal to the root value, which should not match"

[queries.results]
count = 0
spans = []
nodes = []
35 changes: 35 additions & 0 deletions crates/rsonpath-lib/tests/documents/toml/atomic_root_null.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Define the JSON input for all query test cases.
[input]
# Short description of the input structure.
description = "The root is the atomic value null."
# Set to true only if your specific test input is fully compressed (no extraneous whitespace).
is_compressed = true

# Inline JSON document.
[input.source]
json_string = "null"

# Define queries to test on the input.
[[queries]]
# Valid JSONPath query string.
query = "$"
# Short descritpion of the query semantics.
description = "select the root"

[queries.results]
# Number of expected matches.
count = 1
# Byte locations of spans of all matches, in order.
spans = [[0, 4]]
# Stringified values of all matches, verbatim as in the input,
# in the same order as above.
nodes = ["null"]

[[queries]]
query = "$..*"
description = "select all subdocuments of which there are none"

[queries.results]
count = 0
spans = []
nodes = []
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Define the JSON input for all query test cases.
[input]
# Short description of the input structure.
description = "The root is an atomic floating-point number."
# Set to true only if your specific test input is fully compressed (no extraneous whitespace).
is_compressed = true

# Inline JSON document.
[input.source]
json_string = "123456789.1337"

# Define queries to test on the input.
[[queries]]
# Valid JSONPath query string.
query = "$"
# Short descritpion of the query semantics.
description = "select the root"

[queries.results]
# Number of expected matches.
count = 1
# Byte locations of spans of all matches, in order.
spans = [[0, 14]]
# Stringified values of all matches, verbatim as in the input,
# in the same order as above.
nodes = ["123456789.1337"]

[[queries]]
query = "$..*"
description = "select all subdocuments of which there are none"

[queries.results]
count = 0
spans = []
nodes = []
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Define the JSON input for all query test cases.
[input]
# Short description of the input structure.
description = "The root is an atomic integral number."
# Set to true only if your specific test input is fully compressed (no extraneous whitespace).
is_compressed = true

# Inline JSON document.
[input.source]
json_string = "123456789"

# Define queries to test on the input.
[[queries]]
# Valid JSONPath query string.
query = "$"
# Short descritpion of the query semantics.
description = "select the root"

[queries.results]
# Number of expected matches.
count = 1
# Byte locations of spans of all matches, in order.
spans = [[0, 9]]
# Stringified values of all matches, verbatim as in the input,
# in the same order as above.
nodes = ["123456789"]

[[queries]]
query = "$..*"
description = "select all subdocuments of which there are none"

[queries.results]
count = 0
spans = []
nodes = []
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Define the JSON input for all query test cases.
[input]
# Short description of the input structure.
description = "The root is an atomic floating-point number in scientific notation."
# Set to true only if your specific test input is fully compressed (no extraneous whitespace).
is_compressed = true

# Inline JSON document.
[input.source]
json_string = "123456789.1337e-25"

# Define queries to test on the input.
[[queries]]
# Valid JSONPath query string.
query = "$"
# Short descritpion of the query semantics.
description = "select the root"

[queries.results]
# Number of expected matches.
count = 1
# Byte locations of spans of all matches, in order.
spans = [[0, 18]]
# Stringified values of all matches, verbatim as in the input,
# in the same order as above.
nodes = ["123456789.1337e-25"]

[[queries]]
query = "$..*"
description = "select all subdocuments of which there are none"

[queries.results]
count = 0
spans = []
nodes = []
35 changes: 35 additions & 0 deletions crates/rsonpath-lib/tests/documents/toml/atomic_root_true.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Define the JSON input for all query test cases.
[input]
# Short description of the input structure.
description = "The root is the atomic value true."
# Set to true only if your specific test input is fully compressed (no extraneous whitespace).
is_compressed = true

# Inline JSON document.
[input.source]
json_string = "true"

# Define queries to test on the input.
[[queries]]
# Valid JSONPath query string.
query = "$"
# Short descritpion of the query semantics.
description = "select the root"

[queries.results]
# Number of expected matches.
count = 1
# Byte locations of spans of all matches, in order.
spans = [[0, 4]]
# Stringified values of all matches, verbatim as in the input,
# in the same order as above.
nodes = ["true"]

[[queries]]
query = "$..*"
description = "select all subdocuments of which there are none"

[queries.results]
count = 0
spans = []
nodes = []
Loading

0 comments on commit 4b9400c

Please sign in to comment.