1use std::rc::Rc;
80
81#[derive(Debug, Clone, PartialEq)]
82pub enum Tree<T: Clone> {
86 Item(T),
88 Section(Vec<Tree<T>>),
90}
91
92#[derive(Debug, Clone, PartialEq)]
93pub enum Path<T: Clone> {
99 Top,
101 Node {
103 left: Vec<Tree<T>>,
105 right: Vec<Tree<T>>,
107 path: Rc<Path<T>>,
109 },
110}
111
112#[derive(Debug, PartialEq, Clone)]
113pub struct Location<T: Clone> {
118 pub cursor: Tree<T>,
120 pub path: Rc<Path<T>>,
122}
123
124impl<T: Clone> Location<T> {
125 pub fn new(tree: Tree<T>) -> Self {
135 Self {
136 cursor: tree.clone(),
137 path: Path::Node {
138 left: vec![],
139 right: vec![tree.clone()],
140 path: Rc::new(Path::Top),
141 }
142 .into(),
143 }
144 }
145
146 pub fn go_left(self) -> Option<Self> {
153 match self.path.as_ref() {
154 Path::Top => None,
155 Path::Node { left, right, path } => left.split_first().map(|(first, rest)| Self {
156 cursor: first.clone(),
157 path: Path::Node {
158 left: rest.to_vec(),
159 path: path.clone(),
160 right: vec![self.cursor].into_iter().chain(right.clone()).collect(),
161 }
162 .into(),
163 }),
164 }
165 }
166
167 pub fn go_right(self) -> Option<Self> {
174 match self.path.as_ref() {
175 Path::Top => None,
176 Path::Node { left, right, path } => right.split_first().map(|(first, rest)| Self {
177 cursor: first.clone(),
178 path: Path::Node {
179 left: vec![self.cursor].into_iter().chain(left.clone()).collect(),
180 right: rest.to_vec(),
181 path: path.clone(),
182 }
183 .into(),
184 }),
185 }
186 }
187
188 pub fn go_up(self) -> Option<Self> {
195 match self.path.as_ref() {
196 Path::Top => None,
197 Path::Node { left, right, path } => {
198 let left = left.iter().rev().cloned().collect::<Vec<Tree<T>>>();
199 Self {
200 path: path.clone(),
201 cursor: Tree::Section(
202 [left, vec![self.cursor], right.clone()]
203 .iter()
204 .flatten()
205 .cloned()
206 .collect::<Vec<Tree<T>>>(),
207 ),
208 }
209 .into()
210 }
211 }
212 }
213
214 pub fn go_down(self) -> Option<Self> {
221 match self.cursor {
222 Tree::Item(_) => None,
223 Tree::Section(trees) => trees.split_first().map(|(first, rest)| Self {
224 cursor: first.clone(),
225 path: Path::Node {
226 left: vec![],
227 right: rest.into(),
228 path: self.path,
229 }
230 .into(),
231 }),
232 }
233 }
234
235 pub fn get_nth(self, n: usize) -> Option<Self> {
248 match n {
249 0 => self.go_down(),
250 n => self.get_nth(n - 1).and_then(Location::go_right),
251 }
252 }
253
254 pub fn change(self, tree: Tree<T>) -> Self {
264 Self {
265 cursor: tree,
266 path: self.path,
267 }
268 }
269
270 pub fn insert_right(self, tree: Tree<T>) -> Option<Self> {
281 match self.path.as_ref() {
282 Path::Top => None,
283 Path::Node { left, right, path } => Self {
284 cursor: self.cursor.clone(),
285 path: Path::Node {
286 left: left.clone(),
287 path: path.clone(),
288 right: vec![tree].into_iter().chain(right.clone()).collect(),
289 }
290 .into(),
291 }
292 .into(),
293 }
294 }
295
296 pub fn insert_left(self, tree: Tree<T>) -> Option<Self> {
307 match self.path.as_ref() {
308 Path::Top => None,
309 Path::Node { left, right, path } => Self {
310 cursor: self.cursor.clone(),
311 path: Path::Node {
312 left: vec![tree].into_iter().chain(left.clone()).collect(),
313 right: right.to_vec(),
314 path: path.clone(),
315 }
316 .into(),
317 }
318 .into(),
319 }
320 }
321
322 pub fn insert_down(self, tree: Tree<T>) -> Option<Self> {
333 match self.cursor {
334 Tree::Item(_) => None,
335 Tree::Section(children) => Some(Self {
336 cursor: tree,
337 path: Path::Node {
338 left: vec![],
339 right: children,
340 path: self.path,
341 }
342 .into(),
343 }),
344 }
345 }
346
347 pub fn delete(self) -> Option<Self> {
354 match self.path.as_ref() {
355 Path::Top => None,
356 Path::Node { left, right, path } => {
357 let left = left.as_slice();
358 let right = right.as_slice();
359
360 let result = match (left, path, right) {
361 (left, path, [first_right, rest_right @ ..]) => Self {
363 cursor: first_right.clone(),
364 path: crate::Path::Node {
365 left: left.to_vec(),
366 right: rest_right.to_vec(),
367 path: path.clone(),
368 }
369 .into(),
370 },
371
372 ([first_left, rest_left @ ..], path, &[]) => Self {
374 cursor: first_left.clone(),
375 path: crate::Path::Node {
376 left: rest_left.to_vec(),
377 right: vec![],
378 path: path.clone(),
379 }
380 .into(),
381 },
382 ([], path, []) => Self {
384 cursor: Tree::Section(vec![]),
385 path: path.clone(),
386 },
387 };
388
389 result.into()
390 }
391 }
392 }
393}
394
395#[cfg(test)]
396mod test {
397
398 use std::rc::Rc;
399
400 use crate::{Location, Path, Tree};
401
402 #[test]
403 fn test_new() {
404 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
405
406 let location = Location::new(tree.clone());
407
408 assert_eq!(
409 location,
410 Location {
411 cursor: tree.clone(),
412 path: Path::Node {
413 left: vec![],
414 right: vec![tree],
415 path: Rc::new(Path::Top),
416 }
417 .into(),
418 }
419 );
420 }
421
422 #[test]
423 fn test_for_readme() {
424 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
425
426 let location = Location::new(tree);
427
428 let location = location.go_down().unwrap();
429 assert_eq!(location.cursor, Tree::Item("a"));
430
431 let location = location.go_right().unwrap();
432 assert_eq!(location.cursor, Tree::Item("+"));
433
434 let location = location.go_left().unwrap();
435 assert_eq!(location.cursor, Tree::Item("a"));
436
437 let location = location.insert_right(Tree::Item(".")).unwrap();
438 assert_eq!(
439 location,
440 Location {
441 cursor: Tree::Item("a"),
442 path: Path::Node {
443 left: vec![],
444 right: vec![Tree::Item("."), Tree::Item("+"), Tree::Item("b")],
445 path: Path::Node {
446 left: vec![],
447 right: vec![Tree::Section(vec![
448 Tree::Item("a"),
449 Tree::Item("+"),
450 Tree::Item("b")
451 ])],
452 path: Path::Top.into()
453 }
454 .into()
455 }
456 .into()
457 }
458 .into()
459 );
460 }
461
462 #[test]
463 fn test_go_left_none() {
464 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
465
466 let location = Location {
467 path: Path::Top.into(),
468 cursor: tree,
469 };
470
471 assert_eq!(location.clone().go_left(), None);
472 }
473
474 #[test]
475 fn test_go_left() {
476 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
477
478 let result = Location {
479 path: Path::Node {
480 left: vec![Tree::Item("a")],
481 right: vec![Tree::Item("b")],
482 path: Path::Node {
483 left: vec![],
484 right: vec![tree.clone()],
485 path: Path::Top.into(),
486 }
487 .into(),
488 }
489 .into(),
490 cursor: Tree::Item("+"),
491 }
492 .go_left();
493
494 let expect = Some(Location {
495 path: Path::Node {
496 left: vec![],
497 right: vec![Tree::Item("+"), Tree::Item("b")],
498 path: Path::Node {
499 left: vec![],
500 right: vec![tree],
501 path: Path::Top.into(),
502 }
503 .into(),
504 }
505 .into(),
506 cursor: Tree::Item("a"),
507 });
508
509 assert_eq!(result, expect,);
510 }
511
512 #[test]
513 fn test_go_right() {
514 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
515
516 let result = Location {
517 path: Path::Node {
518 left: vec![Tree::Item("a")],
519 right: vec![Tree::Item("b")],
520 path: Path::Node {
521 left: vec![],
522 right: vec![tree.clone()],
523 path: Path::Top.into(),
524 }
525 .into(),
526 }
527 .into(),
528 cursor: Tree::Item("+"),
529 }
530 .go_right();
531
532 let expect = Some(Location {
533 path: Path::Node {
534 right: vec![],
535 left: vec![Tree::Item("+"), Tree::Item("a")],
536 path: Path::Node {
537 left: vec![],
538 right: vec![tree],
539 path: Path::Top.into(),
540 }
541 .into(),
542 }
543 .into(),
544 cursor: Tree::Item("b"),
545 });
546
547 assert_eq!(result, expect);
548 }
549
550 #[test]
551 fn test_go_right_none() {
552 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
553
554 let location = Location {
555 path: Path::Top.into(),
556 cursor: tree,
557 };
558
559 assert_eq!(location.clone().go_right(), None);
560 }
561
562 #[test]
563 fn test_go_up_none() {
564 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
565
566 let location = Location {
567 path: Path::Top.into(),
568 cursor: tree,
569 };
570
571 assert_eq!(location.clone().go_up(), None);
572 }
573
574 #[test]
575 fn test_go_up() {
576 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
577
578 let location = Location {
579 path: Path::Node {
580 left: vec![],
581 right: vec![Tree::Item("+"), Tree::Item("b")],
582 path: Path::Top.into(),
583 }
584 .into(),
585 cursor: Tree::Item("a"),
586 }
587 .go_up();
588
589 assert_eq!(
590 location,
591 Some(Location {
592 cursor: tree.clone(),
593 path: Path::Top.into(),
594 })
595 );
596 }
597
598 #[test]
599 fn test_go_down_none() {
600 let tree = Tree::Item("a");
601
602 let location = Location {
603 path: Path::Top.into(),
604 cursor: tree,
605 };
606
607 assert_eq!(location.go_down(), None);
608 }
609
610 #[test]
611 fn test_go_down() {
612 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
613
614 let location = Location {
615 path: Path::Top.into(),
616 cursor: tree,
617 };
618
619 assert_eq!(
620 location.go_down(),
621 Some(Location {
622 cursor: Tree::Item("a"),
623 path: Path::Node {
624 left: [].into(),
625 right: [Tree::Item("+"), Tree::Item("b")].into(),
626 path: crate::Path::Top.into(),
627 }
628 .into()
629 })
630 );
631 }
632
633 #[test]
634 fn test_get_nth_0() {
635 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
636
637 let location = Location {
638 path: Path::Top.into(),
639 cursor: tree,
640 };
641
642 assert_eq!(
643 location.get_nth(0),
644 Some(Location {
645 cursor: Tree::Item("a"),
646 path: Path::Node {
647 left: [].into(),
648 right: [Tree::Item("+"), Tree::Item("b")].into(),
649 path: crate::Path::Top.into(),
650 }
651 .into()
652 })
653 );
654 }
655
656 #[test]
657 fn test_get_nth_1() {
658 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
659
660 let location = Location {
661 path: Path::Top.into(),
662 cursor: tree,
663 };
664
665 assert_eq!(
666 location.get_nth(1),
667 Some(Location {
668 cursor: Tree::Item("+"),
669 path: Path::Node {
670 left: [Tree::Item("a")].into(),
671 right: [Tree::Item("b")].into(),
672 path: crate::Path::Top.into(),
673 }
674 .into()
675 })
676 );
677 }
678
679 #[test]
680 fn test_get_nth_2() {
681 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
682
683 let location = Location {
684 path: Path::Top.into(),
685 cursor: tree,
686 };
687
688 assert_eq!(
689 location.get_nth(2),
690 Some(Location {
691 cursor: Tree::Item("b"),
692 path: Path::Node {
693 left: [Tree::Item("+"), Tree::Item("a")].into(),
694 right: [].into(),
695 path: crate::Path::Top.into(),
696 }
697 .into()
698 })
699 );
700 }
701
702 #[test]
703 fn test_get_nth_out_of_bounds() {
704 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
705
706 let location = Location {
707 path: Path::Top.into(),
708 cursor: tree,
709 };
710
711 assert_eq!(location.get_nth(3), None);
712 }
713
714 #[test]
715 fn test_change() {
716 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
717
718 let location = Location {
719 path: Path::Top.into(),
720 cursor: tree,
721 };
722
723 let new_tree = Tree::Item("z");
724
725 assert_eq!(
726 location.change(new_tree.clone()),
727 Location {
728 cursor: new_tree,
729 path: Path::Top.into(),
730 }
731 );
732 }
733
734 #[test]
735 fn test_change_after_go_left() {
736 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
737
738 let location = Location {
739 path: Path::Top.into(),
740 cursor: tree,
741 };
742
743 let new_tree = Tree::Item("-");
744
745 let updated_location = location
746 .go_down()
747 .and_then(Location::go_right)
748 .map(|loc| loc.change(new_tree.clone()));
749
750 assert_eq!(
751 updated_location,
752 Some(Location {
753 cursor: Tree::Item("-"),
754 path: Path::Node {
755 left: [Tree::Item("a")].into(),
756 right: [Tree::Item("b")].into(),
757 path: crate::Path::Top.into(),
758 }
759 .into()
760 })
761 );
762 }
763
764 #[test]
765 fn test_insert_left() {
766 let result = Location {
767 path: Path::Node {
768 left: vec![],
769 right: vec![Tree::Item("+"), Tree::Item("b")],
770 path: Path::Top.into(),
771 }
772 .into(),
773 cursor: Tree::Item("a"),
774 }
775 .insert_left(Tree::Item("."));
776
777 let expect = Location {
778 path: Path::Node {
779 left: vec![Tree::Item(".")],
780 right: vec![Tree::Item("+"), Tree::Item("b")],
781 path: Path::Top.into(),
782 }
783 .into(),
784 cursor: Tree::Item("a"),
785 }
786 .into();
787
788 assert_eq!(result, expect);
789 }
790
791 #[test]
792 fn test_insert_left_none() {
793 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
794
795 let location = Location {
796 path: Path::Top.into(),
797 cursor: tree,
798 };
799
800 let new_tree = Tree::Item("-");
801
802 assert!(location.insert_left(new_tree).is_none());
803 }
804
805 #[test]
806 fn test_insert_right_none() {
807 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
808
809 let location = Location {
810 path: Path::Top.into(),
811 cursor: tree,
812 };
813
814 let new_tree = Tree::Item("-");
815
816 assert!(location.insert_right(new_tree).is_none());
817 }
818
819 #[test]
820 fn test_insert_right() {
821 let result = Location {
822 path: Path::Node {
823 left: vec![],
824 right: vec![Tree::Item("+"), Tree::Item("b")],
825 path: Path::Top.into(),
826 }
827 .into(),
828 cursor: Tree::Item("a"),
829 }
830 .insert_right(Tree::Item("."));
831
832 let expect = Location {
833 path: Path::Node {
834 left: vec![],
835 right: vec![Tree::Item("."), Tree::Item("+"), Tree::Item("b")],
836 path: Path::Top.into(),
837 }
838 .into(),
839 cursor: Tree::Item("a"),
840 }
841 .into();
842
843 assert_eq!(result, expect);
844 }
845
846 #[test]
847 fn test_insert_down() {
848 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
849
850 let location = Location {
851 path: Path::Top.into(),
852 cursor: tree,
853 };
854
855 let new_tree = Tree::Item("-");
856 let updated_location = location.insert_down(new_tree);
857
858 assert_eq!(
859 updated_location,
860 Some(Location {
861 cursor: Tree::Item("-"),
862 path: Path::Node {
863 left: [].into(),
864 right: vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")],
865 path: crate::Path::Top.into(),
866 }
867 .into()
868 })
869 );
870 }
871
872 #[test]
873 fn test_insert_down_none() {
874 let location = Location {
875 path: Path::Node {
876 left: vec![Tree::Item("a")],
877 right: vec![Tree::Item("b")],
878 path: Path::Top.into(),
879 }
880 .into(),
881 cursor: Tree::Item("+"),
882 };
883
884 let new_tree = Tree::Item("-");
885 let updated_location = location.insert_down(new_tree);
886
887 assert_eq!(updated_location, None);
888 }
889
890 #[test]
891 fn test_delete_top() {
892 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
893
894 let location = Location {
895 path: Path::Top.into(),
896 cursor: tree,
897 };
898
899 assert_eq!(location.delete(), None);
900 }
901
902 #[test]
903 fn test_delete_middle_node() {
904 let location = Location {
905 path: Path::Node {
906 left: vec![Tree::Item("+"), Tree::Item("a")],
907 right: vec![],
908 path: Path::Top.into(),
909 }
910 .into(),
911 cursor: Tree::Item("b"),
912 };
913
914 let updated_location = location.delete();
915
916 assert_eq!(
917 updated_location,
918 Some(Location {
919 cursor: Tree::Item("+"),
920 path: Path::Node {
921 left: [Tree::Item("a")].into(),
922 right: [].into(),
923 path: crate::Path::Top.into(),
924 }
925 .into()
926 })
927 );
928 }
929
930 #[test]
931 fn test_delete_last_node() {
932 let tree = Tree::Section(vec![Tree::Item("a"), Tree::Item("+"), Tree::Item("b")]);
933
934 let location = Location {
935 path: Path::Top.into(),
936 cursor: tree,
937 };
938
939 let updated_location = location.go_down().and_then(Location::delete);
940
941 assert_eq!(
942 updated_location,
943 Some(Location {
944 cursor: Tree::Item("+"),
945 path: Path::Node {
946 right: [Tree::Item("b")].into(),
947 left: [].into(),
948 path: crate::Path::Top.into(),
949 }
950 .into()
951 })
952 );
953 }
954
955 #[test]
956 fn test_delete_only_child() {
957 let tree = Tree::Section(vec![Tree::Item("a")]);
958
959 let location = Location {
960 path: Path::Top.into(),
961 cursor: tree,
962 };
963
964 let updated_location = location.go_down().and_then(Location::delete);
965
966 assert_eq!(
967 updated_location,
968 Some(Location {
969 cursor: Tree::Section(vec![]),
970 path: crate::Path::Top.into(),
971 })
972 );
973 }
974}