rust_chain/
mi_not_generic.rs

1use crate::db::{
2    Idx64Table,
3    Idx128Table,
4    Idx256Table,
5    // IdxF128Table,
6    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
39///
40pub struct Iterator<'a> {
41    ///
42    pub i: i32,
43    primary: Option<u64>,
44    db: &'a TableI64,
45}
46
47impl<'a> Iterator<'a> {
48    ///
49    pub fn new(i: i32, primary: Option<u64>, db: &'a TableI64) -> Self {
50        Self { i, primary, db }
51    }
52
53    ///
54    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    ///
81    pub fn is_ok(&self) -> bool {
82        self.i >= 0
83    }
84
85    ///
86    pub fn is_end(&self) -> bool {
87        return self.i < -1;
88    }
89
90    ///
91    pub fn expect(self, msg: &str) -> Self {
92        check(self.is_ok(), msg);            
93        return self;
94    }
95
96    ///
97    pub fn expect_not_ok(self, msg: &str) -> Self {
98        check(!self.is_ok(), msg);            
99        return self;
100    }
101}
102
103
104///
105pub struct TableI64 {
106    ///
107    pub code: u64,
108    ///
109    pub scope: u64,
110    ///
111    pub table: u64,
112    unpacker: fn(&[u8]) -> Box<dyn MultiIndexValue>,
113}
114
115impl TableI64 {
116    ///
117    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    ///
127    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    ///
133    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    ///
141    pub fn remove(&self, iterator: &Iterator) {
142        db_remove_i64(iterator.i);
143    }
144
145    ///
146    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    ///
156    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    ///
167    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    ///
178    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    ///
184    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    ///
190    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    ///
196    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
202///
203pub struct MultiIndex {
204    ///
205    pub code: Name,
206    ///
207    pub scope: Name,
208    ///
209    pub table: Name,
210    ///
211    pub db: TableI64,
212    ///
213    pub idxdbs: Vec<Box<dyn IdxTable>>,
214    ///
215    pub unpacker: fn(&[u8]) -> Box<dyn MultiIndexValue>,
216}
217
218impl MultiIndex {
219    ///
220    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    ///
250    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    ///
263    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    ///
288    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    ///
302    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    ///
311    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    ///
317    pub fn next(&self, iterator: &Iterator) -> Iterator {
318        return self.db.next(iterator);
319    }
320
321    ///
322    pub fn previous(&self, iterator: &Iterator) -> Iterator {
323        return self.db.previous(iterator);
324    }
325
326    ///
327    pub fn find(&self, id: u64) -> Iterator {
328        return self.db.find(id);
329    }
330
331    ///
332    pub fn lower_bound(&self, id: u64) -> Iterator {
333        return self.db.lower_bound(id);
334    }
335
336    ///
337    pub fn upper_bound(&self, id: u64) -> Iterator {
338        return self.db.upper_bound(id);
339    }
340
341    ///
342    pub fn end(&self) -> Iterator {
343        return self.db.end();
344    }
345
346    ///
347    pub fn get_idx_db(&self, i: usize) -> &dyn IdxTable {
348        return self.idxdbs[i].as_ref();
349    }
350
351    ///
352    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}