1use crate::errors::*;
2
3use serde::de::{self, Deserialize, Deserializer};
4use std::borrow::Cow;
5use std::fmt::{self, Display};
6use std::marker::PhantomData;
7use std::ops::RangeInclusive;
8use std::str::FromStr;
9use std::time::Duration;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct Seconds<const ALLOW_ONCE: bool = true>(pub Duration);
13
14impl<const ALLOW_ONCE: bool> From<u64> for Seconds<ALLOW_ONCE> {
15 fn from(v: u64) -> Self {
16 Self::new(v)
17 }
18}
19
20impl<const ALLOW_ONCE: bool> Seconds<ALLOW_ONCE> {
21 pub fn new(value: u64) -> Self {
22 Self(Duration::from_secs(value))
23 }
24
25 pub fn timer(self) -> tokio::time::Interval {
26 let mut timer = tokio::time::interval_at(tokio::time::Instant::now() + self.0, self.0);
27 timer.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay);
28 timer
29 }
30
31 pub fn seconds(self) -> u64 {
32 self.0.as_secs()
33 }
34}
35
36impl<'de, const ALLOW_ONCE: bool> Deserialize<'de> for Seconds<ALLOW_ONCE> {
37 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
38 where
39 D: Deserializer<'de>,
40 {
41 struct SecondsVisitor<const ALLOW_ONCE: bool>;
42
43 impl<const ALLOW_ONCE: bool> de::Visitor<'_> for SecondsVisitor<ALLOW_ONCE> {
44 type Value = Seconds<ALLOW_ONCE>;
45
46 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
47 formatter.write_str("\"once\", i64 or f64")
48 }
49
50 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
51 where
52 E: de::Error,
53 {
54 if ALLOW_ONCE && v == "once" {
55 Ok(Seconds(Duration::from_secs(60 * 60 * 24 * 365)))
56 } else {
57 Err(E::custom(format!("'{v}' is not a valid duration")))
58 }
59 }
60
61 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
62 where
63 E: de::Error,
64 {
65 Ok(Seconds(Duration::from_secs(v as u64)))
66 }
67
68 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
69 where
70 E: de::Error,
71 {
72 Ok(Seconds(Duration::from_secs_f64(v)))
73 }
74 }
75
76 deserializer.deserialize_any(SecondsVisitor)
77 }
78}
79
80#[derive(Debug, Clone)]
81pub struct ShellString(pub Cow<'static, str>);
82
83impl<T> From<T> for ShellString
84where
85 T: Into<Cow<'static, str>>,
86{
87 fn from(v: T) -> Self {
88 Self(v.into())
89 }
90}
91
92impl<'de> Deserialize<'de> for ShellString {
93 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
94 where
95 D: Deserializer<'de>,
96 {
97 struct Visitor;
98
99 impl de::Visitor<'_> for Visitor {
100 type Value = ShellString;
101
102 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
103 formatter.write_str("text")
104 }
105
106 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
107 where
108 E: de::Error,
109 {
110 Ok(ShellString(v.to_string().into()))
111 }
112 }
113
114 deserializer.deserialize_any(Visitor)
115 }
116}
117
118impl ShellString {
119 pub fn new<T: Into<Cow<'static, str>>>(value: T) -> Self {
120 Self(value.into())
121 }
122
123 pub fn expand(&self) -> Result<Cow<str>> {
124 shellexpand::full(&self.0).error("Failed to expand string")
125 }
126}
127
128#[derive(Debug, Default, Clone)]
130pub struct RangeMap<K, V>(Vec<(RangeInclusive<K>, V)>);
131
132impl<K, V> RangeMap<K, V> {
133 pub fn get(&self, key: &K) -> Option<&V>
134 where
135 K: PartialOrd,
136 {
137 self.0
138 .iter()
139 .find_map(|(k, v)| k.contains(key).then_some(v))
140 }
141}
142
143impl<K, V> From<Vec<(RangeInclusive<K>, V)>> for RangeMap<K, V> {
144 fn from(vec: Vec<(RangeInclusive<K>, V)>) -> Self {
145 Self(vec)
146 }
147}
148
149impl<'de, K, V> Deserialize<'de> for RangeMap<K, V>
150where
151 K: FromStr,
152 K::Err: Display,
153 V: Deserialize<'de>,
154{
155 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
156 where
157 D: Deserializer<'de>,
158 {
159 struct Visitor<K, V>(PhantomData<(K, V)>);
160
161 impl<'de, K, V> de::Visitor<'de> for Visitor<K, V>
162 where
163 K: FromStr,
164 K::Err: Display,
165 V: Deserialize<'de>,
166 {
167 type Value = RangeMap<K, V>;
168
169 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
170 formatter.write_str("range map")
171 }
172
173 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
174 where
175 A: de::MapAccess<'de>,
176 {
177 let mut vec = Vec::with_capacity(map.size_hint().unwrap_or(2));
178 while let Some((range, val)) = map.next_entry::<String, V>()? {
179 let (start, end) = range
180 .split_once("..")
181 .error("invalid range")
182 .serde_error()?;
183 let start: K = start.parse().serde_error()?;
184 let end: K = end.parse().serde_error()?;
185 vec.push((start..=end, val));
186 }
187 Ok(RangeMap(vec))
188 }
189 }
190
191 deserializer.deserialize_map(Visitor(PhantomData))
192 }
193}
194
195#[derive(Debug, Clone)]
196pub struct SerdeRegex(pub regex::Regex);
197
198impl PartialEq for SerdeRegex {
199 fn eq(&self, other: &Self) -> bool {
200 self.0.as_str() == other.0.as_str()
201 }
202}
203
204impl Eq for SerdeRegex {}
205
206impl std::hash::Hash for SerdeRegex {
207 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
208 self.0.as_str().hash(state);
209 }
210}
211
212impl<'de> Deserialize<'de> for SerdeRegex {
213 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
214 where
215 D: Deserializer<'de>,
216 {
217 struct Visitor;
218
219 impl de::Visitor<'_> for Visitor {
220 type Value = SerdeRegex;
221
222 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
223 formatter.write_str("a regex")
224 }
225
226 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
227 where
228 E: de::Error,
229 {
230 regex::Regex::new(v).map(SerdeRegex).map_err(E::custom)
231 }
232 }
233
234 deserializer.deserialize_any(Visitor)
235 }
236}
237
238pub struct DisplaySlice<'a, T>(pub &'a [T]);
240
241impl<T: Display> Display for DisplaySlice<'_, T> {
242 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
243 struct DisplayAsDebug<'a, T>(&'a T);
244 impl<T: Display> fmt::Debug for DisplayAsDebug<'_, T> {
245 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246 fmt::Display::fmt(self.0, f)
247 }
248 }
249 f.debug_list()
250 .entries(self.0.iter().map(DisplayAsDebug))
251 .finish()
252 }
253}