reddb-io-server 1.2.0

RedDB server-side engine: storage, runtime, replication, MCP, AI, and the gRPC/HTTP/RedWire/PG-wire dispatchers. Re-exported by the umbrella `reddb` crate.
Documentation
use std::collections::BTreeMap;

use crate::json::{to_string as json_to_string, Value as JsonValue};

pub(crate) fn json_string_field(payload: &JsonValue, field: &str) -> Option<String> {
    payload
        .get(field)
        .and_then(JsonValue::as_str)
        .map(str::to_string)
}

pub(crate) fn json_object_string_map_field(
    payload: &JsonValue,
    field: &str,
) -> Option<BTreeMap<String, String>> {
    let object = payload.get(field)?.as_object()?;
    Some(
        object
            .iter()
            .map(|(key, value)| (key.to_string(), json_metadata_value_to_string(value)))
            .collect(),
    )
}

pub(crate) fn json_metadata_value_to_string(value: &JsonValue) -> String {
    match value {
        JsonValue::Null => "null".to_string(),
        JsonValue::Bool(value) => value.to_string(),
        JsonValue::Number(value) => value.to_string(),
        JsonValue::String(value) => value.clone(),
        JsonValue::Array(_) | JsonValue::Object(_) => {
            json_to_string(value).unwrap_or_else(|_| "".to_string())
        }
    }
}

pub(crate) fn json_string_list_field(payload: &JsonValue, field: &str) -> Option<Vec<String>> {
    let values = payload.get(field)?.as_array()?;
    let out: Vec<String> = values
        .iter()
        .filter_map(JsonValue::as_str)
        .map(|value| value.trim().to_string())
        .filter(|value| !value.is_empty())
        .collect();
    (!out.is_empty()).then_some(out)
}

pub(crate) fn json_bool_field(payload: &JsonValue, field: &str) -> Option<bool> {
    payload.get(field).and_then(JsonValue::as_bool)
}

pub(crate) fn json_usize_field(payload: &JsonValue, field: &str) -> Option<usize> {
    payload
        .get(field)
        .and_then(JsonValue::as_i64)
        .and_then(|value| usize::try_from(value).ok())
}

pub(crate) fn json_f32_field(payload: &JsonValue, field: &str) -> Option<f32> {
    payload
        .get(field)
        .and_then(JsonValue::as_f64)
        .map(|value| value as f32)
}