compression_codecs/zstd/
mod.rs1mod decoder;
2mod encoder;
3pub mod params;
4
5pub use self::{decoder::ZstdDecoder, encoder::ZstdEncoder};
6
7use compression_core::{
8 unshared::Unshared,
9 util::{PartialBuffer, WriteBuffer},
10};
11use libzstd::stream::raw::{InBuffer, Operation, OutBuffer, WriteBuf};
12use std::io;
13
14#[repr(transparent)]
15struct WriteBufferWrapper<'a>(WriteBuffer<'a>);
16
17unsafe impl WriteBuf for WriteBufferWrapper<'_> {
18 fn as_slice(&self) -> &[u8] {
19 self.0.written()
20 }
21 fn capacity(&self) -> usize {
22 self.0.capacity()
23 }
24 fn as_mut_ptr(&mut self) -> *mut u8 {
25 self.0.as_mut_ptr()
26 }
27 unsafe fn filled_until(&mut self, n: usize) {
28 self.0.set_written_and_initialized_len(n);
29 }
30}
31
32trait WriteBufExt {
33 fn get_out_buf(&mut self) -> OutBuffer<'_, WriteBufferWrapper<'_>>;
34}
35
36impl WriteBufExt for WriteBuffer<'_> {
37 fn get_out_buf(&mut self) -> OutBuffer<'_, WriteBufferWrapper<'_>> {
38 {
39 use std::mem::{align_of, size_of};
40 assert_eq!(
41 size_of::<WriteBuffer<'static>>(),
42 size_of::<WriteBufferWrapper<'static>>()
43 );
44 assert_eq!(
45 align_of::<WriteBuffer<'static>>(),
46 align_of::<WriteBufferWrapper<'static>>()
47 );
48 }
49
50 let written_len = self.written_len();
52 OutBuffer::around_pos(
53 unsafe { &mut *(self as *mut _ as *mut WriteBufferWrapper<'_>) },
54 written_len,
55 )
56 }
57}
58
59trait OperationExt {
60 fn reinit(&mut self) -> io::Result<()>;
61
62 fn run(
64 &mut self,
65 input: &mut PartialBuffer<&[u8]>,
66 output: &mut WriteBuffer<'_>,
67 ) -> io::Result<bool>;
68
69 fn flush(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool>;
70
71 fn finish(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool>;
72}
73
74impl<C: Operation> OperationExt for Unshared<C> {
75 fn reinit(&mut self) -> io::Result<()> {
76 self.get_mut().reinit()
77 }
78
79 fn run(
80 &mut self,
81 input: &mut PartialBuffer<&[u8]>,
82 output: &mut WriteBuffer<'_>,
83 ) -> io::Result<bool> {
84 let mut in_buf = InBuffer::around(input.unwritten());
85 let result = self.get_mut().run(&mut in_buf, &mut output.get_out_buf());
86 input.advance(in_buf.pos());
87 Ok(result? == 0)
88 }
89
90 fn flush(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
91 Ok(self.get_mut().flush(&mut output.get_out_buf())? == 0)
92 }
93
94 fn finish(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
95 Ok(self.get_mut().finish(&mut output.get_out_buf(), true)? == 0)
96 }
97}