moved compression into TiffWriter
This commit is contained in:
1 parent
de95ac35a2
commit
9f1e3d7a89
7 files changed
+179
-193
No files matched your search
@@ -1,23 +1,11 @@
|
|||||||
use std::{
|
use crate::{encoder::compression::*, tags::CompressionMethod};
|
||||||
convert::TryInto,
|
|
||||||
io::{Seek, Write},
|
|
||||||
};
|
|
||||||
|
|
||||||
use flate2::{write::ZlibEncoder, Compression as FlateCompression};
|
use flate2::{write::ZlibEncoder, Compression as FlateCompression};
|
||||||
|
use std::io::Write;
|
||||||
use crate::{
|
|
||||||
encoder::{
|
|
||||||
colortype::ColorType, compression::Compression, DirectoryEncoder, TiffKind, TiffValue,
|
|
||||||
},
|
|
||||||
tags::CompressionMethod,
|
|
||||||
TiffResult,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The Deflate algorithm used to compress image data in TIFF files.
|
/// The Deflate algorithm used to compress image data in TIFF files.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Deflate {
|
pub struct Deflate {
|
||||||
level: FlateCompression,
|
level: FlateCompression,
|
||||||
buffer: Vec<u8>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The level of compression used by the Deflate algorithm.
|
/// The level of compression used by the Deflate algorithm.
|
||||||
@@ -40,13 +28,9 @@ impl Default for DeflateLevel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Deflate {
|
impl Deflate {
|
||||||
/// Lets be greedy and allocate more bytes in advance. We will likely encode longer image strips.
|
/// Create a new deflate compressor with a specific level of compression.
|
||||||
const DEFAULT_BUFFER_SIZE: usize = 256;
|
|
||||||
|
|
||||||
/// Create a new deflate compr+essor with a specific level of compression.
|
|
||||||
pub fn with_level(level: DeflateLevel) -> Self {
|
pub fn with_level(level: DeflateLevel) -> Self {
|
||||||
Self {
|
Self {
|
||||||
buffer: Vec::with_capacity(Self::DEFAULT_BUFFER_SIZE),
|
|
||||||
level: FlateCompression::new(level as u32),
|
level: FlateCompression::new(level as u32),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,36 +45,25 @@ impl Default for Deflate {
|
|||||||
impl Compression for Deflate {
|
impl Compression for Deflate {
|
||||||
const COMPRESSION_METHOD: CompressionMethod = CompressionMethod::Deflate;
|
const COMPRESSION_METHOD: CompressionMethod = CompressionMethod::Deflate;
|
||||||
|
|
||||||
fn write_to<'a, T: ColorType, K: TiffKind, W: 'a + Write + Seek>(
|
fn get_algorithm(&self) -> Compressor {
|
||||||
&mut self,
|
Compressor::Deflate(self.clone())
|
||||||
encoder: &mut DirectoryEncoder<'a, W, K>,
|
}
|
||||||
value: &[T::Inner],
|
}
|
||||||
) -> TiffResult<(K::OffsetType, K::OffsetType)>
|
|
||||||
where
|
|
||||||
[T::Inner]: TiffValue,
|
|
||||||
{
|
|
||||||
let data = value.data();
|
|
||||||
{
|
|
||||||
let mut encoder = ZlibEncoder::new(&mut self.buffer, self.level);
|
|
||||||
encoder.write_all(&data)?;
|
|
||||||
encoder.finish()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let compressed_byte_count = self.buffer.len().try_into()?;
|
impl CompressionAlgorithm for Deflate {
|
||||||
let offset = encoder
|
fn write_to<W: Write>(&mut self, writer: &mut W, bytes: &[u8]) -> Result<u64, io::Error> {
|
||||||
.write_data(self.buffer.as_slice())
|
let mut encoder = ZlibEncoder::new(writer, self.level);
|
||||||
.and_then(K::convert_offset)?;
|
encoder.write(&bytes)?;
|
||||||
|
encoder.try_finish()?;
|
||||||
// Clear the buffer for the next compression.
|
Ok(encoder.total_out())
|
||||||
self.buffer.clear();
|
|
||||||
|
|
||||||
Ok((offset, compressed_byte_count))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::encoder::compression::tests::{compress, TEST_DATA};
|
use super::*;
|
||||||
|
use crate::encoder::compression::tests::TEST_DATA;
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deflate() {
|
fn test_deflate() {
|
||||||
@@ -102,7 +75,9 @@ mod tests {
|
|||||||
0x3E, 0xAC, 0xF1, 0x98, 0xB9, 0x70, 0x17, 0x13,
|
0x3E, 0xAC, 0xF1, 0x98, 0xB9, 0x70, 0x17, 0x13,
|
||||||
];
|
];
|
||||||
|
|
||||||
let compressed_data = compress(TEST_DATA, super::Deflate::default());
|
let mut compressed_data = Vec::<u8>::new();
|
||||||
assert_eq!(compressed_data, EXPECTED_COMPRESSED_DATA);
|
let mut writer = Cursor::new(&mut compressed_data);
|
||||||
|
Deflate::default().write_to(&mut writer, TEST_DATA).unwrap();
|
||||||
|
assert_eq!(EXPECTED_COMPRESSED_DATA, compressed_data.as_slice());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,67 +1,33 @@
|
|||||||
use std::{
|
use crate::{encoder::compression::*, tags::CompressionMethod};
|
||||||
convert::TryInto,
|
use std::io::Write;
|
||||||
io::{Seek, Write},
|
|
||||||
};
|
|
||||||
|
|
||||||
use weezl::encode::Encoder as LZWEncoder;
|
use weezl::encode::Encoder as LZWEncoder;
|
||||||
|
|
||||||
use crate::{
|
|
||||||
encoder::{
|
|
||||||
colortype::ColorType, compression::Compression, DirectoryEncoder, TiffKind, TiffValue,
|
|
||||||
},
|
|
||||||
tags::CompressionMethod,
|
|
||||||
TiffResult,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The LZW algorithm used to compress image data in TIFF files.
|
/// The LZW algorithm used to compress image data in TIFF files.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
pub struct Lzw {
|
pub struct Lzw;
|
||||||
buffer: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Lzw {
|
|
||||||
fn default() -> Self {
|
|
||||||
// Lets be greedy and allocate more bytes in advance. We will likely encode longer image strips.
|
|
||||||
const DEFAULT_BUFFER_SIZE: usize = 256;
|
|
||||||
Self {
|
|
||||||
buffer: Vec::with_capacity(DEFAULT_BUFFER_SIZE),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Compression for Lzw {
|
impl Compression for Lzw {
|
||||||
const COMPRESSION_METHOD: CompressionMethod = CompressionMethod::LZW;
|
const COMPRESSION_METHOD: CompressionMethod = CompressionMethod::LZW;
|
||||||
|
|
||||||
fn write_to<'a, T: ColorType, K: TiffKind, W: 'a + Write + Seek>(
|
fn get_algorithm(&self) -> Compressor {
|
||||||
&mut self,
|
Compressor::Lzw(*self)
|
||||||
encoder: &mut DirectoryEncoder<'a, W, K>,
|
}
|
||||||
value: &[T::Inner],
|
}
|
||||||
) -> TiffResult<(K::OffsetType, K::OffsetType)>
|
|
||||||
where
|
|
||||||
[T::Inner]: TiffValue,
|
|
||||||
{
|
|
||||||
let bytes = value.data();
|
|
||||||
let compressed_byte_count = {
|
|
||||||
let mut encoder = LZWEncoder::with_tiff_size_switch(weezl::BitOrder::Msb, 8);
|
|
||||||
let result = encoder.into_vec(&mut self.buffer).encode_all(&bytes);
|
|
||||||
result.status.map(|_| result.consumed_out)
|
|
||||||
}?
|
|
||||||
.try_into()?;
|
|
||||||
|
|
||||||
let offset = encoder
|
impl CompressionAlgorithm for Lzw {
|
||||||
.write_data(self.buffer.as_slice())
|
fn write_to<W: Write>(&mut self, writer: &mut W, bytes: &[u8]) -> Result<u64, io::Error> {
|
||||||
.and_then(K::convert_offset)?;
|
let mut encoder = LZWEncoder::with_tiff_size_switch(weezl::BitOrder::Msb, 8);
|
||||||
|
let result = encoder.into_stream(writer).encode_all(bytes);
|
||||||
// Clear the buffer for the next compression.
|
let byte_count = result.bytes_written as u64;
|
||||||
self.buffer.clear();
|
result.status.map(|_| byte_count)
|
||||||
|
|
||||||
Ok((offset, compressed_byte_count))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::encoder::compression::tests::{compress, TEST_DATA};
|
use super::*;
|
||||||
|
use crate::encoder::compression::tests::TEST_DATA;
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_lzw() {
|
fn test_lzw() {
|
||||||
@@ -73,7 +39,9 @@ mod tests {
|
|||||||
0x4E, 0x86, 0x83, 0x69, 0xCC, 0x5D, 0x01,
|
0x4E, 0x86, 0x83, 0x69, 0xCC, 0x5D, 0x01,
|
||||||
];
|
];
|
||||||
|
|
||||||
let compressed_data = compress(TEST_DATA, super::Lzw::default());
|
let mut compressed_data = Vec::<u8>::new();
|
||||||
assert_eq!(compressed_data, EXPECTED_COMPRESSED_DATA);
|
let mut writer = Cursor::new(&mut compressed_data);
|
||||||
|
Lzw::default().write_to(&mut writer, TEST_DATA).unwrap();
|
||||||
|
assert_eq!(EXPECTED_COMPRESSED_DATA, compressed_data.as_slice());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,5 @@
|
|||||||
use std::io::prelude::*;
|
use crate::tags::CompressionMethod;
|
||||||
|
use std::io::{self, Write};
|
||||||
use crate::{
|
|
||||||
encoder::{ColorType, DirectoryEncoder, TiffKind, TiffValue},
|
|
||||||
error::TiffResult,
|
|
||||||
tags::CompressionMethod,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod deflate;
|
mod deflate;
|
||||||
mod lzw;
|
mod lzw;
|
||||||
@@ -14,45 +9,48 @@ pub use self::deflate::{Deflate, DeflateLevel};
|
|||||||
pub use self::lzw::Lzw;
|
pub use self::lzw::Lzw;
|
||||||
pub use self::uncompressed::Uncompressed;
|
pub use self::uncompressed::Uncompressed;
|
||||||
|
|
||||||
/// An algorithm used for compression with associated optional buffers and/or configurations.
|
/// An algorithm used for compression
|
||||||
pub trait Compression: Default {
|
pub trait CompressionAlgorithm {
|
||||||
|
/// The algorithm writes data directly into the writer.
|
||||||
|
/// It returns the total number of bytes written.
|
||||||
|
fn write_to<W: Write>(&mut self, writer: &mut W, bytes: &[u8]) -> Result<u64, io::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An algorithm used for compression with associated enums and optional configurations.
|
||||||
|
pub trait Compression: CompressionAlgorithm {
|
||||||
/// The corresponding tag to the algorithm.
|
/// The corresponding tag to the algorithm.
|
||||||
const COMPRESSION_METHOD: CompressionMethod;
|
const COMPRESSION_METHOD: CompressionMethod;
|
||||||
|
|
||||||
/// Write the data of a specific color type to the given encoder and return the offset and byte count, respectively.
|
/// Method to optain a type that can store each variant of comression algorithm.
|
||||||
fn write_to<'a, T: ColorType, K: TiffKind, W: 'a + Write + Seek>(
|
fn get_algorithm(&self) -> Compressor;
|
||||||
&mut self,
|
}
|
||||||
encoder: &mut DirectoryEncoder<'a, W, K>,
|
|
||||||
value: &[T::Inner],
|
/// An enum to store each compression algorithm.
|
||||||
) -> TiffResult<(K::OffsetType, K::OffsetType)>
|
pub enum Compressor {
|
||||||
where
|
Uncompressed(Uncompressed),
|
||||||
[T::Inner]: TiffValue;
|
Lzw(Lzw),
|
||||||
|
Deflate(Deflate),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Compressor {
|
||||||
|
/// The default compression strategy does not apply any compression.
|
||||||
|
fn default() -> Self {
|
||||||
|
Compressor::Uncompressed(Uncompressed::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompressionAlgorithm for Compressor {
|
||||||
|
fn write_to<W: Write>(&mut self, writer: &mut W, bytes: &[u8]) -> Result<u64, io::Error> {
|
||||||
|
match self {
|
||||||
|
Compressor::Uncompressed(algorithm) => algorithm.write_to(writer, bytes),
|
||||||
|
Compressor::Lzw(algorithm) => algorithm.write_to(writer, bytes),
|
||||||
|
Compressor::Deflate(algorithm) => algorithm.write_to(writer, bytes),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::encoder::{colortype::Gray8, compression::Compression, TiffEncoder};
|
|
||||||
use std::io::Cursor;
|
|
||||||
|
|
||||||
pub const TEST_DATA: &'static [u8] =
|
pub const TEST_DATA: &'static [u8] =
|
||||||
b"This is a string for checking various compression algorithms.";
|
b"This is a string for checking various compression algorithms.";
|
||||||
|
|
||||||
pub fn compress<C: Compression>(data: &[u8], compressor: C) -> Vec<u8> {
|
|
||||||
let mut buffer = Vec::new();
|
|
||||||
|
|
||||||
// Compress the data
|
|
||||||
{
|
|
||||||
let mut encoder = TiffEncoder::new(Cursor::new(&mut buffer)).unwrap();
|
|
||||||
let encoder = encoder
|
|
||||||
.new_image_with_compression::<Gray8, _>(data.len() as u32, 1, compressor)
|
|
||||||
.unwrap();
|
|
||||||
encoder.write_data(&data).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the meta data written by the encoder
|
|
||||||
buffer.drain(..8);
|
|
||||||
buffer.drain(buffer.len() - 178..);
|
|
||||||
|
|
||||||
buffer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,5 @@
|
|||||||
use std::{
|
use crate::{encoder::compression::*, tags::CompressionMethod};
|
||||||
convert::TryInto,
|
use std::io::Write;
|
||||||
io::{Seek, Write},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
encoder::{
|
|
||||||
colortype::ColorType, compression::Compression, DirectoryEncoder, TiffKind, TiffValue,
|
|
||||||
},
|
|
||||||
tags::CompressionMethod,
|
|
||||||
TiffResult,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The default algorithm which does not compress at all.
|
/// The default algorithm which does not compress at all.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
@@ -18,27 +8,30 @@ pub struct Uncompressed;
|
|||||||
impl Compression for Uncompressed {
|
impl Compression for Uncompressed {
|
||||||
const COMPRESSION_METHOD: CompressionMethod = CompressionMethod::None;
|
const COMPRESSION_METHOD: CompressionMethod = CompressionMethod::None;
|
||||||
|
|
||||||
fn write_to<'a, T: ColorType, K: TiffKind, W: 'a + Write + Seek>(
|
fn get_algorithm(&self) -> Compressor {
|
||||||
&mut self,
|
Compressor::Uncompressed(*self)
|
||||||
encoder: &mut DirectoryEncoder<'a, W, K>,
|
}
|
||||||
value: &[T::Inner],
|
}
|
||||||
) -> TiffResult<(K::OffsetType, K::OffsetType)>
|
|
||||||
where
|
impl CompressionAlgorithm for Uncompressed {
|
||||||
[T::Inner]: TiffValue,
|
fn write_to<W: Write>(&mut self, writer: &mut W, bytes: &[u8]) -> Result<u64, io::Error> {
|
||||||
{
|
writer.write(bytes).map(|byte_count| byte_count as u64)
|
||||||
let byte_count = value.len().try_into()?;
|
|
||||||
let offset = encoder.write_data(value).and_then(K::convert_offset)?;
|
|
||||||
Ok((offset, byte_count))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::encoder::compression::tests::{compress, TEST_DATA};
|
use super::*;
|
||||||
|
use crate::encoder::compression::tests::TEST_DATA;
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_no_compression() {
|
fn test_no_compression() {
|
||||||
let compressed_data = compress(TEST_DATA, super::Uncompressed);
|
let mut compressed_data = Vec::<u8>::new();
|
||||||
|
let mut writer = Cursor::new(&mut compressed_data);
|
||||||
|
Uncompressed::default()
|
||||||
|
.write_to(&mut writer, TEST_DATA)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(TEST_DATA, compressed_data);
|
assert_eq!(TEST_DATA, compressed_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+18
-6
@@ -246,6 +246,11 @@ impl<'a, W: 'a + Write + Seek, K: TiffKind> DirectoryEncoder<'a, W, K> {
|
|||||||
Ok(offset)
|
Ok(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Provides the number of bytes written by the underlying TiffWriter during the last call.
|
||||||
|
fn last_written(&self) -> u64 {
|
||||||
|
self.writer.last_written()
|
||||||
|
}
|
||||||
|
|
||||||
fn finish_internal(&mut self) -> TiffResult<()> {
|
fn finish_internal(&mut self) -> TiffResult<()> {
|
||||||
let ifd_pointer = self.write_directory()?;
|
let ifd_pointer = self.write_directory()?;
|
||||||
let curr_pos = self.writer.offset();
|
let curr_pos = self.writer.offset();
|
||||||
@@ -383,7 +388,7 @@ impl<'a, W: 'a + Write + Seek, T: ColorType, K: TiffKind, D: Compression>
|
|||||||
strip_offsets: Vec::new(),
|
strip_offsets: Vec::new(),
|
||||||
strip_byte_count: Vec::new(),
|
strip_byte_count: Vec::new(),
|
||||||
dropped: false,
|
dropped: false,
|
||||||
compression,
|
compression: compression,
|
||||||
_phantom: ::std::marker::PhantomData,
|
_phantom: ::std::marker::PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -416,11 +421,11 @@ impl<'a, W: 'a + Write + Seek, T: ColorType, K: TiffKind, D: Compression>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write the (possible compressed) data to the encoder.
|
// Write the (possible compressed) data to the encoder.
|
||||||
let (offset, byte_count) = self
|
let offset = self.encoder.write_data(value)?;
|
||||||
.compression
|
let byte_count = self.encoder.last_written() as usize;
|
||||||
.write_to::<T, K, W>(&mut self.encoder, value)?;
|
|
||||||
self.strip_offsets.push(offset);
|
self.strip_offsets.push(K::convert_offset(offset)?);
|
||||||
self.strip_byte_count.push(byte_count);
|
self.strip_byte_count.push(byte_count.try_into()?);
|
||||||
|
|
||||||
self.strip_idx += 1;
|
self.strip_idx += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -446,12 +451,19 @@ impl<'a, W: 'a + Write + Seek, T: ColorType, K: TiffKind, D: Compression>
|
|||||||
)
|
)
|
||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.encoder
|
||||||
|
.writer
|
||||||
|
.set_compression(self.compression.get_algorithm());
|
||||||
|
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
while self.next_strip_sample_count() > 0 {
|
while self.next_strip_sample_count() > 0 {
|
||||||
let sample_count = usize::try_from(self.next_strip_sample_count())?;
|
let sample_count = usize::try_from(self.next_strip_sample_count())?;
|
||||||
self.write_strip(&data[idx..idx + sample_count])?;
|
self.write_strip(&data[idx..idx + sample_count])?;
|
||||||
idx += sample_count;
|
idx += sample_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.encoder.writer.reset_compression();
|
||||||
self.finish()?;
|
self.finish()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
+63
-23
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::encoder::compression::*;
|
||||||
use crate::error::TiffResult;
|
use crate::error::TiffResult;
|
||||||
use std::io::{self, Seek, SeekFrom, Write};
|
use std::io::{self, Seek, SeekFrom, Write};
|
||||||
|
|
||||||
@@ -42,87 +43,126 @@ pub fn write_bigtiff_header<W: Write>(writer: &mut TiffWriter<W>) -> TiffResult<
|
|||||||
pub struct TiffWriter<W> {
|
pub struct TiffWriter<W> {
|
||||||
writer: W,
|
writer: W,
|
||||||
offset: u64,
|
offset: u64,
|
||||||
|
byte_count: u64,
|
||||||
|
compressor: Compressor,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Write> TiffWriter<W> {
|
impl<W: Write> TiffWriter<W> {
|
||||||
pub fn new(writer: W) -> Self {
|
pub fn new(writer: W) -> Self {
|
||||||
Self { writer, offset: 0 }
|
Self {
|
||||||
|
writer,
|
||||||
|
offset: 0,
|
||||||
|
byte_count: 0,
|
||||||
|
compressor: Compressor::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_compression(&mut self, compressor: Compressor) {
|
||||||
|
self.compressor = compressor;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_compression(&mut self) {
|
||||||
|
self.compressor = Compressor::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset(&self) -> u64 {
|
pub fn offset(&self) -> u64 {
|
||||||
self.offset
|
self.offset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn last_written(&self) -> u64 {
|
||||||
|
self.byte_count
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), io::Error> {
|
pub fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), io::Error> {
|
||||||
self.writer.write_all(bytes)?;
|
self.byte_count = self.compressor.write_to(&mut self.writer, bytes)?;
|
||||||
self.offset += bytes.len() as u64;
|
self.offset += self.byte_count;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_u8(&mut self, n: u8) -> Result<(), io::Error> {
|
pub fn write_u8(&mut self, n: u8) -> Result<(), io::Error> {
|
||||||
self.writer.write_all(&n.to_ne_bytes())?;
|
self.byte_count = self
|
||||||
self.offset += 1;
|
.compressor
|
||||||
|
.write_to(&mut self.writer, &n.to_ne_bytes())?;
|
||||||
|
self.offset += self.byte_count;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_i8(&mut self, n: i8) -> Result<(), io::Error> {
|
pub fn write_i8(&mut self, n: i8) -> Result<(), io::Error> {
|
||||||
self.writer.write_all(&n.to_ne_bytes())?;
|
self.byte_count = self
|
||||||
self.offset += 1;
|
.compressor
|
||||||
|
.write_to(&mut self.writer, &n.to_ne_bytes())?;
|
||||||
|
self.offset += self.byte_count;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_u16(&mut self, n: u16) -> Result<(), io::Error> {
|
pub fn write_u16(&mut self, n: u16) -> Result<(), io::Error> {
|
||||||
self.writer.write_all(&n.to_ne_bytes())?;
|
self.byte_count = self
|
||||||
self.offset += 2;
|
.compressor
|
||||||
|
.write_to(&mut self.writer, &n.to_ne_bytes())?;
|
||||||
|
self.offset += self.byte_count;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_i16(&mut self, n: i16) -> Result<(), io::Error> {
|
pub fn write_i16(&mut self, n: i16) -> Result<(), io::Error> {
|
||||||
self.writer.write_all(&n.to_ne_bytes())?;
|
self.byte_count = self
|
||||||
self.offset += 2;
|
.compressor
|
||||||
|
.write_to(&mut self.writer, &n.to_ne_bytes())?;
|
||||||
|
self.offset += self.byte_count;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_u32(&mut self, n: u32) -> Result<(), io::Error> {
|
pub fn write_u32(&mut self, n: u32) -> Result<(), io::Error> {
|
||||||
self.writer.write_all(&n.to_ne_bytes())?;
|
self.byte_count = self
|
||||||
self.offset += 4;
|
.compressor
|
||||||
|
.write_to(&mut self.writer, &n.to_ne_bytes())?;
|
||||||
|
self.offset += self.byte_count;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_i32(&mut self, n: i32) -> Result<(), io::Error> {
|
pub fn write_i32(&mut self, n: i32) -> Result<(), io::Error> {
|
||||||
self.writer.write_all(&n.to_ne_bytes())?;
|
self.byte_count = self
|
||||||
self.offset += 4;
|
.compressor
|
||||||
|
.write_to(&mut self.writer, &n.to_ne_bytes())?;
|
||||||
|
self.offset += self.byte_count;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_u64(&mut self, n: u64) -> Result<(), io::Error> {
|
pub fn write_u64(&mut self, n: u64) -> Result<(), io::Error> {
|
||||||
self.writer.write_all(&n.to_ne_bytes())?;
|
self.byte_count = self
|
||||||
self.offset += 8;
|
.compressor
|
||||||
|
.write_to(&mut self.writer, &n.to_ne_bytes())?;
|
||||||
|
self.offset += self.byte_count;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_i64(&mut self, n: i64) -> Result<(), io::Error> {
|
pub fn write_i64(&mut self, n: i64) -> Result<(), io::Error> {
|
||||||
self.writer.write_all(&n.to_ne_bytes())?;
|
self.byte_count = self
|
||||||
self.offset += 8;
|
.compressor
|
||||||
|
.write_to(&mut self.writer, &n.to_ne_bytes())?;
|
||||||
|
self.offset += self.byte_count;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_f32(&mut self, n: f32) -> Result<(), io::Error> {
|
pub fn write_f32(&mut self, n: f32) -> Result<(), io::Error> {
|
||||||
self.writer.write_all(&u32::to_ne_bytes(n.to_bits()))?;
|
self.byte_count = self
|
||||||
self.offset += 4;
|
.compressor
|
||||||
|
.write_to(&mut self.writer, &u32::to_ne_bytes(n.to_bits()))?;
|
||||||
|
self.offset += self.byte_count;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_f64(&mut self, n: f64) -> Result<(), io::Error> {
|
pub fn write_f64(&mut self, n: f64) -> Result<(), io::Error> {
|
||||||
self.writer.write_all(&u64::to_ne_bytes(n.to_bits()))?;
|
self.byte_count = self
|
||||||
self.offset += 8;
|
.compressor
|
||||||
|
.write_to(&mut self.writer, &u64::to_ne_bytes(n.to_bits()))?;
|
||||||
|
self.offset += self.byte_count;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ fn encode_decode_with_compression<C: Compression + Clone>(compression: C) {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn encode_decode_without_compression() {
|
fn encode_decode_without_compression() {
|
||||||
encode_decode_with_compression(Uncompressed);
|
encode_decode_with_compression(Uncompressed::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in new issue
Block a user