From 58219f752ba369160c0f6a82b601842facb040e0 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 19:32:46 +0200 Subject: [PATCH 01/23] build: rust-version >= 1.63, edition 2021 and lock file --- .gitignore | 1 - Cargo.lock | 295 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 11 +- 3 files changed, 301 insertions(+), 6 deletions(-) create mode 100644 Cargo.lock diff --git a/.gitignore b/.gitignore index 8bcef1c..b29e36e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,3 @@ .vscode/ /target **/*.rs.bk -Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..d3ad376 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,295 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "bitflags" +version = "2.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "cp437" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891a48ae269a368d5e45e0b13ee401f90d3d400da92d881f7cb67bc9da711c14" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "encoding-next" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9608b0ee6675c72999ffd7f741cce94952ced799a1db80724eab2a77791a994" +dependencies = [ + "encoding-next-index-japanese", + "encoding-next-index-korean", + "encoding-next-index-simpchinese", + "encoding-next-index-singlebyte", + "encoding-next-index-tradchinese", + "encoding-next-types", +] + +[[package]] +name = "encoding-next-index-japanese" +version = "1.20180106.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf1797243d6c8f00a269ec6abc8b13a3b74c30d76f2834a6e801a814204f257" + +[[package]] +name = "encoding-next-index-korean" +version = "1.20180106.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43fb584f42bbc55eae6c98ce2cb6d7f546a83eca694eb4866016dce5d9ea677" + +[[package]] +name = "encoding-next-index-simpchinese" +version = "1.20180106.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1dc69fd6a1f1c5fc2206ba488c73ab401587039539dad3d708a5074e7ae4a20" + +[[package]] +name = "encoding-next-index-singlebyte" +version = "1.20180106.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02c0bac231a1cc5f494a7d78ef01b4a2e8927d34b9b5c8436cd486dc06d9a85" + +[[package]] +name = "encoding-next-index-tradchinese" +version = "1.20180106.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee153a743b1f854f1595037b8fd285c8660ebf20ccb4384b81768b6d5f65ec5c" + +[[package]] +name = "encoding-next-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "140d4fb15765d628e2b75335e8a8697bcbb4cdd2e639130335ce09985857e50f" + +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + +[[package]] +name = "kaitai" +version = "0.2.0" +dependencies = [ + "cp437", + "encoding-next", + "flate2", + "tempfile", + "unicode-segmentation", +] + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "once_cell" +version = "1.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "tempfile" +version = "3.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "wasi" +version = "0.14.4+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a5f4a424faf49c3c2c344f166f0662341d470ea185e939657aaff130f0ec4a" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "wit-bindgen" +version = "0.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" diff --git a/Cargo.toml b/Cargo.toml index 3281f30..b8eb810 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,13 +2,14 @@ name = "kaitai" version = "0.2.0" authors = ["Bradlee Speice ", "Aon"] -edition = "2018" +edition = "2021" +rust-version = "1.63" [dependencies] encoding-next = "0.3" -cp437 = "*" -unicode-segmentation = "1.9.0" -flate2 = "1.0" +cp437 = "0.1" +unicode-segmentation = "1" +flate2 = "1" [dev-dependencies] -tempfile = "3.4.0" +tempfile = "3" From d896728593f852e5312e4ff8de023ee13e004715 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 19:33:07 +0200 Subject: [PATCH 02/23] style: cargo fmt --- src/lib.rs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4f35747..9208389 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,5 @@ use encoding::{label::encoding_from_whatwg_label, DecoderTrap}; use flate2::read::ZlibDecoder; - use std::{ any::{type_name, Any}, cell::{Ref, RefCell, RefMut}, @@ -542,10 +541,7 @@ impl BytesReader { // sync stream pos with state.pos fn sync_pos(&self) -> KResult<()> { - let cur_pos = self - .buf - .borrow_mut() - .stream_position()?; + let cur_pos = self.buf.borrow_mut().stream_position()?; if self.pos() != cur_pos as usize { self.buf .borrow_mut() @@ -585,10 +581,7 @@ impl KStream for BytesReader { // let state = self.state.borrow_mut(); // state.buf.resize(len, 0); let mut buf = vec![0; len]; - self - .buf - .borrow_mut() - .read_exact(&mut buf[..])?; + self.buf.borrow_mut().read_exact(&mut buf[..])?; self.get_state_mut().pos += len; Ok(buf) } @@ -597,10 +590,7 @@ impl KStream for BytesReader { self.sync_pos()?; //let state = self.state.borrow_mut(); let mut buf = Vec::new(); - let readed = self - .buf - .borrow_mut() - .read_to_end(&mut buf)?; + let readed = self.buf.borrow_mut().read_to_end(&mut buf)?; self.get_state_mut().pos += readed; Ok(buf) } @@ -623,7 +613,8 @@ pub fn bytes_terminate(bytes: &Vec, term: u8, include_term: bool) -> Vec &bytes[..term_index + if include_term { 1 } else { 0 }] } else { bytes - }.to_vec() + } + .to_vec() } pub fn bytes_to_str(bytes: &Vec, label: &str) -> KResult { From f53389415dd1fffd9ed93014ed0369c6f26e4e7e Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 19:37:32 +0200 Subject: [PATCH 03/23] refactor: fix lints In the future ptr_arg can improve the performance but as the ksc creates .into() calls this is breaking (while its not considered as a breaking change as this widens the usage its breaking with ksc) --- Cargo.toml | 3 +++ src/lib.rs | 18 +++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b8eb810..4b83b88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Bradlee Speice ", "Aon"] edition = "2021" rust-version = "1.63" +[features] +type_name_of_val = [] + [dependencies] encoding-next = "0.3" cp437 = "0.1" diff --git a/src/lib.rs b/src/lib.rs index 9208389..af69233 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -229,6 +229,7 @@ pub trait KStruct: Default { match t_any.downcast_ref::>() { Some(as_result) => SharedType::::new(Rc::clone(as_result)), None => { + #[allow(clippy::incompatible_msrv)] // behind feature flag if panic { #[cfg(feature = "type_name_of_val")] panic!( @@ -351,8 +352,8 @@ pub trait KStream { Ok(f64::from_le_bytes(self.read_bytes(8)?.try_into().unwrap())) } - fn get_state(&self) -> Ref; - fn get_state_mut(&self) -> RefMut; + fn get_state(&self) -> Ref<'_, ReaderState>; + fn get_state_mut(&self) -> RefMut<'_, ReaderState>; fn align_to_byte(&self) -> KResult<()> { let mut inner = self.get_state_mut(); @@ -556,11 +557,11 @@ impl KStream for BytesReader { Clone::clone(self) } - fn get_state(&self) -> Ref { + fn get_state(&self) -> Ref<'_, ReaderState> { self.state.borrow() } - fn get_state_mut(&self) -> RefMut { + fn get_state_mut(&self) -> RefMut<'_, ReaderState> { self.state.borrow_mut() } @@ -598,6 +599,7 @@ impl KStream for BytesReader { /// Return a byte array that is sized to exclude all trailing instances of the /// padding character. +#[allow(clippy::ptr_arg)] // TODO: use &[u8] as argument and result pub fn bytes_strip_right(bytes: &Vec, pad: u8) -> Vec { if let Some(last_non_pad_index) = bytes.iter().rposition(|&c| c != pad) { bytes[..=last_non_pad_index].to_vec() @@ -608,6 +610,7 @@ pub fn bytes_strip_right(bytes: &Vec, pad: u8) -> Vec { /// Return a byte array that contains all bytes up until the /// termination byte. Can optionally include the termination byte as well. +#[allow(clippy::ptr_arg)] // TODO: use &[u8] as argument and result pub fn bytes_terminate(bytes: &Vec, term: u8, include_term: bool) -> Vec { if let Some(term_index) = bytes.iter().position(|&c| c == term) { &bytes[..term_index + if include_term { 1 } else { 0 }] @@ -617,10 +620,11 @@ pub fn bytes_terminate(bytes: &Vec, term: u8, include_term: bool) -> Vec .to_vec() } +#[allow(clippy::ptr_arg)] // TODO: use &[u8] as argument pub fn bytes_to_str(bytes: &Vec, label: &str) -> KResult { if let Some(enc) = encoding_from_whatwg_label(label) { return Ok(enc - .decode(bytes.as_slice(), DecoderTrap::Replace) + .decode(bytes, DecoderTrap::Replace) .expect("this should never fail because we use DecoderTrap::Replace")); } @@ -637,6 +641,7 @@ pub fn bytes_to_str(bytes: &Vec, label: &str) -> KResult { }) } +#[allow(clippy::ptr_arg)] // TODO: use &[u8] as argument pub fn process_xor_one(bytes: &Vec, key: u8) -> Vec { let mut res = bytes.to_vec(); for i in &mut res { @@ -645,6 +650,7 @@ pub fn process_xor_one(bytes: &Vec, key: u8) -> Vec { res } +#[allow(clippy::ptr_arg)] // TODO: use &[u8] as argument pub fn process_xor_many(bytes: &Vec, key: &[u8]) -> Vec { let mut res = bytes.to_vec(); let mut ki = 0; @@ -658,6 +664,7 @@ pub fn process_xor_many(bytes: &Vec, key: &[u8]) -> Vec { res } +#[allow(clippy::ptr_arg)] // TODO: use &[u8] as argument pub fn process_rotate_left(bytes: &Vec, amount: u8) -> Vec { let mut res = bytes.to_vec(); for i in &mut res { @@ -666,6 +673,7 @@ pub fn process_rotate_left(bytes: &Vec, amount: u8) -> Vec { res } +#[allow(clippy::ptr_arg)] // TODO: use &[u8] as argument pub fn process_zlib(bytes: &Vec) -> Result, String> { let mut dec = ZlibDecoder::new(bytes.as_slice()); let mut dec_bytes = Vec::new(); From d1c367fd5b7b5258ee6d03c10ea146f5ea4a519e Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 19:44:54 +0200 Subject: [PATCH 04/23] refactor(lint): unused_qualifications --- Cargo.toml | 4 ++++ src/lib.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4b83b88..9eb560e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,10 @@ rust-version = "1.63" [features] type_name_of_val = [] +[lints.rust] +unsafe_code = "forbid" +unused_qualifications = "warn" + [dependencies] encoding-next = "0.3" cp437 = "0.1" diff --git a/src/lib.rs b/src/lib.rs index af69233..98a4b68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -492,7 +492,7 @@ impl fmt::Display for dyn ReadSeek { } impl fmt::Debug for dyn ReadSeek { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "ReadSeek") } } From 07f8724f38e54d90377fd1f0291f0df30a3d6515 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 20:07:43 +0200 Subject: [PATCH 05/23] refactor: slice[..] is a noop --- src/lib.rs | 60 +++++++++++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 98a4b68..5c777c7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -582,7 +582,7 @@ impl KStream for BytesReader { // let state = self.state.borrow_mut(); // state.buf.resize(len, 0); let mut buf = vec![0; len]; - self.buf.borrow_mut().read_exact(&mut buf[..])?; + self.buf.borrow_mut().read_exact(&mut buf)?; self.get_state_mut().pos += len; Ok(buf) } @@ -700,7 +700,7 @@ mod tests { let b = vec![1, 2, 3, 4, 5, 5, 5, 5]; let c = bytes_strip_right(&b, 5); - assert_eq!([1, 2, 3, 4], c[..]); + assert_eq!(c, [1, 2, 3, 4]); } #[test] @@ -708,8 +708,8 @@ mod tests { let b = vec![1, 2, 3, 4, 5, 6, 7, 8]; let reader = BytesReader::from(b); - assert_eq!(reader.read_bytes(4).unwrap()[..], [1, 2, 3, 4]); - assert_eq!(reader.read_bytes(3).unwrap()[..], [5, 6, 7]); + assert_eq!(reader.read_bytes(4).unwrap(), [1, 2, 3, 4]); + assert_eq!(reader.read_bytes(3).unwrap(), [5, 6, 7]); assert_eq!( reader.read_bytes(4).unwrap_err(), KError::Eof { @@ -717,7 +717,7 @@ mod tests { available: 1 } ); - assert_eq!(reader.read_bytes(1).unwrap()[..], [8]); + assert_eq!(reader.read_bytes(1).unwrap(), [8]); } #[test] @@ -772,23 +772,14 @@ mod tests { let reader = BytesReader::from(b); assert_eq!( - reader.read_bytes_term(3, false, false, false).unwrap()[..], + reader.read_bytes_term(3, false, false, false).unwrap(), [1, 2] ); + assert_eq!(reader.read_bytes_term(3, true, false, true).unwrap(), [3]); + assert_eq!(reader.read_bytes_term(3, false, true, true).unwrap(), []); + assert_eq!(reader.read_bytes_term(5, true, true, true).unwrap(), [4, 5]); assert_eq!( - reader.read_bytes_term(3, true, false, true).unwrap()[..], - [3] - ); - assert_eq!( - reader.read_bytes_term(3, false, true, true).unwrap()[..], - [] - ); - assert_eq!( - reader.read_bytes_term(5, true, true, true).unwrap()[..], - [4, 5] - ); - assert_eq!( - reader.read_bytes_term(8, false, false, true).unwrap()[..], + reader.read_bytes_term(8, false, false, true).unwrap(), [6, 7] ); assert_eq!( @@ -798,11 +789,11 @@ mod tests { // restore position reader.seek(7).unwrap(); assert_eq!( - reader.read_bytes_term(9, true, true, false).unwrap()[..], + reader.read_bytes_term(9, true, true, false).unwrap(), [8, 9] ); assert_eq!( - reader.read_bytes_term(10, true, false, false).unwrap()[..], + reader.read_bytes_term(10, true, false, false).unwrap(), [10] ); } @@ -812,16 +803,16 @@ mod tests { let b = vec![0x66]; let reader = BytesReader::from(b); let res = process_xor_one(&reader.read_bytes(1).unwrap(), 3); - assert_eq!(0x65, res[0]); + assert_eq!(res[0], 0x65); } #[test] fn process_xor_many_test() { let b = vec![0x66, 0x6F]; let reader = BytesReader::from(b); - let key: Vec = vec![3, 3]; + let key = vec![3, 3]; let res = process_xor_many(&reader.read_bytes(2).unwrap(), &key); - assert_eq!(vec![0x65, 0x6C], res); + assert_eq!(res, [0x65, 0x6C]); } #[test] @@ -829,8 +820,7 @@ mod tests { let b = vec![0x09, 0xAC]; let reader = BytesReader::from(b); let res = process_rotate_left(&reader.read_bytes(2).unwrap(), 3); - let expected: Vec = vec![0x48, 0x65]; - assert_eq!(expected, res); + assert_eq!(res, [0x48, 0x65]); } #[test] @@ -838,12 +828,12 @@ mod tests { let b = vec![1, 2, 3, 4, 5, 6, 7, 8]; let reader = BytesReader::from(b); - assert_eq!(reader.read_bytes(4).unwrap()[..], [1, 2, 3, 4]); + assert_eq!(reader.read_bytes(4).unwrap(), [1, 2, 3, 4]); let pos = reader.pos(); reader.seek(1).unwrap(); - assert_eq!(reader.read_bytes(4).unwrap()[..], [2, 3, 4, 5]); + assert_eq!(reader.read_bytes(4).unwrap(), [2, 3, 4, 5]); reader.seek(pos).unwrap(); - assert_eq!(reader.read_bytes(4).unwrap()[..], [5, 6, 7, 8]); + assert_eq!(reader.read_bytes(4).unwrap(), [5, 6, 7, 8]); reader.seek(9).unwrap(); } @@ -861,8 +851,8 @@ mod tests { fn basic_read_bytes_file() { let reader = dump_and_open(&[1, 2, 3, 4, 5, 6, 7, 8]); - assert_eq!(reader.read_bytes(4).unwrap()[..], [1, 2, 3, 4]); - assert_eq!(reader.read_bytes(3).unwrap()[..], [5, 6, 7]); + assert_eq!(reader.read_bytes(4).unwrap(), [1, 2, 3, 4]); + assert_eq!(reader.read_bytes(3).unwrap(), [5, 6, 7]); assert_eq!( reader.read_bytes(4).unwrap_err(), KError::Eof { @@ -870,19 +860,19 @@ mod tests { available: 1 } ); - assert_eq!(reader.read_bytes(1).unwrap()[..], [8]); + assert_eq!(reader.read_bytes(1).unwrap(), [8]); } #[test] fn basic_seek_file() { let reader = dump_and_open(&[1, 2, 3, 4, 5, 6, 7, 8]); - assert_eq!(reader.read_bytes(4).unwrap()[..], [1, 2, 3, 4]); + assert_eq!(reader.read_bytes(4).unwrap(), [1, 2, 3, 4]); let pos = reader.pos(); reader.seek(1).unwrap(); - assert_eq!(reader.read_bytes(4).unwrap()[..], [2, 3, 4, 5]); + assert_eq!(reader.read_bytes(4).unwrap(), [2, 3, 4, 5]); reader.seek(pos).unwrap(); - assert_eq!(reader.read_bytes(4).unwrap()[..], [5, 6, 7, 8]); + assert_eq!(reader.read_bytes(4).unwrap(), [5, 6, 7, 8]); reader.seek(9).unwrap(); } } From e84a1006a1532e59d2fe22e354cc18eb1c22803f Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 20:19:59 +0200 Subject: [PATCH 06/23] refactor(lint): clippy::min_ident_chars --- Cargo.toml | 2 + src/lib.rs | 189 +++++++++++++++++++++++++++-------------------------- 2 files changed, 99 insertions(+), 92 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9eb560e..e3efd35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,8 @@ type_name_of_val = [] [lints.rust] unsafe_code = "forbid" unused_qualifications = "warn" +[lints.clippy] +min_ident_chars = "warn" [dependencies] encoding-next = "0.3" diff --git a/src/lib.rs b/src/lib.rs index 5c777c7..570d39f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,11 +69,11 @@ impl Clone for SharedType { // stop recursion while printing impl fmt::Debug for SharedType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let w = &*self.0.borrow(); - match w.strong_count() { - 0 => write!(f, "SharedType(Empty)"), - _ => write!(f, "SharedType(Weak({:?}))", Weak::::as_ptr(w)), + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let weak = &*self.0.borrow(); + match weak.strong_count() { + 0 => write!(fmt, "SharedType(Empty)"), + _ => write!(fmt, "SharedType(Weak({:?}))", Weak::::as_ptr(weak)), } } } @@ -104,7 +104,7 @@ impl SharedType { pub fn set(&self, rc: KResult>) { *self.0.borrow_mut() = match rc.ok() { - Some(v) => Rc::downgrade(&v.get()), + Some(rc) => Rc::downgrade(&rc.get()), None => Weak::new(), } } @@ -155,14 +155,14 @@ impl Clone for OptRc { } impl From> for OptRc { - fn from(v: Rc) -> Self { - OptRc(Some(v)) + fn from(value: Rc) -> Self { + OptRc(Some(value)) } } impl From for OptRc { - fn from(v: T) -> Self { - OptRc(Some(v.into())) + fn from(value: T) -> Self { + OptRc(Some(value.into())) } } @@ -188,35 +188,39 @@ pub trait KStruct: Default { ) -> KResult<()>; /// helper function to read struct - fn read_into( + fn read_into( _io: &S, - _root: Option>, - _parent: Option>, - ) -> KResult> { - let t = OptRc::from(T::default()); - let root = Self::downcast(_root, t.clone(), true); - let parent = Self::downcast(_parent, t.clone(), false); - T::read(&t, _io, root, parent)?; - Ok(t) + _root: Option>, + _parent: Option>, + ) -> KResult> { + let output = OptRc::from(Output::default()); + let root = Self::downcast(_root, output.clone(), true); + let parent = Self::downcast(_parent, output.clone(), false); + Output::read(&output, _io, root, parent)?; + Ok(output) } /// helper function to special initialize and read struct - fn read_into_with_init( + fn read_into_with_init( _io: &S, - _root: Option>, - _parent: Option>, - init: &dyn Fn(&mut T) -> KResult<()>, - ) -> KResult> { - let mut t = OptRc::from(T::default()); - init(Rc::get_mut(t.get_mut()).unwrap())?; - - let root = Self::downcast(_root, t.clone(), true); - let parent = Self::downcast(_parent, t.clone(), false); - T::read(&t, _io, root, parent)?; - Ok(t) - } - - fn downcast(opt_rc: Option>, t: OptRc, panic: bool) -> SharedType + _root: Option>, + _parent: Option>, + init: &dyn Fn(&mut Output) -> KResult<()>, + ) -> KResult> { + let mut output = OptRc::from(Output::default()); + init(Rc::get_mut(output.get_mut()).unwrap())?; + + let root = Self::downcast(_root, output.clone(), true); + let parent = Self::downcast(_parent, output.clone(), false); + Output::read(&output, _io, root, parent)?; + Ok(output) + } + + fn downcast( + opt_rc: Option>, + fallback: OptRc, + panic: bool, + ) -> SharedType where T: KStruct + Default + Any, U: 'static, @@ -224,9 +228,9 @@ pub trait KStruct: Default { if let Some(rc) = opt_rc { rc } else { - let t_any = &t.get() as &dyn Any; + let fallback_any = &fallback.get() as &dyn Any; //println!("`{}` is a '{}' type", type_name_of_val(&t), type_name::>()); - match t_any.downcast_ref::>() { + match fallback_any.downcast_ref::>() { Some(as_result) => SharedType::::new(Rc::clone(as_result)), None => { #[allow(clippy::incompatible_msrv)] // behind feature flag @@ -234,11 +238,11 @@ pub trait KStruct: Default { #[cfg(feature = "type_name_of_val")] panic!( "`{}` is not a '{}' type", - std::any::type_name_of_val(&t), + std::any::type_name_of_val(&fallback), type_name::>() ); #[cfg(not(feature = "type_name_of_val"))] - panic!("`{:p}` is not a '{}' type", &t, type_name::>()); + panic!("`{:p}` is not a '{}' type", &fallback, type_name::>()); } SharedType::::empty() } @@ -377,8 +381,8 @@ pub trait KStream { if bits_needed > 0 { let bytes_needed = ((bits_needed - 1) / 8) + 1; let buf = self.read_bytes(bytes_needed.try_into().unwrap())?; - for b in buf { - res = res << 8 | u64::from(b); + for byte in buf { + res = res << 8 | u64::from(byte); } let mut inner = self.get_state_mut(); let new_bits = res; @@ -411,8 +415,8 @@ pub trait KStream { if bits_needed > 0 { let bytes_needed = ((bits_needed - 1) / 8) + 1; let buf = self.read_bytes(bytes_needed.try_into().unwrap())?; - for (i, &b) in buf.iter().enumerate() { - res |= u64::from(b) << (i * 8); + for (i, &byte) in buf.iter().enumerate() { + res |= u64::from(byte) << (i * 8); } let mut inner = self.get_state_mut(); let new_bits = if bits_needed < 64 { @@ -450,26 +454,26 @@ pub trait KStream { ) -> KResult> { let mut buf = vec![]; loop { - let c = match self.read_u1() { - Ok(c) => c, + let byte = match self.read_u1() { + Ok(byte) => byte, Err(KError::Eof { .. }) => { if eos_error { return Err(KError::NoTerminatorFound); } return Ok(buf); } - Err(e) => return Err(e), + Err(error) => return Err(error), }; - if c == term { + if byte == term { if include { - buf.push(c); + buf.push(byte); } if !consume { self.get_state_mut().pos -= 1; } return Ok(buf); } - buf.push(c); + buf.push(byte); } } } @@ -486,14 +490,14 @@ trait ReadSeek: Read + Seek {} impl ReadSeek for T where T: Read + Seek {} impl fmt::Display for dyn ReadSeek { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ReadSeek") + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "ReadSeek") } } impl fmt::Debug for dyn ReadSeek { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ReadSeek") + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "ReadSeek") } } @@ -520,23 +524,23 @@ impl From<&[u8]> for BytesReader { impl BytesReader { pub fn open>(filename: T) -> KResult { - let f = std::fs::File::open(filename)?; - let file_size = f.metadata().unwrap().len(); - let r: Box = Box::new(f); + let file = std::fs::File::open(filename)?; + let file_size = file.metadata().unwrap().len(); + let readseek: Box = Box::new(file); Ok(BytesReader { state: RefCell::new(ReaderState::default()), file_size, - buf: OptRc::from(RefCell::new(r)), + buf: OptRc::from(RefCell::new(readseek)), }) } fn from_buffer(bytes: Vec) -> Self { let file_size = bytes.len() as u64; - let r: Box = Box::new(std::io::Cursor::new(bytes)); + let readseek: Box = Box::new(std::io::Cursor::new(bytes)); BytesReader { state: RefCell::new(ReaderState::default()), file_size, - buf: OptRc::from(RefCell::new(r)), + buf: OptRc::from(RefCell::new(readseek)), } } @@ -601,7 +605,7 @@ impl KStream for BytesReader { /// padding character. #[allow(clippy::ptr_arg)] // TODO: use &[u8] as argument and result pub fn bytes_strip_right(bytes: &Vec, pad: u8) -> Vec { - if let Some(last_non_pad_index) = bytes.iter().rposition(|&c| c != pad) { + if let Some(last_non_pad_index) = bytes.iter().rposition(|&byte| byte != pad) { bytes[..=last_non_pad_index].to_vec() } else { vec![] @@ -612,7 +616,7 @@ pub fn bytes_strip_right(bytes: &Vec, pad: u8) -> Vec { /// termination byte. Can optionally include the termination byte as well. #[allow(clippy::ptr_arg)] // TODO: use &[u8] as argument and result pub fn bytes_terminate(bytes: &Vec, term: u8, include_term: bool) -> Vec { - if let Some(term_index) = bytes.iter().position(|&c| c == term) { + if let Some(term_index) = bytes.iter().position(|&byte| byte == term) { &bytes[..term_index + if include_term { 1 } else { 0 }] } else { bytes @@ -632,8 +636,8 @@ pub fn bytes_to_str(bytes: &Vec, label: &str) -> KResult { use std::io::BufReader; let reader = BufReader::new(bytes.as_slice()); let mut buffer = reader.bytes(); - let mut r = cp437::Reader::new(&mut buffer); - return Ok(r.consume(bytes.len())); + let mut reader = cp437::Reader::new(&mut buffer); + return Ok(reader.consume(bytes.len())); } Err(KError::UnknownEncoding { @@ -677,16 +681,17 @@ pub fn process_rotate_left(bytes: &Vec, amount: u8) -> Vec { pub fn process_zlib(bytes: &Vec) -> Result, String> { let mut dec = ZlibDecoder::new(bytes.as_slice()); let mut dec_bytes = Vec::new(); - dec.read_to_end(&mut dec_bytes).map_err(|e| e.to_string())?; + dec.read_to_end(&mut dec_bytes) + .map_err(|err| err.to_string())?; Ok(dec_bytes) } -pub fn reverse_string>(s: S) -> KResult { - Ok(s.as_ref().graphemes(true).rev().collect()) +pub fn reverse_string>(str: S) -> KResult { + Ok(str.as_ref().graphemes(true).rev().collect()) } -pub fn modulo(a: i64, b: i64) -> i64 { - a.rem_euclid(b) +pub fn modulo(dividend: i64, divisor: i64) -> i64 { + dividend.rem_euclid(divisor) } #[cfg(test)] @@ -697,16 +702,16 @@ mod tests { #[test] fn basic_strip_right() { - let b = vec![1, 2, 3, 4, 5, 5, 5, 5]; - let c = bytes_strip_right(&b, 5); + let bytes = vec![1, 2, 3, 4, 5, 5, 5, 5]; + let stripped = bytes_strip_right(&bytes, 5); - assert_eq!(c, [1, 2, 3, 4]); + assert_eq!(stripped, [1, 2, 3, 4]); } #[test] fn basic_read_bytes() { - let b = vec![1, 2, 3, 4, 5, 6, 7, 8]; - let reader = BytesReader::from(b); + let bytes = vec![1, 2, 3, 4, 5, 6, 7, 8]; + let reader = BytesReader::from(bytes); assert_eq!(reader.read_bytes(4).unwrap(), [1, 2, 3, 4]); assert_eq!(reader.read_bytes(3).unwrap(), [5, 6, 7]); @@ -722,8 +727,8 @@ mod tests { #[test] fn read_bits_single() { - let b = vec![0x80]; - let reader = BytesReader::from(b); + let bytes = vec![0x80]; + let reader = BytesReader::from(bytes); assert_eq!(reader.read_bits_int_be(1).unwrap(), 1); } @@ -731,8 +736,8 @@ mod tests { #[test] fn read_bits_multiple() { // 0xA0 - let b = vec![0b10100000]; - let reader = BytesReader::from(b); + let bytes = vec![0b10100000]; + let reader = BytesReader::from(bytes); assert_eq!(reader.read_bits_int_be(1).unwrap(), 1); assert_eq!(reader.read_bits_int_be(1).unwrap(), 0); @@ -741,24 +746,24 @@ mod tests { #[test] fn read_bits_large() { - let b = vec![0b10100000]; - let reader = BytesReader::from(b); + let bytes = vec![0b10100000]; + let reader = BytesReader::from(bytes); assert_eq!(reader.read_bits_int_be(3).unwrap(), 5); } #[test] fn read_bits_span() { - let b = vec![0x01, 0x80]; - let reader = BytesReader::from(b); + let bytes = vec![0x01, 0x80]; + let reader = BytesReader::from(bytes); assert_eq!(reader.read_bits_int_be(9).unwrap(), 3); } #[test] fn read_bits_too_large() { - let b: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9]; - let reader = BytesReader::from(b); + let bytes = vec![1, 2, 3, 4, 5, 6, 7, 8, 9]; + let reader = BytesReader::from(bytes); assert_eq!( reader.read_bits_int_be(65).unwrap_err(), @@ -768,8 +773,8 @@ mod tests { #[test] fn read_bytes_term() { - let b = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let reader = BytesReader::from(b); + let bytes = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let reader = BytesReader::from(bytes); assert_eq!( reader.read_bytes_term(3, false, false, false).unwrap(), @@ -800,16 +805,16 @@ mod tests { #[test] fn process_xor_one_test() { - let b = vec![0x66]; - let reader = BytesReader::from(b); + let bytes = vec![0x66]; + let reader = BytesReader::from(bytes); let res = process_xor_one(&reader.read_bytes(1).unwrap(), 3); assert_eq!(res[0], 0x65); } #[test] fn process_xor_many_test() { - let b = vec![0x66, 0x6F]; - let reader = BytesReader::from(b); + let bytes = vec![0x66, 0x6F]; + let reader = BytesReader::from(bytes); let key = vec![3, 3]; let res = process_xor_many(&reader.read_bytes(2).unwrap(), &key); assert_eq!(res, [0x65, 0x6C]); @@ -817,16 +822,16 @@ mod tests { #[test] fn process_rotate_left_test() { - let b = vec![0x09, 0xAC]; - let reader = BytesReader::from(b); + let bytes = vec![0x09, 0xAC]; + let reader = BytesReader::from(bytes); let res = process_rotate_left(&reader.read_bytes(2).unwrap(), 3); assert_eq!(res, [0x48, 0x65]); } #[test] fn basic_seek() { - let b = vec![1, 2, 3, 4, 5, 6, 7, 8]; - let reader = BytesReader::from(b); + let bytes = vec![1, 2, 3, 4, 5, 6, 7, 8]; + let reader = BytesReader::from(bytes); assert_eq!(reader.read_bytes(4).unwrap(), [1, 2, 3, 4]); let pos = reader.pos(); From b5c6f477e24c7e0caac104b6a4507b1209aba3b6 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 20:23:08 +0200 Subject: [PATCH 07/23] refactor(lint): redundant_imports --- Cargo.toml | 1 + src/lib.rs | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e3efd35..f109a4b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ rust-version = "1.63" type_name_of_val = [] [lints.rust] +redundant_imports = "warn" unsafe_code = "forbid" unused_qualifications = "warn" [lints.clippy] diff --git a/src/lib.rs b/src/lib.rs index 570d39f..f789651 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,6 @@ use flate2::read::ZlibDecoder; use std::{ any::{type_name, Any}, cell::{Ref, RefCell, RefMut}, - convert::TryInto, fmt, io::{Read, Seek, SeekFrom}, ops::Deref, From deded59f9f3350d7cc902ae92721b887bc2d8d24 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 20:28:58 +0200 Subject: [PATCH 08/23] refactor(lint): trivial_casts --- Cargo.toml | 1 + src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f109a4b..084995a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ type_name_of_val = [] [lints.rust] redundant_imports = "warn" +trivial_casts = "warn" unsafe_code = "forbid" unused_qualifications = "warn" [lints.clippy] diff --git a/src/lib.rs b/src/lib.rs index f789651..fa6b613 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -227,7 +227,7 @@ pub trait KStruct: Default { if let Some(rc) = opt_rc { rc } else { - let fallback_any = &fallback.get() as &dyn Any; + let fallback_any: &dyn Any = &fallback.get(); //println!("`{}` is a '{}' type", type_name_of_val(&t), type_name::>()); match fallback_any.downcast_ref::>() { Some(as_result) => SharedType::::new(Rc::clone(as_result)), From 686719e4c1a4fb27e4727bff5bbf0d226dc847b6 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 20:46:15 +0200 Subject: [PATCH 09/23] refactor(lint): clippy::unreadable_literal --- Cargo.toml | 2 ++ src/lib.rs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 084995a..76d693f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,8 @@ unused_qualifications = "warn" [lints.clippy] min_ident_chars = "warn" +unreadable_literal = "warn" + [dependencies] encoding-next = "0.3" cp437 = "0.1" diff --git a/src/lib.rs b/src/lib.rs index fa6b613..08b20ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -735,7 +735,7 @@ mod tests { #[test] fn read_bits_multiple() { // 0xA0 - let bytes = vec![0b10100000]; + let bytes = vec![0b1010_0000]; let reader = BytesReader::from(bytes); assert_eq!(reader.read_bits_int_be(1).unwrap(), 1); @@ -745,7 +745,7 @@ mod tests { #[test] fn read_bits_large() { - let bytes = vec![0b10100000]; + let bytes = vec![0b1010_0000]; let reader = BytesReader::from(bytes); assert_eq!(reader.read_bits_int_be(3).unwrap(), 5); From 11437d37698f9c5dcc6765f4918be7c6dad4cc80 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 20:47:18 +0200 Subject: [PATCH 10/23] refactor(lint): clippy::semicolon_if_nothing_returned --- Cargo.toml | 1 + src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 76d693f..8bdbcfc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ unused_qualifications = "warn" [lints.clippy] min_ident_chars = "warn" +semicolon_if_nothing_returned = "warn" unreadable_literal = "warn" [dependencies] diff --git a/src/lib.rs b/src/lib.rs index 08b20ce..7d9957b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -767,7 +767,7 @@ mod tests { assert_eq!( reader.read_bits_int_be(65).unwrap_err(), KError::ReadBitsTooLarge { requested: 65 } - ) + ); } #[test] From 97d8015c10076f6c74adffb18fd83f46ba751fee Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 20:50:19 +0200 Subject: [PATCH 11/23] refactor(lint): clippy::bool_to_int_with_if --- Cargo.toml | 1 + src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 8bdbcfc..d41dcd3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ unused_qualifications = "warn" [lints.clippy] min_ident_chars = "warn" +bool_to_int_with_if = "warn" semicolon_if_nothing_returned = "warn" unreadable_literal = "warn" diff --git a/src/lib.rs b/src/lib.rs index 7d9957b..3c6fcc4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -616,7 +616,7 @@ pub fn bytes_strip_right(bytes: &Vec, pad: u8) -> Vec { #[allow(clippy::ptr_arg)] // TODO: use &[u8] as argument and result pub fn bytes_terminate(bytes: &Vec, term: u8, include_term: bool) -> Vec { if let Some(term_index) = bytes.iter().position(|&byte| byte == term) { - &bytes[..term_index + if include_term { 1 } else { 0 }] + &bytes[..term_index + usize::from(include_term)] } else { bytes } From 6647c028f59a35667b7fe1323217a802204c141d Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 20:53:33 +0200 Subject: [PATCH 12/23] refactor(lint): clippy::needless_pass_by_value --- Cargo.toml | 1 + src/lib.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d41dcd3..f3a2822 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ unused_qualifications = "warn" min_ident_chars = "warn" bool_to_int_with_if = "warn" +needless_pass_by_value = "warn" semicolon_if_nothing_returned = "warn" unreadable_literal = "warn" diff --git a/src/lib.rs b/src/lib.rs index 3c6fcc4..b4152aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,6 +78,7 @@ impl fmt::Debug for SharedType { } impl SharedType { + #[allow(clippy::needless_pass_by_value)] // TODO: change on breaking release pub fn new(rc: Rc) -> Self { Self(RefCell::new(Rc::downgrade(&rc))) } @@ -230,7 +231,7 @@ pub trait KStruct: Default { let fallback_any: &dyn Any = &fallback.get(); //println!("`{}` is a '{}' type", type_name_of_val(&t), type_name::>()); match fallback_any.downcast_ref::>() { - Some(as_result) => SharedType::::new(Rc::clone(as_result)), + Some(as_result) => SharedType::::new(as_result.clone()), None => { #[allow(clippy::incompatible_msrv)] // behind feature flag if panic { From 984164cb5012644a4df71e55b9f4b2b1ee774a1a Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 22:36:57 +0200 Subject: [PATCH 13/23] refactor(lint): clippy::manual_assert --- Cargo.toml | 1 + src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index f3a2822..fd84d1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ unused_qualifications = "warn" min_ident_chars = "warn" bool_to_int_with_if = "warn" +manual_assert = "warn" needless_pass_by_value = "warn" semicolon_if_nothing_returned = "warn" unreadable_literal = "warn" diff --git a/src/lib.rs b/src/lib.rs index b4152aa..77ea49a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -234,6 +234,7 @@ pub trait KStruct: Default { Some(as_result) => SharedType::::new(as_result.clone()), None => { #[allow(clippy::incompatible_msrv)] // behind feature flag + #[allow(clippy::manual_assert)] if panic { #[cfg(feature = "type_name_of_val")] panic!( From 3fe7773b54a85a07057a445be219d7224c1ded78 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 22:38:53 +0200 Subject: [PATCH 14/23] refactor(lint): clippy::single_match_else --- Cargo.toml | 1 + src/lib.rs | 31 +++++++++++++++---------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fd84d1b..29e0a68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ bool_to_int_with_if = "warn" manual_assert = "warn" needless_pass_by_value = "warn" semicolon_if_nothing_returned = "warn" +single_match_else = "warn" unreadable_literal = "warn" [dependencies] diff --git a/src/lib.rs b/src/lib.rs index 77ea49a..5eb6f51 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -230,23 +230,22 @@ pub trait KStruct: Default { } else { let fallback_any: &dyn Any = &fallback.get(); //println!("`{}` is a '{}' type", type_name_of_val(&t), type_name::>()); - match fallback_any.downcast_ref::>() { - Some(as_result) => SharedType::::new(as_result.clone()), - None => { - #[allow(clippy::incompatible_msrv)] // behind feature flag - #[allow(clippy::manual_assert)] - if panic { - #[cfg(feature = "type_name_of_val")] - panic!( - "`{}` is not a '{}' type", - std::any::type_name_of_val(&fallback), - type_name::>() - ); - #[cfg(not(feature = "type_name_of_val"))] - panic!("`{:p}` is not a '{}' type", &fallback, type_name::>()); - } - SharedType::::empty() + if let Some(as_result) = fallback_any.downcast_ref::>() { + SharedType::::new(as_result.clone()) + } else { + #[allow(clippy::incompatible_msrv)] // behind feature flag + #[allow(clippy::manual_assert)] + if panic { + #[cfg(feature = "type_name_of_val")] + panic!( + "`{}` is not a '{}' type", + std::any::type_name_of_val(&fallback), + type_name::>() + ); + #[cfg(not(feature = "type_name_of_val"))] + panic!("`{:p}` is not a '{}' type", &fallback, type_name::>()); } + SharedType::::empty() } } } From ff5283b8de1789e6b4f76cfddd886b1ea2fd7de6 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 22:41:01 +0200 Subject: [PATCH 15/23] refactor(lint): clippy::inline_always --- Cargo.toml | 1 + src/lib.rs | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 29e0a68..391a43d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ unused_qualifications = "warn" min_ident_chars = "warn" bool_to_int_with_if = "warn" +inline_always = "warn" manual_assert = "warn" needless_pass_by_value = "warn" semicolon_if_nothing_returned = "warn" diff --git a/src/lib.rs b/src/lib.rs index 5eb6f51..8df9ecf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -169,7 +169,6 @@ impl From for OptRc { impl Deref for OptRc { type Target = T; - #[inline(always)] fn deref(&self) -> &Self::Target { self.0.as_ref().unwrap() } From dae83753163522c8344e52cc431dad21093c0900 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 22:46:42 +0200 Subject: [PATCH 16/23] =?UTF-8?q?refactor(lint):=20clippy::cast=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 2 ++ src/lib.rs | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 391a43d..95609dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,8 @@ unused_qualifications = "warn" min_ident_chars = "warn" bool_to_int_with_if = "warn" +cast_possible_truncation = "warn" +cast_possible_wrap = "warn" inline_always = "warn" manual_assert = "warn" needless_pass_by_value = "warn" diff --git a/src/lib.rs b/src/lib.rs index 8df9ecf..8852e51 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -298,6 +298,7 @@ pub trait KStream { self.get_state().pos } + #[allow(clippy::cast_possible_wrap)] // This is wanted here fn read_s1(&self) -> KResult { Ok(self.read_bytes(1)?[0] as i8) } @@ -543,7 +544,8 @@ impl BytesReader { } } - // sync stream pos with state.pos + /// sync stream pos with state.pos + #[allow(clippy::cast_possible_truncation)] // TODO: use u64 for pos fn sync_pos(&self) -> KResult<()> { let cur_pos = self.buf.borrow_mut().stream_position()?; if self.pos() != cur_pos as usize { @@ -568,6 +570,7 @@ impl KStream for BytesReader { self.state.borrow_mut() } + #[allow(clippy::cast_possible_truncation)] // TODO: return as u64 fn size(&self) -> usize { self.file_size as usize } From 5f59f0904e4d59bb386b8acfbdd234bf782c358d Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 22:48:26 +0200 Subject: [PATCH 17/23] build(lint): enable all clippy::pedantic lints --- Cargo.toml | 14 +++++--------- src/lib.rs | 6 +++--- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 95609dc..962c11e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,17 +14,13 @@ trivial_casts = "warn" unsafe_code = "forbid" unused_qualifications = "warn" [lints.clippy] +pedantic = { level = "warn", priority = -1 } min_ident_chars = "warn" -bool_to_int_with_if = "warn" -cast_possible_truncation = "warn" -cast_possible_wrap = "warn" -inline_always = "warn" -manual_assert = "warn" -needless_pass_by_value = "warn" -semicolon_if_nothing_returned = "warn" -single_match_else = "warn" -unreadable_literal = "warn" +missing_errors_doc = "allow" +missing_panics_doc = "allow" +must_use_candidate = "allow" +used_underscore_binding = "allow" # _io and so on are the same as on other reader implementations [dependencies] encoding-next = "0.3" diff --git a/src/lib.rs b/src/lib.rs index 8852e51..3b3e5cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -647,7 +647,7 @@ pub fn bytes_to_str(bytes: &Vec, label: &str) -> KResult { }) } -#[allow(clippy::ptr_arg)] // TODO: use &[u8] as argument +#[allow(clippy::ptr_arg, clippy::implicit_clone)] // TODO: use &[u8] as argument pub fn process_xor_one(bytes: &Vec, key: u8) -> Vec { let mut res = bytes.to_vec(); for i in &mut res { @@ -656,7 +656,7 @@ pub fn process_xor_one(bytes: &Vec, key: u8) -> Vec { res } -#[allow(clippy::ptr_arg)] // TODO: use &[u8] as argument +#[allow(clippy::ptr_arg, clippy::implicit_clone)] // TODO: use &[u8] as argument pub fn process_xor_many(bytes: &Vec, key: &[u8]) -> Vec { let mut res = bytes.to_vec(); let mut ki = 0; @@ -670,7 +670,7 @@ pub fn process_xor_many(bytes: &Vec, key: &[u8]) -> Vec { res } -#[allow(clippy::ptr_arg)] // TODO: use &[u8] as argument +#[allow(clippy::ptr_arg, clippy::implicit_clone)] // TODO: use &[u8] as argument pub fn process_rotate_left(bytes: &Vec, amount: u8) -> Vec { let mut res = bytes.to_vec(); for i in &mut res { From 5bdcb30ca026567a74580a6857d881bb058e571b Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 22:52:04 +0200 Subject: [PATCH 18/23] refactor(lint): clippy::use_self --- Cargo.toml | 2 ++ src/lib.rs | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 962c11e..08f2391 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,8 @@ unused_qualifications = "warn" pedantic = { level = "warn", priority = -1 } min_ident_chars = "warn" +use_self = "warn" + missing_errors_doc = "allow" missing_panics_doc = "allow" must_use_candidate = "allow" diff --git a/src/lib.rs b/src/lib.rs index 3b3e5cd..4f278e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,8 +119,8 @@ pub struct OptRc(Option>); impl OptRc { pub fn new(orc: &Option>) -> Self { match orc { - Some(rc) => OptRc::from(rc.clone()), - None => OptRc::default(), + Some(rc) => Self::from(rc.clone()), + None => Self::default(), } } @@ -144,25 +144,25 @@ impl OptRc { impl Default for OptRc { #[inline] fn default() -> Self { - OptRc(None) + Self(None) } } impl Clone for OptRc { fn clone(&self) -> Self { - OptRc(self.0.clone()) + Self(self.0.clone()) } } impl From> for OptRc { fn from(value: Rc) -> Self { - OptRc(Some(value)) + Self(Some(value)) } } impl From for OptRc { fn from(value: T) -> Self { - OptRc(Some(value.into())) + Self(Some(value.into())) } } @@ -257,8 +257,8 @@ pub trait KStruct: Default { pub struct KStructUnit; impl KStruct for KStructUnit { - type Root = KStructUnit; - type Parent = KStructUnit; + type Root = Self; + type Parent = Self; fn read( _self_rc: &OptRc, @@ -511,14 +511,14 @@ pub struct BytesReader { } impl From> for BytesReader { - fn from(bytes: Vec) -> BytesReader { - BytesReader::from_buffer(bytes) + fn from(bytes: Vec) -> Self { + Self::from_buffer(bytes) } } impl From<&[u8]> for BytesReader { - fn from(slice: &[u8]) -> BytesReader { - BytesReader::from_buffer(slice.to_vec()) + fn from(slice: &[u8]) -> Self { + Self::from_buffer(slice.to_vec()) } } @@ -527,7 +527,7 @@ impl BytesReader { let file = std::fs::File::open(filename)?; let file_size = file.metadata().unwrap().len(); let readseek: Box = Box::new(file); - Ok(BytesReader { + Ok(Self { state: RefCell::new(ReaderState::default()), file_size, buf: OptRc::from(RefCell::new(readseek)), @@ -537,7 +537,7 @@ impl BytesReader { fn from_buffer(bytes: Vec) -> Self { let file_size = bytes.len() as u64; let readseek: Box = Box::new(std::io::Cursor::new(bytes)); - BytesReader { + Self { state: RefCell::new(ReaderState::default()), file_size, buf: OptRc::from(RefCell::new(readseek)), From 6a169a30d671fa76549f0055a14bc7f271718a14 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 22:56:38 +0200 Subject: [PATCH 19/23] refactor(lint): clippy::precedence_bits --- Cargo.toml | 1 + src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 08f2391..4c427e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ unused_qualifications = "warn" [lints.clippy] pedantic = { level = "warn", priority = -1 } min_ident_chars = "warn" +precedence_bits = "warn" use_self = "warn" diff --git a/src/lib.rs b/src/lib.rs index 4f278e6..e38de5a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -382,7 +382,7 @@ pub trait KStream { let bytes_needed = ((bits_needed - 1) / 8) + 1; let buf = self.read_bytes(bytes_needed.try_into().unwrap())?; for byte in buf { - res = res << 8 | u64::from(byte); + res = (res << 8) | u64::from(byte); } let mut inner = self.get_state_mut(); let new_bits = res; @@ -424,7 +424,7 @@ pub trait KStream { } else { 0 }; - res = res << inner.bits_left | inner.bits; + res = (res << inner.bits_left) | inner.bits; inner.bits = new_bits; } else { let mut inner = self.get_state_mut(); From be60e332d6472e76f98a9c157cbca31cb6c2a107 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 22:58:15 +0200 Subject: [PATCH 20/23] refactor(lint): clippy::derive_partial_eq_without_eq --- Cargo.toml | 1 + src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4c427e7..4411b63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ pedantic = { level = "warn", priority = -1 } min_ident_chars = "warn" precedence_bits = "warn" +derive_partial_eq_without_eq = "warn" use_self = "warn" missing_errors_doc = "allow" diff --git a/src/lib.rs b/src/lib.rs index e38de5a..c4d46b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -253,7 +253,7 @@ pub trait KStruct: Default { /// Dummy struct used to indicate an absence of value; needed for /// root structs to satisfy the associated type bounds in the /// `KStruct` trait. -#[derive(Debug, Default, Copy, Clone, PartialEq)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] pub struct KStructUnit; impl KStruct for KStructUnit { From ec6ed9fe2ca234b61068a78f2eb682fa726618b8 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 23:00:43 +0200 Subject: [PATCH 21/23] refactor(lint): clippy::str_to_string --- Cargo.toml | 1 + src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4411b63..1666b99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ unsafe_code = "forbid" unused_qualifications = "warn" [lints.clippy] pedantic = { level = "warn", priority = -1 } +str_to_string = "warn" min_ident_chars = "warn" precedence_bits = "warn" diff --git a/src/lib.rs b/src/lib.rs index c4d46b9..74398d4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -643,7 +643,7 @@ pub fn bytes_to_str(bytes: &Vec, label: &str) -> KResult { } Err(KError::UnknownEncoding { - name: label.to_string(), + name: label.to_owned(), }) } From 9b9df7778f0dcf22847b489ad025d1456b3daf0b Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 8 Sep 2025 23:08:48 +0200 Subject: [PATCH 22/23] refactor(lint): prepare breaking changes --- clippy.toml | 1 + src/lib.rs | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 clippy.toml diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000..743c946 --- /dev/null +++ b/clippy.toml @@ -0,0 +1 @@ +avoid-breaking-exported-api = true # TODO: change (and keep) to false on breaking change release diff --git a/src/lib.rs b/src/lib.rs index 74398d4..bb8b23f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -117,6 +117,7 @@ impl SharedType { pub struct OptRc(Option>); impl OptRc { + #[allow(clippy::ref_option)] // TODO: breaking change pub fn new(orc: &Option>) -> Self { match orc { Some(rc) => Self::from(rc.clone()), @@ -128,6 +129,7 @@ impl OptRc { self.0.as_ref().unwrap().clone() } + #[allow(clippy::ref_option)] // TODO: breaking change pub fn get_value(&self) -> &Option> { &self.0 } @@ -688,6 +690,7 @@ pub fn process_zlib(bytes: &Vec) -> Result, String> { Ok(dec_bytes) } +#[allow(clippy::unnecessary_wraps)] // TODO: breaking change pub fn reverse_string>(str: S) -> KResult { Ok(str.as_ref().graphemes(true).rev().collect()) } From afb42f1a2662b05d249401204ef9fe421522e7dc Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Mon, 15 Sep 2025 22:26:31 +0200 Subject: [PATCH 23/23] perf: move downcast out of trait it is only used internally and should not be shared as much. While removing this from the trait is technically breaking its not changing the behaviour and isnt used by ksc so it can be changed relatively easily. This allows it to change the arguments reducing the amount of clones. --- src/lib.rs | 62 +++++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index bb8b23f..b1a335d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -195,8 +195,8 @@ pub trait KStruct: Default { _parent: Option>, ) -> KResult> { let output = OptRc::from(Output::default()); - let root = Self::downcast(_root, output.clone(), true); - let parent = Self::downcast(_parent, output.clone(), false); + let root = downcast(_root, &output, true); + let parent = downcast(_parent, &output, false); Output::read(&output, _io, root, parent)?; Ok(output) } @@ -211,43 +211,39 @@ pub trait KStruct: Default { let mut output = OptRc::from(Output::default()); init(Rc::get_mut(output.get_mut()).unwrap())?; - let root = Self::downcast(_root, output.clone(), true); - let parent = Self::downcast(_parent, output.clone(), false); + let root = downcast(_root, &output, true); + let parent = downcast(_parent, &output, false); Output::read(&output, _io, root, parent)?; Ok(output) } +} - fn downcast( - opt_rc: Option>, - fallback: OptRc, - panic: bool, - ) -> SharedType - where - T: KStruct + Default + Any, - U: 'static, - { - if let Some(rc) = opt_rc { - rc +fn downcast(opt_rc: Option>, fallback: &OptRc, panic: bool) -> SharedType +where + T: KStruct + Default + Any, + U: 'static, +{ + if let Some(rc) = opt_rc { + rc + } else { + let fallback_any: &dyn Any = &fallback.get(); + //println!("`{}` is a '{}' type", type_name_of_val(&t), type_name::>()); + if let Some(as_result) = fallback_any.downcast_ref::>() { + SharedType::::new(as_result.clone()) } else { - let fallback_any: &dyn Any = &fallback.get(); - //println!("`{}` is a '{}' type", type_name_of_val(&t), type_name::>()); - if let Some(as_result) = fallback_any.downcast_ref::>() { - SharedType::::new(as_result.clone()) - } else { - #[allow(clippy::incompatible_msrv)] // behind feature flag - #[allow(clippy::manual_assert)] - if panic { - #[cfg(feature = "type_name_of_val")] - panic!( - "`{}` is not a '{}' type", - std::any::type_name_of_val(&fallback), - type_name::>() - ); - #[cfg(not(feature = "type_name_of_val"))] - panic!("`{:p}` is not a '{}' type", &fallback, type_name::>()); - } - SharedType::::empty() + #[allow(clippy::incompatible_msrv)] // behind feature flag + #[allow(clippy::manual_assert)] + if panic { + #[cfg(feature = "type_name_of_val")] + panic!( + "`{}` is not a '{}' type", + std::any::type_name_of_val(&fallback), + type_name::>() + ); + #[cfg(not(feature = "type_name_of_val"))] + panic!("`{:p}` is not a '{}' type", &fallback, type_name::>()); } + SharedType::::empty() } } }