1use crate::db::*;
2use crate::name::{
3 Name,
4};
5
6use crate::{
11 vec::Vec,
12};
13
14use crate::{
15 check,
16 serializer::Packer,
17};
18
19use crate::boxed::Box;
20pub struct MultiIndex<T>
22where T: PrimaryValueInterface + SecondaryValueInterface + Packer + Default
23{
24 pub code: Name,
26 pub scope: Name,
28 pub table: Name,
30 pub db: TableI64<T>,
32 pub idxdbs: Vec<Box<dyn IdxTable>>,
34 _marker: core::marker::PhantomData<T>,
35}
36
37impl<T> MultiIndex<T>
38where T: PrimaryValueInterface + SecondaryValueInterface + Packer + Default
39{
40 pub fn new(code: Name, scope: Name, table: Name, indices: &[SecondaryType]) -> Self {
42 let mut idxdbs: Vec<Box<dyn IdxTable>> = Vec::new();
43 let mut i: usize = 0;
44 let idx_table = table.value() & 0xfffffffffffffff0;
45 for idx in indices {
46 match idx {
47 SecondaryType::Idx64 => idxdbs.push(
48 Box::new(
49 Idx64Table::new(i, code, scope, Name::from_u64(idx_table + i as u64))
50 )
51 ),
52 SecondaryType::Idx128 => idxdbs.push(
53 Box::new(
54 Idx128Table::new(i, code, scope, Name::from_u64(idx_table + i as u64))
55 )
56 ),
57 SecondaryType::Idx256 => idxdbs.push(
58 Box::new(
59 Idx256Table::new(i, code, scope, Name::from_u64(idx_table + i as u64))
60 )
61 ),
62 SecondaryType::IdxF64 => idxdbs.push(
63 Box::new(
64 IdxF64Table::new(i, code, scope, Name::from_u64(idx_table + i as u64))
65 )
66 ),
67 SecondaryType::IdxF128 => idxdbs.push(
68 Box::new(
69 IdxF128Table::new(i, code, scope, Name::from_u64(idx_table + i as u64))
70 )
71 ),
72 }
73 i += 1;
74 }
75 MultiIndex {
76 code,
77 scope,
78 table,
79 db: TableI64::new(code, scope, table),
80 idxdbs,
81 _marker: core::marker::PhantomData::<T>{},
82 }
83 }
84
85 pub fn store(&self, value: &T, payer: Name) -> Iterator<T> {
87 let primary = value.get_primary();
88 for i in 0..self.idxdbs.len() {
89 let v2 = value.get_secondary_value(i);
90 self.idxdbs[i].store(primary, v2, payer);
91 }
92 let it = self.db.store(&value, payer);
93 return it;
94 }
95
96 pub fn find(&self, id: u64) -> Iterator<T> {
98 return self.db.find(id);
99 }
100
101 pub fn update(&self, iterator: &Iterator<T>, value: &T, payer: Name) {
103 check(iterator.is_ok(), "MultiIndex::update: invalid iterator");
104 let primary = iterator.get_primary().unwrap();
105 self.db.update(&iterator,value, payer);
106 for i in 0..self.idxdbs.len() {
107 let v2 = value.get_secondary_value(i);
108 let (it_secondary, secondary_value) = self.idxdbs[i].find_primary(primary);
109 if secondary_value == v2 {
110 continue;
111 }
112 self.idxdbs[i].update(&it_secondary, v2, payer);
113 }
114 }
115
116 pub fn remove(&self, iterator: &Iterator<T>) {
118 check(iterator.is_ok(), "remove: invalid iterator");
119 let primary = iterator.get_primary().unwrap();
120 for i in 0..self.idxdbs.len() {
121 let (it_secondary, _) = self.idxdbs[i].find_primary(primary);
122 self.idxdbs[i].remove(&it_secondary);
123 }
124 self.db.remove(&iterator);
125 }
126
127 pub fn get(&self, iterator: &Iterator<T>) -> Option<T> {
129 if !iterator.is_ok() {
130 return None;
131 }
132 self.db.get(iterator)
133 }
134
135 pub fn get_by_primary(&self, primary: u64) -> Option<T> {
137 let it = self.db.find(primary);
138 return self.get(&it);
139 }
140
141 pub fn next(&self, iterator: &Iterator<T>) -> Iterator<T> {
143 return self.db.next(iterator);
144 }
145
146 pub fn previous(&self, iterator: &Iterator<T>) -> Iterator<T> {
148 return self.db.previous(iterator);
149 }
150
151 pub fn lower_bound(&self, id: u64) -> Iterator<T> {
153 return self.db.lower_bound(id);
154 }
155
156 pub fn upper_bound(&self, id: u64) -> Iterator<T> {
158 return self.db.upper_bound(id);
159 }
160
161 pub fn end(&self) -> Iterator<T> {
163 return self.db.end();
164 }
165
166 pub fn get_idx_db(&self, i: usize) -> &dyn IdxTable {
168 return self.idxdbs[i].as_ref();
169 }
170
171 pub fn idx_update(&self, it: &SecondaryIterator, value: SecondaryValue, payer: Name) {
173 let it_primary = self.find(it.primary).expect("idx_update: invalid primary");
174 let mut db_value = it_primary.get_value().unwrap();
175 let idx_db = self.get_idx_db(it.db_index);
176 db_value.set_secondary_value(idx_db.get_db_index(), value);
177 self.update(&it_primary, &db_value, payer);
178 idx_db.update(it, value, payer);
179 }
180}