eml_codec/text/
boundary.rs

1use nom::{
2    branch::alt,
3    bytes::complete::tag,
4    combinator::{eof, opt},
5    sequence::tuple,
6    IResult,
7};
8
9use crate::text::whitespace::obs_crlf;
10
11#[derive(Debug, PartialEq)]
12pub enum Delimiter {
13    Next,
14    Last,
15}
16
17pub fn boundary<'a>(boundary: &[u8]) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Delimiter> + '_ {
18    move |input: &[u8]| {
19        let (rest, (_, _, _, last, _)) = tuple((
20            opt(obs_crlf),
21            tag(b"--"),
22            tag(boundary),
23            opt(tag(b"--")),
24            alt((obs_crlf, eof)),
25        ))(input)?;
26        match last {
27            Some(_) => Ok((rest, Delimiter::Last)),
28            None => Ok((rest, Delimiter::Next)),
29        }
30    }
31}
32
33#[cfg(test)]
34mod tests {
35    use super::*;
36
37    #[test]
38    fn test_boundary_next() {
39        assert_eq!(
40            boundary(b"hello")(b"\r\n--hello\r\n"),
41            Ok((&b""[..], Delimiter::Next))
42        );
43    }
44
45    #[test]
46    fn test_boundary_last() {
47        assert_eq!(
48            boundary(b"hello")(b"\r\n--hello--\r\n"),
49            Ok((&b""[..], Delimiter::Last))
50        );
51    }
52}