Skip to main content

weimo_wdf/
diagnostic.rs

1use serde::Serialize;
2
3/// A single structured validation failure.
4///
5/// Diagnostics are data, not formatted strings: map `code` to UI behavior,
6/// `path` to the offending node (as JSON-pointer-like segments), and `message`
7/// to a user-facing message. All diagnostics produced by this crate have
8/// `severity == "error"` in v0.1.
9///
10/// `source` names the layer that rejected the input: `"wdf"` for the model
11/// and validator, `"markdown"`, `"prosemirror"` or `"apple"` for an adapter.
12#[derive(Clone, Debug, PartialEq, Serialize)]
13pub struct Diagnostic {
14    /// Layer that produced the failure: `wdf`, `markdown`, `prosemirror`, `apple`.
15    pub source: String,
16    /// Stable machine-readable code, e.g. `wdf.unsupported_mark`.
17    pub code: String,
18    /// Always `"error"` in v0.1.
19    pub severity: String,
20    /// JSON-pointer-like path to the offending value; may be empty.
21    pub path: Vec<serde_json::Value>,
22    /// Human-readable explanation.
23    pub message: String,
24}
25
26impl Diagnostic {
27    /// Creates an error diagnostic; attach a path with [`Diagnostic::at`].
28    pub fn error(source: &str, code: &str, message: impl Into<String>) -> Self {
29        Self {
30            source: source.to_string(),
31            code: code.to_string(),
32            severity: "error".to_string(),
33            path: vec![],
34            message: message.into(),
35        }
36    }
37
38    /// Sets the JSON path of the offending value.
39    pub fn at(mut self, path: Vec<serde_json::Value>) -> Self {
40        self.path = path;
41        self
42    }
43}
44
45/// All failures for one input; empty means the input is valid.
46pub type Diagnostics = Vec<Diagnostic>;