1use std::{borrow::Cow, fmt, ops::{Add, BitAnd, Shl}, path::Path, sync::LazyLock};
20
21use crate::{error::{SyRes, SyslogError}, map_error_code, portable, throw_error};
22
23#[cfg(target_family = "windows")]
24pub use self::common_eventlog_items::*;
25
26#[cfg(target_family = "unix")]
27pub use self::common_syslog_items::*;
28
29#[cfg(target_family = "windows")]
30pub mod common_eventlog_items
31{
32 use std::fmt;
33
34 use windows::Win32::System::EventLog::{EVENTLOG_ERROR_TYPE, EVENTLOG_INFORMATION_TYPE, EVENTLOG_SUCCESS, EVENTLOG_WARNING_TYPE, REPORT_EVENT_TYPE};
35
36
37 #[allow(nonstandard_style)]
38 #[repr(i32)]
39 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
40 pub enum Priority
41 {
42 LOG_EMERG = 0,
44
45 LOG_ALERT = 1,
47
48 LOG_CRIT = 2,
50
51 LOG_ERR = 3,
53
54 LOG_WARNING = 4,
56
57 LOG_NOTICE = 5,
59
60 LOG_INFO = 6,
62
63 LOG_DEBUG = 7,
65 }
66
67 impl fmt::Display for Priority
68 {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
70 {
71 match self
74 {
75 Self::LOG_EMERG =>
76 write!(f, "[EMERG]"),
77 Self::LOG_ALERT =>
78 write!(f, "[ALERT]"),
79 Self::LOG_CRIT =>
80 write!(f, "[CRIT]"),
81 Self::LOG_ERR =>
82 write!(f, "[ERR]"),
83 Self::LOG_WARNING =>
84 write!(f, "[WARNING]"),
85 Self::LOG_NOTICE =>
86 write!(f, "[NOTICE]"),
87 Self::LOG_INFO =>
88 write!(f, "[INFO]"),
89 Self::LOG_DEBUG =>
90 write!(f, "[DEBUG]"),
91 }
92 }
93 }
94
95 impl From<Priority> for REPORT_EVENT_TYPE
96 {
97 fn from(value: Priority) -> Self
98 {
99 match value
100 {
101 Priority::LOG_EMERG | Priority::LOG_ALERT | Priority::LOG_CRIT =>
102 return EVENTLOG_WARNING_TYPE,
103 Priority::LOG_ERR =>
104 return EVENTLOG_ERROR_TYPE,
105 Priority::LOG_WARNING | Priority::LOG_NOTICE =>
106 return EVENTLOG_INFORMATION_TYPE,
107 Priority::LOG_INFO | Priority::LOG_DEBUG =>
108 return EVENTLOG_SUCCESS
109 }
110 }
111 }
112
113 impl Priority
114 {
115 }
143
144
145
146 bitflags! {
147 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
149 pub struct LogStat: i32
150 {
151 const LOG_PID = 1;
153
154 const LOG_CONS = 2;
157
158 const LOG_ODELAY = 0;
162
163 const LOG_NDELAY = 0;
165
166 const LOG_NOWAIT = 0;
169
170 const LOG_PERROR = 0x20;
172 }
173 }
174
175 #[cfg(feature = "build_sync")]
176 impl LogStat
177 {
178 #[inline]
179 pub(crate)
180 fn send_to_stderr(&self, msg: &str)
181 {
182 if self.intersects(LogStat::LOG_PERROR) == true
183 {
184 eprintln!("{}", msg);
185 }
186 }
187
188 #[inline]
189 pub(crate)
190 fn send_to_syscons(&self, msg_payload: &str)
191 {
192 if self.intersects(LogStat::LOG_CONS)
193 {
194 eprintln!("{}", msg_payload);
195 }
196 }
197 }
198
199 bitflags! {
200 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
203 pub struct LogFacility: i32
204 {
205 const LOG_KERN = 0;
207
208 const LOG_USER = 8;
210
211 const LOG_MAIL = 16;
213
214 const LOG_DAEMON = 24;
216
217 const LOG_AUTH = 32;
219
220 const LOG_SYSLOG = 40;
222
223 const LOG_LPR = 48;
225
226 const LOG_NEWS = 56;
228
229 const LOG_UUCP = 64;
231
232 const LOG_LOCAL0 = 128;
234
235 const LOG_LOCAL1 = 136;
237
238 const LOG_LOCAL2 = 144;
240
241 const LOG_LOCAL3 = 152;
243
244 const LOG_LOCAL4 = 160;
246
247 const LOG_LOCAL5 = 168;
249
250 const LOG_LOCAL6 = 176;
252
253 const LOG_LOCAL7 = 184;
255 }
256 }
257
258 impl LogFacility
259 {
260 pub
261 fn into_win_facility(self) -> u32
262 {
263 return self.bits() as u32 >> 3;
264 }
265 }
266
267 #[cfg(test)]
268 mod tests
269 {
270 use windows::Win32::System::EventLog::{EVENTLOG_ERROR_TYPE, EVENTLOG_INFORMATION_TYPE, EVENTLOG_SUCCESS, EVENTLOG_WARNING_TYPE, REPORT_EVENT_TYPE};
271
272 use crate::Priority;
273
274 #[test]
275 fn test_conversion_prio_to_ret()
276 {
277 assert_eq!(REPORT_EVENT_TYPE::from(Priority::LOG_EMERG), EVENTLOG_WARNING_TYPE);
278 assert_eq!(REPORT_EVENT_TYPE::from(Priority::LOG_ALERT), EVENTLOG_WARNING_TYPE);
279 assert_eq!(REPORT_EVENT_TYPE::from(Priority::LOG_CRIT), EVENTLOG_WARNING_TYPE);
280 assert_eq!(REPORT_EVENT_TYPE::from(Priority::LOG_ERR), EVENTLOG_ERROR_TYPE);
281 assert_eq!(REPORT_EVENT_TYPE::from(Priority::LOG_WARNING), EVENTLOG_INFORMATION_TYPE);
282 assert_eq!(REPORT_EVENT_TYPE::from(Priority::LOG_NOTICE), EVENTLOG_INFORMATION_TYPE);
283 assert_eq!(REPORT_EVENT_TYPE::from(Priority::LOG_INFO), EVENTLOG_SUCCESS);
284 assert_eq!(REPORT_EVENT_TYPE::from(Priority::LOG_DEBUG), EVENTLOG_SUCCESS);
285 }
286 }
287}
288
289#[cfg(target_family = "unix")]
290pub mod common_syslog_items
291{
292 use nix::libc;
293
294 use std::{fmt, str::FromStr};
295
296
297 bitflags! {
298 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
300 pub struct LogStat: libc::c_int
301 {
302 const LOG_PID = libc::LOG_PID;
304
305 const LOG_CONS = libc::LOG_CONS;
308
309 const LOG_ODELAY = libc::LOG_ODELAY;
313
314 const LOG_NDELAY = libc::LOG_NDELAY;
316
317 const LOG_NOWAIT = libc::LOG_NOWAIT;
320
321 const LOG_PERROR = 0x20;
323 }
324 }
325
326 #[cfg(feature = "build_sync")]
327 impl LogStat
328 {
329 #[inline]
330 pub(crate)
331 fn send_to_stderr(&self, msg: &str)
332 {
333 if self.intersects(LogStat::LOG_PERROR) == true
334 {
335 let stderr_lock = std::io::stderr().lock();
336 let newline = "\n";
337
338 let _ = send_to_fd(stderr_lock, msg, &newline);
339 }
340 }
341
342 #[inline]
343 pub(crate)
344 fn send_to_syscons(&self, msg_payload: &str)
345 {
346 use std::fs::File;
347 use std::os::unix::fs::OpenOptionsExt;
348
349 if self.intersects(LogStat::LOG_CONS)
350 {
351 use crate::PATH_CONSOLE;
352
353 let syscons =
354 File
355 ::options()
356 .create(false)
357 .read(false)
358 .write(true)
359 .custom_flags(libc::O_NONBLOCK | libc::O_CLOEXEC)
360 .open(*PATH_CONSOLE);
361
362 if let Ok(file) = syscons
363 {
364 let newline = "\n";
365 let _ = send_to_fd(file, msg_payload, newline);
366 }
367 }
368 }
369 }
370
371 #[allow(nonstandard_style)]
372 #[repr(i32)]
373 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
374 pub enum Priority
375 {
376 LOG_EMERG = libc::LOG_EMERG,
378
379 LOG_ALERT = libc::LOG_ALERT,
381
382 LOG_CRIT = libc::LOG_CRIT,
384
385 LOG_ERR = libc::LOG_ERR,
387
388 LOG_WARNING = libc::LOG_WARNING,
390
391 LOG_NOTICE = libc::LOG_NOTICE,
393
394 LOG_INFO = libc::LOG_INFO,
396
397 LOG_DEBUG = libc::LOG_DEBUG,
399 }
400
401 impl fmt::Display for Priority
402 {
403 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
404 {
405 match self
408 {
409 Self::LOG_EMERG =>
410 write!(f, "EMERG"),
411 Self::LOG_ALERT =>
412 write!(f, "ALERT"),
413 Self::LOG_CRIT =>
414 write!(f, "CRIT"),
415 Self::LOG_ERR =>
416 write!(f, "ERR"),
417 Self::LOG_WARNING =>
418 write!(f, "WARNING"),
419 Self::LOG_NOTICE =>
420 write!(f, "NOTICE"),
421 Self::LOG_INFO =>
422 write!(f, "INFO"),
423 Self::LOG_DEBUG =>
424 write!(f, "DEBUG"),
425 }
426 }
427 }
428
429 impl FromStr for Priority
430 {
431 type Err = SyslogError;
432
433 fn from_str(s: &str) -> Result<Self, Self::Err>
434 {
435 let ss = s.trim().to_uppercase();
436
437 match ss.as_str()
438 {
439 "LOG_EMERG" => Ok(Self::LOG_EMERG),
440 "LOG_ALERT" => Ok(Self::LOG_ALERT),
441 "LOG_CRIT" => Ok(Self::LOG_CRIT),
442 "LOG_ERR" => Ok(Self::LOG_ERR),
443 "LOG_WARNING" => Ok(Self::LOG_WARNING),
444 "LOG_NOTICE" => Ok(Self::LOG_NOTICE),
445 "LOG_INFO" => Ok(Self::LOG_INFO),
446 "LOG_DEBUG" => Ok(Self::LOG_DEBUG),
447 n =>
448 throw_error!("unknown priority: {}", n)
449 }
450
451 }
452 }
453
454 impl Priority
455 {
456
457 }
458
459 bitflags! {
460 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
463 pub struct LogFacility: libc::c_int
464 {
465 const LOG_KERN = libc::LOG_KERN;
467
468 const LOG_USER = libc::LOG_USER;
470
471 const LOG_MAIL = libc::LOG_MAIL;
473
474 const LOG_DAEMON = libc::LOG_DAEMON;
476
477 const LOG_AUTH = libc::LOG_AUTH;
479
480 const LOG_SYSLOG = libc::LOG_SYSLOG;
482
483 const LOG_LPR = libc::LOG_LPR;
485
486 const LOG_NEWS = libc::LOG_NEWS;
488
489 const LOG_UUCP = libc::LOG_UUCP;
491
492 const LOG_LOCAL0 = libc::LOG_LOCAL0;
494
495 const LOG_LOCAL1 = libc::LOG_LOCAL1;
497
498 const LOG_LOCAL2 = libc::LOG_LOCAL2;
500
501 const LOG_LOCAL3 = libc::LOG_LOCAL3;
503
504 const LOG_LOCAL4 = libc::LOG_LOCAL4;
506
507 const LOG_LOCAL5 = libc::LOG_LOCAL5;
509
510 const LOG_LOCAL6 = libc::LOG_LOCAL6;
512
513 const LOG_LOCAL7 = libc::LOG_LOCAL7;
515 }
516 }
517
518
519 impl FromStr for LogFacility
520 {
521 type Err = SyslogError;
522
523 fn from_str(s: &str) -> Result<Self, Self::Err>
524 {
525 let s_up = s.to_ascii_uppercase();
526
527 match s_up.as_str()
528 {
529 "LOG_KERN" => Ok(Self::LOG_KERN),
530 "LOG_USER" => Ok(Self::LOG_USER),
531 "LOG_MAIL" => Ok(Self::LOG_MAIL),
532 "LOG_DAEMON" => Ok(Self::LOG_DAEMON),
533 "LOG_AUTH" => Ok(Self::LOG_AUTH),
534 "LOG_SYSLOG" => Ok(Self::LOG_SYSLOG),
535 "LOG_LPR" => Ok(Self::LOG_LPR),
536 "LOG_NEWS" => Ok(Self::LOG_NEWS),
537 "LOG_UUCP" => Ok(Self::LOG_UUCP),
538 "LOG_LOCAL0" => Ok(Self::LOG_LOCAL0),
539 "LOG_LOCAL1" => Ok(Self::LOG_LOCAL1),
540 "LOG_LOCAL2" => Ok(Self::LOG_LOCAL2),
541 "LOG_LOCAL3" => Ok(Self::LOG_LOCAL3),
542 "LOG_LOCAL4" => Ok(Self::LOG_LOCAL4),
543 "LOG_LOCAL5" => Ok(Self::LOG_LOCAL5),
544 "LOG_LOCAL6" => Ok(Self::LOG_LOCAL6),
545 "LOG_LOCAL7" => Ok(Self::LOG_LOCAL7),
546 n =>
547 throw_error!("unknwon log facility: {}", n)
548 }
549 }
550 }
551
552 impl fmt::Display for LogFacility
553 {
554 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
555 {
556 match *self
557 {
558 Self::LOG_KERN =>
559 write!(f, "LOG_KERN"),
560 Self::LOG_USER =>
561 write!(f, "LOG_USER"),
562 Self::LOG_MAIL =>
563 write!(f, "LOG_MAIL"),
564 Self::LOG_DAEMON =>
565 write!(f, "LOG_DAEMON"),
566 Self::LOG_AUTH =>
567 write!(f, "LOG_AUTH"),
568 Self::LOG_SYSLOG =>
569 write!(f, "LOG_SYSLOG"),
570 Self::LOG_LPR =>
571 write!(f, "LOG_LPR"),
572 Self::LOG_NEWS =>
573 write!(f, "LOG_NEWS"),
574 Self::LOG_UUCP =>
575 write!(f, "LOG_UUCP"),
576 Self::LOG_LOCAL0 =>
577 write!(f, "LOG_LOCAL0"),
578 Self::LOG_LOCAL1 =>
579 write!(f, "LOG_LOCAL1"),
580 Self::LOG_LOCAL2 =>
581 write!(f, "LOG_LOCAL2"),
582 Self::LOG_LOCAL3 =>
583 write!(f, "LOG_LOCAL3"),
584 Self::LOG_LOCAL4 =>
585 write!(f, "LOG_LOCAL4"),
586 Self::LOG_LOCAL5 =>
587 write!(f, "LOG_LOCAL5"),
588 Self::LOG_LOCAL6 =>
589 write!(f, "LOG_LOCAL6"),
590 Self::LOG_LOCAL7 =>
591 write!(f, "LOG_LOCAL7"),
592 n =>
593 write!(f, "LOG_[{}]", n),
594 }
595 }
596 }
597
598 pub const PATH_LOG: &'static str = "/var/run/log";
600
601 pub const PATH_LOG_PRIV: &'static str = "/var/run/logpriv";
603
604 pub const PATH_OLDLOG: &'static str = "/dev/log";
606
607 pub const PATH_OSX: &'static str = "/var/run/syslog";
609
610 #[cfg(feature = "build_sync")]
619 pub(crate) mod sync_portion
620 {
621 use std::io::Write;
622 use std::io::IoSlice;
623 use crate::error::SyRes;
624 use crate::map_error_os;
625
626 pub(crate)
637 fn send_to_fd<W>(mut file_fd: W, msg: &str, newline: &str) -> SyRes<usize>
638 where W: Write
639 {
640 return
641 file_fd
642 .write_vectored(
643 &[IoSlice::new(msg.as_bytes()), IoSlice::new(newline.as_bytes())]
644 )
645 .map_err(|e|
646 map_error_os!(e, "send_to_fd() writev() failed")
647 );
648 }
649 }
650
651 use crate::{error::SyslogError, throw_error};
652
653#[cfg(feature = "build_sync")]
654 pub(crate) use self::sync_portion::*;
655
656 #[cfg(test)]
657 mod tests
658 {
659 use super::*;
660
661 #[cfg(feature = "build_sync")]
662 #[test]
663 fn test_error_message()
664 {
665 let testmsg = "this is test message!";
671 let newline = "\n";
672 let stderr_lock = std::io::stderr().lock();
673 let res = send_to_fd(stderr_lock, testmsg, &newline);
674
675 println!("res: {:?}", res);
676
677 assert_eq!(res.is_ok(), true, "err: {}", res.err().unwrap());
678
679 return;
680 }
681
682 #[test]
683 fn test_priority_shl()
684 {
685 assert_eq!((1 << 5), (1 << Priority::LOG_NOTICE));
686 }
687 }
688}
689
690pub static PATH_CONSOLE: LazyLock<&Path> = LazyLock::new(||
692 {
693 Path::new("/dev/console")
694 }
695);
696
697pub static RFC5424_MAX_DGRAM: LazyLock<usize> = LazyLock::new(||
699 {
700 portable::get_local_dgram_maxdgram() as usize
701 }
702);
703
704
705pub const MAXHOSTNAMELEN: usize = 256;
707
708pub const LOG_FACMASK: i32 = 0x03f8;
710
711pub const MAXLINE: usize = 8192;
715
716pub const RFC3164_MAX_PAYLOAD_LEN: usize = 1024;
718
719pub const WINDOWS_EVENT_REPORT_MAX_PAYLOAD_LEN: usize = 31839;
721
722#[cfg(all(feature = "udp_truncate_1024_bytes", feature = "udp_truncate_1440_bytes"))]
723compile_error!("either 'udp_truncate_1024_bytes' or 'udp_truncate_1440_bytes' should be enabled");
724
725#[cfg(feature = "udp_truncate_1024_bytes")]
727pub const RFC5424_UDP_MAX_PKT_LEN: usize = 1024;
728
729#[cfg(any(feature = "udp_truncate_1440_bytes", all(not(feature = "udp_truncate_1440_bytes"), not(feature = "udp_truncate_1024_bytes"))))]
730pub const RFC5424_UDP_MAX_PKT_LEN: usize = 2048;
731
732#[cfg(feature = "tcp_truncate_1024_bytes")]
733pub const RFC5424_TCP_MAX_PKT_LEN: usize = 1024;
734
735#[cfg(feature = "tcp_truncate_2048_bytes")]
736pub const RFC5424_TCP_MAX_PKT_LEN: usize = 2048;
737
738#[cfg(feature = "tcp_truncate_4096_bytes")]
739pub const RFC5424_TCP_MAX_PKT_LEN: usize = 4096;
740
741#[cfg(feature = "tcp_truncate_max_bytes")]
742pub const RFC5424_TCP_MAX_PKT_LEN: usize = MAXLINE;
743
744pub const RFC_MAX_APP_NAME: usize = 48;
746
747pub const IANA_PRIV_ENT_NUM: u64 = 32473;
749
750pub const NILVALUE: &'static str = "-";
752
753pub const ESC_CHAR_REPL: &'static str = "#000";
755
756pub const NILVALUE_B: &'static [u8] = b"-";
758
759pub const WSPACE: &'static str = " ";
761
762pub const OBRACE: &'static str = "[";
764
765pub const CBRACE: &'static str = "]";
767
768pub const CBRACE_SEM: &'static str = "]:";
770
771pub const QCHAR: &'static str = "\"";
773
774pub const ATSIGN: &'static str = "@";
776
777pub const EQSIGN: &'static str = "=";
779
780pub const NEXTLINE: &'static str = "\n";
782
783bitflags! {
784 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
786 pub(crate) struct LogMask: i32
787 {
788 const LOG_FACMASK = 0x3f8;
790
791 const LOG_PRIMASK = 7;
793 }
794}
795
796#[derive(Debug, Clone, Copy, PartialEq, Eq)]
802pub struct SyslogMsgPriFac(i32);
803
804impl fmt::Display for SyslogMsgPriFac
805{
806 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
807 {
808 write!(f, "{}", self.0)
809 }
810}
811
812impl TryFrom<i32> for SyslogMsgPriFac
813{
814 type Error = SyslogError;
815
816 fn try_from(value: i32) -> Result<Self, Self::Error>
817 {
818 if (value & !(LogMask::LOG_PRIMASK | LogMask::LOG_FACMASK )) != 0
819 {
820 throw_error!("unknwon facility/priority: {:x}", value);
821 }
822
823 return Ok(Self(value));
824 }
825}
826
827impl TryFrom<&[u8]> for SyslogMsgPriFac
828{
829 type Error = SyslogError;
830
831 fn try_from(value: &[u8]) -> Result<Self, Self::Error>
832 {
833 let val =
834 str::from_utf8(value)
835 .map_or(
836 None,
837 |pri_str|
838 {
839 i32::from_str_radix(pri_str, 10)
840 .map_or(
841 None,
842 |val|
843 Some(val & LogMask::LOG_PRIMASK | val & LogMask::LOG_FACMASK.bits())
844 )
845 }
846 )
847 .ok_or(
848 map_error_code!(InternalError, "cannot convert to prio|facility")
849 )?;
850
851 if (val & !(LogMask::LOG_PRIMASK | LogMask::LOG_FACMASK )) != 0
852 {
853 throw_error!("unknwon facility/priority: {:x}", val);
854 }
855
856 return Ok(Self(val));
857 }
858}
859
860impl SyslogMsgPriFac
861{
862 pub(crate)
865 fn set_facility(p: Priority, f: LogFacility) -> Self
866 {
867 return Self( p as i32 | f.bits() );
868 }
869
870 pub
872 fn get_val(&self) -> i32
873 {
874 return self.0;
875 }
876
877 pub
879 fn get_priority(&self) -> Priority
880 {
881 return Priority::from(self.0 & LogMask::LOG_PRIMASK);
882 }
883
884 pub
886 fn get_log_facility(&self) -> LogFacility
887 {
888 return LogFacility::from_bits_retain(self.0 & LogMask::LOG_FACMASK);
889 }
890}
891
892impl From<i32> for Priority
893{
894 fn from(value: i32) -> Self
895 {
896 if value == Priority::LOG_ALERT as i32
897 {
898 return Priority::LOG_ALERT;
899 }
900 else if value == Priority::LOG_CRIT as i32
901 {
902 return Priority::LOG_CRIT;
903 }
904 else if value == Priority::LOG_DEBUG as i32
905 {
906 return Priority::LOG_DEBUG;
907 }
908 else if value == Priority::LOG_EMERG as i32
909 {
910 return Priority::LOG_EMERG;
911 }
912 else if value == Priority::LOG_ERR as i32
913 {
914 return Priority::LOG_ERR;
915 }
916 else if value == Priority::LOG_INFO as i32
917 {
918 return Priority::LOG_INFO;
919 }
920 else if value == Priority::LOG_NOTICE as i32
921 {
922 return Priority::LOG_NOTICE;
923 }
924 else
925 {
926 return Priority::LOG_WARNING;
927 }
928 }
929}
930
931#[macro_export]
942macro_rules! LOG_MASK
943{
944 ($arg:expr) => (
945 (1 << ($arg))
946 )
947}
948
949#[macro_export]
959macro_rules! LOG_UPTO
960{
961 ($arg:expr) => (
962 ((1 << (($arg) + 1)) - 1)
963 )
964}
965
966impl Shl<Priority> for i32
967{
968 type Output = i32;
969
970 fn shl(self, rhs: Priority) -> i32
971 {
972 let lhs = self;
973 return lhs << rhs as i32;
974 }
975}
976
977impl BitAnd<Priority> for i32
978{
979 type Output = i32;
980
981 #[inline]
982 fn bitand(self, rhs: Priority) -> i32
983 {
984 return self & rhs as i32;
985 }
986}
987
988impl Add<Priority> for i32
989{
990 type Output = i32;
991
992 fn add(self, rhs: Priority) -> Self::Output
993 {
994 rhs as i32 + self
995 }
996}
997
998impl Add<i32> for Priority
999{
1000 type Output = i32;
1001
1002 fn add(self, rhs: i32) -> Self::Output
1003 {
1004 self as i32 + rhs
1005 }
1006}
1007
1008impl BitAnd<LogMask> for Priority
1009{
1010 type Output = i32;
1011
1012 #[inline]
1013 fn bitand(self, rhs: LogMask) -> i32
1014 {
1015 return self as i32 & rhs.bits();
1016 }
1017}
1018
1019impl BitAnd<LogMask> for LogFacility
1020{
1021 type Output = LogFacility;
1022
1023 #[inline]
1024 fn bitand(self, rhs: LogMask) -> Self::Output
1025 {
1026 return Self::from_bits_retain(self.bits() & rhs.bits());
1027 }
1028}
1029
1030impl BitAnd<LogMask> for i32
1031{
1032 type Output = i32;
1033
1034 #[inline]
1035 fn bitand(self, rhs: LogMask) -> i32
1036 {
1037 return self & rhs.bits();
1038 }
1039}
1040
1041pub
1051fn truncate(lt: &str) -> &str
1052{
1053 let ltt =
1054 match lt.char_indices().nth(lt.len()-1)
1055 {
1056 None => lt,
1057 Some((idx, _)) => <[..idx],
1058 };
1059 return ltt;
1060}
1061
1062pub
1086fn truncate_n<'t>(lt: &'t str, n: usize) -> &'t str
1087{
1088 if lt.as_bytes().len() <= n
1089 {
1090 return lt;
1091 }
1092
1093 let mut nn: usize = 0;
1094 let mut cc = lt.chars();
1095 let mut ln: usize;
1096
1097 loop
1098 {
1099 match cc.next()
1100 {
1101 Some(r) =>
1102 {
1103 ln = r.len_utf8();
1104 nn += ln;
1105
1106 if nn == n
1107 {
1108 return <[..nn];
1109 }
1110 else if nn > n
1111 {
1112 return <[..nn-ln];
1113 }
1114 },
1115 None =>
1116 return lt,
1117 }
1118 }
1119}
1120
1121pub
1130fn check_printable(a: &str) -> SyRes<()>
1131{
1132 if a.is_empty() == true
1133 {
1134 throw_error!("empty SD value");
1135 }
1136
1137 for p in a.chars()
1138 {
1139 if p.is_ascii() == false || p.is_ascii_graphic() == false || p == '@' || p == '=' || p == ']' || p == '\"'
1140 {
1141 throw_error!("incorrect char: '{:X}' in SD value", p as u64);
1142 }
1143 }
1144
1145 return Ok(());
1146}
1147
1148
1149pub
1150fn escape_chars(st: Cow<'static, str>) -> Cow<'static, str>
1151{
1152 let mut out = String::with_capacity(st.len());
1153
1154 for c in st.chars()
1155 {
1156 if c.is_control() == true
1157 {
1158 out.push_str(ESC_CHAR_REPL);
1159 }
1160 else if c == '\"' || c == '\\' || c == ']'
1161 {
1162 out.push('\\');
1163 out.push(c);
1164 }
1165 else
1166 {
1167 out.push(c);
1168 }
1169 }
1170
1171 if st.len() == out.len()
1172 {
1173 return st;
1174 }
1175 else
1176 {
1177 return Cow::Owned(out);
1178 }
1179}
1180
1181
1182#[cfg(test)]
1183mod tests
1184{
1185 use super::*;
1186
1187 #[test]
1188 fn test_truncate()
1189 {
1190 let test = "cat\n";
1191
1192 let trunc = truncate(test);
1193
1194 assert_eq!("cat", trunc);
1195 }
1196
1197
1198
1199 #[test]
1200 fn test_truncate_n()
1201 {
1202 assert_eq!(truncate_n("abcde", 3), "abc");
1203 assert_eq!(truncate_n("ボルテ", 4), "ボ");
1204 assert_eq!(truncate_n("ボルテ", 5), "ボ");
1205 assert_eq!(truncate_n("ボルテ", 6), "ボル");
1206 assert_eq!(truncate_n("abcde", 0), "");
1207 assert_eq!(truncate_n("abcde", 5), "abcde");
1208 assert_eq!(truncate_n("abcde", 6), "abcde");
1209 assert_eq!(truncate_n("ДАТА", 3), "Д");
1210 assert_eq!(truncate_n("ДАТА", 4), "ДА");
1211 assert_eq!(truncate_n("ДАТА", 1), "");
1212 }
1213
1214}