use core::fmt;
use core::marker::PhantomData;
use base64ct::{Base64UrlUnpadded, Encoding};
use super::{Error, Update};
use crate::Zeroizing;
pub struct Decoder<T, E = Base64UrlUnpadded> {
decoded: Zeroizing<[u8; 3]>,
encoded: Zeroizing<[u8; 4]>,
config: PhantomData<E>,
used: usize,
all: usize,
next: T,
}
impl<T: Default, E> Default for Decoder<T, E> {
fn default() -> Self {
Self::from(T::default())
}
}
impl<T, E> From<T> for Decoder<T, E> {
fn from(next: T) -> Self {
Self {
decoded: Default::default(),
encoded: Default::default(),
config: Default::default(),
used: Default::default(),
all: Default::default(),
next,
}
}
}
impl<T: Update, E: Encoding> Update for Decoder<T, E> {
type Error = Error<T::Error>;
fn update(&mut self, chunk: impl AsRef<[u8]>) -> Result<(), Self::Error> {
for byte in chunk.as_ref() {
if self.used == 4 {
if E::decode_3bytes(&self.encoded[..], &mut self.decoded[..]) != 0 {
return Err(Error::Value);
}
self.next.update(&self.decoded).map_err(Error::Inner)?;
self.used = 0;
}
self.encoded[self.used] = *byte;
self.used += 1;
self.all += 1;
}
Ok(())
}
}
impl<T: Update, E: Encoding> Decoder<T, E> {
pub fn finish(mut self) -> Result<T, Error<T::Error>> {
let encoded = &self.encoded[..self.used];
let decoded = E::decode(encoded, &mut self.decoded[..])?;
self.next.update(decoded).map_err(Error::Inner)?;
Ok(self.next)
}
}
impl<T: fmt::Debug, E> fmt::Debug for Decoder<T, E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Encoder")
.field("next", &self.next)
.finish_non_exhaustive()
}
}