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