diff options
author | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2020-07-26 16:08:22 +0300 |
---|---|---|
committer | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2020-07-27 15:06:56 +0300 |
commit | 32b4c30feecb43586843900e2a77c094437a18c9 (patch) | |
tree | e3948595176850cab7ec26336543d10afa16587e /melib/src/email/parser.rs | |
parent | 52cec592158e5afd4332557098ee4f11ab5e2bdd (diff) |
melib/email.rs: use SmallVec for Address fields
Diffstat (limited to 'melib/src/email/parser.rs')
-rw-r--r-- | melib/src/email/parser.rs | 70 |
1 files changed, 67 insertions, 3 deletions
diff --git a/melib/src/email/parser.rs b/melib/src/email/parser.rs index 8e46fb0e..6f29fb8b 100644 --- a/melib/src/email/parser.rs +++ b/melib/src/email/parser.rs @@ -1348,8 +1348,8 @@ pub mod address { // ws!(alt_complete!(mailbox | group)) } - pub fn rfc2822address_list(input: &[u8]) -> IResult<&[u8], Vec<Address>> { - separated_list(is_a(","), address)(input.ltrim()) + pub fn rfc2822address_list(input: &[u8]) -> IResult<&[u8], SmallVec<[Address; 1]>> { + separated_list_smallvec(is_a(","), address)(input.ltrim()) // ws!( separated_list!(is_a!(","), address)) } @@ -1417,6 +1417,70 @@ pub mod address { separated_list(is_a(" \n\t\r"), message_id_peek)(input) // separated_list!(complete!(is_a!(" \n\t\r")), message_id_peek)); } + + use smallvec::SmallVec; + pub fn separated_list_smallvec<I, O, Sep, E, F, G>( + sep: G, + f: F, + ) -> impl FnMut(I) -> IResult<I, SmallVec<[O; 1]>, E> + where + I: Clone + PartialEq, + F: Fn(I) -> IResult<I, O, E>, + G: Fn(I) -> IResult<I, Sep, E>, + E: nom::error::ParseError<I>, + { + move |i: I| { + let mut res = SmallVec::new(); + let mut i = i.clone(); + + // Parse the first element + match f(i.clone()) { + Err(e) => return Err(e), + Ok((i1, o)) => { + if i1 == i { + return Err(nom::Err::Error(E::from_error_kind( + i1, + ErrorKind::SeparatedList, + ))); + } + + res.push(o); + i = i1; + } + } + + loop { + match sep(i.clone()) { + Err(nom::Err::Error(_)) => return Ok((i, res)), + Err(e) => return Err(e), + Ok((i1, _)) => { + if i1 == i { + return Err(nom::Err::Error(E::from_error_kind( + i1, + ErrorKind::SeparatedList, + ))); + } + + match f(i1.clone()) { + Err(nom::Err::Error(_)) => return Ok((i, res)), + Err(e) => return Err(e), + Ok((i2, o)) => { + if i2 == i { + return Err(nom::Err::Error(E::from_error_kind( + i2, + ErrorKind::SeparatedList, + ))); + } + + res.push(o); + i = i2; + } + } + } + } + } + } + } } #[cfg(test)] @@ -1497,7 +1561,7 @@ mod tests { assert_eq!( ( &s[0..0], - vec![ + smallvec::smallvec![ make_address!("Obit Oppidum", "user@domain"), make_address!("list", "list@domain.tld"), make_address!("list2", "list2@domain.tld"), |