mindb 0.1.2

Lightweight embedded key–value store with write-ahead log and zstd compression.
Documentation
//! JSON trie sidecar that indexes structured document fields.
#![allow(dead_code)]

use std::collections::HashMap;
use std::sync::Arc;

use parking_lot::RwLock;
use serde_json::Value;

use crate::index::{SequenceNumber, VersionPointer};

#[derive(Clone, Default)]
pub struct JsonTrieSidecar {
    inner: Arc<RwLock<HashMap<(String, String), HashMap<Vec<u8>, VersionPointer>>>>,
}

impl JsonTrieSidecar {
    /// Creates a new JSON trie sidecar.
    pub fn new() -> Self {
        Self {
            inner: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    /// Indexes the provided JSON value for the path.
    pub fn index_value(
        &self,
        path: impl Into<String>,
        value: &Value,
        key: Vec<u8>,
        pointer: VersionPointer,
    ) {
        let path = path.into();
        let value_repr = JsonTrieSidecar::stringify(value);
        let mut guard = self.inner.write();
        let entry = guard.entry((path, value_repr)).or_default();
        match entry.get_mut(&key) {
            Some(existing) if existing.sequence >= pointer.sequence => return,
            Some(existing) => *existing = pointer,
            None => {
                entry.insert(key, pointer);
            }
        }
    }

    /// Returns the keys that match the path/value pair and are visible for the snapshot.
    pub fn query_equals(
        &self,
        path: &str,
        value: &Value,
        snapshot: SequenceNumber,
    ) -> Vec<Vec<u8>> {
        let guard = self.inner.read();
        guard
            .get(&(path.to_string(), JsonTrieSidecar::stringify(value)))
            .map(|mapping| {
                mapping
                    .iter()
                    .filter(|(_, pointer)| pointer.is_visible_at(snapshot))
                    .map(|(key, _)| key.clone())
                    .collect()
            })
            .unwrap_or_default()
    }

    fn stringify(value: &Value) -> String {
        match value {
            Value::String(s) => s.clone(),
            Value::Bool(b) => b.to_string(),
            Value::Number(n) => n.to_string(),
            Value::Null => "null".to_string(),
            Value::Array(_) | Value::Object(_) => value.to_string(),
        }
    }
}