1use std::str::FromStr;
4
5use buffa::Enumeration;
6use serde::{Deserialize, Serialize};
7
8use crate::UnknownVariant;
9
10#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
14#[serde(rename_all = "snake_case")]
15#[repr(i32)]
16#[non_exhaustive]
17pub enum MetricKind {
18 #[default]
20 Unspecified = 0,
21 Counter = 1,
23 Gauge = 2,
25 Histogram = 3,
27}
28
29impl MetricKind {
30 #[must_use]
32 pub const fn as_str(self) -> &'static str {
33 match self {
34 Self::Unspecified => "unspecified",
35 Self::Counter => "counter",
36 Self::Gauge => "gauge",
37 Self::Histogram => "histogram",
38 }
39 }
40}
41
42impl Enumeration for MetricKind {
43 fn from_i32(value: i32) -> Option<Self> {
44 match value {
45 0 => Some(Self::Unspecified),
46 1 => Some(Self::Counter),
47 2 => Some(Self::Gauge),
48 3 => Some(Self::Histogram),
49 _ => None,
50 }
51 }
52
53 fn to_i32(&self) -> i32 {
54 *self as i32
55 }
56
57 fn proto_name(&self) -> &'static str {
58 match self {
59 Self::Unspecified => "METRIC_KIND_UNSPECIFIED",
60 Self::Counter => "METRIC_KIND_COUNTER",
61 Self::Gauge => "METRIC_KIND_GAUGE",
62 Self::Histogram => "METRIC_KIND_HISTOGRAM",
63 }
64 }
65
66 fn from_proto_name(name: &str) -> Option<Self> {
67 match name {
68 "METRIC_KIND_UNSPECIFIED" => Some(Self::Unspecified),
69 "METRIC_KIND_COUNTER" => Some(Self::Counter),
70 "METRIC_KIND_GAUGE" => Some(Self::Gauge),
71 "METRIC_KIND_HISTOGRAM" => Some(Self::Histogram),
72 _ => None,
73 }
74 }
75
76 fn values() -> &'static [Self] {
77 &[
78 Self::Unspecified,
79 Self::Counter,
80 Self::Gauge,
81 Self::Histogram,
82 ]
83 }
84}
85
86impl FromStr for MetricKind {
87 type Err = UnknownVariant;
88
89 fn from_str(s: &str) -> Result<Self, Self::Err> {
90 match s.to_ascii_lowercase().as_str() {
91 "counter" => Ok(Self::Counter),
92 "gauge" => Ok(Self::Gauge),
93 "histogram" => Ok(Self::Histogram),
94 _ => Err(UnknownVariant {
95 kind: "MetricKind",
96 value: s.to_string(),
97 }),
98 }
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn test_should_round_trip_via_i32() {
108 for v in MetricKind::values() {
109 assert_eq!(MetricKind::from_i32(v.to_i32()), Some(*v));
110 }
111 }
112}