use crate::common::{take_until_crlf, take_until_crlf_consume_crlf, take_until_sp};
use crate::types::command::{Apop, Pass, User};
use nom::{
bytes::complete::tag, bytes::complete::tag_no_case, combinator::map, sequence::delimited,
sequence::preceded, sequence::separated_pair, IResult,
};
pub fn user(s: &[u8]) -> Option<User> {
match user_parser(s) {
Ok((_, x)) => Some(x),
Err(_) => None,
}
}
pub(crate) fn user_parser(s: &[u8]) -> IResult<&[u8], User> {
map(
preceded(tag_no_case(b"USER "), take_until_crlf_consume_crlf),
|name| User { name: name },
)(s)
}
pub fn pass(s: &[u8]) -> Option<Pass> {
match pass_parser(s) {
Ok((_, x)) => Some(x),
Err(_) => None,
}
}
pub(crate) fn pass_parser(s: &[u8]) -> IResult<&[u8], Pass> {
map(
preceded(tag_no_case(b"PASS "), take_until_crlf_consume_crlf),
|string| Pass { string: string },
)(s)
}
pub fn apop(s: &[u8]) -> Option<Apop> {
match apop_parser(s) {
Ok((_, x)) => Some(x),
Err(_) => None,
}
}
pub(crate) fn apop_parser(s: &[u8]) -> IResult<&[u8], Apop> {
map(
delimited(
tag_no_case(b"APOP "),
separated_pair(take_until_sp, tag(b" "), take_until_crlf),
tag(b"\r\n"),
),
|(x, y)| Apop { name: x, digest: y },
)(s)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_user() {
assert_eq!(user(b"USER name\r\n").unwrap(), User { name: b"name" })
}
#[test]
fn test_pass() {
assert_eq!(pass(b"PASS pwd\r\n").unwrap(), Pass { string: b"pwd" })
}
#[test]
fn test_apop() {
assert_eq!(
apop(b"APOP mrose c4c9334bac560ecc979e58001b3e22fb\r\n").unwrap(),
Apop {
name: b"mrose",
digest: b"c4c9334bac560ecc979e58001b3e22fb"
}
)
}
}