diff options
Diffstat (limited to 'vendor/gix-actor/src/signature/decode.rs')
-rw-r--r-- | vendor/gix-actor/src/signature/decode.rs | 154 |
1 files changed, 89 insertions, 65 deletions
diff --git a/vendor/gix-actor/src/signature/decode.rs b/vendor/gix-actor/src/signature/decode.rs index 5483d1651..6bd7bfed6 100644 --- a/vendor/gix-actor/src/signature/decode.rs +++ b/vendor/gix-actor/src/signature/decode.rs @@ -1,69 +1,93 @@ -use bstr::ByteSlice; -use btoi::btoi; -use nom::{ - branch::alt, - bytes::complete::{tag, take, take_until, take_while_m_n}, - character::is_digit, - error::{context, ContextError, ParseError}, - sequence::{terminated, tuple}, - IResult, -}; - -use crate::{Sign, SignatureRef, Time}; - -const SPACE: &[u8] = b" "; - -/// Parse a signature from the bytes input `i` using `nom`. -pub fn decode<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>( - i: &'a [u8], -) -> IResult<&'a [u8], SignatureRef<'a>, E> { - let (i, (name, email, time, tzsign, hours, minutes)) = context( - "<name> <<email>> <timestamp> <+|-><HHMM>", - tuple(( - context("<name>", terminated(take_until(&b" <"[..]), take(2usize))), - context("<email>", terminated(take_until(&b"> "[..]), take(2usize))), - context("<timestamp>", |i| { - terminated(take_until(SPACE), take(1usize))(i).and_then(|(i, v)| { - btoi::<u32>(v) - .map(|v| (i, v)) - .map_err(|_| nom::Err::Error(E::from_error_kind(i, nom::error::ErrorKind::MapRes))) - }) - }), - context("+|-", alt((tag(b"-"), tag(b"+")))), - context("HH", |i| { - take_while_m_n(2usize, 2, is_digit)(i).and_then(|(i, v)| { - btoi::<i32>(v) - .map(|v| (i, v)) - .map_err(|_| nom::Err::Error(E::from_error_kind(i, nom::error::ErrorKind::MapRes))) - }) - }), - context("MM", |i| { - take_while_m_n(2usize, 2, is_digit)(i).and_then(|(i, v)| { - btoi::<i32>(v) - .map(|v| (i, v)) - .map_err(|_| nom::Err::Error(E::from_error_kind(i, nom::error::ErrorKind::MapRes))) - }) - }), - )), - )(i)?; - - debug_assert!(tzsign[0] == b'-' || tzsign[0] == b'+', "parser assure it's +|- only"); - let sign = if tzsign[0] == b'-' { Sign::Minus } else { Sign::Plus }; // - let offset = (hours * 3600 + minutes * 60) * if sign == Sign::Minus { -1 } else { 1 }; - - Ok(( - i, - SignatureRef { - name: name.as_bstr(), - email: email.as_bstr(), - time: Time { - seconds_since_unix_epoch: time, - offset_in_seconds: offset, - sign, +pub(crate) mod function { + use bstr::ByteSlice; + use btoi::btoi; + use nom::{ + branch::alt, + bytes::complete::{tag, take, take_until, take_while_m_n}, + character::is_digit, + error::{context, ContextError, ParseError}, + sequence::{terminated, tuple}, + IResult, + }; + + use crate::{IdentityRef, Sign, SignatureRef, Time}; + + const SPACE: &[u8] = b" "; + + /// Parse a signature from the bytes input `i` using `nom`. + pub fn decode<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>( + i: &'a [u8], + ) -> IResult<&'a [u8], SignatureRef<'a>, E> { + let (i, (identity, _, time, tzsign, hours, minutes)) = context( + "<name> <<email>> <timestamp> <+|-><HHMM>", + tuple(( + identity, + tag(b" "), + context("<timestamp>", |i| { + terminated(take_until(SPACE), take(1usize))(i).and_then(|(i, v)| { + btoi::<u32>(v) + .map(|v| (i, v)) + .map_err(|_| nom::Err::Error(E::from_error_kind(i, nom::error::ErrorKind::MapRes))) + }) + }), + context("+|-", alt((tag(b"-"), tag(b"+")))), + context("HH", |i| { + take_while_m_n(2usize, 2, is_digit)(i).and_then(|(i, v)| { + btoi::<i32>(v) + .map(|v| (i, v)) + .map_err(|_| nom::Err::Error(E::from_error_kind(i, nom::error::ErrorKind::MapRes))) + }) + }), + context("MM", |i| { + take_while_m_n(2usize, 2, is_digit)(i).and_then(|(i, v)| { + btoi::<i32>(v) + .map(|v| (i, v)) + .map_err(|_| nom::Err::Error(E::from_error_kind(i, nom::error::ErrorKind::MapRes))) + }) + }), + )), + )(i)?; + + debug_assert!(tzsign[0] == b'-' || tzsign[0] == b'+', "parser assure it's +|- only"); + let sign = if tzsign[0] == b'-' { Sign::Minus } else { Sign::Plus }; // + let offset = (hours * 3600 + minutes * 60) * if sign == Sign::Minus { -1 } else { 1 }; + + Ok(( + i, + SignatureRef { + name: identity.name, + email: identity.email, + time: Time { + seconds_since_unix_epoch: time, + offset_in_seconds: offset, + sign, + }, + }, + )) + } + + /// Parse an identity from the bytes input `i` (like `name <email>`) using `nom`. + pub fn identity<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>( + i: &'a [u8], + ) -> IResult<&'a [u8], IdentityRef<'a>, E> { + let (i, (name, email)) = context( + "<name> <<email>>", + tuple(( + context("<name>", terminated(take_until(&b" <"[..]), take(2usize))), + context("<email>", terminated(take_until(&b">"[..]), take(1usize))), + )), + )(i)?; + + Ok(( + i, + IdentityRef { + name: name.as_bstr(), + email: email.as_bstr(), }, - }, - )) + )) + } } +pub use function::identity; #[cfg(test)] mod tests { @@ -141,7 +165,7 @@ mod tests { .map_err(to_bstr_err) .expect_err("parse fails as > is missing") .to_string(), - "Parse error:\nTakeUntil at: 12345 -1215\nin section '<email>', at: 12345 -1215\nin section '<name> <<email>> <timestamp> <+|-><HHMM>', at: hello < 12345 -1215\n" + "Parse error:\nTakeUntil at: 12345 -1215\nin section '<email>', at: 12345 -1215\nin section '<name> <<email>>', at: hello < 12345 -1215\nin section '<name> <<email>> <timestamp> <+|-><HHMM>', at: hello < 12345 -1215\n" ); } |