1use std::any::TypeId;
2use std::ops::RangeBounds;
3use std::sync::{Arc, Condvar, Mutex};
4
5use chashmap::{CHashMap, ReadGuard, WriteGuard};
6use serde::{Deserialize, Serialize};
7use serde_json::value::{from_value, to_value};
8
9use entry::{Entry, RangeLookupEntry, ValueLookupEntry};
10use helpers::{deflatten, flatten};
11
12pub trait ObjectSpace {
29 fn write<T>(&self, obj: T)
39 where
40 for<'de> T: Serialize + Deserialize<'de> + 'static;
41
42 fn try_read<T>(&self) -> Option<T>
58 where
59 for<'de> T: Serialize + Deserialize<'de> + 'static;
60
61 fn read_all<'a, T>(&'a self) -> Box<Iterator<Item = T> + 'a>
79 where
80 for<'de> T: Serialize + Deserialize<'de> + 'static;
81
82 fn read<T>(&self) -> T
97 where
98 for<'de> T: Serialize + Deserialize<'de> + 'static;
99
100 fn try_take<T>(&self) -> Option<T>
116 where
117 for<'de> T: Serialize + Deserialize<'de> + 'static;
118
119 fn take_all<'a, T>(&'a self) -> Box<Iterator<Item = T> + 'a>
138 where
139 for<'de> T: Serialize + Deserialize<'de> + 'static;
140
141 fn take<T>(&self) -> T
156 where
157 for<'de> T: Serialize + Deserialize<'de> + 'static;
158}
159
160pub trait RangeLookupObjectSpace<U>: ObjectSpace {
179 fn try_read_by_range<T, R>(&self, field: &str, range: R) -> Option<T>
195 where
196 for<'de> T: Serialize + Deserialize<'de> + 'static,
197 R: RangeBounds<U> + Clone;
198
199 fn read_all_by_range<'a, T, R>(&'a self, field: &str, range: R) -> Box<Iterator<Item = T> + 'a>
214 where
215 for<'de> T: Deserialize<'de> + 'static,
216 R: RangeBounds<U> + Clone;
217
218 fn read_by_range<T, R>(&self, field: &str, range: R) -> T
233 where
234 for<'de> T: Serialize + Deserialize<'de> + 'static,
235 R: RangeBounds<U> + Clone;
236
237 fn try_take_by_range<T, R>(&self, field: &str, range: R) -> Option<T>
254 where
255 for<'de> T: Serialize + Deserialize<'de> + 'static,
256 R: RangeBounds<U> + Clone;
257
258 fn take_all_by_range<'a, T, R>(&'a self, field: &str, range: R) -> Box<Iterator<Item = T> + 'a>
273 where
274 for<'de> T: Deserialize<'de> + 'static,
275 R: RangeBounds<U> + Clone;
276
277 fn take_by_range<T, R>(&self, field: &str, range: R) -> T
293 where
294 for<'de> T: Serialize + Deserialize<'de> + 'static,
295 R: RangeBounds<U> + Clone;
296}
297
298pub trait ValueLookupObjectSpace<U>: ObjectSpace {
317 fn try_read_by_value<T>(&self, field: &str, key: &U) -> Option<T>
333 where
334 for<'de> T: Serialize + Deserialize<'de> + 'static;
335
336 fn read_all_by_value<'a, T>(&'a self, field: &str, key: &U) -> Box<Iterator<Item = T> + 'a>
351 where
352 for<'de> T: Deserialize<'de> + 'static;
353
354 fn read_by_value<T>(&self, field: &str, key: &U) -> T
369 where
370 for<'de> T: Serialize + Deserialize<'de> + 'static;
371
372 fn try_take_by_value<T>(&self, field: &str, key: &U) -> Option<T>
389 where
390 for<'de> T: Serialize + Deserialize<'de> + 'static;
391
392 fn take_all_by_value<'a, T>(&'a self, field: &str, key: &U) -> Box<Iterator<Item = T> + 'a>
407 where
408 for<'de> T: Deserialize<'de> + 'static;
409
410 fn take_by_value<T>(&self, field: &str, key: &U) -> T
425 where
426 for<'de> T: Serialize + Deserialize<'de> + 'static;
427}
428
429type Lock = Arc<(Mutex<bool>, Condvar)>;
430
431#[derive(Default)]
446pub struct TreeObjectSpace {
447 typeid_entries_dict: CHashMap<TypeId, Entry>,
448 lock_dict: CHashMap<TypeId, Lock>,
449}
450
451impl TreeObjectSpace {
452 pub fn new() -> TreeObjectSpace {
453 Default::default()
454 }
455
456 fn get_object_entry_ref<T>(&self) -> Option<ReadGuard<TypeId, Entry>>
457 where
458 T: 'static,
459 {
460 let type_id = TypeId::of::<T>();
461 self.typeid_entries_dict.get(&type_id)
462 }
463
464 fn get_object_entry_mut<T>(&self) -> Option<WriteGuard<TypeId, Entry>>
465 where
466 T: 'static,
467 {
468 let type_id = TypeId::of::<T>();
469 self.typeid_entries_dict.get_mut(&type_id)
470 }
471
472 fn get_lock<T>(&self) -> Option<ReadGuard<TypeId, Lock>>
473 where
474 T: 'static,
475 {
476 let type_id = TypeId::of::<T>();
477 self.lock_dict.get(&type_id)
478 }
479
480 fn add_entry(&self, id: TypeId) {
481 let default_value = Entry::new();
482
483 self.typeid_entries_dict
484 .upsert(id, || default_value, |_| ());
485 self.lock_dict
486 .upsert(id, || Arc::new((Mutex::new(false), Condvar::new())), |_| ());
487 }
488}
489
490impl ObjectSpace for TreeObjectSpace {
491 fn write<T>(&self, obj: T)
492 where
493 for<'de> T: Serialize + Deserialize<'de> + 'static,
494 {
495 let type_id = TypeId::of::<T>();
496 self.add_entry(type_id);
497 let &(ref lock, ref cvar) = &*self.get_lock::<T>().unwrap().clone();
498 let value = flatten(to_value(obj).expect("struct cannot be serialized"));
499 let mut status = lock.lock().unwrap();
500 *status = !*status;
501 self.typeid_entries_dict
502 .get_mut(&type_id)
503 .unwrap()
504 .add(value);
505 cvar.notify_all();
506 }
507
508 fn try_read<T>(&self) -> Option<T>
509 where
510 for<'de> T: Serialize + Deserialize<'de> + 'static,
511 {
512 let value = match self.get_object_entry_ref::<T>() {
513 Some(entry) => entry.get(),
514 _ => None,
515 };
516 match value {
517 Some(val) => from_value(deflatten(val)).ok(),
518 _ => None,
519 }
520 }
521
522 fn read_all<'a, T>(&'a self) -> Box<Iterator<Item = T> + 'a>
523 where
524 for<'de> T: Serialize + Deserialize<'de> + 'static,
525 {
526 let val_iter: Vec<_> = match self.get_object_entry_ref::<T>() {
527 Some(ent) => ent.get_all().collect(),
528 None => Vec::new(),
529 };
530
531 Box::new(
532 val_iter
533 .into_iter()
534 .filter_map(|item| from_value(deflatten(item)).ok()),
535 )
536 }
537
538 fn read<T>(&self) -> T
539 where
540 for<'de> T: Serialize + Deserialize<'de> + 'static,
541 {
542 self.add_entry(TypeId::of::<T>());
543 let &(ref lock, ref cvar) = &*self.get_lock::<T>().unwrap().clone();
544 let value;
545 {
546 let mut fetched = lock.lock().unwrap();
547 loop {
548 let result = match self.get_object_entry_ref::<T>() {
549 Some(entry) => entry.get(),
550 _ => None,
551 };
552 if let Some(item) = result {
553 value = item;
554 break;
555 }
556 fetched = cvar.wait(fetched).unwrap();
557 }
558 }
559 from_value(deflatten(value)).unwrap()
560 }
561
562 fn try_take<T>(&self) -> Option<T>
563 where
564 for<'de> T: Serialize + Deserialize<'de> + 'static,
565 {
566 let value = match self.get_object_entry_mut::<T>() {
567 Some(mut entry) => entry.remove(),
568 _ => None,
569 };
570 match value {
571 Some(val) => from_value(deflatten(val)).ok(),
572 _ => None,
573 }
574 }
575
576 fn take_all<'a, T>(&'a self) -> Box<Iterator<Item = T> + 'a>
577 where
578 for<'de> T: Serialize + Deserialize<'de> + 'static,
579 {
580 let val_iter = match self.get_object_entry_mut::<T>() {
581 Some(mut ent) => ent.remove_all(),
582 None => Vec::new(),
583 };
584
585 Box::new(
586 val_iter
587 .into_iter()
588 .filter_map(|item| from_value(deflatten(item)).ok()),
589 )
590 }
591
592 fn take<T>(&self) -> T
593 where
594 for<'de> T: Serialize + Deserialize<'de> + 'static,
595 {
596 self.add_entry(TypeId::of::<T>());
597 let &(ref lock, ref cvar) = &*self.get_lock::<T>().unwrap().clone();
598 let value;
599 {
600 let mut fetched = lock.lock().unwrap();
601 loop {
602 let result = match self.get_object_entry_mut::<T>() {
603 Some(mut entry) => entry.remove(),
604 _ => None,
605 };
606 if let Some(item) = result {
607 value = item;
608 break;
609 }
610 fetched = cvar.wait(fetched).unwrap();
611 }
612 }
613 from_value(deflatten(value)).unwrap()
614 }
615}
616
617macro_rules! object_range{
618 ($($ty:ident)*) => {
619 $(
620 impl RangeLookupObjectSpace<$ty> for TreeObjectSpace {
621 fn try_read_by_range<T, R>(&self, field: &str, range: R) -> Option<T>
622 where
623 for<'de> T: Serialize + Deserialize<'de> + 'static,
624 R: RangeBounds<$ty> + Clone,
625 {
626 let value = match self.get_object_entry_ref::<T>() {
627 Some(entry) => entry.get_by_range::<_>(field, range),
628 _ => None,
629 };
630 match value {
631 Some(val) => from_value(deflatten(val)).ok(),
632 _ => None,
633 }
634 }
635
636 fn read_all_by_range<'a, T, R>(&'a self, field: &str, range: R) -> Box<Iterator<Item = T> + 'a>
637 where
638 for<'de> T: Deserialize<'de> + 'static,
639 R: RangeBounds<$ty> + Clone,
640 {
641 let val_iter: Vec<_> = match self.get_object_entry_ref::<T>() {
642 Some(ent) => ent.get_all_by_range::<_>(field, range).collect(),
643 None => Vec::new(),
644 };
645
646 Box::new(val_iter.into_iter().filter_map(|item| from_value(deflatten(item)).ok()))
647 }
648
649 fn read_by_range<T, R>(&self, field: &str, range: R) -> T
650 where
651 for<'de> T: Serialize + Deserialize<'de> + 'static,
652 R: RangeBounds<$ty> + Clone,
653 {
654 self.add_entry(TypeId::of::<T>());
655 let &(ref lock, ref cvar) = &*self.get_lock::<T>().unwrap().clone();
656 let value;
657 {
658 let mut fetched = lock.lock().unwrap();
659 loop {
660 let result = match self.get_object_entry_ref::<T>() {
661 Some(entry) => entry.get_by_range::<_>(field, range.clone()),
662 _ => None,
663 };
664 if let Some(item) = result {
665 value = item;
666 break;
667 }
668 fetched = cvar.wait(fetched).unwrap();
669 }
670 }
671 from_value(deflatten(value)).unwrap()
672 }
673
674 fn try_take_by_range<T, R>(&self, field: &str, range: R) -> Option<T>
675 where
676 for<'de> T: Serialize + Deserialize<'de> + 'static,
677 R: RangeBounds<$ty> + Clone,
678 {
679 let value = match self.get_object_entry_mut::<T>() {
680 Some(mut entry) => entry.remove_by_range::<_>(field, range),
681 _ => None,
682 };
683 match value {
684 Some(val) => from_value(deflatten(val)).ok(),
685 _ => None,
686 }
687 }
688
689 fn take_all_by_range<'a, T, R>(
690 &'a self,
691 field: &str,
692 range: R,
693 ) -> Box<Iterator<Item = T> + 'a>
694 where
695 for<'de> T: Deserialize<'de> + 'static,
696 R: RangeBounds<$ty> + Clone,
697 {
698 let val_iter = match self.get_object_entry_mut::<T>() {
699 Some(mut ent) => ent.remove_all_by_range::<_>(field, range),
700 None => Vec::new(),
701 };
702
703 Box::new(
704 val_iter
705 .into_iter()
706 .filter_map(|item| from_value(deflatten(item)).ok())
707 )
708 }
709
710 fn take_by_range<T, R>(&self, field: &str, range: R) -> T
711 where
712 for<'de> T: Serialize + Deserialize<'de> + 'static,
713 R: RangeBounds<$ty> + Clone,
714 {
715 self.add_entry(TypeId::of::<T>());
716 let &(ref lock, ref cvar) = &*self.get_lock::<T>().unwrap().clone();
717 let value;
718 {
719 let mut fetched = lock.lock().unwrap();
720 loop {
721 let result = match self.get_object_entry_mut::<T>() {
722 Some(mut entry) => entry.remove_by_range::<_>(field, range.clone()),
723 _ => None,
724 };
725 if let Some(item) = result {
726 value = item;
727 break;
728 }
729 fetched = cvar.wait(fetched).unwrap();
730 }
731 }
732 from_value(deflatten(value)).unwrap()
733 }
734 }
735 )*
736 };
737}
738
739macro_rules! object_key{
740 ($($ty:ty)*) => {
741 $(
742 impl ValueLookupObjectSpace<$ty> for TreeObjectSpace {
743 fn try_read_by_value<T>(&self, field: &str, key: &$ty) -> Option<T>
744 where
745 for<'de> T: Serialize + Deserialize<'de> + 'static,
746 {
747 let value = match self.get_object_entry_ref::<T>() {
748 Some(entry) => entry.get_by_value(field, key),
749 _ => None,
750 };
751 match value {
752 Some(val) => from_value(deflatten(val)).ok(),
753 _ => None,
754 }
755 }
756
757 fn read_all_by_value<'a, T>(&'a self, field: &str, key: &$ty) -> Box<Iterator<Item = T> + 'a>
758 where
759 for<'de> T: Deserialize<'de> + 'static,
760 {
761 let val_iter: Vec<_> = match self.get_object_entry_ref::<T>() {
762 Some(ent) => ent.get_all_by_value(field, key).collect(),
763 None => Vec::new(),
764 };
765
766 Box::new(val_iter.into_iter().filter_map(|item| from_value(deflatten(item)).ok()))
767 }
768
769 fn read_by_value<T>(&self, field: &str, key: &$ty) -> T
770 where
771 for<'de> T: Serialize + Deserialize<'de> + 'static,
772 {
773 self.add_entry(TypeId::of::<T>());
774 let &(ref lock, ref cvar) = &*self.get_lock::<T>().unwrap().clone();
775 let value;
776 {
777 let mut fetched = lock.lock().unwrap();
778 loop {
779 let result = match self.get_object_entry_ref::<T>() {
780 Some(entry) => entry.get_by_value(field, key),
781 _ => None,
782 };
783 if let Some(item) = result {
784 value = item;
785 break;
786 }
787 fetched = cvar.wait(fetched).unwrap();
788 }
789 }
790 from_value(deflatten(value)).unwrap()
791 }
792
793 fn try_take_by_value<T>(&self, field: &str, key: &$ty) -> Option<T>
794 where
795 for<'de> T: Serialize + Deserialize<'de> + 'static,
796 {
797 let value = match self.get_object_entry_mut::<T>() {
798 Some(mut entry) => entry.remove_by_value(field, key),
799 _ => None,
800 };
801 match value {
802 Some(val) => from_value(deflatten(val)).ok(),
803 _ => None,
804 }
805 }
806
807 fn take_all_by_value<'a, T>(
808 &'a self,
809 field: &str,
810 key: &$ty,
811 ) -> Box<Iterator<Item = T> + 'a>
812 where
813 for<'de> T: Deserialize<'de> + 'static,
814 {
815 let val_iter = match self.get_object_entry_mut::<T>() {
816 Some(mut ent) => ent.remove_all_by_value(field, key),
817 None => Vec::new(),
818 };
819
820 Box::new(
821 val_iter
822 .into_iter()
823 .filter_map(|item| from_value(deflatten(item)).ok())
824 )
825 }
826
827 fn take_by_value<T>(&self, field: &str, key: &$ty) -> T
828 where
829 for<'de> T: Serialize + Deserialize<'de> + 'static,
830 {
831 self.add_entry(TypeId::of::<T>());
832 let &(ref lock, ref cvar) = &*self.get_lock::<T>().unwrap().clone();
833 let value;
834 {
835 let mut fetched = lock.lock().unwrap();
836 loop {
837 let result = match self.get_object_entry_mut::<T>() {
838 Some(mut entry) => entry.remove_by_value(field, key),
839 _ => None,
840 };
841 if let Some(item) = result {
842 value = item;
843 break;
844 }
845 fetched = cvar.wait(fetched).unwrap();
846 }
847 }
848 from_value(deflatten(value)).unwrap()
849 }
850 }
851 )*
852 };
853}
854
855object_range!{i64 String f64}
856object_key!{i64 String bool f64}
857
858mod tests {
859 use super::*;
860
861 #[derive(Serialize, Deserialize, PartialEq, Debug)]
862 struct TestStruct {
863 count: i32,
864 name: String,
865 }
866
867 #[derive(Serialize, Deserialize, PartialEq, Debug)]
868 struct CompoundStruct {
869 person: TestStruct,
870 gpa: f64,
871 }
872
873 #[derive(Serialize, Deserialize, PartialEq, Debug)]
874 enum TestEnum {
875 String(String),
876 Int(i32),
877 Struct { count: i32, name: String },
878 }
879
880 #[test]
881 fn try_read() {
882 let space = TreeObjectSpace::new();
883 assert_eq!(space.try_read::<String>(), None);
884 space.write(String::from("Hello World"));
885 space.write(TestStruct {
886 count: 3,
887 name: String::from("Tuan"),
888 });
889 space.write(CompoundStruct {
890 person: TestStruct {
891 count: 3,
892 name: String::from("Tuan"),
893 },
894 gpa: 3.0,
895 });
896
897 assert_eq!(
898 space.try_read::<String>(),
899 Some(String::from("Hello World"))
900 );
901 assert_ne!(space.try_read::<String>(), None);
902
903 assert_eq!(
904 space.try_read::<TestStruct>(),
905 Some(TestStruct {
906 count: 3,
907 name: String::from("Tuan"),
908 })
909 );
910
911 assert_eq!(
912 space.try_read::<CompoundStruct>(),
913 Some(CompoundStruct {
914 person: TestStruct {
915 count: 3,
916 name: String::from("Tuan"),
917 },
918 gpa: 3.0
919 })
920 );
921 assert!(space.try_read::<CompoundStruct>().is_some());
922 }
923
924 #[test]
925 fn try_take() {
926 let space = TreeObjectSpace::new();
927 assert_eq!(space.try_take::<String>(), None);
928 space.write(String::from("Hello World"));
929 space.write(TestStruct {
930 count: 3,
931 name: String::from("Tuan"),
932 });
933 space.write(CompoundStruct {
934 person: TestStruct {
935 count: 3,
936 name: String::from("Tuan"),
937 },
938 gpa: 3.5,
939 });
940
941 assert_eq!(
942 space.try_take::<String>(),
943 Some(String::from("Hello World"))
944 );
945 assert_eq!(space.try_take::<String>(), None);
946
947 assert_eq!(
948 space.try_take::<TestStruct>(),
949 Some(TestStruct {
950 count: 3,
951 name: String::from("Tuan"),
952 })
953 );
954 assert_eq!(space.try_take::<TestStruct>(), None);
955
956 assert_eq!(
957 space.try_take::<CompoundStruct>(),
958 Some(CompoundStruct {
959 person: TestStruct {
960 count: 3,
961 name: String::from("Tuan"),
962 },
963 gpa: 3.5
964 })
965 );
966 assert!(space.try_take::<CompoundStruct>().is_none());
967 }
968
969 #[test]
970 fn read_all() {
971 let space = TreeObjectSpace::new();
972 assert_eq!(space.read_all::<String>().count(), 0);
973 space.write("Hello".to_string());
974 space.write("World".to_string());
975 space.write(TestStruct {
976 count: 3,
977 name: String::from("Tuan"),
978 });
979 space.write(TestStruct {
980 count: 5,
981 name: String::from("Duane"),
982 });
983
984 assert_eq!(
985 space.read_all::<String>().collect::<Vec<String>>(),
986 vec!["Hello", "World"]
987 );
988 assert_ne!(space.read_all::<String>().count(), 0);
989
990 assert_eq!(space.read_all::<TestStruct>().count(), 2);
991 assert_eq!(space.read_all::<TestStruct>().count(), 2);
992 }
993
994 #[test]
995 fn take_all() {
996 let space = TreeObjectSpace::new();
997 assert_eq!(space.take_all::<String>().count(), 0);
998 space.write("Hello".to_string());
999 space.write("World".to_string());
1000 space.write(TestStruct {
1001 count: 3,
1002 name: String::from("Tuan"),
1003 });
1004 space.write(TestStruct {
1005 count: 5,
1006 name: String::from("Duane"),
1007 });
1008
1009 assert_eq!(space.take_all::<String>().count(), 2);
1010 assert_eq!(space.take_all::<String>().count(), 0);
1011
1012 assert_eq!(space.take_all::<TestStruct>().count(), 2);
1013 assert_eq!(space.take_all::<TestStruct>().count(), 0);
1014 }
1015
1016 #[test]
1017 fn try_read_by_range() {
1018 let space = TreeObjectSpace::new();
1019 assert_eq!(space.try_read_by_range::<i64, _>("", 2..4), None);
1020 space.write::<i64>(3);
1021 space.write::<i64>(5);
1022
1023 assert_eq!(space.try_read_by_range::<i64, _>("", 2..4), Some(3));
1024 assert_ne!(space.try_read_by_range::<i64, _>("", 2..4), None);
1025
1026 space.write(TestStruct {
1027 count: 3,
1028 name: String::from("Tuan"),
1029 });
1030 space.write(TestStruct {
1031 count: 5,
1032 name: String::from("Duane"),
1033 });
1034
1035 assert_eq!(
1036 space.try_read_by_range::<TestStruct, _>("count", 2..4),
1037 Some(TestStruct {
1038 count: 3,
1039 name: String::from("Tuan"),
1040 })
1041 );
1042 assert!(
1043 space
1044 .try_read_by_range::<TestStruct, _>("count", 2..4)
1045 .is_some()
1046 );
1047
1048 space.write(CompoundStruct {
1049 person: TestStruct {
1050 count: 5,
1051 name: String::from("Duane"),
1052 },
1053 gpa: 3.0,
1054 });
1055 space.write(CompoundStruct {
1056 person: TestStruct {
1057 count: 3,
1058 name: String::from("Tuan"),
1059 },
1060 gpa: 3.5,
1061 });
1062
1063 assert_eq!(
1064 space.try_read_by_range::<CompoundStruct, _>("person.count", 2..4),
1065 Some(CompoundStruct {
1066 person: TestStruct {
1067 count: 3,
1068 name: String::from("Tuan"),
1069 },
1070 gpa: 3.5
1071 })
1072 );
1073 assert!(
1074 space
1075 .try_read_by_range::<CompoundStruct, _>("person.count", 2..4)
1076 .is_some()
1077 );
1078 }
1079
1080 #[test]
1081 fn try_take_by_range() {
1082 let space = TreeObjectSpace::new();
1083 assert_eq!(space.try_take_by_range::<i64, _>("", 2..4), None);
1084 space.write::<i64>(3);
1085 space.write::<i64>(5);
1086 assert_eq!(space.try_take_by_range::<i64, _>("", 2..4), Some(3));
1087 assert_eq!(space.try_take_by_range::<i64, _>("", 2..4), None);
1088
1089 space.write(TestStruct {
1090 count: 3,
1091 name: String::from("Tuan"),
1092 });
1093 space.write(TestStruct {
1094 count: 5,
1095 name: String::from("Duane"),
1096 });
1097
1098 assert_eq!(
1099 space.try_take_by_range::<TestStruct, _>("count", 2..4),
1100 Some(TestStruct {
1101 count: 3,
1102 name: String::from("Tuan"),
1103 })
1104 );
1105 assert!(
1106 space
1107 .try_take_by_range::<TestStruct, _>("count", 2..4)
1108 .is_none()
1109 );
1110
1111 space.write(CompoundStruct {
1112 person: TestStruct {
1113 count: 3,
1114 name: String::from("Tuan"),
1115 },
1116 gpa: 3.0,
1117 });
1118 space.write(CompoundStruct {
1119 person: TestStruct {
1120 count: 5,
1121 name: String::from("Duane"),
1122 },
1123 gpa: 3.5,
1124 });
1125
1126 assert_eq!(
1127 space.try_take_by_range::<CompoundStruct, _>("gpa", 3.0..3.5),
1128 Some(CompoundStruct {
1129 person: TestStruct {
1130 count: 3,
1131 name: String::from("Tuan"),
1132 },
1133 gpa: 3.0
1134 })
1135 );
1136 assert!(
1137 space
1138 .try_take_by_range::<CompoundStruct, _>("person.count", 2..4)
1139 .is_none()
1140 );
1141 }
1142
1143 #[test]
1144 fn read_all_by_range() {
1145 let space = TreeObjectSpace::new();
1146 space.write::<i64>(3);
1147 space.write::<i64>(5);
1148 assert_eq!(space.read_all_by_range::<i64, _>("", 2..4).count(), 1);
1149 assert_eq!(space.read_all_by_range::<i64, _>("", 2..4).count(), 1);
1150
1151 space.write(TestStruct {
1152 count: 3,
1153 name: String::from("Tuan"),
1154 });
1155 space.write(TestStruct {
1156 count: 3,
1157 name: String::from("Minh"),
1158 });
1159
1160 space.write(TestStruct {
1161 count: 5,
1162 name: String::from("Duane"),
1163 });
1164
1165 assert_eq!(
1166 space
1167 .read_all_by_range::<TestStruct, _>("count", 2..4)
1168 .count(),
1169 2
1170 );
1171 assert_eq!(
1172 space
1173 .read_all_by_range::<TestStruct, _>("count", 2..4)
1174 .count(),
1175 2
1176 );
1177
1178 space.write(CompoundStruct {
1179 person: TestStruct {
1180 count: 5,
1181 name: String::from("Duane"),
1182 },
1183 gpa: 4.0,
1184 });
1185 space.write(CompoundStruct {
1186 person: TestStruct {
1187 count: 3,
1188 name: String::from("Tuan"),
1189 },
1190 gpa: 3.0,
1191 });
1192 space.write(CompoundStruct {
1193 person: TestStruct {
1194 count: 3,
1195 name: String::from("Minh"),
1196 },
1197 gpa: 3.0,
1198 });
1199
1200 assert_eq!(
1201 space
1202 .read_all_by_range::<CompoundStruct, _>("gpa", 2.5..4.0)
1203 .count(),
1204 2
1205 );
1206 assert_eq!(
1207 space
1208 .read_all_by_range::<CompoundStruct, _>("person.count", 2..4)
1209 .count(),
1210 2
1211 );
1212 }
1213
1214 #[test]
1215 fn take_all_by_range() {
1216 let space = TreeObjectSpace::new();
1217 space.write::<i64>(3);
1218 space.write::<i64>(5);
1219 assert_eq!(space.take_all_by_range::<i64, _>("", 2..4).count(), 1);
1220 assert_eq!(space.take_all_by_range::<i64, _>("", 2..4).count(), 0);
1221
1222 space.write(TestStruct {
1223 count: 3,
1224 name: String::from("Tuan"),
1225 });
1226 space.write(TestStruct {
1227 count: 3,
1228 name: String::from("Minh"),
1229 });
1230
1231 space.write(TestStruct {
1232 count: 5,
1233 name: String::from("Duane"),
1234 });
1235
1236 assert_eq!(
1237 space
1238 .take_all_by_range::<TestStruct, _>("count", 2..4)
1239 .count(),
1240 2
1241 );
1242 assert_eq!(
1243 space
1244 .take_all_by_range::<TestStruct, _>("count", 2..4)
1245 .count(),
1246 0
1247 );
1248 assert_eq!(
1249 space
1250 .take_all_by_range::<TestStruct, _>("count", 4..)
1251 .count(),
1252 1
1253 );
1254
1255 space.write(CompoundStruct {
1256 person: TestStruct {
1257 count: 5,
1258 name: String::from("Duane"),
1259 },
1260 gpa: 3.5,
1261 });
1262 space.write(CompoundStruct {
1263 person: TestStruct {
1264 count: 3,
1265 name: String::from("Tuan"),
1266 },
1267 gpa: 3.0,
1268 });
1269 space.write(CompoundStruct {
1270 person: TestStruct {
1271 count: 3,
1272 name: String::from("Minh"),
1273 },
1274 gpa: 3.0,
1275 });
1276
1277 assert_eq!(
1278 space
1279 .take_all_by_range::<CompoundStruct, _>("gpa", 2.5..3.5)
1280 .count(),
1281 2
1282 );
1283 assert_eq!(
1284 space
1285 .take_all_by_range::<CompoundStruct, _>("person.count", 2..4)
1286 .count(),
1287 0
1288 );
1289 assert_eq!(
1290 space
1291 .take_all_by_range::<CompoundStruct, _>("gpa", 3.5..)
1292 .count(),
1293 1
1294 );
1295 }
1296
1297 #[test]
1298 fn try_read_by_value() {
1299 let space = TreeObjectSpace::new();
1300 assert_eq!(space.try_read_by_value::<i64>("", &3), None);
1301 space.write::<i64>(3);
1302 space.write::<i64>(5);
1303
1304 assert_eq!(space.try_read_by_value::<i64>("", &3), Some(3));
1305 assert_eq!(space.try_read_by_value::<i64>("", &2), None);
1306
1307 space.write(TestStruct {
1308 count: 3,
1309 name: String::from("Tuan"),
1310 });
1311 space.write(TestStruct {
1312 count: 5,
1313 name: String::from("Duane"),
1314 });
1315
1316 assert_eq!(
1317 space.try_read_by_value::<TestStruct>("count", &3),
1318 Some(TestStruct {
1319 count: 3,
1320 name: String::from("Tuan"),
1321 })
1322 );
1323 assert!(space.try_read_by_value::<TestStruct>("count", &3).is_some());
1324
1325 space.write(CompoundStruct {
1326 person: TestStruct {
1327 count: 5,
1328 name: String::from("Duane"),
1329 },
1330 gpa: 4.0,
1331 });
1332 space.write(CompoundStruct {
1333 person: TestStruct {
1334 count: 3,
1335 name: String::from("Tuan"),
1336 },
1337 gpa: 3.0,
1338 });
1339
1340 assert_eq!(
1341 space.try_read_by_value::<CompoundStruct>("person.count", &3),
1342 Some(CompoundStruct {
1343 person: TestStruct {
1344 count: 3,
1345 name: String::from("Tuan"),
1346 },
1347 gpa: 3.0
1348 })
1349 );
1350 assert!(
1351 space
1352 .try_read_by_value::<CompoundStruct>("gpa", &3.0)
1353 .is_some()
1354 );
1355 }
1356
1357 #[test]
1358 fn try_take_by_value() {
1359 let space = TreeObjectSpace::new();
1360 assert_eq!(space.try_take_by_value::<i64>("", &3), None);
1361 space.write::<i64>(3);
1362 space.write::<i64>(5);
1363 assert_eq!(space.try_take_by_value::<i64>("", &4), None);
1364 assert_eq!(space.try_take_by_value::<i64>("", &3), Some(3));
1365 assert_eq!(space.try_take_by_value::<i64>("", &3), None);
1366
1367 space.write(TestStruct {
1368 count: 3,
1369 name: String::from("Tuan"),
1370 });
1371 assert_eq!(
1372 space.try_take_by_value::<TestStruct>("count", &3),
1373 Some(TestStruct {
1374 count: 3,
1375 name: String::from("Tuan"),
1376 })
1377 );
1378 assert!(space.try_take_by_value::<TestStruct>("count", &3).is_none());
1379
1380 space.write(CompoundStruct {
1381 person: TestStruct {
1382 count: 3,
1383 name: String::from("Tuan"),
1384 },
1385 gpa: 3.0,
1386 });
1387
1388 assert_eq!(
1389 space.try_take_by_value::<CompoundStruct>("person.count", &3),
1390 Some(CompoundStruct {
1391 person: TestStruct {
1392 count: 3,
1393 name: String::from("Tuan"),
1394 },
1395 gpa: 3.0
1396 })
1397 );
1398 assert!(
1399 space
1400 .try_take_by_value::<CompoundStruct>("gpa", &3.0)
1401 .is_none()
1402 );
1403 }
1404
1405 #[test]
1406 fn read_all_by_value() {
1407 let space = TreeObjectSpace::new();
1408 space.write::<i64>(3);
1409 space.write::<i64>(5);
1410 assert_eq!(space.read_all_by_value::<i64>("", &3).count(), 1);
1411 assert_eq!(space.read_all_by_value::<i64>("", &4).count(), 0);
1412
1413 space.write(TestStruct {
1414 count: 3,
1415 name: String::from("Tuan"),
1416 });
1417 space.write(TestStruct {
1418 count: 3,
1419 name: String::from("Minh"),
1420 });
1421
1422 space.write(TestStruct {
1423 count: 5,
1424 name: String::from("Duane"),
1425 });
1426
1427 assert_eq!(
1428 space.read_all_by_value::<TestStruct>("count", &3).count(),
1429 2
1430 );
1431 assert_eq!(
1432 space.read_all_by_value::<TestStruct>("count", &4).count(),
1433 0
1434 );
1435
1436 space.write(CompoundStruct {
1437 person: TestStruct {
1438 count: 5,
1439 name: String::from("Duane"),
1440 },
1441 gpa: 4.0,
1442 });
1443 space.write(CompoundStruct {
1444 person: TestStruct {
1445 count: 3,
1446 name: String::from("Tuan"),
1447 },
1448 gpa: 3.0,
1449 });
1450 space.write(CompoundStruct {
1451 person: TestStruct {
1452 count: 3,
1453 name: String::from("Minh"),
1454 },
1455 gpa: 3.5,
1456 });
1457
1458 assert_eq!(
1459 space
1460 .read_all_by_value::<CompoundStruct>("person.count", &3)
1461 .count(),
1462 2
1463 );
1464 assert_eq!(
1465 space
1466 .read_all_by_value::<CompoundStruct>("person.count", &4)
1467 .count(),
1468 0
1469 );
1470 assert_eq!(
1471 space
1472 .read_all_by_value::<CompoundStruct>("gpa", &4.0)
1473 .count(),
1474 1
1475 );
1476 }
1477
1478 #[test]
1479 fn take_all_by_value() {
1480 let space = TreeObjectSpace::new();
1481 space.write::<i64>(3);
1482 space.write::<i64>(5);
1483 assert_eq!(space.take_all_by_value::<i64>("", &3).count(), 1);
1484 assert_eq!(space.take_all_by_value::<i64>("", &4).count(), 0);
1485
1486 space.write(TestStruct {
1487 count: 3,
1488 name: String::from("Tuan"),
1489 });
1490 space.write(TestStruct {
1491 count: 3,
1492 name: String::from("Minh"),
1493 });
1494
1495 space.write(TestStruct {
1496 count: 5,
1497 name: String::from("Duane"),
1498 });
1499
1500 assert_eq!(
1501 space.take_all_by_value::<TestStruct>("count", &3).count(),
1502 2
1503 );
1504 assert_eq!(
1505 space.take_all_by_value::<TestStruct>("count", &3).count(),
1506 0
1507 );
1508 assert_eq!(
1509 space.take_all_by_value::<TestStruct>("count", &5).count(),
1510 1
1511 );
1512
1513 space.write(CompoundStruct {
1514 person: TestStruct {
1515 count: 5,
1516 name: String::from("Duane"),
1517 },
1518 gpa: 4.0,
1519 });
1520 space.write(CompoundStruct {
1521 person: TestStruct {
1522 count: 3,
1523 name: String::from("Tuan"),
1524 },
1525 gpa: 3.0,
1526 });
1527 space.write(CompoundStruct {
1528 person: TestStruct {
1529 count: 3,
1530 name: String::from("Minh"),
1531 },
1532 gpa: 3.0,
1533 });
1534
1535 assert_eq!(
1536 space
1537 .take_all_by_value::<CompoundStruct>("gpa", &3.0)
1538 .count(),
1539 2
1540 );
1541 assert_eq!(
1542 space
1543 .take_all_by_value::<CompoundStruct>("person.count", &3)
1544 .count(),
1545 0
1546 );
1547 assert_eq!(
1548 space
1549 .take_all_by_value::<CompoundStruct>("person.count", &5)
1550 .count(),
1551 1
1552 );
1553 }
1554
1555 #[test]
1556 fn read_enum_range() {
1557 let space = TreeObjectSpace::new();
1558 assert_eq!(space.read_all::<TestEnum>().count(), 0);
1559 space.write(TestEnum::Int(4));
1560 assert_eq!(space.read::<TestEnum>(), TestEnum::Int(4));
1561 assert_eq!(
1562 space.try_read_by_value::<TestEnum>("Int", &4),
1563 Some(TestEnum::Int(4))
1564 );
1565 assert_eq!(
1566 space.try_read_by_value::<TestEnum>("Struct.count", &4),
1567 None
1568 );
1569 assert_eq!(
1570 space.try_read_by_range::<TestEnum, _>("Struct.count", 3..5),
1571 None
1572 );
1573
1574 space.write(TestEnum::Struct {
1575 count: 4,
1576 name: String::from("Tuan"),
1577 });
1578 assert_eq!(
1579 space.read_by_value::<TestEnum>("Struct.count", &4),
1580 TestEnum::Struct {
1581 count: 4,
1582 name: String::from("Tuan")
1583 }
1584 );
1585 assert_eq!(
1586 space.take_by_range::<TestEnum, _>("Struct.count", 3..5),
1587 TestEnum::Struct {
1588 count: 4,
1589 name: String::from("Tuan")
1590 }
1591 );
1592 assert_eq!(space.read::<TestEnum>(), TestEnum::Int(4));
1593 }
1594}