diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 2b80e70..b57f396 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -13,6 +13,7 @@ env: jobs: test: strategy: + fail-fast: false matrix: os: - ubuntu-latest @@ -25,7 +26,7 @@ jobs: - os: ubuntu-latest rust: msrv lint: 1 - - rust: stable + - rust: msrv rust-args: --all-features runs-on: ${{ matrix.os }} steps: @@ -38,7 +39,7 @@ jobs: ver="${{ matrix.rust }}" if [ "$ver" = msrv ]; then ver=$(cargo metadata --format-version 1 --no-deps | \ - jq -r '.packages[0].rust_version') + jq -r 'first(.packages[] | select(.rust_version != null).rust_version)') extra=(-c rustfmt -c clippy) fi rustup toolchain install "$ver" --profile minimal --no-self-update "${extra[@]}" @@ -49,17 +50,10 @@ jobs: - uses: Swatinem/rust-cache@v2 - - name: Set serde-big-array to minimum version (0.4.1) - if: matrix.rust == 'msrv' - run: cargo update -p serde-big-array --precise 0.4.1 + - run: cargo test --workspace ${{ matrix.rust-args }} - - name: cargo test - run: cargo test --workspace ${{ matrix.rust-args }} - - - name: rustfmt + - run: cargo fmt --all -- --check if: github.event_name == 'pull_request' && matrix.lint - run: cargo fmt --all -- --check - - name: clippy + - run: cargo clippy --all --tests --all-features -- -D warnings if: github.event_name == 'pull_request' && matrix.lint - run: cargo clippy --all --tests --all-features -- -D warnings diff --git a/Cargo.toml b/Cargo.toml index 95e3059..ad879b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "mbrman" version = "0.5.4" authors = ["Cecile Tonglet "] edition = "2021" -rust-version = "1.56" +rust-version = "1.85" license = "MIT OR Apache-2.0" description = "MBR Partition Management in Rust" repository = "https://github.com/rust-disk-partition-management/mbrman" @@ -11,14 +11,14 @@ homepage = "https://github.com/rust-disk-partition-management/mbrman" documentation = "https://docs.rs/mbrman" readme = "README.md" keywords = ["mbr", "partition", "table", "filesystem", "disk"] -categories = [] +categories = ["filesystem"] include = ["src/**/*.rs", "tests/fixtures/*.img", "README.md", "LICENSE.Apache-2.0", "LICENSE.MIT"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] bitvec = "1.0.1" -bincode = "1.0.1" -serde = { version = "1.0.116", features = ["derive"] } -serde-big-array = ">= 0.4.1, < 0.6" -thiserror = "1.0.24" +bincode = { version = "2.0.1", features = ["serde"] } +serde = { version = "1.0.210", features = ["derive"] } +serde-big-array = "0.5.1" +thiserror = "2.0.12" diff --git a/src/lib.rs b/src/lib.rs index 9691885..4323040 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -156,7 +156,9 @@ #![deny(missing_docs)] -use bincode::{deserialize_from, serialize_into}; +use bincode::config::legacy; +use bincode::error::{DecodeError, EncodeError}; +use bincode::serde::{decode_from_std_read, encode_into_std_write}; use bitvec::prelude::*; use serde::de::{SeqAccess, Visitor}; use serde::ser::SerializeTuple; @@ -196,7 +198,10 @@ pub enum Error { LBAExceedsMaximumCylinders, /// Deserialization errors. #[error("deserialization failed")] - Deserialize(#[from] bincode::Error), + Deserialize(#[from] DecodeError), + /// Serialization errors. + #[error("Serialization failed")] + Serialize(#[from] EncodeError), /// I/O errors. #[error("generic I/O error")] Io(#[from] std::io::Error), @@ -377,7 +382,7 @@ impl MBR { S: Seek, { let disk_size = u32::try_from(seeker.seek(SeekFrom::End(0))? / u64::from(sector_size)) - .unwrap_or(u32::max_value()); + .unwrap_or(u32::MAX); let header = MBRHeader::new(disk_signature); Ok(MBR { @@ -402,12 +407,12 @@ impl MBR { /// let mbr = mbrman::MBR::read_from(&mut f, 512) /// .expect("could not read the partition table"); /// ``` - pub fn read_from(mut reader: &mut R, sector_size: u32) -> Result + pub fn read_from(mut reader: &mut R, sector_size: u32) -> Result where - R: Read + Seek, + R: Read + Seek + ?Sized, { let disk_size = u32::try_from(reader.seek(SeekFrom::End(0))? / u64::from(sector_size)) - .unwrap_or(u32::max_value()); + .unwrap_or(u32::MAX); let header = MBRHeader::read_from(&mut reader)?; let mut logical_partitions = Vec::new(); @@ -481,13 +486,13 @@ impl MBR { /// Updates the header to match the specifications of the seeker given in argument. /// `disk_size` will be updated after this operation. - pub fn update_from(&mut self, seeker: &mut S) -> Result<()> + pub fn update_from(&mut self, seeker: &mut S) -> Result<()> where - S: Seek, + S: Seek + ?Sized, { self.disk_size = u32::try_from(seeker.seek(SeekFrom::End(0))? / u64::from(self.sector_size)) - .unwrap_or(u32::max_value()); + .unwrap_or(u32::MAX); Ok(()) } @@ -549,9 +554,9 @@ impl MBR { /// mbr.write_into(&mut cur) /// .expect("could not write MBR to disk") /// ``` - pub fn write_into(&mut self, mut writer: &mut W) -> Result<()> + pub fn write_into(&mut self, mut writer: &mut W) -> Result<()> where - W: Write + Seek, + W: Write + Seek + ?Sized, { self.header.write_into(&mut writer)?; @@ -588,11 +593,10 @@ impl MBR { writer.seek(SeekFrom::Start(u64::from( l.absolute_ebr_lba * self.sector_size, )))?; - serialize_into(&mut writer, &BootstrapCode446(l.bootstrap_code))?; - serialize_into(&mut writer, &partition)?; + encode_into_std_write(BootstrapCode446(l.bootstrap_code), &mut writer, legacy())?; + encode_into_std_write(&partition, &mut writer, legacy())?; if let Some(next) = next { - serialize_into( - &mut writer, + encode_into_std_write( &MBRPartitionEntry { boot: BOOT_INACTIVE, first_chs: next.ebr_first_chs, @@ -603,12 +607,14 @@ impl MBR { .saturating_sub(extended.starting_lba), sectors: next.ebr_sectors.unwrap(), }, + &mut writer, + legacy(), )?; } else { - serialize_into(&mut writer, &MBRPartitionEntry::empty())?; + encode_into_std_write(MBRPartitionEntry::empty(), &mut writer, legacy())?; } writer.write_all(&[0; 16 * 2])?; - serialize_into(&mut writer, &BOOT_SIGNATURE)?; + encode_into_std_write(BOOT_SIGNATURE, &mut writer, legacy())?; } } @@ -1128,12 +1134,12 @@ impl MBRHeader { /// Attempt to read a MBR header from a reader. This operation will seek at the /// correct location before trying to write to disk. - pub fn read_from(mut reader: &mut R) -> Result + pub fn read_from(mut reader: &mut R) -> Result where - R: Read + Seek, + R: Read + Seek + ?Sized, { reader.seek(SeekFrom::Start(0))?; - let header: Self = deserialize_from(&mut reader)?; + let header: Self = decode_from_std_read(&mut reader, legacy())?; header.check()?; Ok(header) } @@ -1154,13 +1160,13 @@ impl MBRHeader { /// Write the MBR header into a writer. This operation will seek at the /// correct location before trying to write to disk. - pub fn write_into(&self, mut writer: &mut W) -> Result<()> + pub fn write_into(&self, mut writer: &mut W) -> Result<()> where - W: Write + Seek, + W: Write + Seek + ?Sized, { self.check()?; writer.seek(SeekFrom::Start(0))?; - serialize_into(&mut writer, &self)?; + encode_into_std_write(self, &mut writer, legacy())?; Ok(()) } @@ -1178,14 +1184,14 @@ impl Index for MBRHeader { type Output = MBRPartitionEntry; fn index(&self, i: usize) -> &Self::Output { - assert!(i != 0, "invalid partition index: 0"); + assert_ne!(i, 0, "invalid partition index: 0"); self.get(i).expect("invalid partition") } } impl IndexMut for MBRHeader { fn index_mut(&mut self, i: usize) -> &mut Self::Output { - assert!(i != 0, "invalid partition index: 0"); + assert_ne!(i, 0, "invalid partition index: 0"); self.get_mut(i).expect("invalid partition") } } @@ -1202,11 +1208,11 @@ struct EBRHeader { } impl EBRHeader { - fn read_from(reader: &mut R) -> Result + fn read_from(reader: &mut R) -> Result where R: Read, { - let header: Self = deserialize_from(reader)?; + let header: Self = decode_from_std_read(reader, legacy())?; header.check()?; Ok(header) } @@ -1562,6 +1568,7 @@ impl Serialize for CHS { #[allow(clippy::cognitive_complexity)] mod tests { use super::*; + use bincode::serde::{decode_from_slice, encode_into_slice}; use std::fs::File; use std::io::Cursor; @@ -1570,7 +1577,7 @@ mod tests { #[test] fn deserialize_maximum_chs_value() { - let chs: CHS = bincode::deserialize(&[0xff, 0xff, 0xff]).unwrap(); + let chs: CHS = decode_from_slice(&[0xff, 0xff, 0xff], legacy()).unwrap().0; assert_eq!( chs, CHS { @@ -1588,13 +1595,16 @@ mod tests { head: 255, sector: 63, }; - let out = bincode::serialize(&chs).unwrap(); - assert_eq!(out, &[0xff, 0xff, 0xff]); + let mut slice = [0; 3]; + encode_into_slice(chs, &mut slice, legacy()).unwrap(); + for element in slice { + assert_eq!(element, 0xff); + } } #[test] fn serialize_and_deserialize_some_chs_value() { - let chs: CHS = bincode::deserialize(&[0xaa, 0xaa, 0xaa]).unwrap(); + let chs: CHS = decode_from_slice(&[0xaa, 0xaa, 0xaa], legacy()).unwrap().0; assert_eq!( chs, CHS { @@ -1603,8 +1613,11 @@ mod tests { sector: 42, } ); - let out = bincode::serialize(&chs).unwrap(); - assert_eq!(out, &[0xaa, 0xaa, 0xaa]); + let mut slice = [0; 3]; + encode_into_slice(chs, &mut slice, legacy()).unwrap(); + for element in slice { + assert_eq!(element, 0xaa); + } } #[test] @@ -1707,7 +1720,7 @@ mod tests { assert_eq!( CHS::from_lba_exact( mbr.logical_partitions[2].partition.starting_lba, - u16::max_value(), + u16::MAX, 2, 3 ) @@ -2042,7 +2055,8 @@ mod tests { mbr.header.partition_1.sys = 0x0f; mbr.header.partition_1.starting_lba = 1; mbr.header.partition_1.sectors = 10; - mbr.push(0x0f, 1, 9).unwrap().partition.boot = BOOT_ACTIVE | 0x01; + let partition = mbr.push(0x0f, 1, 9).unwrap(); + partition.partition.boot = BOOT_ACTIVE | 0x01; assert!(matches!( mbr.write_into(&mut cur).unwrap_err(), Error::InvalidBootFlag