use core::{fmt, str};
use crate::{
Vector,
writer::{Writer, write, write_slice},
};
pub trait EscapesBuilder {
type Escapes<V: Vector>: Escapes<Vector = V>;
fn new<V: Vector>() -> Self::Escapes<V>;
}
pub trait Escapes: Copy + fmt::Debug {
const ESCAPE_LEN: usize;
const FALSE_POSITIVE: bool;
type Vector: Vector;
fn masking(&self, v: Self::Vector) -> Self::Vector;
fn escape(c: usize) -> &'static str;
fn position(c: u8) -> usize;
#[inline(always)]
fn byte_byte_escape<R>(haystack: &str, mut writer: impl Writer<R>) -> Result<(), R> {
let len = haystack.len();
let start = haystack.as_ptr();
unsafe { Self::byte_byte_escape_raw(start, start.add(len), &mut writer) }
}
#[inline(always)]
unsafe fn byte_byte_escape_raw<R>(
start: *const u8,
end: *const u8,
writer: &mut impl Writer<R>,
) -> Result<(), R> {
unsafe {
let mut written = start;
let mut cur = start;
while cur < end {
let c = *cur;
if Self::byte_byte_compare(c) {
if written < cur {
write_slice(written, cur, writer)?;
}
let escaped = Self::escape(Self::position(c));
write(escaped, writer)?;
written = cur.add(1);
}
cur = cur.add(1);
}
if written < end {
write_slice(written, end, writer)?;
}
Ok(())
}
}
fn byte_byte_compare(c: u8) -> bool;
}