Merge StreamDecoder into Decoder

This commit is contained in:
Ivan Smirnov 2022-01-04 00:25:05 +03:00
parent 5371c75a59
commit 88a020b851
2 changed files with 88 additions and 87 deletions

View file

@ -125,68 +125,6 @@ pub fn decode_header(data: impl AsRef<[u8]>) -> Result<Header> {
Header::decode(data) Header::decode(data)
} }
#[derive(Clone)]
pub struct Decoder<'a> {
data: &'a [u8],
header: Header,
channels: Channels,
}
impl<'a> Decoder<'a> {
#[inline]
pub fn new(data: &'a (impl AsRef<[u8]> + ?Sized)) -> Result<Self> {
let data = data.as_ref();
let header = Header::decode(data)?;
let data = &data[QOI_HEADER_SIZE..]; // can't panic
Ok(Self { data, header, channels: header.channels })
}
#[inline]
pub const fn with_channels(mut self, channels: Channels) -> Self {
self.channels = channels;
self
}
#[inline]
pub const fn channels(&self) -> Channels {
self.channels
}
#[inline]
pub const fn header(&self) -> &Header {
&self.header
}
#[inline]
pub const fn data(self) -> &'a [u8] {
self.data
}
#[inline]
pub fn decode_to_buf(&mut self, mut buf: impl AsMut<[u8]>) -> Result<usize> {
let buf = buf.as_mut();
let size = self.header.n_pixels() * self.channels.as_u8() as usize;
if unlikely(buf.len() < size) {
return Err(Error::OutputBufferTooSmall { size: buf.len(), required: size });
}
let n_read = decode_impl_slice_all(
self.data,
buf,
self.channels.as_u8(),
self.header.channels.as_u8(),
)?;
self.data = &self.data[n_read..]; // can't panic
Ok(size)
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[inline]
pub fn decode_to_vec(&mut self) -> Result<Vec<u8>> {
let mut out = vec![0; self.header.n_pixels() * self.channels.as_u8() as usize];
self.decode_to_buf(&mut out).map(|_| out)
}
}
#[cfg(any(feature = "std"))] #[cfg(any(feature = "std"))]
#[inline] #[inline]
fn decode_impl_stream<R: Read, const N: usize, const RGBA: bool>( fn decode_impl_stream<R: Read, const N: usize, const RGBA: bool>(
@ -274,20 +212,98 @@ fn decode_impl_stream_all<R: Read>(
} }
} }
#[doc(hidden)]
pub trait Reader: Sized {
fn decode_header(&mut self) -> Result<Header>;
fn decode_image(&mut self, out: &mut [u8], channels: u8, src_channels: u8) -> Result<()>;
}
struct Bytes<'a>(&'a [u8]);
impl<'a> Bytes<'a> {
#[inline]
pub const fn new(buf: &'a [u8]) -> Self {
Self(buf)
}
#[inline]
pub const fn as_slice(&self) -> &[u8] {
self.0
}
}
impl<'a> Reader for Bytes<'a> {
#[inline]
fn decode_header(&mut self) -> Result<Header> {
let header = Header::decode(self.0)?;
self.0 = &self.0[QOI_HEADER_SIZE..]; // can't panic
Ok(header)
}
#[inline]
fn decode_image(&mut self, out: &mut [u8], channels: u8, src_channels: u8) -> Result<()> {
let n_read = decode_impl_slice_all(self.0, out, channels, src_channels)?;
self.0 = &self.0[n_read..];
Ok(())
}
}
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub struct StreamDecoder<R> { impl<R: Read> Reader for R {
#[inline]
fn decode_header(&mut self) -> Result<Header> {
let mut b = [0; QOI_HEADER_SIZE];
self.read_exact(&mut b)?;
Header::decode(b)
}
#[inline]
fn decode_image(&mut self, out: &mut [u8], channels: u8, src_channels: u8) -> Result<()> {
decode_impl_stream_all(self, out, channels, src_channels)
}
}
#[derive(Clone)]
pub struct Decoder<R> {
reader: R, reader: R,
header: Header, header: Header,
channels: Channels, channels: Channels,
} }
#[cfg(feature = "std")] impl<'a> Decoder<Bytes<'a>> {
impl<R: Read> StreamDecoder<R> {
#[inline] #[inline]
pub fn new(mut reader: R) -> Result<Self> { pub fn new(data: &'a (impl AsRef<[u8]> + ?Sized)) -> Result<Self> {
let mut b = [0; QOI_HEADER_SIZE]; Self::new_impl(Bytes::new(data.as_ref()))
reader.read_exact(&mut b)?; }
let header = Header::decode(b)?;
#[inline]
pub const fn data(&self) -> &[u8] {
self.reader.as_slice()
}
}
#[cfg(feature = "std")]
impl<R: Read> Decoder<R> {
#[inline]
pub fn from_stream(reader: R) -> Result<Self> {
Self::new_impl(reader)
}
#[inline]
pub fn reader(&self) -> &R {
&self.reader
}
#[inline]
pub fn into_reader(self) -> R {
self.reader
}
}
impl<R: Reader> Decoder<R> {
#[inline]
fn new_impl(mut reader: R) -> Result<Self> {
let header = reader.decode_header()?;
Ok(Self { reader, header, channels: header.channels }) Ok(Self { reader, header, channels: header.channels })
} }
@ -306,16 +322,6 @@ impl<R: Read> StreamDecoder<R> {
&self.header &self.header
} }
#[inline]
pub fn reader(&self) -> &R {
&self.reader
}
#[inline]
pub fn into_reader(self) -> R {
self.reader
}
#[inline] #[inline]
pub fn decode_to_buf(&mut self, mut buf: impl AsMut<[u8]>) -> Result<usize> { pub fn decode_to_buf(&mut self, mut buf: impl AsMut<[u8]>) -> Result<usize> {
let buf = buf.as_mut(); let buf = buf.as_mut();
@ -323,15 +329,11 @@ impl<R: Read> StreamDecoder<R> {
if unlikely(buf.len() < size) { if unlikely(buf.len() < size) {
return Err(Error::OutputBufferTooSmall { size: buf.len(), required: size }); return Err(Error::OutputBufferTooSmall { size: buf.len(), required: size });
} }
decode_impl_stream_all( self.reader.decode_image(buf, self.channels.as_u8(), self.header.channels.as_u8())?;
&mut self.reader,
buf,
self.channels.as_u8(),
self.header.channels.as_u8(),
)?;
Ok(size) Ok(size)
} }
#[cfg(any(feature = "std", feature = "alloc"))]
#[inline] #[inline]
pub fn decode_to_vec(&mut self) -> Result<Vec<u8>> { pub fn decode_to_vec(&mut self) -> Result<Vec<u8>> {
let mut out = vec![0; self.header.n_pixels() * self.channels.as_u8() as usize]; let mut out = vec![0; self.header.n_pixels() * self.channels.as_u8() as usize];

View file

@ -27,13 +27,12 @@ pub mod consts;
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
pub use crate::decode::decode_to_vec; pub use crate::decode::decode_to_vec;
#[cfg(feature = "std")]
pub use crate::decode::StreamDecoder;
pub use crate::decode::{decode_header, decode_to_buf, Decoder}; pub use crate::decode::{decode_header, decode_to_buf, Decoder};
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
pub use crate::encode::encode_to_vec; pub use crate::encode::encode_to_vec;
pub use crate::encode::{encode_size_limit, encode_to_buf, Encoder}; pub use crate::encode::{encode_size_limit, encode_to_buf, Encoder};
pub use crate::error::{Error, Result}; pub use crate::error::{Error, Result};
pub use crate::header::Header; pub use crate::header::Header;
pub use crate::types::{Channels, ColorSpace}; pub use crate::types::{Channels, ColorSpace};