Skip to main content

rustbrain_core/mutator/
mod.rs

1//! Optional jshift-backed in-place JSON field mutation helpers.
2//!
3//! Enabled with the `jshift` Cargo feature. Not used by the core indexing path;
4//! provided for tooling that streams JSONL manifests or agent side-channels
5//! without full `serde_json` re-serialization.
6//!
7//! **Why optional / not default:** criterion benches on rustbrain-shaped workloads
8//! show `serde_json` wins for full typed encode/decode and pretty CLI JSON; jshift
9//! wins for sparse path get and in-place patch on larger buffers. See
10//! `docs/JSON_STACK.md` in the repository root.
11
12#[cfg(feature = "jshift")]
13mod imp {
14    use crate::error::{BrainError, Result};
15    use jshift::{find_value, mutate_value, parse_path};
16
17    /// Mutate a JSON byte buffer in-place using jshift.
18    pub fn update_json_field_inplace(
19        json_bytes: &mut Vec<u8>,
20        path_expr: &str,
21        new_value_bytes: &[u8],
22    ) -> Result<()> {
23        let path = parse_path(path_expr);
24        mutate_value(json_bytes, &path, new_value_bytes)
25            .map_err(|e| BrainError::other(format!("jshift mutate failed: {e}")))?;
26        Ok(())
27    }
28
29    /// Zero-copy extraction of a JSON field slice from raw bytes.
30    pub fn extract_json_field_slice<'a>(
31        json_bytes: &'a [u8],
32        path_expr: &str,
33    ) -> Option<&'a [u8]> {
34        let path = parse_path(path_expr);
35        find_value(json_bytes, &path).ok()
36    }
37
38    #[cfg(test)]
39    mod tests {
40        use super::*;
41
42        #[test]
43        fn jshift_inplace_mutation() {
44            let mut json =
45                b"{\"node_id\": \"concept-1\", \"status\": \"draft\", \"weight\": 0.5}".to_vec();
46            update_json_field_inplace(&mut json, "status", b"\"published\"").unwrap();
47            let status = extract_json_field_slice(&json, "status").unwrap();
48            assert_eq!(status, b"\"published\"");
49        }
50    }
51}
52
53#[cfg(feature = "jshift")]
54pub use imp::*;