#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn capture_snapshot(&mut self) -> Result<ExecutionSnapshot, String> {
if !self.is_recording {
return Err("Not recording".to_string());
}
let dap = self
.dap_server
.lock()
.map_err(|e| format!("Failed to lock DAP server: {}", e))?;
let stopped_file = dap
.current_stopped_file()
.ok_or_else(|| "No file currently stopped at".to_string())?;
let stopped_line = dap
.current_stopped_line()
.ok_or_else(|| "No line currently stopped at".to_string())?;
let variables_vec = dap
.get_variables_at_line(&stopped_file, stopped_line)
.map_err(|e| format!("Failed to get variables: {}", e))?;
let mut variables = HashMap::new();
for var in variables_vec {
variables.insert(
var.name.clone(),
serde_json::json!({
"value": var.value,
"type": var.type_info
}),
);
}
let call_stack = vec![StackFrame {
id: 1,
name: "main".to_string(),
source: Some(super::types::Source {
name: Some(stopped_file.clone()),
path: Some(stopped_file.clone()),
}),
line: stopped_line as i64,
column: 0,
}];
let snapshot = ExecutionSnapshot {
timestamp: SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("internal error")
.as_nanos() as u64,
sequence: self.snapshots.len(),
variables,
call_stack,
location: SourceLocation {
file: stopped_file,
line: stopped_line,
column: Some(0),
},
delta: None, };
if let Some(ref mut writer) = self.writer {
let recording_snapshot = Self::convert_to_recording_snapshot(&snapshot);
writer
.write_snapshot(&recording_snapshot)
.map_err(|e| format!("Failed to write snapshot to recording: {}", e))?;
}
self.snapshots.push(snapshot.clone());
Ok(snapshot)
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "non_empty_index")]
pub fn save_to_file(&self, path: &str) -> Result<(), String> {
let json = serde_json::to_string_pretty(&self.snapshots)
.map_err(|e| format!("Failed to serialize: {}", e))?;
std::fs::write(path, json).map_err(|e| format!("Failed to write file: {}", e))?;
Ok(())
}