mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-30 12:18:11 -07:00
global: snapshot
This commit is contained in:
@@ -2,75 +2,76 @@ use std::ops::ControlFlow;
|
||||
|
||||
use brk_types::{BlkMetadata, BlkPosition};
|
||||
|
||||
use crate::{XORBytes, XORIndex};
|
||||
use crate::{XORBytes, XORIndex, xor_bytes::XOR_LEN};
|
||||
|
||||
const MAGIC_BYTES: [u8; 4] = [249, 190, 180, 217];
|
||||
const MAGIC_BYTES: [u8; 4] = [0xF9, 0xBE, 0xB4, 0xD9];
|
||||
|
||||
pub fn find_magic(bytes: &[u8], xor_i: &mut XORIndex, xor_bytes: XORBytes) -> Option<usize> {
|
||||
let mut window = [0u8; 4];
|
||||
for (i, &b) in bytes.iter().enumerate() {
|
||||
window.rotate_left(1);
|
||||
window[3] = xor_i.byte(b, xor_bytes);
|
||||
if window == MAGIC_BYTES {
|
||||
return Some(i + 1);
|
||||
}
|
||||
/// Returns the position **immediately after** the matched magic, or
|
||||
/// `None` if no match. Advances `xor_i` by the bytes consumed either
|
||||
/// way.
|
||||
pub(crate) fn find_magic(bytes: &[u8], xor_i: &mut XORIndex, xor_bytes: XORBytes) -> Option<usize> {
|
||||
let len = bytes.len();
|
||||
if len < MAGIC_BYTES.len() {
|
||||
xor_i.add_assign(len);
|
||||
return None;
|
||||
}
|
||||
|
||||
let xb = *xor_bytes;
|
||||
let mut phase = xor_i.phase();
|
||||
let mut i = 0;
|
||||
let stop = len - MAGIC_BYTES.len();
|
||||
|
||||
while i <= stop {
|
||||
if bytes[i] ^ xb[phase] == MAGIC_BYTES[0] {
|
||||
let p1 = (phase + 1) & (XOR_LEN - 1);
|
||||
let p2 = (phase + 2) & (XOR_LEN - 1);
|
||||
let p3 = (phase + 3) & (XOR_LEN - 1);
|
||||
if bytes[i + 1] ^ xb[p1] == MAGIC_BYTES[1]
|
||||
&& bytes[i + 2] ^ xb[p2] == MAGIC_BYTES[2]
|
||||
&& bytes[i + 3] ^ xb[p3] == MAGIC_BYTES[3]
|
||||
{
|
||||
xor_i.set_phase(phase + MAGIC_BYTES.len());
|
||||
return Some(i + MAGIC_BYTES.len());
|
||||
}
|
||||
}
|
||||
phase = (phase + 1) & (XOR_LEN - 1);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
xor_i.set_phase(phase + (len - i));
|
||||
None
|
||||
}
|
||||
|
||||
pub struct ScanResult {
|
||||
pub first_magic: Option<usize>,
|
||||
pub interrupted: bool,
|
||||
}
|
||||
|
||||
/// Scans `buf` for blocks. `file_offset` is the absolute position of
|
||||
/// `buf[0]` in the file. Calls `on_block` for each complete block found,
|
||||
/// passing the block's raw bytes as a mutable borrow of the buffer — the
|
||||
/// caller decides whether to clone them (e.g. to ship owned data to a
|
||||
/// parser thread) or process them in place (e.g. cheap header peek).
|
||||
pub fn scan_bytes(
|
||||
/// Scans `buf` (the full contents of one blk file) for blocks,
|
||||
/// calling `on_block` for each. The block bytes are passed as a
|
||||
/// mutable borrow so the callback can clone (to ship to a parser
|
||||
/// thread) or process in place (to peek the header).
|
||||
pub(crate) fn scan_bytes(
|
||||
buf: &mut [u8],
|
||||
blk_index: u16,
|
||||
file_offset: usize,
|
||||
xor_bytes: XORBytes,
|
||||
mut on_block: impl FnMut(BlkMetadata, &mut [u8], XORIndex) -> ControlFlow<()>,
|
||||
) -> ScanResult {
|
||||
) {
|
||||
let mut xor_i = XORIndex::default();
|
||||
xor_i.add_assign(file_offset);
|
||||
let mut first_magic = None;
|
||||
let mut i = 0;
|
||||
|
||||
while let Some(off) = find_magic(&buf[i..], &mut xor_i, xor_bytes) {
|
||||
let before = i;
|
||||
i += off;
|
||||
first_magic.get_or_insert(before + off.saturating_sub(4));
|
||||
if i + 4 > buf.len() {
|
||||
break;
|
||||
return;
|
||||
}
|
||||
let len = u32::from_le_bytes(
|
||||
xor_i
|
||||
.bytes(&mut buf[i..i + 4], xor_bytes)
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
) as usize;
|
||||
let mut size_bytes = [buf[i], buf[i + 1], buf[i + 2], buf[i + 3]];
|
||||
xor_i.bytes(&mut size_bytes, xor_bytes);
|
||||
let len = u32::from_le_bytes(size_bytes) as usize;
|
||||
i += 4;
|
||||
if i + len > buf.len() {
|
||||
break;
|
||||
return;
|
||||
}
|
||||
let position = BlkPosition::new(blk_index, (file_offset + i) as u32);
|
||||
let metadata = BlkMetadata::new(position, len as u32);
|
||||
let metadata = BlkMetadata::new(BlkPosition::new(blk_index, i as u32), len as u32);
|
||||
if on_block(metadata, &mut buf[i..i + len], xor_i).is_break() {
|
||||
return ScanResult {
|
||||
first_magic,
|
||||
interrupted: true,
|
||||
};
|
||||
return;
|
||||
}
|
||||
i += len;
|
||||
xor_i.add_assign(len);
|
||||
}
|
||||
|
||||
ScanResult {
|
||||
first_magic,
|
||||
interrupted: false,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user