1use crate::{CapturesParser, Error, Regex, RegexParser};
2use core::fmt::Debug;
3use winnow::{
4 error::ParserError,
5 stream::{Offset, Stream, StreamIsPartial},
6};
7
8pub use crate::Captures;
9
10pub trait BytesRegexPattern {
11 type Error;
12 type Output;
13
14 fn try_into_regex(self) -> Result<Self::Output, Self::Error>;
15
16 fn into_regex(self) -> Self::Output
21 where
22 Self: Sized,
23 Self::Error: Debug,
24 {
25 self.try_into_regex()
26 .unwrap_or_else(|e| panic!("failed to compile regex for bytes parser: {:?}", e))
27 }
28}
29
30impl BytesRegexPattern for &str {
31 type Error = Error;
32 type Output = regex::bytes::Regex;
33
34 #[inline(always)]
35 fn try_into_regex(self) -> Result<Self::Output, Self::Error> {
36 Ok(Self::Output::new(self)?)
37 }
38}
39
40#[inline(always)]
65pub fn regex<'h, Input, Re, Error>(re: Re) -> RegexParser<'h, Input, Re::Output, Error>
66where
67 Input: StreamIsPartial + Stream + Offset + Clone,
68 Re: BytesRegexPattern,
69 Re::Output: Regex<Haystack<'h> = <Input as Stream>::Slice>,
70 Re::Error: Debug,
71 Error: ParserError<Input> + 'static,
72{
73 let re = re.into_regex();
74
75 RegexParser {
76 re,
77 _marker: core::marker::PhantomData,
78 }
79}
80
81#[inline(always)]
112pub fn captures<'h, Input, Re, Error>(re: Re) -> CapturesParser<'h, Input, Re::Output, Error>
113where
114 Input: StreamIsPartial + Stream + Offset + Clone,
115 Re: BytesRegexPattern,
116 Re::Output: Regex<Haystack<'h> = <Input as Stream>::Slice>,
117 Re::Error: Debug,
118 Error: ParserError<Input> + 'static,
119{
120 let re = re.into_regex();
121
122 CapturesParser {
123 re,
124 _marker: core::marker::PhantomData,
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131 use winnow::error::{ContextError, ErrMode, Needed};
132 use winnow::prelude::*;
133
134 #[test]
135 fn partial() {
136 use winnow::stream::Partial;
137 fn partial<'i>(i: &mut Partial<&'i [u8]>) -> ModalResult<&'i [u8], ContextError> {
138 regex(r"^\d+").parse_next(i)
139 }
140 assert_eq!(
141 partial.parse_peek(Partial::new(&b"123abc"[..])),
142 Ok((Partial::new(&b"abc"[..]), &b"123"[..]))
143 );
144 assert_eq!(
145 partial.parse_peek(Partial::new(&b"123"[..])),
146 Err(ErrMode::Incomplete(Needed::Unknown))
147 );
148 }
149
150 #[test]
151 fn test_re() {
152 let re = regex::Regex::new(r"\d+").unwrap();
153 assert!(re.find_at("1abc123", 0).is_some());
154 assert!(re.find_at("1abc123", 1).is_some());
155 assert!(re.find("abc123").is_some());
156 }
157}