fuel_storage/lib.rs
1#![no_std]
2#![deny(
3 clippy::arithmetic_side_effects,
4 clippy::cast_sign_loss,
5 clippy::cast_possible_truncation,
6 clippy::cast_possible_wrap,
7 clippy::string_slice
8)]
9#![deny(unsafe_code)]
10#![deny(unused_crate_dependencies)]
11
12mod impls;
13
14extern crate alloc;
15
16use core::borrow::Borrow;
17
18use alloc::{
19 borrow::{
20 Cow,
21 ToOwned,
22 },
23 vec::Vec,
24};
25
26/// Merkle root alias type
27pub type MerkleRoot = [u8; 32];
28
29/// Mappable type with `Key` and `Value`.
30///
31/// # Example
32///
33/// ```rust
34/// use fuel_storage::Mappable;
35/// pub struct Contract;
36///
37/// impl Mappable for Contract {
38/// /// The `[u8; 32]` is a primitive type, so we can't optimize it more.
39/// type Key = Self::OwnedKey;
40/// type OwnedKey = [u8; 32];
41/// /// It is optimized to use slice instead of vector.
42/// type Value = [u8];
43/// type OwnedValue = Vec<u8>;
44/// }
45/// ```
46pub trait Mappable {
47 /// The key type is used during interaction with the storage. In most cases, it is the
48 /// same as `Self::OwnedKey`.
49 type Key: ?Sized + ToOwned;
50 /// The owned type of the `Key` retrieving from the storage.
51 type OwnedKey: From<<Self::Key as ToOwned>::Owned> + Borrow<Self::Key> + Clone;
52 /// The value type is used while setting the value to the storage. In most cases, it
53 /// is the same as `Self::OwnedValue`, but it is without restriction and can be
54 /// used for performance optimizations.
55 type Value: ?Sized + ToOwned;
56 /// The owned type of the `Value` retrieving from the storage.
57 type OwnedValue: From<<Self::Value as ToOwned>::Owned> + Borrow<Self::Value> + Clone;
58}
59
60/// Base read storage trait for Fuel infrastructure.
61///
62/// Generic should implement [`Mappable`] trait with all storage type information.
63pub trait StorageInspect<Type: Mappable> {
64 type Error;
65
66 /// Retrieve `Cow<Value>` such as `Key->Value`.
67 fn get(
68 &self,
69 key: &Type::Key,
70 ) -> Result<Option<Cow<'_, Type::OwnedValue>>, Self::Error>;
71
72 /// Return `true` if there is a `Key` mapping to a value in the storage.
73 fn contains_key(&self, key: &Type::Key) -> Result<bool, Self::Error>;
74}
75
76/// Base storage trait for Fuel infrastructure.
77///
78/// Generic should implement [`Mappable`] trait with all storage type information.
79pub trait StorageMutate<Type: Mappable>: StorageInspect<Type> {
80 /// Append `Key->Value` mapping to the storage.
81 fn insert(
82 &mut self,
83 key: &Type::Key,
84 value: &Type::Value,
85 ) -> Result<(), Self::Error> {
86 self.replace(key, value).map(|_| ())
87 }
88
89 /// Append `Key->Value` mapping to the storage.
90 ///
91 /// If `Key` was already mappped to a value, return the replaced value as
92 /// `Ok(Some(Value))`. Return `Ok(None)` otherwise.
93 fn replace(
94 &mut self,
95 key: &Type::Key,
96 value: &Type::Value,
97 ) -> Result<Option<Type::OwnedValue>, Self::Error>;
98
99 /// Remove `Key->Value` mapping from the storage.
100 fn remove(&mut self, key: &Type::Key) -> Result<(), Self::Error> {
101 self.take(key).map(|_| ())
102 }
103
104 /// Remove `Key->Value` mapping from the storage.
105 ///
106 /// Return `Ok(Some(Value))` if the value was present. If the key wasn't found, return
107 /// `Ok(None)`.
108 fn take(&mut self, key: &Type::Key) -> Result<Option<Type::OwnedValue>, Self::Error>;
109}
110
111/// Base storage trait for Fuel infrastructure.
112///
113/// Allows checking the size of the value stored at a given key.
114/// Checking the size of a value is a cheap operation and should not require
115/// copying the value into a buffer.
116pub trait StorageSize<Type: Mappable>: StorageInspect<Type> {
117 /// Return the number of bytes stored at this key.
118 fn size_of_value(&self, key: &Type::Key) -> Result<Option<usize>, Self::Error>;
119}
120
121/// Base storage trait for Fuel infrastructure.
122///
123/// Allows reading the raw bytes of the value stored at a given key
124/// into a provided buffer.
125///
126/// This trait should skip any deserialization and simply copy the raw bytes.
127pub trait StorageRead<Type: Mappable>: StorageInspect<Type> + StorageSize<Type> {
128 /// Read the value stored at the given key into the provided buffer if the value
129 /// exists. Errors if the buffer cannot be filled completely, or if attempting
130 /// to read past the end of the value.
131 ///
132 /// Does not perform any deserialization.
133 ///
134 /// Returns `Ok(true)` if the value does exist, and `Ok(false)` otherwise.
135 fn read(
136 &self,
137 key: &Type::Key,
138 offset: usize,
139 buf: &mut [u8],
140 ) -> Result<bool, Self::Error>;
141
142 /// Same as `read` but allocates a new buffer and returns it.
143 ///
144 /// Checks the size of the value and allocates a buffer of that size.
145 fn read_alloc(&self, key: &Type::Key) -> Result<Option<Vec<u8>>, Self::Error>;
146}
147
148/// Base storage trait for Fuel infrastructure.
149///
150/// Allows writing the raw bytes of the value stored to a given key
151/// from a provided buffer.
152///
153/// This trait should skip any serialization and simply copy the raw bytes
154/// to the storage.
155pub trait StorageWrite<Type: Mappable>: StorageMutate<Type> {
156 /// Write the bytes to the given key from the provided buffer.
157 ///
158 /// Does not perform any serialization.
159 fn write_bytes(&mut self, key: &Type::Key, buf: &[u8]) -> Result<(), Self::Error>;
160
161 /// Write the bytes to the given key from the provided buffer and
162 /// return the previous bytes if it existed.
163 ///
164 /// Does not perform any serialization.
165 ///
166 /// Returns the previous value if it existed.
167 fn replace_bytes(
168 &mut self,
169 key: &Type::Key,
170 buf: &[u8],
171 ) -> Result<Option<Vec<u8>>, Self::Error>;
172
173 /// Removes a bytes from the storage and returning it without deserializing it.
174 fn take_bytes(&mut self, key: &Type::Key) -> Result<Option<Vec<u8>>, Self::Error>;
175}
176
177/// Returns the merkle root for the `StorageType` per merkle `Key`. Per one storage, it is
178/// possible to have several merkle trees under different `Key`.
179pub trait MerkleRootStorage<Key, StorageType>: StorageInspect<StorageType>
180where
181 StorageType: Mappable,
182{
183 /// Return the merkle root of the stored `Type` in the storage.
184 ///
185 /// The cryptographic primitive is an arbitrary choice of the implementor and this
186 /// trait won't impose any restrictions to that.
187 fn root(&self, key: &Key) -> Result<MerkleRoot, Self::Error>;
188}
189
190/// The wrapper around the storage that supports only methods from `StorageInspect`.
191pub struct StorageRef<'a, T: 'a + ?Sized, Type: Mappable>(
192 &'a T,
193 core::marker::PhantomData<Type>,
194);
195
196/// Helper trait for `StorageInspect` to provide user-friendly API to retrieve storage as
197/// reference.
198///
199/// # Example
200///
201/// ```rust
202/// use fuel_storage::{Mappable, StorageInspect, StorageAsRef};
203///
204/// pub struct Contracts;
205///
206/// impl Mappable for Contracts {
207/// type Key = Self::OwnedKey;
208/// type OwnedKey = [u8; 32];
209/// type Value = [u8];
210/// type OwnedValue = Vec<u8>;
211/// }
212///
213/// pub struct Balances;
214///
215/// impl Mappable for Balances {
216/// type Key = Self::OwnedKey;
217/// type OwnedKey = u128;
218/// type Value = Self::OwnedValue;
219/// type OwnedValue = u64;
220/// }
221///
222/// pub trait Logic: StorageInspect<Contracts> + StorageInspect<Balances> {
223/// fn run(&self) {
224/// // You can specify which storage do you want to call with `storage::<Type>()`
225/// let _ = self.storage::<Contracts>().get(&[0; 32]);
226/// let _ = self.storage::<Balances>().get(&123);
227/// }
228/// }
229/// ```
230pub trait StorageAsRef {
231 #[inline(always)]
232 fn storage<Type>(&self) -> StorageRef<'_, Self, Type>
233 where
234 Type: Mappable,
235 {
236 self.storage_as_ref()
237 }
238
239 #[inline(always)]
240 fn storage_as_ref<Type>(&self) -> StorageRef<'_, Self, Type>
241 where
242 Type: Mappable,
243 {
244 StorageRef(self, Default::default())
245 }
246}
247
248impl<T> StorageAsRef for T {}
249
250/// The wrapper around the storage that supports methods from `StorageInspect` and
251/// `StorageMutate`.
252pub struct StorageMut<'a, T: 'a + ?Sized, Type: Mappable>(
253 &'a mut T,
254 core::marker::PhantomData<Type>,
255);
256
257/// Helper trait for `StorageMutate` to provide user-friendly API to retrieve storage as
258/// mutable reference.
259///
260/// # Example
261///
262/// ```rust
263/// use fuel_storage::{Mappable, StorageMutate, StorageInspect, StorageAsMut};
264///
265/// pub struct Contracts;
266///
267/// impl Mappable for Contracts {
268/// type Key = Self::OwnedKey;
269/// type OwnedKey = [u8; 32];
270/// type Value = [u8];
271/// type OwnedValue = Vec<u8>;
272/// }
273///
274/// pub struct Balances;
275///
276/// impl Mappable for Balances {
277/// type Key = Self::OwnedKey;
278/// type OwnedKey = u128;
279/// type Value = Self::OwnedValue;
280/// type OwnedValue = u64;
281/// }
282///
283/// pub trait Logic: StorageInspect<Contracts> + StorageMutate<Balances> {
284/// fn run(&mut self) {
285/// let mut self_ = self;
286/// // You can specify which storage do you want to call with `storage::<Type>()`
287/// let _ = self_.storage::<Balances>().insert(&123, &321);
288/// let _ = self_.storage::<Contracts>().get(&[0; 32]);
289/// }
290/// }
291/// ```
292pub trait StorageAsMut {
293 #[inline(always)]
294 fn storage<Type>(&mut self) -> StorageMut<'_, Self, Type>
295 where
296 Type: Mappable,
297 {
298 self.storage_as_mut()
299 }
300
301 #[inline(always)]
302 fn storage_as_mut<Type>(&mut self) -> StorageMut<'_, Self, Type>
303 where
304 Type: Mappable,
305 {
306 StorageMut(self, Default::default())
307 }
308}
309
310impl<T> StorageAsMut for T {}