1use crate::db::{
2 Idx64Table,
3 Idx128Table,
4 Idx256Table,
5 SecondaryType,
7 SecondaryValue,
8 SecondaryIterator,
9 IdxTable,
10 MultiIndexValue,
11};
12
13use crate::vmapi::db::*;
14use crate::name::{
15 Name,
16};
17
18use crate::{
19 vec::Vec,
20};
21
22use crate::{
23 check,
24};
25
26use crate::boxed::Box;
27use crate::serializer::{
28 Encoder,
29};
30
31pub fn cast_value<T: MultiIndexValue>(value: &Option<Box<dyn MultiIndexValue>>) -> Option<&T> {
32 if let Some(x) = value {
33 x.as_any().downcast_ref::<T>()
34 } else {
35 None
36 }
37}
38
39pub struct Iterator<'a> {
41 pub i: i32,
43 primary: Option<u64>,
44 db: &'a TableI64,
45}
46
47impl<'a> Iterator<'a> {
48 pub fn new(i: i32, primary: Option<u64>, db: &'a TableI64) -> Self {
50 Self { i, primary, db }
51 }
52
53 pub fn get_primary(&self) -> Option<u64> {
55 if !self.is_ok() {
56 return None;
57 }
58
59 if self.primary.is_some() {
60 return self.primary;
61 }
62
63 let value = self.db.get(self).unwrap();
64 return Some(value.get_primary());
65 }
66
67 pub fn get_value(&self) -> Option<Box<dyn MultiIndexValue>> {
68 return self.db.get(self);
69 }
70
71 pub fn get_value_ex<T: MultiIndexValue + core::clone::Clone>(&self) -> Option<T> {
72 let value = self.get_value();
73 if let Some(x) = cast_value::<T>(&value) {
74 Some(x.clone())
75 } else {
76 None
77 }
78 }
79
80 pub fn is_ok(&self) -> bool {
82 self.i >= 0
83 }
84
85 pub fn is_end(&self) -> bool {
87 return self.i < -1;
88 }
89
90 pub fn expect(self, msg: &str) -> Self {
92 check(self.is_ok(), msg);
93 return self;
94 }
95
96 pub fn expect_not_ok(self, msg: &str) -> Self {
98 check(!self.is_ok(), msg);
99 return self;
100 }
101}
102
103
104pub struct TableI64 {
106 pub code: u64,
108 pub scope: u64,
110 pub table: u64,
112 unpacker: fn(&[u8]) -> Box<dyn MultiIndexValue>,
113}
114
115impl TableI64 {
116 pub fn new(code: Name, scope: Name, table: Name, unpacker: fn(&[u8]) -> Box<dyn MultiIndexValue>) -> Self {
118 TableI64 {
119 code: code.value(),
120 scope: scope.value(),
121 table: table.value(),
122 unpacker,
123 }
124 }
125
126 pub fn store(&self, id: u64, data: &[u8], payer: Name) -> Iterator {
128 let it = db_store_i64(self.scope, self.table, payer.value(), id, data.as_ptr(), data.len() as u32);
129 Iterator { i: it, primary: Some(id), db: self }
130 }
131
132 pub fn update(&self, iterator: &Iterator, value: &dyn MultiIndexValue, payer: Name) {
134 let mut enc = Encoder::new(value.size());
135 value.pack(&mut enc);
136 let data = enc.get_bytes();
137 db_update_i64(iterator.i, payer.value(), data.as_ptr(), data.len() as u32);
138 }
139
140 pub fn remove(&self, iterator: &Iterator) {
142 db_remove_i64(iterator.i);
143 }
144
145 pub fn get(&self, iterator: &Iterator) -> Option<Box<dyn MultiIndexValue>> {
147 if !iterator.is_ok() {
148 return None;
149 }
150
151 let data = db_get_i64(iterator.i);
152 return Some((self.unpacker)(&data));
153 }
154
155 pub fn next(&self, iterator: &Iterator) -> Iterator {
157 let mut primary = 0;
158 let it = db_next_i64(iterator.i, &mut primary);
159 if it >= 0 {
160 Iterator { i: it, primary: Some(primary), db: self }
161 } else {
162 Iterator { i: it, primary: None, db: self }
163 }
164 }
165
166 pub fn previous(&self, iterator: &Iterator) -> Iterator {
168 let mut primary = 0;
169 let it = db_previous_i64(iterator.i, &mut primary);
170 if it >= 0 {
171 Iterator { i: it, primary: Some(primary), db: self }
172 } else {
173 Iterator { i: it, primary: None, db: self }
174 }
175 }
176
177 pub fn find(&self, primary_key: u64) -> Iterator {
179 let it = db_find_i64(self.code, self.scope, self.table, primary_key);
180 Iterator { i: it, primary: Some(primary_key), db: self }
181 }
182
183 pub fn lower_bound(&self, id: u64) -> Iterator {
185 let it = db_lowerbound_i64(self.code, self.scope, self.table, id);
186 Iterator { i: it, primary: None, db: self }
187 }
188
189 pub fn upper_bound(&self, id: u64) -> Iterator {
191 let it = db_upperbound_i64(self.code, self.scope, self.table, id);
192 Iterator { i: it, primary: None, db: self }
193 }
194
195 pub fn end(&self) -> Iterator {
197 let it = db_end_i64(self.code, self.scope, self.table);
198 Iterator { i: it, primary: None, db: self }
199 }
200}
201
202pub struct MultiIndex {
204 pub code: Name,
206 pub scope: Name,
208 pub table: Name,
210 pub db: TableI64,
212 pub idxdbs: Vec<Box<dyn IdxTable>>,
214 pub unpacker: fn(&[u8]) -> Box<dyn MultiIndexValue>,
216}
217
218impl MultiIndex {
219 pub fn new(code: Name, scope: Name, table: Name, indices: &[SecondaryType], unpacker: fn(&[u8]) -> Box<dyn MultiIndexValue>) -> Self {
221 let mut idxdbs: Vec<Box<dyn IdxTable>> = Vec::new();
222 let mut i: usize = 0;
223 let idx_table = table.value() & 0xfffffffffffffff0;
224 for idx in indices {
225 match idx {
226 SecondaryType::Idx64 => idxdbs.push(
227 Box::new(Idx64Table::new(i, code, scope, Name::from_u64(idx_table + i as u64)))
228 ),
229 SecondaryType::Idx128 => idxdbs.push(
230 Box::new(Idx128Table::new(i, code, scope, Name::from_u64(idx_table + i as u64)))
231 ),
232 SecondaryType::Idx256 => idxdbs.push(
233 Box::new(Idx256Table::new(i, code, scope, Name::from_u64(idx_table + i as u64)))
234 ),
235 _ => panic!("unsupported secondary index type"),
236 }
237 i += 1;
238 }
239 MultiIndex {
240 code,
241 scope,
242 table,
243 db: TableI64::new(code, scope, table, unpacker),
244 idxdbs,
245 unpacker: unpacker,
246 }
247 }
248
249 pub fn store(&self, value: &dyn MultiIndexValue, payer: Name) -> Iterator {
251 let primary = value.get_primary();
252 for i in 0..self.idxdbs.len() {
253 let v2 = value.get_secondary_value(i);
254 self.idxdbs[i].store(primary, v2, payer);
255 }
256 let mut enc = Encoder::new(value.size());
257 value.pack(&mut enc);
258 let it = self.db.store(primary, enc.get_bytes(), payer);
259 return it;
260 }
261
262 pub fn update(&self, iterator: &Iterator, value: &dyn MultiIndexValue, payer: Name) {
264 check(iterator.is_ok(), "update: invalid iterator");
265 let primary = iterator.get_primary().unwrap();
266 for i in 0..self.idxdbs.len() {
267 let v2 = value.get_secondary_value(i);
268 let (it_secondary, secondary_value) = self.idxdbs[i].find_primary(primary);
269 if secondary_value == v2 {
270 continue;
271 }
272 self.idxdbs[i].update(&it_secondary, v2, payer);
273 }
274 self.db.update(iterator, value, payer);
275 }
276
277 pub fn set(&self, value: &dyn MultiIndexValue, payer: Name) {
278 let primary = value.get_primary();
279 let it = self.find(primary);
280 if it.is_ok() {
281 self.update(&it, value, payer);
282 } else {
283 self.store(value, payer);
284 }
285 }
286
287 pub fn remove(&self, iterator: &Iterator) {
289 if !iterator.is_ok() {
290 return;
291 }
292 let primary = iterator.get_primary().unwrap();
293
294 for i in 0..self.idxdbs.len() {
295 let (it_secondary, _) = self.idxdbs[i].find_primary(primary);
296 self.idxdbs[i].remove(&it_secondary);
297 }
298 self.db.remove(iterator);
299 }
300
301 pub fn get(&self, iterator: &Iterator) -> Option<Box<dyn MultiIndexValue>> {
303 if !iterator.is_ok() {
304 return None;
305 }
306
307 return self.db.get(iterator);
308 }
309
310 pub fn get_by_primary(&self, primary: u64) -> Option<Box<dyn MultiIndexValue>> {
312 let it = self.db.find(primary);
313 return self.get(&it);
314 }
315
316 pub fn next(&self, iterator: &Iterator) -> Iterator {
318 return self.db.next(iterator);
319 }
320
321 pub fn previous(&self, iterator: &Iterator) -> Iterator {
323 return self.db.previous(iterator);
324 }
325
326 pub fn find(&self, id: u64) -> Iterator {
328 return self.db.find(id);
329 }
330
331 pub fn lower_bound(&self, id: u64) -> Iterator {
333 return self.db.lower_bound(id);
334 }
335
336 pub fn upper_bound(&self, id: u64) -> Iterator {
338 return self.db.upper_bound(id);
339 }
340
341 pub fn end(&self) -> Iterator {
343 return self.db.end();
344 }
345
346 pub fn get_idx_db(&self, i: usize) -> &dyn IdxTable {
348 return self.idxdbs[i].as_ref();
349 }
350
351 pub fn idx_update(&self, it: &SecondaryIterator, value: SecondaryValue, payer: Name) {
353 check(it.is_ok(), "idx_update: invalid iterator");
354
355 let it_primary = self.find(it.primary);
356 let mut db_value = self.get(&it_primary).unwrap();
357 let idx_db = self.idxdbs[it.db_index].as_ref();
358 db_value.set_secondary_value(idx_db.get_db_index(), value);
359 self.update(&it_primary, db_value.as_ref(), payer);
360 idx_db.update(it, value, payer);
361 }
362}