corvus_json_schema 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +13 -2
  3. data/README.md +6 -4
  4. data/THIRD-PARTY-NOTICES.txt +15 -14
  5. data/VERSIONHISTORY.md +9 -0
  6. data/ext/corvus_json_schema/Cargo.toml +2 -2
  7. data/ext/corvus_json_schema/src/lib.rs +29 -2
  8. data/ext/corvus_json_schema/vendor/corvus-json-schema/Cargo.toml +4 -9
  9. data/ext/corvus_json_schema/vendor/corvus-json-schema/README.md +30 -49
  10. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/compiler.rs +5 -3
  11. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/formats.rs +7 -6
  12. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/lib.rs +4 -4
  13. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/options.rs +12 -0
  14. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/pattern.rs +344 -974
  15. data/lib/corvus_json_schema/version.rb +1 -1
  16. data/lib/corvus_json_schema.rb +8 -3
  17. metadata +2 -15
  18. data/ext/corvus_json_schema/vendor/corvus-json-schema/THIRD-PARTY-NOTICES.txt +0 -93
  19. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/charset.rs +0 -271
  20. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/compile.rs +0 -941
  21. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/dfa.rs +0 -366
  22. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/fold.rs +0 -138
  23. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/mod.rs +0 -329
  24. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/parse.rs +0 -1128
  25. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/re2.rs +0 -129
  26. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/tables_gen.rs +0 -6685
  27. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/tests.rs +0 -1672
  28. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/ucd.rs +0 -309
  29. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/units.rs +0 -165
  30. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/vm.rs +0 -981
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CorvusJsonSchema
4
- VERSION = "0.1.4"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -39,16 +39,21 @@ module CorvusJsonSchema
39
39
  # "#/$defs/item"), max_depth (of in-place recursion, default 128) and pattern_match_limit (the seconds one match of
40
40
  # a pattern or patternProperties regular expression may take, default 1. A match that takes longer is abandoned and
41
41
  # the validation raises PatternMatchLimitError. nil or 0 turns the limit off, for a caller who trusts both the
42
- # schema and the instances).
42
+ # schema and the instances), regex_edition (the edition of ECMA-262 patterns are read with: :dialect, the default,
43
+ # which is ECMAScript 2020 for 2019-09 and 2020-12 and today's for the drafts before them, :current or :es2020) and
44
+ # regex_unicode_version (the version of Unicode they are read with: :default, Unicode 17 today, :latest, 13, 17 or
45
+ # 18).
43
46
  #
44
47
  # A schema that does not compile raises CompilationError, and one with a regular expression over a limit of size
45
48
  # (1,048,576 bytes of pattern, 1,000 levels of groups) raises PatternTooLargeError, which is a CompilationError.
46
49
  def self.compile(schema, default_dialect: :draft202012, assert_format: nil, assert_format_in_legacy_drafts: false,
47
50
  assert_content: true, formats: nil, resolver: nil, base_uri: nil, entry_point: nil, max_depth: 128,
48
- pattern_match_limit: DEFAULT_PATTERN_MATCH_LIMIT)
51
+ pattern_match_limit: DEFAULT_PATTERN_MATCH_LIMIT, regex_edition: :dialect,
52
+ regex_unicode_version: :default)
49
53
  dialect = DIALECTS.fetch(default_dialect) { raise ArgumentError, "unknown dialect #{default_dialect.inspect}" }
50
54
  Native.compile(schema, dialect, assert_format, assert_format_in_legacy_drafts, assert_content, formats, resolver,
51
- base_uri, entry_point, Integer(max_depth), pattern_match_limit&.to_f)
55
+ base_uri, entry_point, Integer(max_depth), pattern_match_limit&.to_f, regex_edition.to_s,
56
+ regex_unicode_version.to_s)
52
57
  end
53
58
 
54
59
  # The version of the corvus-json-schema crate the extension was built from.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: corvus_json_schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - endjin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-17 00:00:00.000000000 Z
11
+ date: 2026-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rb_sys
@@ -47,22 +47,9 @@ files:
47
47
  - ext/corvus_json_schema/vendor/corvus-json-schema/Cargo.toml
48
48
  - ext/corvus_json_schema/vendor/corvus-json-schema/LICENSE
49
49
  - ext/corvus_json_schema/vendor/corvus-json-schema/README.md
50
- - ext/corvus_json_schema/vendor/corvus-json-schema/THIRD-PARTY-NOTICES.txt
51
50
  - ext/corvus_json_schema/vendor/corvus-json-schema/src/compiler.rs
52
51
  - ext/corvus_json_schema/vendor/corvus-json-schema/src/dialect.rs
53
52
  - ext/corvus_json_schema/vendor/corvus-json-schema/src/document.rs
54
- - ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/charset.rs
55
- - ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/compile.rs
56
- - ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/dfa.rs
57
- - ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/fold.rs
58
- - ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/mod.rs
59
- - ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/parse.rs
60
- - ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/re2.rs
61
- - ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/tables_gen.rs
62
- - ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/tests.rs
63
- - ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/ucd.rs
64
- - ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/units.rs
65
- - ext/corvus_json_schema/vendor/corvus-json-schema/src/ecmaregex/vm.rs
66
53
  - ext/corvus_json_schema/vendor/corvus-json-schema/src/eval.rs
67
54
  - ext/corvus_json_schema/vendor/corvus-json-schema/src/eval/plan.rs
68
55
  - ext/corvus_json_schema/vendor/corvus-json-schema/src/eval/plan/fused.rs
@@ -1,93 +0,0 @@
1
- corvus-json-schema uses third-party libraries or other resources that may be
2
- distributed under licenses different than the corvus-json-schema software.
3
-
4
- In the event that we accidentally failed to list a required notice, please
5
- bring it to our attention. Post an issue or email us:
6
-
7
- licensing@endjin.com
8
-
9
- The attached notices are provided for information only.
10
-
11
- License notice for the Unicode Character Database
12
- -------------------------------
13
-
14
- src/ecmaregex/tables_gen.rs holds tables derived from the data files of
15
- the Unicode Character Database, version 17.0.0
16
- (https://www.unicode.org/Public/17.0.0/ucd/): the General_Category values,
17
- the binary properties, the Script and Script_Extensions values, the simple
18
- case folding and the simple uppercase mapping. The data files are
19
- "© 2025 Unicode®, Inc." and are licensed under the Unicode License V3
20
- (SPDX-License-Identifier: Unicode-3.0), as https://www.unicode.org/license.txt
21
- gives it:
22
-
23
- UNICODE LICENSE V3
24
-
25
- COPYRIGHT AND PERMISSION NOTICE
26
-
27
- Copyright © 1991-2026 Unicode, Inc.
28
-
29
- NOTICE TO USER: Carefully read the following legal agreement. BY
30
- DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
31
- SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
32
- TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
33
- DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
34
-
35
- Permission is hereby granted, free of charge, to any person obtaining a
36
- copy of data files and any associated documentation (the "Data Files") or
37
- software and any associated documentation (the "Software") to deal in the
38
- Data Files or Software without restriction, including without limitation
39
- the rights to use, copy, modify, merge, publish, distribute, and/or sell
40
- copies of the Data Files or Software, and to permit persons to whom the
41
- Data Files or Software are furnished to do so, provided that either (a)
42
- this copyright and permission notice appear with all copies of the Data
43
- Files or Software, or (b) this copyright and permission notice appear in
44
- associated Documentation.
45
-
46
- THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
47
- KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
48
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
49
- THIRD PARTY RIGHTS.
50
-
51
- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
52
- BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
53
- OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
54
- WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
55
- ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
56
- FILES OR SOFTWARE.
57
-
58
- Except as contained in this notice, the name of a copyright holder shall
59
- not be used in advertising or otherwise to promote the sale, use or other
60
- dealings in these Data Files or Software without prior written
61
- authorization of the copyright holder.
62
-
63
- License notice for https://github.com/ridiculousfish/regress
64
- -------------------------------
65
-
66
- The tables of src/ecmaregex/tables_gen.rs were written by
67
- tools/gen-ucd-tables.ps1 from the tables of the Corvus Go module, which were
68
- written from src/unicodetables.rs of regress 0.12.0. That crate generates the
69
- file from the Unicode Character Database. regress is licensed under the MIT
70
- license or the Apache License, Version 2.0, at the user's option. This crate
71
- does not depend on it.
72
-
73
- MIT License
74
-
75
- Copyright (c) 2020 ridiculous_fish
76
-
77
- Permission is hereby granted, free of charge, to any person obtaining a copy
78
- of this software and associated documentation files (the "Software"), to deal
79
- in the Software without restriction, including without limitation the rights
80
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
81
- copies of the Software, and to permit persons to whom the Software is
82
- furnished to do so, subject to the following conditions:
83
-
84
- The above copyright notice and this permission notice shall be included in all
85
- copies or substantial portions of the Software.
86
-
87
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
88
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
89
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
90
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
91
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
92
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
93
- SOFTWARE.
@@ -1,271 +0,0 @@
1
- //! Sets of code points, the classes ECMA-262 defines, and the sets of the Unicode properties (`charset.go`).
2
-
3
- use std::collections::HashMap;
4
- use std::sync::{Arc, LazyLock, Mutex};
5
-
6
- use super::Rune;
7
- use super::ucd;
8
-
9
- /// The last Unicode code point.
10
- pub(crate) const MAX_RUNE: Rune = ucd::MAX_RUNE;
11
-
12
- /// An immutable set of code points. The ranges are sorted, inclusive, and neither overlap nor touch. The two words
13
- /// of `ascii` repeat the membership of the code points below 128 so that the common case is one bit test.
14
- #[derive(Debug, PartialEq, Eq)]
15
- pub(crate) struct CharSet {
16
- pub(crate) ranges: Vec<Rune>,
17
- pub(crate) ascii: [u64; 2],
18
- }
19
-
20
- impl CharSet {
21
- /// Builds a set from inclusive pairs in any order, which may overlap. With `negate` it builds the complement.
22
- pub(crate) fn new(pairs: &[Rune], negate: bool) -> CharSet {
23
- let mut idx: Vec<usize> = (0..pairs.len() / 2).collect();
24
- idx.sort_by_key(|&i| pairs[2 * i]);
25
- let mut merged: Vec<Rune> = Vec::with_capacity(pairs.len());
26
- for i in idx {
27
- let (lo, hi) = (pairs[2 * i], pairs[2 * i + 1]);
28
- if let Some(last) = merged.last_mut()
29
- && lo <= *last + 1
30
- {
31
- if hi > *last {
32
- *last = hi;
33
- }
34
- continue;
35
- }
36
- merged.push(lo);
37
- merged.push(hi);
38
- }
39
- if negate {
40
- let mut inverse = Vec::with_capacity(merged.len() + 2);
41
- let mut next: Rune = 0;
42
- for &[lo, hi] in merged.as_chunks::<2>().0 {
43
- if lo > next {
44
- inverse.push(next);
45
- inverse.push(lo - 1);
46
- }
47
- next = hi + 1;
48
- }
49
- if next <= MAX_RUNE {
50
- inverse.push(next);
51
- inverse.push(MAX_RUNE);
52
- }
53
- merged = inverse;
54
- }
55
- let mut ascii = [0u64; 2];
56
- for &[lo, hi] in merged.as_chunks::<2>().0 {
57
- if lo >= 128 {
58
- break;
59
- }
60
- let mut c = lo;
61
- while c <= hi && c < 128 {
62
- ascii[(c >> 6) as usize] |= 1 << (c & 63);
63
- c += 1;
64
- }
65
- }
66
- CharSet { ranges: merged, ascii }
67
- }
68
-
69
- /// [`CharSet::new`], shared.
70
- pub(crate) fn shared(pairs: &[Rune], negate: bool) -> Arc<CharSet> {
71
- Arc::new(CharSet::new(pairs, negate))
72
- }
73
-
74
- /// Whether the set holds the ASCII character.
75
- #[inline(always)]
76
- pub(crate) fn has_ascii(&self, c: u8) -> bool {
77
- (self.ascii[(c >> 6) as usize & 1] >> (c & 63)) & 1 != 0
78
- }
79
-
80
- /// Whether the set holds the code point.
81
- #[inline]
82
- pub(crate) fn contains(&self, r: Rune) -> bool {
83
- if (0..128).contains(&r) {
84
- return (self.ascii[(r >> 6) as usize] >> (r & 63)) & 1 != 0;
85
- }
86
- let ranges = &self.ranges[..];
87
- let (mut lo, mut hi) = (0, ranges.len() / 2);
88
- while lo < hi {
89
- let mid = (lo + hi) >> 1;
90
- if r > ranges[2 * mid + 1] {
91
- lo = mid + 1;
92
- } else if r < ranges[2 * mid] {
93
- hi = mid;
94
- } else {
95
- return true;
96
- }
97
- }
98
- false
99
- }
100
-
101
- /// Whether the set holds no code point.
102
- pub(crate) fn is_empty(&self) -> bool {
103
- self.ranges.is_empty()
104
- }
105
- }
106
-
107
- // The classes ECMA-262 defines. \d and \w are ASCII only, \s is WhiteSpace and LineTerminator, and . is everything
108
- // but the four line terminators.
109
- pub(crate) const DIGIT_PAIRS: &[Rune] = &[0x30, 0x39];
110
- pub(crate) const WORD_PAIRS: &[Rune] = &[0x30, 0x39, 0x41, 0x5A, 0x5F, 0x5F, 0x61, 0x7A];
111
- pub(crate) const SPACE_PAIRS: &[Rune] = &[
112
- 0x9, 0xD, 0x20, 0x20, 0xA0, 0xA0, 0x1680, 0x1680, 0x2000, 0x200A, 0x2028, 0x2029, 0x202F, 0x202F, 0x205F, 0x205F,
113
- 0x3000, 0x3000, 0xFEFF, 0xFEFF,
114
- ];
115
- pub(crate) const LINE_TERMINATOR_PAIRS: &[Rune] = &[0xA, 0xA, 0xD, 0xD, 0x2028, 0x2029];
116
-
117
- pub(crate) static DOT_SET: LazyLock<Arc<CharSet>> = LazyLock::new(|| CharSet::shared(LINE_TERMINATOR_PAIRS, true));
118
-
119
- /// Whether a byte is an ECMA-262 word character. Every word character is ASCII, so a word boundary can be decided
120
- /// from the bytes on either side of a position.
121
- #[inline(always)]
122
- pub(crate) fn is_word_byte(b: u8) -> bool {
123
- b.is_ascii_alphanumeric() || b == b'_'
124
- }
125
-
126
- /// The short name of a General_Category value, from its long name, an alias or the short name itself.
127
- fn category_name(value: &str) -> Option<&'static str> {
128
- Some(match value {
129
- "Letter" | "L" => "L",
130
- "Lowercase_Letter" | "Ll" => "Ll",
131
- "Uppercase_Letter" | "Lu" => "Lu",
132
- "Titlecase_Letter" | "Lt" => "Lt",
133
- "Cased_Letter" | "LC" => "LC",
134
- "Modifier_Letter" | "Lm" => "Lm",
135
- "Other_Letter" | "Lo" => "Lo",
136
- "Mark" | "Combining_Mark" | "M" => "M",
137
- "Nonspacing_Mark" | "Mn" => "Mn",
138
- "Spacing_Mark" | "Mc" => "Mc",
139
- "Enclosing_Mark" | "Me" => "Me",
140
- "Number" | "N" => "N",
141
- "Decimal_Number" | "digit" | "Nd" => "Nd",
142
- "Letter_Number" | "Nl" => "Nl",
143
- "Other_Number" | "No" => "No",
144
- "Punctuation" | "punct" | "P" => "P",
145
- "Connector_Punctuation" | "Pc" => "Pc",
146
- "Dash_Punctuation" | "Pd" => "Pd",
147
- "Open_Punctuation" | "Ps" => "Ps",
148
- "Close_Punctuation" | "Pe" => "Pe",
149
- "Initial_Punctuation" | "Pi" => "Pi",
150
- "Final_Punctuation" | "Pf" => "Pf",
151
- "Other_Punctuation" | "Po" => "Po",
152
- "Symbol" | "S" => "S",
153
- "Math_Symbol" | "Sm" => "Sm",
154
- "Currency_Symbol" | "Sc" => "Sc",
155
- "Modifier_Symbol" | "Sk" => "Sk",
156
- "Other_Symbol" | "So" => "So",
157
- "Separator" | "Z" => "Z",
158
- "Space_Separator" | "Zs" => "Zs",
159
- "Line_Separator" | "Zl" => "Zl",
160
- "Paragraph_Separator" | "Zp" => "Zp",
161
- "Other" | "C" => "C",
162
- "Control" | "cntrl" | "Cc" => "Cc",
163
- "Format" | "Cf" => "Cf",
164
- "Surrogate" | "Cs" => "Cs",
165
- "Private_Use" | "Co" => "Co",
166
- "Unassigned" | "Cn" => "Cn",
167
- _ => return None,
168
- })
169
- }
170
-
171
- /// The canonical name of a binary property ECMA-262 lists, from the name or an alias.
172
- fn binary_name(name: &str) -> Option<&'static str> {
173
- Some(match name {
174
- "ASCII" => "ASCII",
175
- "ASCII_Hex_Digit" | "AHex" => "ASCII_Hex_Digit",
176
- "Alphabetic" | "Alpha" => "Alphabetic",
177
- "Any" => "Any",
178
- "Assigned" => "Assigned",
179
- "Bidi_Control" | "Bidi_C" => "Bidi_Control",
180
- "Bidi_Mirrored" | "Bidi_M" => "Bidi_Mirrored",
181
- "Case_Ignorable" | "CI" => "Case_Ignorable",
182
- "Cased" => "Cased",
183
- "Changes_When_Casefolded" | "CWCF" => "Changes_When_Casefolded",
184
- "Changes_When_Casemapped" | "CWCM" => "Changes_When_Casemapped",
185
- "Changes_When_Lowercased" | "CWL" => "Changes_When_Lowercased",
186
- "Changes_When_NFKC_Casefolded" | "CWKCF" => "Changes_When_NFKC_Casefolded",
187
- "Changes_When_Titlecased" | "CWT" => "Changes_When_Titlecased",
188
- "Changes_When_Uppercased" | "CWU" => "Changes_When_Uppercased",
189
- "Dash" => "Dash",
190
- "Default_Ignorable_Code_Point" | "DI" => "Default_Ignorable_Code_Point",
191
- "Deprecated" | "Dep" => "Deprecated",
192
- "Diacritic" | "Dia" => "Diacritic",
193
- "Emoji" => "Emoji",
194
- "Emoji_Component" | "EComp" => "Emoji_Component",
195
- "Emoji_Modifier" | "EMod" => "Emoji_Modifier",
196
- "Emoji_Modifier_Base" | "EBase" => "Emoji_Modifier_Base",
197
- "Emoji_Presentation" | "EPres" => "Emoji_Presentation",
198
- "Extended_Pictographic" | "ExtPict" => "Extended_Pictographic",
199
- "Extender" | "Ext" => "Extender",
200
- "Grapheme_Base" | "Gr_Base" => "Grapheme_Base",
201
- "Grapheme_Extend" | "Gr_Ext" => "Grapheme_Extend",
202
- "Hex_Digit" | "Hex" => "Hex_Digit",
203
- "IDS_Binary_Operator" | "IDSB" => "IDS_Binary_Operator",
204
- "IDS_Trinary_Operator" | "IDST" => "IDS_Trinary_Operator",
205
- "ID_Continue" | "IDC" => "ID_Continue",
206
- "ID_Start" | "IDS" => "ID_Start",
207
- "Ideographic" | "Ideo" => "Ideographic",
208
- "Join_Control" | "Join_C" => "Join_Control",
209
- "Logical_Order_Exception" | "LOE" => "Logical_Order_Exception",
210
- "Lowercase" | "Lower" => "Lowercase",
211
- "Math" => "Math",
212
- "Noncharacter_Code_Point" | "NChar" => "Noncharacter_Code_Point",
213
- "Pattern_Syntax" | "Pat_Syn" => "Pattern_Syntax",
214
- "Pattern_White_Space" | "Pat_WS" => "Pattern_White_Space",
215
- "Quotation_Mark" | "QMark" => "Quotation_Mark",
216
- "Radical" => "Radical",
217
- "Regional_Indicator" | "RI" => "Regional_Indicator",
218
- "Sentence_Terminal" | "STerm" => "Sentence_Terminal",
219
- "Soft_Dotted" | "SD" => "Soft_Dotted",
220
- "Terminal_Punctuation" | "Term" => "Terminal_Punctuation",
221
- "Unified_Ideograph" | "UIdeo" => "Unified_Ideograph",
222
- "Uppercase" | "Upper" => "Uppercase",
223
- "Variation_Selector" | "VS" => "Variation_Selector",
224
- "White_Space" | "space" => "White_Space",
225
- "XID_Continue" | "XIDC" => "XID_Continue",
226
- "XID_Start" | "XIDS" => "XID_Start",
227
- _ => return None,
228
- })
229
- }
230
-
231
- /// The sets already built for property expressions. A property set can have hundreds of ranges, and schemas tend to
232
- /// repeat the same few. Only an expression ECMA-262 defines is kept, and those are a fixed few hundred, so the
233
- /// cache is bounded.
234
- static PROPERTY_CACHE: LazyLock<Mutex<HashMap<String, Arc<CharSet>>>> = LazyLock::new(|| Mutex::new(HashMap::new()));
235
-
236
- /// Resolves the expression between the braces of `\p{...}` to its set. `None` for a name or value that ECMA-262
237
- /// does not define.
238
- pub(crate) fn property_set(expr: &str) -> Option<Arc<CharSet>> {
239
- if let Some(cached) = PROPERTY_CACHE.lock().unwrap_or_else(|e| e.into_inner()).get(expr) {
240
- return Some(cached.clone());
241
- }
242
- let pairs = property_pairs(expr)?;
243
- let set = CharSet::shared(&pairs, false);
244
- PROPERTY_CACHE.lock().unwrap_or_else(|e| e.into_inner()).insert(expr.to_string(), set.clone());
245
- Some(set)
246
- }
247
-
248
- /// The ranges of a property expression. Every range comes from the tables of `ucd`, which hold one fixed version of
249
- /// Unicode, so the answer does not depend on the toolchain.
250
- fn property_pairs(expr: &str) -> Option<Vec<Rune>> {
251
- if let Some((name, value)) = expr.split_once('=') {
252
- return match name {
253
- "General_Category" | "gc" => category_pairs(value),
254
- "Script" | "sc" => ucd::script(value).map(|t| t.pairs()),
255
- "Script_Extensions" | "scx" => ucd::script_extensions(value).map(|t| t.pairs()),
256
- _ => None,
257
- };
258
- }
259
- if let Some(pairs) = category_pairs(expr) {
260
- return Some(pairs);
261
- }
262
- match binary_name(expr)? {
263
- "ASCII" => Some(vec![0, 0x7F]),
264
- "Any" => Some(vec![0, MAX_RUNE]),
265
- canonical => ucd::binary(canonical).map(|t| t.pairs()),
266
- }
267
- }
268
-
269
- fn category_pairs(value: &str) -> Option<Vec<Rune>> {
270
- ucd::category(category_name(value)?).map(|t| t.pairs())
271
- }