1use alloc::vec::Vec;
4
5use fuel_tx::Receipt;
6use fuel_types::{
7 Bytes32,
8 Word,
9};
10
11mod debug;
12
13mod debugger;
14
15pub use debug::{
16 Breakpoint,
17 DebugEval,
18};
19
20pub use debugger::Debugger;
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23pub enum ExecuteState {
25 Proceed,
27 Return(Word),
29 ReturnData(Bytes32),
31 Revert(Word),
33
34 DebugEvent(DebugEval),
36}
37
38impl ExecuteState {
39 pub const fn should_continue(&self) -> bool {
41 matches!(self, Self::Proceed | Self::DebugEvent(DebugEval::Continue))
42 }
43}
44
45impl Default for ExecuteState {
46 fn default() -> Self {
47 Self::Proceed
48 }
49}
50
51impl From<DebugEval> for ExecuteState {
52 fn from(d: DebugEval) -> Self {
53 Self::DebugEvent(d)
54 }
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
58#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
59pub enum ProgramState {
61 Return(Word),
63 ReturnData(Bytes32),
65 Revert(Word),
67
68 RunProgram(DebugEval),
70
71 VerifyPredicate(DebugEval),
74}
75
76impl PartialEq<Breakpoint> for ProgramState {
77 fn eq(&self, other: &Breakpoint) -> bool {
78 match self.debug_ref() {
79 Some(&DebugEval::Breakpoint(b)) => &b == other,
80 _ => false,
81 }
82 }
83}
84
85impl ProgramState {
86 pub const fn debug_ref(&self) -> Option<&DebugEval> {
90 match self {
91 Self::RunProgram(d) | Self::VerifyPredicate(d) => Some(d),
92 _ => None,
93 }
94 }
95
96 pub const fn is_debug(&self) -> bool {
98 self.debug_ref().is_some()
99 }
100}
101
102#[derive(Debug, Clone, PartialEq, Eq)]
103pub struct StateTransition<Tx> {
105 state: ProgramState,
106 tx: Tx,
107 receipts: Vec<Receipt>,
108}
109
110impl<Tx> StateTransition<Tx> {
111 pub const fn new(state: ProgramState, tx: Tx, receipts: Vec<Receipt>) -> Self {
113 Self {
114 state,
115 tx,
116 receipts,
117 }
118 }
119
120 pub const fn state(&self) -> &ProgramState {
122 &self.state
123 }
124
125 pub const fn tx(&self) -> &Tx {
127 &self.tx
128 }
129
130 pub fn should_revert(&self) -> bool {
132 self.receipts
133 .iter()
134 .any(|r| matches!(r, Receipt::Revert { .. } | Receipt::Panic { .. }))
135 }
136
137 pub fn receipts(&self) -> &[Receipt] {
139 self.receipts.as_slice()
140 }
141
142 pub fn into_inner(self) -> (ProgramState, Tx, Vec<Receipt>) {
144 (self.state, self.tx, self.receipts)
145 }
146}
147
148impl<Tx> From<StateTransition<Tx>> for ProgramState {
149 fn from(t: StateTransition<Tx>) -> ProgramState {
150 t.state
151 }
152}
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq)]
155pub struct StateTransitionRef<'a, Tx> {
158 state: ProgramState,
159 tx: &'a Tx,
160 receipts: &'a [Receipt],
161}
162
163impl<'a, Tx> StateTransitionRef<'a, Tx> {
164 pub const fn new(state: ProgramState, tx: &'a Tx, receipts: &'a [Receipt]) -> Self {
166 Self {
167 state,
168 tx,
169 receipts,
170 }
171 }
172
173 pub const fn state(&self) -> &ProgramState {
175 &self.state
176 }
177
178 pub const fn tx(&self) -> &Tx {
180 self.tx
181 }
182
183 pub const fn receipts(&self) -> &[Receipt] {
185 self.receipts
186 }
187
188 pub fn should_revert(&self) -> bool {
190 self.receipts
191 .iter()
192 .any(|r| matches!(r, Receipt::Revert { .. } | Receipt::Panic { .. }))
193 }
194}
195
196impl<'a, Tx> From<&'a StateTransition<Tx>> for StateTransitionRef<'a, Tx> {
197 fn from(t: &'a StateTransition<Tx>) -> StateTransitionRef<'a, Tx> {
198 Self {
199 state: *t.state(),
200 tx: t.tx(),
201 receipts: t.receipts(),
202 }
203 }
204}
205
206impl<'a, Tx: Clone> From<StateTransitionRef<'a, Tx>> for StateTransition<Tx> {
207 fn from(t: StateTransitionRef<Tx>) -> StateTransition<Tx> {
208 StateTransition {
209 state: *t.state(),
210 tx: t.tx().clone(),
211 receipts: t.receipts().to_vec(),
212 }
213 }
214}
215
216impl<'a, Tx: Clone> From<StateTransitionRef<'a, Tx>> for ProgramState {
217 fn from(t: StateTransitionRef<'a, Tx>) -> ProgramState {
218 t.state
219 }
220}