Skip to main content

micromegas_telemetry/
property.rs

1use sqlx::postgres::{PgHasArrayType, PgTypeInfo};
2use std::{collections::HashMap, sync::Arc};
3
4/// Re-exported so server code keeps reaching this name through `property`; it is defined in
5/// [`crate::property_names`] so client crates can reach it without the `server` feature.
6pub use crate::property_names::RESERVED_PROPERTY_PREFIX;
7
8/// Represents a key-value property.
9///
10/// Properties are used to add context to telemetry events.
11/// Both key and value are stored as `Arc<String>` for efficient sharing.
12#[derive(Debug)]
13pub struct Property {
14    key: Arc<String>,
15    value: Arc<String>,
16}
17
18impl Property {
19    /// Creates a new `Property`.
20    pub fn new(key: Arc<String>, value: Arc<String>) -> Self {
21        Self { key, value }
22    }
23
24    /// Returns the key of the property as a string slice.
25    pub fn key_str(&self) -> &str {
26        self.key.as_str()
27    }
28
29    /// Returns the value of the property as a string slice.
30    pub fn value_str(&self) -> &str {
31        self.value.as_str()
32    }
33}
34
35impl ::sqlx::encode::Encode<'_, ::sqlx::Postgres> for Property {
36    fn encode_by_ref(
37        &self,
38        buf: &mut ::sqlx::postgres::PgArgumentBuffer,
39    ) -> std::result::Result<
40        sqlx::encode::IsNull,
41        std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync + 'static>,
42    > {
43        let mut encoder = ::sqlx::postgres::types::PgRecordEncoder::new(buf);
44        encoder.encode(self.key.as_str())?;
45        encoder.encode(self.value.as_str())?;
46        encoder.finish();
47        Ok(::sqlx::encode::IsNull::No)
48    }
49    fn size_hint(&self) -> ::std::primitive::usize {
50        2usize * (4 + 4)
51            + <String as ::sqlx::encode::Encode<::sqlx::Postgres>>::size_hint(&self.key)
52            + <String as ::sqlx::encode::Encode<::sqlx::Postgres>>::size_hint(&self.value)
53    }
54}
55
56impl ::sqlx::decode::Decode<'_, ::sqlx::Postgres> for Property {
57    fn decode(
58        value: ::sqlx::postgres::PgValueRef<'_>,
59    ) -> ::std::result::Result<
60        Self,
61        ::std::boxed::Box<
62            dyn ::std::error::Error + 'static + ::std::marker::Send + ::std::marker::Sync,
63        >,
64    > {
65        let mut decoder = ::sqlx::postgres::types::PgRecordDecoder::new(value)?;
66        let key = decoder.try_decode::<String>()?;
67        let value = decoder.try_decode::<String>()?;
68        ::std::result::Result::Ok(Property::new(Arc::new(key), Arc::new(value)))
69    }
70}
71#[automatically_derived]
72impl ::sqlx::Type<::sqlx::Postgres> for Property {
73    fn type_info() -> ::sqlx::postgres::PgTypeInfo {
74        ::sqlx::postgres::PgTypeInfo::with_name("micromegas_property")
75    }
76}
77
78// array support
79impl PgHasArrayType for Property {
80    fn array_type_info() -> PgTypeInfo {
81        PgTypeInfo::with_name("_micromegas_property")
82    }
83}
84
85/// Converts a `HashMap<String, String>` to a `Vec<Property>`.
86///
87/// This is a convenience function for creating a list of properties from a map.
88pub fn make_properties(map: &HashMap<String, String>) -> Vec<Property> {
89    map.iter()
90        .map(|(k, v)| Property::new(Arc::new(k.clone()), Arc::new(v.clone())))
91        .collect()
92}
93
94/// Converts a `Vec<Property>` to a `HashMap<String, String>`.
95///
96/// This is a convenience function for converting a list of properties back to a map.
97pub fn into_hashmap(properties: Vec<Property>) -> HashMap<String, String> {
98    let mut hashmap = HashMap::new();
99    for property in properties {
100        hashmap.insert((*property.key).clone(), (*property.value).clone());
101    }
102    hashmap
103}