From 0a3f400e92296b3dade6ff1995d183b8dec1d997 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 11 May 2024 23:16:41 +0200 Subject: [PATCH] add rest of compression algorithms --- Cargo.lock | 110 +++++++++++++++++++++++++ Cargo.toml | 13 ++- examples/Cargo.lock | 104 +++++++++++++++++++++++ examples/announce/Cargo.toml | 2 +- examples/game_of_life/Cargo.toml | 2 +- examples/moving_line/Cargo.toml | 2 +- examples/random_brightness/Cargo.toml | 2 +- examples/random_brightness/src/main.rs | 1 - examples/wiping_clear/src/main.rs | 4 +- src/command.rs | 43 +--------- src/command_codes.rs | 4 + src/compression.rs | 103 +++++++++++++++++++++++ src/lib.rs | 1 + 13 files changed, 342 insertions(+), 49 deletions(-) create mode 100644 src/compression.rs diff --git a/Cargo.lock b/Cargo.lock index 64c50d4..1fbdff1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,6 +14,38 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +dependencies = [ + "jobserver", + "libc", + "once_cell", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -39,12 +71,47 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "jobserver" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +dependencies = [ + "libc", +] + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + [[package]] name = "log" version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +[[package]] +name = "lz4" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" +dependencies = [ + "libc", + "lz4-sys", +] + +[[package]] +name = "lz4-sys" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "miniz_oxide" version = "0.7.2" @@ -138,6 +205,18 @@ dependencies = [ "autocfg", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + [[package]] name = "proc-macro2" version = "1.0.82" @@ -160,11 +239,14 @@ dependencies = [ name = "servicepoint2" version = "0.1.0" dependencies = [ + "bzip2", "flate2", "log", + "lz4", "num", "num-derive", "num-traits", + "zstd", ] [[package]] @@ -183,3 +265,31 @@ name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "zstd" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.10+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index cc26ab8..e7ed4de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,15 @@ num = "0.4" num-derive = "0.4" num-traits = "0.2" log = "0.4" -flate2 = "1.0" +flate2 = { version = "1.0", optional = true } +bzip2 = { version = "0.4", optional = true } +lz4 = { version = "1.24", optional = true } +zstd = { version = "0.13", optional = true } + +[features] +default = ["compression-gz", "compression-bz", "compression-lz", "compression-zs"] +compression-gz = ["dep:flate2"] +compression-bz = ["dep:bzip2"] +compression-lz = ["dep:lz4"] +compression-zs = ["dep:zstd"] + diff --git a/examples/Cargo.lock b/examples/Cargo.lock index 2f2338a..346ad30 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -82,6 +82,38 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +dependencies = [ + "jobserver", + "libc", + "once_cell", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -216,6 +248,15 @@ version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +[[package]] +name = "jobserver" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +dependencies = [ + "libc", +] + [[package]] name = "libc" version = "0.2.154" @@ -228,6 +269,26 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +[[package]] +name = "lz4" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" +dependencies = [ + "libc", + "lz4-sys", +] + +[[package]] +name = "lz4-sys" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "memchr" version = "2.7.2" @@ -337,6 +398,18 @@ dependencies = [ "autocfg", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -435,11 +508,14 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" name = "servicepoint2" version = "0.1.0" dependencies = [ + "bzip2", "flate2", "log", + "lz4", "num", "num-derive", "num-traits", + "zstd", ] [[package]] @@ -559,3 +635,31 @@ dependencies = [ "log", "servicepoint2", ] + +[[package]] +name = "zstd" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.10+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/examples/announce/Cargo.toml b/examples/announce/Cargo.toml index fbbf365..044d137 100644 --- a/examples/announce/Cargo.toml +++ b/examples/announce/Cargo.toml @@ -6,6 +6,6 @@ publish = false [dependencies] clap = { version = "4.5.4", features = ["derive"] } -servicepoint2 = { path = "../.." } +servicepoint2 = { path = "../.." , default-features = false } log = "0.4.21" env_logger = "0.11.3" diff --git a/examples/game_of_life/Cargo.toml b/examples/game_of_life/Cargo.toml index 16b8aa1..ee9f8e8 100644 --- a/examples/game_of_life/Cargo.toml +++ b/examples/game_of_life/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" publish = false [dependencies] -servicepoint2 = { path = "../.." } +servicepoint2 = { path = "../.." , default-features = false } rand = "0.8.5" clap = { version = "4.5.4", features = ["derive"] } log = "0.4.21" diff --git a/examples/moving_line/Cargo.toml b/examples/moving_line/Cargo.toml index 2f87a32..1d49a52 100644 --- a/examples/moving_line/Cargo.toml +++ b/examples/moving_line/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" publish = false [dependencies] -servicepoint2 = { path = "../.." } +servicepoint2 = { path = "../.." , default-features = false } clap = { version = "4.5.4", features = ["derive"] } env_logger = "0.11.3" log = "0.4.21" \ No newline at end of file diff --git a/examples/random_brightness/Cargo.toml b/examples/random_brightness/Cargo.toml index 5b6fe63..75025bc 100644 --- a/examples/random_brightness/Cargo.toml +++ b/examples/random_brightness/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" publish = false [dependencies] -servicepoint2 = { path = "../.." } +servicepoint2 = { path = "../.." , default-features = false } clap = { version = "4.5.4", features = ["derive"] } rand = "0.8.5" env_logger = "0.11.3" diff --git a/examples/random_brightness/src/main.rs b/examples/random_brightness/src/main.rs index 209d918..112edc2 100644 --- a/examples/random_brightness/src/main.rs +++ b/examples/random_brightness/src/main.rs @@ -1,4 +1,3 @@ -use std::cmp::Ord; use std::time::Duration; use clap::Parser; use rand::Rng; diff --git a/examples/wiping_clear/src/main.rs b/examples/wiping_clear/src/main.rs index 1310c5f..67f4c1a 100644 --- a/examples/wiping_clear/src/main.rs +++ b/examples/wiping_clear/src/main.rs @@ -15,9 +15,7 @@ struct Cli { } fn main() { - env_logger::builder() - .filter_level(log::LevelFilter::Debug) - .init(); + env_logger::init(); let cli = Cli::parse(); let connection = Connection::open(cli.destination).unwrap(); diff --git a/src/command.rs b/src/command.rs index b688ed3..f126d0b 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,9 +1,7 @@ -use std::io::Read; -use flate2::bufread::GzEncoder; -use flate2::Compression; -use flate2::read::GzDecoder; -use crate::{BitVec, ByteGrid, Header, Packet, Payload, PixelGrid, TILE_SIZE}; +use crate::{BitVec, ByteGrid, Header, Packet, PixelGrid, TILE_SIZE}; use crate::command_codes::{CommandCode, CompressionCode}; +use crate::compression::{into_compressed, into_decompressed}; + /// An origin marks the top left position of the /// data sent to the display. @@ -239,38 +237,3 @@ fn packet_into_linear_bitmap(packet: Packet) -> Result<(BitVec, CompressionCode) }; Ok((BitVec::load(&payload), sub)) } - -fn into_decompressed(kind: CompressionCode, payload: Payload) -> Option { - match kind { - CompressionCode::None => Some(payload), - CompressionCode::Gz => { - let mut decoder = GzDecoder::new(&*payload); - let mut decompressed = vec!(); - match decoder.read_to_end(&mut decompressed) { - Err(_) => None, - Ok(_) => Some(decompressed) - } - } - CompressionCode::Bz => todo!(), - CompressionCode::Lz => todo!(), - CompressionCode::Zs => todo!(), - } -} - -fn into_compressed(kind: CompressionCode, payload: Payload) -> Payload { - match kind { - CompressionCode::None => payload, - CompressionCode::Gz => { - let mut encoder = GzEncoder::new(&*payload, Compression::best()); - let mut compressed = vec!(); - match encoder.read_to_end(&mut compressed) { - Err(err) => panic!("could not compress payload: {}", err), - Ok(_) => compressed, - } - } - CompressionCode::Bz => todo!(), - CompressionCode::Lz => todo!(), - CompressionCode::Zs => todo!(), - } -} - diff --git a/src/command_codes.rs b/src/command_codes.rs index 023aa8e..7048348 100644 --- a/src/command_codes.rs +++ b/src/command_codes.rs @@ -33,9 +33,13 @@ impl CommandCode { #[derive(Debug, FromPrimitive, ToPrimitive, Clone, Copy)] pub enum CompressionCode { None = 0x0, + #[cfg(feature = "compression-gz")] Gz = 0x677a, + #[cfg(feature = "compression-bz")] Bz = 0x627a, + #[cfg(feature = "compression-lz")] Lz = 0x6c7a, + #[cfg(feature = "compression-zs")] Zs = 0x7a73, } diff --git a/src/compression.rs b/src/compression.rs new file mode 100644 index 0000000..3798575 --- /dev/null +++ b/src/compression.rs @@ -0,0 +1,103 @@ +use crate::{CompressionCode, Payload}; +use std::io::{Read, Write}; + +#[cfg(feature = "compression-bz")] +use bzip2::read::{BzEncoder, BzDecoder}; +#[cfg(feature = "compression-gz")] +use flate2::read::{GzEncoder, GzDecoder}; +#[cfg(feature = "compression-lz")] +use lz4::{EncoderBuilder as Lz4EncoderBuilder, Decoder as Lz4Decoder}; +#[cfg(feature = "compression-zs")] +use zstd::{Encoder as ZstdEncoder, Decoder as ZstdDecoder}; + +pub(crate) fn into_decompressed(kind: CompressionCode, payload: Payload) -> Option { + match kind { + CompressionCode::None => Some(payload), + #[cfg(feature = "compression-gz")] + CompressionCode::Gz => { + let mut decoder = GzDecoder::new(&*payload); + let mut decompressed = vec!(); + match decoder.read_to_end(&mut decompressed) { + Err(_) => None, + Ok(_) => Some(decompressed) + } + } + #[cfg(feature = "compression-bz")] + CompressionCode::Bz => { + let mut decoder = BzDecoder::new(&*payload); + let mut decompressed = vec!(); + match decoder.read_to_end(&mut decompressed) { + Err(_) => None, + Ok(_) => Some(decompressed) + } + } + #[cfg(feature = "compression-lz")] + CompressionCode::Lz => { + let mut decoder = match Lz4Decoder::new(&*payload) { + Err(_) => return None, + Ok(value) => value + }; + let mut decompressed = vec!(); + match decoder.read_to_end(&mut decompressed) { + Err(_) => None, + Ok(_) => Some(decompressed) + } + } + #[cfg(feature = "compression-zs")] + CompressionCode::Zs => { + let mut decoder = match ZstdDecoder::new(&*payload) { + Err(_) => return None, + Ok(value) => value + }; + let mut decompressed = vec!(); + match decoder.read_to_end(&mut decompressed) { + Err(_) => None, + Ok(_) => Some(decompressed) + } + } + } +} + +pub(crate) fn into_compressed(kind: CompressionCode, payload: Payload) -> Payload { + match kind { + CompressionCode::None => payload, + #[cfg(feature = "compression-gz")] + CompressionCode::Gz => { + let mut encoder = GzEncoder::new(&*payload, flate2::Compression::fast()); + let mut compressed = vec!(); + match encoder.read_to_end(&mut compressed) { + Err(err) => panic!("could not compress payload: {}", err), + Ok(_) => compressed, + } + } + #[cfg(feature = "compression-bz")] + CompressionCode::Bz => { + let mut encoder = BzEncoder::new(&*payload, bzip2::Compression::fast()); + let mut compressed = vec!(); + match encoder.read_to_end(&mut compressed) { + Err(err) => panic!("could not compress payload: {}", err), + Ok(_) => compressed, + } + } + #[cfg(feature = "compression-lz")] + CompressionCode::Lz => { + let mut encoder = Lz4EncoderBuilder::new() + .build(vec!()) + .expect("could not create encoder"); + encoder.write(&*payload) + .expect("could not write payload"); + let (payload, _) = encoder.finish(); + payload + } + #[cfg(feature = "compression-zs")] + CompressionCode::Zs => { + let mut encoder = ZstdEncoder::new(vec!(), zstd::DEFAULT_COMPRESSION_LEVEL) + .expect("could not create encoder"); + encoder.write(&*payload) + .expect("could not compress payload"); + encoder.finish() + .expect("could not finish encoding") + } + } +} + diff --git a/src/lib.rs b/src/lib.rs index 6a49669..3242a21 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ mod packet; mod command; mod command_codes; mod byte_grid; +mod compression; pub use crate::connection::Connection; pub use crate::pixel_grid::PixelGrid;