1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
//! Matches ECMA-262 regular expressions against UTF-8 text, with the semantics JSON Schema requires of the
//! `pattern` and `patternProperties` keywords and of the `regex` format.
//!
//! This is a port of the `ecmaregex` package of the Go module (`src-go/corvus-json-schema/internal/ecmaregex`),
//! which the Object Pascal and OCaml ports of the evaluator also carry. The files and the names follow the Go
//! source, so that a fix made in one port can be carried to the others: `parse.rs` is `parse.go`, `compile.rs` is
//! `compile.go`, `vm.rs` is `vm.go`, `dfa.rs` is `dfa.go`, `charset.rs`, `fold.rs` and `units.rs` are the files of
//! the same names, and `ucd.rs` with `tables_gen.rs` is the `ucd` package.
//!
//! # Unicode mode
//!
//! A pattern is read first with the grammar of the ECMA-262 u flag, which is what JSON Schema specifies. A pattern
//! that is not valid under that grammar is then read with the Annex B grammar of a pattern with no flag, which
//! accepts what many schemas in the wild contain (identity escapes such as `\&`, a lone brace, legacy octal
//! escapes). Only a pattern that neither grammar accepts is an error. [`valid`], which backs the `regex` format,
//! accepts only the u flag grammar.
//!
//! A pattern the u flag grammar accepts is matched by Unicode code point over the UTF-8 text. The dot, a class and a
//! quantifier each see a character beyond the Basic Multilingual Plane as one character, and a surrogate pair
//! written as two `\u` escapes names one code point.
//!
//! A pattern that only the Annex B grammar accepts is matched by UTF-16 code unit, as ECMA-262 matches a pattern
//! with no u flag. A character beyond the Basic Multilingual Plane is then two characters, a high surrogate and a
//! low one, to the dot, a class, a quantifier, a group and a backreference. A match can start or end between the
//! two. Such a character in the pattern is two atoms, and a class range between two of them is an error. Case is
//! folded by the Canonicalize of a pattern with no u flag. The text stays UTF-8 and no UTF-16 copy of it is made
//! (see `units.rs`). Only a text with a character beyond the Basic Multilingual Plane is read differently by the
//! two.
//!
//! The text is a `&str`, so it is UTF-8 and cannot hold half of a surrogate pair. A pattern that names one, such
//! as `\ud800`, matches it only as half of a character and only when the pattern has no u flag.
//!
//! JSON Schema gives a pattern no flags, so matching is case sensitive, `^` and `$` match only at the ends of the
//! text, and the dot excludes the four line terminators. A pattern can change that for part of itself with a
//! modifier group of ECMAScript 2025, such as `(?i:...)`, `(?m:...)` or `(?s:...)`.
//!
//! # The matcher
//!
//! Every pattern is compiled for a backtracking matcher. A pattern with no lookaround, no backreference, no
//! multiline anchor and no case-insensitive word boundary also gets a deterministic automaton over ASCII text when
//! it is small enough and has no word boundary (see `dfa.rs`), which decides an ASCII text with one table read per
//! byte. (The Go engine gives such a pattern to the standard library's regexp package as well. In this crate the
//! `regex` crate has that part, and `pattern.rs` decides which patterns it gets before the engine is asked.)
//!
//! The backtracking matcher keeps its choices on an explicit stack that the thread reuses, so a long text cannot
//! overflow the stack of the thread and a match does not allocate once the stack has grown. Four things keep it
//! from the time a backtracking matcher can take. A repetition whose body cannot consume a character is run once,
//! or not at all (see `simplify`), as V8 runs it. A counted loop gives up at a position from which the rest of the
//! pattern, with the iterations the loop still owes, needs more text than is left (see `set_needs`). A way the next
//! character of the text rules out is not taken (see `set_quick`), as in V8. And where a pattern has no
//! backreference the matcher remembers the places from which every way has failed (see `memo` in `vm.rs`), so a
//! repetition inside a repetition takes time proportional to the pattern times the text. What is left, a group read
//! back inside a repetition above all, can still take time that doubles with each character, and is ended by the
//! limit of the match.
//!
//! # Limits
//!
//! [`Regexp::match_limit`] gives a match a limit of time, and with it a cap on the memory of its backtracking.
//! [`compile`] refuses a pattern over a limit of size ([`MAX_PATTERN_LENGTH`], [`MAX_NESTING`], [`MAX_SIZE`]) with
//! a [`TooLargeError`], so that reading and compiling a pattern take bounded time and memory whatever the pattern
//! holds.
//!
//! # Coverage
//!
//! The grammar is that of ECMAScript 2025. It includes lookbehind, named groups, group names shared between
//! separate alternatives, modifier groups, and Unicode property escapes for every property, value and alias
//! ECMA-262 lists, with Unicode 17 data. The properties and the case folding come from the tables of `ucd.rs` and
//! never from the standard library or from a dependency, so a pattern matches the same texts whatever built the
//! program. The v flag (set notation and properties of strings) does not apply, because a JSON Schema pattern has
//! no flags.
// Generated: it has names of scripts and properties that only the tests read.
use fmt;
use OnceLock;
use Duration;
pub use ;
use Limit;
pub use ;
pub use MAX_RE2_COST;
pub use has_supplementary;
pub use MatchError;
/// A code point, or a UTF-16 code unit of a pattern read without the u flag. It is signed, as the `rune` of the Go
/// source is, and -1 stands for "none".
pub type Rune = i32;
/// Why a pattern does not compile.
pub
/// What reading a pattern tells of it, without compiling it.
pub
/// Reads a pattern with the u flag grammar and, when that refuses it, with the Annex B grammar.
/// The number of groups a pattern may open and still be read on the stack of the thread that asks.
const SHALLOW: usize = 32;
/// The stack of the thread that reads a pattern with more groups than that. The parser, the compiler and the
/// dropping of the syntax tree go one level deeper for each level of groups, and [`MAX_NESTING`] allows a thousand
/// levels, which is more than the stack of a thread can be relied on to hold: a thread of a language runtime that
/// embeds the crate may have a few hundred kilobytes. Only the pages the work touches are used.
const DEEP_STACK: usize = 64 << 20;
/// Runs the reading of a pattern, with everything that walks its syntax tree, where the depth of the tree cannot
/// overflow the stack. A pattern that opens few groups is shallow, and is read where it is. Any other is read on a
/// thread of its own with a stack for the deepest nesting the limits allow. (Go grows the stack of a goroutine as
/// it is needed, so the Go engine has no such step.) `None` when that thread could not be started.
/// Runs work that goes a level deeper for each level of groups of a pattern on a thread with a stack for the
/// deepest nesting the limits allow. `None` when the thread could not be started.
pub
/// Whether a pattern opens few enough groups to be read on the stack of the thread that asks.
pub
/// The error of a pattern that nests deeply when no thread could be started to read it: the pattern is refused as
/// one over the limit of nesting, which is the limit the thread is there to serve.
const NO_DEEP_STACK: Error = TooLarge;
/// A compiled ECMA-262 pattern. It is immutable once compiled, and safe to share between threads.
pub
/// Compiles an ECMA-262 pattern with the semantics JSON Schema requires. It returns an error for a pattern that is
/// not valid, and a [`TooLargeError`] for a pattern over a limit of size (see [`MAX_SIZE`]), whether or not it is
/// valid.
pub
/// Reports whether the pattern is a valid ECMA-262 pattern (for `format: regex`). It applies the grammar of the u
/// flag. A pattern over a limit of size is not read to its end and is reported as not valid.
pub
/// Reads the pattern without compiling it. It returns what the parser learnt of it, or the error [`compile`]
/// would: a [`TooLargeError`] for a pattern over a limit of size, and any other error for a pattern that is not
/// valid.
pub