1#![cfg_attr(not(feature = "std"), no_std)]
8#![deny(clippy::arithmetic_side_effects)]
9#![deny(clippy::cast_possible_truncation)]
10#![deny(unused_crate_dependencies)]
11#![deny(missing_docs)]
12#![deny(warnings)]
13
14#[cfg(feature = "alloc")]
15extern crate alloc;
16
17#[cfg(test)]
18use fuel_core_storage as _;
19
20use anyhow::anyhow;
21use core::array::TryFromSliceError;
22use fuel_core_types::services::executor::Error as ExecutorError;
23
24#[cfg(feature = "alloc")]
25use alloc::{
26 boxed::Box,
27 string::ToString,
28};
29
30pub use fuel_vm_private::{
31 fuel_storage::*,
32 storage::{
33 ContractsAssetsStorage,
34 InterpreterStorage,
35 predicate::PredicateStorageRequirements,
36 },
37};
38
39pub mod blueprint;
40pub mod codec;
41pub mod column;
42pub mod iter;
43pub mod kv_store;
44pub mod merkle;
45pub mod structured_storage;
46pub mod tables;
47#[cfg(feature = "test-helpers")]
48pub mod test_helpers;
49pub mod transactional;
50pub mod vm_storage;
51
52use fuel_core_types::fuel_merkle::binary::MerkleTreeError;
53pub use fuel_vm_private::storage::{
54 ContractsAssetKey,
55 ContractsStateData,
56 ContractsStateKey,
57};
58#[doc(hidden)]
59pub use paste;
60#[cfg(feature = "test-helpers")]
61#[doc(hidden)]
62pub use rand;
63
64pub type Result<T> = core::result::Result<T, Error>;
66
67#[derive(Debug, derive_more::Display, derive_more::From)]
68#[non_exhaustive]
69pub enum Error {
71 #[display("error performing serialization or deserialization `{_0}`")]
73 Codec(anyhow::Error),
74 #[display("error occurred in the underlying datastore `{_0:?}`")]
76 DatabaseError(Box<dyn core::fmt::Debug + Send + Sync>),
77 #[display("resource was not found in table `{_0}` at the: {_1}")]
79 NotFound(&'static str, &'static str),
80 #[from]
83 Other(anyhow::Error),
84}
85
86#[cfg(feature = "test-helpers")]
87impl PartialEq for Error {
88 fn eq(&self, other: &Self) -> bool {
89 self.to_string().eq(&other.to_string())
90 }
91}
92
93impl From<Error> for anyhow::Error {
94 fn from(error: Error) -> Self {
95 anyhow::Error::msg(error)
96 }
97}
98
99impl From<TryFromSliceError> for Error {
100 fn from(e: TryFromSliceError) -> Self {
101 Self::Other(anyhow::anyhow!(e))
102 }
103}
104
105impl From<Error> for ExecutorError {
106 fn from(e: Error) -> Self {
107 ExecutorError::StorageError(e.to_string())
108 }
109}
110
111impl From<Error> for fuel_vm_private::prelude::InterpreterError<Error> {
112 fn from(e: Error) -> Self {
113 fuel_vm_private::prelude::InterpreterError::Storage(e)
114 }
115}
116
117impl From<Error> for fuel_vm_private::prelude::RuntimeError<Error> {
118 fn from(e: Error) -> Self {
119 fuel_vm_private::prelude::RuntimeError::Storage(e)
120 }
121}
122
123impl From<MerkleTreeError<Error>> for Error {
124 fn from(e: MerkleTreeError<Error>) -> Self {
125 match e {
126 MerkleTreeError::StorageError(s) => s,
127 e => Error::Other(anyhow!(e)),
128 }
129 }
130}
131
132pub trait IsNotFound {
134 fn is_not_found(&self) -> bool;
136}
137
138impl IsNotFound for Error {
139 fn is_not_found(&self) -> bool {
140 matches!(self, Error::NotFound(_, _))
141 }
142}
143
144impl<T> IsNotFound for Result<T> {
145 fn is_not_found(&self) -> bool {
146 match self {
147 Err(err) => err.is_not_found(),
148 _ => false,
149 }
150 }
151}
152
153#[impl_tools::autoimpl(for<T: trait> &mut T)]
156pub trait StorageBatchMutate<Type: Mappable>: StorageMutate<Type> {
157 fn init_storage<'a, Iter>(&mut self, set: Iter) -> Result<()>
164 where
165 Iter: 'a + Iterator<Item = (&'a Type::Key, &'a Type::Value)>,
166 Type::Key: 'a,
167 Type::Value: 'a;
168
169 fn insert_batch<'a, Iter>(&mut self, set: Iter) -> Result<()>
171 where
172 Iter: 'a + Iterator<Item = (&'a Type::Key, &'a Type::Value)>,
173 Type::Key: 'a,
174 Type::Value: 'a;
175
176 fn remove_batch<'a, Iter>(&mut self, set: Iter) -> Result<()>
178 where
179 Iter: 'a + Iterator<Item = &'a Type::Key>,
180 Type::Key: 'a;
181}
182
183#[macro_export]
196macro_rules! not_found {
197 ($name: literal) => {
198 $crate::Error::NotFound($name, concat!(file!(), ":", line!()))
199 };
200 ($ty: path) => {
201 $crate::Error::NotFound(
202 ::core::any::type_name::<$ty>(),
203 concat!(file!(), ":", line!()),
204 )
205 };
206}
207
208#[cfg(test)]
209mod test {
210 use crate::tables::Coins;
211
212 #[test]
213 fn not_found_output() {
214 #[rustfmt::skip]
215 assert_eq!(
216 format!("{}", not_found!("BlockId")),
217 format!("resource was not found in table `BlockId` at the: {}:{}", file!(), line!() - 1)
218 );
219 #[rustfmt::skip]
220 assert_eq!(
221 format!("{}", not_found!(Coins)),
222 format!("resource was not found in table `fuel_core_storage::tables::Coins` at the: {}:{}", file!(), line!() - 1)
223 );
224 }
225}