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}