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