1use std::{collections::HashMap, fmt::Display, fs::File};
4use std::{io::prelude::*, ops::Deref};
5use std::{io::BufReader, ops::DerefMut};
6
7use crate::ForceUnwrap;
8use serde_json::json;
9
10#[derive(Clone, Debug, PartialEq, PartialOrd)]
12pub enum FQLType {
13 String(String),
15 Float(f64),
17 Int(i64),
19 Null,
21}
22
23impl Into<serde_json::Value> for FQLType {
24 fn into(self) -> serde_json::Value {
25 match self {
26 Self::String(s) => json!(s),
27 Self::Int(s) => json!(s),
28 Self::Float(s) => json!(s),
29 Self::Null => serde_json::Value::Null,
30 }
31 }
32}
33
34impl std::fmt::Display for FQLType {
35 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
36 match self {
37 Self::String(s) => write!(f, "\"{}\"", s),
38 Self::Int(s) => write!(f, "{}", s),
39 Self::Float(s) => write!(f, "{}", s),
40 Self::Null => write!(f, "null"),
41 }
42 }
43}
44
45macro_rules! _impl_from_for_fqltype {
46
47 (int: $($t:ty),*) => {
48 $(
49 impl From<$t> for FQLType {
50 fn from(value: $t) -> Self {
51 Self::Int(value as i64)
52 }
53 }
54 )*
55 };
56 (float: $($t:ty),*) => {
57 $(
58 impl From<$t> for FQLType {
59 fn from(value: $t) -> Self {
60 Self::Float(value as f64)
61 }
62 }
63 )*
64 };
65 (display: $($t:ty),*) => {
66 $(
67 impl From<$t> for FQLType {
68 fn from(value: $t) -> Self {
69
70 if format!("{}", value) == "null" {
71 return Self::Null;
72 }
73
74 if let Ok(v) = value.parse::<i64>() {
75 return Self::Int(v);
76 }
77
78 if let Ok(v) = value.parse::<f64>() {
79 return Self::Float(v);
80 }
81
82 if value.starts_with("\"") && value.ends_with("\"") {
83 return Self::String(value[1..value.len() - 1].to_string());
84 }
85
86 Self::String(value.to_string())
87 }
88 }
89 )*
90 };
91}
92
93_impl_from_for_fqltype!(float: f32, f64);
94_impl_from_for_fqltype!(display: String, &str, &String);
95_impl_from_for_fqltype!(int: i8, u8, i16, u16, i32, u32, i64, u64, isize, usize);
96#[derive(Clone, Debug)]
99pub struct AppData(HashMap<String, FQLType>);
100
101impl AppData {
102 pub fn update(&mut self, key: String, val: FQLType) {
104 self.0.insert(key, val);
105 }
106
107 pub fn inner(self) -> HashMap<String, FQLType> {
109 self.0
110 }
111
112 pub fn serialize(&self) -> HashMap<String, serde_json::Value> {
114 let mut map = HashMap::new();
115 for (k, v) in &self.0 {
116 map.insert(k.to_string(), v.clone().into());
117 }
118 map
119 }
120}
121
122impl From<HashMap<String, FQLType>> for AppData {
123 fn from(data: HashMap<String, FQLType>) -> Self {
124 AppData(data)
125 }
126}
127
128impl AsRef<HashMap<String, FQLType>> for AppData {
129 fn as_ref(&self) -> &HashMap<String, FQLType> {
130 &self.0
131 }
132}
133
134impl Deref for AppData {
135 type Target = HashMap<String, FQLType>;
136
137 fn deref(&self) -> &Self::Target {
138 &self.0
139 }
140}
141
142impl DerefMut for AppData {
143 fn deref_mut(&mut self) -> &mut Self::Target {
144 &mut self.0
145 }
146}
147
148#[derive(Clone, Debug)]
155pub struct App {
156 pub path: Option<String>,
158 pub data: Vec<AppData>,
160 pub keys: Vec<String>,
162 delimiter: String,
164}
165
166impl From<Vec<String>> for App {
167 fn from(lines: Vec<String>) -> Self {
168 let mut index = 0;
169 let mut data = Vec::new();
170 let delimiter = lines[0].trim().to_string();
171 let keys: Vec<String> = lines[1].split(&delimiter).map(|s| s.to_string()).collect();
172
173 for line in &lines[2..] {
174 let mut map = HashMap::new();
175 line.split(&delimiter)
176 .enumerate()
177 .into_iter()
178 .for_each(|(i, s)| {
179 map.insert(keys[i].clone(), FQLType::from(s));
180 map.insert("$index".to_string(), FQLType::from(index));
181 });
182 data.push(AppData::from(map));
183 index += 1;
184 }
185
186 Self {
187 path: None,
188 data,
189 keys,
190 delimiter,
191 }
192 }
193}
194
195impl From<&str> for App {
196 fn from(s: &str) -> Self {
197 App::from(
198 s.split("\n")
199 .map(|s| s.trim().to_string())
200 .filter(|s| s.len() > 0)
201 .collect::<Vec<String>>(),
202 )
203 }
204}
205
206impl From<Vec<AppData>> for App {
207 fn from(data: Vec<AppData>) -> Self {
208 if data.len() == 0 {
209 return Self {
210 path: None,
211 data: Vec::new(),
212 keys: Vec::new(),
213 delimiter: "".to_string(),
214 };
215 }
216 let keys: Vec<String> = data[0].keys().map(|s| s.to_string()).collect();
217 Self {
218 path: None,
219 data,
220 keys,
221 delimiter: "".to_string(),
222 }
223 }
224}
225
226impl From<Vec<&AppData>> for App {
227 fn from(data: Vec<&AppData>) -> Self {
228 if data.len() == 0 {
229 return Self {
230 path: None,
231 data: Vec::new(),
232 keys: Vec::new(),
233 delimiter: "".to_string(),
234 };
235 }
236 let keys: Vec<String> = data[0].keys().map(|s| s.to_string()).collect();
237 let data = data.into_iter().map(|s| s.clone()).collect();
238 Self {
239 path: None,
240 data,
241 keys,
242 delimiter: "".to_string(),
243 }
244 }
245}
246
247impl Into<Vec<Vec<FQLType>>> for App {
248 fn into(self) -> Vec<Vec<FQLType>> {
249 self.data
250 .into_iter()
251 .map(|item| {
252 item.values()
253 .map(|t| t.to_owned())
254 .collect::<Vec<FQLType>>()
255 })
256 .collect()
257 }
258}
259
260impl App {
261 pub fn from_file<T: Display>(path: T) -> std::io::Result<Self> {
263 File::open(format!("{}", path)).and_then(|f| {
264 Ok(Self {
265 path: Some(format!("{}", path)),
266 ..Self::from(
267 BufReader::new(f)
268 .lines()
269 .map(|line| line.force_unwrap().trim().to_string())
270 .collect::<Vec<String>>(),
271 )
272 })
273 })
274 }
275
276 pub fn serialize(&self) -> Vec<HashMap<String, serde_json::Value>> {
278 self.data.iter().map(|s| s.clone().serialize()).collect()
279 }
280
281 pub fn merge_data(&mut self, data: Vec<AppData>) {
282 self.data = data;
283 }
284
285 pub fn save_at<T: Display>(&self, path: T) {
287 let mut file = File::create(format!("{}", path)).unwrap();
288
289 let head = format!("{}\n{}\n", self.delimiter, self.keys.join(&self.delimiter));
290
291 file.write(head.as_bytes()).expect(&format!(
292 "Parse::save_file failed at {} \ncontent: {}",
293 path, head
294 ));
295
296 for data in &self.data {
297 let line = self
298 .keys
299 .iter()
300 .map(|s| format!("{}", data.get(s).force_unwrap()))
301 .collect::<Vec<String>>()
302 .join(&self.delimiter);
303 file.write(line.as_bytes()).expect(&format!(
304 "Parse::save_file failed at {} \ncontent: {}",
305 path, line
306 ));
307 file.write(b"\n").force_unwrap();
308 }
309 }
310
311 pub fn create_data(&self) -> AppData {
313 let mut map = HashMap::new();
314 for key in &self.keys {
315 map.insert(key.to_string(), FQLType::Null);
316 }
317
318 AppData::from(map)
319 }
320
321 pub fn init_data(&self, data: &mut AppData) {
323 data.0.clear();
324 for key in &self.keys {
325 data.0.insert(key.to_string(), FQLType::Null);
326 }
327 }
328
329 pub fn save(&self) {
331 if let Some(path) = &self.path {
332 self.save_at(&path);
333 }
334 }
335}
336
337#[cfg(test)]
338mod test {
339 use crate::*;
340 use app::App;
341
342 #[test]
343 fn test_app_from_file() {
344 let app = App::from_file("E:/web/rust-web/fql_server/uestc/student-info.csv".to_string())
345 .unwrap();
346 println!("{:#?}", app);
347
348 }
350
351 #[test]
352 fn test_app_from() {
353 let mut app = App::from(
354 r"
355 ,
356 year,month,day
357 2020,12,14
358 2019,05,12
359 2018,10,null
360 ",
361 );
362 app.update(0, "day", FQLType::Int(15));
363 app.save_at("examples/save.fql");
364 println!("{:#?}", app);
365 }
366}