fail2ban-log-parser-core 0.1.2

Fast, zero-copy fail2ban log parser built with winnow
Documentation
mod date;
mod event;
mod header;
mod ip;
mod jail;
mod level;
mod pid;
mod time;
mod timestamp;

pub use event::Fail2BanEvent;
pub use header::Fail2BanHeaderType;
pub use level::Fail2BanLevel;

use std::net::IpAddr;

use chrono::{DateTime, Utc};
use winnow::Parser;

use crate::parser::{
    event::parse_event, header::parse_header, ip::parse_ip, jail::parse_jail, level::parse_level,
    pid::parse_pid, timestamp::parse_timestamp,
};
use winnow::ascii::multispace1;

#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Fail2BanStructuredLog<'a> {
    timestamp: Option<DateTime<Utc>>,
    header: Option<Fail2BanHeaderType>,
    pid: Option<u32>,
    level: Option<Fail2BanLevel>,
    #[cfg_attr(feature = "serde", serde(borrow))]
    jail: Option<&'a str>,
    event: Option<Fail2BanEvent>,
    ip: Option<IpAddr>,
}

impl Fail2BanStructuredLog<'_> {
    #[must_use]
    pub fn ip(&self) -> Option<&IpAddr> {
        self.ip.as_ref()
    }

    #[must_use]
    pub fn event(&self) -> Option<&Fail2BanEvent> {
        self.event.as_ref()
    }

    #[must_use]
    pub fn jail(&self) -> Option<&str> {
        self.jail
    }

    #[must_use]
    pub fn level(&self) -> Option<&Fail2BanLevel> {
        self.level.as_ref()
    }

    #[must_use]
    pub fn pid(&self) -> Option<u32> {
        self.pid
    }

    #[must_use]
    pub fn header(&self) -> Option<&Fail2BanHeaderType> {
        self.header.as_ref()
    }

    #[must_use]
    pub fn timestamp(&self) -> Option<DateTime<Utc>> {
        self.timestamp
    }
}

pub(crate) fn parse_log_line<'a>(input: &mut &'a str) -> winnow::Result<Fail2BanStructuredLog<'a>> {
    let timestamp = parse_timestamp.parse_next(input)?;
    multispace1.parse_next(input)?;
    let header = parse_header.parse_next(input)?;
    multispace1.parse_next(input)?;
    let pid = parse_pid.parse_next(input)?;
    multispace1.parse_next(input)?;
    let level = parse_level.parse_next(input)?;
    multispace1.parse_next(input)?;
    let jail = parse_jail.parse_next(input)?;
    multispace1.parse_next(input)?;
    let event = parse_event.parse_next(input)?;
    multispace1.parse_next(input)?;
    let ip = parse_ip.parse_next(input)?;

    Ok(Fail2BanStructuredLog {
        timestamp,
        header,
        pid,
        level,
        jail,
        event,
        ip,
    })
}