Skip to main content

Crate bblock

Crate bblock 

Source
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:

TypeRole
BBlockAllocatorWraps a BStackAllocator; produces BBlocks
BBlockChecksummed block handle; source of views, readers, and writers
BBlockViewSafe read/write window with subview support
BBlockReaderCursor-based io::Read + io::Seek over a view’s data
BBlockWriterCursor-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

  • unsafe code bypassing checksum tracking. Writing through a raw BStackSlice obtained via BBlock::into_slice leaves the checksum stale. The safe API (BBlockView, BBlockWriter) always recomputes it.
  • A buggy or malicious allocator. If the underlying BStackAllocator writes to the wrong offsets or lengths, checksums cannot compensate.
  • Direct use of bstack. Writing to the same region through a bstack handle 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 return true for corrupt data or false for 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 another BBlock is 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.
BBlockAllocator
Generic wrapper over any BStackAllocator that transparently appends a 4-byte CRC32 checksum to every allocation.
BBlockReader
A cursor-based reader over the bytes covered by a BBlockView.
BBlockView
A safe read/write window into a sub-range of a BBlock’s usable data.
BBlockWriter
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.