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. Errors if the buffer cannot be filled completely, or if attempting
125    /// to read past the end of the value.
126    ///
127    /// Does not perform any deserialization.
128    ///
129    /// Returns `Ok(true)` if the value does exist, and `Ok(false)` otherwise.
130    fn read(
131        &self,
132        key: &Type::Key,
133        offset: usize,
134        buf: &mut [u8],
135    ) -> Result<bool, 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    fn write_bytes(&mut self, key: &Type::Key, buf: &[u8]) -> Result<(), Self::Error>;
155
156    /// Write the bytes to the given key from the provided buffer and
157    /// return the previous bytes if it existed.
158    ///
159    /// Does not perform any serialization.
160    ///
161    /// Returns the previous value if it existed.
162    fn replace_bytes(
163        &mut self,
164        key: &Type::Key,
165        buf: &[u8],
166    ) -> Result<Option<Vec<u8>>, Self::Error>;
167
168    /// Removes a bytes from the storage and returning it without deserializing it.
169    fn take_bytes(&mut self, key: &Type::Key) -> Result<Option<Vec<u8>>, Self::Error>;
170}
171
172/// Returns the merkle root for the `StorageType` per merkle `Key`. Per one storage, it is
173/// possible to have several merkle trees under different `Key`.
174pub trait MerkleRootStorage<Key, StorageType>: StorageInspect<StorageType>
175where
176    StorageType: Mappable,
177{
178    /// Return the merkle root of the stored `Type` in the storage.
179    ///
180    /// The cryptographic primitive is an arbitrary choice of the implementor and this
181    /// trait won't impose any restrictions to that.
182    fn root(&self, key: &Key) -> Result<MerkleRoot, Self::Error>;
183}
184
185/// The wrapper around the storage that supports only methods from `StorageInspect`.
186pub struct StorageRef<'a, T: 'a + ?Sized, Type: Mappable>(
187    &'a T,
188    core::marker::PhantomData<Type>,
189);
190
191/// Helper trait for `StorageInspect` to provide user-friendly API to retrieve storage as
192/// reference.
193///
194/// # Example
195///
196/// ```rust
197/// use fuel_storage::{Mappable, StorageInspect, StorageAsRef};
198///
199/// pub struct Contracts;
200///
201/// impl Mappable for Contracts {
202///     type Key = Self::OwnedKey;
203///     type OwnedKey = [u8; 32];
204///     type Value = [u8];
205///     type OwnedValue = Vec<u8>;
206/// }
207///
208/// pub struct Balances;
209///
210/// impl Mappable for Balances {
211///     type Key = Self::OwnedKey;
212///     type OwnedKey = u128;
213///     type Value = Self::OwnedValue;
214///     type OwnedValue = u64;
215/// }
216///
217/// pub trait Logic: StorageInspect<Contracts> + StorageInspect<Balances> {
218///     fn run(&self) {
219///         // You can specify which storage do you want to call with `storage::<Type>()`
220///         let _ = self.storage::<Contracts>().get(&[0; 32]);
221///         let _ = self.storage::<Balances>().get(&123);
222///     }
223/// }
224/// ```
225pub trait StorageAsRef {
226    #[inline(always)]
227    fn storage<Type>(&self) -> StorageRef<Self, Type>
228    where
229        Type: Mappable,
230    {
231        self.storage_as_ref()
232    }
233
234    #[inline(always)]
235    fn storage_as_ref<Type>(&self) -> StorageRef<Self, Type>
236    where
237        Type: Mappable,
238    {
239        StorageRef(self, Default::default())
240    }
241}
242
243impl<T> StorageAsRef for T {}
244
245/// The wrapper around the storage that supports methods from `StorageInspect` and
246/// `StorageMutate`.
247pub struct StorageMut<'a, T: 'a + ?Sized, Type: Mappable>(
248    &'a mut T,
249    core::marker::PhantomData<Type>,
250);
251
252/// Helper trait for `StorageMutate` to provide user-friendly API to retrieve storage as
253/// mutable reference.
254///
255/// # Example
256///
257/// ```rust
258/// use fuel_storage::{Mappable, StorageMutate, StorageInspect, StorageAsMut};
259///
260/// pub struct Contracts;
261///
262/// impl Mappable for Contracts {
263///     type Key = Self::OwnedKey;
264///     type OwnedKey = [u8; 32];
265///     type Value = [u8];
266///     type OwnedValue = Vec<u8>;
267/// }
268///
269/// pub struct Balances;
270///
271/// impl Mappable for Balances {
272///     type Key = Self::OwnedKey;
273///     type OwnedKey = u128;
274///     type Value = Self::OwnedValue;
275///     type OwnedValue = u64;
276/// }
277///
278/// pub trait Logic: StorageInspect<Contracts> + StorageMutate<Balances> {
279///     fn run(&mut self) {
280///         let mut self_ = self;
281///         // You can specify which storage do you want to call with `storage::<Type>()`
282///         let _ = self_.storage::<Balances>().insert(&123, &321);
283///         let _ = self_.storage::<Contracts>().get(&[0; 32]);
284///     }
285/// }
286/// ```
287pub trait StorageAsMut {
288    #[inline(always)]
289    fn storage<Type>(&mut self) -> StorageMut<Self, Type>
290    where
291        Type: Mappable,
292    {
293        self.storage_as_mut()
294    }
295
296    #[inline(always)]
297    fn storage_as_mut<Type>(&mut self) -> StorageMut<Self, Type>
298    where
299        Type: Mappable,
300    {
301        StorageMut(self, Default::default())
302    }
303}
304
305impl<T> StorageAsMut for T {}