1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use crate::{ByteArray32, StorageOutcome};
use borsh::{BorshDeserialize, BorshSerialize};
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, BorshSerialize, BorshDeserialize)]
pub struct StackMemDB<const S: usize> {
storage: [ByteArray32; S],
}
impl<const S: usize> StackMemDB<S> {
pub fn new() -> Self {
StackMemDB {
storage: [[0; 32]; S],
}
}
pub fn storage_len(&self) -> usize {
self.storage.len()
}
pub fn insert(&mut self, value: ByteArray32) -> StorageOutcome {
if self.storage[0] != [0_u8; 32] {
return StorageOutcome::CapacityExceeded;
}
match self.find(value) {
None => {
self.storage[0] = value;
self.storage.sort_unstable();
StorageOutcome::Inserted(value)
}
Some(value) => StorageOutcome::ValueExists(value),
}
}
pub fn update(&mut self, old_value: ByteArray32, new_value: ByteArray32) -> StorageOutcome {
match self.find(new_value) {
None => (),
Some(value) => return StorageOutcome::ValueExists(value),
}
match self.find_and_index(old_value) {
(Some(index_found), _) => {
self.storage[index_found] = new_value;
StorageOutcome::Updated(old_value)
}
(None, _) => StorageOutcome::NonExistentValue(old_value),
}
}
pub fn remove(&mut self, value: ByteArray32) -> StorageOutcome {
match self.find_and_index(value) {
(Some(index_found), _) => {
self.storage[index_found] = [0_u8; 32];
self.storage.sort_unstable();
StorageOutcome::Zeroed(value)
}
(None, _) => StorageOutcome::NonExistentValue(value),
}
}
pub fn find(&self, value: ByteArray32) -> Option<ByteArray32> {
match self.storage.binary_search(&value) {
Err(_) => None,
Ok(_) => Some(value),
}
}
pub fn find_and_index(&self, value: ByteArray32) -> (Option<usize>, Option<ByteArray32>) {
match self.storage.binary_search(&value) {
Err(_) => (None, None),
Ok(index_found) => (Some(index_found), Some(value)),
}
}
}
#[cfg(feature = "heap_available")]
use core::fmt;
#[cfg(feature = "heap_available")]
impl<const S: usize> fmt::Debug for StackMemDB<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let storage = self
.storage
.iter()
.map(|value| hex::encode(value))
.collect::<Vec<String>>();
f.debug_struct("StackMemDb")
.field("storage", &storage)
.finish()
}
}