1use std::{
2 convert::TryFrom,
3 error::Error,
4 fmt::{self, Display},
5 str::FromStr,
6};
7
8pub use crate::packet::{RejectReason, ServerRejectReason};
9pub use crate::settings::{AcceptParameters, StreamAcceptor};
10
11#[derive(Debug, PartialEq, Eq)]
13pub struct AccessControlList(pub Vec<AccessControlEntry>);
14
15#[derive(Debug, PartialEq, Eq)]
16pub struct AccessControlEntry {
17 pub key: String,
18 pub value: String,
19}
20
21#[non_exhaustive]
22#[derive(Debug, Copy, Clone, Eq, PartialEq)]
23pub enum ConnectionType {
24 Stream,
25 File,
26 Auth,
27}
28
29#[non_exhaustive]
30#[derive(Debug, Copy, Clone, Eq, PartialEq)]
31pub enum ConnectionMode {
32 Request,
33 Publish,
34 Bidirectional,
35}
36
37#[derive(Debug, Clone)]
38pub enum StandardAccessControlEntry {
39 UserName(String),
40 ResourceName(String),
41 HostName(String),
42 SessionId(String),
43 Type(ConnectionType),
44 Mode(ConnectionMode),
45}
46
47#[derive(Debug, Eq, PartialEq)]
48#[non_exhaustive]
49pub enum ParseAccessControlEntryError {
50 NoValue,
52 WrongStart,
54}
55
56impl Display for AccessControlList {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 let mut iter = self.0.iter().fuse();
59 if let Some(item) = iter.next() {
60 write!(f, "#!::{item}")?;
61 }
62
63 for item in iter {
64 write!(f, ",{item}")?;
65 }
66 Ok(())
67 }
68}
69
70impl FromStr for AccessControlList {
71 type Err = ParseAccessControlEntryError;
72 fn from_str(mut s: &str) -> Result<Self, Self::Err> {
73 if !s.starts_with("#!::") {
74 return Err(ParseAccessControlEntryError::WrongStart);
75 }
76 s = &s[4..]; Ok(AccessControlList(
79 s.split(',')
80 .map(str::parse)
81 .collect::<Result<Vec<_>, _>>()?,
82 ))
83 }
84}
85
86impl AccessControlEntry {
87 fn new(key: impl Into<String>, value: impl Into<String>) -> AccessControlEntry {
88 AccessControlEntry {
89 key: key.into(),
90 value: value.into(),
91 }
92 }
93}
94
95impl Display for AccessControlEntry {
96 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97 write!(f, "{}={}", self.key, self.value)
98 }
99}
100
101impl FromStr for AccessControlEntry {
102 type Err = ParseAccessControlEntryError;
103 fn from_str(s: &str) -> Result<Self, Self::Err> {
104 let eq = s.find('=').ok_or(ParseAccessControlEntryError::NoValue)?;
105 let (k, v) = s.split_at(eq);
106
107 Ok(AccessControlEntry::new(k, &v[1..])) }
109}
110
111impl Display for ConnectionType {
112 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113 match self {
114 ConnectionType::Stream => write!(f, "stream"),
115 ConnectionType::File => write!(f, "file"),
116 ConnectionType::Auth => write!(f, "auth"),
117 }
118 }
119}
120
121impl FromStr for ConnectionType {
122 type Err = ();
123
124 fn from_str(s: &str) -> Result<Self, Self::Err> {
125 match s {
126 "stream" => Ok(ConnectionType::Stream),
127 "file" => Ok(ConnectionType::File),
128 "auth" => Ok(ConnectionType::Auth),
129 _ => Err(()),
130 }
131 }
132}
133
134impl Display for ConnectionMode {
135 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
136 match self {
137 ConnectionMode::Request => write!(f, "request"),
138 ConnectionMode::Publish => write!(f, "publish"),
139 ConnectionMode::Bidirectional => write!(f, "bidirectional"),
140 }
141 }
142}
143
144impl FromStr for ConnectionMode {
145 type Err = ();
146
147 fn from_str(s: &str) -> Result<Self, Self::Err> {
148 match s {
149 "request" => Ok(ConnectionMode::Request),
150 "publish" => Ok(ConnectionMode::Publish),
151 "bidirectional" => Ok(ConnectionMode::Bidirectional),
152 _ => Err(()),
153 }
154 }
155}
156
157impl TryFrom<AccessControlEntry> for StandardAccessControlEntry {
158 type Error = ();
159
160 fn try_from(value: AccessControlEntry) -> Result<Self, Self::Error> {
161 match &value.key[..] {
162 "u" => Ok(StandardAccessControlEntry::UserName(value.value)),
163 "r" => Ok(StandardAccessControlEntry::ResourceName(value.value)),
164 "h" => Ok(StandardAccessControlEntry::HostName(value.value)),
165 "s" => Ok(StandardAccessControlEntry::SessionId(value.value)),
166 "t" => Ok(StandardAccessControlEntry::Type(value.value.parse()?)),
167 "m" => Ok(StandardAccessControlEntry::Mode(value.value.parse()?)),
168 _ => Err(()),
169 }
170 }
171}
172
173impl From<StandardAccessControlEntry> for AccessControlEntry {
174 fn from(sace: StandardAccessControlEntry) -> Self {
175 match sace {
176 StandardAccessControlEntry::UserName(un) => AccessControlEntry::new("u", un),
177 StandardAccessControlEntry::ResourceName(rn) => AccessControlEntry::new("r", rn),
178 StandardAccessControlEntry::HostName(hn) => AccessControlEntry::new("h", hn),
179 StandardAccessControlEntry::SessionId(sid) => AccessControlEntry::new("s", sid),
180 StandardAccessControlEntry::Type(ty) => AccessControlEntry::new("t", format!("{ty}")),
181 StandardAccessControlEntry::Mode(m) => AccessControlEntry::new("m", format!("{m}")),
182 }
183 }
184}
185
186impl Display for StandardAccessControlEntry {
187 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
188 AccessControlEntry::from(self.clone()).fmt(f)
189 }
190}
191
192impl Display for ParseAccessControlEntryError {
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 match self {
195 ParseAccessControlEntryError::NoValue => write!(f, "No value to corresponding key"),
196 ParseAccessControlEntryError::WrongStart => {
197 write!(f, "Access control entry did not start with #!::")
198 }
199 }
200 }
201}
202
203impl Error for ParseAccessControlEntryError {}
204
205#[cfg(test)]
206mod tests {
207 use super::*;
208
209 #[test]
210 fn parse_ace() {
211 let ace_str = "#!::u=admin,r=bluesbrothers1_hi";
212 let ace = ace_str.parse::<AccessControlList>().unwrap();
213
214 assert_eq!(
215 ace,
216 AccessControlList(vec![
217 AccessControlEntry::new("u", "admin"),
218 AccessControlEntry::new("r", "bluesbrothers1_hi")
219 ])
220 );
221
222 assert_eq!(ace_str, format!("{ace}"))
223 }
224}