Skip to main content

fluentbase_types/
syscall.rs

1use crate::{ExitCode, B256};
2use alloc::{string::String, vec::Vec};
3use core::ops::Range;
4
5#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7pub struct SyscallInvocationParams {
8    pub code_hash: B256,
9    pub input: Range<usize>,
10    pub fuel_limit: u64,
11    pub state: u32,
12    pub fuel16_ptr: u32,
13}
14
15impl SyscallInvocationParams {
16    pub fn encode(&self) -> Vec<u8> {
17        bincode::encode_to_vec(self, bincode::config::legacy()).unwrap()
18    }
19
20    pub fn decode(bytes: &[u8]) -> Option<Self> {
21        let (result, _bytes_read) =
22            bincode::decode_from_slice(bytes, bincode::config::legacy()).ok()?;
23        Some(result)
24    }
25}
26
27impl ::bincode::Encode for SyscallInvocationParams {
28    fn encode<__E: bincode::enc::Encoder>(
29        &self,
30        encoder: &mut __E,
31    ) -> Result<(), bincode::error::EncodeError> {
32        ::bincode::Encode::encode(&self.code_hash.0, encoder)?;
33        ::bincode::Encode::encode(&self.fuel_limit, encoder)?;
34        ::bincode::Encode::encode(&self.state, encoder)?;
35        ::bincode::Encode::encode(&self.fuel16_ptr, encoder)?;
36        ::bincode::Encode::encode(&self.input, encoder)?;
37        Ok(())
38    }
39}
40
41impl<__Context> ::bincode::Decode<__Context> for SyscallInvocationParams {
42    fn decode<__D: ::bincode::de::Decoder<Context = __Context>>(
43        decoder: &mut __D,
44    ) -> Result<Self, bincode::error::DecodeError> {
45        let code_hash: [u8; 32] = bincode::Decode::decode(decoder)?;
46        let fuel_limit: u64 = bincode::Decode::decode(decoder)?;
47        let state: u32 = bincode::Decode::decode(decoder)?;
48        let fuel16_ptr: u32 = bincode::Decode::decode(decoder)?;
49        let input: Range<usize> = bincode::Decode::decode(decoder)?;
50        Ok(Self {
51            code_hash: B256::from(code_hash),
52            input,
53            fuel_limit,
54            state,
55            fuel16_ptr,
56        })
57    }
58}
59
60#[derive(Debug)]
61pub struct SyscallResult<T> {
62    pub data: T,
63    pub fuel_consumed: u64,
64    pub fuel_refunded: i64,
65    pub status: ExitCode,
66}
67
68impl<T: Default> Default for SyscallResult<T> {
69    fn default() -> Self {
70        Self {
71            data: T::default(),
72            fuel_consumed: 0,
73            fuel_refunded: 0,
74            status: ExitCode::Ok,
75        }
76    }
77}
78
79impl SyscallResult<()> {
80    pub fn is_ok<I: Into<ExitCode>>(status: I) -> bool {
81        Into::<ExitCode>::into(status) == ExitCode::Ok
82    }
83    pub fn is_panic<I: Into<ExitCode>>(status: I) -> bool {
84        Into::<ExitCode>::into(status) == ExitCode::Panic
85    }
86}
87
88impl<T> SyscallResult<T> {
89    pub fn new<I: Into<ExitCode>>(
90        data: T,
91        fuel_consumed: u64,
92        fuel_refunded: i64,
93        status: I,
94    ) -> Self {
95        Self {
96            data,
97            fuel_consumed,
98            fuel_refunded,
99            status: Into::<ExitCode>::into(status),
100        }
101    }
102    pub fn expect<I: Into<String>>(self, msg: I) -> Self {
103        if !self.status.is_ok() {
104            panic!("syscall failed with status {}: {}", self.status, msg.into());
105        }
106        self
107    }
108    pub fn unwrap(self) -> T {
109        if !self.status.is_ok() {
110            panic!("syscall failed with status ({})", self.status);
111        }
112        self.data
113    }
114    pub fn ok(self) -> Result<T, ExitCode> {
115        if self.status == ExitCode::Ok {
116            Ok(self.data)
117        } else {
118            Err(self.status)
119        }
120    }
121}
122
123impl<T: Default> SyscallResult<T> {
124    pub fn unwrap_or_default(self) -> T {
125        if self.status.is_ok() {
126            self.data
127        } else {
128            T::default()
129        }
130    }
131
132    pub fn map<U: Default>(
133        self,
134        f: impl FnOnce(SyscallResult<T>) -> SyscallResult<U>,
135    ) -> SyscallResult<U> {
136        f(self)
137    }
138}
139
140impl<T> core::ops::Deref for SyscallResult<T> {
141    type Target = T;
142
143    fn deref(&self) -> &Self::Target {
144        &self.data
145    }
146}
147impl<T> core::ops::DerefMut for SyscallResult<T> {
148    fn deref_mut(&mut self) -> &mut Self::Target {
149        &mut self.data
150    }
151}