@@ -19,79 +19,10 @@ pub struct Automaton<'q> {
19
19
states : Vec < StateTable < ' q > > ,
20
20
}
21
21
22
- /// Represent the distinct methods of moving on a match between states.
23
- #[ derive( Debug , Copy , PartialEq , Clone , Eq ) ]
24
- pub enum TransitionLabel < ' q > {
25
- /// Transition when a JSON member name matches a [`JsonString`]i.
26
- ObjectMember ( & ' q JsonString ) ,
27
- /// Transition on the n-th element of an array, with n specified by a [`JsonUInt`].
28
- ArrayIndex ( JsonUInt ) ,
29
- }
30
-
31
- impl < ' q > TransitionLabel < ' q > {
32
- ///Return the textual [`JsonString`] being wrapped if so. Returns [`None`] otherwise.
33
- #[ must_use]
34
- #[ inline( always) ]
35
- pub fn get_member_name ( & self ) -> Option < & ' q JsonString > {
36
- match self {
37
- TransitionLabel :: ObjectMember ( name) => Some ( name) ,
38
- TransitionLabel :: ArrayIndex ( _) => None ,
39
- }
40
- }
41
-
42
- ///Return the [`JsonUInt`] being wrapped if so. Returns [`None`] otherwise.
43
- #[ must_use]
44
- #[ inline( always) ]
45
- pub fn get_array_index ( & ' q self ) -> Option < & ' q JsonUInt > {
46
- match self {
47
- TransitionLabel :: ArrayIndex ( name) => Some ( name) ,
48
- TransitionLabel :: ObjectMember ( _) => None ,
49
- }
50
- }
51
-
52
- /// Wraps a [`JsonString`] in a [`TransitionLabel`].
53
- #[ must_use]
54
- #[ inline( always) ]
55
- pub fn new_object_member ( member_name : & ' q JsonString ) -> Self {
56
- TransitionLabel :: ObjectMember ( member_name)
57
- }
58
-
59
- /// Wraps a [`JsonUInt`] in a [`TransitionLabel`].
60
- #[ must_use]
61
- #[ inline( always) ]
62
- pub fn new_array_index ( index : JsonUInt ) -> Self {
63
- TransitionLabel :: ArrayIndex ( index)
64
- }
65
- }
66
-
67
- impl < ' q > From < & ' q JsonString > for TransitionLabel < ' q > {
68
- #[ must_use]
69
- #[ inline( always) ]
70
- fn from ( member_name : & ' q JsonString ) -> Self {
71
- TransitionLabel :: new_object_member ( member_name)
72
- }
73
- }
74
-
75
- impl Display for TransitionLabel < ' _ > {
76
- #[ inline( always) ]
77
- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
78
- match self {
79
- TransitionLabel :: ObjectMember ( name) => write ! ( f, "{}" , name. unquoted( ) ) ,
80
- TransitionLabel :: ArrayIndex ( index) => write ! ( f, "{}" , index. as_u64( ) ) ,
81
- }
82
- }
83
- }
84
-
85
- impl From < JsonUInt > for TransitionLabel < ' _ > {
86
- #[ must_use]
87
- #[ inline( always) ]
88
- fn from ( index : JsonUInt ) -> Self {
89
- TransitionLabel :: new_array_index ( index)
90
- }
91
- }
92
-
93
- /// A single transition of an [`Automaton`].
94
- type Transition < ' q > = ( TransitionLabel < ' q > , State ) ;
22
+ /// Transition when a JSON member name matches a [`JsonString`]i.
23
+ pub type MemberTransition < ' q > = ( & ' q JsonString , State ) ;
24
+ /// Transition on the n-th element of an array, with n specified by a [`JsonUInt`].
25
+ pub type ArrayTransition < ' q > = ( JsonUInt , State ) ;
95
26
96
27
/// A transition table of a single [`State`] of an [`Automaton`].
97
28
///
@@ -100,7 +31,8 @@ type Transition<'q> = (TransitionLabel<'q>, State);
100
31
#[ derive( Debug ) ]
101
32
pub struct StateTable < ' q > {
102
33
attributes : StateAttributes ,
103
- transitions : SmallVec < [ Transition < ' q > ; 2 ] > ,
34
+ member_transitions : SmallVec < [ MemberTransition < ' q > ; 2 ] > ,
35
+ array_transitions : SmallVec < [ ArrayTransition < ' q > ; 2 ] > ,
104
36
fallback_state : State ,
105
37
}
106
38
@@ -109,7 +41,8 @@ impl<'q> Default for StateTable<'q> {
109
41
fn default ( ) -> Self {
110
42
Self {
111
43
attributes : StateAttributes :: default ( ) ,
112
- transitions : Default :: default ( ) ,
44
+ member_transitions : SmallVec :: default ( ) ,
45
+ array_transitions : SmallVec :: default ( ) ,
113
46
fallback_state : State ( 0 ) ,
114
47
}
115
48
}
@@ -118,11 +51,17 @@ impl<'q> Default for StateTable<'q> {
118
51
impl < ' q > PartialEq for StateTable < ' q > {
119
52
#[ inline]
120
53
fn eq ( & self , other : & Self ) -> bool {
121
- self . fallback_state == other. fallback_state
122
- && self . transitions . len ( ) == other. transitions . len ( )
123
- && self . transitions . iter ( ) . all ( |x| other. transitions . contains ( x) )
124
- && other. transitions . iter ( ) . all ( |x| self . transitions . contains ( x) )
125
- && self . attributes == other. attributes
54
+ return self . fallback_state == other. fallback_state
55
+ && set_eq ( & self . array_transitions , & other. array_transitions )
56
+ && set_eq ( & self . member_transitions , & other. member_transitions )
57
+ && self . attributes == other. attributes ;
58
+
59
+ #[ inline( always) ]
60
+ fn set_eq < T : Eq , A : smallvec:: Array < Item = T > > ( left : & SmallVec < A > , right : & SmallVec < A > ) -> bool {
61
+ left. len ( ) == right. len ( )
62
+ && left. iter ( ) . all ( |x| right. contains ( x) )
63
+ && right. iter ( ) . all ( |x| left. contains ( x) )
64
+ }
126
65
}
127
66
}
128
67
@@ -209,7 +148,7 @@ impl<'q> Automaton<'q> {
209
148
/// # use rsonpath::automaton::*;
210
149
/// let query = rsonpath_syntax::parse("$.a").unwrap();
211
150
/// let automaton = Automaton::new(&query).unwrap();
212
- /// let state_2 = automaton[automaton.initial_state()].transitions ()[0].1;
151
+ /// let state_2 = automaton[automaton.initial_state()].member_transitions ()[0].1;
213
152
///
214
153
/// assert!(automaton.is_accepting(state_2));
215
154
/// ```
@@ -233,30 +172,7 @@ impl<'q> Automaton<'q> {
233
172
#[ must_use]
234
173
#[ inline( always) ]
235
174
pub fn has_any_array_item_transition ( & self , state : State ) -> bool {
236
- self [ state]
237
- . transitions ( )
238
- . iter ( )
239
- . any ( |t| matches ! ( t, ( TransitionLabel :: ArrayIndex ( _) , _) ) )
240
- }
241
-
242
- /// Returns whether the given state is accepting an item in a list.
243
- ///
244
- /// # Example
245
- /// ```rust
246
- /// # use rsonpath::automaton::*;
247
- /// let query = rsonpath_syntax::parse("$[2]").unwrap();
248
- /// let automaton = Automaton::new(&query).unwrap();
249
- /// let state = automaton.initial_state();
250
- ///
251
- /// assert!(automaton.has_any_array_item_transition_to_accepting(state));
252
- /// ```
253
- #[ must_use]
254
- #[ inline( always) ]
255
- pub fn has_any_array_item_transition_to_accepting ( & self , state : State ) -> bool {
256
- self [ state] . transitions ( ) . iter ( ) . any ( |t| match t {
257
- ( TransitionLabel :: ArrayIndex ( _) , s) => self . is_accepting ( * s) ,
258
- _ => false ,
259
- } )
175
+ self [ state] . attributes . has_array_index_transition ( )
260
176
}
261
177
262
178
/// Returns whether the given state is accepting the first item in a list.
@@ -302,10 +218,12 @@ impl<'q> Automaton<'q> {
302
218
#[ must_use]
303
219
#[ inline( always) ]
304
220
pub fn has_array_index_transition_to_accepting ( & self , state : State , match_index : & JsonUInt ) -> bool {
305
- self [ state] . transitions ( ) . iter ( ) . any ( |t| match t {
306
- ( TransitionLabel :: ArrayIndex ( i) , s) => i. eq ( match_index) && self . is_accepting ( * s) ,
307
- _ => false ,
308
- } )
221
+ let state = & self [ state] ;
222
+ state. attributes . has_array_index_transition_to_accepting ( )
223
+ && state
224
+ . array_transitions ( )
225
+ . iter ( )
226
+ . any ( |( i, s) | i. eq ( match_index) && self . is_accepting ( * s) )
309
227
}
310
228
311
229
/// Returns whether the given state has any transitions
@@ -379,14 +297,24 @@ impl<'q> StateTable<'q> {
379
297
self . fallback_state
380
298
}
381
299
382
- /// Returns the collection of labelled transitions from this state.
300
+ /// Returns the collection of labelled array transitions from this state.
383
301
///
384
- /// A transition is triggered if the [`TransitionLabel `] is matched and leads
302
+ /// A transition is triggered if the [`ArrayTransition `] is matched and leads
385
303
/// to the contained [`State`].
386
304
#[ must_use]
387
305
#[ inline( always) ]
388
- pub fn transitions ( & self ) -> & [ Transition < ' q > ] {
389
- & self . transitions
306
+ pub fn array_transitions ( & self ) -> & [ ArrayTransition < ' q > ] {
307
+ & self . array_transitions
308
+ }
309
+
310
+ /// Returns the collection of labelled member transitions from this state.
311
+ ///
312
+ /// A transition is triggered if the [`MemberTransition`] is matched and leads
313
+ /// to the contained [`State`].
314
+ #[ must_use]
315
+ #[ inline( always) ]
316
+ pub fn member_transitions ( & self ) -> & [ MemberTransition < ' q > ] {
317
+ & self . member_transitions
390
318
}
391
319
}
392
320
@@ -420,8 +348,11 @@ impl<'q> Display for Automaton<'q> {
420
348
}
421
349
422
350
for ( i, transitions) in self . states . iter ( ) . enumerate ( ) {
423
- for ( label, state) in & transitions. transitions {
424
- writeln ! ( f, " {i} -> {} [label=\" {}\" ]" , state. 0 , label, ) ?
351
+ for ( label, state) in & transitions. array_transitions {
352
+ writeln ! ( f, " {i} -> {} [label=\" [{}]\" ]" , state. 0 , label. as_u64( ) ) ?
353
+ }
354
+ for ( label, state) in & transitions. member_transitions {
355
+ writeln ! ( f, " {i} -> {} [label=\" {}\" ]" , state. 0 , label. unquoted( ) ) ?
425
356
}
426
357
writeln ! ( f, " {i} -> {} [label=\" *\" ]" , transitions. fallback_state. 0 ) ?;
427
358
}
0 commit comments