1#[macro_use]
2extern crate serde;
3extern crate serde_json;
4extern crate uuid;
5
6use serde::Serialize;
7
8use std::str::FromStr;
9
10pub mod node;
11pub mod prelude;
12
13pub type ResultList = Vec<Vec<u8>>;
14pub type ReturnPkg = (
15 Option<[u8; 16]>,
16 Option<String>,
17 Option<Vec<u8>>,
18 Option<ResultList>,
19 Option<Vec<String>>,
20);
21
22#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
23pub enum KeyWord {
24 Unknown,
25 Archive,
26 First,
27 From,
28 Insert,
29 Into,
30 Last,
31 Limit,
32 Select,
33 Top,
34 Update,
35 Where,
36}
37
38impl From<&str> for KeyWord {
39 fn from(s: &str) -> Self {
40 match s.to_lowercase().as_str() {
41 "archive" => KeyWord::Archive,
42 "first" => KeyWord::First,
43 "from" => KeyWord::From,
44 "insert" => KeyWord::Insert,
45 "into" => KeyWord::Into,
46 "last" => KeyWord::Last,
47 "limit" => KeyWord::Limit,
48 "select" => KeyWord::Select,
49 "top" => KeyWord::Top,
50 "update" => KeyWord::Update,
51 "where" => KeyWord::Where,
52 _ => KeyWord::Unknown,
53 }
54 }
55}
56
57impl Into<&str> for KeyWord {
58 fn into(self) -> &'static str {
59 match self {
60 KeyWord::Unknown => "unknown",
61 KeyWord::Archive => "archive",
62 KeyWord::First => "first",
63 KeyWord::From => "from",
64 KeyWord::Insert => "insert",
65 KeyWord::Into => "into",
66 KeyWord::Last => "last",
67 KeyWord::Limit => "limit",
68 KeyWord::Select => "select",
69 KeyWord::Top => "top",
70 KeyWord::Update => "update",
71 KeyWord::Where => "where",
72 }
73 }
74}
75
76#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
96pub struct Command {
97 pub action: Action,
98 pub limit: Option<Limits>,
99 pub ops: Vec<(LogicOp, What)>,
100 pub tag: String,
101 pub what: What,
102}
103
104#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
114pub enum Action {
115 Default,
116 Archive([u8; 16]),
117 Insert(Vec<u8>),
118 Select,
119 Update(([u8; 16], Vec<u8>)),
120}
121
122#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
130pub enum What {
131 Default,
132 Id([u8; 16]),
133 Index(String),
134}
135
136#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
140pub enum LogicOp {
141 Default,
142 And,
143 Or,
144}
145
146#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
150pub enum Limits {
151 Default,
152 Limit(usize),
153 First(usize),
154 Last(usize),
155}
156
157#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
158pub enum Result {
159 Some(ReturnPkg),
160 None,
161}
162
163impl Default for Command {
164 fn default() -> Command {
165 Command {
166 action: Action::Default,
167 limit: None,
168 ops: vec![],
169 tag: "".to_string(),
170 what: What::Default,
171 }
172 }
173}
174
175impl Command {
176 pub fn new() -> Command {
177 Command::default()
178 }
179
180 pub fn parse(cmd: &str) -> std::result::Result<Command, Box<dyn std::error::Error>> {
193 let tmp = cmd.trim().to_string();
194 let split = tmp.split_at(7);
195
196 match split.0.trim().to_lowercase().as_str() {
197 "archive" => parse_archive(split.1),
198 "insert" => parse_insert(split.1),
199 "select" => parse_select(split.1),
200 "update" => parse_update(split.1),
201 _ => Err(From::from(format!(
202 "Invalid command: {} unrecognized.",
203 split.0
204 ))),
205 }
206 }
207
208 pub fn with_action(mut self, action: Action) -> Self {
209 self.action = action;
210 self
211 }
212
213 pub fn with_limit(mut self, limit: Limits) -> Self {
214 self.limit = Some(limit);
215 self
216 }
217
218 pub fn with_what(mut self, what: What) -> Self {
219 self._what(what);
220 self
221 }
222
223 fn _what(&mut self, what: What) {
224 self.what = what;
225 }
226
227 pub fn with_and_what(mut self, what: What) -> Self {
228 self._and_what(what);
229 self
230 }
231
232 fn _and_what(&mut self, what: What) {
233 self.ops.push((LogicOp::And, what));
234 }
235
236 pub fn with_or_what(mut self, what: What) -> Self {
237 self._or_what(what);
238 self
239 }
240
241 fn _or_what(&mut self, what: What) {
242 self.ops.push((LogicOp::Or, what));
243 }
244
245 pub fn with_tag(mut self, tag: &str) -> Self {
246 self._tag(tag);
247 self
248 }
249
250 fn _tag(&mut self, tag: &str) {
251 self.tag = tag.to_string();
252 }
253}
254
255fn parse_archive(_select: &str) -> std::result::Result<Command, Box<dyn std::error::Error>> {
257 unimplemented!()
258}
259
260fn parse_item_arr(stmt: &str) -> std::result::Result<Vec<u8>, Box<dyn std::error::Error>> {
261 match (stmt.find('['), stmt.find(']')) {
262 (Some(start), Some(end)) => {
263 let obj = stmt.get(start..=end).unwrap();
264 match serde_json::from_str(obj) {
265 Ok(item) => Ok(item),
266 _ => Err(From::from("Invalid command.")),
267 }
268 }
269 (_, _) => Err(From::from("Invalid statement termination.")),
270 }
271}
272
273fn parse_insert(stmt: &str) -> std::result::Result<Command, Box<dyn std::error::Error>> {
276 let item_vec = parse_item_arr(stmt)?;
277 let mut item = Command::new().with_action(Action::Insert(item_vec));
278 let tag = parse_tag(stmt).expect("Failed to parse tag.");
279 item._tag(tag.as_str());
280 Ok(item)
281}
282
283fn parse_select(select: &str) -> std::result::Result<Command, Box<dyn std::error::Error>> {
288 let cmd = Command::new().with_action(Action::Select);
289
290 let pattern = (
291 select.find("from"),
292 select.find("where"),
293 select.find("limit"),
294 );
295 match pattern {
296 (Some(_), None, None) => {
297 let tag = parse_tag(select)?;
298 let mut cmd = cmd;
299 cmd._tag(&tag);
300 Ok(cmd)
301 }
302 (Some(_), Some(l_where), None) => {
303 let cmd_tag = parse_tag(select)?;
304 let mut cmd = cmd;
305 cmd._tag(&cmd_tag);
306 parse_where(select, l_where, select.len(), cmd)
307 }
308 (Some(_from), Some(_l_where), Some(_limit)) => {
309 unimplemented!()
312 }
313 (Some(_from), None, Some(_limit)) => unimplemented!(),
314 (None, _, _) => Err(From::from("from part required")),
315 }
316}
317
318fn parse_where(
322 stmt: &str,
323 l_where: usize,
324 stop: usize,
325 cmd: Command,
326) -> std::result::Result<Command, Box<dyn std::error::Error>> {
327 match stmt.find("id") {
328 Some(_) => {
329 let id = parse_id(stmt);
331 if id.is_some() {
332 let id = *uuid::Uuid::from_str(&id.unwrap())?.as_bytes();
333 let mut cmd = cmd;
334 cmd._what(What::Id(id));
335 Ok(cmd)
336 } else {
337 Err(From::from("statement id is required"))
338 }
339 }
340 None => {
341 let l_where = stmt.get((l_where + 5)..stop).unwrap();
343 parse_what(l_where, cmd)
344 }
345 }
346}
347
348fn parse_id(stmt: &str) -> Option<String> {
351 let pattern = (stmt.find("id"), stmt.find("is"));
352 match pattern {
353 (Some(_), Some(is_idx)) => {
354 let tmp = stmt.get(is_idx + 2..stmt.len()).unwrap();
355 let rmv = next_keyword_idx(tmp);
356 if rmv.is_some() {
357 let rmv = rmv.unwrap();
358 Some(stmt.get(0..rmv).unwrap().trim().to_string())
359 } else {
360 Some(tmp.trim().to_string())
361 }
362 }
363 (Some(id_idx), None) => {
364 let tmp = stmt.get(id_idx + 2..stmt.len()).unwrap();
365 let rmv = next_keyword_idx(tmp);
366 if rmv.is_some() {
367 let rmv = rmv.unwrap();
368 Some(stmt.get(0..rmv).unwrap().trim().to_string())
369 } else {
370 Some(tmp.trim().to_string())
371 }
372 }
373 _ => None,
374 }
375}
376
377fn parse_what(
378 stmt: &str,
379 cmd: Command,
380) -> std::result::Result<Command, Box<dyn std::error::Error>> {
381 let mut cmd = cmd;
382 match stmt.find("is") {
383 Some(_is) => {
384 let is: Vec<&str> = stmt.split("is").collect();
385 let mut next_modifier = None;
386 for condition in is {
387 let this_modifier = next_modifier.clone();
388 match (condition.trim().is_empty(), condition.len() > 4) {
389 (true, _) => (), (false, false) => {
391 let what = condition.trim().to_string();
392 match this_modifier {
393 Some(LogicOp::And) => cmd._and_what(What::Index(what)),
394 Some(LogicOp::Or) => cmd._or_what(What::Index(what)),
395 Some(LogicOp::Default) | None => cmd._what(What::Index(what)),
396 }
397 }
398 (false, true) => {
399 let mut what = condition.trim().to_string();
400 let next_op = what.get((what.len() - 3)..what.len()).unwrap();
401 match next_op.trim() {
402 "and" => next_modifier = Some(LogicOp::And),
403 "or" => next_modifier = Some(LogicOp::Or),
404 _ => next_modifier = None,
405 }
406 if next_modifier.is_some() {
407 what = what.get(0..(what.len() - 3)).unwrap().trim().to_string();
408 }
409
410 match this_modifier {
411 Some(LogicOp::And) => cmd._and_what(What::Index(what)),
412 Some(LogicOp::Or) => cmd._or_what(What::Index(what)),
413 Some(LogicOp::Default) | None => cmd._what(What::Index(what)),
414 }
415 }
416 }
417 }
418 }
419 None => {
420 let stmt = stmt.trim().to_string();
421 cmd._what(What::Index(stmt))
422 }
423 }
424 Ok(cmd)
425}
426
427fn parse_tag(stmt: &str) -> std::result::Result<String, Box<dyn std::error::Error>> {
428 let kw_from: &str = KeyWord::From.into();
429 let kw_into: &str = KeyWord::Into.into();
430 let pattern = (stmt.find(kw_from), stmt.find(kw_into));
431 match pattern {
432 (Some(idx), None) | (None, Some(idx)) => {
433 let stmt_minus_kw = stmt
434 .get((idx + 4)..stmt.len())
435 .expect("Split off from failed");
436 let next_key_word = next_keyword_idx(stmt_minus_kw);
437 if next_key_word.is_some() {
438 let next_key_word = next_key_word.unwrap();
439 Ok(stmt_minus_kw
440 .get(0..next_key_word)
441 .expect("Seperate tag from statement failed")
442 .trim()
443 .to_string())
444 } else {
445 Ok(stmt_minus_kw
446 .get(0..stmt_minus_kw.len())
447 .expect("Seperate tag from statement failed")
448 .trim()
449 .to_string())
450 }
451 }
452 _ => Err(From::from("Failed to parse tag out of statement")),
453 }
454}
455
456fn next_keyword_idx(stmt: &str) -> Option<usize> {
457 let mut iter = stmt
458 .split_whitespace()
459 .filter(|&s| KeyWord::from(s) != KeyWord::Unknown);
460 let first = iter.nth(0);
461
462 if first.is_some() {
463 let first = first.unwrap();
464 return Some(stmt.find(first).expect("Shouldn't error"));
465 }
466
467 None
468}
469
470fn parse_update(stmt: &str) -> std::result::Result<Command, Box<dyn std::error::Error>> {
472 let item = parse_item_arr(stmt)?;
473 let id = parse_id(stmt);
474 let tag = parse_tag(stmt)?;
475 if id.is_some() {
476 let id = *uuid::Uuid::from_str(&id.unwrap())?.as_bytes();
477 let mut cmd = Command::new().with_action(Action::Update((id, item)));
478 cmd._tag(tag.as_str());
479 Ok(cmd)
480 } else {
481 Err(From::from("Statement id is required."))
482 }
483}
484
485#[cfg(test)]
486mod tests {
487 use super::*;
488 use std::str::FromStr;
489 use uuid::Uuid;
490
491 #[derive(Serialize, Deserialize, Clone, Debug)]
492 pub struct Test {
493 pub test: String,
494 pub test_int: i32,
495 pub test_lint: i64,
496 pub test_index: usize,
497 pub test_float: f32,
498 pub test_lfloat: f64,
499 pub test_bool: bool,
500 pub test_vec: Vec<u8>,
501 pub test_arr: [u8; 16],
502 }
503
504 impl Default for Test {
505 fn default() -> Self {
506 Test {
507 test: "Test".to_string(),
508 test_int: 0,
509 test_lint: 0,
510 test_index: 0,
511 test_float: 0.1,
512 test_lfloat: 0.22,
513 test_bool: false,
514 test_vec: vec![],
515 test_arr: [0; 16],
516 }
517 }
518 }
519
520 impl Test {
521 #[allow(clippy::neg_multiply, clippy::cast_lossless)]
522 pub fn new<S>(text: S, index: usize) -> Test
523 where
524 S: Into<String>,
525 {
526 let mut test = Test::default();
527 test.test = text.into();
528 test.test_int = (index as i32 * -1) as i32;
529 test.test_lint = (index as i32 * -1) as i64;
530 test.test_float = index as f32;
531 test.test_lfloat = index as f64;
532 test.test_index = index;
533
534 test
535 }
536
537 pub fn get_index(&self) -> usize {
538 self.test_index
539 }
540
541 pub fn serialize(&self) -> String {
542 serde_json::to_string(self).expect("Failed to serialize test data.")
543 }
544 }
545
546 use std::cmp::Ordering;
547 impl std::cmp::Ord for Test {
548 fn cmp(&self, other: &Self) -> Ordering {
549 self.get_index().cmp(&other.get_index())
550 }
551 }
552
553 impl Eq for Test {}
554
555 impl PartialOrd for Test {
556 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
557 Some(self.get_index().cmp(&other.get_index()))
558 }
559 }
560
561 impl PartialEq for Test {
562 fn eq(&self, other: &Self) -> bool {
563 self.get_index() == other.get_index()
564 }
565 }
566
567 #[test]
568 fn parse_update() {
569 let id = "936DA01F9ABD4d9d80C702AF85C822A8";
571 let test = Test::new("Some text", 1).serialize();
572 let test_vec = test.as_bytes().to_vec();
573 let sql_sorta = format!(
574 "update {} from dog where id {}",
575 serde_json::to_string(&test_vec).unwrap(),
576 id
577 );
578 let parse_cmd = Command::parse(sql_sorta.as_str()).expect("Error parsing update command.");
579 let uid = *Uuid::from_str(id).expect("Shouldn't fail").as_bytes();
580 let correct_cmd = Command::new()
581 .with_action(Action::Update((uid, test_vec)))
582 .with_tag("dog");
583 assert_eq!(correct_cmd, parse_cmd);
586 }
587
588 #[test]
589 fn parse_insert() {
590 let mut cmp = Command::new().with_action(Action::Insert(
591 "A dog is a dog is a fish".as_bytes().to_vec(),
592 ));
593 cmp._tag("dog");
594 let tmp = "A dog is a dog is a fish".as_bytes().to_vec();
595 let cmd_string = format!("Insert {} into dog", serde_json::to_string(&tmp).unwrap());
596 match Command::parse(cmd_string.as_str()) {
597 Ok(cmd) => {
598 assert_eq!(cmp, cmd);
599 }
600 Err(_) => assert!(false),
601 }
602 }
603
604 #[test]
605 fn parse_select_and_or() {
606 let mut cmp = Command::new().with_action(Action::Select);
607 cmp._tag("frog");
608 cmp._what(What::Index("duck".into()));
609 cmp._and_what(What::Index("wet".into()));
610 cmp._or_what(What::Index("flower".into()));
611
612 match Command::parse("Select from frog where duck and is wet or is flower") {
613 Ok(cmd) => assert_eq!(cmp, cmd),
614 Err(_) => assert!(false),
615 }
616 }
617
618 #[test]
619 fn parse_select_id() {
620 let cmd = Command::parse(
622 format!("select from tag where id is 936DA01F9ABD4d9d80C702AF85C822A8").as_str(),
623 )
624 .expect("Valid shouldn't fail");
625
626 let mut cmd_cmp = Command::new().with_action(Action::Select);
627 cmd_cmp._tag("tag");
628 cmd_cmp._what(What::Id([
629 147, 109, 160, 31, 154, 189, 77, 157, 128, 199, 2, 175, 133, 200, 34, 168,
630 ]));
631
632 assert_eq!(cmd_cmp, cmd);
633 }
634
635 #[test]
636 fn parse_select() {
637 let cmd = Command::parse("select from tag").expect("Valid shouldn't fail");
639 let mut cmd_cmp = Command::new().with_action(Action::Select);
640 cmd_cmp._tag("tag");
641
642 assert_eq!(cmd_cmp, cmd);
643 }
644
645 #[test]
646 fn parse_select_where() {
647 let cmd = Command::parse("select from tag where duck").expect("Valid shouldn't fail.");
648 let mut cmd_cmp = Command::new().with_action(Action::Select);
649 cmd_cmp._tag("tag");
650 cmd_cmp._what(What::Index("duck".to_string()));
651
652 assert_eq!(cmd_cmp, cmd);
653 }
654}