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 }
74 i += 1;
75 }
76 MultiIndex {
77 code,
78 scope,
79 table,
80 db: TableI64::new(code, scope, table),
81 idxdbs,
82 _marker: core::marker::PhantomData::<T>{},
83 }
84 }
85
86 pub fn store(&self, value: &T, payer: Name) -> Iterator<T> {
88 let primary = value.get_primary();
89 for i in 0..self.idxdbs.len() {
90 let v2 = value.get_secondary_value(i);
91 self.idxdbs[i].store(primary, v2, payer);
92 }
93 let it = self.db.store(&value, payer);
94 return it;
95 }
96
97 pub fn find(&self, id: u64) -> Iterator<T> {
99 return self.db.find(id);
100 }
101
102 pub fn update(&self, iterator: &Iterator<T>, value: &T, payer: Name) {
104 check(iterator.is_ok(), "MultiIndex::update: invalid iterator");
105 let primary = iterator.get_primary().unwrap();
106 self.db.update(&iterator, value, payer);
107 for i in 0..self.idxdbs.len() {
108 let v2 = value.get_secondary_value(i);
109 let (it_secondary, secondary_value) = self.idxdbs[i].find_primary(primary);
110 if secondary_value == v2 {
111 continue;
112 }
113 self.idxdbs[i].update(&it_secondary, v2, payer);
114 }
115 }
116
117 pub fn remove(&self, iterator: &Iterator<T>) {
119 check(iterator.is_ok(), "remove: invalid iterator");
120 let primary = iterator.get_primary().unwrap();
121 for i in 0..self.idxdbs.len() {
122 let (it_secondary, _) = self.idxdbs[i].find_primary(primary);
123 self.idxdbs[i].remove(&it_secondary);
124 }
125 self.db.remove(&iterator);
126 }
127
128 pub fn get(&self, iterator: &Iterator<T>) -> Option<T> {
130 if !iterator.is_ok() {
131 return None;
132 }
133 self.db.get(iterator)
134 }
135
136 pub fn get_by_primary(&self, primary: u64) -> Option<T> {
138 let it = self.db.find(primary);
139 return self.get(&it);
140 }
141
142 pub fn next(&self, iterator: &Iterator<T>) -> Iterator<T> {
144 return self.db.next(iterator);
145 }
146
147 pub fn previous(&self, iterator: &Iterator<T>) -> Iterator<T> {
149 return self.db.previous(iterator);
150 }
151
152 pub fn lower_bound(&self, id: u64) -> Iterator<T> {
154 return self.db.lower_bound(id);
155 }
156
157 pub fn upper_bound(&self, id: u64) -> Iterator<T> {
159 return self.db.upper_bound(id);
160 }
161
162 pub fn end(&self) -> Iterator<T> {
164 return self.db.end();
165 }
166
167 pub fn get_idx_db(&self, i: usize) -> &dyn IdxTable {
169 return self.idxdbs[i].as_ref();
170 }
171
172 pub fn idx_update(&self, it: &SecondaryIterator, value: SecondaryValue, payer: Name) {
174 let it_primary = self.find(it.primary).expect("idx_update: invalid primary");
175 if let Some(mut db_value) = it_primary.get_value() {
176 let idx_db = self.idxdbs[it.db_index].as_ref();
177 db_value.set_secondary_value(idx_db.get_db_index(), value);
178 self.update(&it_primary, &db_value, payer);
179 idx_db.update(it, value, payer);
180 } else {
181 }
182 }
183}