@@ -2,20 +2,97 @@ use std::{cell::RefCell, time::SystemTime};
2
2
3
3
use crate :: error:: EngineError ;
4
4
5
- /// Hold information about limitations and constraints of operations execution:
6
- /// - max_number_of_states: the maximum number of states that a non-determinitic finite automaton can hold.
7
- /// - start_execution_time: timestamp of when the execution has started.
8
- /// - execution_timeout: the longest time in milliseconds that an operation execution can last.
9
- /// - max_number_of_terms: the maximum number of terms that an operation can have.
5
+ /// Hold settings about limitations and constraints of operations execution within the engine.
6
+ ///
7
+ /// To apply the settings on the current thread you need to call the following function:
8
+ /// ```
9
+ /// use regexsolver::execution_profile::{ExecutionProfile, ThreadLocalParams};
10
+ ///
11
+ /// let execution_profile = ExecutionProfile {
12
+ /// max_number_of_states: 1,
13
+ /// start_execution_time: None,
14
+ /// execution_timeout: 1000,
15
+ /// max_number_of_terms: 10,
16
+ /// };
17
+ ///
18
+ /// // Store the settings on the current thread.
19
+ /// ThreadLocalParams::init_profile(&execution_profile);
20
+ /// ```
21
+ ///
22
+ /// # Examples:
23
+ ///
24
+ /// ## Limiting the number of states
25
+ /// ```
26
+ /// use regexsolver::{Term, execution_profile::{ExecutionProfile, ThreadLocalParams}, error::EngineError};
27
+ ///
28
+ /// let term1 = Term::from_regex(".*abc.*").unwrap();
29
+ /// let term2 = Term::from_regex(".*def.*").unwrap();
30
+ ///
31
+ /// let execution_profile = ExecutionProfile {
32
+ /// max_number_of_states: 1,
33
+ /// start_execution_time: None,
34
+ /// execution_timeout: 1000,
35
+ /// max_number_of_terms: 10,
36
+ /// };
37
+ /// ThreadLocalParams::init_profile(&execution_profile);
38
+ ///
39
+ /// assert_eq!(EngineError::AutomatonHasTooManyStates, term1.intersection(&[term2]).unwrap_err());
40
+ /// ```
41
+ ///
42
+ /// ## Limiting the number of terms
43
+ /// ```
44
+ /// use regexsolver::{Term, execution_profile::{ExecutionProfile, ThreadLocalParams}, error::EngineError};
45
+ ///
46
+ /// let term1 = Term::from_regex(".*abc.*").unwrap();
47
+ /// let term2 = Term::from_regex(".*def.*").unwrap();
48
+ /// let term3 = Term::from_regex(".*hij.*").unwrap();
49
+ ///
50
+ /// let execution_profile = ExecutionProfile {
51
+ /// max_number_of_states: 8192,
52
+ /// start_execution_time: None,
53
+ /// execution_timeout: 1000,
54
+ /// max_number_of_terms: 2,
55
+ /// };
56
+ /// ThreadLocalParams::init_profile(&execution_profile);
57
+ ///
58
+ /// assert_eq!(EngineError::TooMuchTerms(2,3), term1.intersection(&[term2, term3]).unwrap_err());
59
+ /// ```
60
+ ///
61
+ /// ## Limiting the execution time
62
+ /// ```
63
+ /// use regexsolver::{Term, execution_profile::{ExecutionProfile, ThreadLocalParams}, error::EngineError};
64
+ /// use std::time::SystemTime;
65
+ ///
66
+ /// let term = Term::from_regex(".*abc.*cdef.*sqdsqf.*").unwrap();
67
+ ///
68
+ /// let execution_profile = ExecutionProfile {
69
+ /// max_number_of_states: 8192,
70
+ /// start_execution_time: Some(SystemTime::now()),
71
+ /// execution_timeout: 1,
72
+ /// max_number_of_terms: 50,
73
+ /// };
74
+ /// ThreadLocalParams::init_profile(&execution_profile);
75
+ ///
76
+ /// assert_eq!(EngineError::OperationTimeOutError, term.generate_strings(100).unwrap_err());
77
+ /// ```
10
78
pub struct ExecutionProfile {
79
+ /// The maximum number of states that a non-determinitic finite automaton can hold, this is checked during the convertion of regular expression to automaton.
11
80
pub max_number_of_states : usize ,
81
+ /// Timestamp of when the execution has started, if this value is not set the operations will never timeout.
12
82
pub start_execution_time : Option < SystemTime > ,
83
+ /// The longest time in milliseconds that an operation execution can last, there are no guaranties that the exact time will be respected.
13
84
pub execution_timeout : u128 ,
85
+ /// The maximum number of terms that an operation can have.
14
86
pub max_number_of_terms : usize ,
15
87
}
16
88
17
89
impl ExecutionProfile {
18
- pub fn is_timed_out ( & self ) -> Result < ( ) , EngineError > {
90
+ /// Assert that `execution_timeout` is not exceeded.
91
+ ///
92
+ /// Return empty if `execution_timeout` is not exceeded or if `start_execution_time` is not set.
93
+ ///
94
+ /// Return [`EngineError::OperationTimeOutError`] otherwise.
95
+ pub fn assert_not_timed_out ( & self ) -> Result < ( ) , EngineError > {
19
96
if let Some ( start) = self . start_execution_time {
20
97
let run_duration = SystemTime :: now ( )
21
98
. duration_since ( start)
@@ -33,6 +110,20 @@ impl ExecutionProfile {
33
110
}
34
111
}
35
112
113
+
114
+ /// Hold [`ExecutionProfile`] on the current thread.
115
+ ///
116
+ /// The default [`ExecutionProfile`] is the following:
117
+ /// ```
118
+ /// use regexsolver::execution_profile::ExecutionProfile;
119
+ ///
120
+ /// ExecutionProfile {
121
+ /// max_number_of_states: 8192,
122
+ /// start_execution_time: None,
123
+ /// execution_timeout: 1500,
124
+ /// max_number_of_terms: 50,
125
+ /// };
126
+ /// ```
36
127
pub struct ThreadLocalParams ;
37
128
impl ThreadLocalParams {
38
129
thread_local ! {
@@ -42,7 +133,7 @@ impl ThreadLocalParams {
42
133
static MAX_NUMBER_OF_TERMS : RefCell <usize > = const { RefCell :: new( 50 ) } ;
43
134
}
44
135
45
- /// Initialize the thread local holding the ExecutionProfile.
136
+ /// Store on the current thread [` ExecutionProfile`] .
46
137
pub fn init_profile ( profile : & ExecutionProfile ) {
47
138
ThreadLocalParams :: MAX_NUMBER_OF_STATES . with ( |cell| {
48
139
* cell. borrow_mut ( ) = profile. max_number_of_states ;
@@ -77,6 +168,7 @@ impl ThreadLocalParams {
77
168
ThreadLocalParams :: MAX_NUMBER_OF_TERMS . with ( |cell| * cell. borrow ( ) )
78
169
}
79
170
171
+ /// Return the [`ExecutionProfile`] stored on the current thread.
80
172
pub fn get_execution_profile ( ) -> ExecutionProfile {
81
173
ExecutionProfile {
82
174
max_number_of_states : Self :: get_max_number_of_states ( ) ,
0 commit comments