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