Skip to content

Commit acb90d7

Browse files
authored
Merge pull request #50 from Byron/edward-shen/odb-zlib-ng
Use zlib-ng by default
2 parents fb52a24 + fd73731 commit acb90d7

File tree

14 files changed

+112
-322
lines changed

14 files changed

+112
-322
lines changed

Cargo.lock

Lines changed: 33 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: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ prodash-render-line-termion = ["prodash-render-line", "prodash/render-line-termi
5757
prodash-render-tui = ["prodash/render-tui"]
5858
prodash-render-line = ["prodash/render-line"]
5959

60-
6160
[dependencies]
6261
anyhow = "1.0.31"
6362

git-odb/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ include = ["src/**/*"]
1212
doctest = false
1313

1414
[features]
15+
default = ["flate2/zlib-ng-compat"]
1516
serde1 = ["serde", "git-object/serde1"]
1617

1718
[package.metadata.docs.rs]
@@ -22,7 +23,7 @@ git-object = { version = "^0.6.0", path = "../git-object" }
2223
git-hash = { version = "^0.1.0", path = "../git-hash" }
2324
git-features = { version = "^0.11.0", path = "../git-features" }
2425

25-
miniz_oxide = "0.4.1"
26+
flate2 = { version = "1.0.17", default-features = false }
2627
smallvec = "1.3.0"
2728
filebuffer = "0.4.0"
2829
byteorder = "1.2.3"

git-odb/src/loose/db/locate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl Db {
7373
})?;
7474
(
7575
inflate
76-
.once(&compressed[..bytes_read], &mut decompressed[..], true)
76+
.once(&compressed[..bytes_read], &mut decompressed[..])
7777
.map_err(|e| Error::DecompressFile {
7878
source: e,
7979
path: path.to_owned(),

git-odb/src/loose/object/decode.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use super::stream;
2-
use crate::{loose, zlib};
1+
use crate::loose;
2+
use flate2::Decompress;
33
use git_object as object;
4-
use miniz_oxide::inflate::decompress_to_vec_zlib;
54
use object::borrowed;
65
use smallvec::SmallVec;
76
use std::{io::Read, path::PathBuf};
@@ -11,7 +10,7 @@ use std::{io::Read, path::PathBuf};
1110
#[allow(missing_docs)]
1211
pub enum Error {
1312
#[error("decompression of object data failed")]
14-
Decompress(#[from] zlib::Error),
13+
Decompress(#[from] flate2::DecompressError),
1514
#[error(transparent)]
1615
Parse(#[from] borrowed::Error),
1716
#[error("Could not {action} data at '{path}'")]
@@ -41,9 +40,9 @@ impl loose::Object {
4140
///
4241
/// **Note**: This is most useful for big blobs as these won't be read into memory in full. Use [`decode()`][loose::Object::decode()] for
4342
/// Trees, Tags and Commits instead for convenient access to their payload.
44-
pub fn stream(&mut self) -> Result<stream::Reader<'_>, Error> {
43+
pub fn stream(&mut self) -> Result<loose::object::stream::Reader<'_>, Error> {
4544
match &self.path {
46-
Some(path) => Ok(stream::Reader::from_file(
45+
Some(path) => Ok(loose::object::stream::Reader::from_file(
4746
self.header_size,
4847
std::fs::File::open(path).map_err(|source| Error::Io {
4948
source,
@@ -53,7 +52,7 @@ impl loose::Object {
5352
)),
5453
None => {
5554
self.decompress_all()?;
56-
Ok(stream::Reader::from_data(
55+
Ok(loose::object::stream::Reader::from_data(
5756
self.header_size,
5857
&self.decompressed_data.as_slice(),
5958
))
@@ -94,7 +93,9 @@ impl loose::Object {
9493
})?;
9594
self.compressed_data = SmallVec::from(buf);
9695
}
97-
self.decompressed_data = SmallVec::from(decompress_to_vec_zlib(&self.compressed_data[..]).unwrap());
96+
let mut vec = Vec::with_capacity(std::cmp::min(self.compressed_data.len() * 2, usize::MAX));
97+
Decompress::new(true).decompress_vec(&self.compressed_data[..], &mut vec, flate2::FlushDecompress::None)?;
98+
self.decompressed_data = SmallVec::from(vec);
9899
self.compressed_data = Default::default();
99100
self.decompressed_data.shrink_to_fit();
100101
assert!(self.decompressed_data.len() == total_size);

git-odb/src/pack/data/decode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ impl File {
130130
assert!(offset < self.data.len(), "entry offset out of bounds");
131131

132132
zlib::Inflate::default()
133-
.once(&self.data[offset..], out, true)
133+
.once(&self.data[offset..], out)
134134
.map_err(Into::into)
135135
.map(|(_, consumed_in, _)| consumed_in)
136136
}

git-odb/src/pack/data/iter.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
use crate::{
2-
hash, pack,
3-
zlib::stream::inflate::{Inflate, InflateReaderBoxed},
4-
};
1+
use crate::{hash, pack, zlib::stream::inflate::InflateReaderBoxed};
2+
use flate2::Decompress;
53
use git_features::hash::Sha1;
64
use git_object::owned;
75
use std::{fs, io};
@@ -16,6 +14,8 @@ pub enum Error {
1614
PackParse(#[from] pack::data::parse::Error),
1715
#[error("pack checksum in trailer was {expected}, but actual checksum was {actual}")]
1816
ChecksumMismatch { expected: owned::Id, actual: owned::Id },
17+
#[error("pack is incomplete: it was decompressed into {actual} bytes but {expected} bytes where expected.")]
18+
IncompletePack { actual: u64, expected: u64 },
1919
}
2020

2121
/// An item of the iteration produced by [`Iter`]
@@ -51,7 +51,7 @@ pub struct Entry {
5151
/// The iterator used as part of [Bundle::write_stream_to_directory(…)][pack::Bundle::write_stream_to_directory()].
5252
pub struct Iter<R> {
5353
read: R,
54-
decompressor: Option<Box<Inflate>>,
54+
decompressor: Option<Box<Decompress>>,
5555
offset: u64,
5656
had_error: bool,
5757
kind: pack::data::Version,
@@ -183,9 +183,12 @@ where
183183
.map_err(Error::from)?;
184184

185185
// Decompress object to learn it's compressed bytes
186-
let mut decompressor = self.decompressor.take().unwrap_or_default();
186+
let mut decompressor = self
187+
.decompressor
188+
.take()
189+
.unwrap_or_else(|| Box::new(Decompress::new(true)));
187190
let compressed_buf = self.compressed_buf.take().unwrap_or_else(|| Vec::with_capacity(4096));
188-
decompressor.reset();
191+
decompressor.reset(true);
189192
let mut decompressed_reader = InflateReaderBoxed {
190193
inner: read_and_pass_to(
191194
&mut self.read,
@@ -199,14 +202,15 @@ where
199202
};
200203

201204
let bytes_copied = io::copy(&mut decompressed_reader, &mut io::sink())?;
202-
debug_assert_eq!(
203-
bytes_copied, entry.decompressed_size,
204-
"We should have decompressed {} bytes, but got {} instead",
205-
entry.decompressed_size, bytes_copied
206-
);
205+
if bytes_copied != entry.decompressed_size {
206+
return Err(Error::IncompletePack {
207+
actual: bytes_copied,
208+
expected: entry.decompressed_size,
209+
});
210+
}
207211

208212
let pack_offset = self.offset;
209-
let compressed_size = decompressed_reader.decompressor.total_in;
213+
let compressed_size = decompressed_reader.decompressor.total_in();
210214
self.offset += entry.header_size() as u64 + compressed_size;
211215
self.decompressor = Some(decompressed_reader.decompressor);
212216

git-odb/src/pack/tree/traverse/resolve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ fn decompress_all_at_once(b: &[u8], decompressed_len: usize) -> Result<Vec<u8>,
105105
let mut out = Vec::new();
106106
out.resize(decompressed_len, 0);
107107
zlib::Inflate::default()
108-
.once(&b, &mut out, true)
108+
.once(&b, &mut out)
109109
.map_err(|err| Error::ZlibInflate {
110110
source: err,
111111
message: "Failed to decompress entry",

git-odb/src/zlib/mod.rs

Lines changed: 14 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,39 @@
1-
use miniz_oxide::{
2-
inflate::core::DecompressorOxide,
3-
inflate::{
4-
core::inflate_flags::{
5-
TINFL_FLAG_HAS_MORE_INPUT, TINFL_FLAG_PARSE_ZLIB_HEADER, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF,
6-
},
7-
TINFLStatus,
8-
},
9-
};
1+
use flate2::Decompress;
102

113
#[derive(thiserror::Error, Debug)]
124
pub enum Error {
135
#[error("Could not write all bytes when decompressing content")]
146
WriteInflated(#[from] std::io::Error),
157
#[error("Could not decode zip stream, status was '{0:?}'")]
16-
Inflate(miniz_oxide::inflate::TINFLStatus),
8+
Inflate(#[from] flate2::DecompressError),
179
}
1810

1911
/// Decompress a few bytes of a zlib stream without allocation
2012
pub struct Inflate {
21-
state: DecompressorOxide,
13+
state: Decompress,
2214
pub is_done: bool,
2315
}
2416

2517
impl Default for Inflate {
2618
fn default() -> Self {
2719
Inflate {
28-
state: DecompressorOxide::default(),
20+
state: Decompress::new(true),
2921
is_done: false,
3022
}
3123
}
3224
}
3325

3426
impl Inflate {
35-
/// Run the decompressor exactly once. Cannot be run mutliple times
36-
pub fn once(
37-
&mut self,
38-
input: &[u8],
39-
out: &mut [u8],
40-
parse_header: bool,
41-
) -> Result<(TINFLStatus, usize, usize), Error> {
42-
let (status, in_consumed, out_consumed) = miniz_oxide::inflate::core::decompress(
43-
&mut self.state,
44-
input,
45-
out,
46-
0,
47-
if parse_header { TINFL_FLAG_PARSE_ZLIB_HEADER } else { 0 }
48-
| TINFL_FLAG_HAS_MORE_INPUT
49-
| TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF,
50-
);
51-
52-
use miniz_oxide::inflate::TINFLStatus::*;
53-
match status {
54-
Failed | FailedCannotMakeProgress | BadParam | Adler32Mismatch => return Err(Error::Inflate(status)),
55-
HasMoreOutput | NeedsMoreInput => {}
56-
Done => {
57-
self.is_done = true;
58-
}
59-
};
60-
Ok((status, in_consumed, out_consumed))
27+
/// Run the decompressor exactly once. Cannot be run multiple times
28+
pub fn once(&mut self, input: &[u8], out: &mut [u8]) -> Result<(flate2::Status, usize, usize), Error> {
29+
let before_in = self.state.total_in();
30+
let before_out = self.state.total_out();
31+
let status = self.state.decompress(input, out, flate2::FlushDecompress::None)?;
32+
Ok((
33+
status,
34+
(self.state.total_in() - before_in) as usize,
35+
(self.state.total_out() - before_out) as usize,
36+
))
6137
}
6238
}
6339

0 commit comments

Comments
 (0)