craft_codec/
compression.rs1use crate::{Compression, Error, Result};
2
3#[allow(clippy::large_enum_variant)]
5pub(crate) enum CompressionState {
6 None,
7 #[cfg(feature = "lz4")]
8 Lz4(Lz4),
9}
10
11impl CompressionState {
12 pub(crate) fn new(parameters: Compression) -> Result<Self> {
13 match parameters {
14 Compression::None => Ok(Self::None),
15 #[cfg(feature = "lz4")]
16 Compression::Lz4 => Ok(Self::Lz4(Lz4::new())),
17 #[cfg(not(feature = "lz4"))]
18 Compression::Lz4 => Err(Error::CompressionUnavailable),
19 }
20 }
21
22 pub(crate) fn encode(&mut self, _buffer: &mut Vec<u8>) -> Result<()> {
23 match self {
24 Self::None => Ok(()),
25 #[cfg(feature = "lz4")]
26 Self::Lz4(codec) => codec.encode(_buffer),
27 }
28 }
29
30 pub(crate) fn decode(&mut self, _buffer: &mut Vec<u8>, _raw_len: usize) -> Result<()> {
31 match self {
32 Self::None => Err(Error::DecompressionFailed),
33 #[cfg(feature = "lz4")]
34 Self::Lz4(codec) => codec.decode(_buffer, _raw_len),
35 }
36 }
37}
38
39#[cfg(feature = "lz4")]
43#[derive(Default)]
44pub(crate) struct Lz4 {
45 scratch: Vec<u8>,
46 table: Option<lz4_flex::block::CompressTable>,
47}
48
49#[cfg(feature = "lz4")]
50impl Lz4 {
51 pub(crate) fn new() -> Self {
53 Self::default()
54 }
55}
56
57#[cfg(feature = "lz4")]
58impl Lz4 {
59 fn encode(&mut self, buffer: &mut Vec<u8>) -> Result<()> {
60 use lz4_flex::block::{CompressTable, compress_into_with_table, get_maximum_output_size};
61 crate::error::resize(&mut self.scratch, get_maximum_output_size(buffer.len()))?;
63 let table = self.table.get_or_insert_with(CompressTable::large);
64 let written = compress_into_with_table(buffer, &mut self.scratch, table)
65 .map_err(|_| crate::Error::CompressionFailed)?;
66 if written < buffer.len() {
67 self.scratch.truncate(written);
68 std::mem::swap(buffer, &mut self.scratch);
69 }
70 Ok(())
71 }
72
73 fn decode(&mut self, buffer: &mut Vec<u8>, raw_len: usize) -> Result<()> {
74 crate::error::resize(&mut self.scratch, raw_len)?;
75 let written = lz4_flex::block::decompress_into(buffer, &mut self.scratch)
77 .map_err(|_| crate::Error::DecompressionFailed)?;
78 if written != raw_len {
79 return Err(crate::Error::DecompressionFailed);
80 }
81 std::mem::swap(buffer, &mut self.scratch);
82 Ok(())
83 }
84}