#![expect(
clippy::expect_used,
reason = "test helpers assert on known-present values; a panic is the failure signal"
)]
#![allow(
dead_code,
reason = "helpers are compiled in every feature subset; their consumers are feature-gated"
)]
#![allow(
clippy::redundant_clone,
reason = "the cloned range is reused on branches other feature subsets compile"
)]
pub fn forge_stale_kv_footer(path: &std::path::Path) -> crate::Result<()> {
use crate::table::block::kv_checksum::FOOTER_TAIL_LEN;
flip_and_restamp_first_data_block(path, FOOTER_TAIL_LEN + 1)
}
pub fn forge_restamped_data_block(path: &std::path::Path) -> crate::Result<()> {
flip_and_restamp_first_data_block(path, 1)
}
pub fn forge_duplicate_section_name(
path: &std::path::Path,
from: &[u8],
to: &[u8],
to_role: crate::table::block::BlockType,
) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::Header;
let mut bytes = std::fs::read(path)?;
const TRAILER_SIZE: usize = 4 + 1 + 1 + 16 + 8 + 8;
let trailer_start = bytes.len() - TRAILER_SIZE;
let read_u64 = |bytes: &[u8], at: usize| {
let Some(b) = bytes.get(at..at + 8) else {
panic!("u64 field within the trailer");
};
u64::from_le_bytes(b.try_into().expect("8 bytes"))
};
let toc_pos = usize::try_from(read_u64(&bytes, trailer_start + 4 + 1 + 1 + 16))
.expect("toc_pos fits usize");
let toc_len = usize::try_from(read_u64(&bytes, trailer_start + 4 + 1 + 1 + 16 + 8))
.expect("toc_len fits usize");
let section_off = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == from) else {
panic!("the SST must carry the section to rename");
};
usize::try_from(entry.pos()).expect("section offset fits usize")
};
{
let Some(block) = bytes.get(section_off..) else {
panic!("section block within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
assert_eq!(
header_len,
Header::header_len(to_role),
"the rerole must keep the header length so the geometry holds",
);
let new_header = Header {
block_type: to_role,
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
let Some(dst) = bytes.get_mut(section_off..section_off + header_len) else {
panic!("section header within the file");
};
dst.copy_from_slice(&hdr_bytes);
}
let toc = bytes.get(toc_pos..toc_pos + toc_len).expect("TOC region");
assert_eq!(toc.get(..4), Some(&b"TOC!"[..]), "TOC magic");
assert_eq!(
toc_pos + toc_len,
trailer_start,
"the TOC must sit directly before the trailer",
);
let count = u32::from_le_bytes(toc.get(4..8).expect("count").try_into().expect("4 bytes"));
let mut new_toc = Vec::with_capacity(toc.len());
new_toc.extend_from_slice(toc.get(..8).expect("TOC header"));
let mut at = 8usize;
let mut renamed = false;
for _ in 0..count {
let pos = toc.get(at..at + 16).expect("pos+len");
at += 16;
let name_len = usize::from(u16::from_le_bytes(
toc.get(at..at + 2)
.expect("name_len")
.try_into()
.expect("2 bytes"),
));
at += 2;
let entry_name = toc.get(at..at + name_len).expect("name");
at += name_len;
new_toc.extend_from_slice(pos);
if entry_name == from {
renamed = true;
new_toc.extend_from_slice(
&u16::try_from(to.len())
.expect("name fits u16")
.to_le_bytes(),
);
new_toc.extend_from_slice(to);
} else {
new_toc.extend_from_slice(&u16::try_from(name_len).expect("fits u16").to_le_bytes());
new_toc.extend_from_slice(entry_name);
}
}
assert!(renamed, "section name present in the TOC");
let fresh = {
let mut hasher = xxhash_rust::xxh3::Xxh3Default::new();
hasher.update(&new_toc);
hasher.digest128()
};
let mut out = Vec::with_capacity(toc_pos + new_toc.len() + TRAILER_SIZE);
out.extend_from_slice(bytes.get(..toc_pos).expect("pre-TOC prefix"));
out.extend_from_slice(&new_toc);
out.extend_from_slice(
bytes
.get(trailer_start..trailer_start + 4 + 1 + 1)
.expect("trailer head"),
);
out.extend_from_slice(&fresh.to_le_bytes());
out.extend_from_slice(
&u64::try_from(toc_pos)
.expect("toc_pos fits u64")
.to_le_bytes(),
);
out.extend_from_slice(
&u64::try_from(new_toc.len())
.expect("TOC length fits u64")
.to_le_bytes(),
);
std::fs::write(path, &out)?;
Ok(())
}
pub fn forge_section_len(path: &std::path::Path, name: &[u8], new_len: u64) -> crate::Result<()> {
let mut bytes = std::fs::read(path)?;
const TRAILER_SIZE: usize = 4 + 1 + 1 + 16 + 8 + 8;
let trailer_start = bytes.len() - TRAILER_SIZE;
let read_u64 = |bytes: &[u8], at: usize| {
let Some(b) = bytes.get(at..at + 8) else {
panic!("u64 field within the trailer");
};
u64::from_le_bytes(b.try_into().expect("8 bytes"))
};
let toc_pos = usize::try_from(read_u64(&bytes, trailer_start + 4 + 1 + 1 + 16))
.expect("toc_pos fits usize");
let toc_len = usize::try_from(read_u64(&bytes, trailer_start + 4 + 1 + 1 + 16 + 8))
.expect("toc_len fits usize");
let toc = bytes.get(toc_pos..toc_pos + toc_len).expect("TOC region");
assert_eq!(toc.get(..4), Some(&b"TOC!"[..]), "TOC magic");
let count = u32::from_le_bytes(toc.get(4..8).expect("count").try_into().expect("4 bytes"));
let mut at = 8usize;
let mut len_field_off: Option<usize> = None;
for _ in 0..count {
let entry_off = at;
at += 16;
let name_len = usize::from(u16::from_le_bytes(
toc.get(at..at + 2)
.expect("name_len")
.try_into()
.expect("2 bytes"),
));
at += 2;
let entry_name = toc.get(at..at + name_len).expect("name");
at += name_len;
if entry_name == name {
len_field_off = Some(toc_pos + entry_off + 8);
}
}
let Some(len_off) = len_field_off else {
panic!(
"section {:?} present in the TOC",
core::str::from_utf8(name)
);
};
bytes
.get_mut(len_off..len_off + 8)
.expect("len field within file")
.copy_from_slice(&new_len.to_le_bytes());
let fresh = {
let mut hasher = xxhash_rust::xxh3::Xxh3Default::new();
hasher.update(bytes.get(toc_pos..toc_pos + toc_len).expect("TOC region"));
hasher.digest128()
};
let ck_off = trailer_start + 4 + 1 + 1;
bytes
.get_mut(ck_off..ck_off + 16)
.expect("trailer checksum")
.copy_from_slice(&fresh.to_le_bytes());
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_section_name(path: &std::path::Path, from: &[u8], to: &[u8]) -> crate::Result<()> {
assert_eq!(from.len(), to.len(), "the rename must keep the name length");
let mut bytes = std::fs::read(path)?;
const TRAILER_SIZE: usize = 4 + 1 + 1 + 16 + 8 + 8;
let trailer_start = bytes.len() - TRAILER_SIZE;
let read_u64 = |bytes: &[u8], at: usize| {
let Some(b) = bytes.get(at..at + 8) else {
panic!("u64 field within the trailer");
};
u64::from_le_bytes(b.try_into().expect("8 bytes"))
};
let toc_pos = usize::try_from(read_u64(&bytes, trailer_start + 4 + 1 + 1 + 16))
.expect("toc_pos fits usize");
let toc_len = usize::try_from(read_u64(&bytes, trailer_start + 4 + 1 + 1 + 16 + 8))
.expect("toc_len fits usize");
{
let Some(toc) = bytes.get_mut(toc_pos..toc_pos + toc_len) else {
panic!("TOC region within the file");
};
let count = u32::from_le_bytes(
toc.get(4..8)
.expect("count prefix")
.try_into()
.expect("4 bytes"),
);
let mut at = 8usize;
let mut name_at = None;
for _ in 0..count {
let name_len = usize::from(u16::from_le_bytes(
toc.get(at + 16..at + 18)
.expect("name_len")
.try_into()
.expect("2 bytes"),
));
let entry_name = toc.get(at + 18..at + 18 + name_len).expect("name");
if entry_name == from {
name_at = Some(at + 18);
break;
}
at += 18 + name_len;
}
let Some(name_at) = name_at else {
panic!("section name present in the TOC");
};
let Some(dst) = toc.get_mut(name_at..name_at + to.len()) else {
panic!("section name within the TOC");
};
dst.copy_from_slice(to);
}
let Some(toc) = bytes.get(toc_pos..toc_pos + toc_len) else {
panic!("TOC region within the file");
};
let fresh = {
let mut hasher = xxhash_rust::xxh3::Xxh3Default::new();
hasher.update(toc);
hasher.digest128()
};
let Some(dst) = bytes.get_mut(trailer_start + 4 + 1 + 1..trailer_start + 4 + 1 + 1 + 16) else {
panic!("toc_checksum within the trailer");
};
dst.copy_from_slice(&fresh.to_le_bytes());
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_section_omitted(path: &std::path::Path, name: &[u8]) -> crate::Result<()> {
let bytes = std::fs::read(path)?;
const TRAILER_SIZE: usize = 4 + 1 + 1 + 16 + 8 + 8;
let trailer_start = bytes.len() - TRAILER_SIZE;
let read_u64 = |bytes: &[u8], at: usize| {
let Some(b) = bytes.get(at..at + 8) else {
panic!("u64 field within the trailer");
};
u64::from_le_bytes(b.try_into().expect("8 bytes"))
};
let toc_pos = usize::try_from(read_u64(&bytes, trailer_start + 4 + 1 + 1 + 16))
.expect("toc_pos fits usize");
let toc_len = usize::try_from(read_u64(&bytes, trailer_start + 4 + 1 + 1 + 16 + 8))
.expect("toc_len fits usize");
let toc = bytes.get(toc_pos..toc_pos + toc_len).expect("TOC region");
assert_eq!(toc.get(..4), Some(&b"TOC!"[..]), "TOC magic");
let count = u32::from_le_bytes(toc.get(4..8).expect("count").try_into().expect("4 bytes"));
let mut new_toc = Vec::with_capacity(toc.len());
new_toc.extend_from_slice(b"TOC!");
new_toc.extend_from_slice(&count.checked_sub(1).expect("TOC has entries").to_le_bytes());
let mut at = 8usize;
let mut omitted = false;
for _ in 0..count {
let entry_start = at;
at += 16;
let name_len = usize::from(u16::from_le_bytes(
toc.get(at..at + 2)
.expect("name_len")
.try_into()
.expect("2 bytes"),
));
at += 2;
let entry_name = toc.get(at..at + name_len).expect("name");
at += name_len;
if entry_name == name {
omitted = true;
} else {
new_toc.extend_from_slice(toc.get(entry_start..at).expect("entry"));
}
}
assert!(omitted, "section name present in the TOC");
let fresh = {
let mut hasher = xxhash_rust::xxh3::Xxh3Default::new();
hasher.update(&new_toc);
hasher.digest128()
};
let mut out = Vec::with_capacity(toc_pos + new_toc.len() + TRAILER_SIZE);
out.extend_from_slice(bytes.get(..toc_pos).expect("pre-TOC prefix"));
out.extend_from_slice(&new_toc);
out.extend_from_slice(
bytes
.get(trailer_start..trailer_start + 4 + 1 + 1)
.expect("trailer head"),
);
out.extend_from_slice(&fresh.to_le_bytes());
out.extend_from_slice(
&u64::try_from(toc_pos)
.expect("toc_pos fits u64")
.to_le_bytes(),
);
out.extend_from_slice(
&u64::try_from(new_toc.len())
.expect("TOC length fits u64")
.to_le_bytes(),
);
std::fs::write(path, &out)?;
Ok(())
}
pub fn forge_tail_meta_value(
path: &std::path::Path,
key: &[u8],
forged_value: &[u8],
) -> crate::Result<()> {
forge_meta_value_in_section(path, b"meta", key, forged_value)
}
pub fn forge_mid_meta_value(
path: &std::path::Path,
key: &[u8],
forged_value: &[u8],
) -> crate::Result<()> {
forge_meta_value_in_section(path, b"meta_mid", key, forged_value)
}
pub fn forge_meta_value_both_mirrors(
path: &std::path::Path,
key: &[u8],
forged_value: &[u8],
) -> crate::Result<()> {
forge_meta_value_in_section(path, b"meta", key, forged_value)?;
forge_meta_value_in_section(path, b"meta_mid", key, forged_value)
}
fn forge_meta_value_in_section(
path: &std::path::Path,
section: &[u8],
key: &[u8],
forged_value: &[u8],
) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::Header;
let mut bytes = std::fs::read(path)?;
let (pos, section_len) = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == section) else {
panic!("the SST must carry the requested meta section");
};
(entry.pos(), entry.len())
};
let block_off = usize::try_from(pos).expect("meta offset fits usize");
let Some(block) = bytes.get(block_off..) else {
panic!("meta block within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
let payload_range =
block_off + header_len..block_off + header_len + header.data_length as usize;
{
let Some(payload) = bytes.get_mut(payload_range.clone()) else {
panic!("meta payload within the file");
};
let Some(key_pos) = payload.windows(key.len()).position(|w| w == key) else {
panic!("meta key present verbatim (restart interval 1)");
};
let val_at = key_pos + key.len();
assert_eq!(
payload.get(val_at).copied(),
u8::try_from(forged_value.len()).ok(),
"the forged value must keep the original length",
);
let Some(value) = payload.get_mut(val_at + 1..val_at + 1 + forged_value.len()) else {
panic!("meta value within the payload");
};
value.copy_from_slice(forged_value);
}
let Some(payload) = bytes.get(payload_range.clone()) else {
panic!("meta payload within the file");
};
let new_checksum = crate::Checksum::from_raw(crate::hash::hash128(payload));
let new_header = Header {
checksum: new_checksum,
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
let Some(hdr_dst) = bytes.get_mut(block_off..block_off + header_len) else {
panic!("meta header within the file");
};
hdr_dst.copy_from_slice(&hdr_bytes);
#[cfg(feature = "page_ecc")]
{
let payload_end = payload_range.end;
let Ok(section_len) = usize::try_from(section_len) else {
panic!("meta section length fits usize");
};
let frame_end = block_off + section_len;
if frame_end > payload_end {
let Some(payload) = bytes.get(payload_range) else {
panic!("meta payload within the file");
};
let parity = crate::ecc::encode_parity(payload, 4, 2)?;
assert_eq!(
frame_end - payload_end,
parity.len(),
"the meta frame's trailer length matches the fixed RS(4,2) layout",
);
let Some(dst) = bytes.get_mut(payload_end..frame_end) else {
panic!("meta parity trailer within the file");
};
dst.copy_from_slice(&parity);
}
}
#[cfg(not(feature = "page_ecc"))]
let _ = section_len;
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_inflated_item_count(path: &std::path::Path) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::Header;
let mut bytes = std::fs::read(path)?;
let block_off = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == b"data") else {
panic!("the SST must carry a data section");
};
usize::try_from(entry.pos()).expect("data offset fits usize")
};
let Some(block) = bytes.get(block_off..) else {
panic!("data block within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
let payload_range =
block_off + header_len..block_off + header_len + header.data_length as usize;
{
let Some(payload) = bytes.get_mut(payload_range.clone()) else {
panic!("data payload within the file");
};
let count_at = payload.len() - core::mem::size_of::<u32>();
let Some(count_le) = payload.get_mut(count_at..) else {
panic!("item count within the payload");
};
let count = u32::from_le_bytes(count_le.try_into().expect("4 bytes"));
count_le.copy_from_slice(&(count + 1).to_le_bytes());
}
let Some(payload) = bytes.get(payload_range) else {
panic!("data payload within the file");
};
let new_checksum = crate::Checksum::from_raw(crate::hash::hash128(payload));
let new_header = Header {
checksum: new_checksum,
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
let Some(hdr_dst) = bytes.get_mut(block_off..block_off + header_len) else {
panic!("data header within the file");
};
hdr_dst.copy_from_slice(&hdr_bytes);
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_section_block_role(
path: &std::path::Path,
section: &[u8],
forged: crate::table::block::BlockType,
) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::Header;
let mut bytes = std::fs::read(path)?;
let block_off = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == section) else {
panic!("the SST must carry the targeted section");
};
usize::try_from(entry.pos()).expect("section offset fits usize")
};
let Some(block) = bytes.get(block_off..) else {
panic!("section block within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
assert_eq!(
header_len,
Header::header_len(forged),
"the forged role must keep the header length so the relabel is in place",
);
let new_header = Header {
block_type: forged,
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
let Some(hdr_dst) = bytes.get_mut(block_off..block_off + header_len) else {
panic!("section header within the file");
};
hdr_dst.copy_from_slice(&hdr_bytes);
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_flip_section_last_payload_byte(
path: &std::path::Path,
section: &[u8],
shards: Option<(u8, u8)>,
) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::Header;
let mut bytes = std::fs::read(path)?;
let (pos, section_len) = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == section) else {
panic!("the SST must carry the targeted section");
};
(entry.pos(), entry.len())
};
let block_off = usize::try_from(pos).expect("section offset fits usize");
let Some(block) = bytes.get(block_off..) else {
panic!("section block within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
let payload_range =
block_off + header_len..block_off + header_len + header.data_length as usize;
{
let Some(payload) = bytes.get_mut(payload_range.clone()) else {
panic!("section payload within the file");
};
let last = payload.len() - 1;
let Some(slot) = payload.get_mut(last) else {
panic!("payload is non-empty");
};
*slot ^= 0xFF;
}
let Some(payload) = bytes.get(payload_range.clone()) else {
panic!("section payload within the file");
};
let new_checksum = crate::Checksum::from_raw(crate::hash::hash128(payload));
let new_header = Header {
checksum: new_checksum,
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
let Some(hdr_dst) = bytes.get_mut(block_off..block_off + header_len) else {
panic!("section header within the file");
};
hdr_dst.copy_from_slice(&hdr_bytes);
#[cfg(feature = "page_ecc")]
if let Some((data_shards, parity_shards)) = shards {
let payload_end = payload_range.end;
let Ok(section_len) = usize::try_from(section_len) else {
panic!("section length fits usize");
};
let frame_end = block_off + section_len;
if frame_end > payload_end {
let Some(payload) = bytes.get(payload_range) else {
panic!("section payload within the file");
};
let parity =
crate::ecc::encode_parity(payload, data_shards.into(), parity_shards.into())?;
assert_eq!(
frame_end - payload_end,
parity.len(),
"the frame's trailer length matches the descriptor scheme",
);
let Some(dst) = bytes.get_mut(payload_end..frame_end) else {
panic!("parity trailer within the file");
};
dst.copy_from_slice(&parity);
}
}
#[cfg(not(feature = "page_ecc"))]
let _ = (section_len, shards);
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_replace_section_payload(
path: &std::path::Path,
section: &[u8],
new_payload: &[u8],
shards: Option<(u8, u8)>,
) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::Header;
let mut bytes = std::fs::read(path)?;
let (pos, section_len) = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == section) else {
panic!("the SST must carry the targeted section");
};
(entry.pos(), entry.len())
};
let block_off = usize::try_from(pos).expect("section offset fits usize");
let Some(block) = bytes.get(block_off..) else {
panic!("section block within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
let payload_range =
block_off + header_len..block_off + header_len + header.data_length as usize;
assert_eq!(
payload_range.len(),
new_payload.len(),
"the replacement payload must keep the frame geometry",
);
{
let Some(dst) = bytes.get_mut(payload_range.clone()) else {
panic!("section payload within the file");
};
dst.copy_from_slice(new_payload);
}
let new_checksum = crate::Checksum::from_raw(crate::hash::hash128(new_payload));
let new_header = Header {
checksum: new_checksum,
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
let Some(hdr_dst) = bytes.get_mut(block_off..block_off + header_len) else {
panic!("section header within the file");
};
hdr_dst.copy_from_slice(&hdr_bytes);
#[cfg(feature = "page_ecc")]
if let Some((data_shards, parity_shards)) = shards {
let payload_end = payload_range.end;
let Ok(section_len) = usize::try_from(section_len) else {
panic!("section length fits usize");
};
let frame_end = block_off + section_len;
if frame_end > payload_end {
let parity =
crate::ecc::encode_parity(new_payload, data_shards.into(), parity_shards.into())?;
assert_eq!(
frame_end - payload_end,
parity.len(),
"the frame's trailer length matches the descriptor scheme",
);
let Some(dst) = bytes.get_mut(payload_end..frame_end) else {
panic!("parity trailer within the file");
};
dst.copy_from_slice(&parity);
}
}
#[cfg(not(feature = "page_ecc"))]
let _ = (section_len, shards);
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_value_byte_in_first_data_block(
path: &std::path::Path,
shards: Option<(u8, u8)>,
) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::{Header, ParsedItem as _};
let mut bytes = std::fs::read(path)?;
let block_off = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == b"data") else {
panic!("the SST must carry a data section");
};
usize::try_from(entry.pos()).expect("data offset fits usize")
};
let Some(block) = bytes.get(block_off..) else {
panic!("data block within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
let payload_range =
block_off + header_len..block_off + header_len + header.data_length as usize;
let Some(payload) = bytes.get(payload_range.clone()) else {
panic!("data payload within the file");
};
let decode = |payload: &[u8]| -> Option<alloc::vec::Vec<crate::InternalValue>> {
let block = crate::table::Block {
header: Header {
checksum: crate::Checksum::from_raw(crate::hash::hash128(payload)),
..header
},
data: crate::Slice::from(payload.to_vec()),
};
let data_block = crate::table::DataBlock::from_loaded(block, false).ok()?;
let data = data_block.inner.data.clone();
let iter = data_block
.try_iter(crate::comparator::default_comparator())
.ok()?;
Some(iter.map(|p| p.materialize(&data)).collect())
};
let Some(baseline) = decode(payload) else {
panic!("the healthy first data block decodes");
};
let mut candidate = payload.to_vec();
let flipped_at = (0..candidate.len()).find(|&i| {
let Some(slot) = candidate.get_mut(i) else {
return false;
};
*slot ^= 0xFF;
let ok = decode(&candidate).is_some_and(|entries| {
entries.len() == baseline.len()
&& entries
.iter()
.zip(&baseline)
.all(|(a, b)| a.key == b.key && a.value.len() == b.value.len())
&& entries
.iter()
.zip(&baseline)
.any(|(a, b)| a.value != b.value)
});
if !ok {
let Some(slot) = candidate.get_mut(i) else {
return false;
};
*slot ^= 0xFF;
}
ok
});
assert!(
flipped_at.is_some(),
"some payload byte flip must alter only a value while the block stays decodable",
);
{
let Some(dst) = bytes.get_mut(payload_range.clone()) else {
panic!("data payload within the file");
};
dst.copy_from_slice(&candidate);
}
let new_checksum = crate::Checksum::from_raw(crate::hash::hash128(&candidate));
let new_header = Header {
checksum: new_checksum,
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
let Some(hdr_dst) = bytes.get_mut(block_off..block_off + header_len) else {
panic!("data header within the file");
};
hdr_dst.copy_from_slice(&hdr_bytes);
#[cfg(feature = "page_ecc")]
if let Some((data_shards, parity_shards)) = shards {
let payload_end = payload_range.end;
let parity =
crate::ecc::encode_parity(&candidate, data_shards.into(), parity_shards.into())?;
let Some(dst) = bytes.get_mut(payload_end..payload_end + parity.len()) else {
panic!("parity trailer within the file");
};
dst.copy_from_slice(&parity);
}
#[cfg(not(feature = "page_ecc"))]
let _ = shards;
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_block_layout_shift_middle_end(
path: &std::path::Path,
shards: Option<(u8, u8)>,
) -> crate::Result<()> {
use crate::coding::Decode;
use crate::table::block::Header;
let bytes = std::fs::read(path)?;
let pos = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == b"block_layout") else {
panic!("the SST must carry a block_layout section");
};
entry.pos()
};
let block_off = usize::try_from(pos).expect("section offset fits usize");
let Some(block) = bytes.get(block_off..) else {
panic!("section block within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
let Some(payload) =
bytes.get(block_off + header_len..block_off + header_len + header.data_length as usize)
else {
panic!("section payload within the file");
};
let read_u32 = |at: usize| {
u32::from_le_bytes(
payload
.get(at..at + 4)
.expect("u32 within the payload")
.try_into()
.expect("4 bytes"),
)
};
assert!(read_u32(0) >= 1, "the map records at least one block");
let inner = read_u32(12) as usize;
assert!(inner >= 2, "a recorded block has at least two inner blocks");
let target_at = 16 + (inner - 2) * 4;
let prev = if inner >= 3 {
read_u32(target_at - 4)
} else {
0
};
let current = read_u32(target_at);
assert!(
current > prev + 1,
"the target boundary must leave room for a shifted midpoint",
);
let shifted = prev + (current - prev) / 2;
let mut candidate = payload.to_vec();
let Some(dst) = candidate.get_mut(target_at..target_at + 4) else {
panic!("target end within the payload");
};
dst.copy_from_slice(&shifted.to_le_bytes());
forge_replace_section_payload(path, b"block_layout", &candidate, shards)
}
pub fn forge_hash_index_all_free(
path: &std::path::Path,
shards: Option<(u8, u8)>,
) -> crate::Result<()> {
use crate::table::block::hash_index::MARKER_FREE;
patch_first_data_block_hash_index(path, shards, |region| region.fill(MARKER_FREE))
}
pub fn forge_hash_index_bucket(
path: &std::path::Path,
key: &[u8],
binary_index_pos: u8,
shards: Option<(u8, u8)>,
) -> crate::Result<()> {
use crate::table::block::hash_index::MARKER_CONFLICT;
patch_first_data_block_hash_index(path, shards, |region| {
#[expect(
clippy::cast_possible_truncation,
reason = "hash % region.len() < region.len() <= usize::MAX"
)]
let bucket = (crate::hash::hash64(key) % region.len() as u64) as usize;
let Some(slot) = region.get_mut(bucket) else {
panic!("bucket within the hash index");
};
assert_eq!(
*slot, MARKER_CONFLICT,
"the target key's bucket must be a conflict marker (spans restart intervals)",
);
*slot = binary_index_pos;
})
}
fn patch_first_data_block_hash_index(
path: &std::path::Path,
shards: Option<(u8, u8)>,
patch: impl FnOnce(&mut [u8]),
) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::{Block, Header};
use crate::table::{DataBlock, block::BlockType};
let mut bytes = std::fs::read(path)?;
let block_off = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == b"data") else {
panic!("the SST must carry a data section");
};
usize::try_from(entry.pos()).expect("data offset fits usize")
};
let Some(block) = bytes.get(block_off..) else {
panic!("data block within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
let payload_range =
block_off + header_len..block_off + header_len + header.data_length as usize;
let Some(payload) = bytes.get(payload_range.clone()) else {
panic!("data payload within the file");
};
let (hi_offset, hi_len) = {
let loaded = Block {
header: Header {
block_type: BlockType::Data,
..header
},
data: crate::Slice::from(payload.to_vec()),
};
let data_block = DataBlock::from_loaded(loaded, true)?;
data_block
.hash_index_span()
.expect("the block must carry a hash index")
};
{
let start = payload_range.start + hi_offset;
let Some(region) = bytes.get_mut(start..start + hi_len) else {
panic!("hash index within the payload");
};
patch(region);
}
let Some(payload) = bytes.get(payload_range.clone()) else {
panic!("data payload within the file");
};
let new_checksum = crate::Checksum::from_raw(crate::hash::hash128(payload));
let new_header = Header {
checksum: new_checksum,
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
let Some(hdr_dst) = bytes.get_mut(block_off..block_off + header_len) else {
panic!("data header within the file");
};
hdr_dst.copy_from_slice(&hdr_bytes);
#[cfg(feature = "page_ecc")]
if let Some((data_shards, parity_shards)) = shards {
let payload_end = payload_range.end;
let parity = crate::ecc::encode_parity(
bytes.get(payload_range).expect("payload"),
data_shards.into(),
parity_shards.into(),
)?;
let Some(dst) = bytes.get_mut(payload_end..payload_end + parity.len()) else {
panic!("parity trailer within the file");
};
dst.copy_from_slice(&parity);
}
#[cfg(not(feature = "page_ecc"))]
let _ = shards;
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_filter_false_negative(
path: &std::path::Path,
target_hash: u64,
shards: Option<(u8, u8)>,
) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::Header;
use crate::table::filter::ribbon::burr::contains_hash_from_bytes;
let mut bytes = std::fs::read(path)?;
let (pos, section_len) = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == b"filter") else {
panic!("the SST must carry a filter section");
};
(entry.pos(), entry.len())
};
let block_off = usize::try_from(pos).expect("section offset fits usize");
let Some(block) = bytes.get(block_off..) else {
panic!("section block within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
let payload_range =
block_off + header_len..block_off + header_len + header.data_length as usize;
let Some(payload) = bytes.get(payload_range.clone()) else {
panic!("section payload within the file");
};
assert!(
matches!(contains_hash_from_bytes(payload, target_hash), Ok(true)),
"the target key must be present in the healthy filter",
);
let mut candidate = payload.to_vec();
let flipped_at = (0..candidate.len()).find(|&i| {
let Some(slot) = candidate.get_mut(i) else {
return false;
};
*slot ^= 0xFF;
let miss = matches!(contains_hash_from_bytes(&candidate, target_hash), Ok(false));
if !miss {
let Some(slot) = candidate.get_mut(i) else {
return false;
};
*slot ^= 0xFF;
}
miss
});
assert!(
flipped_at.is_some(),
"some payload byte flip must produce a parseable false-negative filter",
);
{
let Some(dst) = bytes.get_mut(payload_range.clone()) else {
panic!("section payload within the file");
};
dst.copy_from_slice(&candidate);
}
let new_checksum = crate::Checksum::from_raw(crate::hash::hash128(&candidate));
let new_header = Header {
checksum: new_checksum,
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
let Some(hdr_dst) = bytes.get_mut(block_off..block_off + header_len) else {
panic!("section header within the file");
};
hdr_dst.copy_from_slice(&hdr_bytes);
#[cfg(feature = "page_ecc")]
if let Some((data_shards, parity_shards)) = shards {
let payload_end = payload_range.end;
let parity =
crate::ecc::encode_parity(&candidate, data_shards.into(), parity_shards.into())?;
let Ok(section_len) = usize::try_from(section_len) else {
panic!("section length fits usize");
};
assert!(
payload_end + parity.len() <= block_off + section_len,
"the parity trailer stays within the section",
);
let Some(dst) = bytes.get_mut(payload_end..payload_end + parity.len()) else {
panic!("parity trailer within the file");
};
dst.copy_from_slice(&parity);
}
#[cfg(not(feature = "page_ecc"))]
let _ = (section_len, shards);
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_seqno_bounds_zeroed_entry(
path: &std::path::Path,
shards: Option<(u8, u8)>,
) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::Header;
let mut bytes = std::fs::read(path)?;
let (pos, section_len) = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == b"seqno_bounds") else {
panic!("the SST must carry a seqno_bounds section");
};
(entry.pos(), entry.len())
};
let block_off = usize::try_from(pos).expect("section offset fits usize");
let Some(block) = bytes.get(block_off..) else {
panic!("seqno_bounds block within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
let payload_range =
block_off + header_len..block_off + header_len + header.data_length as usize;
{
let Some(payload) = bytes.get_mut(payload_range.clone()) else {
panic!("seqno_bounds payload within the file");
};
let count = u32::from_le_bytes(
payload
.get(..4)
.expect("count prefix")
.try_into()
.expect("4 bytes"),
) as usize;
assert!(count >= 1, "the map records at least one block");
let min_at = 4 + (count - 1) * 24 + 8;
let Some(minmax) = payload.get_mut(min_at..min_at + 16) else {
panic!("last entry's bounds within the payload");
};
minmax.fill(0);
}
let Some(payload) = bytes.get(payload_range.clone()) else {
panic!("seqno_bounds payload within the file");
};
let new_checksum = crate::Checksum::from_raw(crate::hash::hash128(payload));
let new_header = Header {
checksum: new_checksum,
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
let Some(hdr_dst) = bytes.get_mut(block_off..block_off + header_len) else {
panic!("seqno_bounds header within the file");
};
hdr_dst.copy_from_slice(&hdr_bytes);
#[cfg(feature = "page_ecc")]
if let Some((data_shards, parity_shards)) = shards {
let payload_end = payload_range.end;
let Ok(section_len) = usize::try_from(section_len) else {
panic!("section length fits usize");
};
let frame_end = block_off + section_len;
if frame_end > payload_end {
let Some(payload) = bytes.get(payload_range) else {
panic!("seqno_bounds payload within the file");
};
let parity =
crate::ecc::encode_parity(payload, data_shards.into(), parity_shards.into())?;
assert_eq!(
frame_end - payload_end,
parity.len(),
"the frame's trailer length matches the descriptor scheme",
);
let Some(dst) = bytes.get_mut(payload_end..frame_end) else {
panic!("parity trailer within the file");
};
dst.copy_from_slice(&parity);
}
}
#[cfg(not(feature = "page_ecc"))]
let _ = (section_len, shards);
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_seqno_bounds_empty(
path: &std::path::Path,
table_id: crate::TableId,
) -> crate::Result<()> {
use crate::table::block::{Block, BlockIdentity, BlockTransform, BlockType};
let mut payload = Vec::new();
crate::table::seqno_bounds::encode_seqno_bounds(&mut payload, &[])?;
let identity = BlockIdentity {
table_id,
block_type: BlockType::SeqnoBounds,
dict_id: 0,
window_log: 0,
};
let mut forged = Vec::new();
Block::write_into(&mut forged, &payload, identity, &BlockTransform::PLAIN)?;
replace_section_frame(path, b"seqno_bounds", &forged)
}
pub fn forge_block_layout_empty(
path: &std::path::Path,
table_id: crate::TableId,
encryption: Option<&dyn crate::encryption::EncryptionProvider>,
) -> crate::Result<()> {
use crate::table::block::{Block, BlockIdentity, BlockTransform, BlockType};
let mut payload = Vec::new();
crate::table::block_layout::encode_block_layouts(&mut payload, &[]);
let identity = BlockIdentity {
table_id,
block_type: BlockType::BlockLayout,
dict_id: 0,
window_log: 0,
};
let transform = match encryption {
Some(enc) => BlockTransform::Encrypted(enc),
None => BlockTransform::PLAIN,
};
let mut forged = Vec::new();
Block::write_into(&mut forged, &payload, identity, &transform)?;
replace_section_frame(path, b"block_layout", &forged)
}
#[cfg(feature = "zstd")]
pub fn forge_block_layout_shifted_end(
path: &std::path::Path,
table_id: crate::TableId,
) -> crate::Result<()> {
use crate::table::block::{Block, BlockIdentity, BlockTransform, BlockType};
use crate::table::block_layout::BlockLayoutMap;
let map = {
let mut file = std::fs::File::open(path)?;
let reader = crate::sfa::Reader::from_reader(&mut file)?;
let entry = reader
.toc()
.iter()
.find(|e| e.name() == b"block_layout")
.ok_or(crate::Error::InvalidHeader("no block_layout section"))?;
let handle = crate::table::BlockHandle::new(
crate::table::BlockOffset(entry.pos()),
u32::try_from(entry.len()).map_err(|_| crate::Error::InvalidHeader("block_layout"))?,
);
let fs = crate::fs::StdFs;
let f = crate::fs::Fs::open(&fs, path, &crate::fs::FsOpenOptions::new().read(true))?;
let block = Block::from_file(
f.as_ref(),
handle,
BlockIdentity {
table_id,
block_type: BlockType::BlockLayout,
dict_id: 0,
window_log: 0,
},
&BlockTransform::PLAIN,
)?;
BlockLayoutMap::decode(&block.data)?
};
let mut layouts: Vec<(crate::table::BlockOffset, Vec<u32>)> = map
.offsets()
.into_iter()
.map(|offset| {
let ends = map.ends_for(offset).unwrap_or_default().to_vec();
(crate::table::BlockOffset(offset), ends)
})
.collect();
let first = layouts
.first_mut()
.ok_or(crate::Error::InvalidHeader("empty block_layout"))?;
if first.1.len() < 3 {
return Err(crate::Error::InvalidHeader(
"block_layout entry has no interior boundary to move",
));
}
let interior = first
.1
.get_mut(0)
.ok_or(crate::Error::InvalidHeader("block_layout entry is empty"))?;
*interior = interior
.checked_sub(1)
.ok_or(crate::Error::InvalidHeader("boundary at zero"))?;
let mut payload = Vec::new();
crate::table::block_layout::encode_block_layouts(&mut payload, &layouts);
let mut forged = Vec::new();
Block::write_into(
&mut forged,
&payload,
BlockIdentity {
table_id,
block_type: BlockType::BlockLayout,
dict_id: 0,
window_log: 0,
},
&BlockTransform::PLAIN,
)?;
replace_section_frame(path, b"block_layout", &forged)
}
pub fn forge_zone_map_empty(path: &std::path::Path, table_id: crate::TableId) -> crate::Result<()> {
use crate::table::block::{Block, BlockIdentity, BlockTransform, BlockType};
let mut payload = Vec::new();
crate::table::zone_map::encode_zone_map(&mut payload, &[])?;
let identity = BlockIdentity {
table_id,
block_type: BlockType::ZoneMap,
dict_id: 0,
window_log: 0,
};
let mut forged = Vec::new();
Block::write_into(&mut forged, &payload, identity, &BlockTransform::PLAIN)?;
replace_section_frame(path, b"zone_map", &forged)
}
pub fn forge_delete_bitmap_empty(
path: &std::path::Path,
table_id: crate::TableId,
) -> crate::Result<()> {
use crate::table::block::{Block, BlockIdentity, BlockTransform, BlockType};
let payload = crate::table::delete_bitmap::DeleteBitmap::new().encode();
let identity = BlockIdentity {
table_id,
block_type: BlockType::DeleteBitmap,
dict_id: 0,
window_log: 0,
};
let mut forged = Vec::new();
Block::write_into(&mut forged, &payload, identity, &BlockTransform::PLAIN)?;
replace_section_frame(path, b"delete_bitmap", &forged)
}
pub fn forge_delete_bitmap_substitute(
path: &std::path::Path,
table_id: crate::TableId,
positions: &[u32],
) -> crate::Result<()> {
use crate::table::block::{Block, BlockIdentity, BlockTransform, BlockType};
let mut bitmap = crate::table::delete_bitmap::DeleteBitmap::new();
for &pos in positions {
bitmap.insert(pos);
}
let payload = bitmap.encode();
let identity = BlockIdentity {
table_id,
block_type: BlockType::DeleteBitmap,
dict_id: 0,
window_log: 0,
};
let mut forged = Vec::new();
Block::write_into(&mut forged, &payload, identity, &BlockTransform::PLAIN)?;
replace_section_frame(path, b"delete_bitmap", &forged)
}
pub fn forge_filter_empty(path: &std::path::Path, table_id: crate::TableId) -> crate::Result<()> {
use crate::table::block::{Block, BlockIdentity, BlockTransform, BlockType};
let identity = BlockIdentity {
table_id,
block_type: BlockType::Filter,
dict_id: 0,
window_log: 0,
};
let mut forged = Vec::new();
Block::write_into(&mut forged, &[], identity, &BlockTransform::PLAIN)?;
replace_section_frame(path, b"filter", &forged)
}
pub fn forge_filter_first_partition_empty(path: &std::path::Path) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::Header;
let mut bytes = std::fs::read(path)?;
let pos = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == b"filter") else {
panic!("the SST must carry a filter section");
};
entry.pos()
};
let block_off = usize::try_from(pos).expect("section offset fits usize");
let Some(block) = bytes.get(block_off..) else {
panic!("filter partition block within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
let new_header = Header {
data_length: 0,
uncompressed_length: 0,
checksum: crate::Checksum::from_raw(crate::hash::hash128(&[])),
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
let Some(hdr_dst) = bytes.get_mut(block_off..block_off + header_len) else {
panic!("filter partition header within the file");
};
hdr_dst.copy_from_slice(&hdr_bytes);
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_data_block_oversized_header(
path: &std::path::Path,
block_off: u64,
forged_end_off: u64,
) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::Header;
let mut bytes = std::fs::read(path)?;
let at = usize::try_from(block_off).expect("block offset fits usize");
let end = usize::try_from(forged_end_off).expect("forged end offset fits usize");
let Some(block) = bytes.get(at..) else {
panic!("the data block header at {at} lies within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
let forged_len = end
.checked_sub(at + header_len)
.expect("forged end offset lies past the block header");
let forged_data_length = u32::try_from(forged_len).expect("forged data_length fits u32");
let new_header = Header {
data_length: forged_data_length,
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
let Some(hdr_dst) = bytes.get_mut(at..at + header_len) else {
panic!("the data block header at {at} lies within the file");
};
hdr_dst.copy_from_slice(&hdr_bytes);
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_tli_tail_truncated(
path: &std::path::Path,
table_id: crate::TableId,
ecc: Option<crate::table::block::EccParams>,
) -> crate::Result<()> {
let forged = truncated_tli_frame(path, table_id, ecc)?;
replace_section_frame(path, b"tli_tail", &forged)
}
pub fn forge_tli_mirrors_truncated(
path: &std::path::Path,
table_id: crate::TableId,
ecc: Option<crate::table::block::EccParams>,
) -> crate::Result<()> {
let forged = truncated_tli_frame(path, table_id, ecc)?;
replace_section_frame(path, b"tli", &forged)?;
replace_section_frame(path, b"tli_tail", &forged)
}
pub fn forge_tli_mirrors_lower_first_separator(
path: &std::path::Path,
table_id: crate::TableId,
ecc: Option<crate::table::block::EccParams>,
) -> crate::Result<()> {
let forged = rebuilt_tli_frame(path, table_id, ecc, |handles| {
use crate::table::KeyedBlockHandle;
let first = handles.first().expect("at least two handles");
let key = first.end_key().as_ref();
assert!(key.len() >= 2, "separator key long enough to truncate");
let lowered = crate::UserKey::from(key.get(..key.len() - 1).expect("prefix"));
let rebuilt = KeyedBlockHandle::new(lowered, first.seqno(), *first.as_ref());
if let Some(slot) = handles.get_mut(0) {
*slot = rebuilt;
}
})?;
replace_section_frame(path, b"tli", &forged)?;
replace_section_frame(path, b"tli_tail", &forged)
}
pub fn forge_tli_binary_index_pointer(
path: &std::path::Path,
table_id: crate::TableId,
ecc: Option<crate::table::block::EccParams>,
) -> crate::Result<()> {
use crate::table::block::Block;
let (identity, transform, index) = tli_forge_frame(path, table_id, ecc)?;
let (mut payload, bi_offset, bi_len, step) = {
let meta = index.decoder_meta().expect("tli trailer parses");
(
index.as_slice().to_vec(),
usize::try_from(meta.binary_index_offset()).expect("offset fits usize"),
usize::try_from(meta.binary_index_len()).expect("len fits usize"),
usize::from(meta.binary_index_step_size()),
)
};
assert!(
bi_len >= 2,
"the forge needs at least two pointers so first != last",
);
let first: Vec<u8> = payload
.get(bi_offset..bi_offset + step)
.expect("first pointer within the payload")
.to_vec();
let last_at = bi_offset + (bi_len - 1) * step;
payload
.get_mut(last_at..last_at + step)
.expect("last pointer within the payload")
.copy_from_slice(&first);
let mut forged = Vec::new();
Block::write_into(&mut forged, &payload, identity, &transform)?;
replace_section_frame(path, b"tli", &forged)?;
replace_section_frame(path, b"tli_tail", &forged)
}
pub fn forge_locator_slots(
path: &std::path::Path,
table_id: crate::TableId,
entries: &[(u64, u64, u64)],
) -> crate::Result<()> {
use crate::table::block::{Block, BlockIdentity, BlockType};
let spec = crate::table::locator::LocatorSpec {
precision: crate::config::LocatorPrecision::Restart,
block_id_bits: None,
slot_bits: None,
};
let Some(section) = crate::table::locator::build_locator_section(entries, spec) else {
panic!("the forged locator entries must build a section");
};
let identity = BlockIdentity {
table_id,
block_type: BlockType::Locator,
dict_id: 0,
window_log: 0,
};
let transform = crate::table::block::BlockTransform::PLAIN;
let mut forged = Vec::new();
Block::write_into(&mut forged, §ion, identity, &transform)?;
replace_section_frame(path, b"locator", &forged)
}
pub fn forge_zone_map_drop_last_entry(
path: &std::path::Path,
table_id: crate::TableId,
) -> crate::Result<()> {
use crate::table::block::{Block, BlockIdentity, BlockType};
use crate::table::{BlockHandle, BlockOffset};
let identity = BlockIdentity {
table_id,
block_type: BlockType::ZoneMap,
dict_id: 0,
window_log: 0,
};
let transform = crate::table::block::BlockTransform::from_parts(
crate::CompressionType::None,
None,
#[cfg(zstd_any)]
None,
)?;
let (pos, len) = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == b"zone_map") else {
panic!("the SST must carry a zone_map section");
};
(
usize::try_from(entry.pos()).expect("pos fits usize"),
usize::try_from(entry.len()).expect("len fits usize"),
)
};
let blocks: Vec<(BlockOffset, Vec<crate::table::zone_map::ColumnStats>)> = {
let file = crate::fs::Fs::open(
&crate::fs::StdFs,
path,
&crate::fs::FsOpenOptions::new().read(true),
)?;
let block = Block::from_file(
&*file,
BlockHandle::new(
BlockOffset(u64::try_from(pos).expect("pos fits u64")),
u32::try_from(len).expect("section fits u32"),
),
identity,
&transform,
)?;
let map = crate::table::zone_map::ZoneMap::decode(&block.data)?;
let entries = map.entries();
assert!(
entries.len() >= 2,
"dropping the last entry must leave a non-empty map",
);
entries
.get(..entries.len() - 1)
.expect("all but the last entry")
.iter()
.map(|(off, cols)| (BlockOffset(*off), cols.clone()))
.collect()
};
let mut payload = Vec::new();
crate::table::zone_map::encode_zone_map(&mut payload, &blocks)?;
let mut forged = Vec::new();
Block::write_into(&mut forged, &payload, identity, &transform)?;
replace_section_frame(path, b"zone_map", &forged)
}
pub fn forge_zone_map_column_id(
path: &std::path::Path,
table_id: crate::TableId,
) -> crate::Result<()> {
use crate::table::block::{Block, BlockIdentity, BlockType};
use crate::table::{BlockHandle, BlockOffset};
let identity = BlockIdentity {
table_id,
block_type: BlockType::ZoneMap,
dict_id: 0,
window_log: 0,
};
let transform = crate::table::block::BlockTransform::from_parts(
crate::CompressionType::None,
None,
#[cfg(zstd_any)]
None,
)?;
let (pos, len) = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == b"zone_map") else {
panic!("the SST must carry a zone_map section");
};
(
usize::try_from(entry.pos()).expect("pos fits usize"),
usize::try_from(entry.len()).expect("len fits usize"),
)
};
let mut blocks: Vec<(BlockOffset, Vec<crate::table::zone_map::ColumnStats>)> = {
let file = crate::fs::Fs::open(
&crate::fs::StdFs,
path,
&crate::fs::FsOpenOptions::new().read(true),
)?;
let block = Block::from_file(
&*file,
BlockHandle::new(
BlockOffset(u64::try_from(pos).expect("pos fits u64")),
u32::try_from(len).expect("section fits u32"),
),
identity,
&transform,
)?;
let map = crate::table::zone_map::ZoneMap::decode(&block.data)?;
map.entries()
.iter()
.map(|(off, cols)| (BlockOffset(*off), cols.clone()))
.collect()
};
let Some((_off, cols)) = blocks.first_mut() else {
panic!("the zone_map carries at least one block entry");
};
let Some(col) = cols.first_mut() else {
panic!("the block entry carries its synthetic column");
};
assert_eq!(
col.column_id, 0,
"the writer stamps a zero synthetic column id",
);
col.column_id = 7;
let mut payload = Vec::new();
crate::table::zone_map::encode_zone_map(&mut payload, &blocks)?;
let mut forged = Vec::new();
Block::write_into(&mut forged, &payload, identity, &transform)?;
replace_section_frame(path, b"zone_map", &forged)
}
fn tli_forge_frame(
path: &std::path::Path,
table_id: crate::TableId,
ecc: Option<crate::table::block::EccParams>,
) -> crate::Result<(
crate::table::block::BlockIdentity,
crate::table::block::BlockTransform<'static>,
crate::table::IndexBlock,
)> {
use crate::table::block::{Block, BlockIdentity, BlockType};
use crate::table::{BlockHandle, BlockOffset, IndexBlock};
let identity = BlockIdentity {
table_id,
block_type: BlockType::Index,
dict_id: 0,
window_log: 0,
};
let transform = {
let t = crate::table::block::BlockTransform::from_parts(
crate::CompressionType::None,
None,
#[cfg(zstd_any)]
None,
)?;
if let Some(ecc) = ecc {
t.with_ecc(ecc)
} else {
t
}
};
let (tail_pos, tail_len) = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == b"tli_tail") else {
panic!("the SST must carry a tli_tail mirror");
};
(
usize::try_from(entry.pos()).expect("pos fits usize"),
usize::try_from(entry.len()).expect("len fits usize"),
)
};
let file = crate::fs::Fs::open(
&crate::fs::StdFs,
path,
&crate::fs::FsOpenOptions::new().read(true),
)?;
let block = Block::from_file(
&*file,
BlockHandle::new(
BlockOffset(u64::try_from(tail_pos).expect("pos fits u64")),
u32::try_from(tail_len).expect("tail section fits u32"),
),
identity,
&transform,
)?;
Ok((identity, transform, IndexBlock::new(block)))
}
pub fn forge_tli_mirrors_drop_interior(
path: &std::path::Path,
table_id: crate::TableId,
ecc: Option<crate::table::block::EccParams>,
) -> crate::Result<()> {
let forged = rebuilt_tli_frame(path, table_id, ecc, |handles| {
assert!(
handles.len() >= 3,
"an interior drop needs a handle strictly between two neighbours",
);
handles.remove(handles.len() / 2);
})?;
replace_section_frame(path, b"tli", &forged)?;
replace_section_frame(path, b"tli_tail", &forged)
}
pub fn forge_tli_mirrors_span_single_handle(
path: &std::path::Path,
table_id: crate::TableId,
) -> crate::Result<()> {
let forged = rebuilt_tli_frame(path, table_id, None, |handles| {
use crate::table::{BlockHandle, KeyedBlockHandle};
assert!(
handles.len() >= 2,
"spanning a single handle needs at least two handles to hide",
);
let total: u32 = handles.iter().map(|h| h.as_ref().size()).sum();
let Some(first) = handles.first() else {
panic!("the source carries data blocks");
};
let spanning = KeyedBlockHandle::new(
first.end_key().clone(),
first.seqno(),
BlockHandle::new(first.as_ref().offset(), total),
);
*handles = vec![spanning];
})?;
replace_section_frame(path, b"tli", &forged)?;
replace_section_frame(path, b"tli_tail", &forged)
}
pub fn forge_tli_mirrors_offset_beyond_section(
path: &std::path::Path,
table_id: crate::TableId,
) -> crate::Result<()> {
let forged = rebuilt_tli_frame(path, table_id, None, |handles| {
use crate::table::{BlockHandle, KeyedBlockHandle};
let Some(last) = handles.last().cloned() else {
panic!("the source carries data blocks");
};
let beyond = KeyedBlockHandle::new(
last.end_key().clone(),
last.seqno(),
BlockHandle::new(
crate::table::block::BlockOffset(u64::MAX / 2),
last.as_ref().size(),
),
);
handles.push(beyond);
})?;
replace_section_frame(path, b"tli", &forged)?;
replace_section_frame(path, b"tli_tail", &forged)
}
pub fn forge_tli_mirrors_swap_first_two(
path: &std::path::Path,
table_id: crate::TableId,
ecc: Option<crate::table::block::EccParams>,
) -> crate::Result<()> {
let forged = rebuilt_tli_frame(path, table_id, ecc, |handles| {
handles.swap(0, 1);
})?;
replace_section_frame(path, b"tli", &forged)?;
replace_section_frame(path, b"tli_tail", &forged)
}
fn truncated_tli_frame(
path: &std::path::Path,
table_id: crate::TableId,
ecc: Option<crate::table::block::EccParams>,
) -> crate::Result<Vec<u8>> {
rebuilt_tli_frame(path, table_id, ecc, |handles| {
handles.pop();
})
}
fn rebuilt_tli_frame(
path: &std::path::Path,
table_id: crate::TableId,
ecc: Option<crate::table::block::EccParams>,
mutate: impl FnOnce(&mut Vec<crate::table::KeyedBlockHandle>),
) -> crate::Result<Vec<u8>> {
use crate::table::block::Block;
use crate::table::{IndexBlock, KeyedBlockHandle};
let (identity, transform, index) = tli_forge_frame(path, table_id, ecc)?;
let mut handles: Vec<KeyedBlockHandle> = {
use crate::table::block::ParsedItem as _;
let mut out = Vec::new();
for item in index.iter(crate::comparator::default_comparator()) {
out.push(item.materialize(index.as_slice()));
}
out
};
assert!(
handles.len() >= 2,
"the forge needs at least two handles so the mutation leaves a valid index",
);
mutate(&mut handles);
let payload = IndexBlock::encode_into_vec(&handles)?;
let mut forged = Vec::new();
Block::write_into(&mut forged, &payload, identity, &transform)?;
Ok(forged)
}
fn replace_section_frame(
path: &std::path::Path,
section: &[u8],
forged: &[u8],
) -> crate::Result<()> {
let bytes = std::fs::read(path)?;
const TRAILER_SIZE: usize = 4 + 1 + 1 + 16 + 8 + 8;
let trailer_start = bytes.len() - TRAILER_SIZE;
let read_u64 = |bytes: &[u8], at: usize| {
let Some(b) = bytes.get(at..at + 8) else {
panic!("u64 field within the trailer");
};
u64::from_le_bytes(b.try_into().expect("8 bytes"))
};
let toc_pos = usize::try_from(read_u64(&bytes, trailer_start + 4 + 1 + 1 + 16))
.expect("toc_pos fits usize");
let (section_pos, section_len) = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == section) else {
panic!("the SST must carry the section to replace");
};
(
usize::try_from(entry.pos()).expect("pos fits usize"),
usize::try_from(entry.len()).expect("len fits usize"),
)
};
let delta = i64::try_from(forged.len()).expect("forged block fits i64")
- i64::try_from(section_len).expect("section fits i64");
let mut out = Vec::with_capacity(bytes.len());
out.extend_from_slice(bytes.get(..section_pos).expect("pre-section prefix"));
out.extend_from_slice(forged);
out.extend_from_slice(
bytes
.get(section_pos + section_len..toc_pos)
.expect("post-section sections"),
);
let new_toc_pos = out.len();
let toc_len = usize::try_from(read_u64(&bytes, trailer_start + 4 + 1 + 1 + 16 + 8))
.expect("toc_len fits usize");
let toc = bytes.get(toc_pos..toc_pos + toc_len).expect("TOC region");
assert_eq!(toc.get(..4), Some(&b"TOC!"[..]), "TOC magic");
let count = u32::from_le_bytes(toc.get(4..8).expect("count").try_into().expect("4 bytes"));
let mut new_toc = Vec::with_capacity(toc.len());
new_toc.extend_from_slice(toc.get(..8).expect("TOC header"));
let mut at = 8usize;
for _ in 0..count {
let pos = read_u64(toc, at);
let len = read_u64(toc, at + 8);
let name_len = usize::from(u16::from_le_bytes(
toc.get(at + 16..at + 18)
.expect("name_len")
.try_into()
.expect("2 bytes"),
));
let name = toc.get(at + 18..at + 18 + name_len).expect("name");
let (new_pos, new_len) = if name == section {
(pos, forged.len() as u64)
} else if pos > section_pos as u64 {
(
pos.checked_add_signed(delta).expect("shifted pos fits u64"),
len,
)
} else {
(pos, len)
};
new_toc.extend_from_slice(&new_pos.to_le_bytes());
new_toc.extend_from_slice(&new_len.to_le_bytes());
new_toc.extend_from_slice(toc.get(at + 16..at + 18 + name_len).expect("name field"));
at += 18 + name_len;
}
let fresh = {
let mut hasher = xxhash_rust::xxh3::Xxh3Default::new();
hasher.update(&new_toc);
hasher.digest128()
};
out.extend_from_slice(&new_toc);
out.extend_from_slice(
bytes
.get(trailer_start..trailer_start + 4 + 1 + 1)
.expect("trailer head"),
);
out.extend_from_slice(&fresh.to_le_bytes());
out.extend_from_slice(
&u64::try_from(new_toc_pos)
.expect("toc_pos fits u64")
.to_le_bytes(),
);
out.extend_from_slice(
&u64::try_from(new_toc.len())
.expect("TOC length fits u64")
.to_le_bytes(),
);
std::fs::write(path, &out)?;
Ok(())
}
pub fn forge_rename_and_replace_section(
path: &std::path::Path,
from: &[u8],
to: &[u8],
new_payload: &[u8],
) -> crate::Result<()> {
let bytes = std::fs::read(path)?;
const TRAILER_SIZE: usize = 4 + 1 + 1 + 16 + 8 + 8;
let trailer_start = bytes.len() - TRAILER_SIZE;
let read_u64 = |bytes: &[u8], at: usize| {
let Some(b) = bytes.get(at..at + 8) else {
panic!("u64 field within the trailer");
};
u64::from_le_bytes(b.try_into().expect("8 bytes"))
};
let toc_pos = usize::try_from(read_u64(&bytes, trailer_start + 4 + 1 + 1 + 16))
.expect("toc_pos fits usize");
let (section_pos, section_len) = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == from) else {
panic!("the SST must carry the section to rename");
};
(
usize::try_from(entry.pos()).expect("pos fits usize"),
usize::try_from(entry.len()).expect("len fits usize"),
)
};
let delta = i64::try_from(new_payload.len()).expect("payload fits i64")
- i64::try_from(section_len).expect("section fits i64");
let mut out = Vec::with_capacity(bytes.len());
out.extend_from_slice(bytes.get(..section_pos).expect("pre-section prefix"));
out.extend_from_slice(new_payload);
out.extend_from_slice(
bytes
.get(section_pos + section_len..toc_pos)
.expect("post-section sections"),
);
let new_toc_pos = out.len();
let toc_len = usize::try_from(read_u64(&bytes, trailer_start + 4 + 1 + 1 + 16 + 8))
.expect("toc_len fits usize");
let toc = bytes.get(toc_pos..toc_pos + toc_len).expect("TOC region");
assert_eq!(toc.get(..4), Some(&b"TOC!"[..]), "TOC magic");
assert_eq!(
toc_pos + toc_len,
trailer_start,
"the TOC must sit directly before the trailer; the splice above drops any gap",
);
let count = u32::from_le_bytes(toc.get(4..8).expect("count").try_into().expect("4 bytes"));
let mut new_toc = Vec::with_capacity(toc.len());
new_toc.extend_from_slice(b"TOC!");
new_toc.extend_from_slice(&count.to_le_bytes());
let mut at = 8usize;
for _ in 0..count {
let pos = read_u64(toc, at);
let len = read_u64(toc, at + 8);
let name_len = usize::from(u16::from_le_bytes(
toc.get(at + 16..at + 18)
.expect("name_len")
.try_into()
.expect("2 bytes"),
));
let name = toc.get(at + 18..at + 18 + name_len).expect("name");
if name == from {
new_toc.extend_from_slice(&pos.to_le_bytes());
new_toc.extend_from_slice(&(new_payload.len() as u64).to_le_bytes());
new_toc.extend_from_slice(
&u16::try_from(to.len())
.expect("name fits u16")
.to_le_bytes(),
);
new_toc.extend_from_slice(to);
} else {
let new_pos = if pos > section_pos as u64 {
pos.checked_add_signed(delta).expect("shifted pos fits u64")
} else {
pos
};
new_toc.extend_from_slice(&new_pos.to_le_bytes());
new_toc.extend_from_slice(&len.to_le_bytes());
new_toc.extend_from_slice(toc.get(at + 16..at + 18 + name_len).expect("name field"));
}
at += 18 + name_len;
}
let fresh = {
let mut hasher = xxhash_rust::xxh3::Xxh3Default::new();
hasher.update(&new_toc);
hasher.digest128()
};
out.extend_from_slice(&new_toc);
out.extend_from_slice(
bytes
.get(trailer_start..trailer_start + 4 + 1 + 1)
.expect("trailer head"),
);
out.extend_from_slice(&fresh.to_le_bytes());
out.extend_from_slice(
&u64::try_from(new_toc_pos)
.expect("toc_pos fits u64")
.to_le_bytes(),
);
out.extend_from_slice(
&u64::try_from(new_toc.len())
.expect("TOC len fits u64")
.to_le_bytes(),
);
std::fs::write(path, &out)?;
Ok(())
}
#[cfg(not(feature = "zstd"))]
pub fn forge_delete_bitmap_as_empty_block_layout(
path: &std::path::Path,
table_id: crate::TableId,
) -> crate::Result<()> {
use crate::table::block::{Block, BlockIdentity, BlockTransform, BlockType};
let mut payload = Vec::new();
crate::table::block_layout::encode_block_layouts(&mut payload, &[]);
let identity = BlockIdentity {
table_id,
block_type: BlockType::BlockLayout,
dict_id: 0,
window_log: 0,
};
let mut frame = Vec::new();
Block::write_into(&mut frame, &payload, identity, &BlockTransform::PLAIN)?;
forge_rename_and_replace_section(path, b"delete_bitmap", b"block_layout", &frame)
}
fn flip_and_restamp_first_data_block(
path: &std::path::Path,
flip_from_end: usize,
) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::Header;
let mut bytes = std::fs::read(path)?;
let block_off = {
let mut f = std::fs::File::open(path)?;
let reader = match crate::sfa::Reader::from_reader(&mut f) {
Ok(r) => r,
Err(e) => panic!("reading the SFA trailer failed: {e:?}"),
};
let Some(entry) = reader.toc().iter().find(|e| e.name() == b"data") else {
panic!("the SST must carry a data section");
};
usize::try_from(entry.pos()).expect("data offset fits usize")
};
let Some(block) = bytes.get(block_off..) else {
panic!("data block within the file");
};
let mut cursor = block;
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
let payload_range =
block_off + header_len..block_off + header_len + header.data_length as usize;
{
let Some(payload) = bytes.get_mut(payload_range.clone()) else {
panic!("data payload within the file");
};
let flip_at = payload.len() - flip_from_end;
let Some(slot) = payload.get_mut(flip_at) else {
panic!("flip offset within the payload");
};
*slot ^= 0xFF;
}
let Some(payload) = bytes.get(payload_range) else {
panic!("data payload within the file");
};
let new_checksum = crate::Checksum::from_raw(crate::hash::hash128(payload));
let new_header = Header {
checksum: new_checksum,
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
let Some(hdr_dst) = bytes.get_mut(block_off..block_off + header_len) else {
panic!("data header within the file");
};
hdr_dst.copy_from_slice(&hdr_bytes);
std::fs::write(path, &bytes)?;
Ok(())
}
pub fn forge_raise_data_block_first_seqno(
path: &std::path::Path,
block_off: usize,
new_seqno: u8,
) -> crate::Result<()> {
use crate::coding::{Decode, Encode};
use crate::table::block::Header;
assert!(
new_seqno < 0x80,
"the raised seqno must stay a 1-byte varint"
);
let mut bytes = std::fs::read(path)?;
let mut cursor = bytes.get(block_off..).expect("block within the file");
let header = Header::decode_from(&mut cursor)?;
let header_len = Header::header_len(header.block_type);
let payload_range =
block_off + header_len..block_off + header_len + header.data_length as usize;
let seqno_at = block_off + header_len + 1;
let old = *bytes.get(seqno_at).expect("seqno byte within the payload");
assert!(
old < 0x80,
"the original seqno must be a 1-byte varint, got {old:#x}"
);
if let Some(slot) = bytes.get_mut(seqno_at) {
*slot = new_seqno;
}
let payload = bytes.get(payload_range).expect("payload within the file");
let new_header = Header {
checksum: crate::Checksum::from_raw(crate::hash::hash128(payload)),
..header
};
let mut hdr_bytes = Vec::with_capacity(header_len);
new_header.encode_into(&mut hdr_bytes)?;
bytes
.get_mut(block_off..block_off + header_len)
.expect("header within the file")
.copy_from_slice(&hdr_bytes);
std::fs::write(path, &bytes)?;
Ok(())
}