referrerpolicy=no-referrer-when-downgrade

snowbridge_core/
ringbuffer.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
3use 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
9/// Trait object presenting the ringbuffer interface.
10pub trait RingBufferMap<Key, Value, QueryKind>
11where
12	Key: FullCodec,
13	Value: FullCodec,
14	QueryKind: QueryKindTrait<Value, GetDefault>,
15{
16	/// Insert a map entry.
17	fn insert(k: Key, v: Value);
18
19	/// Check if map contains a key
20	fn contains_key(k: Key) -> bool;
21
22	/// Get the value of the key
23	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
30/// Ringbuffer implementation based on `RingBufferTransient`
31impl<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	/// Insert a map entry.
45	fn insert(k: Key, v: Value) {
46		let bound = B::get();
47		let mut current_index = CurrentIndex::get();
48
49		// Adding one here as bound denotes number of items but our index starts with zero.
50		if (current_index + Index::one()) >= bound {
51			current_index = Index::zero();
52		} else {
53			current_index = current_index + Index::one();
54		}
55
56		// Deleting earlier entry if it exists
57		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	/// Check if map contains a key
68	fn contains_key(k: Key) -> bool {
69		M::contains_key(k)
70	}
71
72	/// Get the value associated with key
73	fn get(k: Key) -> M::Query {
74		M::get(k)
75	}
76}