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