Skip to main content

ferridriver_script/
result.rs

1//! Structured result returned by `ScriptEngine::run`.
2
3use crate::error::ScriptError;
4
5/// Severity of a captured console entry.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
7#[serde(rename_all = "lowercase")]
8pub enum ConsoleLevel {
9  Log,
10  Info,
11  Warn,
12  Error,
13  Debug,
14  /// Emitted by the engine itself (e.g., truncation notices).
15  System,
16}
17
18/// One captured `console.*` call from inside the script.
19#[derive(Debug, Clone, serde::Serialize)]
20pub struct ConsoleEntry {
21  pub level: ConsoleLevel,
22  pub message: String,
23  /// Milliseconds since the script started running.
24  pub ts_ms: u64,
25}
26
27/// Payload returned by a successful script.
28///
29/// `value` is the JSON-serialized return of the script's top-level expression
30/// (or `null` if nothing was returned).
31#[derive(Debug, Clone, serde::Serialize)]
32pub struct ScriptSuccess {
33  pub value: serde_json::Value,
34}
35
36/// Full result of running a script.
37///
38/// Regardless of success or failure, `console` and `duration_ms` are populated.
39/// On failure, `outcome` carries a structured `ScriptError`.
40#[derive(Debug, Clone, serde::Serialize)]
41pub struct ScriptResult {
42  #[serde(flatten)]
43  pub outcome: Outcome,
44  pub duration_ms: u64,
45  pub console: Vec<ConsoleEntry>,
46}
47
48/// Tagged-union representation of success vs failure for JSON output.
49#[derive(Debug, Clone, serde::Serialize)]
50#[serde(tag = "status", rename_all = "snake_case")]
51pub enum Outcome {
52  Ok {
53    #[serde(flatten)]
54    success: ScriptSuccess,
55  },
56  Error {
57    error: ScriptError,
58  },
59}
60
61impl ScriptResult {
62  #[must_use]
63  pub fn ok(value: serde_json::Value, duration_ms: u64, console: Vec<ConsoleEntry>) -> Self {
64    Self {
65      outcome: Outcome::Ok {
66        success: ScriptSuccess { value },
67      },
68      duration_ms,
69      console,
70    }
71  }
72
73  #[must_use]
74  pub fn err(error: ScriptError, duration_ms: u64, console: Vec<ConsoleEntry>) -> Self {
75    Self {
76      outcome: Outcome::Error { error },
77      duration_ms,
78      console,
79    }
80  }
81
82  #[must_use]
83  pub fn is_ok(&self) -> bool {
84    matches!(self.outcome, Outcome::Ok { .. })
85  }
86
87  #[must_use]
88  pub fn is_err(&self) -> bool {
89    matches!(self.outcome, Outcome::Error { .. })
90  }
91}