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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#[cfg(feature = "serde-serialize")]
use serde::{Serialize, Serializer};

use std::convert::TryFrom;

use thiserror::Error;

#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
#[allow(non_camel_case_types)]
/// Syslog facilities. Taken From RFC 5424, but I've heard that some platforms mix these around.
/// Names are from Linux.
pub enum SyslogFacility {
    LOG_KERN = 0,
    LOG_USER = 1,
    LOG_MAIL = 2,
    LOG_DAEMON = 3,
    LOG_AUTH = 4,
    LOG_SYSLOG = 5,
    LOG_LPR = 6,
    LOG_NEWS = 7,
    LOG_UUCP = 8,
    LOG_CRON = 9,
    LOG_AUTHPRIV = 10,
    LOG_FTP = 11,
    LOG_NTP = 12,
    LOG_AUDIT = 13,
    LOG_ALERT = 14,
    LOG_CLOCKD = 15,
    LOG_LOCAL0 = 16,
    LOG_LOCAL1 = 17,
    LOG_LOCAL2 = 18,
    LOG_LOCAL3 = 19,
    LOG_LOCAL4 = 20,
    LOG_LOCAL5 = 21,
    LOG_LOCAL6 = 22,
    LOG_LOCAL7 = 23,
}

#[derive(Debug, Error)]
pub enum SyslogFacilityError {
    #[error("integer does not correspond to a known facility")]
    InvalidInteger,
}

impl TryFrom<i32> for SyslogFacility {
    type Error = SyslogFacilityError;

    #[inline(always)]
    fn try_from(i: i32) -> Result<SyslogFacility, Self::Error> {
        Ok(match i {
            0 => SyslogFacility::LOG_KERN,
            1 => SyslogFacility::LOG_USER,
            2 => SyslogFacility::LOG_MAIL,
            3 => SyslogFacility::LOG_DAEMON,
            4 => SyslogFacility::LOG_AUTH,
            5 => SyslogFacility::LOG_SYSLOG,
            6 => SyslogFacility::LOG_LPR,
            7 => SyslogFacility::LOG_NEWS,
            8 => SyslogFacility::LOG_UUCP,
            9 => SyslogFacility::LOG_CRON,
            10 => SyslogFacility::LOG_AUTHPRIV,
            11 => SyslogFacility::LOG_FTP,
            12 => SyslogFacility::LOG_NTP,
            13 => SyslogFacility::LOG_AUDIT,
            14 => SyslogFacility::LOG_ALERT,
            15 => SyslogFacility::LOG_CLOCKD,
            16 => SyslogFacility::LOG_LOCAL0,
            17 => SyslogFacility::LOG_LOCAL1,
            18 => SyslogFacility::LOG_LOCAL2,
            19 => SyslogFacility::LOG_LOCAL3,
            20 => SyslogFacility::LOG_LOCAL4,
            21 => SyslogFacility::LOG_LOCAL5,
            22 => SyslogFacility::LOG_LOCAL6,
            23 => SyslogFacility::LOG_LOCAL7,
            _ => return Err(SyslogFacilityError::InvalidInteger),
        })
    }
}

impl SyslogFacility {
    /// Convert an int (as used in the wire serialization) into a `SyslogFacility`
    pub(crate) fn from_int(i: i32) -> Option<Self> {
        Self::try_from(i).ok()
    }

    /// Convert a syslog facility into a unique string representation
    pub fn as_str(self) -> &'static str {
        match self {
            SyslogFacility::LOG_KERN => "kern",
            SyslogFacility::LOG_USER => "user",
            SyslogFacility::LOG_MAIL => "mail",
            SyslogFacility::LOG_DAEMON => "daemon",
            SyslogFacility::LOG_AUTH => "auth",
            SyslogFacility::LOG_SYSLOG => "syslog",
            SyslogFacility::LOG_LPR => "lpr",
            SyslogFacility::LOG_NEWS => "news",
            SyslogFacility::LOG_UUCP => "uucp",
            SyslogFacility::LOG_CRON => "cron",
            SyslogFacility::LOG_AUTHPRIV => "authpriv",
            SyslogFacility::LOG_FTP => "ftp",
            SyslogFacility::LOG_NTP => "ntp",
            SyslogFacility::LOG_AUDIT => "audit",
            SyslogFacility::LOG_ALERT => "alert",
            SyslogFacility::LOG_CLOCKD => "clockd",
            SyslogFacility::LOG_LOCAL0 => "local0",
            SyslogFacility::LOG_LOCAL1 => "local1",
            SyslogFacility::LOG_LOCAL2 => "local2",
            SyslogFacility::LOG_LOCAL3 => "local3",
            SyslogFacility::LOG_LOCAL4 => "local4",
            SyslogFacility::LOG_LOCAL5 => "local5",
            SyslogFacility::LOG_LOCAL6 => "local6",
            SyslogFacility::LOG_LOCAL7 => "local7",
        }
    }
}

#[cfg(feature = "serde-serialize")]
impl Serialize for SyslogFacility {
    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
        ser.serialize_str(self.as_str())
    }
}

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

    #[test]
    fn test_deref() {
        assert_eq!(SyslogFacility::LOG_KERN.as_str(), "kern");
    }
}