eml-codec/src/fragments/part.rs

63 lines
1.5 KiB
Rust
Raw Normal View History

2023-07-14 17:12:34 +00:00
use nom::{
IResult,
bytes::complete::tag,
sequence::tuple,
combinator::opt,
};
use crate::fragments::mime::{Mechanism, Type};
use crate::fragments::model::MessageId;
use crate::fragments::misc_token::Unstructured;
2023-07-16 07:55:47 +00:00
use crate::fragments::whitespace::obs_crlf;
2023-07-14 17:12:34 +00:00
#[derive(Debug, PartialEq, Default)]
pub struct PartHeader<'a> {
pub content_type: Option<&'a Type<'a>>,
pub content_transfer_encoding: Option<&'a Mechanism<'a>>,
pub content_id: Option<&'a MessageId<'a>>,
pub content_description: Option<&'a Unstructured>,
}
#[derive(Debug, PartialEq)]
pub enum PartNode<'a> {
Discrete(PartHeader<'a>, &'a [u8]),
Composite(PartHeader<'a>, Vec<PartNode<'a>>),
}
2023-07-16 08:09:22 +00:00
#[derive(Debug, PartialEq)]
2023-07-14 17:12:34 +00:00
pub enum Delimiter {
Next,
Last
}
2023-07-16 07:55:47 +00:00
pub fn boundary<'a>(boundary: &'a [u8]) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Delimiter> {
move |input: &[u8]| {
let (rest, (_, _, _, last, _)) = tuple((obs_crlf, tag(b"--"), tag(boundary), opt(tag(b"--")), obs_crlf))(input)?;
2023-07-14 17:12:34 +00:00
match last {
2023-07-16 07:55:47 +00:00
Some(_) => Ok((rest, Delimiter::Last)),
None => Ok((rest, Delimiter::Next)),
2023-07-14 17:12:34 +00:00
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
2023-07-16 08:09:22 +00:00
fn test_boundary_next() {
assert_eq!(
boundary(b"hello")(b"\r\n--hello\r\n"),
Ok((&b""[..], Delimiter::Next))
);
}
#[test]
fn test_boundary_last() {
assert_eq!(
boundary(b"hello")(b"\r\n--hello--\r\n"),
Ok((&b""[..], Delimiter::Last))
);
2023-07-14 17:12:34 +00:00
}
}