1use std::fmt;
2use std::fs;
3use std::path::Path;
4
5use crate::engine::{Engine, EngineConfig};
6use crate::proto::{Frame, SceneMap};
7
8#[derive(Debug)]
9pub enum FixtureError {
10 Io(std::io::Error),
11 Json(serde_json::Error),
12}
13
14impl fmt::Display for FixtureError {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 match self {
17 FixtureError::Io(e) => write!(f, "failed to read fixture file: {e}"),
18 FixtureError::Json(e) => write!(f, "failed to parse fixture JSON: {e}"),
19 }
20 }
21}
22
23impl std::error::Error for FixtureError {}
24
25impl From<std::io::Error> for FixtureError {
26 fn from(e: std::io::Error) -> Self {
27 FixtureError::Io(e)
28 }
29}
30
31impl From<serde_json::Error> for FixtureError {
32 fn from(e: serde_json::Error) -> Self {
33 FixtureError::Json(e)
34 }
35}
36
37pub fn replay_fixture(
45 path: impl AsRef<Path>,
46 config: EngineConfig,
47) -> Result<Vec<SceneMap>, FixtureError> {
48 let data = fs::read_to_string(path)?;
49 let frames: Vec<Frame> = serde_json::from_str(&data)?;
50
51 let mut engine = Engine::with_config(config);
52 Ok(frames.into_iter().map(|frame| engine.ingest_frame(frame).clone()).collect())
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn missing_file_reports_an_io_error() {
61 let result = replay_fixture("/no/such/fixture.json", EngineConfig::default());
62 assert!(matches!(result, Err(FixtureError::Io(_))));
63 }
64}