use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum Status {
#[default]
Open,
InProgress,
Blocked,
Deferred,
Closed,
Tombstone,
Pinned,
Hooked,
}
impl Status {
pub fn is_active(&self) -> bool {
matches!(self, Status::Open | Status::InProgress | Status::Blocked)
}
pub fn is_terminal(&self) -> bool {
matches!(self, Status::Closed | Status::Tombstone)
}
pub fn blocks_dependents(&self) -> bool {
!matches!(self, Status::Closed | Status::Tombstone)
}
pub fn all() -> &'static [Status] {
&[
Status::Open,
Status::InProgress,
Status::Blocked,
Status::Deferred,
Status::Closed,
Status::Tombstone,
Status::Pinned,
Status::Hooked,
]
}
pub fn as_str(&self) -> &'static str {
match self {
Status::Open => "open",
Status::InProgress => "in_progress",
Status::Blocked => "blocked",
Status::Deferred => "deferred",
Status::Closed => "closed",
Status::Tombstone => "tombstone",
Status::Pinned => "pinned",
Status::Hooked => "hooked",
}
}
}
impl fmt::Display for Status {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl FromStr for Status {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"open" => Ok(Status::Open),
"in_progress" | "in-progress" | "inprogress" => Ok(Status::InProgress),
"blocked" => Ok(Status::Blocked),
"deferred" => Ok(Status::Deferred),
"closed" => Ok(Status::Closed),
"tombstone" => Ok(Status::Tombstone),
"pinned" => Ok(Status::Pinned),
"hooked" => Ok(Status::Hooked),
_ => Err(format!("unknown status: {}", s)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_status_roundtrip() {
for status in Status::all() {
let s = status.as_str();
let parsed: Status = s.parse().unwrap();
assert_eq!(*status, parsed);
}
}
#[test]
fn test_status_serde() {
let status = Status::InProgress;
let json = serde_json::to_string(&status).unwrap();
assert_eq!(json, "\"in_progress\"");
let parsed: Status = serde_json::from_str(&json).unwrap();
assert_eq!(status, parsed);
}
}