re2 2.23.0 → 2.27.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.
data/spec/re2_spec.rb CHANGED
@@ -1,34 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe RE2 do
4
- describe ".Replace" do
4
+ describe ".replace" do
5
5
  it "only replaces the first occurrence of the pattern" do
6
- expect(RE2.Replace("woo", "o", "a")).to eq("wao")
6
+ expect(RE2.replace("woo", "o", "a")).to eq("wao")
7
7
  end
8
8
 
9
9
  it "supports inputs with null bytes" do
10
- expect(RE2.Replace("w\0oo", "o", "a")).to eq("w\0ao")
10
+ expect(RE2.replace("w\0oo", "o", "a")).to eq("w\0ao")
11
11
  end
12
12
 
13
13
  it "supports patterns with null bytes" do
14
- expect(RE2.Replace("w\0oo", "\0", "o")).to eq("wooo")
14
+ expect(RE2.replace("w\0oo", "\0", "o")).to eq("wooo")
15
15
  end
16
16
 
17
17
  it "supports replacements with null bytes" do
18
- expect(RE2.Replace("woo", "o", "\0")).to eq("w\0o")
18
+ expect(RE2.replace("woo", "o", "\0")).to eq("w\0o")
19
19
  end
20
20
 
21
21
  it "performs replacement based on regular expressions" do
22
- expect(RE2.Replace("woo", "o+", "e")).to eq("we")
22
+ expect(RE2.replace("woo", "o+", "e")).to eq("we")
23
23
  end
24
24
 
25
25
  it "supports flags in patterns" do
26
- expect(RE2.Replace("Good morning", "(?i)gOOD MORNING", "hi")).to eq("hi")
26
+ expect(RE2.replace("Good morning", "(?i)gOOD MORNING", "hi")).to eq("hi")
27
27
  end
28
28
 
29
29
  it "does not perform replacements in-place", :aggregate_failures do
30
30
  name = "Robert"
31
- replacement = RE2.Replace(name, "R", "Cr")
31
+ replacement = RE2.replace(name, "R", "Cr")
32
32
 
33
33
  expect(name).to eq("Robert")
34
34
  expect(replacement).to eq("Crobert")
@@ -37,88 +37,118 @@ RSpec.describe RE2 do
37
37
  it "supports passing an RE2::Regexp as the pattern" do
38
38
  re = RE2::Regexp.new('wo{2}')
39
39
 
40
- expect(RE2.Replace("woo", re, "miaow")).to eq("miaow")
40
+ expect(RE2.replace("woo", re, "miaow")).to eq("miaow")
41
41
  end
42
42
 
43
43
  it "respects any passed RE2::Regexp's flags" do
44
44
  re = RE2::Regexp.new('gOOD MORNING', case_sensitive: false)
45
45
 
46
- expect(RE2.Replace("Good morning", re, "hi")).to eq("hi")
46
+ expect(RE2.replace("Good morning", re, "hi")).to eq("hi")
47
47
  end
48
48
 
49
49
  it "supports passing something that can be coerced to a String as input" do
50
- expect(RE2.Replace(StringLike.new("woo"), "oo", "ah")).to eq("wah")
50
+ expect(RE2.replace(StringLike.new("woo"), "oo", "ah")).to eq("wah")
51
51
  end
52
52
 
53
53
  it "supports passing something that can be coerced to a String as a pattern" do
54
- expect(RE2.Replace("woo", StringLike.new("oo"), "ah")).to eq("wah")
54
+ expect(RE2.replace("woo", StringLike.new("oo"), "ah")).to eq("wah")
55
55
  end
56
56
 
57
57
  it "supports passing something that can be coerced to a String as a replacement" do
58
- expect(RE2.Replace("woo", "oo", StringLike.new("ah"))).to eq("wah")
58
+ expect(RE2.replace("woo", "oo", StringLike.new("ah"))).to eq("wah")
59
59
  end
60
60
 
61
61
  it "returns UTF-8 strings if the pattern is UTF-8" do
62
62
  original = "Foo".encode("ISO-8859-1")
63
- replacement = RE2.Replace(original, "oo", "ah")
63
+ replacement = RE2.replace(original, "oo", "ah")
64
64
 
65
65
  expect(replacement.encoding).to eq(Encoding::UTF_8)
66
66
  end
67
67
 
68
68
  it "returns ISO-8859-1 strings if the pattern is not UTF-8" do
69
69
  original = "Foo"
70
- replacement = RE2.Replace(original, RE2("oo", utf8: false), "ah")
70
+ replacement = RE2.replace(original, RE2("oo", utf8: false), "ah")
71
71
 
72
72
  expect(replacement.encoding).to eq(Encoding::ISO_8859_1)
73
73
  end
74
74
 
75
75
  it "returns UTF-8 strings when given a String pattern" do
76
- replacement = RE2.Replace("Foo", "oo".encode("ISO-8859-1"), "ah")
76
+ replacement = RE2.replace("Foo", "oo".encode("ISO-8859-1"), "ah")
77
77
 
78
78
  expect(replacement.encoding).to eq(Encoding::UTF_8)
79
79
  end
80
80
 
81
81
  it "raises a Type Error for input that can't be converted to String" do
82
- expect { RE2.Replace(0, "oo", "ah") }.to raise_error(TypeError)
82
+ expect { RE2.replace(0, "oo", "ah") }.to raise_error(TypeError)
83
83
  end
84
84
 
85
85
  it "raises a Type Error for a non-RE2::Regexp pattern that can't be converted to String" do
86
- expect { RE2.Replace("woo", 0, "ah") }.to raise_error(TypeError)
86
+ expect { RE2.replace("woo", 0, "ah") }.to raise_error(TypeError)
87
+ end
88
+
89
+ it "does not leak memory when given a non-String, non-RE2::Regexp pattern" do
90
+ expect { RE2.replace("a" * 128, 0, "ah") }.to raise_error(TypeError)
87
91
  end
88
92
 
89
93
  it "raises a Type Error for a replacement that can't be converted to String" do
90
- expect { RE2.Replace("woo", "oo", 0) }.to raise_error(TypeError)
94
+ expect { RE2.replace("woo", "oo", 0) }.to raise_error(TypeError)
95
+ end
96
+
97
+ it "can be run concurrently with the same RE2::Regexp pattern" do
98
+ re = RE2::Regexp.new('(\w+)\s(\w+)')
99
+
100
+ threads = 10.times.map do
101
+ Thread.new { RE2.replace("one two", re, '\2 \1') }
102
+ end
103
+
104
+ expect(threads.map(&:value)).to all(eq("two one"))
105
+ end
106
+
107
+ it "can be run concurrently with the same string pattern" do
108
+ re = '(\w+)\s(\w+)'
109
+
110
+ threads = 10.times.map do
111
+ Thread.new { RE2.replace("one two", re, '\2 \1') }
112
+ end
113
+
114
+ expect(threads.map(&:value)).to all(eq("two one"))
91
115
  end
92
116
  end
93
117
 
94
- describe ".GlobalReplace" do
118
+ describe ".Replace" do
119
+ it "is an alias for .replace" do
120
+ expect(RE2.Replace("woo", "o", "a")).to eq("wao")
121
+ end
122
+ end
123
+
124
+ describe ".global_replace" do
95
125
  it "replaces every occurrence of a pattern" do
96
- expect(RE2.GlobalReplace("woo", "o", "a")).to eq("waa")
126
+ expect(RE2.global_replace("woo", "o", "a")).to eq("waa")
97
127
  end
98
128
 
99
129
  it "supports inputs with null bytes" do
100
- expect(RE2.GlobalReplace("w\0oo", "o", "a")).to eq("w\0aa")
130
+ expect(RE2.global_replace("w\0oo", "o", "a")).to eq("w\0aa")
101
131
  end
102
132
 
103
133
  it "supports patterns with null bytes" do
104
- expect(RE2.GlobalReplace("w\0\0oo", "\0", "a")).to eq("waaoo")
134
+ expect(RE2.global_replace("w\0\0oo", "\0", "a")).to eq("waaoo")
105
135
  end
106
136
 
107
137
  it "supports replacements with null bytes" do
108
- expect(RE2.GlobalReplace("woo", "o", "\0")).to eq("w\0\0")
138
+ expect(RE2.global_replace("woo", "o", "\0")).to eq("w\0\0")
109
139
  end
110
140
 
111
141
  it "performs replacement based on regular expressions" do
112
- expect(RE2.GlobalReplace("woohoo", "o+", "e")).to eq("wehe")
142
+ expect(RE2.global_replace("woohoo", "o+", "e")).to eq("wehe")
113
143
  end
114
144
 
115
145
  it "supports flags in patterns" do
116
- expect(RE2.GlobalReplace("Robert", "(?i)r", "w")).to eq("wobewt")
146
+ expect(RE2.global_replace("Robert", "(?i)r", "w")).to eq("wobewt")
117
147
  end
118
148
 
119
149
  it "does not perform replacement in-place", :aggregate_failures do
120
150
  name = "Robert"
121
- replacement = RE2.GlobalReplace(name, "(?i)R", "w")
151
+ replacement = RE2.global_replace(name, "(?i)R", "w")
122
152
 
123
153
  expect(name).to eq("Robert")
124
154
  expect(replacement).to eq("wobewt")
@@ -127,75 +157,219 @@ RSpec.describe RE2 do
127
157
  it "supports passing an RE2::Regexp as the pattern" do
128
158
  re = RE2::Regexp.new('wo{2,}')
129
159
 
130
- expect(RE2.GlobalReplace("woowooo", re, "miaow")).to eq("miaowmiaow")
160
+ expect(RE2.global_replace("woowooo", re, "miaow")).to eq("miaowmiaow")
131
161
  end
132
162
 
133
163
  it "respects any passed RE2::Regexp's flags" do
134
164
  re = RE2::Regexp.new('gOOD MORNING', case_sensitive: false)
135
165
 
136
- expect(RE2.GlobalReplace("Good morning Good morning", re, "hi")).to eq("hi hi")
166
+ expect(RE2.global_replace("Good morning Good morning", re, "hi")).to eq("hi hi")
137
167
  end
138
168
 
139
169
  it "supports passing something that can be coerced to a String as input" do
140
- expect(RE2.GlobalReplace(StringLike.new("woo"), "o", "a")).to eq("waa")
170
+ expect(RE2.global_replace(StringLike.new("woo"), "o", "a")).to eq("waa")
141
171
  end
142
172
 
143
173
  it "supports passing something that can be coerced to a String as a pattern" do
144
- expect(RE2.GlobalReplace("woo", StringLike.new("o"), "a")).to eq("waa")
174
+ expect(RE2.global_replace("woo", StringLike.new("o"), "a")).to eq("waa")
145
175
  end
146
176
 
147
177
  it "supports passing something that can be coerced to a String as a replacement" do
148
- expect(RE2.GlobalReplace("woo", "o", StringLike.new("a"))).to eq("waa")
178
+ expect(RE2.global_replace("woo", "o", StringLike.new("a"))).to eq("waa")
149
179
  end
150
180
 
151
181
  it "returns UTF-8 strings if the pattern is UTF-8" do
152
182
  original = "Foo".encode("ISO-8859-1")
153
- replacement = RE2.GlobalReplace(original, "oo", "ah")
183
+ replacement = RE2.global_replace(original, "oo", "ah")
154
184
 
155
185
  expect(replacement.encoding).to eq(Encoding::UTF_8)
156
186
  end
157
187
 
158
188
  it "returns ISO-8859-1 strings if the pattern is not UTF-8" do
159
189
  original = "Foo"
160
- replacement = RE2.GlobalReplace(original, RE2("oo", utf8: false), "ah")
190
+ replacement = RE2.global_replace(original, RE2("oo", utf8: false), "ah")
161
191
 
162
192
  expect(replacement.encoding).to eq(Encoding::ISO_8859_1)
163
193
  end
164
194
 
165
195
  it "returns UTF-8 strings when given a String pattern" do
166
- replacement = RE2.GlobalReplace("Foo", "oo".encode("ISO-8859-1"), "ah")
196
+ replacement = RE2.global_replace("Foo", "oo".encode("ISO-8859-1"), "ah")
167
197
 
168
198
  expect(replacement.encoding).to eq(Encoding::UTF_8)
169
199
  end
170
200
 
171
201
  it "raises a Type Error for input that can't be converted to String" do
172
- expect { RE2.GlobalReplace(0, "o", "a") }.to raise_error(TypeError)
202
+ expect { RE2.global_replace(0, "o", "a") }.to raise_error(TypeError)
173
203
  end
174
204
 
175
205
  it "raises a Type Error for a non-RE2::Regexp pattern that can't be converted to String" do
176
- expect { RE2.GlobalReplace("woo", 0, "a") }.to raise_error(TypeError)
206
+ expect { RE2.global_replace("woo", 0, "a") }.to raise_error(TypeError)
207
+ end
208
+
209
+ it "does not leak memory when given a non-String, non-RE2::Regexp pattern" do
210
+ expect { RE2.global_replace("a" * 128, 0, "a") }.to raise_error(TypeError)
177
211
  end
178
212
 
179
213
  it "raises a Type Error for a replacement that can't be converted to String" do
180
- expect { RE2.GlobalReplace("woo", "o", 0) }.to raise_error(TypeError)
214
+ expect { RE2.global_replace("woo", "o", 0) }.to raise_error(TypeError)
215
+ end
216
+
217
+ it "can be run concurrently with the same RE2::Regexp pattern" do
218
+ re = RE2::Regexp.new('(\w+)\s(\w+)')
219
+
220
+ threads = 10.times.map do
221
+ Thread.new { RE2.global_replace("one two three four", re, '\2 \1') }
222
+ end
223
+
224
+ expect(threads.map(&:value)).to all(eq("two one four three"))
225
+ end
226
+
227
+ it "can be run concurrently with the same string pattern" do
228
+ re = '(\w+)\s(\w+)'
229
+
230
+ threads = 10.times.map do
231
+ Thread.new { RE2.global_replace("one two three four", re, '\2 \1') }
232
+ end
233
+
234
+ expect(threads.map(&:value)).to all(eq("two one four three"))
181
235
  end
182
236
  end
183
237
 
184
- describe "#QuoteMeta" do
238
+ describe ".GlobalReplace" do
239
+ it "is an alias for .global_replace" do
240
+ expect(RE2.GlobalReplace("woo", "o", "a")).to eq("waa")
241
+ end
242
+ end
243
+
244
+ describe ".extract" do
245
+ it "extracts a rewrite of the first match" do
246
+ expect(RE2.extract("alice@example.com", '(\w+)@(\w+)', '\2-\1')).to eq("example-alice")
247
+ end
248
+
249
+ it "returns nil if there is no match" do
250
+ expect(RE2.extract("no match", '(\d+)', '\1')).to be_nil
251
+ end
252
+
253
+ it "supports passing an RE2::Regexp as the pattern" do
254
+ re = RE2::Regexp.new('(\w+)@(\w+)')
255
+
256
+ expect(RE2.extract("alice@example.com", re, '\2-\1')).to eq("example-alice")
257
+ end
258
+
259
+ it "respects any passed RE2::Regexp's flags" do
260
+ re = RE2::Regexp.new('(hello)', case_sensitive: false)
261
+
262
+ expect(RE2.extract("Hello", re, '\1')).to eq("Hello")
263
+ end
264
+
265
+ it "returns UTF-8 strings if the pattern is UTF-8" do
266
+ re = RE2::Regexp.new('(foo)')
267
+ result = RE2.extract("foo", re, '\1')
268
+
269
+ expect(result.encoding.name).to eq("UTF-8")
270
+ end
271
+
272
+ it "returns ISO-8859-1 strings if the pattern is not UTF-8" do
273
+ re = RE2::Regexp.new('(foo)', utf8: false)
274
+ result = RE2.extract("foo", re, '\1')
275
+
276
+ expect(result.encoding.name).to eq("ISO-8859-1")
277
+ end
278
+
279
+ it "returns UTF-8 strings when given a String pattern" do
280
+ result = RE2.extract("foo", '(foo)', '\1')
281
+
282
+ expect(result.encoding.name).to eq("UTF-8")
283
+ end
284
+
285
+ it "supports inputs with null bytes" do
286
+ expect(RE2.extract("ab\0cd", '(a.*d)', '\1')).to eq("ab\0cd")
287
+ end
288
+
289
+ it "supports patterns with null bytes" do
290
+ expect(RE2.extract("ab\0cd", "(b\0c)", '\1')).to eq("b\0c")
291
+ end
292
+
293
+ it "supports rewrites with null bytes" do
294
+ expect(RE2.extract("abcd", '(bc)', "x\0\\1")).to eq("x\0bc")
295
+ end
296
+
297
+ it "supports passing something that can be coerced to a String as input" do
298
+ expect(RE2.extract(StringLike.new("bob123"), '(\d+)', '\1')).to eq("123")
299
+ end
300
+
301
+ it "supports passing something that can be coerced to a String as a pattern" do
302
+ expect(RE2.extract("bob123", StringLike.new('(\d+)'), '\1')).to eq("123")
303
+ end
304
+
305
+ it "supports passing something that can be coerced to a String as a rewrite" do
306
+ expect(RE2.extract("bob123", '(\d+)', StringLike.new('\1'))).to eq("123")
307
+ end
308
+
309
+ it "raises a Type Error for input that can't be converted to String" do
310
+ expect { RE2.extract(0, '(\d+)', '\1') }.to raise_error(TypeError)
311
+ end
312
+
313
+ it "raises a Type Error for a non-RE2::Regexp pattern that can't be converted to String" do
314
+ expect { RE2.extract("woo", 0, '\1') }.to raise_error(TypeError)
315
+ end
316
+
317
+ it "does not leak memory when given a non-String, non-RE2::Regexp pattern" do
318
+ expect { RE2.extract("a" * 128, 0, '\1') }.to raise_error(TypeError)
319
+ end
320
+
321
+ it "raises a Type Error for a rewrite that can't be converted to String" do
322
+ expect { RE2.extract("woo", '(\w+)', 0) }.to raise_error(TypeError)
323
+ end
324
+
325
+ it "can be run concurrently with the same RE2::Regexp pattern" do
326
+ re = RE2::Regexp.new('(\w+)@(\w+)')
327
+
328
+ threads = 10.times.map do
329
+ Thread.new { RE2.extract("alice@example", re, '\2-\1') }
330
+ end
331
+
332
+ expect(threads.map(&:value)).to all(eq("example-alice"))
333
+ end
334
+
335
+ it "can be run concurrently with the same string pattern" do
336
+ re = '(\w+)@(\w+)'
337
+
338
+ threads = 10.times.map do
339
+ Thread.new { RE2.extract("alice@example", re, '\2-\1') }
340
+ end
341
+
342
+ expect(threads.map(&:value)).to all(eq("example-alice"))
343
+ end
344
+ end
345
+
346
+ describe "#escape" do
185
347
  it "escapes a string so it can be used as a regular expression" do
186
- expect(RE2.QuoteMeta("1.5-2.0?")).to eq('1\.5\-2\.0\?')
348
+ expect(RE2.escape("1.5-2.0?")).to eq('1\.5\-2\.0\?')
187
349
  end
188
350
 
189
351
  it "raises a Type Error for input that can't be converted to String" do
190
- expect { RE2.QuoteMeta(0) }.to raise_error(TypeError)
352
+ expect { RE2.escape(0) }.to raise_error(TypeError)
191
353
  end
192
354
 
193
355
  it "supports passing something that can be coerced to a String as input" do
194
- expect(RE2.QuoteMeta(StringLike.new("1.5"))).to eq('1\.5')
356
+ expect(RE2.escape(StringLike.new("1.5"))).to eq('1\.5')
195
357
  end
196
358
 
197
359
  it "supports strings containing null bytes" do
198
- expect(RE2.QuoteMeta("abc\0def")).to eq('abc\x00def')
360
+ expect(RE2.escape("abc\0def")).to eq('abc\x00def')
361
+ end
362
+ end
363
+
364
+ describe ".quote" do
365
+ it "is an alias for .escape" do
366
+ expect(RE2.quote("1.5-2.0?")).to eq('1\.5\-2\.0\?')
367
+ end
368
+ end
369
+
370
+ describe ".QuoteMeta" do
371
+ it "is an alias for .escape" do
372
+ expect(RE2.QuoteMeta("1.5-2.0?")).to eq('1\.5\-2\.0\?')
199
373
  end
200
374
  end
201
375
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: re2
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.23.0
4
+ version: 2.27.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Mucur
@@ -88,7 +88,7 @@ files:
88
88
  - lib/re2/scanner.rb
89
89
  - lib/re2/string.rb
90
90
  - lib/re2/version.rb
91
- - ports/archives/20250814.1.tar.gz
91
+ - ports/archives/20260107.1.tar.gz
92
92
  - ports/archives/re2-2025-11-05.tar.gz
93
93
  - re2.gemspec
94
94
  - spec/kernel_spec.rb
@@ -117,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
117
  - !ruby/object:Gem::Version
118
118
  version: '0'
119
119
  requirements: []
120
- rubygems_version: 4.0.3
120
+ rubygems_version: 4.0.6
121
121
  specification_version: 4
122
122
  summary: Ruby bindings to RE2.
123
123
  test_files:
Binary file