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