use crate::helpers::write_varint_ohb;
pub(super) const NO_NEXT: u64 = 0xFF_FFFF_FFFF;
pub(super) const BASE_OVERHEAD: usize = 11;
pub(super) fn write_placeholder(
out: &mut Vec<u8>,
ohb: usize,
first_placeholder: &mut Option<usize>,
last_placeholder: &mut Option<usize>,
) -> (usize, usize) {
let placeholder_start = out.len();
out.push(0u8);
let sentinel = NO_NEXT.to_le_bytes();
out.extend_from_slice(&sentinel[..5]);
for _ in 0..5 + ohb {
out.push(0u8);
}
if let Some(last_ph) = *last_placeholder {
let next_bytes = (placeholder_start as u64).to_le_bytes();
out[last_ph + 1..last_ph + 6].copy_from_slice(&next_bytes[..5]);
}
if first_placeholder.is_none() {
*first_placeholder = Some(placeholder_start);
}
*last_placeholder = Some(placeholder_start);
(placeholder_start, out.len())
}
pub(super) fn fill_placeholder(
out: &mut [u8],
placeholder_start: usize,
ohb: usize,
content_start: usize,
frame_acw: usize,
) -> usize {
let child_len_raw = out.len() - content_start;
let child_len_compacted = child_len_raw - frame_acw;
let ohb_opt = if ohb > 0 { Some(ohb as u64) } else { None };
let mut tmp = Vec::new();
write_varint_ohb(child_len_compacted as u64, ohb_opt, &mut tmp);
let k = tmp.len();
let varint_room_end = placeholder_start + BASE_OVERHEAD + ohb;
let varint_write_start = varint_room_end - k;
out[varint_write_start..varint_room_end].copy_from_slice(&tmp);
let waste = BASE_OVERHEAD + ohb - k;
out[placeholder_start] = waste as u8;
waste + frame_acw
}
pub(super) fn compact(out: &mut Vec<u8>, first_placeholder: usize) {
let total_len = out.len();
let mut read_pos = 0usize;
let mut write_pos = 0usize;
let mut cursor = first_placeholder;
#[cfg(debug_assertions)]
eprintln!(
"[encode_text] compact: total_len={} first_placeholder={}",
total_len, first_placeholder
);
loop {
if cursor > read_pos {
out.copy_within(read_pos..cursor, write_pos);
write_pos += cursor - read_pos;
}
let waste = out[cursor] as usize;
let mut next_bytes = [0u8; 8];
next_bytes[..5].copy_from_slice(&out[cursor + 1..cursor + 6]);
let next = u64::from_le_bytes(next_bytes);
read_pos = cursor + waste;
if next == NO_NEXT {
break;
}
cursor = next as usize;
}
if read_pos < total_len {
out.copy_within(read_pos..total_len, write_pos);
write_pos += total_len - read_pos;
}
out.truncate(write_pos);
#[cfg(debug_assertions)]
eprintln!(
"[encode_text] compact done: final_len={} (saved {} bytes)",
write_pos,
total_len - write_pos
);
}