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
96#[cfg(feature = "alloc")]
97impl ToStatic for KeyValue<'_> {
98 type Static = KeyValue<'static>;
99
100 fn to_static(&self) -> Self::Static {
101 KeyValue {
102 key: self.key.clone().into_owned().into(),
103 value: self.value.to_static(),
104 }
105 }
106}
107
108/// A value that can be stored in a telemetry attribute.
109///
110/// This enum represents the different types of values that can be associated
111///
112/// # Examples
113///
114/// ```rust
115/// use veecle_telemetry::Value;
116///
117/// // Create values of different types
118/// let text = Value::String("hello world".into());
119/// let number = Value::I64(42);
120/// let flag = Value::Bool(true);
121/// let rating = Value::F64(4.5);
122/// ```
123#[derive(Clone, Debug, Serialize, Deserialize)]
124pub enum Value<'a> {
125 /// A string value (adapted to platform string type)
126 String(#[serde(borrow)] StringType<'a>),
127 /// A boolean value
128 Bool(bool),
129 /// A 64-bit signed integer
130 I64(i64),
131 /// A 64-bit floating-point number
132 F64(f64),
133}
134
135#[cfg(feature = "alloc")]
136impl ToStatic for Value<'_> {
137 type Static = Value<'static>;
138
139 fn to_static(&self) -> Self::Static {
140 match self {
141 Value::String(s) => Value::String(s.clone().into_owned().into()),
142 Value::Bool(b) => Value::Bool(*b),
143 Value::I64(i) => Value::I64(*i),
144 Value::F64(f) => Value::F64(*f),
145 }
146 }
147}
148
149#[cfg(feature = "alloc")]
150impl<'a> From<alloc::borrow::Cow<'a, str>> for Value<'a> {
151 fn from(value: alloc::borrow::Cow<'a, str>) -> Self {
152 Value::String(value)
153 }
154}
155
156#[cfg(feature = "alloc")]
157impl<'a> From<alloc::string::String> for Value<'a> {
158 fn from(value: alloc::string::String) -> Self {
159 Value::String(value.into())
160 }
161}
162
163#[cfg(feature = "alloc")]
164impl<'a> From<&'a alloc::string::String> for Value<'a> {
165 fn from(value: &'a alloc::string::String) -> Self {
166 Value::String(value.into())
167 }
168}
169
170impl<'a> From<&'a str> for Value<'a> {
171 fn from(value: &'a str) -> Self {
172 #[cfg(feature = "alloc")]
173 {
174 Value::String(alloc::borrow::Cow::Borrowed(value))
175 }
176 #[cfg(not(feature = "alloc"))]
177 {
178 Value::String(value)
179 }
180 }
181}
182
183impl From<bool> for Value<'_> {
184 fn from(value: bool) -> Self {
185 Value::Bool(value)
186 }
187}
188
189impl From<i64> for Value<'_> {
190 fn from(value: i64) -> Self {
191 Value::I64(value)
192 }
193}
194
195impl From<f64> for Value<'_> {
196 fn from(value: f64) -> Self {
197 Value::F64(value)
198 }
199}