1pub mod membership;
2pub mod model;
3
4pub mod server;
5
6pub mod lattices;
7
8pub mod util;
9
10use std::collections::HashSet;
11use std::fmt::Display;
12use std::str::FromStr;
13
14use serde::{Deserialize, Serialize};
15
16use crate::KeyParseError::InvalidNamespace;
17use crate::model::{Clock, Namespaces};
18
19#[derive(Debug, Eq, PartialEq, Clone, Copy, Serialize, Deserialize, Hash)]
21pub enum Namespace {
22 User,
24
25 System,
27}
28
29#[derive(Debug, Eq, PartialEq, Clone, Copy)]
31pub enum KeyParseError {
32 InvalidNamespace,
34
35 InvalidFormat,
37}
38
39impl Display for KeyParseError {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 match self {
42 InvalidNamespace => write!(f, "Invalid namespace"),
43 KeyParseError::InvalidFormat => write!(f, "Invalid key format"),
44 }
45 }
46}
47
48impl FromStr for Namespace {
49 type Err = KeyParseError;
50 fn from_str(s: &str) -> Result<Self, Self::Err> {
51 match s {
52 "usr" => Ok(Namespace::User),
53 "sys" => Ok(Namespace::System),
54 _ => Err(InvalidNamespace),
55 }
56 }
57}
58
59pub type TableName = String;
61
62pub type RowKey = String;
64
65#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize, Hash)]
71pub struct Key {
72 pub namespace: Namespace,
74 pub table: TableName,
76 pub row_key: RowKey,
78}
79
80impl FromStr for Key {
81 type Err = KeyParseError;
82 fn from_str(s: &str) -> Result<Self, Self::Err> {
83 let mut parts: Vec<String> = vec![];
84 let mut current_part = String::new();
85 let mut escaping = false;
86
87 for c in s.chars() {
88 match (escaping, c) {
89 (true, '\\') | (true, '/') => {
90 current_part.push(c);
91 escaping = false;
92 }
93 (true, _) => return Err(KeyParseError::InvalidFormat),
94 (false, '\\') => {
95 escaping = true;
96 }
97 (false, '/') => {
98 parts.push(current_part);
99 current_part = String::new();
100 }
101 (false, _) => {
102 current_part.push(c);
103 }
104 }
105 }
106
107 if escaping {
108 return Err(KeyParseError::InvalidFormat);
109 }
110
111 if !current_part.is_empty() {
112 parts.push(current_part);
113 }
114
115 if parts.len() != 4 {
116 return Err(KeyParseError::InvalidFormat);
117 }
118
119 if !parts[0].is_empty() {
120 return Err(KeyParseError::InvalidFormat);
121 }
122
123 if parts[2].is_empty() || parts[3].is_empty() {
124 return Err(KeyParseError::InvalidFormat);
125 }
126
127 let namespace = parts[1].parse()?;
128 Ok(Key {
129 namespace,
130 table: parts[2].to_string(),
131 row_key: parts[3].to_string(),
132 })
133 }
134}
135
136#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
138pub enum ClientRequest {
139 Get { key: Key },
141 Set { key: Key, value: String },
143 Delete { key: Key },
145}
146
147#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
148pub enum ClientResponse {
149 Get { key: Key, value: HashSet<String> },
152 Set { success: bool },
154 Delete { success: bool },
156}
157
158#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
159pub enum GossipMessage {
160 Gossip {
162 message_id: String,
163 member_id: String,
164 writes: Namespaces<Clock>,
165 },
166 Ack {
169 message_id: String,
170 member_id: String,
171 },
172 Nack {
175 message_id: String,
176 member_id: String,
177 },
178}
179
180#[cfg(test)]
181mod tests {
182 use super::{Key, Namespace};
183
184 #[test]
185 fn test_key_parsing_sys_namespace() {
186 let first = "/sys/sys_table/sys_row".parse::<Key>().unwrap();
188 assert_eq!(first.namespace, Namespace::System);
189 assert_eq!(first.table, "sys_table");
190 assert_eq!(first.row_key, "sys_row");
191 }
192 #[test]
193 fn test_key_parsing_user_namespace() {
194 let second = "/usr/usr_table/usr_row".parse::<Key>().unwrap();
196 assert_eq!(second.namespace, Namespace::User);
197 assert_eq!(second.table, "usr_table");
198 assert_eq!(second.row_key, "usr_row");
199 }
200
201 #[test]
202 fn test_key_empty_table() {
203 let empty_table = "/usr//usr_row".parse::<Key>();
205 assert!(empty_table.is_err());
206 assert_eq!(
207 empty_table.unwrap_err(),
208 super::KeyParseError::InvalidFormat
209 );
210 }
211
212 #[test]
213 fn test_key_empty_row() {
214 let empty_row = "/usr/usr_table/".parse::<Key>();
216 assert!(empty_row.is_err());
217 assert_eq!(empty_row.unwrap_err(), super::KeyParseError::InvalidFormat);
218 }
219
220 #[test]
221 fn test_key_parsing_invalid_namespace() {
222 let non_existent_namespace = "/ne_namespace/ne_table/ne_row".parse::<Key>();
224 assert!(non_existent_namespace.is_err());
225 assert_eq!(
226 non_existent_namespace.unwrap_err(),
227 super::KeyParseError::InvalidNamespace
228 );
229 }
230
231 #[test]
232 fn test_key_parsing_invalid_format() {
233 let invalid_format = "/not_even_a_key".parse::<Key>();
235 assert!(invalid_format.is_err());
236 assert_eq!(
237 invalid_format.unwrap_err(),
238 super::KeyParseError::InvalidFormat
239 );
240
241 let invalid_format = "abcd/sys/sys_table/sys_row".parse::<Key>();
242 assert!(invalid_format.is_err());
243 assert_eq!(
244 invalid_format.unwrap_err(),
245 super::KeyParseError::InvalidFormat
246 );
247 }
248
249 #[test]
250 fn test_key_parsing_escaping() {
251 let key = r"/usr/usr\/table/usr\/row".parse::<Key>().unwrap();
253 assert_eq!(key.namespace, Namespace::User);
254 assert_eq!(key.table, r"usr/table");
255 assert_eq!(key.row_key, r"usr/row");
256
257 let key = r"/usr/usr\\table/usr\\row".parse::<Key>().unwrap();
259 assert_eq!(key.namespace, Namespace::User);
260 assert_eq!(key.table, r"usr\table");
261 assert_eq!(key.row_key, r"usr\row");
262
263 let key = r"/usr/usr\table/usr\row".parse::<Key>();
265 assert!(key.is_err());
266 assert_eq!(key.unwrap_err(), super::KeyParseError::InvalidFormat);
267
268 let key = r"/usr/usr_table/usr_row\".parse::<Key>();
270 assert!(key.is_err());
271 assert_eq!(key.unwrap_err(), super::KeyParseError::InvalidFormat);
272 }
273}