1use super::data_type::DataType;
7use crate::utils;
8use std::collections::HashMap;
9
10pub type Document = HashMap<String, DataType>;
11
12
13#[macro_export]
14macro_rules! doc {
15 ( $( $key: expr => $value: expr ),* ) => {
16 {
17 use std::collections::HashMap;
18 let mut map = HashMap::new();
19 $(
20 map.insert($key.to_string(), DataType::from($value));
21 )*
22 DataType::Document(map)
23 }
24 };
25}
26
27pub struct Collection {
28 pub name: String,
29 pub(crate) data: DataType,
30 }
32
33pub trait _KV {
34 fn new(name: &str) -> Self;
35 fn add(&mut self, key: &str, value: DataType) -> &mut Self;
36 fn rm(&mut self, key: &str);
37 fn count(&self) -> usize;
38 fn list(&self) -> HashMap<String, DataType>;
39 fn get(&mut self, key: &str) -> Option<&DataType>;
40 fn dump(&self) -> String;
41 fn load(data: &str) -> Collection;
42}
43
44impl Collection {
46 pub fn new(name: &str) -> Self {
47 Collection {
48 name: name.to_string(),
49 data: DataType::Document(Document::new()),
50 }
52 }
53
54 pub fn add(&mut self, key: &str, value: DataType) -> &mut Self {
55 let _ = self.data.set(key, value);
56 return self;
57 }
58
59 pub fn rm(&mut self, key: &str) {
60 let _ = self.data.remove(key);
61 }
62
63 pub fn count(&self) -> usize {
64 self.data.to_document().len()
65 }
66
67 pub fn list(&self) -> HashMap<String, DataType> {
68 return self.data.to_document().clone();
69 }
70
71 pub fn get(&mut self, key: &str) -> Option<&DataType> {
72 return self.data.get(key);
73 }
74
75 pub fn dump(&self) -> String {
76 let mut result = String::new();
77 result.push_str(format!("[{}]\n", self.name).as_str());
78 for (k, v) in self.data.to_document().iter() {
79 let t = match v.get_type() {
80 "id" => "1",
81 "text" => "2",
82 "number" => "3",
83 "boolean" => "4",
84 "array" => "5",
85 "document" => "6",
86 _ => "7",
87 };
88 let line = format!("{} {} {}\n", t, k, v.to_string());
89 result.push_str(line.as_str());
90 }
91 return result;
92 }
93
94 pub fn load(data: &str) -> Collection {
95 let data_text = data.to_string();
96 let parser = data_text.lines();
97 let name = parser.clone().next();
98 if name.is_none() {
99 panic!("invalid data")
100 }
101 let name = name
102 .unwrap()
103 .strip_suffix(']')
104 .unwrap()
105 .strip_prefix('[')
106 .unwrap();
107 let mut result = Collection::new(name);
108 for line in parser.into_iter() {
109 if line.starts_with('[') {
110 continue;
111 }
112 let line_text = line.to_string();
113 let elements = utils::smart_split(line_text);
114 if elements.len() != 3 {
115 continue;
116 }
117 let raw_t = elements[0].clone();
118 let t = raw_t.parse::<u16>();
119 if t.is_err() {
120 println!("Error parsing: {:?}", t.err());
121 continue;
122 }
123 let t = t.unwrap();
124 let k = elements[1].clone();
125 let raw_v = elements[2].clone();
126 let v = DataType::load(t, raw_v);
127 if v.is_none() {
128 println!("Error parsing: unresolved value");
129 continue;
130 }
131 let v = v.unwrap();
132 result.add(k.as_str(), v);
133 }
134
135 return result;
136 }
137}
138
139#[cfg(test)]
141#[test]
142fn test_collection() {
143 let mut collection = Collection::new("users");
144 collection.add(
145 "John",
146 doc!(
147 "name" => "John",
148 "age" => 25,
149 "isMarried" => false,
150 "birthDate" => "1995-01-01"
151 ),
152 );
153 assert!(collection.get("John").is_some());
154}
155
156#[test]
157fn test_dump() {
158 let header = "[prueba]\n";
159 let kv_name = "2 name \"Juan\"";
160 let kv_surname = "2 surname \"Perez\"";
161 let kv_age = "3 age 15";
162
163 let mut collection = Collection::new("prueba");
164 collection.add("name", DataType::from("Juan"));
165 collection.add("surname", DataType::from("Perez"));
166 collection.add("age", DataType::from(15));
167
168 let dump = collection.dump();
169 println!("{}", dump);
170 assert!(dump.starts_with(header));
171 assert!(dump.contains(kv_name));
172 assert!(dump.contains(kv_surname));
173 assert!(dump.contains(kv_age));
174}
175
176#[test]
177fn test_load() {
178 let dump = "[prueba]\n2 name Juan\n2 surname Perez\n3 age 15\n";
179 let c = Collection::load(dump);
180 assert_eq!(c.name, "prueba");
181}