sword_layers/req_timeout/
config.rs

1use console::style;
2use duration_str::parse as parse_duration;
3use serde::{Deserialize, Serialize};
4use std::time::Duration;
5
6use crate::DisplayConfig;
7
8/// ### Request Timeout Configuration
9/// Configuration for the Request Timeout Layer
10/// This configuration allows you to set a maximum duration for request handling.
11///
12/// #### Fields:
13/// - `enabled`: A boolean indicating if request timeout is enabled.
14/// - `duration`: A string representing the timeout duration (e.g., "30s", "5m").
15/// - `parsed`: The parsed duration in std::time::Duration derived from `duration`.
16/// - `display`: A boolean indicating if the configuration should be displayed.
17#[derive(Debug, Clone, Serialize)]
18pub struct RequestTimeoutConfig {
19    pub enabled: bool,
20    pub duration: String,
21
22    #[serde(skip)]
23    pub parsed: Duration,
24
25    #[serde(default)]
26    pub display: bool,
27}
28
29impl DisplayConfig for RequestTimeoutConfig {
30    fn display(&self) {
31        if !self.display {
32            return;
33        }
34
35        println!("\n{}", style("Request Timeout Configuration:").bold());
36
37        if self.enabled {
38            println!("  ↳  Request Timeout: {}", self.duration);
39        } else {
40            println!("  ↳  Request Timeout: disabled");
41        }
42    }
43}
44
45impl Default for RequestTimeoutConfig {
46    fn default() -> Self {
47        let duration_str = "30s".to_string();
48        let parsed_duration =
49            parse_duration(&duration_str).unwrap_or_else(|_| Duration::from_secs(30));
50
51        RequestTimeoutConfig {
52            enabled: false,
53            duration: duration_str,
54            parsed: parsed_duration,
55            display: false,
56        }
57    }
58}
59
60impl<'de> Deserialize<'de> for RequestTimeoutConfig {
61    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
62    where
63        D: serde::Deserializer<'de>,
64    {
65        use serde::de::{Error, MapAccess, Visitor};
66        use std::fmt;
67
68        struct TimeoutLimitVisitor;
69
70        impl<'de> Visitor<'de> for TimeoutLimitVisitor {
71            type Value = RequestTimeoutConfig;
72
73            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
74                formatter.write_str(
75                    "a map with 'enabled' (bool), 'duration' (string), and optional 'display' (bool) fields",
76                )
77            }
78
79            // Deserialize from a map/object
80            fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
81            where
82                M: MapAccess<'de>,
83            {
84                let mut enabled = None;
85                let mut duration = None;
86                let mut display = None;
87
88                while let Some(key) = map.next_key::<String>()? {
89                    match key.as_str() {
90                        "enabled" => enabled = Some(map.next_value()?),
91                        "duration" => duration = Some(map.next_value()?),
92                        "display" => display = Some(map.next_value()?),
93                        _ => {
94                            let _: serde::de::IgnoredAny = map.next_value()?;
95                        }
96                    }
97                }
98
99                let enabled = enabled.ok_or_else(|| Error::missing_field("enabled"))?;
100                let duration: String = duration.ok_or_else(|| Error::missing_field("duration"))?;
101                let parsed = parse_duration(&duration).map_err(Error::custom)?;
102
103                Ok(RequestTimeoutConfig {
104                    enabled,
105                    duration,
106                    parsed,
107                    display: display.unwrap_or_else(|| false),
108                })
109            }
110        }
111
112        deserializer.deserialize_any(TimeoutLimitVisitor)
113    }
114}