1use alloc::string::String;
36use alloc::vec::Vec;
37
38use crate::datamodel::{Datamodel, Environment, EvalError, Event, SessionInfo, StateQuery, Value};
39use crate::session::{Input, StartInput};
40use crate::trace::MacrostepTrace;
41
42#[derive(Clone, Debug, PartialEq)]
44#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
45pub enum Request {
46 InitSession(SessionInfo),
48 SetEnvironment(Environment),
50 Declare {
52 id: String,
54 },
55 SetEvent(Event),
57 EvalCond {
59 expr: String,
61 },
62 EvalValue {
64 expr: String,
66 },
67 EvalContent {
69 content: String,
71 },
72 AssignExpr {
74 location: String,
76 expr: String,
78 },
79 AssignValue {
81 location: String,
83 value: Value,
85 },
86 BindVar {
88 name: String,
90 value: Value,
92 },
93 IsLocation {
95 location: String,
97 },
98 ExecScript {
100 script: String,
102 },
103 ForeachItems {
105 array: String,
107 },
108 Restore(Value),
110}
111
112#[derive(Clone, Debug, PartialEq)]
114#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
115pub enum Answer {
116 Unit,
118 Bool(bool),
120 Value(Value),
122 Values(Vec<Value>),
124 Error(EvalError),
126}
127
128#[derive(Clone, Debug, PartialEq)]
130#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
131pub struct TapeEntry {
132 pub request: Request,
134 pub answer: Answer,
136}
137
138#[derive(Clone, Debug, PartialEq)]
140#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
141pub enum OracleInput {
142 Start(StartInput),
144 Step(Input),
146}
147
148#[derive(Clone, Debug, PartialEq)]
151#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
152pub struct OracleRecord {
153 pub input: OracleInput,
155 pub tape: Vec<TapeEntry>,
157 pub trace: MacrostepTrace,
159}
160
161pub struct TapeDatamodel<'a> {
163 inner: &'a mut dyn Datamodel,
164 entries: Vec<TapeEntry>,
165}
166
167impl<'a> TapeDatamodel<'a> {
168 pub fn new(inner: &'a mut dyn Datamodel) -> Self {
170 TapeDatamodel {
171 inner,
172 entries: Vec::new(),
173 }
174 }
175
176 pub fn entries(&self) -> &[TapeEntry] {
178 &self.entries
179 }
180
181 pub fn take(&mut self) -> Vec<TapeEntry> {
183 core::mem::take(&mut self.entries)
184 }
185
186 fn log(&mut self, request: Request, answer: Answer) {
187 self.entries.push(TapeEntry { request, answer });
188 }
189}
190
191fn unit(r: &Result<(), EvalError>) -> Answer {
192 match r {
193 Ok(()) => Answer::Unit,
194 Err(e) => Answer::Error(e.clone()),
195 }
196}
197
198impl Datamodel for TapeDatamodel<'_> {
199 fn name(&self) -> &str {
200 self.inner.name()
201 }
202
203 fn init_session(&mut self, info: &SessionInfo) -> Result<(), EvalError> {
204 let r = self.inner.init_session(info);
205 self.log(Request::InitSession(info.clone()), unit(&r));
206 r
207 }
208
209 fn set_environment(&mut self, env: &Environment) {
210 self.inner.set_environment(env);
211 self.log(Request::SetEnvironment(*env), Answer::Unit);
212 }
213
214 fn declare(&mut self, id: &str) -> Result<(), EvalError> {
215 let r = self.inner.declare(id);
216 self.log(Request::Declare { id: id.into() }, unit(&r));
217 r
218 }
219
220 fn set_event(&mut self, event: &Event) {
221 self.inner.set_event(event);
222 self.log(Request::SetEvent(event.clone()), Answer::Unit);
223 }
224
225 fn check_event(&self, event: &Event) -> Result<(), EvalError> {
227 self.inner.check_event(event)
228 }
229
230 fn eval_cond(&mut self, expr: &str, states: &dyn StateQuery) -> Result<bool, EvalError> {
231 let r = self.inner.eval_cond(expr, states);
232 let a = match &r {
233 Ok(b) => Answer::Bool(*b),
234 Err(e) => Answer::Error(e.clone()),
235 };
236 self.log(Request::EvalCond { expr: expr.into() }, a);
237 r
238 }
239
240 fn eval_value(&mut self, expr: &str, states: &dyn StateQuery) -> Result<Value, EvalError> {
241 let r = self.inner.eval_value(expr, states);
242 let a = match &r {
243 Ok(v) => Answer::Value(v.clone()),
244 Err(e) => Answer::Error(e.clone()),
245 };
246 self.log(Request::EvalValue { expr: expr.into() }, a);
247 r
248 }
249
250 fn eval_content(&mut self, content: &str) -> Result<Value, EvalError> {
251 let r = self.inner.eval_content(content);
252 let a = match &r {
253 Ok(v) => Answer::Value(v.clone()),
254 Err(e) => Answer::Error(e.clone()),
255 };
256 self.log(
257 Request::EvalContent {
258 content: content.into(),
259 },
260 a,
261 );
262 r
263 }
264
265 fn assign_expr(
266 &mut self,
267 location: &str,
268 expr: &str,
269 states: &dyn StateQuery,
270 ) -> Result<(), EvalError> {
271 let r = self.inner.assign_expr(location, expr, states);
272 self.log(
273 Request::AssignExpr {
274 location: location.into(),
275 expr: expr.into(),
276 },
277 unit(&r),
278 );
279 r
280 }
281
282 fn assign_value(&mut self, location: &str, value: Value) -> Result<(), EvalError> {
283 let req = Request::AssignValue {
284 location: location.into(),
285 value: value.clone(),
286 };
287 let r = self.inner.assign_value(location, value);
288 self.log(req, unit(&r));
289 r
290 }
291
292 fn bind_var(&mut self, name: &str, value: Value) -> Result<(), EvalError> {
293 let req = Request::BindVar {
294 name: name.into(),
295 value: value.clone(),
296 };
297 let r = self.inner.bind_var(name, value);
298 self.log(req, unit(&r));
299 r
300 }
301
302 fn is_location(&mut self, location: &str) -> bool {
303 let r = self.inner.is_location(location);
304 self.log(
305 Request::IsLocation {
306 location: location.into(),
307 },
308 Answer::Bool(r),
309 );
310 r
311 }
312
313 fn exec_script(&mut self, script: &str, states: &dyn StateQuery) -> Result<(), EvalError> {
314 let r = self.inner.exec_script(script, states);
315 self.log(
316 Request::ExecScript {
317 script: script.into(),
318 },
319 unit(&r),
320 );
321 r
322 }
323
324 fn foreach_items(
325 &mut self,
326 array: &str,
327 states: &dyn StateQuery,
328 ) -> Result<Vec<Value>, EvalError> {
329 let r = self.inner.foreach_items(array, states);
330 let a = match &r {
331 Ok(v) => Answer::Values(v.clone()),
332 Err(e) => Answer::Error(e.clone()),
333 };
334 self.log(
335 Request::ForeachItems {
336 array: array.into(),
337 },
338 a,
339 );
340 r
341 }
342
343 fn snapshot(&self) -> Value {
344 self.inner.snapshot()
345 }
346
347 fn restore(&mut self, snapshot: &Value) -> Result<(), EvalError> {
348 let r = self.inner.restore(snapshot);
349 self.log(Request::Restore(snapshot.clone()), unit(&r));
350 r
351 }
352}