rnotifylib/message/author.rs
1use std::fmt::{Display, Formatter};
2
3/// The hostname used when the hostname
4/// cannot be retrieved.
5const UNKNOWN_HOSTNAME: &str = "?";
6
7/// The author or creator of the message.
8///
9/// The base author will contain the hostname of the OS that sent to message.
10/// This helps identify which machine the message came from. If this is not available then '?' will
11/// be used.
12///
13/// A good author should allow the user to quickly and easily identify where the message
14/// originates from.
15/// To make a good author, think, could you quickly and easily stop the source of the messages just
16/// based on the author?
17///
18/// Filtering should not be performed based on an Author, rather you should filter instead
19/// based on [`Level`] and [`Component`]
20///
21/// [`Level`]: crate::message::Level
22/// [`Component`]: crate::message::component::Component
23#[derive(Debug, Clone, PartialEq)]
24pub struct Author {
25 parts: Vec<String>,
26}
27
28impl Author {
29 /// Parses an Author from the given string.
30 ///
31 /// ```rust
32 /// // A good Author for a message originating from the db_checker program
33 /// // which is invoked by user's crontab.
34 /// use rnotifylib::message::author::Author;
35 ///
36 /// let author = Author::parse("user/cron/db_checker".to_owned());
37 /// ```
38 pub fn parse(parts: String) -> Author {
39 let mut new = Self::base();
40 new.extend(parts);
41 new
42 }
43
44 /// Provides the base Author, of either the hostname.
45 /// If the hostname cannot be found, uses [`base_incognito`](Self::base_incognito)
46 pub fn base() -> Author {
47 let base = match hostname::get() {
48 Ok(hostname) => {
49 hostname.to_string_lossy().to_string()
50 }
51 Err(_) => {
52 return Self::base_incognito();
53 }
54 };
55
56 Author {
57 parts: vec![base],
58 }
59 }
60
61 /// Creates an Author with an unknown hostname.
62 /// You should use [`base`](Self::base) whenever possible, but if you do not want to expose
63 /// the hostname of the sender, you can use this method.
64 pub fn base_incognito() -> Author {
65 Author {
66 parts: vec![UNKNOWN_HOSTNAME.to_string()]
67 }
68 }
69
70 /// Parses an author, using an unknown hostname
71 /// You should use [`parse`](Self::parse) whenever possible, but if you do not want to expose
72 /// the hostname of the sender, you can use this method.
73 pub fn parse_incognito(s: String) -> Author {
74 let mut base = Self::base_incognito();
75 base.extend(s);
76 base
77 }
78
79 /// Adds more information to the author of this
80 /// ```rust
81 /// use rnotifylib::message::author::Author;
82 ///
83 /// // Normally you should use Author::base(), but we want predictable output for this test.
84 /// let mut author = Author::base_incognito();
85 /// author.extend("user".to_owned());
86 /// author.extend("cron".to_owned());
87 /// author.extend("db_checker".to_owned());
88 ///
89 /// assert_eq!(author.to_string(), "?/user/cron/db_checker");
90 pub fn extend(&mut self, parts: String) {
91 let vec: Vec<String> = parts.split("/").into_iter()
92 .filter(|s| !s.is_empty())
93 .map(|s| s.to_owned())
94 .collect();
95
96 self.parts.extend(vec);
97 }
98}
99
100impl Display for Author {
101 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
102 write!(f, "{}", self.parts.join("/"))
103 }
104}