From f20bb27c257df2c76a5d1f72fede7268be133c76 Mon Sep 17 00:00:00 2001 From: kraktus Date: Thu, 9 Nov 2023 13:59:06 +0100 Subject: [PATCH 1/7] fix typo --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 0ba7d6f..f781d4b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,7 +80,7 @@ use bit_vec::BitVec; use num_traits::ops::saturating::Saturating; -/// A trie used for decoding. +/// A tree used for decoding. #[derive(Debug, Clone)] pub struct Tree { root: usize, From 68917a60940dc1250540d49fdbba5e787de8d41d Mon Sep 17 00:00:00 2001 From: kraktus Date: Thu, 9 Nov 2023 14:00:38 +0100 Subject: [PATCH 2/7] add 2021 edition --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 0a0106d..572dca4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ readme = "README.md" repository = "https://github.com/niklasf/rust-huffman-compress" categories = ["compression", "encoding", "algorithms"] description = "Huffman compression given a probability distribution over arbitrary symbols" +edition = "2021" [[bench]] name = "benches" From 702b541d8c3bcdc8e68d0a660d7b4a8829b9e3b5 Mon Sep 17 00:00:00 2001 From: kraktus Date: Fri, 10 Nov 2023 11:24:46 +0100 Subject: [PATCH 3/7] update imports --- src/lib.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f781d4b..4941e8e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,7 +17,7 @@ //! //! # use std::error::Error; //! # -//! # fn try_main() -> Result<(), Box> { +//! # fn try_main() -> Result<(), Box> { //! use std::iter::FromIterator; //! use std::collections::HashMap; //! use bit_vec::BitVec; @@ -61,13 +61,6 @@ #![deny(missing_docs)] #![deny(missing_debug_implementations)] -extern crate bit_vec; -extern crate num_traits; - -#[cfg(test)] -#[macro_use] -extern crate quickcheck; - use std::borrow::Borrow; use std::cmp; use std::cmp::Reverse; @@ -469,6 +462,7 @@ where #[cfg(test)] mod tests { use super::*; + use quickcheck::quickcheck; use std::collections::HashMap; #[test] From 923f0fe47783678f39b1e5f7e7a10dd88a4eaf3b Mon Sep 17 00:00:00 2001 From: kraktus Date: Fri, 10 Nov 2023 16:15:55 +0100 Subject: [PATCH 4/7] migrate to criterion --- Cargo.toml | 2 +- benches/benches.rs | 35 ++++++++++++++++------------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 572dca4..29de7c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ bit-vec = "0.6" num-traits = "0.2" [dev-dependencies] -bencher = "0.1" +criterion = "0.5" quickcheck = "1" [badges] diff --git a/benches/benches.rs b/benches/benches.rs index e946df1..56de3d4 100644 --- a/benches/benches.rs +++ b/benches/benches.rs @@ -1,14 +1,9 @@ -#[macro_use] -extern crate bencher; -extern crate bit_vec; -extern crate huffman_compress; - -use bencher::{black_box, Bencher}; use bit_vec::BitVec; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; use huffman_compress::codebook; use std::collections::HashMap; -fn bench_encode_decode(b: &mut Bencher) { +fn bench_encode_decode(c: &mut Criterion) { let mut weights = HashMap::new(); weights.insert("CG", 293); weights.insert("AG", 34); @@ -20,19 +15,21 @@ fn bench_encode_decode(b: &mut Bencher) { let example = black_box(vec!["AT", "CG", "AT", "TG", "AG", "CT", "CT", "AG", "CG"]); - b.iter(|| { - let mut buffer = BitVec::new(); - for symbol in &example { - book.encode(&mut buffer, symbol).unwrap(); - } - - assert!(example - .iter() - .zip(tree.unbounded_decoder(&buffer)) - .all(|(l, r)| l == &r)); + c.bench_function("encode-decode", |b| { + b.iter(|| { + let mut buffer = BitVec::new(); + for symbol in &example { + book.encode(&mut buffer, symbol).unwrap(); + } + + assert!(example + .iter() + .zip(tree.unbounded_decoder(&buffer)) + .all(|(l, r)| l == &r)); + }) }); } -benchmark_group!(benches, bench_encode_decode); +criterion_group!(benches, bench_encode_decode); -benchmark_main!(benches); +criterion_main!(benches); From 776c84f1274e329f79e29c4f41d930733312e694 Mon Sep 17 00:00:00 2001 From: kraktus Date: Fri, 10 Nov 2023 16:23:09 +0100 Subject: [PATCH 5/7] clippy --fix --- src/lib.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4941e8e..3f02833 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,6 +60,7 @@ #![forbid(unsafe_code)] #![deny(missing_docs)] #![deny(missing_debug_implementations)] +#![warn(clippy::pedantic)] use std::borrow::Borrow; use std::cmp; @@ -174,6 +175,7 @@ pub struct Book { impl Book { /// Returns the underlying B-Tree. + #[must_use] pub fn into_inner(self) -> BTreeMap { self.book } @@ -189,11 +191,13 @@ impl Book { } /// Returns the number of symbols in the book. + #[must_use] pub fn len(&self) -> usize { self.book.len() } /// Returns true if the map has no symbols. + #[must_use] pub fn is_empty(&self) -> bool { self.book.is_empty() } @@ -296,6 +300,7 @@ pub struct CodeBuilder { impl CodeBuilder { /// Creates a new, empty `CodeBuilder`. + #[must_use] pub fn new() -> CodeBuilder { CodeBuilder { heap: BinaryHeap::new(), @@ -305,6 +310,7 @@ impl CodeBuilder { /// Creates a new, empty `CodeBuilder` and preallocates space /// for `capacity` symbols. + #[must_use] pub fn with_capacity(capacity: usize) -> CodeBuilder { CodeBuilder { heap: BinaryHeap::with_capacity(capacity), @@ -328,6 +334,7 @@ impl CodeBuilder { /// Constructs a [book](struct.Book.html) and [tree](struct.Tree.html) pair /// for encoding and decoding. + #[must_use] pub fn finish(mut self) -> (Book, Tree) { let mut book = Book::new(); @@ -494,7 +501,7 @@ mod tests { #[test] fn test_uniform_from_static() { const WEIGHTS: &[(&char, &usize)] = &[(&'a', &1), (&'b', &1), (&'c', &1), (&'d', &1)]; - let (book, tree) = codebook(WEIGHTS.iter().cloned()); + let (book, tree) = codebook(WEIGHTS.iter().copied()); let mut buffer = BitVec::new(); book.encode(&mut buffer, &'a').unwrap(); @@ -546,7 +553,7 @@ mod tests { let (book, _) = builder.finish(); let len = |symbol| { - book.get(symbol).map_or(0, |code| code.len()) + book.get(symbol).map_or(0, bit_vec::BitVec::len) }; at >= ct || len("CT") <= len("AT") || From 8fc5ceaa69f8e21e3328e2d99037c82cbfcda994 Mon Sep 17 00:00:00 2001 From: kraktus Date: Fri, 10 Nov 2023 16:38:46 +0100 Subject: [PATCH 6/7] code golf --- src/lib.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3f02833..9340f6a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -147,19 +147,16 @@ impl<'a, K: Clone, I: IntoIterator> Iterator for UnboundedDecoder<' type Item = K; fn next(&mut self) -> Option { - let mut node = match self.tree.arena.get(self.tree.root) { - Some(root) => root, - None => return None, // empty tree - }; + let mut node = self.tree.arena.get(self.tree.root)?; loop { match node.data { NodeData::Leaf { ref symbol } => return Some(symbol.clone()), NodeData::Branch { left, right } => { - node = match self.iter.next() { - Some(true) => &self.tree.arena[left], - Some(false) => &self.tree.arena[right], - None => return None, + node = if self.iter.next()? { + &self.tree.arena[left] + } else { + &self.tree.arena[right] }; } } From ff85195e89d3495fb89f41aaeb500c5464e45316 Mon Sep 17 00:00:00 2001 From: kraktus Date: Fri, 10 Nov 2023 17:17:51 +0100 Subject: [PATCH 7/7] finish fixing clippy lints, add changelog and codegolf --- README.md | 3 +++ src/lib.rs | 12 ++++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e9bd7ed..651e967 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,9 @@ Documentation Changelog --------- +* to be released + - Switch to 2021 edition. + * 0.6.1 - Fix deprecation warning and remove `#[deny(warnings)]` (a future compatibility hazard in libraries). diff --git a/src/lib.rs b/src/lib.rs index 9340f6a..4e85b10 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,6 +61,7 @@ #![deny(missing_docs)] #![deny(missing_debug_implementations)] #![warn(clippy::pedantic)] +#![allow(clippy::manual_let_else)] use std::borrow::Borrow; use std::cmp; @@ -229,12 +230,7 @@ impl Book { K: Borrow, Q: Ord, { - match self.book.get(k) { - Some(code) => buffer.extend(code), - None => return Err(EncodeError {}), - } - - Ok(()) + self.book.get(k).map(|code| buffer.extend(code)).ok_or(EncodeError {}) } fn new() -> Book { @@ -422,7 +418,7 @@ impl<'a, K: Ord + Clone, W: Saturating + Ord + Clone> FromIterator<(&'a K, &'a W where T: IntoIterator, { - CodeBuilder::from_iter(weights.into_iter().map(|(k, v)| (k.clone(), v.clone()))) + weights.into_iter().map(|(k, v)| (k.clone(), v.clone())).collect() } } @@ -554,7 +550,7 @@ mod tests { }; at >= ct || len("CT") <= len("AT") || - ag.saturating_add(at).saturating_add(cg).saturating_add(ct).saturating_add(tg) >= u32::MAX + ag.saturating_add(at).saturating_add(cg).saturating_add(ct).saturating_add(tg) == u32::MAX } fn encode_decode_bytes(symbols: Vec) -> bool {