1use std::convert::TryInto;
7use std::marker::PhantomData;
8
9use serde::{de::DeserializeOwned, Serialize};
10
11use cosmwasm_std::{ReadonlyStorage, StdError, StdResult, Storage};
12
13use hermit_toolkit_serialization::{Bincode2, Serde};
14
15const LEN_KEY: &[u8] = b"len";
16
17#[derive(Debug)]
21pub struct AppendStoreMut<'a, T, S, Ser = Bincode2>
22 where
23 T: Serialize + DeserializeOwned,
24 S: Storage,
25 Ser: Serde,
26{
27 storage: &'a mut S,
28 item_type: PhantomData<*const T>,
29 serialization_type: PhantomData<*const Ser>,
30 len: u32,
31}
32
33impl<'a, T, S> AppendStoreMut<'a, T, S, Bincode2>
34 where
35 T: Serialize + DeserializeOwned,
36 S: Storage,
37{
38 pub fn attach_or_create(storage: &'a mut S) -> StdResult<Self> {
43 AppendStoreMut::attach_or_create_with_serialization(storage, Bincode2)
44 }
45
46 pub fn attach(storage: &'a mut S) -> Option<StdResult<Self>> {
51 AppendStoreMut::attach_with_serialization(storage, Bincode2)
52 }
53}
54
55impl<'a, T, S, Ser> AppendStoreMut<'a, T, S, Ser>
56 where
57 T: Serialize + DeserializeOwned,
58 S: Storage,
59 Ser: Serde,
60{
61 pub fn attach_or_create_with_serialization(storage: &'a mut S, _ser: Ser) -> StdResult<Self> {
66 if let Some(len_vec) = storage.get(LEN_KEY) {
67 Self::new(storage, &len_vec)
68 } else {
69 let len_vec = 0_u32.to_be_bytes();
70 storage.set(LEN_KEY, &len_vec);
71 Self::new(storage, &len_vec)
72 }
73 }
74
75 pub fn attach_with_serialization(storage: &'a mut S, _ser: Ser) -> Option<StdResult<Self>> {
81 let len_vec = storage.get(LEN_KEY)?;
82 Some(Self::new(storage, &len_vec))
83 }
84
85 fn new(storage: &'a mut S, len_vec: &[u8]) -> StdResult<Self> {
86 let len_array = len_vec
87 .try_into()
88 .map_err(|err| StdError::parse_err("u32", err))?;
89 let len = u32::from_be_bytes(len_array);
90
91 Ok(Self {
92 storage,
93 item_type: PhantomData,
94 serialization_type: PhantomData,
95 len,
96 })
97 }
98
99 pub fn len(&self) -> u32 {
100 self.len
101 }
102
103 pub fn is_empty(&self) -> bool {
104 self.len == 0
105 }
106
107 pub fn storage(&mut self) -> &mut S {
108 self.storage
109 }
110
111 pub fn readonly_storage(&self) -> &S {
112 self.storage
113 }
114
115 pub fn iter(&self) -> Iter<T, S, Ser> {
117 self.as_readonly().iter()
118 }
119
120 pub fn get_at(&self, pos: u32) -> StdResult<T> {
125 self.as_readonly().get_at(pos)
126 }
127
128 fn get_at_unchecked(&self, pos: u32) -> StdResult<T> {
129 self.as_readonly().get_at_unchecked(pos)
130 }
131
132 pub fn set_at(&mut self, pos: u32, item: &T) -> StdResult<()> {
137 if pos >= self.len {
138 return Err(StdError::generic_err("AppendStorage access out of bounds"));
139 }
140 self.set_at_unchecked(pos, item)
141 }
142
143 fn set_at_unchecked(&mut self, pos: u32, item: &T) -> StdResult<()> {
144 let serialized = Ser::serialize(item)?;
145 self.storage.set(&pos.to_be_bytes(), &serialized);
146 Ok(())
147 }
148
149 pub fn push(&mut self, item: &T) -> StdResult<()> {
153 self.set_at_unchecked(self.len, item)?;
154 self.set_length(self.len + 1);
155 Ok(())
156 }
157
158 pub fn pop(&mut self) -> StdResult<T> {
160 if let Some(len) = self.len.checked_sub(1) {
161 let item = self.get_at_unchecked(len);
162 self.set_length(len);
163 item
164 } else {
165 Err(StdError::generic_err("Can not pop from empty AppendStore"))
166 }
167 }
168
169 pub fn clear(&mut self) {
171 self.set_length(0);
172 }
173
174 fn set_length(&mut self, len: u32) {
176 self.storage.set(LEN_KEY, &len.to_be_bytes());
177 self.len = len;
178 }
179
180 fn as_readonly(&self) -> AppendStore<T, S, Ser> {
182 AppendStore {
183 storage: self.storage,
184 item_type: self.item_type,
185 serialization_type: self.serialization_type,
186 len: self.len,
187 }
188 }
189}
190
191#[derive(Debug)]
217pub struct AppendStore<'a, T, S, Ser = Bincode2>
218 where
219 T: Serialize + DeserializeOwned,
220 S: ReadonlyStorage,
221 Ser: Serde,
222{
223 storage: &'a S,
224 item_type: PhantomData<*const T>,
225 serialization_type: PhantomData<*const Ser>,
226 len: u32,
227}
228
229impl<'a, T, S> AppendStore<'a, T, S, Bincode2>
230 where
231 T: Serialize + DeserializeOwned,
232 S: ReadonlyStorage,
233{
234 pub fn attach(storage: &'a S) -> Option<StdResult<Self>> {
239 AppendStore::attach_with_serialization(storage, Bincode2)
240 }
241}
242
243impl<'a, T, S, Ser> AppendStore<'a, T, S, Ser>
244 where
245 T: Serialize + DeserializeOwned,
246 S: ReadonlyStorage,
247 Ser: Serde,
248{
249 pub fn attach_with_serialization(storage: &'a S, _ser: Ser) -> Option<StdResult<Self>> {
255 let len_vec = storage.get(LEN_KEY)?;
256 Some(AppendStore::new(storage, len_vec))
257 }
258
259 fn new(storage: &'a S, len_vec: Vec<u8>) -> StdResult<Self> {
260 let len_array = len_vec
261 .as_slice()
262 .try_into()
263 .map_err(|err| StdError::parse_err("u32", err))?;
264 let len = u32::from_be_bytes(len_array);
265
266 Ok(Self {
267 storage,
268 item_type: PhantomData,
269 serialization_type: PhantomData,
270 len,
271 })
272 }
273
274 pub fn len(&self) -> u32 {
275 self.len
276 }
277
278 pub fn is_empty(&self) -> bool {
279 self.len == 0
280 }
281
282 pub fn readonly_storage(&self) -> &S {
283 self.storage
284 }
285
286 pub fn iter(&self) -> Iter<'a, T, S, Ser> {
288 Iter {
289 storage: AppendStore::clone(self),
290 start: 0,
291 end: self.len,
292 }
293 }
294
295 pub fn get_at(&self, pos: u32) -> StdResult<T> {
300 if pos >= self.len {
301 return Err(StdError::generic_err("AppendStorage access out of bounds"));
302 }
303 self.get_at_unchecked(pos)
304 }
305
306 fn get_at_unchecked(&self, pos: u32) -> StdResult<T> {
307 let serialized = self.storage.get(&pos.to_be_bytes()).ok_or_else(|| {
308 StdError::generic_err(format!("No item in AppendStorage at position {}", pos))
309 })?;
310 Ser::deserialize(&serialized)
311 }
312}
313
314impl<'a, T, S, Ser> IntoIterator for AppendStore<'a, T, S, Ser>
315 where
316 T: Serialize + DeserializeOwned,
317 S: ReadonlyStorage,
318 Ser: Serde,
319{
320 type Item = StdResult<T>;
321 type IntoIter = Iter<'a, T, S, Ser>;
322
323 fn into_iter(self) -> Iter<'a, T, S, Ser> {
324 let end = self.len;
325 Iter {
326 storage: self,
327 start: 0,
328 end,
329 }
330 }
331}
332
333impl<'a, T, S, Ser> Clone for AppendStore<'a, T, S, Ser>
335 where
336 T: Serialize + DeserializeOwned,
337 S: ReadonlyStorage,
338 Ser: Serde,
339{
340 fn clone(&self) -> Self {
341 Self {
342 storage: self.storage,
343 item_type: self.item_type,
344 serialization_type: self.serialization_type,
345 len: self.len,
346 }
347 }
348}
349
350#[derive(Debug)]
354pub struct Iter<'a, T, S, Ser>
355 where
356 T: Serialize + DeserializeOwned,
357 S: ReadonlyStorage,
358 Ser: Serde,
359{
360 storage: AppendStore<'a, T, S, Ser>,
361 start: u32,
362 end: u32,
363}
364
365impl<'a, T, S, Ser> Iterator for Iter<'a, T, S, Ser>
366 where
367 T: Serialize + DeserializeOwned,
368 S: ReadonlyStorage,
369 Ser: Serde,
370{
371 type Item = StdResult<T>;
372
373 fn next(&mut self) -> Option<Self::Item> {
374 if self.start >= self.end {
375 return None;
376 }
377 let item = self.storage.get_at(self.start);
378 self.start += 1;
379 Some(item)
380 }
381
382 fn size_hint(&self) -> (usize, Option<usize>) {
384 let len = (self.end - self.start) as usize;
385 (len, Some(len))
386 }
387
388 fn nth(&mut self, n: usize) -> Option<Self::Item> {
395 self.start = self.start.saturating_add(n as u32);
396 self.next()
397 }
398}
399
400impl<'a, T, S, Ser> DoubleEndedIterator for Iter<'a, T, S, Ser>
401 where
402 T: Serialize + DeserializeOwned,
403 S: ReadonlyStorage,
404 Ser: Serde,
405{
406 fn next_back(&mut self) -> Option<Self::Item> {
407 if self.start >= self.end {
408 return None;
409 }
410 self.end -= 1;
411 let item = self.storage.get_at(self.end);
412 Some(item)
413 }
414
415 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
422 self.end = self.end.saturating_sub(n as u32);
423 self.next_back()
424 }
425}
426
427impl<'a, T, S, Ser> ExactSizeIterator for Iter<'a, T, S, Ser>
429 where
430 T: Serialize + DeserializeOwned,
431 S: ReadonlyStorage,
432 Ser: Serde,
433{
434}
435
436#[cfg(test)]
437mod tests {
438 use cosmwasm_std::testing::MockStorage;
439
440 use hermit_toolkit_serialization::Json;
441
442 use super::*;
443
444 #[test]
445 fn test_push_pop() -> StdResult<()> {
446 let mut storage = MockStorage::new();
447 let mut append_store = AppendStoreMut::attach_or_create(&mut storage)?;
448 append_store.push(&1234)?;
449 append_store.push(&2143)?;
450 append_store.push(&3412)?;
451 append_store.push(&4321)?;
452
453 assert_eq!(append_store.pop(), Ok(4321));
454 assert_eq!(append_store.pop(), Ok(3412));
455 assert_eq!(append_store.pop(), Ok(2143));
456 assert_eq!(append_store.pop(), Ok(1234));
457 assert!(append_store.pop().is_err());
458
459 Ok(())
460 }
461
462 #[test]
463 fn test_iterator() -> StdResult<()> {
464 let mut storage = MockStorage::new();
465 let mut append_store = AppendStoreMut::attach_or_create(&mut storage)?;
466 append_store.push(&1234)?;
467 append_store.push(&2143)?;
468 append_store.push(&3412)?;
469 append_store.push(&4321)?;
470
471 let mut iter = append_store.iter();
473 assert_eq!(iter.next(), Some(Ok(1234)));
474 assert_eq!(iter.next(), Some(Ok(2143)));
475 assert_eq!(iter.next(), Some(Ok(3412)));
476 assert_eq!(iter.next(), Some(Ok(4321)));
477 assert_eq!(iter.next(), None);
478
479 let mut iter = append_store.iter();
480 assert_eq!(iter.next(), Some(Ok(1234)));
481 assert_eq!(iter.next(), Some(Ok(2143)));
482 assert_eq!(iter.next(), Some(Ok(3412)));
483 assert_eq!(iter.next(), Some(Ok(4321)));
484 assert_eq!(iter.next(), None);
485
486 let mut iter = append_store.iter().skip(2);
488 assert_eq!(iter.next(), Some(Ok(3412)));
489 assert_eq!(iter.next(), Some(Ok(4321)));
490 assert_eq!(iter.next(), None);
491
492 Ok(())
493 }
494
495 #[test]
496 fn test_reverse_iterator() -> StdResult<()> {
497 let mut storage = MockStorage::new();
498 let mut append_store = AppendStoreMut::attach_or_create(&mut storage)?;
499 append_store.push(&1234)?;
500 append_store.push(&2143)?;
501 append_store.push(&3412)?;
502 append_store.push(&4321)?;
503
504 let mut iter = append_store.iter().rev();
505 assert_eq!(iter.next(), Some(Ok(4321)));
506 assert_eq!(iter.next(), Some(Ok(3412)));
507 assert_eq!(iter.next(), Some(Ok(2143)));
508 assert_eq!(iter.next(), Some(Ok(1234)));
509 assert_eq!(iter.next(), None);
510
511 let mut iter = append_store.iter().rev();
513 assert_eq!(iter.next(), Some(Ok(4321)));
514 assert_eq!(iter.next(), Some(Ok(3412)));
515 assert_eq!(iter.next(), Some(Ok(2143)));
516 assert_eq!(iter.next(), Some(Ok(1234)));
517 assert_eq!(iter.next(), None);
518
519 let mut iter = append_store.iter().rev().skip(2);
521 assert_eq!(iter.next(), Some(Ok(2143)));
522 assert_eq!(iter.next(), Some(Ok(1234)));
523 assert_eq!(iter.next(), None);
524
525 let mut iter = append_store.iter().skip(2).rev();
527 assert_eq!(iter.next(), Some(Ok(4321)));
528 assert_eq!(iter.next(), Some(Ok(3412)));
529 assert_eq!(iter.next(), None);
530
531 Ok(())
532 }
533
534 #[test]
535 fn test_attach_to_wrong_location() {
536 let mut storage = MockStorage::new();
537 assert!(AppendStore::<u8, _>::attach(&storage).is_none());
538 assert!(AppendStoreMut::<u8, _>::attach(&mut storage).is_none());
539 }
540
541 #[test]
542 fn test_serializations() -> StdResult<()> {
543 let mut storage = MockStorage::new();
545
546 let mut append_store = AppendStoreMut::attach_or_create(&mut storage)?;
547 append_store.push(&1234)?;
548
549 let bytes = append_store.readonly_storage().get(&0_u32.to_be_bytes());
550 assert_eq!(bytes, Some(vec![210, 4, 0, 0]));
551
552 let mut storage = MockStorage::new();
554 let mut append_store =
555 AppendStoreMut::attach_or_create_with_serialization(&mut storage, Json)?;
556 append_store.push(&1234)?;
557 let bytes = append_store.readonly_storage().get(&0_u32.to_be_bytes());
558 assert_eq!(bytes, Some(b"1234".to_vec()));
559
560 Ok(())
561 }
562}