snowbridge_core/
ringbuffer.rs
1use codec::FullCodec;
4use core::{cmp::Ord, marker::PhantomData, ops::Add};
5use frame_support::storage::{types::QueryKindTrait, StorageMap, StorageValue};
6use sp_core::{Get, GetDefault};
7use sp_runtime::traits::{One, Zero};
8
9pub trait RingBufferMap<Key, Value, QueryKind>
11where
12 Key: FullCodec,
13 Value: FullCodec,
14 QueryKind: QueryKindTrait<Value, GetDefault>,
15{
16 fn insert(k: Key, v: Value);
18
19 fn contains_key(k: Key) -> bool;
21
22 fn get(k: Key) -> QueryKind::Query;
24}
25
26pub struct RingBufferMapImpl<Index, B, CurrentIndex, Intermediate, M, QueryKind>(
27 PhantomData<(Index, B, CurrentIndex, Intermediate, M, QueryKind)>,
28);
29
30impl<Key, Value, Index, B, CurrentIndex, Intermediate, M, QueryKind>
32 RingBufferMap<Key, Value, QueryKind>
33 for RingBufferMapImpl<Index, B, CurrentIndex, Intermediate, M, QueryKind>
34where
35 Key: FullCodec + Clone,
36 Value: FullCodec,
37 Index: Ord + One + Zero + Add<Output = Index> + Copy + FullCodec + Eq,
38 B: Get<Index>,
39 CurrentIndex: StorageValue<Index, Query = Index>,
40 Intermediate: StorageMap<Index, Key, Query = Key>,
41 M: StorageMap<Key, Value, Query = QueryKind::Query>,
42 QueryKind: QueryKindTrait<Value, GetDefault>,
43{
44 fn insert(k: Key, v: Value) {
46 let bound = B::get();
47 let mut current_index = CurrentIndex::get();
48
49 if (current_index + Index::one()) >= bound {
51 current_index = Index::zero();
52 } else {
53 current_index = current_index + Index::one();
54 }
55
56 if Intermediate::contains_key(current_index) {
58 let older_key = Intermediate::get(current_index);
59 M::remove(older_key);
60 }
61
62 Intermediate::insert(current_index, k.clone());
63 CurrentIndex::set(current_index);
64 M::insert(k, v);
65 }
66
67 fn contains_key(k: Key) -> bool {
69 M::contains_key(k)
70 }
71
72 fn get(k: Key) -> M::Query {
74 M::get(k)
75 }
76}