wedb_embed 0.1.1

Embedded database engine providing Redis-like APIs, built on fjall / 嵌入式数据库引擎,提供类似 Redis 的接口,底层基于 fjall 开发
Documentation
use sonic_rs::{JsonContainerTrait, JsonValueMutTrait, JsonValueTrait, Value};
use std::fmt::Write as _;

/// JSON Merge Patch (RFC 7396)
pub fn json_merge_patch(target: &mut Value, patch: &Value) {
    if let Some(patch_obj) = patch.as_object() {
        if !target.is_object() {
            *target = sonic_rs::json!({});
        }
        let Some(target_obj) = target.as_object_mut() else {
            return;
        };
        for (k, v) in patch_obj.iter() {
            if v.is_null() {
                target_obj.remove(&k);
            } else {
                let entry = target_obj.entry(k).or_insert(sonic_rs::json!(null));
                json_merge_patch(entry, v);
            }
        }
    } else {
        *target = patch.clone();
    }
}

/// 格式化 JSON 字符串输出(对标 Kvrocks INDENT / NEWLINE / SPACE 选项)
pub fn format_json(
    val: &Value,
    indent: Option<&str>,
    newline: Option<&str>,
    space: Option<&str>,
) -> String {
    if indent.is_none() && newline.is_none() && space.is_none() {
        return sonic_rs::to_string(val).unwrap_or_default();
    }

    let mut out = String::with_capacity(128);
    format_value_recursive(val, 0, indent, newline, space, &mut out);
    out
}

fn format_value_recursive(
    val: &Value,
    depth: usize,
    indent: Option<&str>,
    newline: Option<&str>,
    space: Option<&str>,
    out: &mut String,
) {
    if val.is_null() {
        out.push_str("null");
    } else if let Some(b) = val.as_bool() {
        out.push_str(if b { "true" } else { "false" });
    } else if let Some(i) = val.as_i64() {
        let _ = write!(out, "{i}");
    } else if let Some(u) = val.as_u64() {
        let _ = write!(out, "{u}");
    } else if let Some(f) = val.as_f64() {
        let _ = write!(out, "{f}");
    } else if val.is_str() {
        out.push_str(&sonic_rs::to_string(val).unwrap_or_default());
    } else if let Some(arr) = val.as_array() {
        if arr.is_empty() {
            out.push_str("[]");
            return;
        }
        let nl = newline.unwrap_or("");
        let has_nl = !nl.is_empty();
        let ind = indent.unwrap_or("");

        out.push('[');
        for (i, elem) in arr.iter().enumerate() {
            if i > 0 {
                out.push(',');
            }
            if has_nl {
                out.push_str(nl);
                for _ in 0..=depth {
                    out.push_str(ind);
                }
            }
            format_value_recursive(elem, depth + 1, indent, newline, space, out);
        }
        if has_nl {
            out.push_str(nl);
            for _ in 0..depth {
                out.push_str(ind);
            }
        }
        out.push(']');
    } else if let Some(obj) = val.as_object() {
        if obj.is_empty() {
            out.push_str("{}");
            return;
        }
        let nl = newline.unwrap_or("");
        let has_nl = !nl.is_empty();
        let ind = indent.unwrap_or("");
        let colon_sep = if space == Some(" ") { ": " } else { ":" };

        out.push('{');
        for (i, (k, v)) in obj.iter().enumerate() {
            if i > 0 {
                out.push(',');
            }
            if has_nl {
                out.push_str(nl);
                for _ in 0..=depth {
                    out.push_str(ind);
                }
            }
            out.push('"');
            out.push_str(k);
            out.push('"');
            out.push_str(colon_sep);
            format_value_recursive(v, depth + 1, indent, newline, space, out);
        }
        if has_nl {
            out.push_str(nl);
            for _ in 0..depth {
                out.push_str(ind);
            }
        }
        out.push('}');
    }
}