use crate::Result;
use crate::store::CodecFormat;
use serde::Serialize;
use serde::de::DeserializeOwned;
use std::fmt::Debug;
pub trait TextDocument: Send + Sync + Sized + Clone + 'static {
type Node: Clone + Debug;
fn format() -> CodecFormat;
fn get(&self, parts: &[&str]) -> Option<&Self::Node>;
fn set(&mut self, parts: &[&str], node: Self::Node) -> Result<()>;
fn delete(&mut self, parts: &[&str]) -> Result<Option<Self::Node>>;
fn scan(&self, parts: &[&str]) -> Vec<(String, Self::Node)>;
fn parse(src: &str) -> Result<Self>;
fn serialize(&self) -> Result<String>;
fn empty() -> Self;
fn deserialize_node<T: DeserializeOwned>(node: &Self::Node) -> Result<T>;
fn serialize_node<T: Serialize>(value: &T) -> Result<Self::Node>;
fn node_to_bytes(node: &Self::Node) -> Result<Vec<u8>>;
fn bytes_to_node(bytes: &[u8]) -> Result<Self::Node>;
}
pub trait Navigable: Sized + Clone {
fn make_empty_map() -> Self;
fn get_child(&self, key: &str) -> Option<&Self>;
fn get_child_mut(&mut self, key: &str) -> Option<&mut Self>;
fn ensure_map(&mut self);
fn insert_child(&mut self, key: &str, val: Self);
fn remove_child(&mut self, key: &str) -> Option<Self>;
fn scan_children(&self) -> Vec<(String, Self)>;
}
#[inline]
fn normalise_parts<'a>(parts: &'a [&'a str]) -> &'a [&'a str] {
if parts == ["."] { &[] } else { parts }
}
pub fn generic_get<'a, N: Navigable>(root: &'a N, parts: &[&str]) -> Option<&'a N> {
let parts = normalise_parts(parts);
if parts.is_empty() {
return Some(root);
}
let mut current = root;
for part in parts {
current = current.get_child(part)?;
}
Some(current)
}
pub fn generic_set<N: Navigable>(root: &mut N, parts: &[&str], node: N) -> Result<()> {
let parts = normalise_parts(parts);
if parts.is_empty() {
*root = node;
return Ok(());
}
let (last, heads) = parts.split_last().unwrap();
let mut current = root;
for &part in heads {
current.ensure_map();
if current.get_child(part).is_none() {
current.insert_child(part, N::make_empty_map());
}
current = current.get_child_mut(part).unwrap();
}
current.ensure_map();
current.insert_child(last, node);
Ok(())
}
pub fn generic_delete<N: Navigable>(root: &mut N, parts: &[&str]) -> Result<Option<N>> {
let parts = normalise_parts(parts);
if parts.is_empty() {
return Ok(None);
}
let (last, heads) = parts.split_last().unwrap();
let mut current = root;
for &part in heads {
if let Some(next) = current.get_child_mut(part) {
current = next;
} else {
return Ok(None);
}
}
Ok(current.remove_child(last))
}
pub fn generic_scan<N: Navigable>(root: &N, parts: &[&str]) -> Vec<(String, N)> {
let parts = normalise_parts(parts);
let mut results = Vec::new();
let prefix_str = parts.join(".");
let node = if parts.is_empty() {
Some(root)
} else {
generic_get(root, parts)
};
if let Some(node) = node {
for (k, v) in node.scan_children() {
let full_key = if prefix_str.is_empty() {
k
} else {
format!("{}.{}", prefix_str, k)
};
results.push((full_key, v));
}
}
results
}