1use crate::compiler::prelude::*;
2
3fn to_syslog_facility(value: Value) -> Resolved {
4 let value = value.try_integer()?;
5 let code = match value {
7 0 => "kern",
8 1 => "user",
9 2 => "mail",
10 3 => "daemon",
11 4 => "auth",
12 5 => "syslog",
13 6 => "lpr",
14 7 => "news",
15 8 => "uucp",
16 9 => "cron",
17 10 => "authpriv",
18 11 => "ftp",
19 12 => "ntp",
20 13 => "security",
21 14 => "console",
22 15 => "solaris-cron",
23 16 => "local0",
24 17 => "local1",
25 18 => "local2",
26 19 => "local3",
27 20 => "local4",
28 21 => "local5",
29 22 => "local6",
30 23 => "local7",
31 _ => return Err(format!("facility code {value} not valid").into()),
32 };
33 Ok(code.into())
34}
35
36#[derive(Clone, Copy, Debug)]
37pub struct ToSyslogFacility;
38
39impl Function for ToSyslogFacility {
40 fn identifier(&self) -> &'static str {
41 "to_syslog_facility"
42 }
43
44 fn usage(&self) -> &'static str {
45 r#"Converts the `value`, a Syslog [facility code](https://en.wikipedia.org/wiki/Syslog#Facility), into its corresponding Syslog keyword. For example, `0` into `"kern"`, `1` into `"user"`, etc."#
46 }
47
48 fn category(&self) -> &'static str {
49 Category::Convert.as_ref()
50 }
51
52 fn internal_failure_reasons(&self) -> &'static [&'static str] {
53 &[
54 "`value` is not a valid Syslog [facility code](https://en.wikipedia.org/wiki/Syslog#Facility).",
55 ]
56 }
57
58 fn return_kind(&self) -> u16 {
59 kind::BYTES
60 }
61
62 fn parameters(&self) -> &'static [Parameter] {
63 const PARAMETERS: &[Parameter] = &[Parameter::required(
64 "value",
65 kind::INTEGER,
66 "The facility code.",
67 )];
68 PARAMETERS
69 }
70
71 fn examples(&self) -> &'static [Example] {
72 &[
73 example! {
74 title: "Coerce to a Syslog facility",
75 source: "to_syslog_facility!(4)",
76 result: Ok("auth"),
77 },
78 example! {
79 title: "invalid",
80 source: "to_syslog_facility!(500)",
81 result: Err(
82 r#"function call error for "to_syslog_facility" at (0:24): facility code 500 not valid"#,
83 ),
84 },
85 ]
86 }
87
88 fn compile(
89 &self,
90 _state: &state::TypeState,
91 _ctx: &mut FunctionCompileContext,
92 arguments: ArgumentList,
93 ) -> Compiled {
94 let value = arguments.required("value");
95
96 Ok(ToSyslogFacilityFn { value }.as_expr())
97 }
98}
99
100#[derive(Debug, Clone)]
101struct ToSyslogFacilityFn {
102 value: Box<dyn Expression>,
103}
104
105impl FunctionExpression for ToSyslogFacilityFn {
106 fn resolve(&self, ctx: &mut Context) -> Resolved {
107 let value = self.value.resolve(ctx)?;
108
109 to_syslog_facility(value)
110 }
111
112 fn type_def(&self, _: &state::TypeState) -> TypeDef {
113 TypeDef::bytes().fallible()
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use crate::value;
121
122 test_function![
123 to_syslog_facility => ToSyslogFacility;
124
125 kern {
126 args: func_args![value: value!(0)],
127 want: Ok(value!("kern")),
128 tdef: TypeDef::bytes().fallible(),
129 }
130
131 user {
132 args: func_args![value: value!(1)],
133 want: Ok(value!("user")),
134 tdef: TypeDef::bytes().fallible(),
135 }
136
137 mail {
138 args: func_args![value: value!(2)],
139 want: Ok(value!("mail")),
140 tdef: TypeDef::bytes().fallible(),
141 }
142
143 daemon {
144 args: func_args![value: value!(3)],
145 want: Ok(value!("daemon")),
146 tdef: TypeDef::bytes().fallible(),
147 }
148
149 auth {
150 args: func_args![value: value!(4)],
151 want: Ok(value!("auth")),
152 tdef: TypeDef::bytes().fallible(),
153 }
154
155 syslog {
156 args: func_args![value: value!(5)],
157 want: Ok(value!("syslog")),
158 tdef: TypeDef::bytes().fallible(),
159 }
160
161 lpr {
162 args: func_args![value: value!(6)],
163 want: Ok(value!("lpr")),
164 tdef: TypeDef::bytes().fallible(),
165 }
166
167 news {
168 args: func_args![value: value!(7)],
169 want: Ok(value!("news")),
170 tdef: TypeDef::bytes().fallible(),
171 }
172
173 uucp {
174 args: func_args![value: value!(8)],
175 want: Ok(value!("uucp")),
176 tdef: TypeDef::bytes().fallible(),
177 }
178
179 cron {
180 args: func_args![value: value!(9)],
181 want: Ok(value!("cron")),
182 tdef: TypeDef::bytes().fallible(),
183 }
184
185 authpriv {
186 args: func_args![value: value!(10)],
187 want: Ok(value!("authpriv")),
188 tdef: TypeDef::bytes().fallible(),
189 }
190
191 ftp {
192 args: func_args![value: value!(11)],
193 want: Ok(value!("ftp")),
194 tdef: TypeDef::bytes().fallible(),
195 }
196
197 ntp {
198 args: func_args![value: value!(12)],
199 want: Ok(value!("ntp")),
200 tdef: TypeDef::bytes().fallible(),
201 }
202
203 security {
204 args: func_args![value: value!(13)],
205 want: Ok(value!("security")),
206 tdef: TypeDef::bytes().fallible(),
207 }
208
209 console {
210 args: func_args![value: value!(14)],
211 want: Ok(value!("console")),
212 tdef: TypeDef::bytes().fallible(),
213 }
214
215 solaris_cron {
216 args: func_args![value: value!(15)],
217 want: Ok(value!("solaris-cron")),
218 tdef: TypeDef::bytes().fallible(),
219 }
220
221 local0 {
222 args: func_args![value: value!(16)],
223 want: Ok(value!("local0")),
224 tdef: TypeDef::bytes().fallible(),
225 }
226
227 local1 {
228 args: func_args![value: value!(17)],
229 want: Ok(value!("local1")),
230 tdef: TypeDef::bytes().fallible(),
231 }
232
233 local2 {
234 args: func_args![value: value!(18)],
235 want: Ok(value!("local2")),
236 tdef: TypeDef::bytes().fallible(),
237 }
238
239 local3 {
240 args: func_args![value: value!(19)],
241 want: Ok(value!("local3")),
242 tdef: TypeDef::bytes().fallible(),
243 }
244
245 local4 {
246 args: func_args![value: value!(20)],
247 want: Ok(value!("local4")),
248 tdef: TypeDef::bytes().fallible(),
249 }
250
251 local5 {
252 args: func_args![value: value!(21)],
253 want: Ok(value!("local5")),
254 tdef: TypeDef::bytes().fallible(),
255 }
256
257 local6 {
258 args: func_args![value: value!(22)],
259 want: Ok(value!("local6")),
260 tdef: TypeDef::bytes().fallible(),
261 }
262
263 local7 {
264 args: func_args![value: value!(23)],
265 want: Ok(value!("local7")),
266 tdef: TypeDef::bytes().fallible(),
267 }
268
269 invalid_facility_larger_int {
270 args: func_args![value: value!(475)],
271 want: Err("facility code 475 not valid"),
272 tdef: TypeDef::bytes().fallible(),
273 }
274
275 invalid_facility_negative_int {
276 args: func_args![value: value!(-1)],
277 want: Err("facility code -1 not valid"),
278 tdef: TypeDef::bytes().fallible(),
279 }
280
281 invalid_facility_non_int {
282 args: func_args![value: value!("nope")],
283 want: Err("expected integer, got string"),
284 tdef: TypeDef::bytes().fallible(),
285 }
286 ];
287}