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}