use std::fmt;
use std::io::{self, Read};
#[cfg(feature = "deflate")]
use flate2::read::ZlibDecoder;
use rusqlite::blob::Blob;
use super::store::FileBlob;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Compression {
None,
#[cfg(feature = "deflate")]
Deflate {
level: u32,
},
}
impl Compression {
#[cfg(feature = "deflate")]
pub const FAST: Self = Self::Deflate { level: 1 };
#[cfg(feature = "deflate")]
pub const BEST: Self = Self::Deflate { level: 9 };
}
enum InnerReader<'conn> {
#[cfg(feature = "deflate")]
Compressed(ZlibDecoder<Blob<'conn>>),
Uncompressed(Blob<'conn>),
}
impl<'conn> fmt::Debug for InnerReader<'conn> {
#[cfg_attr(coverage_nightly, coverage(off))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
#[cfg(feature = "deflate")]
Self::Compressed(_) => f.debug_tuple("Compressed").finish(),
Self::Uncompressed(_) => f.debug_tuple("Uncompressed").finish(),
}
}
}
impl<'conn> Read for InnerReader<'conn> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self {
#[cfg(feature = "deflate")]
InnerReader::Compressed(reader) => reader.read(buf),
InnerReader::Uncompressed(reader) => reader.read(buf),
}
}
}
#[derive(Debug)]
pub struct FileReader<'conn> {
inner: InnerReader<'conn>,
}
impl<'conn> FileReader<'conn> {
pub(super) fn new(blob: FileBlob<'conn>) -> crate::Result<Self> {
if blob.is_compressed() {
#[cfg(feature = "deflate")]
return Ok(Self {
inner: InnerReader::Compressed(ZlibDecoder::new(blob.into_blob())),
});
#[cfg(not(feature = "deflate"))]
return Err(crate::Error::CompressionNotSupported);
}
Ok(Self {
inner: InnerReader::Uncompressed(blob.into_blob()),
})
}
}
impl<'conn> Read for FileReader<'conn> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
}