micromegas_analytics/properties/
utils.rs

1//! Utility functions for converting between property formats
2
3use anyhow::{Context, Result};
4use jsonb::RawJsonb;
5use std::collections::HashMap;
6
7use crate::properties::properties_column_accessor::PropertiesColumnAccessor;
8
9/// Convert JSONB bytes to a property HashMap
10pub fn jsonb_to_property_map(jsonb_bytes: &[u8]) -> Result<HashMap<String, String>> {
11    if jsonb_bytes.is_empty() {
12        return Ok(HashMap::new());
13    }
14
15    let jsonb = RawJsonb::new(jsonb_bytes);
16    let mut map = HashMap::new();
17
18    // Use object_each to get key-value pairs
19    if let Some(pairs) = jsonb
20        .object_each()
21        .with_context(|| "getting JSONB object pairs")?
22    {
23        for (key, value) in pairs {
24            let value_str = if let Ok(Some(str_val)) = value.as_raw().as_str() {
25                str_val.to_string()
26            } else {
27                value.as_raw().to_string()
28            };
29            map.insert(key, value_str);
30        }
31    }
32
33    Ok(map)
34}
35
36/// Extract properties from a properties column accessor at the given row index.
37/// Returns an empty HashMap if the column value is null, otherwise deserializes the JSONB.
38pub fn extract_properties_from_properties_column(
39    column: &dyn PropertiesColumnAccessor,
40    row_index: usize,
41) -> Result<HashMap<String, String>> {
42    if column.is_null(row_index) {
43        Ok(HashMap::new())
44    } else {
45        let jsonb_bytes = column.jsonb_value(row_index)?;
46        jsonb_to_property_map(&jsonb_bytes)
47    }
48}