From ddf6311925cdd05bd38efcc4721e9b8d2d54be69 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Mon, 19 Jun 2023 18:18:15 +0200 Subject: [PATCH] segment parser is working --- src/error.rs | 6 +++++ src/lib.rs | 1 + src/multipass/mod.rs | 1 + src/multipass/segment.rs | 54 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 src/error.rs diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..0ad4707 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,6 @@ +use nom; + +#[derive(Debug, PartialEq)] +pub enum IMFError<'a> { + Segment(nom::Err>), +} diff --git a/src/lib.rs b/src/lib.rs index 13b9106..257344f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,3 @@ +pub mod error; pub mod fragments; pub mod multipass; diff --git a/src/multipass/mod.rs b/src/multipass/mod.rs index e69de29..c5780e0 100644 --- a/src/multipass/mod.rs +++ b/src/multipass/mod.rs @@ -0,0 +1 @@ +pub mod segment; diff --git a/src/multipass/segment.rs b/src/multipass/segment.rs index 3640bb3..6478e8d 100644 --- a/src/multipass/segment.rs +++ b/src/multipass/segment.rs @@ -1,7 +1,61 @@ +use std::convert::TryFrom; +use nom::{ + IResult, + branch::alt, + bytes::complete::{is_not, tag}, + combinator::recognize, + sequence::{pair, terminated}, + multi::many0, +}; + +use crate::error::IMFError; + #[derive(Debug, PartialEq)] pub struct Segment<'a> { pub header: &'a [u8], pub body: &'a [u8], } +const cr: u8 = 0x0D; +const lf: u8 = 0x0A; +const crlf: &[u8] = &[cr, lf]; +impl<'a> TryFrom<&'a [u8]> for Segment<'a> { + type Error = IMFError<'a>; + + fn try_from(buffer: &'a [u8]) -> Result { + terminated( + recognize(many0(line)), + obs_crlf + )(buffer) + .map_err(|e| IMFError::Segment(e)) + .map(|(body, header)| Segment { header, body }) + } +} + +fn line(input: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + pair( + is_not(crlf), + obs_crlf, + )(input) +} + +fn obs_crlf(input: &[u8]) -> IResult<&[u8], &[u8]> { + alt((tag(crlf), tag(&[cr]), tag(&[lf])))(input) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_segment() { + assert_eq!( + Segment::try_from(&b"From: hello@world.com\r\nDate: 12 Mar 1997 07:33:25 Z\r\n\r\nHello world!"[..]), + Ok(Segment { + body: b"Hello world!", + header: b"From: hello@world.com\r\nDate: 12 Mar 1997 07:33:25 Z\r\n", + }) + ); + } +}