Skip to main content

buildfix_types/wire/
mod.rs

1use serde::{Deserialize, Serialize};
2
3pub mod apply_v1;
4pub mod plan_v1;
5pub mod report_v1;
6
7pub use apply_v1::ApplyV1;
8pub use plan_v1::PlanV1;
9pub use report_v1::ReportV1;
10
11/// Tool information for wire-level schemas (schema-exact).
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct ToolInfoV1 {
14    pub name: String,
15    pub version: String,
16    #[serde(default, skip_serializing_if = "Option::is_none")]
17    pub commit: Option<String>,
18}
19
20/// Errors emitted while converting internal models to wire models.
21#[derive(Debug, Clone)]
22pub enum WireError {
23    MissingToolVersion { context: &'static str },
24}
25
26impl std::fmt::Display for WireError {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        match self {
29            WireError::MissingToolVersion { context } => {
30                write!(f, "missing tool version for {}", context)
31            }
32        }
33    }
34}
35
36impl std::error::Error for WireError {}
37
38#[cfg(test)]
39mod tests {
40    use super::{ToolInfoV1, WireError};
41
42    #[test]
43    fn tool_info_serializes_without_commit_when_none() {
44        let tool = ToolInfoV1 {
45            name: "buildfix".to_string(),
46            version: "1.2.3".to_string(),
47            commit: None,
48        };
49
50        let json = serde_json::to_string(&tool).expect("serialize");
51        assert!(json.contains("\"name\""));
52        assert!(json.contains("\"version\""));
53        assert!(!json.contains("commit"));
54    }
55
56    #[test]
57    fn wire_error_display_includes_context() {
58        let err = WireError::MissingToolVersion { context: "plan" };
59        assert_eq!(err.to_string(), "missing tool version for plan");
60    }
61}