Skip to main content

cli_engine/
tier.rs

1use std::{fmt, str::FromStr};
2
3use serde::{Deserialize, Serialize};
4
5/// Command risk tier.
6#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
7#[serde(rename_all = "lowercase")]
8pub enum Tier {
9    /// Safe read-only behavior.
10    Read,
11    /// State-changing behavior.
12    Mutate,
13    /// Irreversible or high-risk state-changing behavior.
14    Destructive,
15}
16
17impl Tier {
18    /// Returns true for tiers that should short-circuit under `--dry-run`.
19    #[must_use]
20    pub const fn is_mutating(self) -> bool {
21        matches!(self, Self::Mutate | Self::Destructive)
22    }
23
24    /// Returns the wire string for the tier.
25    #[must_use]
26    pub const fn as_str(self) -> &'static str {
27        match self {
28            Self::Read => "read",
29            Self::Mutate => "mutate",
30            Self::Destructive => "destructive",
31        }
32    }
33}
34
35impl fmt::Display for Tier {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        f.write_str(self.as_str())
38    }
39}
40
41impl FromStr for Tier {
42    type Err = ParseTierError;
43
44    fn from_str(value: &str) -> Result<Self, Self::Err> {
45        match value {
46            "read" => Ok(Self::Read),
47            "mutate" => Ok(Self::Mutate),
48            "destructive" => Ok(Self::Destructive),
49            other => Err(ParseTierError {
50                value: other.to_owned(),
51            }),
52        }
53    }
54}
55
56/// Error returned when parsing an unknown risk tier.
57#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
58#[error("invalid tier {value:?}: must be one of read, mutate, destructive")]
59pub struct ParseTierError {
60    value: String,
61}