-
Notifications
You must be signed in to change notification settings - Fork 618
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pure Rust lib for zlib #419
Comments
It does not seem to be so trivial. There are three independent Rust zlib inflaters I know of:
They all work ok for some images but they all fail for the examples given in #300 and #376. They are working fine using flate2. |
I'm going to try tackling this by writing a very clean implementation and lots of unit tests. |
That would be great! If you’re interested, I ported the third decoder to the latest nightly: https://gist.github.com/nwin/d874ae14f1c5804b93c6 this one is most promising as it allows to stream data. |
@nwin Whoa, thanks, I didn't expect that code to live on. |
@eddyb don’t be surprised, that particular version takes one minute to compile, due to a regression in rustc |
@nwin hehe it's not a regression, it always took very long to compile. That's what you get for abusing macros to get zlib's performance. |
@eddyb It is unfortunately. :( rust-lang/rust#25069 The version posted there compiles a bit faster because I added some more type annotation which I didn’t add here to be sure I didn’t make a mistake. |
I started https://github.com/tomaka/flate3 Since I'm not familiar with the PNG format, could someone extract the zlib data from #300 and #376 so that I can test it? (hopefully it's not too hard to do) |
@tomaka This is my test for #300: #![feature(box_patterns, core)]
extern crate flate2;
mod inflate;
use std::fs;
use std::io::prelude::*;
use flate2::FlateReadExt;
fn main() {
let idat_offset = 0x7a;
let idat_size = 0x3f64;
let mut data = vec![];
fs::File::open("test1.png").unwrap().read_to_end(&mut data).unwrap();
let data = &data[idat_offset..][..idat_size];
let mut flate2 = vec![];
if let Err(e) = data.zlib_decode().read_to_end(&mut flate2) {
println!("flate2 failed: {}", e);
}
let mut inflate = vec![];
{
let mut inflate_stream = inflate::InflateStream::from_zlib();
let mut data = data;
while !data.is_empty() {
let (used, out) = inflate_stream.update(data).unwrap();
data = &data[used..];
inflate.extend(out.iter().cloned());
}
}
println!("{} vs {}", flate2.len(), inflate.len());
for i in 0..flate2.len() {
if flate2[i] != inflate[i] {
panic!("found mismatch at offset 0x{:x}: {:02x} vs {:02x}", i, flate2[i], inflate[i]);
}
}
}
You should be able to get the respective offset/size pair from any PNG file with just a hex editor. |
You can use the example "pngcheck" of https://github.com/nwin/png to get these offsets (you’ll have to add 4 to it). Just call it with |
@eddyb made a tremendous effort to fix the remaining bugs in his inflate implementation. Impressive work! Chances are good that there are no mayor bug left as it is able to decode the whole pngsuite properly. I’ll probably do some fuzzing on it before merging it into image. |
What's the status? |
@jonas-schievink to my knowledge there is no update on this. |
Someone also made a full rust port of miniz.c, it seems inactive now, but maybe it could be a starting point. |
@oyvindln I took a look at it (since I just stated doing the exact same thing - porting miniz.c to Rust), and it uses (x86-only?) inline assembly to implement the decoding - miniz.c uses coroutines implemented with C macros and some switch-construction akin to Duff's device (this pattern is probably well-known among C programmers), so that looks like it'd be a non-starter. The bad thing is that (I begin to feel like every single deflate implementation in Rust is cursed - there are so many, yet not a single one that satisfies many use cases or is bug free) |
Indeed, the linked port is not very idiomatic rust. Maybe starting a rust implementation from scratch and focusing on safety and correctness first before venturing into low-level optimisation is the better approach. In any case I'm interested in working on this issue, but I'm not quite sure where to start seeing as there are a number of inactive half-finished attempts at implementing zlib in rust. |
@nwin Not sure what you mean, but I believe the updated inflate code lives at https://github.com/PistonDevelopers/inflate. |
Heh, so apparently |
@eddyb this discussion was about de- and encoding and I was assuming that @jonas-schievink was asking if there was any update to the encoding part. |
Is this the reason for the dependency on GCC or was that bug introduced some other way? |
I think it is Kyle Ladd notifications@github.com schrieb am Sa., 18. Juni 2016, 16:45:
|
So in case there is still interest in this, I've now got a pretty functional deflate encoder written in rust up and running here: https://crates.io/crates/deflate Then there is also https://crates.io/crates/zopfli if you want a very high level of compression not achievable using the normal deflate encoders. |
@oyvindln That's great! |
Current status:
I think we can close this issue ? |
There are many people interested in this, so I'm opening this issue for discussion. The PR #418 replaces the Rust implementation, which currently has some bugs, with flate2.
The text was updated successfully, but these errors were encountered: