use crate::{verifier::Verifier, Error, Status};
#[derive(Debug)]
pub struct Options {
pub maximum_depth: usize,
pub initial_capacity: usize,
}
impl Default for Options {
fn default() -> Self {
Self {
initial_capacity: 512,
maximum_depth: std::usize::MAX,
}
}
}
#[derive(Debug, Default)]
pub struct Builder {
pub(crate) data: Vec<u8>,
pub(crate) invalid: bool,
pub(crate) verifier: Verifier,
}
impl Builder {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with_maximum_depth(maximum_depth: usize) -> Self {
Self::with_options(&Options {
maximum_depth,
..Default::default()
})
}
#[must_use]
pub fn with_capacity(initial_capacity: usize) -> Self {
Self::with_options(&Options {
initial_capacity,
..Default::default()
})
}
#[must_use]
pub fn with_options(options: &Options) -> Self {
Self {
invalid: false,
data: Vec::with_capacity(options.initial_capacity),
verifier: Verifier::with_maximum_depth(options.maximum_depth),
}
}
#[must_use]
pub fn len(&self) -> usize {
self.data.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
#[must_use]
pub fn status(&self) -> Status {
self.verifier.status()
}
pub fn reset(&mut self) {
self.invalid = false;
self.data.clear();
self.verifier.reset();
}
pub fn update(&mut self, source: &impl Source) -> Result<(), Error> {
if self.invalid {
Err(Error::Invalid)
} else {
for character in source.stream() {
match self.verifier.update(*character) {
Ok(()) => {
self.data.push(*character);
},
Err(e) => {
self.invalid = true;
return Err(e);
},
}
}
Ok(())
}
}
pub fn bytes(self) -> Result<Vec<u8>, Error> {
if self.invalid {
return Err(Error::Invalid);
}
Ok(self.data)
}
pub fn string(self) -> Result<String, Error> {
let data = self.bytes()?;
String::from_utf8(data).map_err(|_| Error::Utf8)
}
pub fn completed_bytes(mut self) -> Result<Vec<u8>, Error> {
if self.invalid {
Err(Error::Invalid)
} else {
if self.verifier.status() == Status::Continue {
let (until, tokens) = self.verifier.complete();
if let Some(until) = until {
self.data.truncate(if until == 0 { 1 } else { until });
}
self.data.extend(tokens);
}
Ok(self.data)
}
}
pub fn completed_string(self) -> Result<String, Error> {
let data = self.completed_bytes()?;
String::from_utf8(data).map_err(|_| Error::Utf8)
}
}
pub trait Source {
fn stream(&self) -> &[u8];
}
impl Source for u8 {
fn stream(&self) -> &[u8] {
unsafe { std::slice::from_raw_parts(self, 1) }
}
}
impl Source for &[u8] {
fn stream(&self) -> &[u8] {
self
}
}
impl Source for Vec<u8> {
fn stream(&self) -> &[u8] {
self
}
}
impl Source for &str {
fn stream(&self) -> &[u8] {
self.as_bytes()
}
}
impl Source for String {
fn stream(&self) -> &[u8] {
self.as_bytes()
}
}