rust_chain/
mi.rs

1use crate::db::*;
2use crate::name::{
3    Name,
4};
5
6// use crate::{
7//     check,
8// };
9
10use crate::{
11    vec::Vec,
12};
13
14use crate::{
15    check,
16    serializer::Packer,
17};
18
19use crate::boxed::Box;
20///
21pub struct MultiIndex<T>
22where T: PrimaryValueInterface + SecondaryValueInterface + Packer + Default
23{
24    ///
25    pub code: Name,
26    ///
27    pub scope: Name,
28    ///
29    pub table: Name,
30    ///
31    pub db: TableI64<T>,
32    ///
33    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    /// Creates a new instance of the MultiIndex struct.
41    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    /// Stores a given value into the table with a specified payer.
86    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    /// Searches for a record with a given primary key and returns an iterator.
97    pub fn find(&self, id: u64) -> Iterator<T> {
98        return self.db.find(id);
99    }
100
101    /// Updates the record pointed by the given iterator with a new value and payer.
102    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    /// Removes the record pointed by the given iterator.
117    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    /// Retrieves the value pointed by the given iterator.
128    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    /// Retrieves the value by its primary key.
136    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    /// Returns an iterator pointing to the next record.
142    pub fn next(&self, iterator: &Iterator<T>) -> Iterator<T> {
143        return self.db.next(iterator);
144    }
145
146    /// Returns an iterator pointing to the previous record.
147    pub fn previous(&self, iterator: &Iterator<T>) -> Iterator<T> {
148        return self.db.previous(iterator);
149    }
150
151    /// Returns an iterator pointing to the first record that is not less than the given primary key.
152    pub fn lower_bound(&self, id: u64) -> Iterator<T> {
153        return self.db.lower_bound(id);
154    }
155
156    /// Returns an iterator pointing to the first record that is greater than the given primary key.
157    pub fn upper_bound(&self, id: u64) -> Iterator<T> {
158        return self.db.upper_bound(id);
159    }
160
161    /// Returns an iterator pointing to the end of the table.
162    pub fn end(&self) -> Iterator<T> {
163        return self.db.end();
164    }
165
166    /// Retrieves a reference to the secondary index database at the given index.
167    pub fn get_idx_db(&self, i: usize) -> &dyn IdxTable {
168        return self.idxdbs[i].as_ref();
169    }
170
171    /// Updates the secondary index with a given iterator, value, and payer.
172    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}