datadog_agent_metrics_v3/
types.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7#[repr(u8)]
8pub enum V3MetricType {
9 Count = 1,
11 Rate = 2,
13 Gauge = 3,
15 Sketch = 4,
17}
18
19impl V3MetricType {
20 pub const fn as_u64(self) -> u64 {
22 self as u64
23 }
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31#[repr(u8)]
32pub(crate) enum V3ValueType {
33 Zero = 0x00,
35
36 Sint64 = 0x10,
38
39 Float32 = 0x20,
41
42 Float64 = 0x30,
44}
45
46impl V3ValueType {
47 pub fn as_u64(self) -> u64 {
49 self as u64
50 }
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
61#[repr(u8)]
62enum PointKind {
63 Zero = 0,
65 Int24 = 1,
67 Int48 = 2,
69 Float32 = 3,
71 Float64 = 4,
73}
74
75const F32_INT_MAX: i64 = 1 << 24;
77
78impl PointKind {
79 fn for_value(v: f64) -> Self {
81 if v == 0.0 {
82 return Self::Zero;
83 }
84
85 const VARINT_WIDTH: i32 = 7 * 7 - 1;
87 const MAX_INT: i64 = 1 << VARINT_WIDTH;
88 const MIN_INT: i64 = -MAX_INT;
89
90 let i = v as i64;
91 if (MIN_INT..MAX_INT).contains(&i) && (i as f64) == v {
92 if (-F32_INT_MAX..=F32_INT_MAX).contains(&i) {
93 return Self::Int24;
94 }
95 return Self::Int48;
96 }
97
98 if (v as f32 as f64) == v {
99 return Self::Float32;
100 }
101
102 Self::Float64
103 }
104
105 fn union(self, other: Self) -> Self {
111 match (self, other) {
112 (Self::Int48, Self::Float32) | (Self::Float32, Self::Int48) => Self::Float64,
113 _ => self.max(other),
114 }
115 }
116
117 fn to_value_type(self) -> V3ValueType {
119 match self {
120 Self::Zero => V3ValueType::Zero,
121 Self::Int24 | Self::Int48 => V3ValueType::Sint64,
122 Self::Float32 => V3ValueType::Float32,
123 Self::Float64 => V3ValueType::Float64,
124 }
125 }
126}
127
128pub(crate) fn value_type_for_values(values: impl Iterator<Item = f64>) -> V3ValueType {
133 let mut kind = PointKind::Zero;
134 for v in values {
135 kind = kind.union(PointKind::for_value(v));
136 }
137 kind.to_value_type()
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[test]
145 fn test_point_kind_classification() {
146 assert_eq!(PointKind::for_value(0.0), PointKind::Zero);
148
149 assert_eq!(PointKind::for_value(100.0), PointKind::Int24);
151 assert_eq!(PointKind::for_value(-100.0), PointKind::Int24);
152 assert_eq!(PointKind::for_value((1 << 24) as f64), PointKind::Int24);
153 assert_eq!(PointKind::for_value(-((1 << 24) as f64)), PointKind::Int24);
154
155 assert_eq!(PointKind::for_value(((1 << 24) + 1) as f64), PointKind::Int48);
157 assert_eq!(PointKind::for_value((1i64 << 30) as f64), PointKind::Int48);
158
159 assert_eq!(PointKind::for_value(1.5), PointKind::Float32);
161 assert_eq!(PointKind::for_value(2.75), PointKind::Float32);
162
163 assert_eq!(PointKind::for_value(std::f64::consts::PI), PointKind::Float64);
165 let large = ((1i64 << 50) + 1) as f64;
166 assert_eq!(PointKind::for_value(large), PointKind::Float64);
167 }
168
169 #[test]
170 fn test_point_kind_union() {
171 assert_eq!(PointKind::Zero.union(PointKind::Int24), PointKind::Int24);
173 assert_eq!(PointKind::Int24.union(PointKind::Int48), PointKind::Int48);
174 assert_eq!(PointKind::Int24.union(PointKind::Float32), PointKind::Float32);
175 assert_eq!(PointKind::Float32.union(PointKind::Float64), PointKind::Float64);
176 assert_eq!(PointKind::Float64.union(PointKind::Zero), PointKind::Float64);
177
178 assert_eq!(PointKind::Int48.union(PointKind::Float32), PointKind::Float64);
180 assert_eq!(PointKind::Float32.union(PointKind::Int48), PointKind::Float64);
181 }
182
183 #[test]
184 fn test_value_type_for_values() {
185 assert_eq!(value_type_for_values([0.0, 0.0].into_iter()), V3ValueType::Zero);
187
188 assert_eq!(value_type_for_values([100.0, 200.0].into_iter()), V3ValueType::Sint64);
190
191 assert_eq!(
193 value_type_for_values([(1i64 << 30) as f64, 200.0].into_iter()),
194 V3ValueType::Sint64
195 );
196
197 assert_eq!(value_type_for_values([100.0, 1.5].into_iter()), V3ValueType::Float32);
199
200 assert_eq!(
202 value_type_for_values([(1i64 << 30) as f64, 1.5].into_iter()),
203 V3ValueType::Float64
204 );
205
206 assert_eq!(
208 value_type_for_values([100.0, std::f64::consts::PI].into_iter()),
209 V3ValueType::Float64
210 );
211
212 assert_eq!(value_type_for_values(std::iter::empty()), V3ValueType::Zero);
214 }
215}