Skip to content

Commit 37e9076

Browse files
azoyanIvan Azoyan
and
Ivan Azoyan
authored
feat: make MainEngine Send and Sync
Changed `Rc` to `Arc` in the automaton labels. Added static_assert that MainEngine implements Send+Sync --------- Co-authored-by: Ivan Azoyan <[email protected]>
1 parent 2c14906 commit 37e9076

File tree

6 files changed

+43
-39
lines changed

6 files changed

+43
-39
lines changed

crates/rsonpath-lib/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,4 @@ path = "examples/approx_spans_usage.rs"
5454
doc-scrape-examples = true
5555

5656
[lints]
57-
workspace = true
57+
workspace = true

crates/rsonpath-lib/src/automaton.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,20 @@ use crate::{automaton::error::CompilerError, debug, string_pattern::StringPatter
1212
use nfa::NondeterministicAutomaton;
1313
use rsonpath_syntax::{num::JsonUInt, JsonPathQuery};
1414
use smallvec::SmallVec;
15-
use std::{fmt::Display, ops::Index, rc::Rc};
15+
use std::{fmt::Display, ops::Index, sync::Arc};
1616

1717
/// A minimal, deterministic automaton representing a JSONPath query.
18-
#[derive(Debug, PartialEq, Eq)]
18+
#[derive(Clone, Debug, PartialEq, Eq)]
1919
pub struct Automaton {
2020
states: Vec<StateTable>,
2121
}
2222

2323
/// Transition when a JSON member name matches a [`StringPattern`].
24-
pub type MemberTransition = (Rc<StringPattern>, State);
24+
pub type MemberTransition = (Arc<StringPattern>, State);
2525

2626
/// Transition on elements of an array with indices specified by either a single index
2727
/// or a simple slice expression.
28-
#[derive(Debug, PartialEq, Eq)]
28+
#[derive(Clone, Debug, PartialEq, Eq)]
2929
pub struct ArrayTransition {
3030
label: ArrayTransitionLabel,
3131
target: State,
@@ -44,7 +44,7 @@ pub(super) enum ArrayTransitionLabel {
4444
///
4545
/// Contains transitions triggered by matching member names or array indices, and a fallback transition
4646
/// triggered when none of the labelled transitions match.
47-
#[derive(Debug)]
47+
#[derive(Debug, Clone)]
4848
pub struct StateTable {
4949
attributes: StateAttributes,
5050
member_transitions: SmallVec<[MemberTransition; 2]>,

crates/rsonpath-lib/src/automaton/minimizer.rs

+22-22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Determinization and minimization of an NFA into the final DFA used by the engines.
22
3-
use std::rc::Rc;
3+
use std::sync::Arc;
44

55
// NOTE: Some comments in this module are outdated, because the minimizer doesn't
66
// actually produce minimal automata as of now - see #91.
@@ -50,7 +50,7 @@ pub(super) struct Minimizer {
5050
#[derive(Debug)]
5151
struct SuperstateTransitionTable {
5252
array: ArrayTransitionSet,
53-
member: VecMap<Rc<StringPattern>, SmallSet256>,
53+
member: VecMap<Arc<StringPattern>, SmallSet256>,
5454
wildcard: SmallSet256,
5555
}
5656

@@ -177,7 +177,7 @@ impl Minimizer {
177177
&self,
178178
id: DfaStateId,
179179
array_transitions: &[ArrayTransition],
180-
member_transitions: &[(Rc<StringPattern>, DfaStateId)],
180+
member_transitions: &[(Arc<StringPattern>, DfaStateId)],
181181
fallback: DfaStateId,
182182
) -> StateAttributes {
183183
let mut attrs = StateAttributesBuilder::new();
@@ -554,8 +554,8 @@ mod tests {
554554
#[test]
555555
fn interstitial_descendant_wildcard() {
556556
// Query = $..a.b..*.a..b
557-
let label_a = Rc::new(StringPattern::new(&JsonString::new("a")));
558-
let label_b = Rc::new(StringPattern::new(&JsonString::new("b")));
557+
let label_a = Arc::new(StringPattern::new(&JsonString::new("a")));
558+
let label_b = Arc::new(StringPattern::new(&JsonString::new("b")));
559559

560560
let nfa = NondeterministicAutomaton {
561561
ordered_states: vec![
@@ -623,8 +623,8 @@ mod tests {
623623
#[test]
624624
fn interstitial_nondescendant_wildcard() {
625625
// Query = $..a.b.*.a..b
626-
let label_a = Rc::new(StringPattern::new(&JsonString::new("a")));
627-
let label_b = Rc::new(StringPattern::new(&JsonString::new("b")));
626+
let label_a = Arc::new(StringPattern::new(&JsonString::new("a")));
627+
let label_b = Arc::new(StringPattern::new(&JsonString::new("b")));
628628

629629
let nfa = NondeterministicAutomaton {
630630
ordered_states: vec![
@@ -698,7 +698,7 @@ mod tests {
698698
#[test]
699699
fn simple_multi_accepting() {
700700
// Query = $..a.*
701-
let label = Rc::new(StringPattern::new(&JsonString::new("a")));
701+
let label = Arc::new(StringPattern::new(&JsonString::new("a")));
702702

703703
let nfa = NondeterministicAutomaton {
704704
ordered_states: vec![
@@ -796,7 +796,7 @@ mod tests {
796796
#[test]
797797
fn chained_wildcard_children() {
798798
// Query = $.a.*.*.*
799-
let label = Rc::new(StringPattern::new(&JsonString::new("a")));
799+
let label = Arc::new(StringPattern::new(&JsonString::new("a")));
800800

801801
let nfa = NondeterministicAutomaton {
802802
ordered_states: vec![
@@ -857,7 +857,7 @@ mod tests {
857857
#[test]
858858
fn chained_wildcard_children_after_descendant() {
859859
// Query = $..a.*.*
860-
let label = Rc::new(StringPattern::new(&JsonString::new("a")));
860+
let label = Arc::new(StringPattern::new(&JsonString::new("a")));
861861

862862
let nfa = NondeterministicAutomaton {
863863
ordered_states: vec![
@@ -935,11 +935,11 @@ mod tests {
935935
#[test]
936936
fn child_and_descendant() {
937937
// Query = $.x..a.b.a.b.c..d
938-
let label_a = Rc::new(StringPattern::new(&JsonString::new("a")));
939-
let label_b = Rc::new(StringPattern::new(&JsonString::new("b")));
940-
let label_c = Rc::new(StringPattern::new(&JsonString::new("c")));
941-
let label_d = Rc::new(StringPattern::new(&JsonString::new("d")));
942-
let label_x = Rc::new(StringPattern::new(&JsonString::new("x")));
938+
let label_a = Arc::new(StringPattern::new(&JsonString::new("a")));
939+
let label_b = Arc::new(StringPattern::new(&JsonString::new("b")));
940+
let label_c = Arc::new(StringPattern::new(&JsonString::new("c")));
941+
let label_d = Arc::new(StringPattern::new(&JsonString::new("d")));
942+
let label_x = Arc::new(StringPattern::new(&JsonString::new("x")));
943943

944944
let nfa = NondeterministicAutomaton {
945945
ordered_states: vec![
@@ -1021,9 +1021,9 @@ mod tests {
10211021
#[test]
10221022
fn child_descendant_and_child_wildcard() {
10231023
// Query = $.x.*..a.*.b
1024-
let label_a = Rc::new(StringPattern::new(&JsonString::new("a")));
1025-
let label_b = Rc::new(StringPattern::new(&JsonString::new("b")));
1026-
let label_x = Rc::new(StringPattern::new(&JsonString::new("x")));
1024+
let label_a = Arc::new(StringPattern::new(&JsonString::new("a")));
1025+
let label_b = Arc::new(StringPattern::new(&JsonString::new("b")));
1026+
let label_x = Arc::new(StringPattern::new(&JsonString::new("x")));
10271027

10281028
let nfa = NondeterministicAutomaton {
10291029
ordered_states: vec![
@@ -1103,10 +1103,10 @@ mod tests {
11031103
#[test]
11041104
fn all_name_and_wildcard_selectors() {
11051105
// Query = $.a.b..c..d.*..*
1106-
let label_a = Rc::new(StringPattern::new(&JsonString::new("a")));
1107-
let label_b = Rc::new(StringPattern::new(&JsonString::new("b")));
1108-
let label_c = Rc::new(StringPattern::new(&JsonString::new("c")));
1109-
let label_d = Rc::new(StringPattern::new(&JsonString::new("d")));
1106+
let label_a = Arc::new(StringPattern::new(&JsonString::new("a")));
1107+
let label_b = Arc::new(StringPattern::new(&JsonString::new("b")));
1108+
let label_c = Arc::new(StringPattern::new(&JsonString::new("c")));
1109+
let label_d = Arc::new(StringPattern::new(&JsonString::new("d")));
11101110

11111111
let nfa = NondeterministicAutomaton {
11121112
ordered_states: vec![

crates/rsonpath-lib/src/automaton/nfa.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{automaton::SimpleSlice, error::UnsupportedFeatureError, string_patte
55

66
use super::{error::CompilerError, ArrayTransitionLabel};
77
use rsonpath_syntax::{str::JsonString, JsonPathQuery, Step};
8-
use std::{collections::HashMap, fmt::Display, ops::Index, rc::Rc};
8+
use std::{collections::HashMap, fmt::Display, ops::Index, sync::Arc};
99

1010
/// An NFA representing a query. It is always a directed path
1111
/// from an initial state to the unique accepting state at the end,
@@ -34,7 +34,7 @@ pub(super) enum Transition {
3434
/// A transition matching array indices.
3535
Array(ArrayTransitionLabel),
3636
/// A transition matching a specific member.
37-
Member(Rc<StringPattern>),
37+
Member(Arc<StringPattern>),
3838
/// A transition matching anything.
3939
Wildcard,
4040
}
@@ -71,7 +71,7 @@ impl NondeterministicAutomaton {
7171
use rsonpath_syntax::{Index, Selector};
7272
use std::collections::hash_map::Entry;
7373

74-
let mut string_pattern_cache: HashMap<&'q JsonString, Rc<StringPattern>> = HashMap::new();
74+
let mut string_pattern_cache: HashMap<&'q JsonString, Arc<StringPattern>> = HashMap::new();
7575

7676
let states_result: Result<Vec<NfaState>, CompilerError> = query
7777
.segments()
@@ -87,7 +87,7 @@ impl NondeterministicAutomaton {
8787
let pattern = match string_pattern_cache.entry(name) {
8888
Entry::Occupied(pat) => pat.get().clone(),
8989
Entry::Vacant(entry) => {
90-
let pat = Rc::new(StringPattern::new(name));
90+
let pat = Arc::new(StringPattern::new(name));
9191
entry.insert(pat.clone());
9292
pat
9393
}
@@ -242,10 +242,10 @@ mod tests {
242242

243243
let expected_automaton = NondeterministicAutomaton {
244244
ordered_states: vec![
245-
NfaState::Direct(Transition::Member(Rc::new(StringPattern::new(&label_a)))),
246-
NfaState::Direct(Transition::Member(Rc::new(StringPattern::new(&label_b)))),
247-
NfaState::Recursive(Transition::Member(Rc::new(StringPattern::new(&label_c)))),
248-
NfaState::Recursive(Transition::Member(Rc::new(StringPattern::new(&label_d)))),
245+
NfaState::Direct(Transition::Member(Arc::new(StringPattern::new(&label_a)))),
246+
NfaState::Direct(Transition::Member(Arc::new(StringPattern::new(&label_b)))),
247+
NfaState::Recursive(Transition::Member(Arc::new(StringPattern::new(&label_c)))),
248+
NfaState::Recursive(Transition::Member(Arc::new(StringPattern::new(&label_d)))),
249249
NfaState::Direct(Transition::Wildcard),
250250
NfaState::Direct(Transition::Wildcard),
251251
NfaState::Recursive(Transition::Wildcard),

crates/rsonpath-lib/src/engine/head_skipping.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//! Engine decorator that performs **head skipping** &ndash; an extremely optimized search for
22
//! the first matching member name in a query starting with a self-looping state.
33
//! This happens in queries starting with a descendant selector.
4-
use std::rc::Rc;
4+
5+
use std::sync::Arc;
56

67
use crate::{
78
automaton::{Automaton, State},
@@ -67,7 +68,7 @@ pub(super) struct HeadSkip<'b, I, V, const N: usize> {
6768
bytes: &'b I,
6869
state: State,
6970
is_accepting: bool,
70-
member_name: Rc<StringPattern>,
71+
member_name: Arc<StringPattern>,
7172
simd: V,
7273
}
7374

crates/rsonpath-lib/src/engine/main.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,15 @@ use smallvec::{smallvec, SmallVec};
6969
///
7070
/// The engine is stateless, meaning that it can be executed
7171
/// on any number of separate inputs, even on separate threads.
72-
#[derive(Debug)]
72+
73+
#[derive(Clone, Debug)]
7374
pub struct MainEngine {
7475
automaton: Automaton,
7576
simd: SimdConfiguration,
7677
}
7778

79+
static_assertions::assert_impl_all!(MainEngine: Send, Sync);
80+
7881
impl Compiler for MainEngine {
7982
type E = Self;
8083

0 commit comments

Comments
 (0)