bolt-lite 0.1.0

Minimal read-only BoltDB parser for containerd metadata
Documentation
# bolt-lite

Minimal, read-only BoltDB parser focused on containerd metadata.db. It keeps everything in-memory, walks buckets, and exposes a tiny API that mirrors common containerd layouts.

## Features
- Parse BoltDB meta pages and B+tree without unsafe code.
- Bucket navigation (`Tx::bucket`, `Tx::bucket_path`), entry lookup, and iteration.
- Cursor over leaf entries and simple stats.
- No writes or page mutations.

## Quick start
```rust
use bolt_lite::Bolt;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let db = Bolt::open_ro("/var/lib/containerd/io.containerd.metadata.v1.bolt/meta.db")?;
    let tx = db.begin()?;
    let images = tx
        .bucket_path(&[b"v1", b"default", b"images"])
        .expect("images bucket")
        .iter_buckets();

    for (name, bucket) in images {
        if let Some(desc) = bucket.get(b"target") {
            println!("{} -> {} bytes", String::from_utf8_lossy(&name), desc.len());
        }
    }
    Ok(())
}
```

## Buckets and helpers
- `Tx::bucket_path` handles nested buckets by byte segments.
- `Bucket::get` and `Bucket::bucket` fetch values or nested buckets.
- `Bucket::cursor` iterates leaf entries; `Bucket::iter_buckets` discovers child buckets with `BUCKET_VALUE_FLAG` set.
- `ok_opt` converts `Result<T, E>` into `Option<T>` when you want fallbacks.

## Notes
- Only supports read-only access; checksum and freelist validation are intentionally skipped to tolerate containerd variants.
- Page sizes outside 1 KiB–64 KiB are rejected.
- Inline buckets (root=0) are handled by inlining the value bytes.

## License
MIT