veecle_telemetry/value.rs
1//! Key-value attribute types for telemetry data.
2//!
3//! This module defines the types used to represent attributes in telemetry data.
4//! Attributes are key-value pairs that provide additional context for spans,
5//! events, and log messages.
6//!
7//! # Value Types
8//!
9//! The [`Value`] enum supports common data types:
10//! - **String**: Text values (adapted to platform string type)
11//! - **Bool**: Boolean values (true/false)
12//! - **I64**: 64-bit signed integers
13//! - **F64**: 64-bit floating-point numbers
14//!
15//! # Examples
16//!
17//! ```rust
18//! use veecle_telemetry::types::StringType;
19//! use veecle_telemetry::{KeyValue, Value};
20//!
21//! // Create key-value pairs
22//! let user_id = KeyValue::new("user_id", 123);
23//! let username = KeyValue::new("username", "alice");
24//! let is_admin = KeyValue::new("is_admin", true);
25//! let score = KeyValue::new("score", 95.5);
26//!
27//! // Values can be created from various types
28//! let string_value = Value::String("hello".into());
29//! let int_value = Value::I64(42);
30//! let bool_value = Value::Bool(true);
31//! let float_value = Value::F64(3.14);
32//! ```
33
34use serde::{Deserialize, Serialize};
35
36#[cfg(feature = "alloc")]
37use crate::to_static::ToStatic;
38use crate::types::StringType;
39
40/// A key-value attribute pair used in telemetry data.
41///
42/// Key-value pairs provide additional context for spans, events, and log messages.
43/// The key is typically a string identifier, and the value can be one of several
44/// supported data types.
45///
46/// # Examples
47///
48/// ```rust
49/// use veecle_telemetry::types::StringType;
50/// use veecle_telemetry::{KeyValue, Value};
51///
52/// // Create attributes with different value types
53/// let user_id = KeyValue::new("user_id", 123);
54/// let username = KeyValue::new("username", "alice");
55/// let is_active = KeyValue::new("is_active", true);
56/// let score = KeyValue::new("score", 95.5);
57/// ```
58#[derive(Clone, Debug, Serialize, Deserialize)]
59pub struct KeyValue<'a> {
60 /// The attribute key (name)
61 #[serde(borrow)]
62 pub key: StringType<'a>,
63 /// The attribute value
64 #[serde(borrow)]
65 pub value: Value<'a>,
66}
67
68impl<'a> KeyValue<'a> {
69 /// Creates a new key-value attribute pair.
70 ///
71 /// # Arguments
72 ///
73 /// * `key` - The attribute key (name)
74 /// * `value` - The attribute value
75 ///
76 /// # Examples
77 ///
78 /// ```rust
79 /// use veecle_telemetry::KeyValue;
80 ///
81 /// let user_id = KeyValue::new("user_id", 123);
82 /// let username = KeyValue::new("username", "alice");
83 /// ```
84 pub fn new<K, V>(key: K, value: V) -> Self
85 where
86 K: Into<StringType<'a>>,
87 V: Into<Value<'a>>,
88 {
89 Self {
90 key: key.into(),
91 value: value.into(),
92 }
93 }
94}
95
96impl core::fmt::Display for KeyValue<'_> {
97 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
98 write!(f, "{}: {}", self.key, self.value)
99 }
100}
101
102#[cfg(feature = "alloc")]
103impl ToStatic for KeyValue<'_> {
104 type Static = KeyValue<'static>;
105
106 fn to_static(&self) -> Self::Static {
107 KeyValue {
108 key: self.key.clone().into_owned().into(),
109 value: self.value.to_static(),
110 }
111 }
112}
113
114/// A value that can be stored in a telemetry attribute.
115///
116/// This enum represents the different types of values that can be associated
117///
118/// # Examples
119///
120/// ```rust
121/// use veecle_telemetry::Value;
122///
123/// // Create values of different types
124/// let text = Value::String("hello world".into());
125/// let number = Value::I64(42);
126/// let flag = Value::Bool(true);
127/// let rating = Value::F64(4.5);
128/// ```
129#[derive(Clone, Debug, Serialize, Deserialize)]
130pub enum Value<'a> {
131 /// A string value (adapted to platform string type)
132 String(#[serde(borrow)] StringType<'a>),
133 /// A boolean value
134 Bool(bool),
135 /// A 64-bit signed integer
136 I64(i64),
137 /// A 64-bit floating-point number
138 F64(f64),
139}
140
141#[cfg(feature = "alloc")]
142impl ToStatic for Value<'_> {
143 type Static = Value<'static>;
144
145 fn to_static(&self) -> Self::Static {
146 match self {
147 Value::String(s) => Value::String(s.clone().into_owned().into()),
148 Value::Bool(b) => Value::Bool(*b),
149 Value::I64(i) => Value::I64(*i),
150 Value::F64(f) => Value::F64(*f),
151 }
152 }
153}
154
155impl<'a> core::fmt::Display for Value<'a> {
156 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
157 match self {
158 // For strings, debug print so they will get delimiters, since we are explicitly
159 // representing strings rather than directly human-targeted text, and they will be used
160 // in situations where knowing where the string ends is important.
161 Value::String(value) => write!(f, "{value:?}"),
162 Value::Bool(value) => write!(f, "{value}"),
163 Value::I64(value) => write!(f, "{value}"),
164 Value::F64(value) => write!(f, "{value}"),
165 }
166 }
167}
168
169#[cfg(feature = "alloc")]
170impl<'a> From<alloc::borrow::Cow<'a, str>> for Value<'a> {
171 fn from(value: alloc::borrow::Cow<'a, str>) -> Self {
172 Value::String(value)
173 }
174}
175
176#[cfg(feature = "alloc")]
177impl<'a> From<alloc::string::String> for Value<'a> {
178 fn from(value: alloc::string::String) -> Self {
179 Value::String(value.into())
180 }
181}
182
183#[cfg(feature = "alloc")]
184impl<'a> From<&'a alloc::string::String> for Value<'a> {
185 fn from(value: &'a alloc::string::String) -> Self {
186 Value::String(value.into())
187 }
188}
189
190impl<'a> From<&'a str> for Value<'a> {
191 fn from(value: &'a str) -> Self {
192 #[cfg(feature = "alloc")]
193 {
194 Value::String(alloc::borrow::Cow::Borrowed(value))
195 }
196 #[cfg(not(feature = "alloc"))]
197 {
198 Value::String(value)
199 }
200 }
201}
202
203impl From<bool> for Value<'_> {
204 fn from(value: bool) -> Self {
205 Value::Bool(value)
206 }
207}
208
209impl From<i64> for Value<'_> {
210 fn from(value: i64) -> Self {
211 Value::I64(value)
212 }
213}
214
215impl From<f64> for Value<'_> {
216 fn from(value: f64) -> Self {
217 Value::F64(value)
218 }
219}