1use fuel_asm::{
4 PanicReason,
5 RegId,
6};
7use fuel_types::{
8 bytes::padded_len_usize,
9 canonical::{
10 Deserialize,
11 Serialize,
12 },
13 AssetId,
14 ContractId,
15 Word,
16};
17
18use crate::consts::{
19 WORD_SIZE,
20 *,
21};
22
23#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25#[derive(Deserialize, Serialize)]
26pub struct Call {
31 to: ContractId,
32 a: Word,
33 b: Word,
34}
35
36impl Call {
37 pub const LEN: usize = ContractId::LEN + 8 + 8;
39
40 pub const fn new(to: ContractId, a: Word, b: Word) -> Self {
42 Self { to, a, b }
43 }
44
45 pub const fn to(&self) -> &ContractId {
47 &self.to
48 }
49
50 pub const fn a(&self) -> Word {
52 self.a
53 }
54
55 pub const fn b(&self) -> Word {
57 self.b
58 }
59
60 pub const fn into_inner(self) -> (ContractId, Word, Word) {
62 (self.to, self.a, self.b)
63 }
64}
65
66#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
67pub struct CallFrame {
71 to: ContractId,
72 asset_id: AssetId,
73 registers: [Word; VM_REGISTER_COUNT],
74 code_size_padded: usize,
75 a: Word,
76 b: Word,
77}
78
79#[cfg(test)]
80impl Default for CallFrame {
81 fn default() -> Self {
82 Self {
83 to: ContractId::default(),
84 asset_id: AssetId::default(),
85 registers: [0; VM_REGISTER_COUNT],
86 code_size_padded: 0,
87 a: 0,
88 b: 0,
89 }
90 }
91}
92
93impl CallFrame {
94 pub fn new(
96 to: ContractId,
97 asset_id: AssetId,
98 registers: [Word; VM_REGISTER_COUNT],
99 code_size: usize,
100 a: Word,
101 b: Word,
102 ) -> Option<Self> {
103 Some(Self {
104 to,
105 asset_id,
106 registers,
107 code_size_padded: padded_len_usize(code_size)?,
108 a,
109 b,
110 })
111 }
112
113 pub const fn contract_id_offset() -> usize {
115 0
116 }
117
118 pub const fn asset_id_offset() -> usize {
120 Self::contract_id_offset().saturating_add(ContractId::LEN)
121 }
122
123 pub const fn registers_offset() -> usize {
125 Self::asset_id_offset().saturating_add(AssetId::LEN)
126 }
127
128 pub const fn code_size_offset() -> usize {
130 Self::registers_offset().saturating_add(WORD_SIZE * VM_REGISTER_COUNT)
131 }
132
133 pub const fn a_offset() -> usize {
135 Self::code_size_offset().saturating_add(WORD_SIZE)
136 }
137
138 pub const fn b_offset() -> usize {
140 Self::a_offset().saturating_add(WORD_SIZE)
141 }
142
143 pub const fn serialized_size() -> usize {
145 Self::b_offset().saturating_add(WORD_SIZE)
146 }
147
148 pub const fn registers(&self) -> &[Word] {
150 &self.registers
151 }
152
153 pub const fn to(&self) -> &ContractId {
155 &self.to
156 }
157
158 #[cfg(feature = "test-helpers")]
159 pub fn code_size_padded(&self) -> usize {
161 self.code_size_padded
162 }
163
164 pub const fn a(&self) -> Word {
166 self.a
167 }
168
169 pub const fn b(&self) -> Word {
171 self.b
172 }
173
174 pub fn context_gas(&self) -> Word {
176 self.registers[RegId::CGAS]
177 }
178
179 pub const fn asset_id(&self) -> &AssetId {
181 &self.asset_id
182 }
183
184 pub fn context_gas_mut(&mut self) -> &mut Word {
186 &mut self.registers[RegId::CGAS]
187 }
188
189 pub fn global_gas_mut(&mut self) -> &mut Word {
191 &mut self.registers[RegId::GGAS]
192 }
193}
194
195impl TryFrom<&[u8]> for Call {
196 type Error = PanicReason;
197
198 fn try_from(mut value: &[u8]) -> Result<Self, Self::Error> {
199 Self::decode(&mut value).map_err(|_| PanicReason::MalformedCallStructure)
200 }
201}
202
203#[cfg(test)]
204impl From<Call> for alloc::vec::Vec<u8> {
205 fn from(call: Call) -> Self {
206 call.to_bytes()
207 }
208}
209
210#[cfg(test)]
211impl From<CallFrame> for alloc::vec::Vec<u8> {
212 fn from(call: CallFrame) -> Self {
213 call.to_bytes()
214 }
215}