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