precomp2 0.2.0

Reversible preprocessing for compressed and container data.
Documentation
use crate::error::{Error, Result};

const PREFLATE_PLAIN_TEXT_LIMIT: usize = i32::MAX as usize;

pub(super) fn parse_preflate_output(buf: &[u8]) -> Result<(u64, Vec<u8>, Vec<u8>)> {
  let mut offset = 0usize;
  let deflate_len = super::varint::read_varint_slice(buf, &mut offset)?;
  let corrections_len = super::varint::read_varint_slice(buf, &mut offset)? as usize;
  if offset + corrections_len > buf.len() {
    return Err(Error::InvalidSegment("preflate corrections bounds"));
  }
  let corrections = buf[offset..offset + corrections_len].to_vec();
  offset += corrections_len;
  let plain_len = super::varint::read_varint_slice(buf, &mut offset)? as usize;
  if offset + plain_len > buf.len() {
    return Err(Error::InvalidSegment("preflate plain bounds"));
  }
  let plain = buf[offset..offset + plain_len].to_vec();
  Ok((deflate_len, corrections, plain))
}

pub(super) fn build_preflate_data(corrections: &[u8], payload: &[u8]) -> Vec<u8> {
  let mut out = Vec::with_capacity(corrections.len() + payload.len() + 16);
  super::varint::write_varint_vec(corrections.len() as u64, &mut out);
  out.extend_from_slice(corrections);
  super::varint::write_varint_vec(payload.len() as u64, &mut out);
  out.extend_from_slice(payload);
  out
}

pub(super) fn parse_preflate_data(data: &[u8]) -> Result<(Vec<u8>, Vec<u8>)> {
  let mut offset = 0usize;
  let corrections_len = super::varint::read_varint_slice(data, &mut offset)? as usize;
  if offset + corrections_len > data.len() {
    return Err(Error::InvalidSegment("corrections bounds"));
  }
  let corrections = data[offset..offset + corrections_len].to_vec();
  offset += corrections_len;
  let payload_len = super::varint::read_varint_slice(data, &mut offset)? as usize;
  if offset + payload_len > data.len() {
    return Err(Error::InvalidSegment("payload bounds"));
  }
  let payload = data[offset..offset + payload_len].to_vec();
  Ok((corrections, payload))
}

pub(super) fn preflate_analyze(deflate: &[u8]) -> Result<Vec<u8>> {
  preflate_analyze_limited(deflate, PREFLATE_PLAIN_TEXT_LIMIT)
}

pub(super) fn preflate_analyze_limited(deflate: &[u8], limit: usize) -> Result<Vec<u8>> {
  let config = preflate_rs::PreflateConfig {
    max_chain_length: 4096,
    plain_text_limit: limit.min(PREFLATE_PLAIN_TEXT_LIMIT),
    verify_compression: false,
  };
  let (analysis, plain_text) =
    preflate_rs::preflate_whole_deflate_stream(deflate, &config).map_err(|err| Error::Other(format!("preflate_analyze failed: {err}")))?;

  let mut out = Vec::with_capacity(deflate.len() + analysis.corrections.len() + 16);
  super::varint::write_varint_vec(analysis.compressed_size as u64, &mut out);
  super::varint::write_varint_vec(analysis.corrections.len() as u64, &mut out);
  out.extend_from_slice(&analysis.corrections);
  super::varint::write_varint_vec(plain_text.text().len() as u64, &mut out);
  out.extend_from_slice(plain_text.text());
  Ok(out)
}

pub(super) fn preflate_reencode(corrections: &[u8], plain: &[u8]) -> Result<Vec<u8>> {
  preflate_rs::recreate_whole_deflate_stream(plain, corrections).map_err(|err| Error::Other(format!("preflate_reencode failed: {err}")))
}