Skip to content

Commit 4769bd2

Browse files
FunKiteclaude
andauthored
release: prepare v0.5.6 (#142)
- Document all remaining public API items (container v2 types, GPU backends and feature-disabled stubs, Avx512Info, occupancy ray casters) for 100% rustdoc item coverage - Update README What's New section for v0.5.6 - Roll CHANGELOG [Unreleased] into [0.5.6] - 2026-06-10 - Bump version to 0.5.6 Co-authored-by: FunKite <FunKite@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 3db2f21 commit 4769bd2

15 files changed

Lines changed: 99 additions & 18 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.5.6] - 2026-06-10
11+
1012
### Added
13+
- Documentation for all remaining public API items — the container v2 format types (`HeaderV2`, `TocEntry`, `Footer`, `ContainerWriterV2`), GPU backend constructors and availability checks (including feature-disabled stubs), `Avx512Info` feature-detection fields and methods, and GPU-accelerated occupancy ray casters — bringing rustdoc item coverage to 100%.
1114
- New high-level `BccGrid` facade (`grid` module, re-exported at the crate root): convert physical points to cells (`cell_at`/`center_of`), query `neighbors`, `k_ring`, `k_shell`, and `distance`, and run A* pathfinding (`astar`, `astar_where` with a traversability predicate, `astar_with_limit`) on modern `Route64` IDs without handling parity, tiers, or coordinate ranges manually.
1215
- New `examples/quickstart.rs` demonstrating the modern API (`BccGrid`, `Index64`, `Route64`).
1316
- The README's Rust code blocks now compile as doctests (`#[doc = include_str!]` harness in `lib.rs`), so documentation examples can no longer drift from the implementation.

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "octaindex3d"
3-
version = "0.5.5"
3+
version = "0.5.6"
44
edition = "2021"
55
rust-version = "1.77"
66
authors = ["Michael A. McLarney"]

README.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
## Table of Contents
1919

20-
- [What's New in v0.5.5](#whats-new-in-v055)
20+
- [What's New in v0.5.6](#whats-new-in-v056)
2121
- [Overview](#overview)
2222
- [Why BCC Lattice?](#why-bcc-lattice)
2323
- [Interactive 3D Maze Game](#-interactive-3d-maze-game)
@@ -34,15 +34,17 @@
3434
- [Contributing](#contributing)
3535
- [Research and Citation](#research-and-citation)
3636

37-
## What's New in v0.5.5
37+
## What's New in v0.5.6
3838

39-
This release focuses on security dependency updates, GPU dependency compatibility, and release metadata cleanup.
39+
This release introduces the high-level `BccGrid` API, corrects several BCC lattice operations, and adds a new survival mode to the interactive maze.
4040

41-
- **Security dependency fix** - Updated `lz4_flex` to 0.13.1 to avoid an upstream unsafe-mode dictionary compression panic for short dictionaries.
42-
- **GPU dependency refresh** - Updated `cudarc` to 0.19.7 and `wgpu` to 29.0.3, including the replacement for the yanked `wgpu` 29.0.2 release.
43-
- **Runtime and tooling updates** - Refreshed `rkyv`, `rayon`, `clap`, Cargo lockfile resolution, and GitHub Actions dependency tooling.
44-
- **Feature build fix** - Restored `--no-default-features` builds by keeping legacy serialization helpers behind the `serde` feature.
45-
- **Release metadata cleanup** - Promoted the accumulated unreleased dependency notes into the v0.5.5 changelog before publishing to crates.io.
41+
- **New `BccGrid` facade** - Convert physical points to cells, query `neighbors`, `k_ring`, `k_shell`, and `distance`, and run A* pathfinding on modern `Route64` IDs without handling parity, tiers, or coordinate ranges manually. See the [Quick Start](#quick-start) and `examples/quickstart.rs`.
42+
- **Lattice correctness fixes** - `physical_to_lattice` now snaps any finite in-range point to the nearest valid BCC point and honors its `resolution` parameter; `get_children` produces the 8 parity-valid children with `get_parent` as its exact inverse; `batch_validate_routes` applies the correct all-same-parity rule.
43+
- **Legacy API deprecations** - The v0.2-era `CellID`, `path::*`, and `Layer` APIs are deprecated in favor of `BccGrid` and the modern ID types. All remain available for compatibility.
44+
- **README doctests** - The README's Rust code blocks now compile as doctests, so documentation examples stay in sync with the implementation.
45+
- **Bloodhound survival mode** - A new mode for `octaindex3d play`: reach the goal before pursuing bloodhounds catch you, with spike traps, scent trails, and progressive level sizing.
46+
- **Security** - Replaced the unmaintained `serde_cbor` dependency with `ciborium` (RUSTSEC-2021-0127); the `Dataset` CBOR API is unchanged.
47+
- **Documentation coverage** - Documented the remaining public API items (container v2 format types, GPU backends, AVX-512 feature detection) for complete docs.rs coverage.
4648

4749
See the full [Changelog](CHANGELOG.md) for release history.
4850

src/container_v2.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,19 @@ impl Default for StreamConfig {
4141
/// Container v2 header (32 bytes)
4242
#[derive(Debug, Clone)]
4343
pub struct HeaderV2 {
44+
/// Container format version (currently 2).
4445
pub format_version: u8,
46+
/// Feature flags; bit 0 indicates per-frame SHA-256 hashes are present.
4547
pub flags: u8,
48+
/// Unique stream identifier, derived from the creation timestamp.
4649
pub stream_id: u64,
50+
/// Byte offset of the first frame (immediately after the 32-byte header).
4751
pub first_frame_offset: u64,
4852
}
4953

5054
impl HeaderV2 {
55+
/// Creates a header for a new stream, generating a fresh `stream_id`
56+
/// and setting the SHA-256 flag if `enable_sha256` is true.
5157
pub fn new(enable_sha256: bool) -> Self {
5258
use std::time::{Duration, SystemTime, UNIX_EPOCH};
5359

@@ -65,10 +71,12 @@ impl HeaderV2 {
6571
}
6672
}
6773

74+
/// Returns true if frames in this stream carry SHA-256 integrity hashes.
6875
pub fn has_sha256(&self) -> bool {
6976
(self.flags & 0x01) != 0
7077
}
7178

79+
/// Serializes the header to its fixed 32-byte on-disk representation.
7280
pub fn to_bytes(&self) -> [u8; 32] {
7381
let mut bytes = [0u8; 32];
7482
bytes[0..8].copy_from_slice(MAGIC_V2);
@@ -80,6 +88,9 @@ impl HeaderV2 {
8088
bytes
8189
}
8290

91+
/// Parses a header from its 32-byte on-disk representation.
92+
///
93+
/// Returns [`Error::InvalidFormat`] if the magic number does not match.
8394
pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self> {
8495
if &bytes[0..8] != MAGIC_V2 {
8596
return Err(Error::InvalidFormat("Invalid magic number".to_string()));
@@ -105,17 +116,26 @@ impl HeaderV2 {
105116
/// TOC entry (32 bytes)
106117
#[derive(Debug, Clone)]
107118
pub struct TocEntry {
119+
/// Byte offset of the frame within the container.
108120
pub offset: u64,
121+
/// Size of the frame payload before compression, in bytes.
109122
pub uncompressed_len: u32,
123+
/// Size of the frame payload after compression, in bytes.
110124
pub compressed_len: u32,
125+
/// Compression codec identifier used for this frame.
111126
pub codec: u8,
127+
/// Graph identifier the frame belongs to.
112128
pub graph: u8,
129+
/// Level-of-detail tag for the frame.
113130
pub lod: u8,
131+
/// Storage tier tag for the frame.
114132
pub tier: u8,
133+
/// Monotonically increasing sequence number of the frame.
115134
pub seq: u64,
116135
}
117136

118137
impl TocEntry {
138+
/// Serializes the entry to its fixed 32-byte on-disk representation.
119139
pub fn to_bytes(&self) -> [u8; 32] {
120140
let mut bytes = [0u8; 32];
121141
bytes[0..8].copy_from_slice(&self.offset.to_be_bytes());
@@ -129,6 +149,7 @@ impl TocEntry {
129149
bytes
130150
}
131151

152+
/// Parses an entry from its 32-byte on-disk representation.
132153
pub fn from_bytes(bytes: &[u8; 32]) -> Self {
133154
Self {
134155
offset: u64::from_be_bytes(
@@ -162,13 +183,18 @@ impl TocEntry {
162183
/// Footer (32 bytes)
163184
#[derive(Debug, Clone)]
164185
pub struct Footer {
186+
/// Byte offset where the table of contents begins.
165187
pub toc_offset: u64,
188+
/// Length of the table of contents, in bytes.
166189
pub toc_len: u64,
190+
/// Number of TOC entries (frames) recorded.
167191
pub entry_count: u64,
192+
/// Copy of the header flags, for recovery without re-reading the header.
168193
pub flags_copy: u64,
169194
}
170195

171196
impl Footer {
197+
/// Serializes the footer to its fixed 32-byte on-disk representation.
172198
pub fn to_bytes(&self) -> [u8; 32] {
173199
let mut bytes = [0u8; 32];
174200
bytes[0..8].copy_from_slice(&self.toc_offset.to_be_bytes());
@@ -178,6 +204,7 @@ impl Footer {
178204
bytes
179205
}
180206

207+
/// Parses a footer from its 32-byte on-disk representation.
181208
pub fn from_bytes(bytes: &[u8; 32]) -> Self {
182209
Self {
183210
toc_offset: u64::from_be_bytes(
@@ -216,6 +243,9 @@ pub struct ContainerWriterV2<W: Write + Seek> {
216243
}
217244

218245
impl<W: Write + Seek> ContainerWriterV2<W> {
246+
/// Creates a writer over `writer`, immediately writing the stream header.
247+
///
248+
/// Frames are LZ4-compressed by default; see [`Self::with_compression`].
219249
pub fn new(mut writer: W, config: StreamConfig) -> Result<Self> {
220250
let header = HeaderV2::new(config.enable_sha256);
221251

@@ -233,11 +263,16 @@ impl<W: Write + Seek> ContainerWriterV2<W> {
233263
})
234264
}
235265

266+
/// Replaces the default LZ4 codec with a custom [`Compression`] implementation.
236267
pub fn with_compression(mut self, compression: Box<dyn Compression>) -> Result<Self> {
237268
self.compression = compression;
238269
Ok(self)
239270
}
240271

272+
/// Appends one frame of data, compressing it and recording a TOC entry.
273+
///
274+
/// A checkpoint (TOC + footer) is flushed automatically once the configured
275+
/// frame-count or byte thresholds in [`StreamConfig`] are reached.
241276
pub fn write_frame(&mut self, data: &[u8]) -> Result<()> {
242277
let uncompressed_len = data.len() as u32;
243278
let offset = self.writer.stream_position()?;
@@ -331,6 +366,10 @@ impl<W: Write + Seek> ContainerWriterV2<W> {
331366
Ok(())
332367
}
333368

369+
/// Finalizes the container, writing the last checkpoint (TOC + footer).
370+
///
371+
/// Must be called for the container to be readable; dropping the writer
372+
/// without calling `finish` leaves only data up to the last checkpoint.
334373
pub fn finish(mut self) -> Result<()> {
335374
// Write final checkpoint
336375
if !self.toc_entries.is_empty() {

src/layers/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub mod ros2 {
6262
pub use super::ros2_bridge::*;
6363
}
6464

65-
// Re-export GPU types (conditionally)
65+
/// Re-export GPU-accelerated occupancy types (available with `gpu-metal` or `gpu-cuda`)
6666
#[cfg(any(feature = "gpu-metal", feature = "gpu-cuda"))]
6767
pub mod gpu {
6868
pub use super::occupancy_gpu::*;

src/layers/occupancy_gpu.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,16 @@ mod metal_impl {
125125
use metal::*;
126126
use std::sync::Arc;
127127

128+
/// Ray-casting backend that runs occupancy updates on the GPU via Metal.
128129
pub struct MetalRayCaster {
129130
_device: Arc<Device>,
130131
_command_queue: Arc<CommandQueue>,
131132
_pipeline: ComputePipelineState,
132133
}
133134

134135
impl MetalRayCaster {
136+
/// Creates a ray caster on the system's default Metal device,
137+
/// compiling the occupancy ray-cast compute shader.
135138
pub fn new() -> Result<Self> {
136139
let device = Device::system_default()
137140
.ok_or_else(|| Error::InvalidFormat("No Metal device found".to_string()))?;
@@ -193,11 +196,13 @@ pub use metal_impl::MetalRayCaster;
193196
mod cuda_impl {
194197
use super::*;
195198

199+
/// Ray-casting backend that runs occupancy updates on NVIDIA GPUs via CUDA.
196200
pub struct CudaRayCaster {
197201
// CUDA context and kernels would go here
198202
}
199203

200204
impl CudaRayCaster {
205+
/// Creates a CUDA ray caster.
201206
pub fn new() -> Result<Self> {
202207
// Initialize CUDA ray casting kernel
203208
Ok(Self {})

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ mod tests {
121121

122122
#[test]
123123
fn test_version() {
124-
assert_eq!(VERSION, "0.5.5");
124+
assert_eq!(VERSION, "0.5.6");
125125
}
126126

127127
#[test]

src/performance/avx512.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub fn has_avx512f() -> bool {
2424
is_x86_feature_detected!("avx512f")
2525
}
2626

27+
/// Check if AVX-512F (foundation) is available (always false on non-x86_64)
2728
#[cfg(not(target_arch = "x86_64"))]
2829
pub fn has_avx512f() -> bool {
2930
false
@@ -35,6 +36,7 @@ pub fn has_avx512cd() -> bool {
3536
is_x86_feature_detected!("avx512cd")
3637
}
3738

39+
/// Check if AVX-512 with conflict detection is available (always false on non-x86_64)
3840
#[cfg(not(target_arch = "x86_64"))]
3941
pub fn has_avx512cd() -> bool {
4042
false
@@ -141,15 +143,22 @@ pub unsafe fn batch_morton_encode_avx512(coords: &[(u16, u16, u16)]) -> Vec<u64>
141143

142144
/// Get AVX-512 feature availability summary
143145
pub struct Avx512Info {
144-
pub has_f: bool, // Foundation
145-
pub has_cd: bool, // Conflict Detection
146-
pub has_dq: bool, // Doubleword and Quadword
147-
pub has_bw: bool, // Byte and Word
148-
pub has_vl: bool, // Vector Length Extensions
149-
pub has_vnni: bool, // Vector Neural Network Instructions
146+
/// Foundation (AVX-512F)
147+
pub has_f: bool,
148+
/// Conflict Detection (AVX-512CD)
149+
pub has_cd: bool,
150+
/// Doubleword and Quadword (AVX-512DQ)
151+
pub has_dq: bool,
152+
/// Byte and Word (AVX-512BW)
153+
pub has_bw: bool,
154+
/// Vector Length Extensions (AVX-512VL)
155+
pub has_vl: bool,
156+
/// Vector Neural Network Instructions (AVX-512VNNI)
157+
pub has_vnni: bool,
150158
}
151159

152160
impl Avx512Info {
161+
/// Detect which AVX-512 feature sets the current CPU supports
153162
#[cfg(target_arch = "x86_64")]
154163
pub fn detect() -> Self {
155164
Self {
@@ -162,6 +171,7 @@ impl Avx512Info {
162171
}
163172
}
164173

174+
/// Detect AVX-512 feature sets (all false on non-x86_64)
165175
#[cfg(not(target_arch = "x86_64"))]
166176
pub fn detect() -> Self {
167177
Self {
@@ -174,10 +184,12 @@ impl Avx512Info {
174184
}
175185
}
176186

187+
/// Returns true if the AVX-512 foundation instructions are available
177188
pub fn is_available(&self) -> bool {
178189
self.has_f
179190
}
180191

192+
/// Print a human-readable summary of detected AVX-512 features to stdout
181193
pub fn print_info(&self) {
182194
println!("AVX-512 Features:");
183195
println!(" Foundation (F): {}", self.has_f);

src/performance/gpu/cuda.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ impl CudaBackend {
4545
}
4646
}
4747

48+
/// Stub CUDA backend for Apple platforms, where CUDA is unavailable.
4849
#[cfg(all(feature = "gpu-cuda", any(target_os = "macos", target_os = "ios")))]
4950
pub struct CudaBackend;
5051

@@ -116,11 +117,13 @@ impl GpuBackend for CudaBackend {
116117
}
117118
}
118119

120+
/// Stub CUDA backend used when the `gpu-cuda` feature is not enabled
119121
#[cfg(not(feature = "gpu-cuda"))]
120122
pub struct CudaBackend;
121123

122124
#[cfg(not(feature = "gpu-cuda"))]
123125
impl CudaBackend {
126+
/// Always returns an error: the `gpu-cuda` feature is not enabled
124127
pub fn new() -> Result<Self> {
125128
Err(Error::InvalidFormat("CUDA feature not enabled".to_string()))
126129
}
@@ -134,11 +137,13 @@ pub fn is_cuda_available() -> bool {
134137
.unwrap_or(false)
135138
}
136139

140+
/// Check if CUDA is available (always false on Apple platforms)
137141
#[cfg(all(feature = "gpu-cuda", any(target_os = "macos", target_os = "ios")))]
138142
pub fn is_cuda_available() -> bool {
139143
false
140144
}
141145

146+
/// Check if CUDA is available (always false without the `gpu-cuda` feature)
142147
#[cfg(not(feature = "gpu-cuda"))]
143148
pub fn is_cuda_available() -> bool {
144149
false

0 commit comments

Comments
 (0)