1use serde::{Deserialize, Serialize};
4
5#[derive(
7 Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize,
8)]
9#[serde(rename_all = "snake_case")]
10#[non_exhaustive]
11pub enum Effort {
12 Low,
14 #[default]
16 Medium,
17 High,
19}
20
21impl Effort {
22 pub const ALL: [Self; 3] = [Self::Low, Self::Medium, Self::High];
24
25 #[must_use]
27 pub const fn as_str(self) -> &'static str {
28 match self {
29 Self::Low => "low",
30 Self::Medium => "medium",
31 Self::High => "high",
32 }
33 }
34}
35
36impl std::fmt::Display for Effort {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 f.write_str(self.as_str())
39 }
40}
41
42#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
44#[error("`{0}` is not an effort level: low, medium or high")]
45pub struct UnknownEffort(pub String);
46
47impl std::str::FromStr for Effort {
48 type Err = UnknownEffort;
49
50 fn from_str(label: &str) -> Result<Self, Self::Err> {
51 Self::ALL
52 .into_iter()
53 .find(|effort| effort.as_str() == label)
54 .ok_or_else(|| UnknownEffort(label.to_owned()))
55 }
56}