bolt-lite 0.1.0

Minimal read-only BoltDB parser for containerd metadata
Documentation
use crate::{meta::*, page::*, Bolt, Error, Result};

pub(crate) fn find_in_tree(db: &Bolt, page_id: u64, key: &[u8]) -> Result<Option<LeafEntry>> {
    let page = db.read_page(page_id)?;
    let flags = page_flags(page);
    if flags & BRANCH_PAGE_FLAG != 0 {
        let elems = branch_elements(db.page_size, page)?;
        for i in 0..elems.len() {
            if key < elems[i].key.as_slice() {
                return find_in_tree(db, elems[i].pgid, key);
            }
        }
        return find_in_tree(db, elems.last().ok_or(Error::Corrupt("empty branch"))?.pgid, key);
    }
    if flags & LEAF_PAGE_FLAG != 0 {
        return find_in_page(db.page_size, page, key);
    }
    Err(Error::Corrupt("unexpected page type"))
}

pub(crate) fn find_in_page(page_size: usize, page: &[u8], key: &[u8]) -> Result<Option<LeafEntry>> {
    let entries = leaf_elements(page_size, page)?;
    for e in entries {
        if e.key == key {
            return Ok(Some(e));
        }
    }
    Ok(None)
}

pub(crate) fn collect_tree_entries(db: &Bolt, page_id: u64) -> Result<Vec<LeafEntry>> {
    let page = db.read_page(page_id)?;
    let flags = page_flags(page);
    if flags & BRANCH_PAGE_FLAG != 0 {
        let mut out = Vec::new();
        for elem in branch_elements(db.page_size, page)? {
            out.extend(collect_tree_entries(db, elem.pgid)?);
        }
        Ok(out)
    } else if flags & LEAF_PAGE_FLAG != 0 {
        leaf_elements(db.page_size, page)
    } else {
        Err(Error::Corrupt("unexpected page type"))
    }
}