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