view src/priority.rs @ 15:ad5154cf110c draft

Add more conversion functions for facilities/levels
author Lewin Bormann <lbo@spheniscida.de>
date Sat, 03 Dec 2016 14:16:44 +0100
parents 46810d1d1a0a
children
line wrap: on
line source

#![allow(dead_code)]

use std::str::FromStr;

#[derive(Debug,  PartialEq, PartialOrd, Clone, Copy)]
pub enum Level {
    NONE = -1,
    EMERG = 0,
    ALERT = 1,
    CRIT = 2,
    ERR = 3,
    WARNING = 4,
    NOTICE = 5,
    INFO = 6,
    DEBUG = 7,
}

pub fn to_level(l: i32) -> Option<Level> {
    if l >= Level::EMERG as i32 && l <= Level::DEBUG as i32 {
        Some(match l {
            0 => Level::EMERG,
            1 => Level::ALERT,
            2 => Level::CRIT,
            3 => Level::ERR,
            4 => Level::WARNING,
            5 => Level::NOTICE,
            6 => Level::INFO,
            7 => Level::DEBUG,
            _ => panic!("Bug: unexpected value"),
        })
    } else {
        None
    }
}

pub fn str_to_level(s: &str) -> Option<Level> {
    if s == "emerg" {
        Some(Level::EMERG)
    } else if s == "alert" {
        Some(Level::ALERT)
    } else if s == "crit" || s == "critical" {
        Some(Level::CRIT)
    } else if s == "err" {
        Some(Level::ERR)
    } else if s == "warn" || s == "warning" {
        Some(Level::WARNING)
    } else if s == "notice" {
        Some(Level::NOTICE)
    } else if s == "info" {
        Some(Level::INFO)
    } else if s == "debug" {
        Some(Level::DEBUG)
    } else if s == "none" {
        Some(Level::NONE)
    } else {
        None
    }
}

#[derive(Debug,  PartialEq, Clone, Copy)]
pub enum Facility {
    KERN = 0,
    USER = 1,
    MAIL = 2,
    DAEMON = 3,
    AUTH = 4,
    SYSLOG = 5,
    LPR = 6,
    NEWS = 7,
    UUCP = 8,
    CRON = 9,
    AUTHPRIV = 10,
    FTP = 11,

    LOCAL0 = 16,
    LOCAL1 = 17,
    LOCAL2 = 18,
    LOCAL3 = 19,
    LOCAL4 = 20,
    LOCAL5 = 21,
    LOCAL6 = 22,
    LOCAL7 = 23,
}

pub fn str_to_facility(s: &str) -> Option<Facility> {
    if s == "kern" {
        Some(Facility::KERN)
    } else if s == "user" {
        Some(Facility::USER)
    } else if s == "mail" {
        Some(Facility::MAIL)
    } else if s == "daemon" {
        Some(Facility::DAEMON)
    } else if s == "auth" {
        Some(Facility::AUTH)
    } else if s == "syslog" {
        Some(Facility::SYSLOG)
    } else if s == "lpr" {
        Some(Facility::LPR)
    } else if s == "news" {
        Some(Facility::NEWS)
    } else if s == "uucp" {
        Some(Facility::UUCP)
    } else if s == "cron" {
        Some(Facility::CRON)
    } else if s == "authpriv" {
        Some(Facility::AUTHPRIV)
    } else if s == "ftp" {
        Some(Facility::FTP)
    } else if s.starts_with("local") {
        let suffix = &s[5..];
        let num = i32::from_str(suffix).unwrap_or(0);
        to_facility(Facility::LOCAL0 as i32 + num)
    } else {
        None
    }
}

pub fn to_facility(l: i32) -> Option<Facility> {
    if (l >= Facility::KERN as i32 && l <= Facility::FTP as i32) ||
       (l >= Facility::LOCAL0 as i32 && l <= Facility::LOCAL7 as i32) {
        Some(match l {
            0 => Facility::KERN,
            1 => Facility::USER,
            2 => Facility::MAIL,
            3 => Facility::DAEMON,
            4 => Facility::AUTH,
            5 => Facility::SYSLOG,
            6 => Facility::LPR,
            7 => Facility::NEWS,
            8 => Facility::UUCP,
            9 => Facility::CRON,
            10 => Facility::AUTHPRIV,
            11 => Facility::FTP,
            16 => Facility::LOCAL0,
            17 => Facility::LOCAL1,
            18 => Facility::LOCAL2,
            19 => Facility::LOCAL3,
            20 => Facility::LOCAL4,
            21 => Facility::LOCAL5,
            22 => Facility::LOCAL6,
            23 => Facility::LOCAL7,
            _ => panic!("Bug: unexpected value"),
        })
    } else {
        None
    }
}


/// Converts a (level, facility) pair into a decimal number
pub fn lf_to_priority(l: Level, f: Facility) -> i32 {
    l as i32 + 8 * f as i32
}

/// Converts a decimal number string into a pair of level, facility
pub fn parse(prio: &str) -> Option<(Level, Facility)> {
    match i32::from_str(prio) {
        Ok(l) => priority_to_lf(l),
        Err(_) => None,
    }
}

pub fn priority_to_lf(prio: i32) -> Option<(Level, Facility)> {
    let level = prio & 0b111;
    let fac = prio >> 3;

    match (to_level(level), to_facility(fac)) {
        (Some(l), Some(f)) => Some((l, f)),
        _ => None,
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_priority_combine() {
        assert_eq!(20, lf_to_priority(Level::WARNING, Facility::MAIL));
        assert_eq!(35, lf_to_priority(Level::ERR, Facility::AUTH));
    }

    #[test]
    fn test_priority_parse() {
        let priostr = format!("{}", lf_to_priority(Level::WARNING, Facility::NEWS));
        assert_eq!(parse(&priostr), Some((Level::WARNING, Facility::NEWS)));
    }
}