ssh/algorithm/compression/
zlib.rs1use flate2;
2
3use crate::SshError;
4
5use super::Compression;
6
7pub(super) struct CompressZlib {
24 decompressor: flate2::Decompress,
25 compressor: flate2::Compress,
26}
27
28impl Compression for CompressZlib {
29 fn new() -> Self
30 where
31 Self: Sized,
32 {
33 Self {
34 decompressor: flate2::Decompress::new(true),
35 compressor: flate2::Compress::new(flate2::Compression::fast(), true),
36 }
37 }
38
39 fn decompress(&mut self, buf: &[u8]) -> crate::SshResult<Vec<u8>> {
40 let mut buf_in = buf;
41 let mut buf_once = [0; 4096];
42 let mut buf_out = vec![];
43 loop {
44 let in_before = self.decompressor.total_in();
45 let out_before = self.decompressor.total_out();
46
47 let result =
48 self.decompressor
49 .decompress(buf_in, &mut buf_once, flate2::FlushDecompress::Sync);
50
51 let consumed = (self.decompressor.total_in() - in_before) as usize;
52 let produced = (self.decompressor.total_out() - out_before) as usize;
53
54 match result {
55 Ok(flate2::Status::Ok) => {
56 buf_in = &buf_in[consumed..];
57 buf_out.extend(&buf_once[..produced]);
58 }
59 Ok(flate2::Status::StreamEnd) => {
60 return Err(SshError::CompressionError(
61 "Stream ends during the decompress".to_owned(),
62 ));
63 }
64 Ok(flate2::Status::BufError) => {
65 break;
66 }
67 Err(e) => return Err(SshError::CompressionError(e.to_string())),
68 }
69 }
70
71 Ok(buf_out)
72 }
73
74 fn compress(&mut self, buf: &[u8]) -> crate::SshResult<Vec<u8>> {
75 let mut buf_in = buf;
76 let mut buf_once = [0; 4096];
77 let mut buf_out = vec![];
78 loop {
79 let in_before = self.compressor.total_in();
80 let out_before = self.compressor.total_out();
81
82 let result =
83 self.compressor
84 .compress(buf_in, &mut buf_once, flate2::FlushCompress::Partial);
85
86 let consumed = (self.compressor.total_in() - in_before) as usize;
87 let produced = (self.compressor.total_out() - out_before) as usize;
88
89 if produced == 6 {
96 break;
97 }
98
99 match result {
100 Ok(flate2::Status::Ok) => {
101 buf_in = &buf_in[consumed..];
102 buf_out.extend(&buf_once[..produced]);
103 }
104 Ok(flate2::Status::StreamEnd) => {
105 return Err(SshError::CompressionError(
106 "Stream ends during the compress".to_owned(),
107 ));
108 }
109 Ok(flate2::Status::BufError) => {
110 break;
111 }
112 Err(e) => return Err(SshError::CompressionError(e.to_string())),
113 }
114 }
115
116 Ok(buf_out)
117 }
118}