rtvm_interpreter/interpreter/
serde.rs

1use crate::{
2    Contract, FunctionStack, Gas, InstructionResult, InterpreterAction, SharedMemory, Stack,
3};
4
5use super::Interpreter;
6use rtvm_primitives::Bytes;
7use serde::de::{self, MapAccess, Visitor};
8use serde::ser::SerializeStruct;
9use serde::{Deserialize, Deserializer, Serialize, Serializer};
10use std::fmt;
11
12impl Serialize for Interpreter {
13    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
14    where
15        S: Serializer,
16    {
17        let mut state = serializer.serialize_struct("Interpreter", 8)?;
18        // Convert the instruction pointer to a usize for serialization
19        let program_counter = self.program_counter();
20        state.serialize_field("program_counter", &program_counter)?;
21        state.serialize_field("gas", &self.gas)?;
22        state.serialize_field("contract", &self.contract)?;
23        state.serialize_field("instruction_result", &self.instruction_result)?;
24        state.serialize_field("bytecode", &self.bytecode)?;
25        state.serialize_field("is_eof", &self.is_eof)?;
26        state.serialize_field("is_eof_init", &self.is_eof_init)?;
27        state.serialize_field("shared_memory", &self.shared_memory)?;
28        state.serialize_field("stack", &self.stack)?;
29        state.serialize_field("function_stack", &self.function_stack)?;
30        state.serialize_field("return_data_buffer", &self.return_data_buffer)?;
31        state.serialize_field("is_static", &self.is_static)?;
32        state.serialize_field("next_action", &self.next_action)?;
33        state.end()
34    }
35}
36
37impl<'de> Deserialize<'de> for Interpreter {
38    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
39    where
40        D: Deserializer<'de>,
41    {
42        struct InterpreterVisitor;
43
44        #[derive(serde::Deserialize)]
45        #[serde(field_identifier, rename_all = "lowercase")]
46        enum InterpreterFields {
47            ProgramCounter,
48            Gas,
49            Contract,
50            InstructionResult,
51            Bytecode,
52            IsEof,
53            IsEofInit,
54            SharedMemory,
55            Stack,
56            FunctionStack,
57            ReturnDataBuffer,
58            IsStatic,
59            NextAction,
60        }
61
62        #[allow(clippy::too_many_arguments)]
63        fn rebuild_interp(
64            program_counter: isize,
65            gas: Gas,
66            contract: Contract,
67            instruction_result: InstructionResult,
68            bytecode: Bytes,
69            is_eof: bool,
70            is_eof_init: bool,
71            shared_memory: SharedMemory,
72            stack: Stack,
73            function_stack: FunctionStack,
74            return_data_buffer: Bytes,
75            is_static: bool,
76            next_action: InterpreterAction,
77        ) -> Result<Interpreter, &'static str> {
78            // Reconstruct the instruction pointer from usize
79            if program_counter < 0 || program_counter >= bytecode.len() as isize {
80                return Err("program_counter index out of range");
81            }
82
83            // SAFETY: range of program_counter checked above
84            let instruction_pointer = unsafe { bytecode.as_ptr().offset(program_counter) };
85
86            // Construct and return the Interpreter instance
87            Ok(Interpreter {
88                instruction_pointer,
89                gas,
90                contract,
91                instruction_result,
92                bytecode,
93                is_eof,
94                is_eof_init,
95                shared_memory,
96                stack,
97                function_stack,
98                return_data_buffer,
99                is_static,
100                next_action,
101            })
102        }
103
104        impl<'de> Visitor<'de> for InterpreterVisitor {
105            type Value = Interpreter;
106
107            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
108                formatter.write_str("struct Interpreter")
109            }
110
111            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
112            where
113                A: de::SeqAccess<'de>,
114            {
115                macro_rules! extract_field {
116                    ($i:ident, $idx:expr) => {
117                        let $i = seq
118                            .next_element()?
119                            .ok_or_else(|| de::Error::invalid_length($idx, &self))?;
120                    };
121                }
122                extract_field!(instruction_pointer, 0);
123                extract_field!(gas, 1);
124                extract_field!(contract, 2);
125                extract_field!(instruction_result, 3);
126                extract_field!(bytecode, 4);
127                extract_field!(is_eof, 5);
128                extract_field!(is_eof_init, 6);
129                extract_field!(shared_memory, 7);
130                extract_field!(stack, 8);
131                extract_field!(function_stack, 9);
132                extract_field!(return_data_buffer, 10);
133                extract_field!(is_static, 11);
134                extract_field!(next_action, 12);
135                rebuild_interp(
136                    instruction_pointer,
137                    gas,
138                    contract,
139                    instruction_result,
140                    bytecode,
141                    is_eof,
142                    is_eof_init,
143                    shared_memory,
144                    stack,
145                    function_stack,
146                    return_data_buffer,
147                    is_static,
148                    next_action,
149                )
150                .map_err(de::Error::custom)
151            }
152
153            fn visit_map<V>(self, mut map: V) -> Result<Interpreter, V::Error>
154            where
155                V: MapAccess<'de>,
156            {
157                macro_rules! parse_map {
158                    ( $(($enum:pat, $var_name:ident)),* ) => {
159                        $(
160                            let mut $var_name = None;
161                        )*
162                        while let Some(key) = map.next_key()? {
163                            match key {
164                                $(
165                                    $enum => {
166                                        $var_name = Some(map.next_value()?);
167                                    }
168                                )*
169                            }
170                        }
171                        $(
172                            let $var_name = $var_name.ok_or_else(|| de::Error::missing_field(stringify!($var_name)))?;
173                        )*
174                    };
175                }
176                parse_map!(
177                    (InterpreterFields::ProgramCounter, program_counter),
178                    (InterpreterFields::Gas, gas),
179                    (InterpreterFields::Contract, contract),
180                    (InterpreterFields::InstructionResult, instruction_result),
181                    (InterpreterFields::Bytecode, bytecode),
182                    (InterpreterFields::IsEof, is_eof),
183                    (InterpreterFields::IsEofInit, is_eof_init),
184                    (InterpreterFields::SharedMemory, shared_memory),
185                    (InterpreterFields::Stack, stack),
186                    (InterpreterFields::FunctionStack, function_stack),
187                    (InterpreterFields::ReturnDataBuffer, return_data_buffer),
188                    (InterpreterFields::IsStatic, is_static),
189                    (InterpreterFields::NextAction, next_action)
190                );
191
192                rebuild_interp(
193                    program_counter,
194                    gas,
195                    contract,
196                    instruction_result,
197                    bytecode,
198                    is_eof,
199                    is_eof_init,
200                    shared_memory,
201                    stack,
202                    function_stack,
203                    return_data_buffer,
204                    is_static,
205                    next_action,
206                )
207                .map_err(de::Error::custom)
208            }
209        }
210
211        const FIELDS: &[&str] = &[
212            "program_counter",
213            "gas",
214            "contract",
215            "instruction_result",
216            "bytecode",
217            "is_eof",
218            "is_eof_init",
219            "shared_memory",
220            "stack",
221            "function_stack",
222            "return_data_buffer",
223            "is_static",
224            "next_action",
225        ];
226
227        deserializer.deserialize_struct("Interpreter", FIELDS, InterpreterVisitor)
228    }
229}
230
231#[cfg(test)]
232mod tests {
233    use super::*;
234
235    #[test]
236    fn test_serde() {
237        let interp = Interpreter::new(Contract::default(), u64::MAX, false);
238        let serialized = bincode::serialize(&interp).unwrap();
239        let de: Interpreter = bincode::deserialize(&serialized).unwrap();
240        assert_eq!(interp.program_counter(), de.program_counter());
241    }
242}