From 64106c4d3d4ddba8c7bc2af75376e6d3d3d75601 Mon Sep 17 00:00:00 2001
From:
Date: Mon, 29 Jun 2015 20:16:15 +0000
Subject: Update documentation
---
src/regex/char.rs.html | 311 ++++++
src/regex/input.rs.html | 325 ++++++
src/regex/lib.rs.html | 959 ++++++++++++++++++
src/regex/program.rs.html | 1057 ++++++++++++++++++++
src/regex/re.rs.html | 2393 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 5045 insertions(+)
create mode 100644 src/regex/char.rs.html
create mode 100644 src/regex/input.rs.html
create mode 100644 src/regex/lib.rs.html
create mode 100644 src/regex/program.rs.html
create mode 100644 src/regex/re.rs.html
(limited to 'src/regex')
diff --git a/src/regex/char.rs.html b/src/regex/char.rs.html
new file mode 100644
index 0000000..f830f03
--- /dev/null
+++ b/src/regex/char.rs.html
@@ -0,0 +1,311 @@
+
+
+
+ 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
+
+
+
+
+
+
+
+
+
+
+
+use std::char;
+use std::cmp::Ordering;
+use std::fmt;
+use std::u32;
+
+use syntax;
+
+
+
+
+
+
+
+
+
+#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Char(u32);
+
+impl fmt::Debug for Char {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match char::from_u32(self.0) {
+ None => write!(f, "Empty"),
+ Some(c) => write!(f, "{:?}", c),
+ }
+ }
+}
+
+impl Char {
+
+ #[inline]
+ pub fn is_none(self) -> bool { self.0 == u32::MAX }
+
+
+
+
+ #[inline]
+ pub fn len_utf8(self) -> usize {
+ char::from_u32(self.0).map(|c| c.len_utf8()).unwrap_or(0)
+ }
+
+
+
+
+ pub fn case_fold(self) -> Char {
+ char::from_u32(self.0).map(syntax::simple_case_fold).into()
+ }
+
+
+
+
+ pub fn is_word_char(self) -> bool {
+ char::from_u32(self.0).map(syntax::is_word_char).unwrap_or(false)
+ }
+
+
+
+
+ pub fn as_char(self) -> Option<char> {
+
+
+ char::from_u32(self.0)
+ }
+}
+
+impl From<char> for Char {
+ fn from(c: char) -> Char { Char(c as u32) }
+}
+
+impl From<Option<char>> for Char {
+ fn from(c: Option<char>) -> Char {
+ c.map(|c| c.into()).unwrap_or(Char(u32::MAX))
+ }
+}
+
+impl PartialEq<char> for Char {
+ #[inline]
+ fn eq(&self, other: &char) -> bool { self.0 == *other as u32 }
+}
+
+impl PartialEq<Char> for char {
+ #[inline]
+ fn eq(&self, other: &Char) -> bool { *self as u32 == other.0 }
+}
+
+impl PartialOrd<char> for Char {
+ #[inline]
+ fn partial_cmp(&self, other: &char) -> Option<Ordering> {
+ self.0.partial_cmp(&(*other as u32))
+ }
+}
+
+impl PartialOrd<Char> for char {
+ #[inline]
+ fn partial_cmp(&self, other: &Char) -> Option<Ordering> {
+ (*self as u32).partial_cmp(&other.0)
+ }
+}
+
+
+ 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
+
+
+
+
+
+
+
+
+
+
+
+use std::ops;
+
+use char::Char;
+use prefix::Prefix;
+
+
+#[derive(Clone, Copy, Debug)]
+pub struct InputAt {
+ pos: usize,
+ c: Char,
+ len: usize,
+}
+
+impl InputAt {
+
+ pub fn is_beginning(&self) -> bool {
+ self.pos == 0
+ }
+
+
+
+
+
+ pub fn char(&self) -> Char {
+ self.c
+ }
+
+
+ pub fn len(&self) -> usize {
+ self.len
+ }
+
+
+ pub fn pos(&self) -> usize {
+ self.pos
+ }
+
+
+ pub fn next_pos(&self) -> usize {
+ self.pos + self.len
+ }
+}
+
+
+pub trait Input {
+
+ fn at(&self, i: usize) -> InputAt;
+
+ fn previous_at(&self, i: usize) -> InputAt;
+
+ fn prefix_at(&self, prefixes: &Prefix, at: InputAt) -> Option<InputAt>;
+}
+
+
+
+
+#[derive(Debug)]
+pub struct CharInput<'t>(&'t str);
+
+impl<'t> CharInput<'t> {
+
+ pub fn new(s: &'t str) -> CharInput<'t> {
+ CharInput(s)
+ }
+}
+
+impl<'t> ops::Deref for CharInput<'t> {
+ type Target = str;
+
+ fn deref(&self) -> &str {
+ self.0
+ }
+}
+
+impl<'t> Input for CharInput<'t> {
+
+
+
+
+
+ #[inline(always)]
+ fn at(&self, i: usize) -> InputAt {
+ let c = self[i..].chars().next().into();
+ InputAt {
+ pos: i,
+ c: c,
+ len: c.len_utf8(),
+ }
+ }
+
+ fn previous_at(&self, i: usize) -> InputAt {
+ let c: Char = self[..i].chars().rev().next().into();
+ let len = c.len_utf8();
+ InputAt {
+ pos: i - len,
+ c: c,
+ len: len,
+ }
+ }
+
+ fn prefix_at(&self, prefixes: &Prefix, at: InputAt) -> Option<InputAt> {
+ prefixes.find(&self[at.pos()..]).map(|(s, _)| self.at(at.pos() + s))
+ }
+}
+
+
+ 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
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#![deny(missing_docs)]
+#![cfg_attr(test, deny(warnings))]
+#![cfg_attr(feature = "pattern", feature(pattern))]
+#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://doc.rust-lang.org/regex/")]
+
+extern crate aho_corasick;
+extern crate memchr;
+extern crate regex_syntax as syntax;
+
+pub use re::{
+ Regex, Error, Captures, SubCaptures, SubCapturesPos, SubCapturesNamed,
+ FindCaptures, FindMatches,
+ Replacer, NoExpand, RegexSplits, RegexSplitsN,
+ quote, is_match,
+};
+
+mod backtrack;
+mod char;
+mod compile;
+mod input;
+mod pool;
+mod prefix;
+mod program;
+mod nfa;
+mod re;
+
+
+
+#[doc(hidden)]
+pub mod internal {
+ pub use char::Char;
+ pub use input::{Input, CharInput, InputAt};
+ pub use program::{
+ Program, MatchEngine, CharRanges, Inst, LookInst, OneChar,
+ };
+ pub use re::ExNative;
+ pub use re::Regex::{Dynamic, Native};
+}
+
+
+ 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
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+
+
+
+
+
+
+
+
+
+
+
+use std::cmp::{self, Ordering};
+
+use syntax;
+
+use Error;
+use backtrack::{Backtrack, BackMachine};
+use char::Char;
+use compile::Compiler;
+use nfa::{Nfa, NfaThreads};
+use pool::Pool;
+use prefix::Prefix;
+use re::CaptureIdxs;
+
+const NUM_PREFIX_LIMIT: usize = 30;
+const PREFIX_LENGTH_LIMIT: usize = 15;
+
+pub type InstIdx = usize;
+
+
+#[derive(Clone, Debug)]
+pub enum Inst {
+
+
+
+
+ Match,
+
+ Save(usize),
+
+ Jump(InstIdx),
+
+ Split(InstIdx, InstIdx),
+
+
+ EmptyLook(LookInst),
+
+ Char(OneChar),
+
+ Ranges(CharRanges),
+}
+
+
+#[derive(Clone, Debug)]
+pub struct OneChar {
+
+ pub c: char,
+
+
+ pub casei: bool,
+}
+
+
+#[derive(Clone, Debug)]
+pub struct CharRanges {
+
+ pub ranges: Vec<(char, char)>,
+
+ pub casei: bool,
+}
+
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum LookInst {
+
+ StartLine,
+
+ EndLine,
+
+ StartText,
+
+ EndText,
+
+ WordBoundary,
+
+ NotWordBoundary,
+}
+
+impl OneChar {
+
+ #[inline(always)]
+ pub fn matches(&self, c: Char) -> bool {
+ self.c == c || (self.casei && self.c == c.case_fold())
+ }
+}
+
+impl CharRanges {
+
+ pub fn any() -> CharRanges {
+ CharRanges {
+ ranges: vec![('\x00', '\u{10ffff}')],
+ casei: false,
+ }
+ }
+
+
+ pub fn any_nonl() -> CharRanges {
+ CharRanges {
+ ranges: vec![('\x00', '\x09'), ('\x0B', '\u{10ffff}')],
+ casei: false,
+ }
+ }
+
+
+ pub fn from_class(cls: syntax::CharClass) -> CharRanges {
+ let casei = cls.is_case_insensitive();
+ CharRanges {
+ ranges: cls.into_iter().map(|r| (r.start, r.end)).collect(),
+ casei: casei,
+ }
+ }
+
+
+ #[inline(always)]
+ pub fn matches(&self, mut c: Char) -> Option<usize> {
+ if self.casei {
+ c = c.case_fold();
+ }
+
+
+
+ for i in 0..cmp::min(self.ranges.len(), 4) {
+ let r = self.ranges[i];
+ if c < r.0 {
+ return None;
+ }
+ if c <= r.1 {
+ return Some(i);
+ }
+ }
+ self.ranges.binary_search_by(|r| {
+ if r.1 < c {
+ Ordering::Less
+ } else if r.0 > c {
+ Ordering::Greater
+ } else {
+ Ordering::Equal
+ }
+ }).ok()
+ }
+}
+
+impl LookInst {
+
+
+ pub fn matches(&self, c1: Char, c2: Char) -> bool {
+ use self::LookInst::*;
+ match *self {
+ StartLine => c1.is_none() || c1 == '\n',
+ EndLine => c2.is_none() || c2 == '\n',
+ StartText => c1.is_none(),
+ EndText => c2.is_none(),
+ ref wbty => {
+ let (w1, w2) = (c1.is_word_char(), c2.is_word_char());
+ (*wbty == WordBoundary && w1 ^ w2)
+ || (*wbty == NotWordBoundary && !(w1 ^ w2))
+ }
+ }
+ }
+}
+
+
+
+
+#[doc(hidden)]
+#[derive(Clone, Copy, Debug)]
+pub enum MatchEngine {
+
+
+ Backtrack,
+
+
+ Nfa,
+
+
+ Literals,
+}
+
+
+
+
+
+
+#[derive(Debug)]
+pub struct Program {
+
+ pub original: String,
+
+ pub insts: Vec<Inst>,
+
+
+ pub cap_names: Vec<Option<String>>,
+
+
+ pub prefixes: Prefix,
+
+ pub prefixes_complete: bool,
+
+ pub anchored_begin: bool,
+
+ pub anchored_end: bool,
+
+
+ pub engine: Option<MatchEngine>,
+
+ pub nfa_threads: Pool<NfaThreads>,
+
+ pub backtrack: Pool<BackMachine>,
+}
+
+impl Program {
+
+ pub fn new(
+ engine: Option<MatchEngine>,
+ size_limit: usize,
+ re: &str,
+ ) -> Result<Program, Error> {
+ let expr = try!(syntax::Expr::parse(re));
+ let (insts, cap_names) = try!(Compiler::new(size_limit).compile(expr));
+ let (insts_len, ncaps) = (insts.len(), num_captures(&insts));
+ let create_threads = move || NfaThreads::new(insts_len, ncaps);
+ let create_backtrack = move || BackMachine::new();
+ let mut prog = Program {
+ original: re.into(),
+ insts: insts,
+ cap_names: cap_names,
+ prefixes: Prefix::Empty,
+ prefixes_complete: false,
+ anchored_begin: false,
+ anchored_end: false,
+ engine: engine,
+ nfa_threads: Pool::new(Box::new(create_threads)),
+ backtrack: Pool::new(Box::new(create_backtrack)),
+ };
+
+ prog.find_prefixes();
+ prog.anchored_begin = match prog.insts[1] {
+ Inst::EmptyLook(LookInst::StartText) => true,
+ _ => false,
+ };
+ prog.anchored_end = match prog.insts[prog.insts.len() - 3] {
+ Inst::EmptyLook(LookInst::EndText) => true,
+ _ => false,
+ };
+ Ok(prog)
+ }
+
+
+ pub fn exec(
+ &self,
+ caps: &mut CaptureIdxs,
+ text: &str,
+ start: usize,
+ ) -> bool {
+ match self.choose_engine(caps.len(), text) {
+ MatchEngine::Backtrack => Backtrack::exec(self, caps, text, start),
+ MatchEngine::Nfa => Nfa::exec(self, caps, text, start),
+ MatchEngine::Literals => {
+ match self.prefixes.find(&text[start..]) {
+ None => false,
+ Some((s, e)) => {
+ if caps.len() == 2 {
+ caps[0] = Some(start + s);
+ caps[1] = Some(start + e);
+ }
+ true
+ }
+ }
+ }
+ }
+ }
+
+ fn choose_engine(&self, cap_len: usize, text: &str) -> MatchEngine {
+
+
+
+
+ self.engine.unwrap_or_else(|| {
+ if cap_len <= 2
+ && self.prefixes.preserves_priority()
+ && self.prefixes_complete {
+ MatchEngine::Literals
+ } else if Backtrack::should_exec(self, text) {
+
+ MatchEngine::Backtrack
+ } else {
+ MatchEngine::Nfa
+ }
+ })
+ }
+
+
+
+ pub fn num_captures(&self) -> usize {
+ num_captures(&self.insts)
+ }
+
+
+ pub fn alloc_captures(&self) -> Vec<Option<usize>> {
+ vec![None; 2 * self.num_captures()]
+ }
+
+
+ pub fn find_prefixes(&mut self) {
+ use self::Inst::*;
+
+ let (ps, complete) = self.prefixes_from_insts(1);
+ if ps.len() > 0 {
+ self.prefixes = Prefix::new(ps);
+ self.prefixes_complete = complete;
+ return;
+ }
+ let mut pc = 1;
+ let mut prefixes = vec![];
+ let mut pcomplete = true;
+ while let Split(x, y) = self.insts[pc] {
+ let (xps, xcomplete) = self.prefixes_from_insts(x);
+ let (yps, ycomplete) = self.prefixes_from_insts(y);
+ let mut done = false;
+ match (&self.insts[x], &self.insts[y]) {
+
+ (&Split(_, _), &Split(_, _)) => return,
+ (_, &Split(_, _)) if xps.len() == 0 => return,
+ (_, &Split(_, _)) => {
+ pcomplete = pcomplete && xcomplete;
+ prefixes.extend(xps);
+ pc = y;
+ }
+ (&Split(_, _), _) if yps.len() == 0 => return,
+ (&Split(_, _), _) => {
+ pcomplete = pcomplete && ycomplete;
+ prefixes.extend(yps);
+ pc = x;
+ }
+ _ if xps.len() == 0 || yps.len() == 0 => return,
+
+
+ _ => {
+ pcomplete = pcomplete && xcomplete && ycomplete;
+ prefixes.extend(xps);
+ prefixes.extend(yps);
+ done = true;
+ }
+ }
+
+
+ if prefixes.len() > NUM_PREFIX_LIMIT {
+ return;
+ }
+ if done { break; }
+ }
+ self.prefixes = Prefix::new(prefixes);
+ self.prefixes_complete = pcomplete && self.prefixes.len() > 0;
+ }
+
+
+
+
+
+
+ fn prefixes_from_insts(&self, mut pc: usize) -> (Vec<String>, bool) {
+ use self::Inst::*;
+
+ let mut complete = true;
+ let mut alts = vec![String::new()];
+ while pc < self.insts.len() {
+ let inst = &self.insts[pc];
+
+
+
+
+
+ if alts[0].len() > PREFIX_LENGTH_LIMIT {
+ complete = false;
+ break;
+ }
+ match *inst {
+ Save(_) => { pc += 1; continue }
+ Char(OneChar { c, casei: false }) => {
+ for alt in &mut alts {
+ alt.push(c);
+ }
+ pc += 1;
+ }
+ Ranges(CharRanges { ref ranges, casei: false }) => {
+ let nchars = num_chars_in_ranges(ranges);
+ if alts.len() * nchars > NUM_PREFIX_LIMIT {
+ complete = false;
+ break;
+ }
+
+ let orig = alts;
+ alts = Vec::with_capacity(orig.len());
+ for &(s, e) in ranges {
+ for c in (s as u32)..(e as u32 + 1){
+ for alt in &orig {
+ let mut alt = alt.clone();
+ alt.push(::std::char::from_u32(c).unwrap());
+ alts.push(alt);
+ }
+ }
+ }
+ pc += 1;
+ }
+ Jump(pc2) => pc = pc2,
+ _ => { complete = self.leads_to_match(pc); break }
+ }
+ }
+ if alts[0].len() == 0 {
+ (vec![], false)
+ } else {
+ (alts, complete)
+ }
+ }
+
+ fn leads_to_match(&self, mut pc: usize) -> bool {
+
+
+ loop {
+ match self.insts[pc] {
+ Inst::Match => return true,
+ Inst::Save(_) => pc += 1,
+ Inst::Jump(pc2) => pc = pc2,
+ _ => return false,
+ }
+ }
+ }
+}
+
+impl Clone for Program {
+ fn clone(&self) -> Program {
+ let (insts_len, ncaps) = (self.insts.len(), self.num_captures());
+ let create_threads = move || NfaThreads::new(insts_len, ncaps);
+ let create_backtrack = move || BackMachine::new();
+ Program {
+ original: self.original.clone(),
+ insts: self.insts.clone(),
+ cap_names: self.cap_names.clone(),
+ prefixes: self.prefixes.clone(),
+ prefixes_complete: self.prefixes_complete,
+ anchored_begin: self.anchored_begin,
+ anchored_end: self.anchored_end,
+ engine: self.engine,
+ nfa_threads: Pool::new(Box::new(create_threads)),
+ backtrack: Pool::new(Box::new(create_backtrack)),
+ }
+ }
+}
+
+
+fn num_captures(insts: &[Inst]) -> usize {
+ let mut n = 0;
+ for inst in insts {
+ match *inst {
+ Inst::Save(c) => n = cmp::max(n, c+1),
+ _ => {}
+ }
+ }
+
+ n / 2
+}
+
+
+
+
+
+fn num_chars_in_ranges(ranges: &[(char, char)]) -> usize {
+ ranges.iter()
+ .map(|&(s, e)| (e as u32) - (s as u32))
+ .fold(0, |acc, len| acc + len) as usize
+}
+
+
+ 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
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+
+
+
+
+
+
+
+
+
+
+
+use std::borrow::Cow;
+use std::collections::HashMap;
+use std::collections::hash_map::Iter;
+use std::fmt;
+#[cfg(feature = "pattern")]
+use std::str::pattern::{Pattern, Searcher, SearchStep};
+use std::str::FromStr;
+
+use program::{Program, MatchEngine};
+use syntax;
+
+const REPLACE_EXPAND: &'static str = r"(?x)
+ (?P<before>^|\b|[^$]) # Ignore `$$name`.
+ \$
+ (?P<name> # Match the actual capture name. Can be...
+ [0-9]+ # A sequence of digits (for indexed captures), or...
+ |
+ [_a-zA-Z][_0-9a-zA-Z]* # A name for named captures.
+ )
+";
+
+
+pub type CaptureIdxs = [Option<usize>];
+
+
+
+
+
+pub fn quote(text: &str) -> String {
+ let mut quoted = String::with_capacity(text.len());
+ for c in text.chars() {
+ if syntax::is_punct(c) {
+ quoted.push('\\')
+ }
+ quoted.push(c);
+ }
+ quoted
+}
+
+
+
+
+
+
+
+
+pub fn is_match(regex: &str, text: &str) -> Result<bool, Error> {
+ Regex::new(regex).map(|r| r.is_match(text))
+}
+
+
+#[derive(Debug)]
+pub enum Error {
+
+ Syntax(syntax::Error),
+
+
+ CompiledTooBig(usize),
+
+
+
+
+
+ #[doc(hidden)]
+ __Nonexhaustive,
+}
+
+impl ::std::error::Error for Error {
+ fn description(&self) -> &str {
+ match *self {
+ Error::Syntax(ref err) => err.description(),
+ Error::CompiledTooBig(_) => "compiled program too big",
+ Error::__Nonexhaustive => unreachable!(),
+ }
+ }
+
+ fn cause(&self) -> Option<&::std::error::Error> {
+ match *self {
+ Error::Syntax(ref err) => Some(err),
+ _ => None,
+ }
+ }
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ Error::Syntax(ref err) => err.fmt(f),
+ Error::CompiledTooBig(limit) => {
+ write!(f, "Compiled regex exceeds size limit of {} bytes.",
+ limit)
+ }
+ Error::__Nonexhaustive => unreachable!(),
+ }
+ }
+}
+
+impl From<syntax::Error> for Error {
+ fn from(err: syntax::Error) -> Error {
+ Error::Syntax(err)
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#[derive(Clone)]
+pub enum Regex {
+
+
+
+
+
+ #[doc(hidden)]
+ Dynamic(Program),
+ #[doc(hidden)]
+ Native(ExNative),
+}
+
+#[doc(hidden)]
+pub struct ExNative {
+ #[doc(hidden)]
+ pub original: &'static str,
+ #[doc(hidden)]
+ pub names: &'static &'static [Option<&'static str>],
+ #[doc(hidden)]
+ pub prog: fn(&mut CaptureIdxs, &str, usize) -> bool,
+}
+
+impl Copy for ExNative {}
+
+impl Clone for ExNative {
+ fn clone(&self) -> ExNative {
+ *self
+ }
+}
+
+impl fmt::Display for Regex {
+
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.as_str())
+ }
+}
+
+impl fmt::Debug for Regex {
+
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(self, f)
+ }
+}
+
+
+
+
+
+impl PartialEq for Regex {
+ fn eq(&self, other: &Regex) -> bool {
+ self.as_str() == other.as_str()
+ }
+}
+
+impl Eq for Regex {}
+
+impl FromStr for Regex {
+ type Err = Error;
+
+
+ fn from_str(s: &str) -> Result<Regex, Error> {
+ Regex::new(s)
+ }
+}
+
+impl Regex {
+
+
+
+
+ pub fn new(re: &str) -> Result<Regex, Error> {
+ Regex::with_size_limit(10 * (1 << 20), re)
+ }
+
+
+
+
+
+
+
+
+ pub fn with_size_limit(size: usize, re: &str) -> Result<Regex, Error> {
+ Regex::with_engine(None, size, re)
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #[doc(hidden)]
+ pub fn with_engine(
+ engine: Option<MatchEngine>,
+ size: usize,
+ re: &str,
+ ) -> Result<Regex, Error> {
+ Program::new(engine, size, re).map(Regex::Dynamic)
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pub fn is_match(&self, text: &str) -> bool {
+ exec(self, &mut [], text, 0)
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pub fn find(&self, text: &str) -> Option<(usize, usize)> {
+ let mut caps = [None, None];
+ if exec(self, &mut caps, text, 0) {
+ Some((caps[0].unwrap(), caps[1].unwrap()))
+ } else {
+ None
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pub fn find_iter<'r, 't>(&'r self, text: &'t str) -> FindMatches<'r, 't> {
+ FindMatches {
+ re: self,
+ search: text,
+ last_end: 0,
+ last_match: None,
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pub fn captures<'t>(&self, text: &'t str) -> Option<Captures<'t>> {
+ let mut caps = self.alloc_captures();
+ if exec(self, &mut caps, text, 0) {
+ Some(Captures::new(self, text, caps))
+ } else {
+ None
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pub fn captures_iter<'r, 't>(&'r self, text: &'t str)
+ -> FindCaptures<'r, 't> {
+ FindCaptures {
+ re: self,
+ search: text,
+ last_match: None,
+ last_end: 0,
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pub fn split<'r, 't>(&'r self, text: &'t str) -> RegexSplits<'r, 't> {
+ RegexSplits {
+ finder: self.find_iter(text),
+ last: 0,
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pub fn splitn<'r, 't>(&'r self, text: &'t str, limit: usize)
+ -> RegexSplitsN<'r, 't> {
+ RegexSplitsN {
+ splits: self.split(text),
+ cur: 0,
+ limit: limit,
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pub fn replace<R: Replacer>(&self, text: &str, rep: R) -> String {
+ self.replacen(text, 1, rep)
+ }
+
+
+
+
+
+
+
+ pub fn replace_all<R: Replacer>(&self, text: &str, rep: R) -> String {
+ self.replacen(text, 0, rep)
+ }
+
+
+
+
+
+
+
+ pub fn replacen<R: Replacer>
+ (&self, text: &str, limit: usize, mut rep: R) -> String {
+ let mut new = String::with_capacity(text.len());
+ let mut last_match = 0;
+
+ if rep.no_expand().is_some() {
+
+
+ let rep = rep.no_expand().unwrap();
+ for (i, (s, e)) in self.find_iter(text).enumerate() {
+ if limit > 0 && i >= limit {
+ break
+ }
+ new.push_str(&text[last_match..s]);
+ new.push_str(&rep);
+ last_match = e;
+ }
+ } else {
+ for (i, cap) in self.captures_iter(text).enumerate() {
+ if limit > 0 && i >= limit {
+ break
+ }
+
+ let (s, e) = cap.pos(0).unwrap();
+ new.push_str(&text[last_match..s]);
+ new.push_str(&rep.reg_replace(&cap));
+ last_match = e;
+ }
+ }
+ new.push_str(&text[last_match..]);
+ new
+ }
+
+
+ pub fn as_str<'a>(&'a self) -> &'a str {
+ match *self {
+ Regex::Dynamic(Program { ref original, .. }) => original,
+ Regex::Native(ExNative { ref original, .. }) => original,
+ }
+ }
+
+ #[doc(hidden)]
+ pub fn names_iter<'a>(&'a self) -> NamesIter<'a> {
+ match *self {
+ Regex::Native(ref n) => NamesIter::Native(n.names.iter()),
+ Regex::Dynamic(ref d) => NamesIter::Dynamic(d.cap_names.iter())
+ }
+ }
+
+ fn names_len(&self) -> usize {
+ match *self {
+ Regex::Native(ref n) => n.names.len(),
+ Regex::Dynamic(ref d) => d.cap_names.len()
+ }
+ }
+
+ fn alloc_captures(&self) -> Vec<Option<usize>> {
+ match *self {
+ Regex::Native(ref n) => vec![None; 2 * n.names.len()],
+ Regex::Dynamic(ref d) => d.alloc_captures(),
+ }
+ }
+}
+
+pub enum NamesIter<'a> {
+ Native(::std::slice::Iter<'a, Option<&'static str>>),
+ Dynamic(::std::slice::Iter<'a, Option<String>>)
+}
+
+impl<'a> Iterator for NamesIter<'a> {
+ type Item=Option<String>;
+
+ fn next(&mut self) -> Option<Option<String>> {
+ match *self {
+ NamesIter::Native(ref mut i) =>
+ i.next().map(|x| x.map(|s| s.to_owned())),
+ NamesIter::Dynamic(ref mut i) =>
+ i.next().map(|x| x.as_ref().map(|s| s.to_owned())),
+ }
+ }
+}
+
+
+
+
+
+
+
+
+pub struct NoExpand<'t>(pub &'t str);
+
+
+pub trait Replacer {
+
+
+
+
+
+ fn reg_replace<'a>(&'a mut self, caps: &Captures) -> Cow<'a, str>;
+
+
+ fn no_expand<'a>(&'a mut self) -> Option<Cow<'a, str>> { None }
+}
+
+impl<'t> Replacer for NoExpand<'t> {
+ fn reg_replace<'a>(&'a mut self, _: &Captures) -> Cow<'a, str> {
+ self.0.into()
+ }
+
+ fn no_expand<'a>(&'a mut self) -> Option<Cow<'a, str>> {
+ Some(self.0.into())
+ }
+}
+
+impl<'t> Replacer for &'t str {
+ fn reg_replace<'a>(&'a mut self, caps: &Captures) -> Cow<'a, str> {
+ caps.expand(*self).into()
+ }
+
+ fn no_expand<'a>(&'a mut self) -> Option<Cow<'a, str>> {
+ let re = Regex::new(REPLACE_EXPAND).unwrap();
+ if !re.is_match(self) {
+ Some((*self).into())
+ } else {
+ None
+ }
+ }
+}
+
+impl<F> Replacer for F where F: FnMut(&Captures) -> String {
+ fn reg_replace<'a>(&'a mut self, caps: &Captures) -> Cow<'a, str> {
+ (*self)(caps).into()
+ }
+}
+
+
+
+
+
+pub struct RegexSplits<'r, 't> {
+ finder: FindMatches<'r, 't>,
+ last: usize,
+}
+
+impl<'r, 't> Iterator for RegexSplits<'r, 't> {
+ type Item = &'t str;
+
+ fn next(&mut self) -> Option<&'t str> {
+ let text = self.finder.search;
+ match self.finder.next() {
+ None => {
+ if self.last >= text.len() {
+ None
+ } else {
+ let s = &text[self.last..];
+ self.last = text.len();
+ Some(s)
+ }
+ }
+ Some((s, e)) => {
+ let matched = &text[self.last..s];
+ self.last = e;
+ Some(matched)
+ }
+ }
+ }
+}
+
+
+
+
+
+
+
+pub struct RegexSplitsN<'r, 't> {
+ splits: RegexSplits<'r, 't>,
+ cur: usize,
+ limit: usize,
+}
+
+impl<'r, 't> Iterator for RegexSplitsN<'r, 't> {
+ type Item = &'t str;
+
+ fn next(&mut self) -> Option<&'t str> {
+ let text = self.splits.finder.search;
+ if self.cur >= self.limit {
+ None
+ } else {
+ self.cur += 1;
+ if self.cur >= self.limit {
+ Some(&text[self.splits.last..])
+ } else {
+ self.splits.next()
+ }
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+pub struct Captures<'t> {
+ text: &'t str,
+ locs: Vec<Option<usize>>,
+ named: Option<HashMap<String, usize>>,
+}
+
+impl<'t> Captures<'t> {
+ fn new(
+ re: &Regex,
+ search: &'t str,
+ locs: Vec<Option<usize>>,
+ ) -> Captures<'t> {
+ let named =
+ if re.names_len() == 0 {
+ None
+ } else {
+ let mut named = HashMap::new();
+ for (i, name) in re.names_iter().enumerate() {
+ if let Some(name) = name {
+ named.insert(name, i);
+ }
+ }
+ Some(named)
+ };
+ Captures {
+ text: search,
+ locs: locs,
+ named: named,
+ }
+ }
+
+
+
+
+
+
+ pub fn pos(&self, i: usize) -> Option<(usize, usize)> {
+ let (s, e) = (i * 2, i * 2 + 1);
+ if e >= self.locs.len() || self.locs[s].is_none() {
+
+ return None
+ }
+ Some((self.locs[s].unwrap(), self.locs[e].unwrap()))
+ }
+
+
+
+
+ pub fn at(&self, i: usize) -> Option<&'t str> {
+ match self.pos(i) {
+ None => None,
+ Some((s, e)) => Some(&self.text[s..e])
+ }
+ }
+
+
+
+
+ pub fn name(&self, name: &str) -> Option<&'t str> {
+ match self.named {
+ None => None,
+ Some(ref h) => {
+ match h.get(name) {
+ None => None,
+ Some(i) => self.at(*i),
+ }
+ }
+ }
+ }
+
+
+
+ pub fn iter(&'t self) -> SubCaptures<'t> {
+ SubCaptures { idx: 0, caps: self, }
+ }
+
+
+
+
+ pub fn iter_pos(&'t self) -> SubCapturesPos<'t> {
+ SubCapturesPos { idx: 0, caps: self, }
+ }
+
+
+
+
+ pub fn iter_named(&'t self) -> SubCapturesNamed<'t> {
+ SubCapturesNamed { caps: self, inner: self.named.as_ref().map(|n| n.iter()) }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pub fn expand(&self, text: &str) -> String {
+
+ let re = Regex::new(REPLACE_EXPAND).unwrap();
+ let text = re.replace_all(text, |refs: &Captures| -> String {
+ let before = refs.name("before").unwrap_or("");
+ let name = refs.name("name").unwrap_or("");
+ format!("{}{}", before, match name.parse::<usize>() {
+ Err(_) => self.name(name).unwrap_or("").to_string(),
+ Ok(i) => self.at(i).unwrap_or("").to_string(),
+ })
+ });
+ let re = Regex::new(r"\$\$").unwrap();
+ re.replace_all(&text, NoExpand("$"))
+ }
+
+
+ #[inline]
+ pub fn len(&self) -> usize { self.locs.len() / 2 }
+
+
+ #[inline]
+ pub fn is_empty(&self) -> bool { self.len() == 0 }
+}
+
+
+
+
+
+pub struct SubCaptures<'t> {
+ idx: usize,
+ caps: &'t Captures<'t>,
+}
+
+impl<'t> Iterator for SubCaptures<'t> {
+ type Item = Option<&'t str>;
+
+ fn next(&mut self) -> Option<Option<&'t str>> {
+ if self.idx < self.caps.len() {
+ self.idx += 1;
+ Some(self.caps.at(self.idx - 1))
+ } else {
+ None
+ }
+ }
+}
+
+
+
+
+
+
+
+pub struct SubCapturesPos<'t> {
+ idx: usize,
+ caps: &'t Captures<'t>,
+}
+
+impl<'t> Iterator for SubCapturesPos<'t> {
+ type Item = Option<(usize, usize)>;
+
+ fn next(&mut self) -> Option<Option<(usize, usize)>> {
+ if self.idx < self.caps.len() {
+ self.idx += 1;
+ Some(self.caps.pos(self.idx - 1))
+ } else {
+ None
+ }
+ }
+}
+
+
+
+
+
+pub struct SubCapturesNamed<'t>{
+ caps: &'t Captures<'t>,
+ inner: Option<Iter<'t, String, usize>>,
+}
+
+impl<'t> Iterator for SubCapturesNamed<'t> {
+ type Item = (&'t str, Option<&'t str>);
+
+ fn next(&mut self) -> Option<(&'t str, Option<&'t str>)> {
+ match self.inner.as_mut().map(|it| it.next()).unwrap_or(None) {
+ Some((name, pos)) => Some((name, self.caps.at(*pos))),
+ None => None
+ }
+ }
+}
+
+
+
+
+
+
+
+
+pub struct FindCaptures<'r, 't> {
+ re: &'r Regex,
+ search: &'t str,
+ last_match: Option<usize>,
+ last_end: usize,
+}
+
+impl<'r, 't> Iterator for FindCaptures<'r, 't> {
+ type Item = Captures<'t>;
+
+ fn next(&mut self) -> Option<Captures<'t>> {
+ if self.last_end > self.search.len() {
+ return None
+ }
+
+ let mut caps = self.re.alloc_captures();
+ if !exec(self.re, &mut caps, self.search, self.last_end) {
+ return None
+ }
+ let (s, e) = (caps[0].unwrap(), caps[1].unwrap());
+
+
+
+ if e == s && Some(self.last_end) == self.last_match {
+ if self.last_end >= self.search.len() {
+ return None;
+ }
+ self.last_end += self.search[self.last_end..].chars()
+ .next().unwrap().len_utf8();
+ return self.next()
+ }
+ self.last_end = e;
+ self.last_match = Some(self.last_end);
+ Some(Captures::new(self.re, self.search, caps))
+ }
+}
+
+
+
+
+
+
+
+
+
+pub struct FindMatches<'r, 't> {
+ re: &'r Regex,
+ search: &'t str,
+ last_match: Option<usize>,
+ last_end: usize,
+}
+
+impl<'r, 't> Iterator for FindMatches<'r, 't> {
+ type Item = (usize, usize);
+
+ fn next(&mut self) -> Option<(usize, usize)> {
+ if self.last_end > self.search.len() {
+ return None
+ }
+
+ let mut caps = [None, None];
+ if !exec(self.re, &mut caps, self.search, self.last_end) {
+ return None;
+ }
+ let (s, e) = (caps[0].unwrap(), caps[1].unwrap());
+
+
+
+ if e == s && Some(self.last_end) == self.last_match {
+ if self.last_end >= self.search.len() {
+ return None;
+ }
+ self.last_end += self.search[self.last_end..].chars()
+ .next().unwrap().len_utf8();
+ return self.next()
+ }
+ self.last_end = e;
+ self.last_match = Some(self.last_end);
+ Some((s, e))
+ }
+}
+
+#[cfg(feature = "pattern")]
+pub struct RegexSearcher<'r, 't> {
+ it: FindMatches<'r, 't>,
+ last_step_end: usize,
+ next_match: Option<(usize, usize)>,
+}
+
+#[cfg(feature = "pattern")]
+impl<'r, 't> Pattern<'t> for &'r Regex {
+ type Searcher = RegexSearcher<'r, 't>;
+
+ fn into_searcher(self, haystack: &'t str) -> RegexSearcher<'r, 't> {
+ RegexSearcher {
+ it: self.find_iter(haystack),
+ last_step_end: 0,
+ next_match: None,
+ }
+ }
+}
+
+#[cfg(feature = "pattern")]
+unsafe impl<'r, 't> Searcher<'t> for RegexSearcher<'r, 't> {
+ #[inline]
+ fn haystack(&self) -> &'t str {
+ self.it.search
+ }
+
+ #[inline]
+ fn next(&mut self) -> SearchStep {
+ if let Some((s, e)) = self.next_match {
+ self.next_match = None;
+ self.last_step_end = e;
+ return SearchStep::Match(s, e);
+ }
+ match self.it.next() {
+ None => {
+ if self.last_step_end < self.haystack().len() {
+ let last = self.last_step_end;
+ self.last_step_end = self.haystack().len();
+ SearchStep::Reject(last, self.haystack().len())
+ } else {
+ SearchStep::Done
+ }
+ }
+ Some((s, e)) => {
+ if s == self.last_step_end {
+ self.last_step_end = e;
+ SearchStep::Match(s, e)
+ } else {
+ self.next_match = Some((s, e));
+ let last = self.last_step_end;
+ self.last_step_end = s;
+ SearchStep::Reject(last, s)
+ }
+ }
+ }
+ }
+}
+
+fn exec(re: &Regex, caps: &mut CaptureIdxs, text: &str, start: usize) -> bool {
+ match *re {
+ Regex::Native(ExNative { ref prog, .. }) => (*prog)(caps, text, start),
+ Regex::Dynamic(ref prog) => prog.exec(caps, text, start),
+ }
+}
+
+
+