rsonpath/
engine.rs

1//! Base traits for different implementations of JSONPath execution engines.
2//!
3//! Defines the [`Engine`] trait that provides different ways of retrieving
4//! query results from input bytes, as well as [`Compiler`] which provides
5//! a standalone entry point for compiling a [`JsonPathQuery`] into an [`Engine`].
6pub mod error;
7mod head_skipping;
8pub mod main;
9mod select_root_query;
10#[cfg(feature = "serde")]
11mod serde;
12mod tail_skipping;
13pub use main::MainEngine as RsonpathEngine;
14
15use self::error::EngineError;
16use crate::{
17    automaton::{error::CompilerError, Automaton},
18    input::Input,
19    result::{Match, MatchCount, MatchIndex, MatchSpan, Sink},
20};
21use rsonpath_syntax::JsonPathQuery;
22
23/// An engine that can run its query on a given input.
24pub trait Engine {
25    /// Find the number of matches on the given [`Input`].
26    ///
27    /// The result is equivalent to using [`matches`](Engine::matches) and counting the matches,
28    /// but in general is much more time and memory efficient.
29    ///
30    /// # Errors
31    /// An appropriate [`EngineError`] is returned if the JSON input is malformed
32    /// and the syntax error is detected.
33    ///
34    /// **Please note** that detecting malformed JSONs is not guaranteed.
35    /// Some glaring errors like mismatched braces or double quotes are raised,
36    /// but in general **the result of an engine run on an invalid JSON is undefined**.
37    /// It _is_ guaranteed that the computation terminates and does not panic.
38    fn count<I>(&self, input: &I) -> Result<MatchCount, EngineError>
39    where
40        I: Input;
41
42    /// Find the starting indices of matches on the given [`Input`] and write them to the [`Sink`].
43    ///
44    /// The result is equivalent to using [`matches`](Engine::matches) and extracting the
45    /// [`Match::span.start_idx`],
46    /// but in general is much more time and memory efficient.
47    ///
48    /// # Errors
49    /// An appropriate [`EngineError`] is returned if the JSON input is malformed
50    /// and the syntax error is detected.
51    ///
52    /// **Please note** that detecting malformed JSONs is not guaranteed.
53    /// Some glaring errors like mismatched braces or double quotes are raised,
54    /// but in general **the result of an engine run on an invalid JSON is undefined**.
55    /// It _is_ guaranteed that the computation terminates and does not panic.
56    fn indices<I, S>(&self, input: &I, sink: &mut S) -> Result<(), EngineError>
57    where
58        I: Input,
59        S: Sink<MatchIndex>;
60
61    /// Find the approximate spans of matches on the given [`Input`] and write them to the [`Sink`].
62    ///
63    /// "Approximate" means that the ends of spans are not guaranteed to be located exactly at the end of a match,
64    /// but may include trailing whitespace. **Importantly**, it may be beyond the rigidly-defined length of the
65    /// input, as the engine is allowed to pad the input with whitespace to help with processing. For the purposes
66    /// of this API, it is assumed that every character after the logical end of the input is a whitespace character.
67    /// With that in mind, it is guaranteed that:
68    /// 1. the span start is exact;
69    /// 2. the span encompasses the entire matched value;
70    /// 3. the only characters included after the value are JSON whitespace characters:
71    ///    space (0x20), horizontal tab (0x09), new line (0x0A), carriage return (0x0D).
72    ///
73    /// # Errors
74    /// An appropriate [`EngineError`] is returned if the JSON input is malformed
75    /// and the syntax error is detected.
76    ///
77    /// **Please note** that detecting malformed JSONs is not guaranteed.
78    /// Some glaring errors like mismatched braces or double quotes are raised,
79    /// but in general **the result of an engine run on an invalid JSON is undefined**.
80    /// It _is_ guaranteed that the computation terminates and does not panic.
81    fn approximate_spans<I, S>(&self, input: &I, sink: &mut S) -> Result<(), EngineError>
82    where
83        I: Input,
84        S: Sink<MatchSpan>;
85
86    /// Find all matches on the given [`Input`] and write them to the [`Sink`].
87    ///
88    /// # Errors
89    /// An appropriate [`EngineError`] is returned if the JSON input is malformed
90    /// and the syntax error is detected.
91    ///
92    /// **Please note** that detecting malformed JSONs is not guaranteed.
93    /// Some glaring errors like mismatched braces or double quotes are raised,
94    /// but in general **the result of an engine run on an invalid JSON is undefined**.
95    /// It _is_ guaranteed that the computation terminates and does not panic.
96    fn matches<I, S>(&self, input: &I, sink: &mut S) -> Result<(), EngineError>
97    where
98        I: Input,
99        S: Sink<Match>;
100}
101
102/// An engine that can be created by compiling a [`JsonPathQuery`].
103pub trait Compiler {
104    /// Concrete type of the [`Engines`](`Engine`) created,
105    /// parameterized with the lifetime of the input query.
106    type E: Engine;
107
108    /// Compile a [`JsonPathQuery`] into an [`Engine`].c
109    ///
110    /// # Errors
111    /// An appropriate [`CompilerError`] is returned if the compiler
112    /// cannot handle the query.
113    fn compile_query(query: &JsonPathQuery) -> Result<Self::E, CompilerError>;
114
115    /// Turn a compiled [`Automaton`] into an [`Engine`].
116    fn from_compiled_query(automaton: Automaton) -> Self::E;
117}