1use std::collections::HashMap;
2
3use serde::Serialize;
4use serde::de::DeserializeOwned;
5use serde_json;
6
7use crate::node_runner::NodeRunner;
8use crate::node_token::NodeToken;
9
10pub trait Node {
11 fn node_step(&mut self, runner: NodeRunner) -> String;
12}
13
14impl<T> Node for Vec<T> where T: Node + Serialize + DeserializeOwned + Default {
15 fn node_step(&mut self, mut runner: NodeRunner) -> String {
16 match runner.step() {
17 NodeToken::ChainIndex (index) => {
18 let length = self.len();
19 match self.get_mut(index) {
20 Some (item) => item.node_step(runner),
21 None => {
22 return match length {
23 0 => format!("Used index {} on an empty vector", index),
24 1 => format!("Used index {} on a vector of size 1 (try 0)", index),
25 _ => format!("Used index {} on a vector of size {} (try a value between 0-{})", index, length, length-1)
26 }
27 }
28 }
29 }
30 NodeToken::ChainAll => {
31 let mut combined = String::from("|");
32 for item in self {
33 combined.push_str(item.node_step(runner.clone()).as_ref());
34 combined.push('|');
35 }
36 combined
37 }
38 NodeToken::ChainProperty (ref s) if s == "length" => { self.len().node_step(runner) } NodeToken::Get => {
40 serde_json::to_string_pretty(self).unwrap()
41 }
42 NodeToken::Set (value) => {
43 match serde_json::from_str(&value) {
44 Ok(result) => {
45 *self = result;
46 String::from("")
47 }
48 Err(err) => {
49 format!("vector set error: {}", err)
50 }
51 }
52 }
53 NodeToken::InsertIndex (index) => {
54 let max_index = self.len();
55 if index > max_index {
56 format!("Tried to insert at index {} on a vector of size {} (try a value between 0-{})", index, max_index, max_index)
57 }
58 else {
59 self.insert(index, T::default());
60 String::new()
61 }
62 }
63 NodeToken::RemoveIndex (index) => {
64 let max_index = self.len() - 1;
65 if index > max_index {
66 format!("Tried to remove the value at index {} on a vector of size {} (try a value between 0-{})", index, self.len(), max_index)
67 }
68 else {
69 self.remove(index);
70 String::new()
71 }
72 }
73 NodeToken::SetDefault => {
74 *self = vec!();
75 String::new()
76 }
77 NodeToken::Help => {
78 String::from(r#"
79Vector Help
80
81Commands:
82* help - display this help
83* get - display JSON
84* set - set to JSON
85* insert - create a new element
86* remove - remove an element
87* reset - reset to empty vector
88
89Accessors:
90* [index] - access item at index
91* .length - display number of items"#)
92 }
93 action => { format!("vector cannot '{:?}'", action) }
94 }
95 }
96}
97
98impl<T> Node for HashMap<String, T> where T: Node + Serialize + DeserializeOwned + Default {
99 fn node_step(&mut self, mut runner: NodeRunner) -> String {
100 match runner.step() {
101 NodeToken::ChainKey (key) => {
102 let length = self.len();
103 match self.get_mut(&key) {
104 Some (item) => { return item.node_step(runner) }
105 None => { }
106 }
107 match length {
108 0 => {
109 format!("Used key '{}' on an empty map.", key)
110 }
111 _ => {
112 format!("Used key '{}' on a map that does not contain it. Try one of: {}", key, format_keys(self))
113 }
114 }
115 }
116 NodeToken::ChainAll => {
117 let mut combined = String::from("|");
118 let mut pairs: Vec<_> = self.iter_mut().collect();
119 pairs.sort_by_key(|x| x.0);
120 for (_, item) in pairs {
121 combined.push_str(item.node_step(runner.clone()).as_ref());
122 combined.push('|');
123 }
124 combined
125 }
126 NodeToken::GetKeys => {
127 format_keys(self)
128 }
129 NodeToken::ChainProperty (ref s) if s == "length" => { self.len().node_step(runner) } NodeToken::Get => {
131 serde_json::to_string_pretty(self).unwrap()
132 }
133 NodeToken::Set (value) => {
134 match serde_json::from_str(&value) {
135 Ok(result) => {
136 *self = result;
137 String::from("")
138 }
139 Err(err) => {
140 format!("map set error: {}", err)
141 }
142 }
143 }
144 NodeToken::InsertKey (key) => {
145 if self.contains_key(&key) {
146 format!("Tried to insert key '{}' on a map that already contains it. Current keys: {}", key, format_keys(self))
147 }
148 else {
149 self.insert(key, T::default());
150 String::new()
151 }
152 }
153 NodeToken::RemoveKey (key) => {
154 if let None = self.remove(&key) {
155 format!("Tried to remove key '{}' on a map that doesnt contain it. Current keys: {}", key, format_keys(self))
156 }
157 else {
158 String::new()
159 }
160 }
161 NodeToken::SetDefault => {
162 *self = HashMap::new();
163 String::new()
164 }
165 NodeToken::Help => {
166 String::from(r#"
167Map Help
168
169Commands:
170* help - display this help
171* get - display JSON
172* getkeys - display keys
173* set - set to JSON
174* insert - create a new element
175* remove - remove an element
176* reset - reset to empty map
177
178Accessors:
179* [key] - access item at the string key
180* .length - display number of items"#)
181 }
182 action => { format!("map cannot '{:?}'", action) }
183 }
184 }
185}
186
187fn format_keys<T>(map: &HashMap<String, T>) -> String {
188 let mut key_list: Vec<String> = map.keys().map(|x| format!("'{}'", x)).collect();
189 key_list.sort();
190 key_list.join(", ")
191}
192
193macro_rules! tuple_node {
194 ( $( $indexes:tt $types:ident ),* ) => {
195 impl <$( $types ),*> Node for ($( $types, )*) where $( $types: Node + Serialize + DeserializeOwned),* {
196 fn node_step(&mut self, mut runner: NodeRunner) -> String {
197 let name = stringify!{ ($( $types, )*) };
198 match runner.step() {
199 NodeToken::ChainIndex (index) => {
200 match index {
201 $(
202 $indexes => self.$indexes.node_step(runner),
203 )*
204 _ => format!("Used index {} on a {}", index, name)
205 }
206 }
207 NodeToken::ChainAll => {
208 let mut combined = String::from("|");
209 $(
210 combined.push_str(self.$indexes.node_step(runner.clone()).as_ref());
211 combined.push('|');
212 )*
213 combined
214 }
215 NodeToken::Get => {
216 serde_json::to_string_pretty(self).unwrap()
217 }
218 NodeToken::Set (value) => {
219 match serde_json::from_str(&value) {
220 Ok (result) => {
221 *self = result;
222 String::from("")
223 }
224 Err (err) => {
225 format!("{} set error: {}", name, err)
226 }
227 }
228 }
229 NodeToken::Help => {
230 String::from(r#"
231Tuple Help
232
233Commands:
234* help - display this help
235* get - display JSON
236* set - set to JSON
237
238Accessors:
239* [index] - access item at index"#)
240 }
241 action => { format!("{} cannot '{:?}'", name, action) }
242 }
243 }
244 }
245 }
246}
247
248tuple_node!(0 T0);
249tuple_node!(0 T0, 1 T1);
250tuple_node!(0 T0, 1 T1, 2 T2);
251tuple_node!(0 T0, 1 T1, 2 T2, 3 T3);
252tuple_node!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4);
253tuple_node!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5);
254tuple_node!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6);
255tuple_node!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7);
256tuple_node!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8);
257tuple_node!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9);
258tuple_node!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9, 10 T10);
259tuple_node!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9, 10 T10, 11 T11);
260tuple_node!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9, 10 T10, 11 T11, 12 T12);
261tuple_node!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9, 10 T10, 11 T11, 12 T12, 13 T13);
262tuple_node!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9, 10 T10, 11 T11, 12 T12, 13 T13, 14 T14);
263tuple_node!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9, 10 T10, 11 T11, 12 T12, 13 T13, 14 T14, 15 T15);
264
265macro_rules! array_node {
266 ( $length:expr ) => {
267 impl<T> Node for [T; $length] where T: Node + Serialize + DeserializeOwned {
268 fn node_step(&mut self, mut runner: NodeRunner) -> String {
269 let length = stringify!{ $length };
270 match runner.step() {
271 NodeToken::ChainIndex (index) => {
272 #[allow(unused_comparisons)] if index < $length {
274 self[index].node_step(runner)
275 } else {
276 format!("Used index {} on an array of length {}", index, length)
277 }
278 }
279 NodeToken::ChainAll => {
280 let mut combined = String::from("|");
281 for i in 0..$length {
282 combined.push_str(self[i].node_step(runner.clone()).as_ref());
283 combined.push('|');
284 }
285 combined
286 }
287 NodeToken::Get => {
288 serde_json::to_string_pretty(self).unwrap()
289 }
290 NodeToken::Set (value) => {
291 match serde_json::from_str(&value) {
292 Ok (result) => {
293 *self = result;
294 String::from("")
295 }
296 Err (err) => {
297 format!("array set error: {}", err)
298 }
299 }
300 }
301 NodeToken::Help => {
302 String::from(r#"
303Array Help
304
305Commands:
306* help - display this help
307* get - display JSON
308* set - set to JSON
309
310Accessors:
311* [index] - access item at index"#)
312 }
313 action => { format!("array cannot '{:?}'", action) }
314 }
315 }
316 }
317 }
318}
319
320array_node!(0);
321array_node!(1);
322array_node!(2);
323array_node!(3);
324array_node!(4);
325array_node!(5);
326array_node!(6);
327array_node!(7);
328array_node!(8);
329array_node!(9);
330array_node!(10);
331array_node!(11);
332array_node!(12);
333array_node!(13);
334array_node!(14);
335array_node!(15);
336array_node!(16);
337
338impl Node for bool {
339 fn node_step(&mut self, mut runner: NodeRunner) -> String {
340 match runner.step() {
341 NodeToken::Get => { if *self { String::from("true") } else { String::from("false") } }
342 NodeToken::Set (value) => { *self = value.as_str() == "true"; String::from("") }
343 NodeToken::Help => {
344 String::from(r#"
345Bool Help
346
347Valid values: true or false
348
349Commands:
350* help - display this help
351* get - display value
352* set - set to value"#)
353 }
354 action => { format!("bool cannot '{:?}'", action) }
355 }
356 }
357}
358
359impl Node for String {
360 fn node_step(&mut self, mut runner: NodeRunner) -> String {
361 match runner.step() {
362 NodeToken::Get => { (*self).clone() }
363 NodeToken::Set (value) => { *self = value; String::from("") }
364 NodeToken::CopyFrom => {
365 let copy = Some (self.clone());
366 unsafe {
367 STRING_COPY = copy;
368 }
369 String::new()
370 }
371 NodeToken::PasteTo => {
372 let paste = unsafe { STRING_COPY.clone() };
373 match paste {
374 Some (value) => {
375 *self = value;
376 String::new()
377 }
378 None => {
379 String::from("String has not been copied")
380 }
381 }
382 }
383 NodeToken::Help => {
384 String::from(r#"
385String Help
386
387Valid values: Anything
388
389Commands:
390* help - display this help
391* copy - copy this value
392* paste - paste the copied value here
393* get - display value
394* set - set to value"#)
395 }
396 action => { format!("String cannot '{:?}'", action) }
397 }
398 }
399}
400
401static mut STRING_COPY: Option<String> = None;
402
403impl<T> Node for Option<T> where T: Node + Serialize + DeserializeOwned + Default {
404 fn node_step(&mut self, mut runner: NodeRunner) -> String {
405 match runner.step() {
406 NodeToken::ChainProperty (ref s) if s == "value" => {
407 if let &mut Some(ref mut value) = self {
408 value.node_step(runner)
409 }
410 else {
411 String::from("Option contains no value")
412 }
413 }
414 NodeToken::Get => {
415 serde_json::to_string_pretty(self).unwrap()
416 }
417 NodeToken::Set (value) => {
418 match serde_json::from_str(&value) {
419 Ok(result) => {
420 *self = result;
421 String::from("")
422 }
423 Err(err) => {
424 format!("Option set error: {}", err)
425 }
426 }
427 }
428 NodeToken::Insert => {
429 *self = Some(T::default());
430 String::new()
431 }
432 NodeToken::Remove => {
433 *self = None;
434 String::new()
435 }
436 NodeToken::SetDefault => {
437 *self = None;
438 String::new()
439 }
440 NodeToken::Help => {
441 String::from(r#"
442Option Help
443
444Commands:
445* help - display this help
446* get - display JSON
447* set - set to JSON
448* insert - set to a value
449* remove - remove value
450* reset - remove value
451
452Accessors:
453* .value - the stored value"#)
454 }
455 action => { format!("Option cannot '{:?}'", action) }
456 }
457 }
458}
459
460macro_rules! int_node {
461 ($e:ty, $valid_values:tt) => {
462 impl Node for $e {
463 fn node_step(&mut self, mut runner: NodeRunner) -> String {
464 match runner.step() {
465 NodeToken::Get => { (*self).to_string() }
466 NodeToken::Set (value) => {
467 match value.parse() {
468 Ok (value) => {
469 *self = value;
470 String::from("")
471 }
472 Err(_) => {
473 format!("Invalid value for {} (needs to be: {})", stringify! { $e }, $valid_values)
474 }
475 }
476 }
477 NodeToken::Help => {
478 format!(r#"
479{} Help
480
481Valid values: {}
482
483Commands:
484* help - display this help
485* copy - copy this value
486* paste - paste the copied value here
487* get - display value
488* set $NUMBER - set to $NUMBER
489* add $NUMBER - adds $NUMBER to this number
490* subtract $NUMBER - subtracts $NUMBER from this number
491* multiply $NUMBER - multiply this number with $NUMBER
492* divide $NUMBER - divide this number by $NUMBER"#,
493 stringify! { $e },
494 $valid_values
495 )
496 }
497 NodeToken::CopyFrom => {
498 let num_copy = match stringify! { $e } {
499 "f32" | "f64" => NumStore::Float (*self as f64),
500 _ => NumStore::Int (*self as u64)
501 };
502 unsafe {
503 NUM_COPY = num_copy;
504 }
505 String::from("")
506 }
507 NodeToken::PasteTo => {
508 let num_copy = unsafe { NUM_COPY.clone() };
509 match num_copy {
510 NumStore::Int (value) => {
511 *self = value as $e;
512 String::from("")
513 }
514 NumStore::Float (value) => {
515 *self = value as $e;
516 String::from("")
517 }
518 NumStore::None => {
519 String::from("A number has not been copied")
520 }
521 }
522 }
523 NodeToken::Custom (action, args) => {
524 match action.as_ref() {
525 "add" => {
526 if let Some(arg0) = args.get(0) {
527 if let Ok(number) = arg0.parse() {
528 *self = (*self).saturating_add(number);
529 String::from("")
530 } else {
531 format!("Invalid value for {} (needs to be: {})", stringify! { $e }, $valid_values)
532 }
533 } else {
534 format!("No value for {} (needs to be: {})", stringify! { $e }, $valid_values)
535 }
536 }
537 "subtract" => {
538 if let Some(arg0) = args.get(0) {
539 if let Ok(number) = arg0.parse() {
540 *self = (*self).saturating_sub(number);
541 String::from("")
542 } else {
543 format!("Invalid value for {} (needs to be: {})", stringify! { $e }, $valid_values)
544 }
545 } else {
546 format!("No value for {} (needs to be: {})", stringify! { $e }, $valid_values)
547 }
548 }
549 "multiply" => {
550 if let Some(arg0) = args.get(0) {
551 if let Ok(number) = arg0.parse() {
552 *self = (*self).saturating_mul(number);
553 String::from("")
554 } else {
555 format!("Invalid value for {} (needs to be: {})", stringify! { $e }, $valid_values)
556 }
557 } else {
558 format!("No value for {} (needs to be: {})", stringify! { $e }, $valid_values)
559 }
560 }
561 "divide" => {
562 if let Some(arg0) = args.get(0) {
563 if let Ok(number) = arg0.parse() {
564 if let Some(number) = (*self).checked_div(number) {
565 *self = number;
566 String::from("")
567 } else {
568 format!("Invalid value for {} (needs to be: {}, excluding 0)", stringify! { $e }, $valid_values)
569 }
570 } else {
571 format!("Invalid value for {} (needs to be: {}, excluding 0)", stringify! { $e }, $valid_values)
572 }
573 } else {
574 format!("No value for {} (needs to be: {})", stringify! { $e }, $valid_values)
575 }
576 }
577 _ => {
578 format!("{} cannot '{}'", stringify! { $e }, action)
579 }
580 }
581 }
582 action => { format!("{} cannot '{:?}'", stringify! { $e }, action) }
583 }
584 }
585 }
586 }
587}
588
589macro_rules! float_node {
590 ($e:ty, $valid_values:tt) => {
591 impl Node for $e {
592 fn node_step(&mut self, mut runner: NodeRunner) -> String {
593 match runner.step() {
594 NodeToken::Get => { (*self).to_string() }
595 NodeToken::Set (value) => {
596 match value.parse() {
597 Ok (value) => {
598 *self = value;
599 String::from("")
600 }
601 Err(_) => {
602 format!("Invalid value for {} (needs to be: {})", stringify! { $e }, $valid_values)
603 }
604 }
605 }
606 NodeToken::Help => {
607 format!(r#"
608{} Help
609
610Valid values: {}
611
612Commands:
613* help - display this help
614* copy - copy this value
615* paste - paste the copied value here
616* get - display value
617* set $NUMBER - set to $NUMBER
618* add $NUMBER - adds $NUMBER to this number
619* subtract $NUMBER - subtracts $NUMBER from this number
620* multiply $NUMBER - multiply this number with $NUMBER
621* divide $NUMBER - divide this number by $NUMBER"#,
622 stringify! { $e },
623 $valid_values
624 )
625 }
626 NodeToken::CopyFrom => {
627 let num_copy = match stringify! { $e } {
628 "f32" | "f64" => NumStore::Float (*self as f64),
629 _ => NumStore::Int (*self as u64)
630 };
631 unsafe {
632 NUM_COPY = num_copy;
633 }
634 String::from("")
635 }
636 NodeToken::PasteTo => {
637 let num_copy = unsafe { NUM_COPY.clone() };
638 match num_copy {
639 NumStore::Int (value) => {
640 *self = value as $e;
641 String::from("")
642 }
643 NumStore::Float (value) => {
644 *self = value as $e;
645 String::from("")
646 }
647 NumStore::None => {
648 String::from("A number has not been copied")
649 }
650 }
651 }
652 NodeToken::Custom (action, args) => {
653 match action.as_ref() {
654 "add" => {
655 if let Some(arg0) = args.get(0) {
656 if let Ok(number) = arg0.parse::<$e>() {
657 *self += number;
658 String::from("")
659 } else {
660 format!("Invalid value for {} (needs to be: {})", stringify! { $e }, $valid_values)
661 }
662 } else {
663 format!("No value for {} (needs to be: {})", stringify! { $e }, $valid_values)
664 }
665 }
666 "subtract" => {
667 if let Some(arg0) = args.get(0) {
668 if let Ok(number) = arg0.parse::<$e>() {
669 *self -= number;
670 String::from("")
671 } else {
672 format!("Invalid value for {} (needs to be: {})", stringify! { $e }, $valid_values)
673 }
674 } else {
675 format!("No value for {} (needs to be: {})", stringify! { $e }, $valid_values)
676 }
677 }
678 "multiply" => {
679 if let Some(arg0) = args.get(0) {
680 if let Ok(number) = arg0.parse::<$e>() {
681 *self *= number;
682 String::from("")
683 } else {
684 format!("Invalid value for {} (needs to be: {})", stringify! { $e }, $valid_values)
685 }
686 } else {
687 format!("No value for {} (needs to be: {})", stringify! { $e }, $valid_values)
688 }
689 }
690 "divide" => {
691 if let Some(arg0) = args.get(0) {
692 if let Ok(number) = arg0.parse::<$e>() {
693 *self /= number;
694 String::from("")
695 } else {
696 format!("Invalid value for {} (needs to be: {})", stringify! { $e }, $valid_values)
697 }
698 } else {
699 format!("No value for {} (needs to be: {})", stringify! { $e }, $valid_values)
700 }
701 }
702 _ => {
703 format!("{} cannot '{}'", stringify! { $e }, action)
704 }
705 }
706 }
707 action => { format!("{} cannot '{:?}'", stringify! { $e }, action) }
708 }
709 }
710 }
711 }
712}
713
714#[derive(Clone)]
715enum NumStore {
716 Int (u64),
717 Float (f64),
718 None,
719}
720
721static mut NUM_COPY: NumStore = NumStore::None;
722
723int_node!(i64, "A number from –9,223,372,036,854,775,808 to 9,223,372,036,854,775,807");
724int_node!(u64, "A number from 0 to 18,446,744,073,709,551,615");
725int_node!(i32, "A number from –2,147,483,648 to 2,147,483,647");
726int_node!(u32, "A number from 0 to 4,294,967,295");
727int_node!(i16, "A number from –32,768 to –32,767");
728int_node!(u16, "A number from 0 to 65,535");
729int_node!(i8, "A number from -128 to 127");
730int_node!(u8, "A number from 0 to 255");
731int_node!(isize, "A number from –9,223,372,036,854,775,808 to 9,223,372,036,854,775,807");
732int_node!(usize, "A number from 0 to 18,446,744,073,709,551,615");
733
734float_node!(f32, "A number with a decimal point");
736float_node!(f64, "A higher precision number with a decimal point");