1use std::hash::Hasher;
2
3use rapidhash::fast::RapidHasher;
4
5use crate::cow::Cow;
6
7pub type SharedString = Cow<'static, str>;
19
20#[deprecated(since = "0.24.4", note = "Use `metrics-util::common::KeyHasher` instead.")]
32pub struct KeyHasher(KeyHasherState);
33
34enum KeyHasherState {
35 Empty,
36 PreHashed(u64),
37 Bytes(RapidHasher<'static>),
38}
39
40#[allow(deprecated)]
41impl std::fmt::Debug for KeyHasher {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 f.debug_struct("KeyHasher").finish_non_exhaustive()
44 }
45}
46
47#[allow(deprecated)]
48impl Default for KeyHasher {
49 fn default() -> Self {
50 KeyHasher(KeyHasherState::Empty)
51 }
52}
53
54#[allow(deprecated)]
55impl Hasher for KeyHasher {
56 fn finish(&self) -> u64 {
57 match &self.0 {
58 KeyHasherState::Empty => 0,
59 KeyHasherState::PreHashed(h) => *h,
60 KeyHasherState::Bytes(h) => h.finish(),
61 }
62 }
63
64 fn write(&mut self, bytes: &[u8]) {
65 let mut hasher = match std::mem::replace(&mut self.0, KeyHasherState::Empty) {
69 KeyHasherState::Empty => RapidHasher::default_const(),
70 KeyHasherState::PreHashed(prior) => {
71 let mut h = RapidHasher::default_const();
72 h.write_u64(prior);
73 h
74 }
75 KeyHasherState::Bytes(h) => h,
76 };
77 hasher.write(bytes);
78 self.0 = KeyHasherState::Bytes(hasher);
79 }
80
81 fn write_u64(&mut self, i: u64) {
82 self.0 = match std::mem::replace(&mut self.0, KeyHasherState::Empty) {
85 KeyHasherState::Empty | KeyHasherState::PreHashed(_) => KeyHasherState::PreHashed(i),
86 KeyHasherState::Bytes(mut h) => {
87 h.write_u64(i);
88 KeyHasherState::Bytes(h)
89 }
90 };
91 }
92}
93
94#[derive(Clone, Debug)]
96pub enum GaugeValue {
97 Absolute(f64),
99 Increment(f64),
101 Decrement(f64),
103}
104
105impl GaugeValue {
106 pub fn update_value(&self, input: f64) -> f64 {
108 match self {
109 GaugeValue::Absolute(val) => *val,
110 GaugeValue::Increment(val) => input + val,
111 GaugeValue::Decrement(val) => input - val,
112 }
113 }
114}
115
116#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
121pub enum Unit {
122 Count,
124 Percent,
126 Seconds,
130 Milliseconds,
134 Microseconds,
138 Nanoseconds,
140 Tebibytes,
144 Gibibytes,
148 Mebibytes,
152 Kibibytes,
156 Bytes,
158 TerabitsPerSecond,
162 GigabitsPerSecond,
166 MegabitsPerSecond,
170 KilobitsPerSecond,
174 BitsPerSecond,
176 CountPerSecond,
178}
179
180impl Unit {
181 pub fn as_str(&self) -> &'static str {
183 match self {
184 Unit::Count => "count",
185 Unit::Percent => "percent",
186 Unit::Seconds => "seconds",
187 Unit::Milliseconds => "milliseconds",
188 Unit::Microseconds => "microseconds",
189 Unit::Nanoseconds => "nanoseconds",
190 Unit::Tebibytes => "tebibytes",
191 Unit::Gibibytes => "gibibytes",
192 Unit::Mebibytes => "mebibytes",
193 Unit::Kibibytes => "kibibytes",
194 Unit::Bytes => "bytes",
195 Unit::TerabitsPerSecond => "terabits_per_second",
196 Unit::GigabitsPerSecond => "gigabits_per_second",
197 Unit::MegabitsPerSecond => "megabits_per_second",
198 Unit::KilobitsPerSecond => "kilobits_per_second",
199 Unit::BitsPerSecond => "bits_per_second",
200 Unit::CountPerSecond => "count_per_second",
201 }
202 }
203
204 pub fn as_canonical_label(&self) -> &'static str {
211 match self {
212 Unit::Count => "",
213 Unit::Percent => "%",
214 Unit::Seconds => "s",
215 Unit::Milliseconds => "ms",
216 Unit::Microseconds => "μs",
217 Unit::Nanoseconds => "ns",
218 Unit::Tebibytes => "TiB",
219 Unit::Gibibytes => "GiB",
220 Unit::Mebibytes => "MiB",
221 Unit::Kibibytes => "KiB",
222 Unit::Bytes => "B",
223 Unit::TerabitsPerSecond => "Tbps",
224 Unit::GigabitsPerSecond => "Gbps",
225 Unit::MegabitsPerSecond => "Mbps",
226 Unit::KilobitsPerSecond => "kbps",
227 Unit::BitsPerSecond => "bps",
228 Unit::CountPerSecond => "/s",
229 }
230 }
231
232 pub fn from_string(s: &str) -> Option<Unit> {
236 match s {
237 "count" => Some(Unit::Count),
238 "percent" => Some(Unit::Percent),
239 "seconds" => Some(Unit::Seconds),
240 "milliseconds" => Some(Unit::Milliseconds),
241 "microseconds" => Some(Unit::Microseconds),
242 "nanoseconds" => Some(Unit::Nanoseconds),
243 "tebibytes" => Some(Unit::Tebibytes),
244 "gibibytes" => Some(Unit::Gibibytes),
245 "mebibytes" => Some(Unit::Mebibytes),
246 "kibibytes" => Some(Unit::Kibibytes),
247 "bytes" => Some(Unit::Bytes),
248 "terabits_per_second" => Some(Unit::TerabitsPerSecond),
249 "gigabits_per_second" => Some(Unit::GigabitsPerSecond),
250 "megabits_per_second" => Some(Unit::MegabitsPerSecond),
251 "kilobits_per_second" => Some(Unit::KilobitsPerSecond),
252 "bits_per_second" => Some(Unit::BitsPerSecond),
253 "count_per_second" => Some(Unit::CountPerSecond),
254 _ => None,
255 }
256 }
257
258 pub fn is_time_based(&self) -> bool {
260 matches!(self, Unit::Seconds | Unit::Milliseconds | Unit::Microseconds | Unit::Nanoseconds)
261 }
262
263 pub fn is_data_based(&self) -> bool {
265 matches!(
266 self,
267 Unit::Tebibytes
268 | Unit::Gibibytes
269 | Unit::Mebibytes
270 | Unit::Kibibytes
271 | Unit::Bytes
272 | Unit::TerabitsPerSecond
273 | Unit::GigabitsPerSecond
274 | Unit::MegabitsPerSecond
275 | Unit::KilobitsPerSecond
276 | Unit::BitsPerSecond
277 )
278 }
279
280 pub fn is_data_rate_based(&self) -> bool {
282 matches!(
283 self,
284 Unit::TerabitsPerSecond
285 | Unit::GigabitsPerSecond
286 | Unit::MegabitsPerSecond
287 | Unit::KilobitsPerSecond
288 | Unit::BitsPerSecond
289 )
290 }
291}
292
293pub trait IntoF64 {
298 fn into_f64(self) -> f64;
300}
301
302impl IntoF64 for f64 {
303 fn into_f64(self) -> f64 {
304 self
305 }
306}
307
308impl IntoF64 for core::time::Duration {
309 fn into_f64(self) -> f64 {
310 self.as_secs_f64()
311 }
312}
313
314into_f64!(i8, u8, i16, u16, i32, u32, f32);
315
316#[doc(hidden)]
318pub fn __into_f64<V: IntoF64>(value: V) -> f64 {
319 value.into_f64()
320}
321
322macro_rules! into_f64 {
323 ($($ty:ty),*) => {
324 $(
325 impl IntoF64 for $ty {
326 fn into_f64(self) -> f64 {
327 f64::from(self)
328 }
329 }
330 )*
331 };
332}
333
334use into_f64;
335
336#[cfg(test)]
337mod tests {
338 use std::time::Duration;
339
340 use super::{IntoF64, Unit};
341
342 #[test]
343 fn test_unit_conversions() {
344 let all_variants = vec![
345 Unit::Count,
346 Unit::Percent,
347 Unit::Seconds,
348 Unit::Milliseconds,
349 Unit::Microseconds,
350 Unit::Nanoseconds,
351 Unit::Tebibytes,
352 Unit::Gibibytes,
353 Unit::Mebibytes,
354 Unit::Kibibytes,
355 Unit::Bytes,
356 Unit::TerabitsPerSecond,
357 Unit::GigabitsPerSecond,
358 Unit::MegabitsPerSecond,
359 Unit::KilobitsPerSecond,
360 Unit::BitsPerSecond,
361 Unit::CountPerSecond,
362 ];
363
364 for variant in all_variants {
365 let s = variant.as_str();
366 let parsed = Unit::from_string(s);
367 assert_eq!(Some(variant), parsed);
368 }
369 }
370
371 #[test]
372 fn into_f64() {
373 fn test<T: IntoF64>(val: T) {
374 assert!(!val.into_f64().is_nan());
375 }
376
377 test::<i8>(1);
378 test::<u8>(1);
379 test::<i16>(1);
380 test::<u16>(1);
381 test::<i32>(1);
382 test::<u32>(1);
383 test::<f32>(1.0);
384 test::<f64>(1.0);
385 test::<Duration>(Duration::from_secs(1));
386 }
387}