rusty_beads/types/
issue_type.rs1use serde::{Deserialize, Serialize};
4use std::fmt;
5use std::str::FromStr;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
9#[serde(rename_all = "snake_case")]
10pub enum IssueType {
11 Bug,
13 Feature,
15 #[default]
17 Task,
18 Epic,
20 Chore,
22 Message,
24 Molecule,
26 Gate,
28 Agent,
30 Role,
32 Rig,
34 Convoy,
36 Event,
38 MergeRequest,
40 Slot,
42}
43
44impl IssueType {
45 pub fn all() -> &'static [IssueType] {
47 &[
48 IssueType::Bug,
49 IssueType::Feature,
50 IssueType::Task,
51 IssueType::Epic,
52 IssueType::Chore,
53 IssueType::Message,
54 IssueType::Molecule,
55 IssueType::Gate,
56 IssueType::Agent,
57 IssueType::Role,
58 IssueType::Rig,
59 IssueType::Convoy,
60 IssueType::Event,
61 IssueType::MergeRequest,
62 IssueType::Slot,
63 ]
64 }
65
66 pub fn as_str(&self) -> &'static str {
68 match self {
69 IssueType::Bug => "bug",
70 IssueType::Feature => "feature",
71 IssueType::Task => "task",
72 IssueType::Epic => "epic",
73 IssueType::Chore => "chore",
74 IssueType::Message => "message",
75 IssueType::Molecule => "molecule",
76 IssueType::Gate => "gate",
77 IssueType::Agent => "agent",
78 IssueType::Role => "role",
79 IssueType::Rig => "rig",
80 IssueType::Convoy => "convoy",
81 IssueType::Event => "event",
82 IssueType::MergeRequest => "merge_request",
83 IssueType::Slot => "slot",
84 }
85 }
86
87 pub fn is_container(&self) -> bool {
89 matches!(self, IssueType::Epic | IssueType::Molecule | IssueType::Convoy)
90 }
91
92 pub fn is_agent_type(&self) -> bool {
94 matches!(self, IssueType::Agent | IssueType::Role | IssueType::Rig)
95 }
96}
97
98impl fmt::Display for IssueType {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 write!(f, "{}", self.as_str())
101 }
102}
103
104impl FromStr for IssueType {
105 type Err = String;
106
107 fn from_str(s: &str) -> Result<Self, Self::Err> {
108 match s.to_lowercase().as_str() {
109 "bug" => Ok(IssueType::Bug),
110 "feature" => Ok(IssueType::Feature),
111 "task" => Ok(IssueType::Task),
112 "epic" => Ok(IssueType::Epic),
113 "chore" => Ok(IssueType::Chore),
114 "message" => Ok(IssueType::Message),
115 "molecule" => Ok(IssueType::Molecule),
116 "gate" => Ok(IssueType::Gate),
117 "agent" => Ok(IssueType::Agent),
118 "role" => Ok(IssueType::Role),
119 "rig" => Ok(IssueType::Rig),
120 "convoy" => Ok(IssueType::Convoy),
121 "event" => Ok(IssueType::Event),
122 "merge_request" | "merge-request" | "mergerequest" => Ok(IssueType::MergeRequest),
123 "slot" => Ok(IssueType::Slot),
124 _ => Err(format!("unknown issue type: {}", s)),
125 }
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 #[test]
134 fn test_issue_type_roundtrip() {
135 for issue_type in IssueType::all() {
136 let s = issue_type.as_str();
137 let parsed: IssueType = s.parse().unwrap();
138 assert_eq!(*issue_type, parsed);
139 }
140 }
141}