use alloc::collections::BTreeMap;
use core::ops::Range;
use std::io;
use crate::digest::Digest;
use crate::path::RelPath;
#[derive(Debug, Default)]
pub(crate) struct Tree {
buf: Vec<u8>,
index: BTreeMap<RelPath, Range<usize>>,
}
impl Tree {
#[must_use]
pub(crate) fn get(&self, path: &RelPath) -> Option<&[u8]> {
self.buf.get(self.index.get(path)?.clone())
}
pub(crate) fn contains(&self, path: &RelPath) -> bool {
self.index.contains_key(path)
}
pub(crate) fn iter(&self) -> impl Iterator<Item = (&RelPath, &[u8])> {
self.index.iter().filter_map(|(path, span)| Some((path, self.buf.get(span.clone())?)))
}
#[must_use]
pub(crate) fn digest(&self) -> Digest {
let mut hasher = blake3::Hasher::new();
for (path, bytes) in self.iter() {
hasher.update(path.as_str().as_bytes());
hasher.update(&[0]);
hasher.update(Digest::of(bytes).as_bytes());
}
Digest::new(hasher.finalize())
}
pub(crate) fn put(&mut self, path: RelPath, bytes: &[u8]) {
let start = self.buf.len();
self.buf.extend_from_slice(bytes);
self.index.insert(path, start..self.buf.len());
}
pub(crate) fn insert<F>(&mut self, path: RelPath, fill: F) -> io::Result<()>
where
F: FnOnce(&mut Vec<u8>) -> io::Result<()>,
{
let start = self.buf.len();
fill(&mut self.buf)?;
self.index.insert(path, start..self.buf.len());
Ok(())
}
}