Skip to main content

shep_core/protocol/request/
response_name.rs

1//! [`Response::name`]: which answer arrived, for an error that must not
2//! print its body.
3
4use super::Response;
5
6impl Response {
7    /// The variant's name, never its body, for an error saying which answer
8    /// arrived.
9    ///
10    /// A listing would flood the message, and [`Self::DogSection`] carries
11    /// credentials. Exhaustive here, so a new variant names itself.
12    #[must_use]
13    pub const fn name(&self) -> &'static str {
14        match self {
15            Self::Pong => "Pong",
16            Self::Flock(_) => "Flock",
17            Self::HostUsage(_) => "HostUsage",
18            Self::Described(_) => "Described",
19            Self::Started(_) => "Started",
20            Self::Added(_) => "Added",
21            Self::Drifted(_) => "Drifted",
22            Self::Applied(_) => "Applied",
23            Self::SheepConfig(_) => "SheepConfig",
24            Self::SheepEnvSet { .. } => "SheepEnvSet",
25            Self::SheepEnvBatch { .. } => "SheepEnvBatch",
26            Self::SheepFieldSet { .. } => "SheepFieldSet",
27            Self::DogSheepSettings { .. } => "DogSheepSettings",
28            Self::SheepDogSettingsSet { .. } => "SheepDogSettingsSet",
29            Self::DogConfigSet { .. } => "DogConfigSet",
30            Self::SecretsPut { .. } => "SecretsPut",
31            Self::Stopped(_) => "Stopped",
32            Self::Disabled(_) => "Disabled",
33            Self::Enabled(_) => "Enabled",
34            Self::Restarted { .. } => "Restarted",
35            Self::Reloading { .. } => "Reloading",
36            Self::Scaled(_) => "Scaled",
37            Self::SmitPainted(_) => "SmitPainted",
38            Self::Deleted(_) => "Deleted",
39            Self::Reopened(_) => "Reopened",
40            Self::Flushed(_) => "Flushed",
41            Self::Triggered(_) => "Triggered",
42            Self::Signalled(_) => "Signalled",
43            Self::SentLine(_) => "SentLine",
44            Self::RollSaved { .. } => "RollSaved",
45            Self::Mustered(_) => "Mustered",
46            Self::DogSection { .. } => "DogSection",
47            Self::DogStarted(_) => "DogStarted",
48            Self::DogStaleness { .. } => "DogStaleness",
49            Self::HandoverFitness { .. } => "HandoverFitness",
50            Self::Subscribed => "Subscribed",
51            Self::ShuttingDown => "ShuttingDown",
52        }
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::super::process::sample_info;
59    use super::*;
60
61    /// An error names the variant and a captured frame names the tag, so the
62    /// two have to agree. A sample of shapes: unit, listing, struct, secret.
63    #[test]
64    fn a_responses_name_is_its_wire_tag_in_the_variants_spelling() {
65        let responses = [
66            Response::Pong,
67            Response::Flock(vec![sample_info()]),
68            Response::HostUsage(None),
69            Response::RollSaved {
70                path: "/home/ada/.shep/flock.json".to_string(),
71                apps: 2,
72            },
73            Response::DogSection {
74                toml: "webhook = \"https://example.invalid/hook\"\n"
75                    .to_string()
76                    .into(),
77            },
78            Response::HandoverFitness { refusal: None },
79            Response::ShuttingDown,
80        ];
81        for response in responses {
82            let wire = serde_json::to_value(&response).unwrap();
83            let snake: String = response
84                .name()
85                .chars()
86                .enumerate()
87                .flat_map(|(at, c)| {
88                    let gap = (at > 0 && c.is_ascii_uppercase()).then_some('_');
89                    gap.into_iter().chain(c.to_lowercase())
90                })
91                .collect();
92            assert_eq!(wire["kind"], snake.as_str(), "{}", response.name());
93        }
94    }
95}