fluentbase_types/
syscall.rs1use 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}