qualia_core_db/q42/volume/
cursor.rs1use std::io;
4
5use super::super::{Q42Volume, QUINS_PER_BLOCK, SUPERBLOCK_HEADER, SUPERBLOCK_SIZE};
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub struct Q42BlockMeta {
10 pub block_index: usize,
11 pub live_quins: usize,
12}
13
14pub struct Q42BlockCursor<'a> {
16 volume: &'a Q42Volume,
17 next_index: usize,
18}
19
20impl<'a> Q42BlockCursor<'a> {
21 pub(super) fn new(volume: &'a Q42Volume) -> Self {
22 Self {
23 volume,
24 next_index: 0,
25 }
26 }
27
28 pub fn next_into(&mut self, out: &mut [u8]) -> io::Result<Option<Q42BlockMeta>> {
31 if self.next_index >= self.volume.block_count() as usize {
32 return Ok(None);
33 }
34 let block_index = self.next_index;
35 self.next_index += 1;
36 let decoded = self.volume.read_superblock_into(block_index, out)?;
37 if decoded != SUPERBLOCK_SIZE {
38 return Err(io::Error::new(
39 io::ErrorKind::InvalidData,
40 "Q42 block did not decode to a complete SuperBlock",
41 ));
42 }
43 let live_quins = u64::from_le_bytes(out[16..24].try_into().unwrap()) as usize;
44 if live_quins > QUINS_PER_BLOCK {
45 return Err(io::Error::new(
46 io::ErrorKind::InvalidData,
47 "Q42 SuperBlock declares more live Quins than its ledger holds",
48 ));
49 }
50 if SUPERBLOCK_HEADER + live_quins * crate::q42_volume::QUIN_SIZE > SUPERBLOCK_SIZE {
51 return Err(io::Error::new(
52 io::ErrorKind::InvalidData,
53 "Q42 SuperBlock live Quin count exceeds its decoded bounds",
54 ));
55 }
56 Ok(Some(Q42BlockMeta {
57 block_index,
58 live_quins,
59 }))
60 }
61
62 #[inline]
63 pub fn next_index(&self) -> usize {
64 self.next_index
65 }
66}
67
68impl Q42Volume {
69 pub fn block_cursor(&self) -> Q42BlockCursor<'_> {
71 Q42BlockCursor::new(self)
72 }
73}