Expand description
Checksummed persistent blocks built on top of bstack.
§Overview
bblock wraps any BStackAllocator and appends a 4-byte CRC32 checksum
to every allocation. You verify integrity at any time with
BBlock::verify or BBlockView::verify; if the stored checksum does
not match the current data, the block has been corrupted since it was last
written through the safe API.
The main types:
| Type | Role |
|---|---|
BBlockAllocator | Wraps a BStackAllocator; produces BBlocks |
BBlock | Checksummed block handle; source of views, readers, and writers |
BBlockView | Safe read/write window with subview support |
BBlockReader | Cursor-based io::Read + io::Seek over a view’s data |
BBlockWriter | Cursor-based io::Write + io::Seek that maintains the checksum |
§What this crate protects you from
Undetected silent corruption — bit rot, partial writes, and other
storage anomalies that change bytes without signalling an error. verify()
catches these as long as the checksum bytes themselves are intact.
§What this crate does not protect you from
unsafecode bypassing checksum tracking. Writing through a rawBStackSliceobtained viaBBlock::into_sliceleaves the checksum stale. The safe API (BBlockView,BBlockWriter) always recomputes it.- A buggy or malicious allocator. If the underlying
BStackAllocatorwrites to the wrong offsets or lengths, checksums cannot compensate. - Direct use of
bstack. Writing to the same region through abstackhandle updates the data but not the checksum.
§Detection, not recovery
bblock only detects corruption — it does not repair, revert, or
reconstruct. verify() returning false means the data must not be trusted,
but the crate provides no mechanism to restore a previous good value.
The CRC32 checksum is also not part of the allocator’s crash-recovery
strategy. When a bstack file is reopened after a crash the allocator
performs its own committed-length recovery; bblock’s checksum is
orthogonal to that. If you want checksum-based corruption detection baked
into allocation-level recovery, use an allocator that natively supports it.
§Limitations and caveats
- If the checksum bytes are also corrupted,
verify()may returntruefor corrupt data orfalsefor intact data, with no way to distinguish the two. CRC32 catches the vast majority of real-world corruption but is not a cryptographic guarantee. - Not a substitute for proper consistency strategies. For applications that require strong guarantees — write-ahead logs, copy-on-write pages, two-phase commit — checksums are a useful building block but do not replace those techniques. Reach for those tools rather than treating checksums as an escape hatch from studying them.
- Avoid double-wrapping small blocks. Storing a block reference (a
serialized
BBlock) inside anotherBBlockis valid, but the 4-byte checksum overhead is proportionally large for tiny payloads. Prefer coarser-grained checksumming for small structures.
§Quick start
use bstack::{BStack, LinearBStackAllocator};
use bblock::BBlockAllocator;
let stack = BStack::open("data.bstk").unwrap();
let alloc = BBlockAllocator::new(LinearBStackAllocator::new(stack));
// Allocate a 16-byte block (20 bytes on disk: 16 data + 4 checksum).
let block = alloc.alloc(16).unwrap();
block.view().write(b"hello, bblock!!!").unwrap();
assert!(block.verify().unwrap());
// Subview writes update the full-block checksum automatically.
block.view().subview(0, 5).write(b"world").unwrap();
assert!(block.verify().unwrap());Structs§
- BBlock
- A handle to a checksummed block allocated by a
BBlockAllocator. - BBlock
Allocator - Generic wrapper over any
BStackAllocatorthat transparently appends a 4-byte CRC32 checksum to every allocation. - BBlock
Reader - A cursor-based reader over the bytes covered by a
BBlockView. - BBlock
View - A safe read/write window into a sub-range of a
BBlock’s usable data. - BBlock
Writer - A cursor-based writer over the bytes covered by a
BBlockView.
Constants§
- CHECKSUM_
LENGTH - Number of bytes appended to every allocation for the CRC32 checksum.