1pub mod benchmark;
21mod client;
22pub mod error;
23mod server;
24pub mod tcp;
25
26pub use client::*;
27use serde_json::json;
28pub use server::*;
29
30use error::WorterbuchResult;
31use serde::{de::DeserializeOwned, Deserialize, Serialize};
32use serde_repr::*;
33use sha2::{Digest, Sha256};
34use std::{fmt, ops::Deref};
35
36pub const PROTOCOL_VERSION: &str = "0.11";
37
38pub const SYSTEM_TOPIC_ROOT: &str = "$SYS";
39pub const SYSTEM_TOPIC_ROOT_PREFIX: &str = "$SYS/";
40pub const SYSTEM_TOPIC_CLIENTS: &str = "clients";
41pub const SYSTEM_TOPIC_VERSION: &str = "version";
42pub const SYSTEM_TOPIC_LICENSE: &str = "license";
43pub const SYSTEM_TOPIC_SOURCES: &str = "source-code";
44pub const SYSTEM_TOPIC_SUBSCRIPTIONS: &str = "subscriptions";
45pub const SYSTEM_TOPIC_CLIENTS_PROTOCOL: &str = "protocol";
46pub const SYSTEM_TOPIC_CLIENTS_ADDRESS: &str = "address";
47pub const SYSTEM_TOPIC_LAST_WILL: &str = "lastWill";
48pub const SYSTEM_TOPIC_GRAVE_GOODS: &str = "graveGoods";
49pub const SYSTEM_TOPIC_CLIENT_NAME: &str = "clientName";
50pub const SYSTEM_TOPIC_SUPPORTED_PROTOCOL_VERSION: &str = "protocolVersion";
51
52pub type TransactionId = u64;
53pub type RequestPattern = String;
54pub type RequestPatterns = Vec<RequestPattern>;
55pub type Key = String;
56pub type Value = serde_json::Value;
57pub type KeyValuePairs = Vec<KeyValuePair>;
58pub type TypedKeyValuePairs<T> = Vec<TypedKeyValuePair<T>>;
59pub type MetaData = String;
60pub type Path = String;
61pub type ProtocolVersionSegment = u16;
62pub type ProtocolVersions = Vec<ProtocolVersion>;
63pub type LastWill = KeyValuePairs;
64pub type GraveGoods = RequestPatterns;
65pub type UniqueFlag = bool;
66pub type LiveOnlyFlag = bool;
67pub type AuthToken = String;
68
69#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
70#[serde(rename_all = "camelCase")]
71pub enum Privilege {
72 Read,
73 Write,
74 Delete,
75}
76
77impl fmt::Display for Privilege {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 match self {
80 Privilege::Read => "read".fmt(f),
81 Privilege::Write => "write".fmt(f),
82 Privilege::Delete => "delete".fmt(f),
83 }
84 }
85}
86
87#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr)]
88#[repr(u8)]
89pub enum ErrorCode {
90 IllegalWildcard = 0b00000000,
91 IllegalMultiWildcard = 0b00000001,
92 MultiWildcardAtIllegalPosition = 0b00000010,
93 IoError = 0b00000011,
94 SerdeError = 0b00000100,
95 NoSuchValue = 0b00000101,
96 NotSubscribed = 0b00000110,
97 ProtocolNegotiationFailed = 0b00000111,
98 InvalidServerResponse = 0b00001000,
99 ReadOnlyKey = 0b00001001,
100 AuthorizationFailed = 0b00001010,
101 AuthorizationRequired = 0b00001011,
102 AlreadyAuthorized = 0b00001100,
103 MissingValue = 0b00001101,
104 Unauthorized = 0b00001110,
105 NoPubStream = 0b00001111,
106 Other = 0b11111111,
107}
108
109impl fmt::Display for ErrorCode {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 (self.to_owned() as u8).fmt(f)
112 }
113}
114
115#[macro_export]
116macro_rules! topic {
117 ($( $x:expr ),+ ) => {
118 {
119 let mut segments = Vec::new();
120 $(
121 segments.push($x.to_string());
122 )+
123 segments.join("/")
124 }
125 };
126}
127
128pub type Version = String;
129pub type ProtocolVersion = String;
130
131#[derive(Debug, Clone, PartialEq, Eq, Serialize, Hash, Deserialize)]
132pub enum Protocol {
133 TCP,
134 WS,
135 HTTP,
136 UNIX,
137}
138
139#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
140#[serde(rename_all = "camelCase")]
141pub struct KeyValuePair {
142 pub key: Key,
143 pub value: Value,
144}
145
146impl fmt::Display for KeyValuePair {
147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 write!(f, "{}={}", self.key, self.value)
149 }
150}
151
152impl From<KeyValuePair> for Option<Value> {
153 fn from(kvp: KeyValuePair) -> Self {
154 Some(kvp.value)
155 }
156}
157
158impl From<KeyValuePair> for Value {
159 fn from(kvp: KeyValuePair) -> Self {
160 kvp.value
161 }
162}
163
164impl KeyValuePair {
165 pub fn new<S: Serialize>(key: String, value: S) -> Self {
166 (key, value).into()
167 }
168
169 pub fn of<S: Serialize>(key: String, value: S) -> Self {
170 KeyValuePair::new(key, value)
171 }
172}
173
174#[derive(Debug, Clone, PartialEq, Eq)]
175pub struct TypedKeyValuePair<T: DeserializeOwned> {
176 pub key: Key,
177 pub value: T,
178}
179
180impl<T: DeserializeOwned> TryFrom<KeyValuePair> for TypedKeyValuePair<T> {
181 type Error = serde_json::Error;
182
183 fn try_from(kvp: KeyValuePair) -> Result<Self, Self::Error> {
184 let deserialized = serde_json::from_value(kvp.value)?;
185 Ok(TypedKeyValuePair {
186 key: kvp.key,
187 value: deserialized,
188 })
189 }
190}
191
192impl<S: Serialize> From<(String, S)> for KeyValuePair {
193 fn from((key, value): (String, S)) -> Self {
194 let value = json!(value);
195 KeyValuePair { key, value }
196 }
197}
198
199impl<S: Serialize> From<(&str, S)> for KeyValuePair {
200 fn from((key, value): (&str, S)) -> Self {
201 let value = json!(value);
202 KeyValuePair {
203 key: key.to_owned(),
204 value,
205 }
206 }
207}
208
209pub type RegularKeySegment = String;
211
212pub fn parse_segments(pattern: &str) -> WorterbuchResult<Vec<RegularKeySegment>> {
213 let mut segments = Vec::new();
214 for segment in pattern.split('/') {
215 let ks: KeySegment = segment.into();
216 match ks {
217 KeySegment::Regular(reg) => segments.push(reg),
218 KeySegment::Wildcard => {
219 return Err(error::WorterbuchError::IllegalWildcard(pattern.to_owned()))
220 }
221 KeySegment::MultiWildcard => {
222 return Err(error::WorterbuchError::IllegalMultiWildcard(
223 pattern.to_owned(),
224 ))
225 }
226 }
227 }
228 Ok(segments)
229}
230
231#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
232pub enum KeySegment {
233 Regular(RegularKeySegment),
234 Wildcard,
235 MultiWildcard,
236 }
238
239pub fn format_path(path: &[KeySegment]) -> String {
240 path.iter()
241 .map(|seg| format!("{seg}"))
242 .collect::<Vec<String>>()
243 .join("/")
244}
245
246impl From<RegularKeySegment> for KeySegment {
247 fn from(reg: RegularKeySegment) -> Self {
248 Self::Regular(reg)
249 }
250}
251
252impl Deref for KeySegment {
253 type Target = str;
254
255 fn deref(&self) -> &Self::Target {
256 match self {
257 KeySegment::Regular(reg) => reg,
258 KeySegment::Wildcard => "?",
259 KeySegment::MultiWildcard => "#",
260 }
261 }
262}
263
264impl fmt::Display for KeySegment {
265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266 match self {
267 KeySegment::Regular(segment) => segment.fmt(f),
268 KeySegment::Wildcard => write!(f, "?"),
269 KeySegment::MultiWildcard => write!(f, "#"),
270 }
272 }
273}
274
275impl From<&str> for KeySegment {
276 fn from(str: &str) -> Self {
277 match str {
278 "?" => KeySegment::Wildcard,
279 "#" => KeySegment::MultiWildcard,
280 other => KeySegment::Regular(other.to_owned()),
281 }
282 }
283}
284
285impl KeySegment {
286 pub fn parse(pattern: impl AsRef<str>) -> Vec<KeySegment> {
287 let segments = pattern.as_ref().split('/');
288 segments.map(KeySegment::from).collect()
289 }
290}
291
292pub fn quote(str: impl AsRef<str>) -> String {
293 let str_ref = str.as_ref();
294 if str_ref.starts_with('\"') && str_ref.ends_with('\"') {
295 str_ref.to_owned()
296 } else {
297 format!("\"{str_ref}\"")
298 }
299}
300
301pub fn digest_token(auth_token: &Option<String>, client_id: String) -> Option<String> {
302 auth_token.as_deref().map(|token| {
303 let salted = client_id + token;
304 let mut hasher = Sha256::new();
305 hasher.update(salted.as_bytes());
306 format!("{:x}", hasher.finalize())
307 })
308}
309
310#[cfg(test)]
311mod test {
312 use crate::ErrorCode;
313 use std::cmp::Ordering;
314
315 #[test]
316 fn protocol_versions_are_sorted_correctly() {
317 assert_eq!("0.1".cmp("0.2"), Ordering::Less);
318 assert_eq!("0.9".cmp("1.0"), Ordering::Less);
319 assert_eq!("1.2".cmp("1.3"), Ordering::Less);
320 assert_eq!("1.234".cmp("1.3"), Ordering::Less);
321
322 assert_eq!("0.1".cmp("0.1"), Ordering::Equal);
323 assert_eq!("0.9".cmp("0.9"), Ordering::Equal);
324 assert_eq!("1.2".cmp("1.2"), Ordering::Equal);
325
326 assert_eq!("0.2".cmp("0.1"), Ordering::Greater);
327 assert_eq!("1.0".cmp("0.9"), Ordering::Greater);
328 assert_eq!("1.3".cmp("1.2"), Ordering::Greater);
329 assert_eq!("1.3".cmp("1.234"), Ordering::Greater);
330 assert_eq!("13.45".cmp("1.345"), Ordering::Greater);
331
332 assert_eq!("0.3", "0.3".min("0.5"));
333 assert_eq!("0.8", "0.8".min("1.2"));
334 assert_eq!("2.3", "2.3".min("3.1"));
335
336 assert_eq!("0.3", "0.5".min("0.3"));
337 assert_eq!("0.8", "1.2".min("0.8"));
338 assert_eq!("2.34", "3.1".min("2.34"));
339
340 let mut versions = vec!["1.2", "0.456", "9.0", "3.15"];
341 versions.sort();
342 assert_eq!(vec!["0.456", "1.2", "3.15", "9.0"], versions);
343 }
344
345 #[test]
346 fn topic_macro_generates_topic_correctly() {
347 assert_eq!(
348 "hello/world/foo/bar",
349 topic!("hello", "world", "foo", "bar")
350 );
351 }
352
353 #[test]
354 fn error_codes_are_serialized_as_numbers() {
355 assert_eq!(
356 "1",
357 serde_json::to_string(&ErrorCode::IllegalMultiWildcard).unwrap()
358 )
359 }
360
361 #[test]
362 fn error_codes_are_deserialized_from_numbers() {
363 assert_eq!(
364 ErrorCode::ProtocolNegotiationFailed,
365 serde_json::from_str("7").unwrap()
366 )
367 }
368}