use std::mem::MaybeUninit;
use crate::{helpers::vec_to_uninit_mut, Result};
pub(crate) mod crlf;
pub(crate) mod lf;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NormalizeChunkResult<S: Sized> {
output_len: usize,
state: Option<S>,
}
impl<S> NormalizeChunkResult<S> {
#[must_use]
pub fn new(output_len: usize, state: Option<S>) -> Self {
Self { output_len, state }
}
#[must_use]
pub fn output_len(&self) -> usize {
self.output_len
}
#[must_use]
pub fn state(&self) -> Option<&S> {
self.state.as_ref()
}
}
pub trait NormalizeChunk {
type State: Clone + Sized;
fn normalize_chunk(
input: &[u8],
output: &mut [MaybeUninit<u8>],
state: Option<&Self::State>,
is_last_chunk: bool,
) -> Result<NormalizeChunkResult<Self::State>>;
#[must_use]
fn max_output_size_for_chunk(
chunk_size: usize,
state: Option<&Self::State>,
is_last_chunk: bool,
) -> usize;
}
pub trait Normalize {
#[must_use]
fn normalize(input: &[u8]) -> Vec<u8>;
#[must_use]
fn normalize_str(input: &str) -> String;
}
impl<N: NormalizeChunk> Normalize for N {
fn normalize(input: &[u8]) -> Vec<u8> {
let mut output =
Vec::with_capacity(Self::max_output_size_for_chunk(input.len(), None, true));
let status = Self::normalize_chunk(input, vec_to_uninit_mut(&mut output), None, true)
.unwrap_or_else(|err| unreachable!("{err} (should be impossible)",));
unsafe {
output.set_len(status.output_len());
}
output
}
fn normalize_str(input: &str) -> String {
unsafe { String::from_utf8_unchecked(Self::normalize(input.as_bytes())) }
}
}