1use crate::{runtime};
2use crate::spread::SpreadLayout;
3use crate::prelude::{Vec};
4use crate::collections::entry_state::{ValueWrapper, EntryState};
5use scale::{Decode, Encode};
6use alloc::collections::BTreeMap;
7use alloc::collections::btree_map::Entry;
8
9pub struct HyperList<T> {
10 size: u32, list_name: Vec<u8>,
12 storage_prefix: Vec<u8>,
14 cache_values: BTreeMap<i64, ValueWrapper<T>>,
16}
17
18static mut DEPLOY_LIST_ID :i32 = 0;
19
20fn get_id() -> i32 {
21 unsafe {
22 DEPLOY_LIST_ID = DEPLOY_LIST_ID + 1;
23 DEPLOY_LIST_ID.clone()
24 }
25}
26
27impl<T> HyperList<T> {
28 pub fn new() -> Self {
29 let new_id = get_id();
30 Self {
31 size: 0,
32 list_name: new_id.encode(),
33 storage_prefix: "_".as_bytes().to_vec(),
34 cache_values: BTreeMap::<i64, ValueWrapper<T>>::new(),
35 }
36 }
37}
38
39impl<T> HyperList<T>
40 where
41 T: Encode + Decode,
42{
43
44 fn get_by_key(&mut self, key: i64) -> Option<&T> {
46 match self.cache_values.entry(key) {
47 Entry::Vacant(entry) => {
49 let storage_key = key.encode();let value = runtime::storage_read(storage_key.as_slice(), self.storage_prefix.as_slice());
52 match value {
53 Some(v) => {
55 let input = &mut &v[..];
56 let res: T = T::decode(input).unwrap();
57 let wrapper = ValueWrapper::new(res, EntryState::NoChanged);
58 let va = entry.insert(wrapper);
60 va.value.as_ref()
61 }
62 None => {
64 None
65 }
66 }
67 }
68 Entry::Occupied(entry) => {
70 let ent = entry.into_mut();
71 if ent.state == EntryState::Deleted {
73 return None;
74 }
75 ent.value.as_ref()
76 }
77 }
78 }
79
80 fn get_mut_by_key(&mut self, key: i64) -> Option<&mut T> {
82 match self.cache_values.entry(key) {
83 Entry::Vacant(entry) => {
85 let storage_key = key.encode();
86 let value = runtime::storage_read(storage_key.as_slice(), self.storage_prefix.as_slice());
87 match value {
88 Some(v) => {
90 let input = &mut &v[..];
91 let res: T = T::decode(input).unwrap();
92 let wrapper = ValueWrapper::new(res, EntryState::Changed);
93 let va = entry.insert(wrapper);
95 va.value.as_mut()
96 }
97 None => {
99 None
100 }
101 }
102 }
103 Entry::Occupied(entry) => {
105 let ent = entry.into_mut();
106 if ent.state == EntryState::Deleted {
107 return None;
108 }
109 ent.state = EntryState::Changed;
110 ent.value.as_mut()
111 }
112 }
113 }
114 fn insert_by_key(&mut self, key: i64, val: T) -> Option<T>{
117 match self.get_mut_by_key(key) {
118 Some(v)=>{
120 let old_value = core::mem::replace(v, val);
121 Some(old_value)
122 }
123 None=>{
125 let wrapper = ValueWrapper::new(val, EntryState::Changed);
126 self.cache_values.insert(key, wrapper);
128 self.size += 1;
130 None
132 }
133 }
134 }
135 fn remove_by_key(&mut self, key: i64) -> Option<T> {
137 match self.cache_values.entry(key) {
139 Entry::Vacant(entry) => {
141 let storage_key = key.encode();
142 let value = runtime::storage_read(storage_key.as_slice(), self.storage_prefix.as_slice());
143 match value {
144 Some(v) => {
145 let input = &mut &v[..];
146 let res: T = T::decode(input).unwrap();
147 let wrapper = ValueWrapper::new_empty_value(EntryState::Deleted);
148 entry.insert(wrapper);
150 self.size -= 1; Some(res)
152 }
153 None => {
154 None
155 }
156 }
157 }
158 Entry::Occupied(mut entry) => {
160 let old = entry.insert(ValueWrapper::new_empty_value(EntryState::Deleted));
162 if old.state == EntryState::Deleted {
163 return None;
164 }
165 self.size -= 1; return old.value;
167 }
168 }
169 }
170
171 pub fn push(&mut self, ele: T) -> bool {
173 self.insert(self.size, ele)
174 }
175
176 pub fn insert(&mut self, index: u32, ele: T) -> bool {
179 if index > self.size {
181 return false;
182 }
183 match runtime::add_list_key(self.list_name.as_slice(), index) {
185 Some(key) => {
186 self.insert_by_key(key, ele);
187 true
188 }
189 None => {
190 false
191 }
192 }
193 }
194
195 pub fn get(&mut self, index: u32) -> Option<&T> {
197 if index >= self.size {
199 return None;
200 }
201 match runtime::get_list_key(self.list_name.as_slice(), index) {
202 Some(key) => {
203 self.get_by_key(key)
204 }
205 None => {
206 None
207 }
208 }
209 }
210
211 pub fn get_mut(&mut self, index: u32) -> Option<&mut T> {
212 if index >= self.size {
213 return None;
214 }
215 match runtime::get_list_key(self.list_name.as_slice(), index){
216 Some(key) => {
217 self.get_mut_by_key(key)
218 }
219 None => {
220 None
221 }
222 }
223 }
224
225 pub fn is_empty(&self) -> bool {
226 self.size == 0
227 }
228
229 pub fn pop(&mut self) -> Option<T> {
230 if self.len() == 0 {
231 None
232 } else {
233 self.remove(self.len() - 1)
234 }
235 }
236
237 pub fn remove(&mut self, index: u32) -> Option<T> {
240 if index >= self.size {
242 return None;
243 }
244 match runtime::remove_list_key(self.list_name.as_slice(), index) {
245 Some(key) => {
246 self.remove_by_key(key)
247 }
248 None => {
249 None
250 }
251 }
252 }
253
254 pub fn len(&self) -> u32 {
255 self.size
256 }
257
258 pub fn replace(&mut self, index: u32, ele :T) -> Option<T> {
260 if index >= self.size {
262 return None;
263 }
264 match runtime::get_list_key(self.list_name.as_slice(), index) {
265 Some(key) => {
266 self.insert_by_key(key, ele)
267 }
268 None => {
269 None
270 }
271 }
272 }
273}
274
275impl<T> Default for HyperList<T> {
276 fn default() -> Self {
277 HyperList::new()
278 }
279}
280
281impl<T> SpreadLayout for HyperList<T>
282 where
283 T: Encode + Decode
284{
285 fn read_ledger(list_name: &[u8], _: &[u8]) -> Self {
287 let mut list: HyperList<T> = HyperList::<T>::new();
288 list.list_name = Vec::from(list_name);
289 list.storage_prefix = Vec::from([list_name, "@K".as_bytes()].concat());
291 let root_info = runtime::storage_read(list_name, "@HyperList".as_bytes()).unwrap();
293 list.size = <u32 as scale::Decode>::decode(&mut &root_info[0..4]).unwrap();
295 list
296 }
297
298 fn write_ledger(&self, list_name: &[u8], deploy_flag: &[u8]) {
299 if deploy_flag == "deploy".as_bytes() {
301 runtime::write_list_keys_back(self.list_name.as_slice(), list_name, self.size)
303 } else {
304 runtime::write_list_keys_back("".as_bytes(), list_name, self.size);
305 }
306 let storage_prefix = Vec::from([list_name, "@K".as_bytes()].concat());
308 self.cache_values.iter().for_each(|(key, value)| {
309 match value.state {
310 EntryState::Changed => {
311 let storage_key = key.encode();
312 let storage_value = value.value.as_ref().unwrap().encode();
313 runtime::storage_write(storage_key.as_slice(), storage_prefix.as_slice(), storage_value.as_slice());
314 }
315 EntryState::Deleted => {
316 let storage_key = key.encode();
317 runtime::storage_delete(storage_key.as_slice(), storage_prefix.as_slice());
318 }
319 _ => {}
320 }
321 });
322
323 }
324}
325
326#[cfg(test)]
327mod test {
328 use crate::collections::hyper_list::HyperList;
329 use crate::spread::SpreadLayout;
330 use crate::runtime;
331 use scale::Encode;
332 use scale::Decode;
333 #[test]
334 fn use_list_normal() {
335 let _mock = fvm_mock::build_runtime();
336 let list: HyperList<String> = HyperList::new();
338 list.write_ledger("list".as_bytes(), "deploy".as_bytes());
339
340 let mut list: HyperList<String> = HyperList::read_ledger("list".as_bytes(), "invoke".as_bytes());
342 let res = list.insert(0, String::from("123"));
343 assert_eq!(res, true);
344 let res = list.get(0).unwrap();
345 assert_eq!(res, &String::from("123"));
346 }
347
348 #[test]
349 fn list_add_set() {
350 let _mock = fvm_mock::build_runtime();
351 let list: HyperList<i32> = HyperList::new();
353 list.write_ledger("list".as_bytes(), "deploy".as_bytes());
354
355 let mut list: HyperList<i32> = HyperList::read_ledger("list".as_bytes(), "invoke".as_bytes());
357 for i in 0..100 {
358 let res = list.insert(i, (i+100) as i32);
359 assert_eq!(res, true);
360 }
361 list.write_ledger(list.list_name.as_slice(), "invoke".as_bytes());
363 list.cache_values.clear();
365 for i in 0..100 {
367 let res = list.get(i);
368 assert_eq!(res, Some(&((i+100) as i32)));
369 }
370 list.write_ledger(list.list_name.as_slice(), "invoke".as_bytes());
371 }
372
373
374 #[test]
375 fn list_delete() {
376 #[derive(Encode, Decode, Eq, PartialEq, Debug)]
377 struct Student {
378 id: u32,
379 name: String,
380 }
381 let _mock = fvm_mock::build_runtime();
382 let list: HyperList<Student> = HyperList::new();
384 list.write_ledger("list".as_bytes(), "deploy".as_bytes());
385
386 let mut list: HyperList<Student> = HyperList::read_ledger("list".as_bytes(), "invoke".as_bytes());
388 let res = list.insert(0, Student { id: 1, name: String::from("s1") });
390 assert_eq!(res, true);
391 let res = list.insert(0, Student { id: 0, name: String::from("s0") });
392 assert_eq!(res, true);
393 assert_eq!(list.len(), 2);
394
395 let old_value = list.remove(0);
397 assert_eq!(old_value, Some(Student{id: 0, name: String::from("s0")}));
398 assert_eq!(list.get(1), None);
399 assert_eq!(list.is_empty(), false);
400 assert_eq!(list.get(0), Some(&Student { id: 1, name: String::from("s1") }));
401
402 list.storage_prefix = [list.list_name.as_slice(), "@K".as_bytes()].concat().to_vec();
404 list.write_ledger(list.list_name.as_slice(), "invoke".as_bytes());
405 list.cache_values.clear();
406 assert_eq!(runtime::storage_read(1i64.encode().as_slice(), list.storage_prefix.as_slice()), None);
408 assert_eq!(runtime::storage_read(0i64.encode().as_slice(), list.storage_prefix.as_slice()), Some(Student { id: 1, name: String::from("s1") }.encode()));
409 }
410
411 #[test]
412 fn list_operate_many_times() {
413 let _mock = fvm_mock::build_runtime();
414 let list: HyperList<i32> = HyperList::new();
416 list.write_ledger("list".as_bytes(), "deploy".as_bytes());
417
418 let mut list: HyperList<i32> = HyperList::read_ledger("list".as_bytes(), "invoke".as_bytes());
420 assert_eq!(list.insert(0, 54), true);
422 assert_eq!(list.insert(0, 56), true);
423 assert_eq!(list.insert(4, 33), false);
424 assert_eq!(list.get(0), Some(&56));
425 assert_eq!(list.get_mut(0), Some(&mut 56));
426 list.write_ledger(list.list_name.as_slice(), "invoke".as_bytes());
428 list.cache_values.clear();
429
430 assert_eq!(list.replace(0, 101), Some(56));
432 assert_eq!(list.replace(1, 111), Some(54));
433 assert_eq!(list.replace(0, 2331), Some(101));
434 assert_eq!(list.replace(0, 100), Some(2331));
435 list.write_ledger(list.list_name.as_slice(), "invoke".as_bytes());
437 list.cache_values.clear();
438
439 assert_eq!(list.remove(1), Some(111));
441 assert_eq!(list.remove(0), Some(100));
442 assert_eq!(list.remove(0), None);
443
444 assert_eq!(list.is_empty(), true);
445 list.write_ledger(list.list_name.as_slice(), "invoke".as_bytes());
447 list.cache_values.clear();
448
449 assert_eq!(list.push(77), true);
451 assert_eq!(list.push(88), true);
452 assert_eq!(list.len(), 2);
453
454 list.write_ledger(list.list_name.as_slice(), "invoke".as_bytes());
456 let root = vec![0;24];
457 let first_four = 2.encode();
458 let root = [ first_four, root].concat();
459 runtime::storage_write(list.list_name.as_slice(), "@HyperList".as_bytes(), root.as_slice());
460
461 let new_list: HyperList<i64> = HyperList::read_ledger(list.list_name.as_slice(), "".as_bytes());
463 assert_eq!(list.list_name, new_list.list_name);
464 assert_eq!(list.storage_prefix, new_list.storage_prefix);
465 assert_eq!(list.size, new_list.size);
466 }
467}