1use std::usize;
2
3use super::collection::Document;
9use uuid::Uuid;
10
11pub enum FindOp {
12 Eq,
13 NotEq,
14 Gt,
15 Lt,
16}
17
18#[derive(PartialEq, Debug)]
19pub enum DataType {
20 Id(Uuid),
21 Text(String),
22 Number(f32),
23 Boolean(bool),
24 Array(Vec<DataType>),
25 Document(Document),
26}
27
28#[macro_export]
29macro_rules! d {
30 ([$( $elem:tt ),* $(,)?]) => {
32 $crate::DataType::Array(vec![$( $crate::DataType::from($elem) ),*])
33 };
34
35 ($val:expr) => {
37 $crate::DataType::from($val)
38 };
39}
40
41impl DataType {
42 pub fn get_type(&self) -> &str {
43 match self {
44 DataType::Id(_) => "id",
45 DataType::Text(_) => "text",
46 DataType::Number(_) => "number",
47 DataType::Boolean(_) => "boolean",
48 DataType::Array(_) => "array",
49 DataType::Document(_) => "document",
50 }
51 }
52
53 pub fn get(&self, index: &str) -> Option<&DataType> {
54 match self {
55 DataType::Array(v) => {
56 let n = index.parse::<usize>().ok()?;
57 v.get(n)
58 }
59 DataType::Document(d) => d.get(index),
60 _ => None,
61 }
62 }
63
64 pub fn get_mut(&mut self, index: &str) -> Option<&mut DataType> {
65 match self {
66 DataType::Array(v) => {
67 let n = index.parse::<usize>().ok()?;
68 v.get_mut(n)
69 }
70 DataType::Document(d) => d.get_mut(index),
71 _ => None,
72 }
73 }
74
75 pub fn find(&self, sub_key: &str, op: FindOp, value: DataType) -> Option<DataType> {
76 let mut result: Vec<DataType> = Vec::new();
77 match self {
78 DataType::Array(v) => {
79 for item in v {
80 let sub_item = item.get(sub_key);
81 if sub_item.is_none() {
82 continue;
83 }
84 let sub_item = sub_item.unwrap();
85 let items_are_number = matches!(value, DataType::Number(_))
86 && matches!(*sub_item, DataType::Number(_));
87 let matched = match op {
88 FindOp::Eq => *sub_item == value,
89 FindOp::NotEq => *sub_item != value,
90 FindOp::Gt => items_are_number && sub_item.to_number() > value.to_number(),
91 FindOp::Lt => items_are_number && sub_item.to_number() < value.to_number(),
92 };
93 if matched {
94 result.push(item.clone());
95 }
96 }
97 return Some(DataType::Array(result));
98 }
99
100 _ => None,
101 }
102 }
103
104 pub fn set(&mut self, index: &str, dt: DataType) -> Result<DataType, &'static str> {
105 match self {
106 DataType::Array(vec) => {
107 if let Ok(index) = index.parse::<usize>() {
108 while index >= vec.len() {
109 vec.push(DataType::Text("".to_string()));
110 }
111 vec[index] = dt;
112 Ok(self.clone())
113 } else {
114 Err("Invalid index")
115 }
116 }
117 DataType::Document(doc) => {
118 doc.insert(index.to_string(), dt);
119 Ok(self.clone())
120 }
121 _ => Err("Not supported"),
122 }
123 }
124 pub fn remove(&mut self, index: &str) -> Result<DataType, &'static str> {
125 match self {
126 DataType::Array(vec) => {
127 if let Ok(index) = index.parse::<usize>() {
128 vec.remove(index);
129 Ok(self.clone())
130 } else {
131 Err("Invalid index")
132 }
133 }
134 DataType::Document(doc) => {
135 doc.remove(index);
136 Ok(self.clone())
137 }
138 _ => Err("Not supported"),
139 }
140 }
141
142 pub fn to_id(&self) -> Uuid {
144 match self {
145 DataType::Id(id) => *id,
146 _ => panic!("Not an ID"),
147 }
148 }
149 pub fn to_text(&self) -> &String {
150 match self {
151 DataType::Text(text) => text,
152 _ => panic!("Not a Text"),
153 }
154 }
155 pub fn to_number(&self) -> f32 {
156 match self {
157 DataType::Number(number) => *number,
158 _ => panic!("Not a Number"),
159 }
160 }
161 pub fn to_boolean(&self) -> bool {
162 match self {
163 DataType::Boolean(boolean) => *boolean,
164 _ => panic!("Not a Boolean"),
165 }
166 }
167 pub fn to_array(&self) -> &Vec<DataType> {
168 match self {
169 DataType::Array(array) => array,
170 _ => panic!("Not an Array"),
171 }
172 }
173 pub fn to_document(&self) -> &Document {
174 match self {
175 DataType::Document(document) => document,
176 _ => panic!("Not a Document"),
177 }
178 }
179
180 pub fn infer_type(raw: &str) -> u16 {
181 let raw = raw.trim();
182 if Uuid::parse_str(raw).is_ok() {
183 1
184 } else if raw.parse::<f32>().is_ok() {
185 3
186 } else if raw.to_lowercase().as_str() == "true" || raw.to_lowercase().as_str() == "false" {
187 4
188 } else if raw.starts_with('[') && raw.ends_with(']') {
189 5
190 } else if raw.starts_with('{') && raw.ends_with('}') {
191 6
192 } else {
193 2
194 }
195 }
196
197 pub fn load(t: u16, raw: String) -> Option<Self> {
198 let raw = raw.trim().to_string();
199 match t {
200 1 => {
201 let id = Uuid::parse_str(raw.as_str());
202 if id.is_err() {
203 return None;
204 }
205 Some(DataType::Id(id.unwrap()))
206 }
207 2 => Some(DataType::Text(raw.trim_matches('"').to_string())),
208 3 => {
209 let n = raw.parse::<f32>();
210 if n.is_err() {
211 return None;
212 }
213 Some(DataType::Number(n.unwrap()))
214 }
215 4 => match raw.to_lowercase().as_str() {
216 "true" => Some(DataType::Boolean(true)),
217 "false" => Some(DataType::Boolean(false)),
218 _ => None,
219 },
220 5 => {
221 let mut new_vec = Vec::new();
222 let raw = raw.strip_suffix(']').unwrap().strip_prefix('[').unwrap();
223 let mut open_array = false;
224 let mut open_string = false;
225 let mut open_bracket = 0;
226
227 let mut sub_raw = String::new();
228 for chr in raw.chars() {
229 if chr == ',' && !open_array && !open_string && open_bracket == 0 {
230 let t = Self::infer_type(&sub_raw);
231 let r = Self::load(t, sub_raw.clone());
232 if r.is_some() {
233 new_vec.push(r.unwrap());
234 sub_raw = String::new();
235 continue;
236 }
237 }
238 if chr == '[' && !open_array {
239 open_array = true;
240 }
241 if chr == ']' && open_array {
242 open_array = false;
243 }
244 if chr == '{' {
245 open_bracket += 1;
246 }
247 if chr == '}' {
248 open_bracket -= 1;
249 }
250 if chr == '"' {
251 open_string = !open_string
252 }
253 sub_raw.push(chr);
254 }
255 if !sub_raw.is_empty() {
256 let t = Self::infer_type(&sub_raw);
257 let r = Self::load(t, sub_raw.clone());
258 if r.is_some() {
259 new_vec.push(r.unwrap());
260 }
261 }
262
263 Some(DataType::Array(new_vec))
264 }
265 6 => {
266 let mut d = Document::new();
267 let raw = raw.strip_suffix('}').unwrap().strip_prefix('{').unwrap();
268 let mut key = String::new();
269 let mut key_done = false;
270 let mut open_array = 0;
271 let mut open_string = false;
272 let mut open_bracket = 0;
273 let mut value = String::new();
274 for chr in raw.chars() {
275 if chr == ':' && !key_done {
276 key_done = true;
277 continue;
278 }
279 if key_done {
280 if chr == ',' && open_array == 0 && !open_string && open_bracket == 0 {
281 let t = Self::infer_type(&value);
282 let r = Self::load(t, value.clone());
283 if r.is_some() {
284 d.insert(key.trim().to_string(), r.unwrap());
285 key = String::new();
286 value = String::new();
287 key_done = false;
288 continue;
289 }
290 }
291
292 if chr == '[' {
293 open_array += 1;
294 }
295 if chr == ']' {
296 open_array -= 1;
297 }
298 if chr == '{' {
299 open_bracket += 1;
300 }
301 if chr == '}' {
302 open_bracket -= 1
303 }
304 if chr == '"' {
305 open_string = !open_string
306 }
307
308 value.push(chr);
309 } else {
310 key.push(chr);
311 }
312 }
313 if !key.is_empty() && !value.is_empty() {
314 let t = Self::infer_type(&value);
315 let r = Self::load(t, value.clone());
316 if r.is_some() {
317 d.insert(key.trim().to_string(), r.unwrap());
318 }
319 }
320 Some(DataType::Document(d))
321 }
322 _ => None,
323 }
324 }
325}
326
327impl ToString for DataType {
328 fn to_string(&self) -> String {
329 match self {
330 DataType::Id(id) => id.to_string(),
331 DataType::Text(text) => format!("\"{}\"", text.to_string()),
332 DataType::Number(number) => number.to_string(),
333 DataType::Boolean(boolean) => boolean.to_string(),
334 DataType::Array(array) => {
335 let mut result = String::new();
336 result.push('[');
337 for value in array {
338 result.push_str(&value.to_string());
339 result.push_str(", ");
340 }
341 let mut result = result.strip_suffix(", ").unwrap_or(&result).to_string();
342 result.push(']');
343 result
344 }
345 DataType::Document(document) => {
346 let mut result = String::new();
347 result.push('{');
348 for (key, value) in document {
349 result.push_str(&key);
350 result.push_str(": ");
351 result.push_str(&value.to_string());
352 result.push_str(", ");
353 }
354 result.pop();
355 result.pop();
356 result.push('}');
357
358 result
359 }
360 }
361 }
362}
363
364impl From<Uuid> for DataType {
365 fn from(value: Uuid) -> Self {
366 DataType::Id(value)
367 }
368}
369
370impl From<String> for DataType {
371 fn from(value: String) -> Self {
372 DataType::Text(value)
373 }
374}
375
376impl From<&str> for DataType {
377 fn from(value: &str) -> Self {
378 DataType::Text(value.to_string())
379 }
380}
381
382impl From<f32> for DataType {
383 fn from(value: f32) -> Self {
384 DataType::Number(value)
385 }
386}
387
388impl From<i32> for DataType {
389 fn from(value: i32) -> Self {
390 DataType::Number(value as f32)
391 }
392}
393
394impl From<bool> for DataType {
395 fn from(value: bool) -> Self {
396 DataType::Boolean(value)
397 }
398}
399
400impl From<Vec<DataType>> for DataType {
401 fn from(value: Vec<DataType>) -> Self {
402 DataType::Array(value)
403 }
404}
405
406impl From<Document> for DataType {
407 fn from(value: Document) -> Self {
408 DataType::Document(value)
409 }
410}
411
412impl Clone for DataType {
414 fn clone(&self) -> Self {
415 match self {
416 DataType::Id(id) => DataType::Id(*id),
417 DataType::Text(text) => DataType::Text(text.clone()),
418 DataType::Number(number) => DataType::Number(*number),
419 DataType::Boolean(boolean) => DataType::Boolean(*boolean),
420 DataType::Array(array) => DataType::Array(array.clone()),
421 DataType::Document(document) => DataType::Document(document.clone()),
422 }
423 }
424}
425
426#[cfg(test)]
427mod tests {
428 use super::DataType;
429
430 #[test]
431 fn test_macro() {
432 let dd = d!("Hello");
433 let expected = DataType::from("Hello");
434 assert!(dd == expected);
435 let dd = d!(10);
436 let expected = DataType::from(10);
437 assert!(dd == expected);
438 let dd = d!(["hello", 10]);
439 let expected = DataType::from(vec![d!("hello"), d!(10)]);
440 assert!(dd == expected);
441 }
442}