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(&self, key: &Type::Key) -> Result<Option<Cow<Type::OwnedValue>>, Self::Error>;
68
69    /// Return `true` if there is a `Key` mapping to a value in the storage.
70    fn contains_key(&self, key: &Type::Key) -> Result<bool, Self::Error>;
71}
72
73/// Base storage trait for Fuel infrastructure.
74///
75/// Generic should implement [`Mappable`] trait with all storage type information.
76pub trait StorageMutate<Type: Mappable>: StorageInspect<Type> {
77    /// Append `Key->Value` mapping to the storage.
78    fn insert(
79        &mut self,
80        key: &Type::Key,
81        value: &Type::Value,
82    ) -> Result<(), Self::Error> {
83        self.replace(key, value).map(|_| ())
84    }
85
86    /// Append `Key->Value` mapping to the storage.
87    ///
88    /// If `Key` was already mappped to a value, return the replaced value as
89    /// `Ok(Some(Value))`. Return `Ok(None)` otherwise.
90    fn replace(
91        &mut self,
92        key: &Type::Key,
93        value: &Type::Value,
94    ) -> Result<Option<Type::OwnedValue>, Self::Error>;
95
96    /// Remove `Key->Value` mapping from the storage.
97    fn remove(&mut self, key: &Type::Key) -> Result<(), Self::Error> {
98        self.take(key).map(|_| ())
99    }
100
101    /// Remove `Key->Value` mapping from the storage.
102    ///
103    /// Return `Ok(Some(Value))` if the value was present. If the key wasn't found, return
104    /// `Ok(None)`.
105    fn take(&mut self, key: &Type::Key) -> Result<Option<Type::OwnedValue>, Self::Error>;
106}
107
108/// Base storage trait for Fuel infrastructure.
109///
110/// Allows checking the size of the value stored at a given key.
111/// Checking the size of a value is a cheap operation and should not require
112/// copying the value into a buffer.
113pub trait StorageSize<Type: Mappable>: StorageInspect<Type> {
114    /// Return the number of bytes stored at this key.
115    fn size_of_value(&self, key: &Type::Key) -> Result<Option<usize>, Self::Error>;
116}
117
118/// Base storage trait for Fuel infrastructure.
119///
120/// Allows reading the raw bytes of the value stored at a given key
121/// into a provided buffer.
122///
123/// This trait should skip any deserialization and simply copy the raw bytes.
124pub trait StorageRead<Type: Mappable>: StorageInspect<Type> + StorageSize<Type> {
125    /// Read the value stored at the given key into the provided buffer if the value
126    /// exists. Errors if the buffer cannot be filled completely, or if attempting
127    /// to read past the end of the value.
128    ///
129    /// Does not perform any deserialization.
130    ///
131    /// Returns `Ok(true)` if the value does exist, and `Ok(false)` otherwise.
132    fn read(
133        &self,
134        key: &Type::Key,
135        offset: usize,
136        buf: &mut [u8],
137    ) -> Result<bool, Self::Error>;
138
139    /// Same as `read` but allocates a new buffer and returns it.
140    ///
141    /// Checks the size of the value and allocates a buffer of that size.
142    fn read_alloc(&self, key: &Type::Key) -> Result<Option<Vec<u8>>, Self::Error>;
143}
144
145/// Base storage trait for Fuel infrastructure.
146///
147/// Allows writing the raw bytes of the value stored to a given key
148/// from a provided buffer.
149///
150/// This trait should skip any serialization and simply copy the raw bytes
151/// to the storage.
152pub trait StorageWrite<Type: Mappable>: StorageMutate<Type> {
153    /// Write the bytes to the given key from the provided buffer.
154    ///
155    /// Does not perform any serialization.
156    fn write_bytes(&mut self, key: &Type::Key, buf: &[u8]) -> Result<(), 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 previous value if it existed.
164    fn replace_bytes(
165        &mut self,
166        key: &Type::Key,
167        buf: &[u8],
168    ) -> Result<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 {}