craft_codec/
compression.rs1use crate::{Compression, Identity, Result};
2
3pub trait CompressionCodec: crate::sealed::Sealed {
6 const FORMAT: Compression;
8 #[doc(hidden)]
10 fn encode(&mut self, buffer: &mut Vec<u8>) -> Result<()>;
11 #[doc(hidden)]
13 fn decode(&mut self, buffer: &mut Vec<u8>, raw_len: usize) -> Result<()>;
14}
15
16impl CompressionCodec for Identity {
17 const FORMAT: Compression = Compression::None;
18 fn encode(&mut self, _: &mut Vec<u8>) -> Result<()> {
19 Ok(())
20 }
21 fn decode(&mut self, _: &mut Vec<u8>, _: usize) -> Result<()> {
22 Err(crate::Error::DecompressionFailed)
23 }
24}
25
26#[cfg(feature = "lz4")]
30#[derive(Default)]
31pub struct Lz4 {
32 scratch: Vec<u8>,
33 table: Option<lz4_flex::block::CompressTable>,
34}
35
36#[cfg(feature = "lz4")]
37impl Lz4 {
38 pub fn new() -> Self {
40 Self::default()
41 }
42}
43
44#[cfg(feature = "lz4")]
45impl crate::sealed::Sealed for Lz4 {}
46
47#[cfg(feature = "lz4")]
48impl CompressionCodec for Lz4 {
49 const FORMAT: Compression = Compression::Lz4;
50
51 fn encode(&mut self, buffer: &mut Vec<u8>) -> Result<()> {
52 use lz4_flex::block::{CompressTable, compress_into_with_table, get_maximum_output_size};
53 crate::error::resize(&mut self.scratch, get_maximum_output_size(buffer.len()))?;
55 let table = self.table.get_or_insert_with(CompressTable::large);
56 let written = compress_into_with_table(buffer, &mut self.scratch, table)
57 .map_err(|_| crate::Error::CompressionFailed)?;
58 if written < buffer.len() {
59 self.scratch.truncate(written);
60 std::mem::swap(buffer, &mut self.scratch);
61 }
62 Ok(())
63 }
64
65 fn decode(&mut self, buffer: &mut Vec<u8>, raw_len: usize) -> Result<()> {
66 crate::error::resize(&mut self.scratch, raw_len)?;
67 let written = lz4_flex::block::decompress_into(buffer, &mut self.scratch)
69 .map_err(|_| crate::Error::DecompressionFailed)?;
70 if written != raw_len {
71 return Err(crate::Error::DecompressionFailed);
72 }
73 std::mem::swap(buffer, &mut self.scratch);
74 Ok(())
75 }
76}