actix_settings/settings/
timeout.rs1use std::fmt;
2
3use once_cell::sync::Lazy;
4use regex::Regex;
5use serde::de;
6
7use crate::{AsResult, Error, Parse};
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub enum Timeout {
12 Default,
14
15 Milliseconds(usize),
17
18 Seconds(usize),
20}
21
22impl Parse for Timeout {
23 fn parse(string: &str) -> AsResult<Self> {
24 pub static FMT: Lazy<Regex> = Lazy::new(|| {
25 Regex::new(r"^\d+ (milliseconds|seconds)$").expect("Failed to compile regex: FMT")
26 });
27
28 pub static DIGITS: Lazy<Regex> =
29 Lazy::new(|| Regex::new(r"^\d+").expect("Failed to compile regex: DIGITS"));
30
31 pub static UNIT: Lazy<Regex> = Lazy::new(|| {
32 Regex::new(r"(milliseconds|seconds)$").expect("Failed to compile regex: UNIT")
33 });
34
35 macro_rules! invalid_value {
36 ($got:expr) => {
37 Err(InvalidValue! {
38 expected: "a string of the format \"N seconds\" or \"N milliseconds\" where N is an integer > 0",
39 got: $got,
40 })
41 }
42 }
43
44 match string {
45 "default" => Ok(Timeout::Default),
46
47 string if !FMT.is_match(string) => invalid_value!(string),
48
49 string => match (DIGITS.find(string), UNIT.find(string)) {
50 (None, _) | (_, None) => invalid_value!(string),
51
52 (Some(digits), Some(unit)) => {
53 let digits = &string[digits.range()];
54 let unit = &string[unit.range()];
55
56 match (digits.parse(), unit) {
57 (Ok(n), "milliseconds") => Ok(Timeout::Milliseconds(n)),
58 (Ok(n), "seconds") => Ok(Timeout::Seconds(n)),
59 _ => invalid_value!(string),
60 }
61 }
62 },
63 }
64 }
65}
66
67impl<'de> de::Deserialize<'de> for Timeout {
68 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
69 where
70 D: de::Deserializer<'de>,
71 {
72 struct TimeoutVisitor;
73
74 impl de::Visitor<'_> for TimeoutVisitor {
75 type Value = Timeout;
76
77 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 let msg = "Either \"default\", \"disabled\", \"os\", or a string of the format \"N seconds\" where N is an integer > 0";
79 f.write_str(msg)
80 }
81
82 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
83 where
84 E: de::Error,
85 {
86 match Timeout::parse(value) {
87 Ok(num_workers) => Ok(num_workers),
88 Err(Error::InvalidValue { expected, got, .. }) => Err(
89 de::Error::invalid_value(de::Unexpected::Str(&got), &expected),
90 ),
91 Err(_) => unreachable!(),
92 }
93 }
94 }
95
96 deserializer.deserialize_string(TimeoutVisitor)
97 }
98}