wickra_benchmark_core/
benchmark.rs1use crate::case::{BenchmarkCase, Candle};
5use crate::error::{Error, Result};
6use crate::hash::canonicalize;
7use crate::runner::{run_case, run_suite_inline};
8use crate::suite::Suite;
9use serde::Deserialize;
10use serde_json::{json, Value};
11use std::collections::BTreeMap;
12use wickra_backtest_core::version as engine_version;
13
14#[derive(Debug, Clone, Copy, Default)]
18pub struct Benchmark;
19
20#[derive(Deserialize)]
21struct RunCaseReq {
22 case: BenchmarkCase,
23 data: Vec<Candle>,
24}
25
26#[derive(Deserialize)]
27struct RunSuiteReq {
28 suite: Suite,
29 #[serde(default)]
30 datasets: BTreeMap<String, Vec<Candle>>,
31}
32
33#[derive(Deserialize)]
34struct ListCasesReq {
35 suite: Suite,
36}
37
38impl Benchmark {
39 #[must_use]
41 pub fn new() -> Self {
42 Self
43 }
44
45 #[must_use]
47 pub fn version() -> &'static str {
48 env!("CARGO_PKG_VERSION")
49 }
50
51 pub fn command_json(&self, cmd_json: &str) -> Result<String> {
55 let value = dispatch(cmd_json);
56 canonicalize(&value)
57 }
58}
59
60fn dispatch(cmd_json: &str) -> Value {
61 match dispatch_inner(cmd_json) {
62 Ok(v) => v,
63 Err(e) => json!({ "ok": false, "error": e.to_string() }),
64 }
65}
66
67fn dispatch_inner(cmd_json: &str) -> Result<Value> {
68 let env: Value = serde_json::from_str(cmd_json).map_err(|e| Error::Parse(e.to_string()))?;
69 let cmd = env.get("cmd").and_then(Value::as_str).unwrap_or("");
70 match cmd {
71 "run_case" => {
72 let req: RunCaseReq =
73 serde_json::from_value(env).map_err(|e| Error::Parse(e.to_string()))?;
74 let result = run_case(&req.case, &req.data)?;
75 serde_json::to_value(result).map_err(|e| Error::BadCase(e.to_string()))
76 }
77 "run_suite" => {
78 let req: RunSuiteReq =
79 serde_json::from_value(env).map_err(|e| Error::Parse(e.to_string()))?;
80 let report = run_suite_inline(&req.suite, &req.datasets)?;
81 serde_json::to_value(report).map_err(|e| Error::BadCase(e.to_string()))
82 }
83 "list_cases" => {
84 let req: ListCasesReq =
85 serde_json::from_value(env).map_err(|e| Error::Parse(e.to_string()))?;
86 req.suite.validate()?;
87 Ok(json!({ "ids": req.suite.case_ids() }))
88 }
89 "version" => Ok(json!({
90 "version": Benchmark::version(),
91 "engine_version": engine_version(),
92 })),
93 other => Err(Error::Parse(format!("unknown cmd: {other}"))),
94 }
95}