1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
use crate::{
    common::Dummy,
    smtp::{command::SmtpUnknownCommand, SmtpContext},
};
use std::{
    fmt::{self, Debug},
    ops::Deref,
};

#[derive(Debug)]
pub enum ParseError {
    Incomplete,
    Failed(String),
    Mismatch(String),
}
impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ParseError::Incomplete => write!(f, "The input is not complete"),
            ParseError::Failed(e) => write!(f, "The input is invalid, parsing failed: {}", e),
            ParseError::Mismatch(e) => write!(f, "Parser did not match the input: {}", e),
        }
    }
}
impl std::error::Error for ParseError {}

pub type ParseResult<T> = std::result::Result<(usize, T), ParseError>;

pub trait Parser<CMD>: fmt::Debug {
    fn parse(&self, input: &[u8], state: &SmtpContext) -> ParseResult<CMD>;
}

impl<CMD, S: Parser<CMD>, T: Deref<Target = S> + Debug> Parser<CMD> for T {
    fn parse(&self, input: &[u8], state: &SmtpContext) -> ParseResult<CMD> {
        S::parse(Deref::deref(self), input, state)
    }
}

impl Parser<SmtpUnknownCommand> for Dummy {
    fn parse(&self, input: &[u8], _state: &SmtpContext) -> ParseResult<SmtpUnknownCommand> {
        if let Some(line) = input.split(|b| *b == b'\n').next() {
            Ok((line.len(), Default::default()))
        } else {
            Err(ParseError::Incomplete)
        }
    }
}