use crate::io::{Error, Read};
pub(crate) const WILDCOPY_OVERLENGTH: usize = 32;
pub(crate) trait BufferBackend: Sized {
const SUPPORTS_INLINE_SEQUENCE_EXEC: bool = false;
#[allow(unused_variables, unused_mut)]
#[inline(always)]
unsafe fn exec_sequence_inline(
&mut self,
lit_src: *const u8,
lit_length: usize,
offset: usize,
match_length: usize,
) -> Result<(), super::errors::ExecuteSequencesError> {
unreachable!(
"exec_sequence_inline called on backend whose SUPPORTS_INLINE_SEQUENCE_EXEC is false"
);
}
fn new() -> Self;
fn clear(&mut self);
fn reserve(&mut self, n: usize);
fn try_reserve(&mut self, n: usize) -> Result<(), BackendOverflow> {
self.reserve(n);
Ok(())
}
fn len(&self) -> usize;
fn cap(&self) -> usize;
fn tail(&self) -> usize;
unsafe fn set_tail(&mut self, new_tail: usize);
fn extend(&mut self, data: &[u8]);
fn extend_and_fill(&mut self, fill_with: u8, fill_length: usize);
fn extend_from_reader<R: Read>(&mut self, read: R, fill_length: usize) -> Result<(), Error>;
unsafe fn extend_from_within_unchecked(&mut self, start: usize, len: usize);
unsafe fn extend_from_within_unchecked_branchless(&mut self, start: usize, len: usize);
fn as_slices(&self) -> (&[u8], &[u8]);
fn drop_first_n(&mut self, n: usize);
fn try_extend(&mut self, data: &[u8]) -> Result<(), BackendOverflow> {
self.extend(data);
Ok(())
}
fn try_extend_and_fill(
&mut self,
fill_with: u8,
fill_length: usize,
) -> Result<(), BackendOverflow> {
self.extend_and_fill(fill_with, fill_length);
Ok(())
}
#[allow(dead_code)]
fn try_extend_from_within(&mut self, start: usize, len: usize) -> Result<(), BackendOverflow> {
let tail = self.tail();
let capacity = self.cap();
let src_end = start.checked_add(len).ok_or(BackendOverflow {
tail,
requested: len,
capacity,
})?;
if src_end > self.len() {
return Err(BackendOverflow {
tail,
requested: len,
capacity,
});
}
self.reserve(len);
unsafe { self.extend_from_within_unchecked(start, len) };
Ok(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct BackendOverflow {
pub tail: usize,
pub requested: usize,
pub capacity: usize,
}
impl core::fmt::Display for BackendOverflow {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"BufferBackend overflow: tail={}, requested={}, capacity={}",
self.tail, self.requested, self.capacity,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::decoding::flat_buf::FlatBuf;
#[test]
fn default_try_extend_from_within_happy_path_copies_from_live_region() {
let mut b = FlatBuf::with_capacity(32);
b.extend(&[1u8, 2, 3, 4, 5]);
assert_eq!(b.len(), 5);
b.try_extend_from_within(0, 3).expect("happy path");
assert_eq!(b.len(), 8);
let (s, t) = b.as_slices();
assert_eq!(s, &[1u8, 2, 3, 4, 5, 1, 2, 3]);
assert!(t.is_empty(), "FlatBuf does not wrap");
}
#[test]
fn default_try_extend_from_within_arithmetic_overflow_returns_err() {
let mut b = FlatBuf::with_capacity(32);
b.extend(&[1u8, 2, 3, 4]);
let live_before = b.len();
let err = b
.try_extend_from_within(usize::MAX, 1)
.expect_err("usize wrap must Err");
assert_eq!(err.requested, 1);
assert_eq!(b.len(), live_before, "backend untouched on Err");
}
#[test]
fn default_try_extend_from_within_source_past_live_region_returns_err() {
let mut b = FlatBuf::with_capacity(32);
b.extend(&[10u8, 20, 30]);
let err = b
.try_extend_from_within(2, 10)
.expect_err("start+len past live region must Err");
assert_eq!(err.requested, 10);
assert_eq!(b.len(), 3, "backend untouched on Err");
}
#[test]
fn backend_overflow_display_renders_diagnostic_fields() {
let err = BackendOverflow {
tail: 5,
requested: 7,
capacity: 10,
};
let rendered = alloc::format!("{}", err);
assert!(rendered.contains("tail=5"), "tail field rendered");
assert!(rendered.contains("requested=7"), "requested field rendered");
assert!(rendered.contains("capacity=10"), "capacity field rendered");
}
}