diff --git a/Cargo.lock b/Cargo.lock index dc2f3cd..7016849 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,22 +1,28 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "adler" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" + [[package]] name = "adler32" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] name = "anyhow" -version = "1.0.34" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7" +checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "bitflags" @@ -26,79 +32,83 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "bytemuck" -version = "1.2.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37fa13df2292ecb479ec23aa06f4507928bef07839be9ef15281411076629431" +checksum = "5a4bad0c5981acc24bc09e532f35160f952e35422603f0563cd7a73c2c2e65a0" [[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" [[package]] name = "cfg-if" -version = "0.1.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "color_quant" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "const_fn" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" [[package]] name = "crc32fast" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" dependencies = [ "cfg-if", ] [[package]] -name = "crossbeam-deque" -version = "0.7.3" +name = "crossbeam-channel" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" dependencies = [ - "crossbeam-epoch", + "cfg-if", "crossbeam-utils", - "maybe-uninit", ] [[package]] -name = "crossbeam-epoch" -version = "0.8.2" +name = "crossbeam-deque" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" dependencies = [ - "autocfg", "cfg-if", + "crossbeam-epoch", "crossbeam-utils", - "lazy_static", - "maybe-uninit", - "memoffset", - "scopeguard", ] [[package]] -name = "crossbeam-queue" -version = "0.2.3" +name = "crossbeam-epoch" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" +checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" dependencies = [ "cfg-if", + "const_fn", "crossbeam-utils", - "maybe-uninit", + "lazy_static", + "memoffset", + "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.7.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" dependencies = [ "autocfg", "cfg-if", @@ -208,6 +218,17 @@ dependencies = [ "byteorder", ] +[[package]] +name = "dmi" +version = "0.1.0" +source = "git+https://github.com/Rohesie/dmi#6d66475306a9677b8b971d5937a898bd5e605793" +dependencies = [ + "deflate", + "image", + "inflate", + "thiserror", +] + [[package]] name = "dont_disappear" version = "3.0.1" @@ -219,25 +240,25 @@ dependencies = [ [[package]] name = "either" -version = "1.5.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "gif" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "471d90201b3b223f3451cd4ad53e34295f16a1df17b1edf3736d47761c3981af" +checksum = "02efba560f227847cb41463a7395c514d127d4f74fff12ef0137fff1b84b96c4" dependencies = [ "color_quant", - "lzw", + "weezl", ] [[package]] name = "hermit-abi" -version = "0.1.15" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" dependencies = [ "libc", ] @@ -247,22 +268,21 @@ name = "icon-cutter" version = "0.1.0" dependencies = [ "anyhow", - "deflate", + "dmi", "dont_disappear", "image", - "inflate", - "thiserror", "yaml-rust", ] [[package]] name = "image" -version = "0.23.6" +version = "0.23.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b0553fec6407d63fe2975b794dfb099f3f790bdc958823851af37b26404ab4" +checksum = "293f07a1875fa7e9c5897b51aa68b2d8ed8271b87e1a44cb64b9c3d98aabbc0d" dependencies = [ "bytemuck", "byteorder", + "color_quant", "gif", "jpeg-decoder", "num-iter", @@ -284,11 +304,10 @@ dependencies = [ [[package]] name = "jpeg-decoder" -version = "0.1.20" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc797adac5f083b8ff0ca6f6294a999393d76e197c36488e2ef732c4715f6fa3" +checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" dependencies = [ - "byteorder", "rayon", ] @@ -300,33 +319,21 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.71" +version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" +checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" [[package]] name = "linked-hash-map" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" - -[[package]] -name = "lzw" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" - -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "memoffset" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c198b026e1bbf08a937e94c6c60f9ec4a2267f5b0d2eec9c1b21b061ce2be55f" +checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" dependencies = [ "autocfg", ] @@ -340,11 +347,21 @@ dependencies = [ "adler32", ] +[[package]] +name = "miniz_oxide" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +dependencies = [ + "adler", + "autocfg", +] + [[package]] name = "num-integer" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ "autocfg", "num-traits", @@ -352,9 +369,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.41" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f" +checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" dependencies = [ "autocfg", "num-integer", @@ -363,9 +380,9 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b4d7360f362cfb50dde8143501e6940b22f644be75a4cc90b2d81968908138" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" dependencies = [ "autocfg", "num-integer", @@ -374,9 +391,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg", ] @@ -393,14 +410,14 @@ dependencies = [ [[package]] name = "png" -version = "0.16.7" +version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfe7f9f1c730833200b134370e1d5098964231af8450bce9b78ee3ab5278b970" +checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" dependencies = [ "bitflags", "crc32fast", "deflate", - "miniz_oxide", + "miniz_oxide 0.3.7", ] [[package]] @@ -414,18 +431,18 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" dependencies = [ "proc-macro2", ] [[package]] name = "rayon" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f02856753d04e03e26929f820d0a0a337ebe71f849801eea335d464b349080" +checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" dependencies = [ "autocfg", "crossbeam-deque", @@ -435,12 +452,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.7.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e92e15d89083484e11353891f1af602cc661426deb9564c298b270c726973280" +checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" dependencies = [ + "crossbeam-channel", "crossbeam-deque", - "crossbeam-queue", "crossbeam-utils", "lazy_static", "num_cpus", @@ -460,9 +477,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "syn" -version = "1.0.48" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac" +checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" dependencies = [ "proc-macro2", "quote", @@ -471,27 +488,27 @@ dependencies = [ [[package]] name = "termios" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0fcee7b24a25675de40d5bb4de6e41b0df07bc9856295e7e2b3a3600c400c2" +checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" dependencies = [ "libc", ] [[package]] name = "thiserror" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e" +checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56" +checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1" dependencies = [ "proc-macro2", "quote", @@ -500,13 +517,13 @@ dependencies = [ [[package]] name = "tiff" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f3b8a87c4da944c3f27e5943289171ac71a6150a79ff6bacfff06d159dfff2f" +checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" dependencies = [ - "byteorder", - "lzw", - "miniz_oxide", + "jpeg-decoder", + "miniz_oxide 0.4.3", + "weezl", ] [[package]] @@ -515,6 +532,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +[[package]] +name = "weezl" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a32b378380f4e9869b22f0b5177c68a5519f03b3454fde0b291455ddbae266c" + [[package]] name = "winapi" version = "0.3.9" @@ -539,9 +562,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "yaml-rust" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] diff --git a/Cargo.toml b/Cargo.toml index d0d9cff..852b86c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,10 +7,8 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +dmi = { git = "https://github.com/Rohesie/dmi" } +anyhow = "1.0.34" image = "0.23.6" yaml-rust = "0.4.4" -inflate = "0.4.5" -deflate = "0.8.6" dont_disappear = "3.0.1" -thiserror = "1.0.22" -anyhow = "1.0.34" diff --git a/src/dmi.rs b/src/dmi.rs deleted file mode 100644 index fd499dd..0000000 --- a/src/dmi.rs +++ /dev/null @@ -1,155 +0,0 @@ -pub mod chunk; -pub mod crc; -pub mod error; -pub mod icon; -pub mod ztxt; - -use std::convert::TryFrom; -use std::io::prelude::*; - -/// The PNG magic header -pub const MAGIC: [u8; 8] = [137, 80, 78, 71, 13, 10, 26, 10]; - -#[derive(Clone, PartialEq, Eq, Debug, Default)] -pub struct RawDmi { - pub header: [u8; 8], - pub chunk_ihdr: chunk::RawGenericChunk, - pub chunk_ztxt: Option, - pub chunk_idat: chunk::RawGenericChunk, - pub chunk_iend: chunk::RawGenericChunk, - pub other_chunks: Vec, -} - -impl RawDmi { - pub fn load(mut reader: R) -> Result { - let mut dmi_bytes = Vec::new(); - reader.read_to_end(&mut dmi_bytes)?; - // 8 bytes for the PNG file signature. - // 12 + 13 bytes for the IHDR chunk. - // 12 for the IDAT chunk. - // 12 + 3 for the zTXt chunk. - // 12 for the IEND chunk. - - // Total minimum size for a DMI file: 72 bytes. - - if dmi_bytes.len() < 72 { - return Err(error::DmiError::Generic(format!("Failed to load DMI. Supplied reader contained size of {} bytes, lower than the required 72.", dmi_bytes.len()))); - }; - - let header = &dmi_bytes[0..8]; - if dmi_bytes[0..8] != MAGIC { - return Err(error::DmiError::Generic(format!( - "PNG header mismatch (expected {:#?}, found {:#?})", - MAGIC, header - ))); - }; - let header = MAGIC; - let mut chunk_ihdr = None; - let mut chunk_ztxt = None; - let mut chunk_idat = None; - let chunk_iend; - let mut other_chunks = vec![]; - - // Index starts after the PNG header. - let mut index = 8; - - loop { - if index + 12 > dmi_bytes.len() { - return Err(error::DmiError::Generic( - "Failed to load DMI. Buffer end reached without finding an IEND chunk." - .to_string(), - )); - } - - let chunk_data_length = u32::from_be_bytes([ - dmi_bytes[index], - dmi_bytes[index + 1], - dmi_bytes[index + 2], - dmi_bytes[index + 3], - ]) as usize; - - // 12 minimum necessary bytes from the chunk plus the data length. - let chunk_bytes = dmi_bytes[index..(index + 12 + chunk_data_length)].to_vec(); - let raw_chunk = chunk::RawGenericChunk::load(&mut &*chunk_bytes)?; - index += 12 + chunk_data_length; - - match &raw_chunk.chunk_type { - b"IHDR" => chunk_ihdr = Some(raw_chunk), - b"zTXt" => chunk_ztxt = Some(ztxt::RawZtxtChunk::try_from(raw_chunk)?), - b"IDAT" => chunk_idat = Some(raw_chunk), - b"IEND" => { - chunk_iend = Some(raw_chunk); - break; - } - _ => other_chunks.push(raw_chunk), - } - } - if chunk_ihdr == None || chunk_idat == None { - return Err(error::DmiError::Generic(format!("Failed to load DMI. Buffer end reached without finding a necessary chunk.\nIHDR: {:#?}\nIDAT: {:#?}", chunk_ihdr, chunk_idat))); - }; - let chunk_ihdr = chunk_ihdr.unwrap(); - let chunk_idat = chunk_idat.unwrap(); - let chunk_iend = chunk_iend.unwrap(); - - Ok(RawDmi { - header, - chunk_ihdr, - chunk_ztxt, - chunk_idat, - chunk_iend, - other_chunks, - }) - } - - pub fn save(&self, mut writter: &mut W) -> Result { - let bytes_written = writter.write(&self.header)?; - let mut total_bytes_written = bytes_written; - if bytes_written < 8 { - return Err(error::DmiError::Generic(format!( - "Failed to save DMI. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - let bytes_written = self.chunk_ihdr.save(&mut writter)?; - total_bytes_written += bytes_written; - if bytes_written < u32::from_be_bytes(self.chunk_ihdr.data_length) as usize + 12 { - return Err(error::DmiError::Generic(format!( - "Failed to save DMI. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - match &self.chunk_ztxt { - Some(chunk_ztxt) => { - let bytes_written = chunk_ztxt.save(&mut writter)?; - total_bytes_written += bytes_written; - if bytes_written < u32::from_be_bytes(chunk_ztxt.data_length) as usize + 12 { - return Err(error::DmiError::Generic(format!("Failed to save DMI. Buffer unable to hold the data, only {} bytes written.", total_bytes_written))); - }; - } - None => (), - }; - - let bytes_written = self.chunk_idat.save(&mut writter)?; - total_bytes_written += bytes_written; - if bytes_written < u32::from_be_bytes(self.chunk_idat.data_length) as usize + 12 { - return Err(error::DmiError::Generic(format!( - "Failed to save DMI. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - let bytes_written = self.chunk_iend.save(&mut writter)?; - total_bytes_written += bytes_written; - if bytes_written < u32::from_be_bytes(self.chunk_iend.data_length) as usize + 12 { - return Err(error::DmiError::Generic(format!( - "Failed to save DMI. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - Ok(total_bytes_written) - } - -} diff --git a/src/dmi/chunk.rs b/src/dmi/chunk.rs deleted file mode 100644 index 696de51..0000000 --- a/src/dmi/chunk.rs +++ /dev/null @@ -1,117 +0,0 @@ -use super::crc; -use super::error; -use std::io::prelude::*; - -#[derive(Clone, PartialEq, Eq, Debug, Default)] -pub struct RawGenericChunk { - pub data_length: [u8; 4], - pub chunk_type: [u8; 4], - pub data: Vec, - pub crc: [u8; 4], -} - -impl RawGenericChunk { - pub fn load(reader: &mut R) -> Result { - let mut chunk_bytes = Vec::new(); - reader.read_to_end(&mut chunk_bytes)?; - - // 4 bytes for the length. - // 4 bytes for the type. - // Data can be 0 bytes. - // 4 bytes for the CRC. - - // Total minimum size for an undetermined PNG chunk: 12 bytes. - let chunk_length = chunk_bytes.len(); - - if chunk_length < 12 { - return Err(error::DmiError::Generic(format!("Failed to load Chunk. Supplied reader contained size of {} bytes, lower than the required 12.", chunk_length))); - }; - - let data_length = [ - chunk_bytes[0], - chunk_bytes[1], - chunk_bytes[2], - chunk_bytes[3], - ]; - - let chunk_type = [ - chunk_bytes[4], - chunk_bytes[5], - chunk_bytes[6], - chunk_bytes[7], - ]; - - // The chunk type is made of four ascii characters. The valid ranges are A-Z and a-z. - if !chunk_type - .iter() - .all(|c| (b'A' <= *c && *c <= b'Z') || (b'a' <= *c && *c <= b'z')) - { - return Err(error::DmiError::Generic(format!( - "Failed to load Chunk. Type contained unlawful characters: {:#?}", - chunk_type - ))); - }; - - let data: Vec = chunk_bytes[8..(chunk_length - 4)].iter().cloned().collect(); - - let crc = [ - chunk_bytes[chunk_length - 4], - chunk_bytes[chunk_length - 3], - chunk_bytes[chunk_length - 2], - chunk_bytes[chunk_length - 1], - ]; - - let recalculated_crc = crc::calculate_crc(chunk_type.iter().chain(data.iter())); - if u32::from_be_bytes(crc) != recalculated_crc { - let chunk_name = String::from_utf8(chunk_type.to_vec())?; - return Err(error::DmiError::Generic(format!("Failed to load Chunk of type {}. Supplied CRC invalid: {:#?}. Its value ({}) does not match the recalculated one ({}).", chunk_name, crc, u32::from_be_bytes(crc), recalculated_crc))); - } - - Ok(RawGenericChunk { - data_length, - chunk_type, - data, - crc, - }) - } - - pub fn save(&self, writter: &mut W) -> Result { - let bytes_written = writter.write(&self.data_length)?; - let mut total_bytes_written = bytes_written; - if bytes_written < self.data_length.len() { - return Err(error::DmiError::Generic(format!( - "Failed to save Chunk. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - let bytes_written = writter.write(&self.chunk_type)?; - total_bytes_written += bytes_written; - if bytes_written < self.chunk_type.len() { - return Err(error::DmiError::Generic(format!( - "Failed to save Chunk. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - let bytes_written = writter.write(&self.data)?; - total_bytes_written += bytes_written; - if bytes_written < self.data.len() { - return Err(error::DmiError::Generic(format!( - "Failed to save Chunk. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - let bytes_written = writter.write(&self.crc)?; - total_bytes_written += bytes_written; - if bytes_written < self.crc.len() { - return Err(error::DmiError::Generic(format!( - "Failed to save Chunk. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - Ok(total_bytes_written) - } -} diff --git a/src/dmi/crc.rs b/src/dmi/crc.rs deleted file mode 100644 index dd8c569..0000000 --- a/src/dmi/crc.rs +++ /dev/null @@ -1,17 +0,0 @@ -pub fn calculate_crc<'a, I: IntoIterator>(buffer: I) -> u32 { - const CRC_POLYNOMIAL: u32 = 0xedb8_8320; - - fn update_crc(crc: u32, message: u8) -> u32 { - let message: u32 = u32::from(message); - let mut crc = crc ^ message; - for _ in 0..8 { - crc = (if crc & 1 != 0 { CRC_POLYNOMIAL } else { 0 }) ^ (crc >> 1); - } - crc - } - - buffer - .into_iter() - .fold(u32::max_value(), |crc, message| update_crc(crc, *message)) - ^ u32::max_value() -} diff --git a/src/dmi/error.rs b/src/dmi/error.rs deleted file mode 100644 index 3e1f85f..0000000 --- a/src/dmi/error.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::io; -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum DmiError { - #[error("IO error")] - Io(#[from] io::Error), - #[error("Invalid chunk type (byte outside the range `A-Za-z`): {chunk_type:?}")] - InvalidChunkType { chunk_type: [u8; 4] }, - #[error("CRC mismatch (stated {stated:?}, calculated {calculated:?})")] - CrcMismatch { stated: u32, calculated: u32 }, - #[error("Image-processing error")] - Image(#[from] image::error::ImageError), - #[error("Dmi error")] - Generic(String), - #[error("Encoding error")] - Encoding(String), - #[error("Conversion error")] - Conversion(String), - #[error("FromUtf8 error")] - FromUtf8(#[from] std::string::FromUtf8Error), - #[error("ParseInt error")] - ParseInt(#[from] std::num::ParseIntError), - #[error("ParseFloat error")] - ParseFloat(#[from] std::num::ParseFloatError), -} diff --git a/src/dmi/icon.rs b/src/dmi/icon.rs deleted file mode 100644 index ecd9d14..0000000 --- a/src/dmi/icon.rs +++ /dev/null @@ -1,394 +0,0 @@ -use super::error; -use super::ztxt; -use super::RawDmi; -use image; -use image::imageops; -use image::GenericImageView; -use std::collections::HashMap; -use std::io::prelude::*; - -#[derive(Clone, Default)] -pub struct Icon { - pub version: String, - pub width: u32, - pub height: u32, - pub states: Vec, -} - -impl Icon { - pub fn load(reader: R) -> Result { - let raw_dmi = RawDmi::load(reader)?; - let chunk_ztxt = match &raw_dmi.chunk_ztxt { - Some(chunk) => chunk.clone(), - None => { - return Err(error::DmiError::Generic(format!( - "Error loading icon: no zTXt chunk found." - ))) - } - }; - let decompressed_text = chunk_ztxt.data.decode()?; - let decompressed_text = String::from_utf8(decompressed_text)?; - let mut decompressed_text = decompressed_text.lines(); - - let current_line = decompressed_text.next(); - if current_line != Some("# BEGIN DMI") { - return Err(error::DmiError::Generic(format!( - "Error loading icon: no DMI header found. Beginning: {:#?}", - current_line - ))); - }; - - let current_line = match decompressed_text.next() { - Some(thing) => thing, - None => { - return Err(error::DmiError::Generic(format!( - "Error loading icon: no version header found." - ))) - } - }; - let split_version: Vec<&str> = current_line.split_terminator(" = ").collect(); - if split_version.len() != 2 || split_version[0] != "version" { - return Err(error::DmiError::Generic(format!( - "Error loading icon: improper version header found: {:#?}", - split_version - ))); - }; - let version = split_version[1].to_string(); - - let current_line = match decompressed_text.next() { - Some(thing) => thing, - None => { - return Err(error::DmiError::Generic(format!( - "Error loading icon: no width found." - ))) - } - }; - let split_version: Vec<&str> = current_line.split_terminator(" = ").collect(); - if split_version.len() != 2 || split_version[0] != "\twidth" { - return Err(error::DmiError::Generic(format!( - "Error loading icon: improper width found: {:#?}", - split_version - ))); - }; - let width = split_version[1].parse::()?; - - let current_line = match decompressed_text.next() { - Some(thing) => thing, - None => { - return Err(error::DmiError::Generic(format!( - "Error loading icon: no height found." - ))) - } - }; - let split_version: Vec<&str> = current_line.split_terminator(" = ").collect(); - if split_version.len() != 2 || split_version[0] != "\theight" { - return Err(error::DmiError::Generic(format!( - "Error loading icon: improper height found: {:#?}", - split_version - ))); - }; - let height = split_version[1].parse::()?; - - if width == 0 || height == 0 { - return Err(error::DmiError::Generic(format!( - "Error loading icon: invalid width ({}) / height ({}) values.", - width, height - ))); - }; - - // Image time. - let mut reader = vec![]; - raw_dmi.save(&mut reader)?; - let base_image = image::load_from_memory_with_format(&reader, image::ImageFormat::Png)?; - - let dimensions = base_image.dimensions(); - let img_width = dimensions.0; - let img_height = dimensions.1; - - if img_width == 0 || img_height == 0 || img_width % width != 0 || img_height % height != 0 { - return Err(error::DmiError::Generic(format!("Error loading icon: invalid image width ({}) / height ({}) values. Missmatch with metadata width ({}) / height ({}).", img_width, img_height, width, height))); - }; - - let max_possible_states = (img_width / width) * (img_height / height); - - let mut index = 0; - - let current_line = match decompressed_text.next() { - Some(thing) => thing, - None => { - return Err(error::DmiError::Generic(format!( - "Error loading icon: no DMI trailer found." - ))) - } - }; - - let mut states = vec![]; - - loop { - if current_line == "# END DMI" { - break; - }; - - let split_version: Vec<&str> = current_line.split_terminator(" = ").collect(); - if split_version.len() != 2 || split_version[0] != "state" { - return Err(error::DmiError::Generic(format!( - "Error loading icon: improper state found: {:#?}", - split_version - ))); - }; - - let name = split_version[1].as_bytes(); - if !name.starts_with(&[b'\"']) || !name.ends_with(&[b'\"']) { - return Err(error::DmiError::Generic(format!("Error loading icon: invalid name icon_state found in metadata, should be preceded and succeeded by double-quotes (\"): {:#?}", name))); - }; - let name = match name.len() { - 0 | 1 => return Err(error::DmiError::Generic(format!("Error loading icon: invalid name icon_state found in metadata, improper size: {:#?}", name))), - 2 => String::new(), //Only the quotes, empty name otherwise. - length @ _ => String::from_utf8(name[1..length].to_vec())?, //Hacky way to trim. Blame the cool methods being nightly experimental. - }; - - let mut dirs = None; - let mut frames = None; - let mut delay = None; - let mut loop_flag = None; - let mut rewind = None; - let mut movement = None; - let mut hotspot = None; - let mut unknown_settings = None; - - loop { - let current_line = match decompressed_text.next() { - Some(thing) => thing, - None => { - return Err(error::DmiError::Generic(format!( - "Error loading icon: no DMI trailer found." - ))) - } - }; - - if current_line == "# END DMI" { - break; - }; - let split_version: Vec<&str> = current_line.split_terminator(" = ").collect(); - if split_version.len() != 2 { - return Err(error::DmiError::Generic(format!( - "Error loading icon: improper state found: {:#?}", - split_version - ))); - }; - - match split_version[0] { - "\tdirs" => dirs = Some(split_version[1].parse::()?), - "\tframes" => frames = Some(split_version[1].parse::()?), - "\tdelay" => { - let mut delay_vector = vec![]; - let text_delays = split_version[1].split_terminator(","); - for text_entry in text_delays { - delay_vector.push(text_entry.parse::()?); - } - delay = Some(delay_vector); - } - "\tloop" => loop_flag = Some(split_version[1].parse::()?), - "\trewind" => rewind = Some(split_version[1].parse::()?), - "\tmovement" => movement = Some(split_version[1].parse::()?), - "\thotspot" => { - let text_coordinates: Vec<&str> = - split_version[1].split_terminator(",").collect(); - if text_coordinates.len() != 3 { - return Err(error::DmiError::Generic(format!( - "Error loading icon: improper hotspot found: {:#?}", - split_version - ))); - }; - hotspot = Some([ - text_coordinates[0].parse::()?, - text_coordinates[1].parse::()?, - text_coordinates[2].parse::()?, - ]); - } - _ => { - unknown_settings = match unknown_settings { - None => { - let mut new_map = HashMap::new(); - new_map.insert( - split_version[0].to_string(), - split_version[1].to_string(), - ); - Some(new_map) - } - Some(mut thing) => { - thing.insert( - split_version[0].to_string(), - split_version[1].to_string(), - ); - Some(thing) - } - }; - } - }; - } - - if dirs == None || frames == None { - return Err(error::DmiError::Generic(format!("Error loading icon: state lacks essential settings. dirs: {:#?}. frames: {:#?}.", dirs, frames))); - }; - let dirs = dirs.unwrap(); - let frames = frames.unwrap(); - - if index + (dirs as u32 * frames) > max_possible_states { - return Err(error::DmiError::Generic(format!("Error loading icon: metadata settings exceeded the maximum number of states possible ({}).", max_possible_states))); - }; - - let mut images = vec![]; - - for _frame in 0..frames { - for _dir in 0..dirs { - let x = (index * width) % img_width; - let y = (index * height) / img_height; - images.push(base_image.crop_imm(x, y, width, height)); - index += 1; - } - } - - states.push(IconState { - name, - dirs, - frames, - images, - delay, - loop_flag, - rewind, - movement, - hotspot, - unknown_settings, - }); - } - - Ok(Icon { - version, - width, - height, - states, - }) - } - - pub fn save(&self, mut writter: &mut W) -> Result { - let mut sprites = vec![]; - let mut signature = format!( - "# BEGIN DMI\nversion = {}\n\twidth = {}\n\theight = {}\n", - self.version, self.width, self.height - ); - - for icon_state in &self.states { - if icon_state.images.len() as u32 != icon_state.dirs as u32 * icon_state.frames { - return Err(error::DmiError::Generic(format!("Error saving Icon: number of images ({}) differs from the stated metadata. Dirs: {}. Frames: {}. Name: \"{}\".", icon_state.images.len(), icon_state.dirs, icon_state.frames, icon_state.name))); - }; - - signature.push_str(&format!( - "state = \"{}\"\n\tdirs = {}\n\tframes = {}\n", - icon_state.name, icon_state.dirs, icon_state.frames - )); - - if icon_state.frames > 1 { - match &icon_state.delay { - Some(delay) => { - if delay.len() as u32 != icon_state.frames { - return Err(error::DmiError::Generic(format!("Error saving Icon: number of frames ({}) differs from the delay entry ({:3?}). Name: \"{}\".", icon_state.frames, delay, icon_state.name))) - }; - let delay: Vec= delay.iter().map(|&c| c.to_string()).collect(); - signature.push_str(&format!("\tdelay = {}\n", delay.join(","))); - }, - None => return Err(error::DmiError::Generic(format!("Error saving Icon: number of frames ({}) larger than one without a delay entry in icon state of name \"{}\".", icon_state.frames, icon_state.name))) - }; - match icon_state.loop_flag { - Some(flag) => signature.push_str(&format!("\tloop = {}\n", flag)), - None => (), - }; - match icon_state.rewind { - Some(flag) => signature.push_str(&format!("\trewind = {}\n", flag)), - None => (), - }; - match icon_state.movement { - Some(flag) => signature.push_str(&format!("\trewind = {}\n", flag)), - None => (), - }; - }; - - match icon_state.hotspot { - Some(array) => signature.push_str(&format!( - "\tarray = {},{},{}\n", - array[0], array[1], array[2] - )), - None => (), - }; - - match &icon_state.unknown_settings { - Some(hashmap) => { - for (setting, value) in hashmap.iter() { - signature.push_str(&format!("\t{} = {}\n", setting, value)); - } - } - None => (), - }; - - sprites.extend(icon_state.images.iter()); - } - - signature.push_str("# END DMI\n"); - - let max_index = (sprites.len() as f64).sqrt().ceil() as u32; - let mut new_png = - image::DynamicImage::new_rgba8(max_index * self.width, max_index * self.height); - - let mut index = 0; - for image in sprites.iter() { - imageops::replace( - &mut new_png, - *image, - self.width * (index % max_index), - self.height * (index / max_index), - ); - index += 1; - } - - let mut new_dmi = vec![]; - new_png.write_to(&mut new_dmi, image::ImageOutputFormat::Png)?; - let mut new_dmi = RawDmi::load(&new_dmi[..])?; - - let new_ztxt = ztxt::create_ztxt_chunk(signature.as_bytes())?; - - new_dmi.chunk_ztxt = Some(new_ztxt); - - Ok(new_dmi.save(&mut writter)?) - } -} - -#[derive(Clone)] -pub struct IconState { - pub name: String, - pub dirs: u8, - pub frames: u32, - pub images: Vec, - pub delay: Option>, - pub loop_flag: Option, - pub rewind: Option, - pub movement: Option, - pub hotspot: Option<[u32; 3]>, - pub unknown_settings: Option>, -} - -impl Default for IconState { - fn default() -> Self { - IconState { - name: String::new(), - dirs: 1, - frames: 1, - images: vec![], - delay: None, - loop_flag: None, - rewind: None, - movement: None, - hotspot: None, - unknown_settings: None, - } - } -} diff --git a/src/dmi/ztxt.rs b/src/dmi/ztxt.rs deleted file mode 100644 index e0c65b2..0000000 --- a/src/dmi/ztxt.rs +++ /dev/null @@ -1,325 +0,0 @@ -use super::chunk; -use super::crc; -use super::error; -use deflate; -use inflate; -use std::convert::TryFrom; -use std::fmt; -use std::io::prelude::*; - -pub const ZTXT_TYPE: [u8; 4] = [b'z', b'T', b'X', b't']; - -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct RawZtxtChunk { - pub data_length: [u8; 4], - pub chunk_type: [u8; 4], - pub data: RawZtxtData, - pub crc: [u8; 4], -} - -pub fn create_ztxt_chunk(dmi_signature: &[u8]) -> Result { - let compressed_text = encode(dmi_signature); - let data = RawZtxtData { - compressed_text, - ..Default::default() - }; - let mut data_bytes = vec![]; - data.save(&mut data_bytes)?; - let data_length = (data_bytes.len() as u32).to_be_bytes(); - let chunk_type = ZTXT_TYPE; - let crc = crc::calculate_crc(chunk_type.iter().chain(data_bytes.iter())).to_be_bytes(); - Ok(RawZtxtChunk { - data_length, - chunk_type, - data, - crc, - }) -} - -impl RawZtxtChunk { - pub fn load(reader: &mut R) -> Result { - let mut raw_chunk_bytes = Vec::new(); - reader.read_to_end(&mut raw_chunk_bytes)?; - let total_bytes_length = raw_chunk_bytes.len(); - if total_bytes_length < 12 { - return Err(error::DmiError::Generic(format!( - "Failed to load RawZtxtChunk from reader. Size: {}. Minimum necessary is 12.", - raw_chunk_bytes.len() - ))); - } - let data_length = [ - raw_chunk_bytes[0], - raw_chunk_bytes[1], - raw_chunk_bytes[2], - raw_chunk_bytes[3], - ]; - if u32::from_be_bytes(data_length) != total_bytes_length as u32 - 12 { - return Err(error::DmiError::Generic(format!("Failed to load RawZtxtChunk from reader. Lengh field value ({}) does not match the actual data field size ({}).", u32::from_be_bytes(data_length), total_bytes_length -12))); - } - let chunk_type = [ - raw_chunk_bytes[4], - raw_chunk_bytes[5], - raw_chunk_bytes[6], - raw_chunk_bytes[7], - ]; - if chunk_type != ZTXT_TYPE { - return Err(error::DmiError::Generic(format!("Failed to load RawZtxtChunk from reader. Chunk type is not zTXt: {:#?}. Should be {:#?}.", chunk_type, ZTXT_TYPE))); - } - let data_bytes = &raw_chunk_bytes[8..(total_bytes_length - 4)].to_vec(); - let data = RawZtxtData::load(&mut &**data_bytes)?; - let crc = [ - raw_chunk_bytes[total_bytes_length - 4], - raw_chunk_bytes[total_bytes_length - 3], - raw_chunk_bytes[total_bytes_length - 2], - raw_chunk_bytes[total_bytes_length - 1], - ]; - let calculated_crc = crc::calculate_crc(chunk_type.iter().chain(data_bytes.iter())); - if u32::from_be_bytes(crc) != calculated_crc { - return Err(error::DmiError::Generic(format!("Failed to load RawZtxtChunk from reader. Given CRC ({}) does not match the calculated one ({}).", u32::from_be_bytes(crc), calculated_crc))); - } - Ok(RawZtxtChunk { - data_length, - chunk_type, - data, - crc, - }) - } - - pub fn save(&self, writter: &mut W) -> Result { - let bytes_written = writter.write(&self.data_length)?; - let mut total_bytes_written = bytes_written; - if bytes_written < self.data_length.len() { - return Err(error::DmiError::Generic(format!( - "Failed to save zTXt chunk. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - let bytes_written = writter.write(&self.chunk_type)?; - total_bytes_written += bytes_written; - if bytes_written < self.chunk_type.len() { - return Err(error::DmiError::Generic(format!( - "Failed to save zTXt chunk. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - let bytes_written = self.data.save(&mut *writter)?; - total_bytes_written += bytes_written; - if bytes_written < u32::from_be_bytes(self.data_length) as usize { - return Err(error::DmiError::Generic(format!( - "Failed to save zTXt chunk. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - let bytes_written = writter.write(&self.crc)?; - total_bytes_written += bytes_written; - if bytes_written < self.crc.len() { - return Err(error::DmiError::Generic(format!( - "Failed to save zTXt chunk. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - Ok(total_bytes_written) - } - - pub fn set_data(&self, data: RawZtxtData) -> Result { - let mut data_bytes = vec![]; - data.save(&mut data_bytes)?; - let data_length = (data_bytes.len() as u32).to_be_bytes(); - let chunk_type = ZTXT_TYPE; - let crc = crc::calculate_crc(chunk_type.iter().chain(data_bytes.iter())).to_be_bytes(); - Ok(RawZtxtChunk { - data_length, - chunk_type, - data, - crc, - }) - } -} - -impl Default for RawZtxtChunk { - fn default() -> Self { - let data: RawZtxtData = Default::default(); - let data_length = (data.length() as u32).to_be_bytes(); - let chunk_type = ZTXT_TYPE; - let crc = data.crc().to_be_bytes(); - RawZtxtChunk { - data_length, - chunk_type, - data, - crc, - } - } -} - -impl TryFrom for RawZtxtChunk { - type Error = error::DmiError; - fn try_from(raw_generic_chunk: chunk::RawGenericChunk) -> Result { - let data_length = raw_generic_chunk.data_length; - let chunk_type = raw_generic_chunk.chunk_type; - if chunk_type != ZTXT_TYPE { - return Err(error::DmiError::Generic(format!("Failed to convert RawGenericChunk into RawZtxtChunk. Wrong type: {:#?}. Expected: {:#?}.", chunk_type, ZTXT_TYPE))); - }; - let chunk_data = &raw_generic_chunk.data; - let data = RawZtxtData::load(&mut &**chunk_data)?; - let crc = raw_generic_chunk.crc; - Ok(RawZtxtChunk { - data_length, - chunk_type, - data, - crc, - }) - } -} - -/* -impl TryFrom> for RawZtxtChunk { - type Error = anyhow::Error; - fn try_from(raw_chunk_bytes: Vec) -> Result { - let total_bytes_length = raw_chunk_bytes.len(); - if total_bytes_length < 12 { - bail!("Failed to convert Vec into RawZtxtChunk. Size: {}. Minimum necessary is 12.", raw_chunk_bytes.len()) - } - let length = [raw_chunk_bytes[0], raw_chunk_bytes[1], raw_chunk_bytes[2], raw_chunk_bytes[3]]; - if u32::from_be_bytes(length) != total_bytes_length as u32 - 12 { - bail!("Failed to convert Vec into RawZtxtChunk. Lengh field value ({}) does not match the actual data field size ({}).", u32::from_be_bytes(length), total_bytes_length -12) - } - let chunk_type = [raw_chunk_bytes[4], raw_chunk_bytes[5], raw_chunk_bytes[6], raw_chunk_bytes[7]]; - if chunk_type != ZTXT_TYPE { - bail!("Failed to convert Vec into RawZtxtChunk. Chunk type is not zTXt: {:#?}. Should be {:#?}.", chunk_type, ZTXT_TYPE) - } - let data_bytes = &raw_chunk_bytes[8..(total_bytes_length - 4)]; - let data = RawZtxtData::load(data_bytes)?; - let crc = [raw_chunk_bytes[total_bytes_length - 4], raw_chunk_bytes[total_bytes_length - 3], raw_chunk_bytes[total_bytes_length - 2], raw_chunk_bytes[total_bytes_length - 1]]; - let calculated_crc = crc::calculate_crc(chunk_type.iter().chain(data_bytes.iter())); - if u32::from_be_bytes(crc) != calculated_crc { - bail!("Failed to convert Vec into RawZtxtChunk. Given CRC ({}) does not match the calculated one ({}).", u32::from_be_bytes(crc), calculated_crc) - } - Ok(RawZtxtChunk { - length, - chunk_type, - data, - crc, - }) - } -} -*/ - -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct RawZtxtData { - pub keyword: Vec, - pub null_separator: u8, - pub compression_method: u8, - pub compressed_text: Vec, -} - -impl RawZtxtData { - pub fn load(reader: &mut R) -> Result { - let mut data_bytes = Vec::new(); - reader.read_to_end(&mut data_bytes)?; - let mut data_bytes_iter = data_bytes.iter().cloned(); - let keyword = data_bytes_iter.by_ref().take_while(|x| *x != 0).collect(); - let null_separator = 0; - let compression_method = data_bytes_iter.next().ok_or_else(|| error::DmiError::Generic(format!("Failed to load RawZtxtData from reader, during compression method reading.\nVector: {:#?}", data_bytes)))?; - //let compressed_text = RawCompressedText::try_from(back_to_vector)?; - let compressed_text = data_bytes_iter.collect(); - //let compressed_text = RawCompressedText::load(&back_to_vector[..])?; - - Ok(RawZtxtData { - keyword, - null_separator, - compression_method, - compressed_text, - }) - } - - pub fn save(&self, writter: &mut W) -> Result { - let bytes_written = writter.write(&self.keyword)?; - let mut total_bytes_written = bytes_written; - if bytes_written < self.keyword.len() { - return Err(error::DmiError::Generic(format!( - "Failed to save zTXt data. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - let bytes_written = writter.write(&[self.null_separator])?; - total_bytes_written += bytes_written; - if bytes_written < 1 { - return Err(error::DmiError::Generic(format!( - "Failed to save zTXt data. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - let bytes_written = writter.write(&[self.compression_method])?; - total_bytes_written += bytes_written; - if bytes_written < 1 { - return Err(error::DmiError::Generic(format!( - "Failed to save zTXt data. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - let bytes_written = writter.write(&self.compressed_text)?; - total_bytes_written += bytes_written; - if bytes_written < self.compressed_text.len() { - return Err(error::DmiError::Generic(format!( - "Failed to save zTXt data. Buffer unable to hold the data, only {} bytes written.", - total_bytes_written - ))); - }; - - Ok(total_bytes_written) - } - - pub fn decode(&self) -> Result, error::DmiError> { - match inflate::inflate_bytes_zlib(&self.compressed_text) { - Ok(decompressed_text) => Ok(decompressed_text), - Err(text) => { - return Err(error::DmiError::Generic(format!( - "Failed to read compressed text. Error: {}", - text - ))) - } - } - } - - fn length(&self) -> usize { - self.keyword.len() + 2 + self.compressed_text.len() - } - - fn crc(&self) -> u32 { - crc::calculate_crc( - ZTXT_TYPE - .iter() - .chain(self.keyword.iter()) - .chain([self.null_separator, self.compression_method].iter()) - .chain(self.compressed_text.iter()), - ) - } -} - -pub fn encode(text_to_compress: &[u8]) -> Vec { - deflate::deflate_bytes_zlib(text_to_compress) -} - -impl Default for RawZtxtData { - fn default() -> Self { - RawZtxtData { - keyword: "Description".as_bytes().to_vec(), - null_separator: 0, - compression_method: 0, - compressed_text: vec![], - } - } -} - -impl fmt::Display for RawZtxtData { - fn fmt(&self, feedback: &mut fmt::Formatter) -> fmt::Result { - write!(feedback, "RawZtxtData chunk error.\nkeyword: {:#?}\nnull_separator: {:#?}\ncompression_method: {:#?}\ncompressed_text: {:#?}", self.keyword, self.null_separator, self.compression_method, self.compressed_text) - } -} diff --git a/src/helpers.rs b/src/helpers.rs index 71d10fc..f274feb 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,4 +1,4 @@ -use super::dmi::error; +use dmi::error; use super::glob; use std::collections::HashSet; @@ -97,7 +97,7 @@ pub fn smooth_dir_to_corner_type(corner: u8, smooth_dirs: u8) -> u8 { } } -pub fn dir_offset_signature(icon_signature: u8, byond_dir: u8) -> Result { +pub fn dir_offset_signature(icon_signature: u8, byond_dir: u8) -> Result { if byond_dir == glob::BYOND_SOUTH { return Ok(icon_signature); } diff --git a/src/main.rs b/src/main.rs index f11f38f..ce45b59 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,6 @@ //Internal modules. mod config; -mod dmi; mod glob; mod helpers; @@ -24,8 +23,8 @@ fn main() { let prefs; match config::load_configs(self_path.clone()) { Ok(thing) => prefs = thing, - Err(e) => { - println!("Failed to load configs: {:#?}", e); + Err(_e) => { + println!("Failed to load configs.\nSolution: add a properly-filled config.yaml file to the folder executing the program. Check the namesake folder for examples."); dont_disappear::any_key_to_continue::default(); return; } @@ -36,9 +35,14 @@ fn main() { None => (), }; + if args.len() == 0 { + println!("Unable to produce any icons. \nSolution: Either add a file to be opened in the config.yaml file or click and drag one or more files into the executable file."); + dont_disappear::any_key_to_continue::default(); + return; + } + let mut icons_built = 0; for image_path_string in args.iter() { - //println!("Debug: image_path_string: {}", image_path_string); let path = Path::new(&image_path_string); let mut file; match File::open(&path) {