nom_regex/lib.rs
1//! Parser combinators that use regular expressions.
2//!
3//! This crate provides combinators for [nom parser combinators](https://crates.io/crates/nom) using the [regex](https://crates.io/crates/regex) crate.
4//!
5//! ## Example
6//!
7//! ```rust,no_run
8//! use nom::{Err, error::ErrorKind};
9//! use nom_regex::str::re_match;
10//! fn main() {
11//! let re = regex::Regex::new(r"^\d{4}").unwrap();
12//! let parser = re_match::<(&str, ErrorKind)>(re);
13//! assert_eq!(parser("2019"), Ok(("", "2019")));
14//! assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::RegexpMatch))));
15//! assert_eq!(parser("2019-10"), Ok(("", "2019-10")));
16//! }
17//! ```
18extern crate nom;
19
20pub mod lib {
21 #[doc(hidden)]
22 pub mod nom {
23 pub use nom::*;
24 }
25 #[doc(hidden)]
26 pub mod regex {
27 pub use regex::*;
28 }
29}
30
31///Regular expression parser combinators for strings.
32pub mod str {
33 use nom::error::{ErrorKind, ParseError};
34 #[cfg(feature = "alloc")]
35 use nom::lib::std::vec::Vec;
36 use nom::{Err, IResult};
37 use nom::{InputLength, Slice};
38 use regex::Regex;
39
40 /// Compares the input with a regular expression and returns the
41 /// whole input if a match is found.
42 ///
43 /// Requires the `regexp` feature.
44 /// # Example
45 ///
46 /// ```
47 /// # use nom::{Err, error::ErrorKind};
48 /// # use nom_regex::str::re_match;
49 /// # fn main() {
50 /// let re = regex::Regex::new(r"^\d{4}").unwrap();
51 /// let parser = re_match::<(&str, ErrorKind)>(re);
52 /// assert_eq!(parser("2019"), Ok(("", "2019")));
53 /// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::RegexpMatch))));
54 /// assert_eq!(parser("2019-10"), Ok(("", "2019-10")));
55 /// # }
56 /// ```
57 pub fn re_match<'a, E>(re: Regex) -> impl Fn(&'a str) -> IResult<&'a str, &'a str, E>
58 where
59 E: ParseError<&'a str>,
60 {
61 move |i| {
62 if re.is_match(i) {
63 Ok((i.slice(i.input_len()..), i))
64 } else {
65 Err(Err::Error(E::from_error_kind(i, ErrorKind::RegexpMatch)))
66 }
67 }
68 }
69
70 /// Compares the input with a regular expression and returns all matches in a `Vec`.
71 ///
72 /// Requires the `regexp` feature.
73 /// # Example
74 ///
75 /// ```
76 /// # use nom::{Err, error::ErrorKind};
77 /// # use nom_regex::str::re_matches;
78 /// # fn main() {
79 /// let re = regex::Regex::new(r"a\d").unwrap();
80 /// let parser = re_matches::<(&str, ErrorKind)>(re);
81 /// assert_eq!(parser("a1ba2"), Ok(("", vec!["a1", "a2"])));
82 /// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::RegexpMatches))));
83 /// # }
84 /// ```
85 #[cfg(feature = "alloc")]
86 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
87 pub fn re_matches<'a, E>(re: Regex) -> impl Fn(&'a str) -> IResult<&'a str, Vec<&'a str>, E>
88 where
89 E: ParseError<&'a str>,
90 {
91 move |i| {
92 let v: Vec<_> = re
93 .find_iter(i)
94 .map(|m| i.slice(m.start()..m.end()))
95 .collect();
96 if !v.is_empty() {
97 let offset = {
98 let end = v.last().unwrap();
99 end.as_ptr() as usize + end.len() - i.as_ptr() as usize
100 };
101 Ok((i.slice(offset..), v))
102 } else {
103 Err(Err::Error(E::from_error_kind(i, ErrorKind::RegexpMatches)))
104 }
105 }
106 }
107
108 /// Compares the input with a regular expression and returns the
109 /// first match.
110 ///
111 /// Requires the `regexp` feature.
112 /// # Example
113 ///
114 /// ```
115 /// # use nom::{Err, error::ErrorKind};
116 /// # use nom_regex::str::re_find;
117 /// # fn main() {
118 /// let re = regex::Regex::new(r"\d{4}").unwrap();
119 /// let parser = re_find::<(&str, ErrorKind)>(re);
120 /// assert_eq!(parser("abc2019"), Ok(("", "2019")));
121 /// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::RegexpFind))));
122 /// assert_eq!(parser("2019-10"), Ok(("-10", "2019")));
123 /// # }
124 /// ```
125 pub fn re_find<'a, E>(re: Regex) -> impl Fn(&'a str) -> IResult<&'a str, &'a str, E>
126 where
127 E: ParseError<&'a str>,
128 {
129 move |i| {
130 if let Some(m) = re.find(i) {
131 Ok((i.slice(m.end()..), i.slice(m.start()..m.end())))
132 } else {
133 Err(Err::Error(E::from_error_kind(i, ErrorKind::RegexpFind)))
134 }
135 }
136 }
137
138 /// Compares the input with a regular expression and returns
139 /// the capture groups of the first match in a `Vec`.
140 ///
141 /// Requires the `regexp` feature.
142 /// # Example
143 ///
144 /// ```
145 /// # use nom::{Err, error::ErrorKind};
146 /// # use nom_regex::str::re_capture;
147 /// # fn main() {
148 /// let re = regex::Regex::new(r"(a)(\d)").unwrap();
149 /// let parser = re_capture::<(&str, ErrorKind)>(re);
150 /// assert_eq!(parser("a1ba2"), Ok(("ba2", vec!["a1", "a", "1"])));
151 /// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::RegexpCapture))));
152 /// # }
153 /// ```
154 #[cfg(feature = "alloc")]
155 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
156 pub fn re_capture<'a, E>(re: Regex) -> impl Fn(&'a str) -> IResult<&'a str, Vec<&'a str>, E>
157 where
158 E: ParseError<&'a str>,
159 {
160 move |i| {
161 if let Some(c) = re.captures(i) {
162 let v: Vec<_> = c
163 .iter()
164 .filter(|el| el.is_some())
165 .map(|el| el.unwrap())
166 .map(|m| i.slice(m.start()..m.end()))
167 .collect();
168 let offset = {
169 let end = v.last().unwrap();
170 end.as_ptr() as usize + end.len() - i.as_ptr() as usize
171 };
172 Ok((i.slice(offset..), v))
173 } else {
174 Err(Err::Error(E::from_error_kind(i, ErrorKind::RegexpCapture)))
175 }
176 }
177 }
178
179 /// Compares the input with a regular expression and returns
180 /// the capture groups of all matches in a nested `Vec`.
181 ///
182 /// Requires the `regexp` feature.
183 /// # Example
184 ///
185 /// ```
186 /// # use nom::{Err, error::ErrorKind};
187 /// # use nom_regex::str::re_captures;
188 /// # fn main() {
189 /// let re = regex::Regex::new(r"(a)(\d)").unwrap();
190 /// let parser = re_captures::<(&str, ErrorKind)>(re);
191 /// assert_eq!(parser("a1ba2"), Ok(("", vec![vec!["a1", "a", "1"], vec!["a2", "a", "2"]])));
192 /// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::RegexpCapture))));
193 /// # }
194 /// ```
195 #[cfg(feature = "alloc")]
196 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
197 pub fn re_captures<'a, E>(
198 re: Regex,
199 ) -> impl Fn(&'a str) -> IResult<&'a str, Vec<Vec<&'a str>>, E>
200 where
201 E: ParseError<&'a str>,
202 {
203 move |i| {
204 let v: Vec<Vec<_>> = re
205 .captures_iter(i)
206 .map(|c| {
207 c.iter()
208 .filter(|el| el.is_some())
209 .map(|el| el.unwrap())
210 .map(|m| i.slice(m.start()..m.end()))
211 .collect()
212 })
213 .collect();
214 if !v.is_empty() {
215 let offset = {
216 let end = v.last().unwrap().last().unwrap();
217 end.as_ptr() as usize + end.len() - i.as_ptr() as usize
218 };
219 Ok((i.slice(offset..), v))
220 } else {
221 Err(Err::Error(E::from_error_kind(i, ErrorKind::RegexpCapture)))
222 }
223 }
224 }
225
226 #[cfg(test)]
227 mod tests {
228 use super::*;
229 use nom::error::ErrorKind;
230 use nom::Err;
231 use regex::Regex;
232
233 macro_rules! assert_parse(
234 ($left: expr, $right: expr) => {
235 let res: $crate::nom::IResult<_, _, (_, ErrorKind)> = $left;
236 assert_eq!(res, $right);
237 };
238 );
239
240 #[test]
241 fn re_match_str() {
242 let re = Regex::new(r"^\d{4}-\d{2}-\d{2}").unwrap();
243 let rm = re_match(re);
244 assert_parse!(rm("2015-09-07"), Ok(("", "2015-09-07")));
245 assert_eq!(
246 rm("blah"),
247 Err(Err::Error((&"blah"[..], ErrorKind::RegexpMatch)))
248 );
249 assert_eq!(rm("2015-09-07blah"), Ok(("", "2015-09-07blah")));
250 }
251
252 #[test]
253 fn re_find_str() {
254 let re = Regex::new(r"^\d{4}-\d{2}-\d{2}").unwrap();
255 let rm = re_find(re);
256 assert_parse!(rm("2015-09-07"), Ok(("", "2015-09-07")));
257 assert_eq!(
258 rm("blah"),
259 Err(Err::Error((&"blah"[..], ErrorKind::RegexpFind)))
260 );
261 assert_eq!(rm("2015-09-07blah"), Ok(("blah", "2015-09-07")));
262 }
263
264 #[cfg(feature = "alloc")]
265 #[test]
266 fn re_matches_str() {
267 let re = Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap();
268 let rm = re_matches(re);
269 assert_parse!(rm("2015-09-07"), Ok(("", vec!["2015-09-07"])));
270 assert_eq!(
271 rm("blah"),
272 Err(Err::Error((&"blah"[..], ErrorKind::RegexpMatches)))
273 );
274 assert_eq!(
275 rm("aaa2015-09-07blah2015-09-09pouet"),
276 Ok(("pouet", vec!["2015-09-07", "2015-09-09"]))
277 );
278 }
279
280 #[cfg(feature = "alloc")]
281 #[test]
282 fn re_capture_str() {
283 let re = Regex::new(r"([[:alpha:]]+)\s+((\d+).(\d+).(\d+))").unwrap();
284 let rm = re_capture(re);
285 assert_parse!(
286 rm("blah nom 0.3.11pouet"),
287 Ok(("pouet", vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]))
288 );
289 assert_eq!(
290 rm("blah"),
291 Err(Err::Error(("blah", ErrorKind::RegexpCapture)))
292 );
293 assert_eq!(
294 rm("hello nom 0.3.11 world regex 0.1.41"),
295 Ok((
296 " world regex 0.1.41",
297 vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]
298 ))
299 );
300 }
301
302 #[cfg(feature = "alloc")]
303 #[test]
304 fn re_captures_str() {
305 let re = Regex::new(r"([[:alpha:]]+)\s+((\d+).(\d+).(\d+))").unwrap();
306 let rm = re_captures(re);
307 assert_parse!(
308 rm("blah nom 0.3.11pouet"),
309 Ok((
310 "pouet",
311 vec![vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]]
312 ))
313 );
314 assert_eq!(
315 rm("blah"),
316 Err(Err::Error((&"blah"[..], ErrorKind::RegexpCapture)))
317 );
318 assert_eq!(
319 rm("hello nom 0.3.11 world regex 0.1.41 aaa"),
320 Ok((
321 " aaa",
322 vec![
323 vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"],
324 vec!["regex 0.1.41", "regex", "0.1.41", "0", "1", "41"],
325 ]
326 ))
327 );
328 }
329 }
330}
331
332///Regular expression parser combinators for bytes.
333pub mod bytes {
334 use nom::error::{ErrorKind, ParseError};
335 #[cfg(feature = "alloc")]
336 use nom::lib::std::vec::Vec;
337 use nom::{Err, IResult};
338 use nom::{InputLength, Slice};
339 use regex::bytes::Regex;
340
341 /// Compares the input with a regular expression and returns the
342 /// whole input if a match is found.
343 ///
344 /// Requires the `regexp` feature.
345 /// # Example
346 ///
347 /// ```
348 /// # use nom::{Err, error::ErrorKind};
349 /// # use nom_regex::bytes::re_match;
350 /// # fn main() {
351 /// let re = regex::bytes::Regex::new(r"^\d{4}").unwrap();
352 /// let parser = re_match::<(&[u8], ErrorKind)>(re);
353 /// assert_eq!(parser(&b"2019"[..]), Ok((&b""[..], &b"2019"[..])));
354 /// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::RegexpMatch))));
355 /// assert_eq!(parser(&b"2019-10"[..]), Ok((&b""[..], &b"2019-10"[..])));
356 /// # }
357 /// ```
358 pub fn re_match<'a, E>(re: Regex) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], &'a [u8], E>
359 where
360 E: ParseError<&'a [u8]>,
361 {
362 move |i| {
363 if re.is_match(i) {
364 Ok((i.slice(i.input_len()..), i))
365 } else {
366 Err(Err::Error(E::from_error_kind(i, ErrorKind::RegexpMatch)))
367 }
368 }
369 }
370
371 /// Compares the input with a regular expression and returns all matches in a `Vec`.
372 ///
373 /// Requires the `regexp` feature.
374 /// # Example
375 ///
376 /// ```
377 /// # use nom::{Err, error::ErrorKind};
378 /// # use nom_regex::bytes::re_matches;
379 /// # fn main() {
380 /// let re = regex::bytes::Regex::new(r"a\d").unwrap();
381 /// let parser = re_matches::<(&[u8], ErrorKind)>(re);
382 /// assert_eq!(parser(&b"a1ba2"[..]), Ok((&b""[..], vec![&b"a1"[..], &b"a2"[..]])));
383 /// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::RegexpMatches))));
384 /// # }
385 /// ```
386 #[cfg(feature = "alloc")]
387 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
388 pub fn re_matches<'a, E>(re: Regex) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Vec<&'a [u8]>, E>
389 where
390 E: ParseError<&'a [u8]>,
391 {
392 move |i| {
393 let v: Vec<_> = re
394 .find_iter(i)
395 .map(|m| i.slice(m.start()..m.end()))
396 .collect();
397 if !v.is_empty() {
398 let offset = {
399 let end = v.last().unwrap();
400 end.as_ptr() as usize + end.len() - i.as_ptr() as usize
401 };
402 Ok((i.slice(offset..), v))
403 } else {
404 Err(Err::Error(E::from_error_kind(i, ErrorKind::RegexpMatches)))
405 }
406 }
407 }
408
409 /// Compares the input with a regular expression and returns the
410 /// first match.
411 ///
412 /// Requires the `regexp` feature.
413 /// # Example
414 ///
415 /// ```
416 /// # use nom::{Err, error::ErrorKind};
417 /// # use nom_regex::bytes::re_find;
418 /// # fn main() {
419 /// let re = regex::bytes::Regex::new(r"\d{4}").unwrap();
420 /// let parser = re_find::<(&[u8], ErrorKind)>(re);
421 /// assert_eq!(parser(&b"abc2019"[..]), Ok((&b""[..], &b"2019"[..])));
422 /// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::RegexpFind))));
423 /// assert_eq!(parser(&b"2019-10"[..]), Ok((&b"-10"[..], &b"2019"[..])));
424 /// # }
425 /// ```
426 pub fn re_find<'a, E>(re: Regex) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], &'a [u8], E>
427 where
428 E: ParseError<&'a [u8]>,
429 {
430 move |i| {
431 if let Some(m) = re.find(i) {
432 Ok((i.slice(m.end()..), i.slice(m.start()..m.end())))
433 } else {
434 Err(Err::Error(E::from_error_kind(i, ErrorKind::RegexpFind)))
435 }
436 }
437 }
438
439 /// Compares the input with a regular expression and returns
440 /// the capture groups of the first match in a `Vec`.
441 ///
442 /// Requires the `regexp` feature.
443 /// # Example
444 ///
445 /// ```
446 /// # use nom::{Err, error::ErrorKind};
447 /// # use nom_regex::bytes::re_capture;
448 /// # fn main() {
449 /// let re = regex::bytes::Regex::new(r"(a)(\d)").unwrap();
450 /// let parser = re_capture::<(&[u8], ErrorKind)>(re);
451 /// assert_eq!(parser(&b"a1ba2"[..]), Ok((&b"ba2"[..], vec![&b"a1"[..], &b"a"[..], &b"1"[..]])));
452 /// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::RegexpCapture))));
453 /// # }
454 /// ```
455 #[cfg(feature = "alloc")]
456 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
457 pub fn re_capture<'a, E>(re: Regex) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Vec<&'a [u8]>, E>
458 where
459 E: ParseError<&'a [u8]>,
460 {
461 move |i| {
462 if let Some(c) = re.captures(i) {
463 let v: Vec<_> = c
464 .iter()
465 .filter(|el| el.is_some())
466 .map(|el| el.unwrap())
467 .map(|m| i.slice(m.start()..m.end()))
468 .collect();
469 let offset = {
470 let end = v.last().unwrap();
471 end.as_ptr() as usize + end.len() - i.as_ptr() as usize
472 };
473 Ok((i.slice(offset..), v))
474 } else {
475 Err(Err::Error(E::from_error_kind(i, ErrorKind::RegexpCapture)))
476 }
477 }
478 }
479
480 /// Compares the input with a regular expression and returns
481 /// the capture groups of all matches in a nested `Vec`.
482 ///
483 /// Requires the `regexp` feature.
484 /// # Example
485 ///
486 /// ```
487 /// # use nom::{Err, error::ErrorKind};
488 /// # use nom_regex::bytes::re_captures;
489 /// # fn main() {
490 /// let re = regex::bytes::Regex::new(r"(a)(\d)").unwrap();
491 /// let parser = re_captures::<(&[u8], ErrorKind)>(re);
492 /// assert_eq!(parser(&b"a1ba2"[..]), Ok((&b""[..], vec![vec![&b"a1"[..], &b"a"[..], &b"1"[..]], vec![&b"a2"[..], &b"a"[..], &b"2"[..]]])));
493 /// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::RegexpCapture))));
494 /// # }
495 /// ```
496 #[cfg(feature = "alloc")]
497 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
498 pub fn re_captures<'a, E>(
499 re: Regex,
500 ) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Vec<Vec<&'a [u8]>>, E>
501 where
502 E: ParseError<&'a [u8]>,
503 {
504 move |i| {
505 let v: Vec<Vec<_>> = re
506 .captures_iter(i)
507 .map(|c| {
508 c.iter()
509 .filter(|el| el.is_some())
510 .map(|el| el.unwrap())
511 .map(|m| i.slice(m.start()..m.end()))
512 .collect()
513 })
514 .collect();
515 if !v.is_empty() {
516 let offset = {
517 let end = v.last().unwrap().last().unwrap();
518 end.as_ptr() as usize + end.len() - i.as_ptr() as usize
519 };
520 Ok((i.slice(offset..), v))
521 } else {
522 Err(Err::Error(E::from_error_kind(i, ErrorKind::RegexpCapture)))
523 }
524 }
525 }
526
527 #[cfg(test)]
528 mod tests {
529 use super::*;
530 use nom::error::ErrorKind;
531 use nom::Err;
532 use regex::bytes::Regex;
533
534 macro_rules! assert_parse(
535 ($left: expr, $right: expr) => {
536 let res: nom::IResult<_, _, (_, ErrorKind)> = $left;
537 assert_eq!(res, $right);
538 };
539 );
540
541 #[test]
542 fn re_match_bytes() {
543 let re = Regex::new(r"^\d{4}-\d{2}-\d{2}").unwrap();
544 let rm = re_match(re);
545 assert_parse!(rm(&b"2015-09-07"[..]), Ok((&b""[..], &b"2015-09-07"[..])));
546 assert_eq!(
547 rm(&b"blah"[..]),
548 Err(Err::Error((&b"blah"[..], ErrorKind::RegexpMatch)))
549 );
550 assert_eq!(
551 rm(&b"2015-09-07blah"[..]),
552 Ok((&b""[..], &b"2015-09-07blah"[..]))
553 );
554 }
555
556 #[test]
557 fn re_find_bytes() {
558 let re = Regex::new(r"^\d{4}-\d{2}-\d{2}").unwrap();
559 let rm = re_find(re);
560 assert_parse!(rm(&b"2015-09-07"[..]), Ok((&b""[..], &b"2015-09-07"[..])));
561 assert_eq!(
562 rm(&b"blah"[..]),
563 Err(Err::Error((&b"blah"[..], ErrorKind::RegexpFind)))
564 );
565 assert_eq!(
566 rm(&b"2015-09-07blah"[..]),
567 Ok((&b"blah"[..], &b"2015-09-07"[..]))
568 );
569 }
570
571 #[cfg(feature = "alloc")]
572 #[test]
573 fn re_matches_bytes() {
574 let re = Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap();
575 let rm = re_matches(re);
576 assert_parse!(
577 rm(&b"2015-09-07"[..]),
578 Ok((&b""[..], vec![&b"2015-09-07"[..]]))
579 );
580 assert_eq!(
581 rm(&b"blah"[..]),
582 Err(Err::Error((&b"blah"[..], ErrorKind::RegexpMatches)))
583 );
584 assert_eq!(
585 rm(&b"aaa2015-09-07blah2015-09-09pouet"[..]),
586 Ok((&b"pouet"[..], vec![&b"2015-09-07"[..], &b"2015-09-09"[..]]))
587 );
588 }
589
590 #[cfg(feature = "alloc")]
591 #[test]
592 fn re_capture_bytes() {
593 let re = Regex::new(r"([[:alpha:]]+)\s+((\d+).(\d+).(\d+))").unwrap();
594 let rm = re_capture(re);
595 assert_parse!(
596 rm(&b"blah nom 0.3.11pouet"[..]),
597 Ok((
598 &b"pouet"[..],
599 vec![
600 &b"nom 0.3.11"[..],
601 &b"nom"[..],
602 &b"0.3.11"[..],
603 &b"0"[..],
604 &b"3"[..],
605 &b"11"[..]
606 ]
607 ))
608 );
609 assert_eq!(
610 rm(&b"blah"[..]),
611 Err(Err::Error((&b"blah"[..], ErrorKind::RegexpCapture)))
612 );
613 assert_eq!(
614 rm(&b"hello nom 0.3.11 world regex 0.1.41"[..]),
615 Ok((
616 &b" world regex 0.1.41"[..],
617 vec![
618 &b"nom 0.3.11"[..],
619 &b"nom"[..],
620 &b"0.3.11"[..],
621 &b"0"[..],
622 &b"3"[..],
623 &b"11"[..]
624 ]
625 ))
626 );
627 }
628
629 #[cfg(feature = "alloc")]
630 #[test]
631 fn re_captures_bytes() {
632 let re = Regex::new(r"([[:alpha:]]+)\s+((\d+).(\d+).(\d+))").unwrap();
633 let rm = re_captures(re);
634 assert_parse!(
635 rm(&b"blah nom 0.3.11pouet"[..]),
636 Ok((
637 &b"pouet"[..],
638 vec![vec![
639 &b"nom 0.3.11"[..],
640 &b"nom"[..],
641 &b"0.3.11"[..],
642 &b"0"[..],
643 &b"3"[..],
644 &b"11"[..]
645 ]]
646 ))
647 );
648
649 assert_eq!(
650 rm(&b"blah"[..]),
651 Err(Err::Error((&b"blah"[..], ErrorKind::RegexpCapture)))
652 );
653 assert_eq!(
654 rm(&b"hello nom 0.3.11 world regex 0.1.41 aaa"[..]),
655 Ok((
656 &b" aaa"[..],
657 vec![
658 vec![
659 &b"nom 0.3.11"[..],
660 &b"nom"[..],
661 &b"0.3.11"[..],
662 &b"0"[..],
663 &b"3"[..],
664 &b"11"[..]
665 ],
666 vec![
667 &b"regex 0.1.41"[..],
668 &b"regex"[..],
669 &b"0.1.41"[..],
670 &b"0"[..],
671 &b"1"[..],
672 &b"41"[..]
673 ],
674 ]
675 ))
676 );
677 }
678 }
679}