1use std::str::FromStr;
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq)]
4pub enum Section {
5 FunctionsTiming,
6 FunctionsAlloc,
7 FunctionsCpu,
8 Channels,
9 Streams,
10 Futures,
11 RwLocks,
12 Mutexes,
13 Sql,
14 Threads,
15 Debug,
16}
17
18impl Section {
19 pub fn all() -> Vec<Section> {
20 vec![
21 Section::FunctionsTiming,
22 Section::FunctionsAlloc,
23 Section::FunctionsCpu,
24 Section::Channels,
25 Section::Streams,
26 Section::Futures,
27 Section::RwLocks,
28 Section::Mutexes,
29 Section::Sql,
30 Section::Threads,
31 Section::Debug,
32 ]
33 }
34
35 pub fn short_name(&self) -> &'static str {
36 match self {
37 Section::FunctionsTiming => "timing",
38 Section::FunctionsAlloc => "alloc",
39 Section::FunctionsCpu => "cpu",
40 Section::Channels => "channels",
41 Section::Streams => "streams",
42 Section::Futures => "futures",
43 Section::RwLocks => "rw_locks",
44 Section::Mutexes => "mutexes",
45 Section::Sql => "sql",
46 Section::Threads => "threads",
47 Section::Debug => "debug",
48 }
49 }
50
51 pub fn from_name(s: &str) -> Option<Section> {
52 match s.trim() {
53 "functions-timing" => Some(Section::FunctionsTiming),
54 "functions-alloc" => Some(Section::FunctionsAlloc),
55 "functions-cpu" => Some(Section::FunctionsCpu),
56 "channels" => Some(Section::Channels),
57 "streams" => Some(Section::Streams),
58 "futures" => Some(Section::Futures),
59 "rw_locks" => Some(Section::RwLocks),
60 "mutexes" => Some(Section::Mutexes),
61 "sql" => Some(Section::Sql),
62 "threads" => Some(Section::Threads),
63 "debug" => Some(Section::Debug),
64 _ => None,
65 }
66 }
67
68 pub fn from_env() -> Option<Vec<Section>> {
69 std::env::var("HOTPATH_META_REPORT").ok().map(|val| {
70 let mut sections = Vec::new();
71 for part in val.split(',') {
72 match part.trim() {
73 "all" => return Section::all(),
74 other => {
75 if let Some(s) = Section::from_name(other) {
76 if !sections.contains(&s) {
77 sections.push(s);
78 }
79 } else {
80 eprintln!("[hotpath-meta] Unknown report section: '{}'", other);
81 }
82 }
83 }
84 }
85 sections
86 })
87 }
88}
89
90#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
109pub enum Format {
110 #[default]
111 Table,
112 Json,
113 JsonPretty,
114 None,
115}
116
117impl FromStr for Format {
118 type Err = String;
119
120 fn from_str(s: &str) -> Result<Self, Self::Err> {
121 match s.to_lowercase().as_str() {
122 "table" => Ok(Format::Table),
123 "json" => Ok(Format::Json),
124 "json-pretty" | "jsonpretty" => Ok(Format::JsonPretty),
125 "none" => Ok(Format::None),
126 _ => Err(format!(
127 "unknown format '{}', expected: table, json, json-pretty, none",
128 s
129 )),
130 }
131 }
132}
133
134impl Format {
135 pub fn from_env() -> Self {
138 match std::env::var("HOTPATH_META_OUTPUT_FORMAT") {
139 Ok(v) => v
140 .parse()
141 .unwrap_or_else(|e| panic!("HOTPATH_META_OUTPUT_FORMAT: {}", e)),
142 Err(_) => Format::default(),
143 }
144 }
145}
146
147pub trait IntoF64 {
148 fn into_f64(self) -> f64;
149}
150
151impl IntoF64 for f64 {
152 fn into_f64(self) -> f64 {
153 self
154 }
155}
156
157impl IntoF64 for f32 {
158 fn into_f64(self) -> f64 {
159 self as f64
160 }
161}
162
163impl IntoF64 for i8 {
164 fn into_f64(self) -> f64 {
165 self as f64
166 }
167}
168
169impl IntoF64 for i16 {
170 fn into_f64(self) -> f64 {
171 self as f64
172 }
173}
174
175impl IntoF64 for i32 {
176 fn into_f64(self) -> f64 {
177 self as f64
178 }
179}
180
181impl IntoF64 for i64 {
182 fn into_f64(self) -> f64 {
183 self as f64
184 }
185}
186
187impl IntoF64 for u8 {
188 fn into_f64(self) -> f64 {
189 self as f64
190 }
191}
192
193impl IntoF64 for u16 {
194 fn into_f64(self) -> f64 {
195 self as f64
196 }
197}
198
199impl IntoF64 for u32 {
200 fn into_f64(self) -> f64 {
201 self as f64
202 }
203}
204
205impl IntoF64 for u64 {
206 fn into_f64(self) -> f64 {
207 self as f64
208 }
209}
210
211impl IntoF64 for isize {
212 fn into_f64(self) -> f64 {
213 self as f64
214 }
215}
216
217impl IntoF64 for usize {
218 fn into_f64(self) -> f64 {
219 self as f64
220 }
221}
222
223#[doc(hidden)]
224pub fn env_flag(name: &str) -> bool {
225 std::env::var(name)
226 .map(|v| v.eq_ignore_ascii_case("true") || v == "1")
227 .unwrap_or(false)
228}
229
230#[cfg(feature = "hotpath-meta")]
231pub(crate) fn resolve_timeout_duration(
232 default_duration: std::time::Duration,
233 env_var: &str,
234) -> Option<std::time::Duration> {
235 let effective_duration = std::env::var(env_var)
236 .ok()
237 .and_then(|value| value.parse::<u64>().ok())
238 .map(std::time::Duration::from_millis)
239 .unwrap_or(default_duration);
240
241 if effective_duration.is_zero() {
242 None
243 } else {
244 Some(effective_duration)
245 }
246}