Merge StreamDecoder into Decoder
This commit is contained in:
parent
5371c75a59
commit
88a020b851
2 changed files with 88 additions and 87 deletions
172
src/decode.rs
172
src/decode.rs
|
@ -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];
|
||||||
|
|
|
@ -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};
|
||||||
|
|
Loading…
Reference in a new issue