use std::fmt;
use std::str::FromStr;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LifecycleStatus {
Nascent,
Active,
Dormant,
Suspended,
Terminated,
Archived,
}
impl LifecycleStatus {
pub fn as_str(&self) -> &'static str {
match self {
Self::Nascent => "nascent",
Self::Active => "active",
Self::Dormant => "dormant",
Self::Suspended => "suspended",
Self::Terminated => "terminated",
Self::Archived => "archived",
}
}
}
impl fmt::Display for LifecycleStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl FromStr for LifecycleStatus {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"nascent" => Ok(Self::Nascent),
"active" => Ok(Self::Active),
"dormant" => Ok(Self::Dormant),
"suspended" => Ok(Self::Suspended),
"terminated" => Ok(Self::Terminated),
"archived" => Ok(Self::Archived),
_ => Err(format!(
"unknown lifecycle status '{s}'; expected one of: nascent, active, dormant, suspended, terminated, archived"
)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn all_statuses_round_trip() {
let statuses = [
LifecycleStatus::Nascent,
LifecycleStatus::Active,
LifecycleStatus::Dormant,
LifecycleStatus::Suspended,
LifecycleStatus::Terminated,
LifecycleStatus::Archived,
];
for status in statuses {
let s = status.as_str();
let parsed = LifecycleStatus::from_str(s);
assert!(parsed.is_ok(), "Failed to parse: {s}");
assert_eq!(parsed.unwrap_or(LifecycleStatus::Nascent), status);
}
}
#[test]
fn serde_round_trip() {
let status = LifecycleStatus::Active;
let json = serde_json::to_string(&status).unwrap_or_default();
assert_eq!(json, r#""active""#);
let parsed: LifecycleStatus =
serde_json::from_str(&json).unwrap_or(LifecycleStatus::Nascent);
assert_eq!(parsed, status);
}
#[test]
fn unknown_status_returns_error() {
assert!(LifecycleStatus::from_str("running").is_err());
}
}