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..1666b99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,13 +2,36 @@ name = "kaitai" version = "0.2.0" authors = ["Bradlee Speice ", "Aon"] -edition = "2018" +edition = "2021" +rust-version = "1.63" + +[features] +type_name_of_val = [] + +[lints.rust] +redundant_imports = "warn" +trivial_casts = "warn" +unsafe_code = "forbid" +unused_qualifications = "warn" +[lints.clippy] +pedantic = { level = "warn", priority = -1 } +str_to_string = "warn" +min_ident_chars = "warn" +precedence_bits = "warn" + +derive_partial_eq_without_eq = "warn" +use_self = "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" -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" 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 4f35747..b1a335d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,8 @@ use encoding::{label::encoding_from_whatwg_label, DecoderTrap}; use flate2::read::ZlibDecoder; - use std::{ any::{type_name, Any}, cell::{Ref, RefCell, RefMut}, - convert::TryInto, fmt, io::{Read, Seek, SeekFrom}, ops::Deref, @@ -70,16 +68,17 @@ 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)), } } } 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))) } @@ -105,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(), } } @@ -118,10 +117,11 @@ 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) => OptRc::from(rc.clone()), - None => OptRc::default(), + Some(rc) => Self::from(rc.clone()), + None => Self::default(), } } @@ -129,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 } @@ -145,32 +146,31 @@ 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(v: Rc) -> Self { - OptRc(Some(v)) + fn from(value: Rc) -> Self { + Self(Some(value)) } } impl From for OptRc { - fn from(v: T) -> Self { - OptRc(Some(v.into())) + fn from(value: T) -> Self { + Self(Some(value.into())) } } impl Deref for OptRc { type Target = T; - #[inline(always)] fn deref(&self) -> &Self::Target { self.0.as_ref().unwrap() } @@ -189,60 +189,61 @@ 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 = downcast(_root, &output, true); + let parent = downcast(_parent, &output, 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 - where - T: KStruct + Default + Any, - U: 'static, - { - if let Some(rc) = opt_rc { - rc + _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 = 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 + } 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 t_any = &t.get() as &dyn Any; - //println!("`{}` is a '{}' type", type_name_of_val(&t), type_name::>()); - match t_any.downcast_ref::>() { - Some(as_result) => SharedType::::new(Rc::clone(as_result)), - None => { - if panic { - #[cfg(feature = "type_name_of_val")] - panic!( - "`{}` is not a '{}' type", - std::any::type_name_of_val(&t), - type_name::>() - ); - #[cfg(not(feature = "type_name_of_val"))] - panic!("`{:p}` is not a '{}' type", &t, 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() } } } @@ -250,12 +251,12 @@ 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 { - type Root = KStructUnit; - type Parent = KStructUnit; + type Root = Self; + type Parent = Self; fn read( _self_rc: &OptRc, @@ -295,6 +296,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) } @@ -352,8 +354,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(); @@ -377,8 +379,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 +413,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 { @@ -420,7 +422,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(); @@ -450,26 +452,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 +488,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 std::fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ReadSeek") + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "ReadSeek") } } @@ -507,45 +509,43 @@ 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()) } } 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); - Ok(BytesReader { + let file = std::fs::File::open(filename)?; + let file_size = file.metadata().unwrap().len(); + let readseek: Box = Box::new(file); + Ok(Self { 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)); - BytesReader { + let readseek: Box = Box::new(std::io::Cursor::new(bytes)); + Self { state: RefCell::new(ReaderState::default()), file_size, - buf: OptRc::from(RefCell::new(r)), + buf: OptRc::from(RefCell::new(readseek)), } } - // 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()?; + let cur_pos = self.buf.borrow_mut().stream_position()?; if self.pos() != cur_pos as usize { self.buf .borrow_mut() @@ -560,14 +560,15 @@ 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() } + #[allow(clippy::cast_possible_truncation)] // TODO: return as u64 fn size(&self) -> usize { self.file_size as usize } @@ -585,10 +586,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 +595,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) } @@ -608,8 +603,9 @@ 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) { + if let Some(last_non_pad_index) = bytes.iter().rposition(|&byte| byte != pad) { bytes[..=last_non_pad_index].to_vec() } else { vec![] @@ -618,18 +614,21 @@ 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 }] + if let Some(term_index) = bytes.iter().position(|&byte| byte == term) { + &bytes[..term_index + usize::from(include_term)] } else { bytes - }.to_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,15 +636,16 @@ 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 { - name: label.to_string(), + name: label.to_owned(), }) } +#[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 { @@ -654,6 +654,7 @@ pub fn process_xor_one(bytes: &Vec, key: u8) -> Vec { res } +#[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; @@ -667,6 +668,7 @@ pub fn process_xor_many(bytes: &Vec, key: &[u8]) -> Vec { res } +#[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 { @@ -675,19 +677,22 @@ 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(); - 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()) +#[allow(clippy::unnecessary_wraps)] // TODO: breaking change +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)] @@ -698,19 +703,19 @@ 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!([1, 2, 3, 4], c[..]); + 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]); + 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 { @@ -718,13 +723,13 @@ mod tests { available: 1 } ); - assert_eq!(reader.read_bytes(1).unwrap()[..], [8]); + assert_eq!(reader.read_bytes(1).unwrap(), [8]); } #[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); } @@ -732,8 +737,8 @@ mod tests { #[test] fn read_bits_multiple() { // 0xA0 - let b = vec![0b10100000]; - let reader = BytesReader::from(b); + let bytes = vec![0b1010_0000]; + 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); @@ -742,54 +747,45 @@ mod tests { #[test] fn read_bits_large() { - let b = vec![0b10100000]; - let reader = BytesReader::from(b); + let bytes = vec![0b1010_0000]; + 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(), KError::ReadBitsTooLarge { requested: 65 } - ) + ); } #[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()[..], + 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!( @@ -799,52 +795,51 @@ 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] ); } #[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!(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 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!(vec![0x65, 0x6C], res); + assert_eq!(res, [0x65, 0x6C]); } #[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); - let expected: Vec = vec![0x48, 0x65]; - assert_eq!(expected, res); + 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]); + 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(); } @@ -862,8 +857,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 { @@ -871,19 +866,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(); } }