1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//! Checksummed persistent blocks built on top of [`bstack`](https://docs.rs/bstack).
//!
//! # Overview
//!
//! `bblock` wraps any [`BStackAllocator`] and appends a 4-byte checksum to
//! every allocation. Two checksum strategies are available:
//!
//! | Module | Checksum | Update strategy | Use when |
//! |---------------------|----------|------------------------------|-------------------------------------|
//! | [`checksum::crc`] | CRC32 | Full-block recompute | Detection strength matters most |
//! | [`checksum::xor`] | XOR | Incremental (changed bytes only) | Write throughput matters most |
//!
//! Both modules expose the same API shape. All types are re-exported at
//! [`checksum`] (e.g. [`checksum::BCrcBlock`]) and at the
//! crate root for backward compatibility.
//!
//! # Composability
//!
//! Both allocator wrappers implement [`bstack::BStackAllocator`] themselves,
//! so they can be used in any generic context that accepts `T: BStackAllocator`.
//! This is what allows [`BCrcBlock`] and [`BXorBlock`] to implement
//! [`bstack::BStackGuardedSlice`] without requiring the stricter
//! `BStackSliceAllocator` bound.
//!
//! The wrappers can be composed freely:
//!
//! ```rust,no_run
//! use bstack::{BStack, LinearBStackAllocator};
//! use bblock::checksum::{BCrcBlockAllocator, BXorBlockAllocator};
//!
//! let stack = BStack::open("data.bstk").unwrap();
//! // XOR checksum over CRC32-checksummed blocks
//! let alloc = BXorBlockAllocator::new(BCrcBlockAllocator::new(LinearBStackAllocator::new(stack)));
//! ```
//!
//! # bstack `guarded` feature
//!
//! When bstack is built with the `guarded` feature (enabled by default in this
//! crate), all four concrete types implement [`bstack::BStackGuardedSlice`]:
//! [`BCrcBlock`], [`BCrcBlockView`], [`BXorBlock`], and [`BXorBlockView`]. The view
//! types additionally implement [`bstack::BStackGuardedSliceSubview`].
//!
//! * `as_slice()` returns the data region only (the checksum trailer is hidden;
//! for views, only the view's sub-range is exposed).
//! * `write()` and `zero()` automatically keep the checksum consistent.
//! `BCrcBlock`/`BCrcBlockView` recompute the full CRC32; `BXorBlock`/`BXorBlockView`
//! update incrementally.
//! * `len()`, `is_empty()` (block types) and `len()`, `is_empty()`, `read()`,
//! `write()`, `zero()` (view types) are provided by the trait — callers must
//! `use bstack::BStackGuardedSlice`.
//!
//! # Detection, not recovery
//!
//! `bblock` only **detects** corruption — it does not repair or revert. A
//! `verify()` returning `false` means the data must not be trusted, but the
//! crate provides no mechanism to restore a previous good value.
//!
//! # Quick start
//!
//! ## CRC32 (default, stronger integrity)
//!
//! ```rust,no_run
//! use bstack::{BStack, BStackAllocator, BStackGuardedSlice, LinearBStackAllocator};
//! use bblock::BCrcBlockAllocator;
//!
//! let stack = BStack::open("data.bstk").unwrap();
//! let alloc = BCrcBlockAllocator::new(LinearBStackAllocator::new(stack));
//!
//! let block = alloc.alloc(16).unwrap();
//! block.view().write(b"hello, bblock!!!").unwrap();
//! assert!(block.verify().unwrap());
//! ```
//!
//! ## XOR (faster writes)
//!
//! ```rust,no_run
//! use bstack::{BStack, BStackAllocator, BStackGuardedSlice, LinearBStackAllocator};
//! use bblock::checksum::BXorBlockAllocator;
//!
//! let stack = BStack::open("data.bstk").unwrap();
//! let alloc = BXorBlockAllocator::new(LinearBStackAllocator::new(stack));
//!
//! let block = alloc.alloc(16).unwrap();
//! block.view().write(b"hello, bblock!!!").unwrap();
//! assert!(block.verify().unwrap());
//! ```
// Backwards compatibility: re-export submodules at their old paths.
pub use crc;
pub use xor;
use ;
/// Retrieves the start offset of an inner allocation without consuming it.
///
/// Implemented for [`bstack::BStackSlice`] (base case) and for the block
/// types produced by each wrapper allocator (recursive case).
pub
/// Reconstructs an inner allocation handle from a raw `BStackSlice`.
///
/// # Safety
///
/// `slice` must be an allocation previously returned by `Self::alloc` or
/// `Self::realloc` — passing an arbitrary slice is undefined behavior.
pub unsafe
// Every BStackSliceAllocator is trivially a BStackRawAllocator because
// its allocated type IS the slice.
unsafe
pub use ;
pub type BBlockAllocator<A> = ;
pub type BBlock<'a, A> = ;
pub type BBlockView<'a, A> = ;
pub type BBlockReader<'a, A> = ;
pub type BBlockWriter<'a, A> = ;