Skip to content

Commit d6b3384

Browse files
authored
Merge pull request #63 from jonhoo/serialization-compat
Fix compression format: needs to have the zlib header around deflate.
2 parents 6f42083 + baac1c2 commit d6b3384

File tree

8 files changed

+100151
-4
lines changed

8 files changed

+100151
-4
lines changed

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ flate2 = { version = "0.2.17", optional = true }
3636
rand = "0.3.15"
3737
rug = "0.6.0"
3838
ieee754 = "0.2.2"
39+
clap = "2.26.2"
3940

4041
[lib]
4142
path = "src/lib.rs"
@@ -45,3 +46,7 @@ debug=true
4546

4647
[profile.bench]
4748
debug=true
49+
50+
[[example]]
51+
name = "cli"
52+
required-features = ["serialization"]

examples/cli.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/// Reads numbers from stdin, one per line, and writes them to a serialized histogram on stdout.
2+
3+
extern crate hdrsample;
4+
extern crate clap;
5+
6+
use std::io::BufRead;
7+
8+
use clap::{App, Arg, SubCommand};
9+
10+
use hdrsample::Histogram;
11+
use hdrsample::serialization::{V2Serializer, V2DeflateSerializer};
12+
13+
fn main() {
14+
let default_max = format!("{}", u64::max_value());
15+
let matches = App::new("hdrsample cli")
16+
.subcommand(SubCommand::with_name("serialize")
17+
.arg(Arg::with_name("min")
18+
.long("min")
19+
.help("Minimum discernible value")
20+
.takes_value(true)
21+
.default_value("1"))
22+
.arg(Arg::with_name("max")
23+
.long("max")
24+
.help("Maximum trackable value")
25+
.takes_value(true)
26+
.default_value(default_max.as_str()))
27+
.arg(Arg::with_name("sigfig")
28+
.long("sigfig")
29+
.help("Number of significant digits")
30+
.takes_value(true)
31+
.default_value("3"))
32+
.arg(Arg::with_name("compression")
33+
.short("c")
34+
.long("compression")
35+
.help("Enable compression"))
36+
.arg(Arg::with_name("resize")
37+
.short("r")
38+
.long("resize")
39+
.help("Enable auto resize")))
40+
.get_matches();
41+
42+
match matches.subcommand_name() {
43+
Some("serialize") => {
44+
let sub_matches = matches.subcommand_matches("serialize").unwrap();
45+
let min = sub_matches.value_of("min").unwrap().parse().unwrap();
46+
let max = sub_matches.value_of("max").unwrap().parse().unwrap();
47+
let sigfig = sub_matches.value_of("sigfig").unwrap().parse().unwrap();
48+
49+
let mut h: Histogram<u64> = Histogram::new_with_bounds(min, max, sigfig).unwrap();
50+
51+
if sub_matches.is_present("resize") {
52+
h.auto(true);
53+
}
54+
55+
serialize(h, sub_matches.is_present("compression"));
56+
},
57+
_ => unreachable!()
58+
}
59+
}
60+
61+
fn serialize(mut h: Histogram<u64>, compression: bool) {
62+
let stdin = std::io::stdin();
63+
let stdin_handle = stdin.lock();
64+
65+
for num in stdin_handle.lines()
66+
.map(|l| l.expect("Should be able to read stdin"))
67+
.map(|s| s.parse().expect("Each line must be a u64")) {
68+
h.record(num).unwrap();
69+
}
70+
71+
let stdout = std::io::stdout();
72+
let mut stdout_handle = stdout.lock();
73+
74+
if compression {
75+
V2DeflateSerializer::new().serialize(&h, &mut stdout_handle).unwrap();
76+
} else {
77+
V2Serializer::new().serialize(&h, &mut stdout_handle).unwrap();
78+
}
79+
}

src/serialization/deserializer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::io::{self, Cursor, ErrorKind, Read};
55
use std::marker::PhantomData;
66
use std;
77
use super::byteorder::{BigEndian, ReadBytesExt};
8-
use super::flate2::read::DeflateDecoder;
8+
use super::flate2::read::ZlibDecoder;
99

1010
/// Errors that can happen during deserialization.
1111
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
@@ -70,7 +70,7 @@ impl Deserializer {
7070
.ok_or(DeserializeError::UsizeTypeTooSmall)?;
7171

7272
// TODO reuse deflate buf, or switch to lower-level flate2::Decompress
73-
let mut deflate_reader = DeflateDecoder::new(reader.take(payload_len as u64));
73+
let mut deflate_reader = ZlibDecoder::new(reader.take(payload_len as u64));
7474
let inner_cookie = deflate_reader.read_u32::<BigEndian>()?;
7575
if inner_cookie != V2_COOKIE {
7676
return Err(DeserializeError::InvalidCookie);

src/serialization/v2_deflate_serializer.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::byteorder::{BigEndian, WriteBytesExt};
55
use super::flate2::Compression;
66
use std;
77
use std::io::{ErrorKind, Write};
8-
use super::flate2::write::DeflateEncoder;
8+
use super::flate2::write::ZlibEncoder;
99

1010
/// Errors that occur during serialization.
1111
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
@@ -23,6 +23,9 @@ impl std::convert::From<std::io::Error> for V2DeflateSerializeError {
2323
}
2424

2525
/// Serializer for the V2 + DEFLATE binary format.
26+
///
27+
/// It's called "deflate" to stay consistent with the naming used in the Java implementation, but
28+
/// it actually uses zlib's wrapper format around plain DEFLATE.
2629
pub struct V2DeflateSerializer {
2730
uncompressed_buf: Vec<u8>,
2831
compressed_buf: Vec<u8>,
@@ -76,7 +79,7 @@ impl V2DeflateSerializer {
7679

7780
{
7881
// TODO reuse deflate buf, or switch to lower-level flate2::Compress
79-
let mut compressor = DeflateEncoder::new(&mut self.compressed_buf, Compression::Default);
82+
let mut compressor = ZlibEncoder::new(&mut self.compressed_buf, Compression::Default);
8083
compressor.write_all(&self.uncompressed_buf[0..uncompressed_len])?;
8184
let _ = compressor.finish()?;
8285
}

tests/data/seq-nums.hist

8.09 KB
Binary file not shown.

tests/data/seq-nums.histz

86 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)