Skip to content

Commit ba9a098

Browse files
committed
Temporary workaround for the zstd-rs PR not being merged yet
1 parent 2e805f1 commit ba9a098

File tree

4 files changed

+153
-4
lines changed

4 files changed

+153
-4
lines changed

Cargo.lock

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ lz4_flex = "0.11.3"
3535
md-5 = "0.10.5"
3636
process_path = "0.1.4"
3737
ratatui = "0.26.0"
38-
ruzstd = { git = "https://github.com/ifd3f/zstd-rs.git", rev = "4b79cb9091b7ae2db110b4e3f0abdf2bd60fd625", version = "0.6.0" }
38+
ruzstd = "0.6.0"
3939
serde = { version = "1.0.200", features = ["derive"] }
4040
serde_json = "1.0.116"
4141
sha1 = "0.10.5"

src/compression.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
mod zstd_streaming_decoder;
2+
13
use clap::ValueEnum;
24
use std::{
35
fmt::Display,
@@ -184,8 +186,8 @@ generate! {
184186
Zst {
185187
extension_pattern: "zst",
186188
display: "zstd/ZStandard",
187-
from_reader() -> ruzstd::streaming_decoder::StreamingDecoder<R, ruzstd::frame_decoder::FrameDecoder> {
188-
ruzstd::streaming_decoder::StreamingDecoder::new(r)?
189+
from_reader() -> self::zstd_streaming_decoder::StreamingDecoder<R, ruzstd::frame_decoder::FrameDecoder> {
190+
self::zstd_streaming_decoder::StreamingDecoder::new(r)?
189191
}
190192
}
191193
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
//! This code is copied from [zstd-rs PR #62](https://github.com/KillingSpark/zstd-rs/pull/62).
2+
//! It is vendored in and slightly modified because I am too impatient to wait for it
3+
//! to be merged and published to crates.io, and nixpkgs does not enjoy git dependencies.
4+
5+
#![allow(dead_code)]
6+
7+
// MIT License
8+
//
9+
// Copyright (c) 2019 Moritz Borcherding
10+
//
11+
// Permission is hereby granted, free of charge, to any person obtaining a copy
12+
// of this software and associated documentation files (the "Software"), to deal
13+
// in the Software without restriction, including without limitation the rights
14+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15+
// copies of the Software, and to permit persons to whom the Software is
16+
// furnished to do so, subject to the following conditions:
17+
//
18+
// The above copyright notice and this permission notice shall be included in all
19+
// copies or substantial portions of the Software.
20+
//
21+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27+
// SOFTWARE.
28+
29+
use core::borrow::BorrowMut;
30+
31+
use ruzstd::frame_decoder::{BlockDecodingStrategy, FrameDecoder, FrameDecoderError};
32+
use ruzstd::io::{Error, ErrorKind, Read};
33+
34+
/// High level decoder that implements a io::Read that can be used with
35+
/// io::Read::read_to_end / io::Read::read_exact or passing this to another library / module as a source for the decoded content
36+
///
37+
/// The lower level FrameDecoder by comparison allows for finer grained control but need sto have it's decode_blocks method called continously
38+
/// to decode the zstd-frame.
39+
///
40+
/// ## Caveat
41+
/// [StreamingDecoder] expects the underlying stream to only contain a single frame.
42+
/// To decode all the frames in a finite stream, the calling code needs to recreate
43+
/// the instance of the decoder
44+
/// and handle
45+
/// [crate::frame::ReadFrameHeaderError::SkipFrame]
46+
/// errors by skipping forward the `length` amount of bytes, see <https://github.com/KillingSpark/zstd-rs/issues/57>
47+
pub struct StreamingDecoder<READ: Read, DEC: BorrowMut<FrameDecoder>> {
48+
pub decoder: DEC,
49+
source: READ,
50+
}
51+
52+
impl<READ: Read, DEC: BorrowMut<FrameDecoder>> StreamingDecoder<READ, DEC> {
53+
pub fn new_with_decoder(
54+
mut source: READ,
55+
mut decoder: DEC,
56+
) -> Result<StreamingDecoder<READ, DEC>, FrameDecoderError> {
57+
decoder.borrow_mut().init(&mut source)?;
58+
Ok(StreamingDecoder { decoder, source })
59+
}
60+
}
61+
62+
impl<READ: Read> StreamingDecoder<READ, FrameDecoder> {
63+
pub fn new(
64+
mut source: READ,
65+
) -> Result<StreamingDecoder<READ, FrameDecoder>, FrameDecoderError> {
66+
let mut decoder = FrameDecoder::new();
67+
decoder.init(&mut source)?;
68+
Ok(StreamingDecoder { decoder, source })
69+
}
70+
}
71+
72+
impl<READ: Read, DEC: BorrowMut<FrameDecoder>> StreamingDecoder<READ, DEC> {
73+
/// Gets a reference to the underlying reader.
74+
pub fn get_ref(&self) -> &READ {
75+
&self.source
76+
}
77+
78+
/// Gets a mutable reference to the underlying reader.
79+
///
80+
/// It is inadvisable to directly read from the underlying reader.
81+
pub fn get_mut(&mut self) -> &mut READ {
82+
&mut self.source
83+
}
84+
85+
/// Destructures this object into the inner reader.
86+
pub fn into_inner(self) -> READ
87+
where
88+
READ: Sized,
89+
{
90+
self.source
91+
}
92+
93+
/// Destructures this object into both the inner reader and [FrameDecoder].
94+
pub fn into_parts(self) -> (READ, DEC)
95+
where
96+
READ: Sized,
97+
{
98+
(self.source, self.decoder)
99+
}
100+
101+
/// Destructures this object into the inner [FrameDecoder].
102+
pub fn into_frame_decoder(self) -> DEC {
103+
self.decoder
104+
}
105+
}
106+
107+
impl<READ: Read, DEC: BorrowMut<FrameDecoder>> Read for StreamingDecoder<READ, DEC> {
108+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
109+
let decoder = self.decoder.borrow_mut();
110+
if decoder.is_finished() && decoder.can_collect() == 0 {
111+
//No more bytes can ever be decoded
112+
return Ok(0);
113+
}
114+
115+
// need to loop. The UpToBytes strategy doesn't take any effort to actually reach that limit.
116+
// The first few calls can result in just filling the decode buffer but these bytes can not be collected.
117+
// So we need to call this until we can actually collect enough bytes
118+
119+
// TODO add BlockDecodingStrategy::UntilCollectable(usize) that pushes this logic into the decode_blocks function
120+
while decoder.can_collect() < buf.len() && !decoder.is_finished() {
121+
//More bytes can be decoded
122+
let additional_bytes_needed = buf.len() - decoder.can_collect();
123+
match decoder.decode_blocks(
124+
&mut self.source,
125+
BlockDecodingStrategy::UptoBytes(additional_bytes_needed),
126+
) {
127+
Ok(_) => { /*Nothing to do*/ }
128+
Err(e) => {
129+
let err;
130+
#[cfg(feature = "std")]
131+
{
132+
err = Error::new(ErrorKind::Other, e);
133+
}
134+
#[cfg(not(feature = "std"))]
135+
{
136+
err = Error::new(ErrorKind::Other, Box::new(e));
137+
}
138+
return Err(err);
139+
}
140+
}
141+
}
142+
143+
decoder.read(buf)
144+
}
145+
}

0 commit comments

Comments
 (0)