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}