1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use derive_more::{Display, Error};
use serde::{Deserialize, Serialize};
use std::{num::ParseFloatError, str::FromStr, time::Duration};
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct ServerConfig {
pub shutdown: Shutdown,
}
#[derive(Copy, Clone, Debug, Display, PartialEq, Eq, Serialize, Deserialize)]
pub enum Shutdown {
#[display(fmt = "after={}", "_0.as_secs_f32()")]
After(Duration),
#[display(fmt = "lonely={}", "_0.as_secs_f32()")]
Lonely(Duration),
#[display(fmt = "never")]
Never,
}
impl Shutdown {
pub fn duration(&self) -> Option<Duration> {
match self {
Self::Never => None,
Self::After(x) | Self::Lonely(x) => Some(*x),
}
}
}
impl Default for Shutdown {
fn default() -> Self {
Self::Never
}
}
#[derive(Clone, Debug, Display, Error, PartialEq, Eq)]
pub enum ShutdownParseError {
#[display(fmt = "Bad value for after: {}", _0)]
BadValueForAfter(ParseFloatError),
#[display(fmt = "Bad value for lonely: {}", _0)]
BadValueForLonely(ParseFloatError),
#[display(fmt = "Missing key")]
MissingKey,
#[display(fmt = "Unknown key")]
UnknownKey,
}
impl FromStr for Shutdown {
type Err = ShutdownParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.eq_ignore_ascii_case("never") {
Ok(Self::Never)
} else {
let (left, right) = s.split_once('=').ok_or(ShutdownParseError::MissingKey)?;
let left = left.trim();
let right = right.trim();
if left.eq_ignore_ascii_case("after") {
Ok(Self::After(Duration::from_secs_f32(
right
.parse()
.map_err(ShutdownParseError::BadValueForAfter)?,
)))
} else if left.eq_ignore_ascii_case("lonely") {
Ok(Self::Lonely(Duration::from_secs_f32(
right
.parse()
.map_err(ShutdownParseError::BadValueForLonely)?,
)))
} else {
Err(ShutdownParseError::UnknownKey)
}
}
}
}