proto_sign/compat/
categories.rs

1//! Breaking change categories matching Buf's categorization system
2
3use serde::{Deserialize, Serialize};
4
5/// Breaking change categories that group related rules
6/// These match exactly with Buf's category system
7#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
8pub enum BreakingCategory {
9    /// FILE category - checks for source-code breaking changes at the per-file level
10    File,
11    /// PACKAGE category - checks for source-code breaking changes at the per-package level  
12    Package,
13    /// WIRE category - checks for wire breaking changes for the binary encoding
14    Wire,
15    /// WIRE_JSON category - checks for wire breaking changes for binary or JSON encodings
16    WireJson,
17}
18
19impl BreakingCategory {
20    /// Get the string identifier for this category (matches Buf exactly)
21    pub fn id(&self) -> &'static str {
22        match self {
23            BreakingCategory::File => "FILE",
24            BreakingCategory::Package => "PACKAGE",
25            BreakingCategory::Wire => "WIRE",
26            BreakingCategory::WireJson => "WIRE_JSON",
27        }
28    }
29
30    /// Get the description for this category
31    pub fn description(&self) -> &'static str {
32        match self {
33            BreakingCategory::File => {
34                "Checks that there are no source-code breaking changes at the per-file level."
35            }
36            BreakingCategory::Package => {
37                "Checks that there are no source-code breaking changes at the per-package level."
38            }
39            BreakingCategory::Wire => {
40                "Checks that there are no wire breaking changes for the binary encoding."
41            }
42            BreakingCategory::WireJson => {
43                "Checks that there are no wire breaking changes for the binary or JSON encodings."
44            }
45        }
46    }
47
48    /// Parse category from string ID
49    pub fn from_id(id: &str) -> Option<Self> {
50        match id {
51            "FILE" => Some(BreakingCategory::File),
52            "PACKAGE" => Some(BreakingCategory::Package),
53            "WIRE" => Some(BreakingCategory::Wire),
54            "WIRE_JSON" => Some(BreakingCategory::WireJson),
55            _ => None,
56        }
57    }
58
59    /// Get all available categories
60    pub fn all() -> Vec<Self> {
61        vec![
62            BreakingCategory::File,
63            BreakingCategory::Package,
64            BreakingCategory::Wire,
65            BreakingCategory::WireJson,
66        ]
67    }
68}
69
70impl std::fmt::Display for BreakingCategory {
71    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72        write!(f, "{}", self.id())
73    }
74}
75
76impl std::str::FromStr for BreakingCategory {
77    type Err = String;
78
79    fn from_str(s: &str) -> Result<Self, Self::Err> {
80        Self::from_id(s).ok_or_else(|| format!("Unknown breaking category: {s}"))
81    }
82}