samotop_core/smtp/
parser.rs1use crate::{
2 common::Dummy,
3 smtp::{command::SmtpUnknownCommand, SmtpContext},
4};
5use std::{
6 fmt::{self, Debug},
7 ops::Deref,
8};
9
10#[derive(Debug)]
11pub enum ParseError {
12 Incomplete,
13 Failed(String),
14 Mismatch(String),
15}
16impl fmt::Display for ParseError {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 match self {
19 ParseError::Incomplete => write!(f, "The input is not complete"),
20 ParseError::Failed(e) => write!(f, "The input is invalid, parsing failed: {}", e),
21 ParseError::Mismatch(e) => write!(f, "Parser did not match the input: {}", e),
22 }
23 }
24}
25impl std::error::Error for ParseError {}
26
27pub type ParseResult<T> = std::result::Result<(usize, T), ParseError>;
28
29pub trait Parser<CMD>: fmt::Debug {
30 fn parse(&self, input: &[u8], state: &SmtpContext) -> ParseResult<CMD>;
31}
32
33impl<CMD, S: Parser<CMD>, T: Deref<Target = S> + Debug> Parser<CMD> for T {
34 fn parse(&self, input: &[u8], state: &SmtpContext) -> ParseResult<CMD> {
35 S::parse(Deref::deref(self), input, state)
36 }
37}
38
39impl Parser<SmtpUnknownCommand> for Dummy {
40 fn parse(&self, input: &[u8], _state: &SmtpContext) -> ParseResult<SmtpUnknownCommand> {
41 if let Some(line) = input.split(|b| *b == b'\n').next() {
42 Ok((line.len(), Default::default()))
43 } else {
44 Err(ParseError::Incomplete)
45 }
46 }
47}