diff --git a/Cargo.lock b/Cargo.lock index cc19448..7521ca0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,12 +85,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "bzip2" version = "0.4.4" @@ -123,9 +117,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.18" +version = "1.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938" dependencies = [ "jobserver", "libc", @@ -352,9 +346,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "liblzma" @@ -367,9 +361,9 @@ dependencies = [ [[package]] name = "liblzma-sys" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "885d379719f1be90c51852451dc658009c1aab2eb867cae8d5eb7f83bfaaca96" +checksum = "6630cb23edeb2e563cd6c30d4117554c69646871455843c33ddcb1d9aef82ecf" dependencies = [ "cc", "libc", @@ -515,9 +509,12 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] [[package]] name = "overload" @@ -533,15 +530,15 @@ checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "portable-atomic" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "proc-macro2" @@ -566,9 +563,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.36.1" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a05e2e8efddfa51a84ca47cec303fac86c8541b686d37cac5efc0e094417bc" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" dependencies = [ "memchr", "serde", @@ -605,14 +602,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -626,13 +623,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -643,9 +640,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "serde" @@ -664,7 +661,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -737,9 +734,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -748,22 +745,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -795,7 +792,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -854,15 +851,15 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "valuable" @@ -1036,23 +1033,22 @@ checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "df7885ffcb82507a0f213c593e77c5f13d12cb96588d4e835ad7e9423ba034db" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "930ad75608219e8ffdb8962a5433cb2b30064c7ccb564d3b76c2963390b1e435" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] diff --git a/nod/Cargo.toml b/nod/Cargo.toml index 6120e7a..fee964b 100644 --- a/nod/Cargo.toml +++ b/nod/Cargo.toml @@ -38,5 +38,5 @@ miniz_oxide = { version = "0.8", optional = true } rayon = "1.10" sha1 = "0.10" thiserror = "1.0" -zerocopy = { version = "0.7", features = ["alloc", "derive"] } +zerocopy = { version = "0.8", features = ["alloc", "derive"] } zstd = { version = "0.13", optional = true } diff --git a/nod/src/disc/fst.rs b/nod/src/disc/fst.rs index 716602b..af15e85 100644 --- a/nod/src/disc/fst.rs +++ b/nod/src/disc/fst.rs @@ -3,7 +3,7 @@ use std::{borrow::Cow, ffi::CStr, mem::size_of}; use encoding_rs::SHIFT_JIS; -use zerocopy::{big_endian::*, AsBytes, FromBytes, FromZeroes}; +use zerocopy::{big_endian::*, FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{static_assert, Result}; @@ -19,7 +19,7 @@ pub enum NodeKind { } /// An individual file system node. -#[derive(Copy, Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Copy, Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct Node { kind: u8, @@ -89,7 +89,7 @@ impl<'a> Fst<'a> { /// Create a new FST view from a buffer. #[allow(clippy::missing_inline_in_public_items)] pub fn new(buf: &'a [u8]) -> Result { - let Some(root_node) = Node::ref_from_prefix(buf) else { + let Ok((root_node, _)) = Node::ref_from_prefix(buf) else { return Err("FST root node not found"); }; // String table starts after the last node @@ -98,7 +98,7 @@ impl<'a> Fst<'a> { return Err("FST string table out of bounds"); } let (node_buf, string_table) = buf.split_at(string_base as usize); - let nodes = Node::slice_from(node_buf).unwrap(); + let nodes = <[Node]>::ref_from_bytes(node_buf).unwrap(); Ok(Self { nodes, string_table }) } diff --git a/nod/src/disc/gcn.rs b/nod/src/disc/gcn.rs index b51518a..3d39b6c 100644 --- a/nod/src/disc/gcn.rs +++ b/nod/src/disc/gcn.rs @@ -4,7 +4,7 @@ use std::{ mem::size_of, }; -use zerocopy::{FromBytes, FromZeroes}; +use zerocopy::{FromBytes, FromZeros}; use super::{ ApploaderHeader, DiscHeader, DolHeader, FileStream, Node, PartitionBase, PartitionHeader, @@ -33,9 +33,9 @@ impl Clone for PartitionGC { Self { io: self.io.clone(), block: Block::default(), - block_buf: ::new_box_slice_zeroed(self.block_buf.len()), + block_buf: <[u8]>::new_box_zeroed_with_elems(self.block_buf.len()).unwrap(), block_idx: u32::MAX, - sector_buf: <[u8; SECTOR_SIZE]>::new_box_zeroed(), + sector_buf: <[u8; SECTOR_SIZE]>::new_box_zeroed().unwrap(), sector: u32::MAX, pos: 0, disc_header: self.disc_header.clone(), @@ -49,9 +49,9 @@ impl PartitionGC { Ok(Box::new(Self { io: inner, block: Block::default(), - block_buf: ::new_box_slice_zeroed(block_size as usize), + block_buf: <[u8]>::new_box_zeroed_with_elems(block_size as usize).unwrap(), block_idx: u32::MAX, - sector_buf: <[u8; SECTOR_SIZE]>::new_box_zeroed(), + sector_buf: <[u8; SECTOR_SIZE]>::new_box_zeroed().unwrap(), sector: u32::MAX, pos: 0, disc_header, @@ -151,7 +151,8 @@ pub(crate) fn read_part_meta( ) -> Result> { // boot.bin let raw_boot: Box<[u8; BOOT_SIZE]> = read_box(reader).context("Reading boot.bin")?; - let partition_header = PartitionHeader::ref_from(&raw_boot[size_of::()..]).unwrap(); + let partition_header = + PartitionHeader::ref_from_bytes(&raw_boot[size_of::()..]).unwrap(); // bi2.bin let raw_bi2: Box<[u8; BI2_SIZE]> = read_box(reader).context("Reading bi2.bin")?; @@ -159,7 +160,7 @@ pub(crate) fn read_part_meta( // apploader.bin let mut raw_apploader: Vec = read_vec(reader, size_of::()).context("Reading apploader header")?; - let apploader_header = ApploaderHeader::ref_from(raw_apploader.as_slice()).unwrap(); + let apploader_header = ApploaderHeader::ref_from_bytes(raw_apploader.as_slice()).unwrap(); raw_apploader.resize( size_of::() + apploader_header.size.get() as usize @@ -189,7 +190,7 @@ pub(crate) fn read_part_meta( .context("Seeking to DOL offset")?; let mut raw_dol: Vec = read_vec(reader, size_of::()).context("Reading DOL header")?; - let dol_header = DolHeader::ref_from(raw_dol.as_slice()).unwrap(); + let dol_header = DolHeader::ref_from_bytes(raw_dol.as_slice()).unwrap(); let dol_size = dol_header .text_offs .iter() diff --git a/nod/src/disc/hashes.rs b/nod/src/disc/hashes.rs index 7019374..a9e0392 100644 --- a/nod/src/disc/hashes.rs +++ b/nod/src/disc/hashes.rs @@ -6,7 +6,7 @@ use std::{ use rayon::iter::{IntoParallelIterator, ParallelIterator}; use sha1::{Digest, Sha1}; -use zerocopy::FromZeroes; +use zerocopy::FromZeros; use crate::{ array_ref, array_ref_mut, @@ -39,7 +39,7 @@ pub struct HashTable { pub h3_hashes: Box<[HashBytes]>, } -#[derive(Clone, FromZeroes)] +#[derive(Clone, FromZeros)] struct HashResult { h0_hashes: [HashBytes; 1984], h1_hashes: [HashBytes; 64], @@ -54,10 +54,10 @@ impl HashTable { let num_subgroups = num_sectors / 8; let num_groups = num_subgroups / 8; Self { - h0_hashes: HashBytes::new_box_slice_zeroed(num_data_hashes), - h1_hashes: HashBytes::new_box_slice_zeroed(num_sectors), - h2_hashes: HashBytes::new_box_slice_zeroed(num_subgroups), - h3_hashes: HashBytes::new_box_slice_zeroed(num_groups), + h0_hashes: <[HashBytes]>::new_box_zeroed_with_elems(num_data_hashes).unwrap(), + h1_hashes: <[HashBytes]>::new_box_zeroed_with_elems(num_sectors).unwrap(), + h2_hashes: <[HashBytes]>::new_box_zeroed_with_elems(num_subgroups).unwrap(), + h3_hashes: <[HashBytes]>::new_box_zeroed_with_elems(num_groups).unwrap(), } } @@ -100,8 +100,8 @@ pub fn rebuild_hashes(reader: &mut DiscReader) -> Result<()> { (0..group_count).into_par_iter().try_for_each_with( (reader.open_partition(part.index, &OpenOptions::default())?, mutex.clone()), |(stream, mutex), h3_index| -> Result<()> { - let mut result = HashResult::new_box_zeroed(); - let mut data_buf = ::new_box_slice_zeroed(SECTOR_DATA_SIZE); + let mut result = HashResult::new_box_zeroed()?; + let mut data_buf = <[u8]>::new_box_zeroed_with_elems(SECTOR_DATA_SIZE)?; let mut h3_hasher = Sha1::new(); for h2_index in 0..8 { let mut h2_hasher = Sha1::new(); diff --git a/nod/src/disc/mod.rs b/nod/src/disc/mod.rs index d5178cf..e48e9da 100644 --- a/nod/src/disc/mod.rs +++ b/nod/src/disc/mod.rs @@ -11,7 +11,7 @@ use std::{ }; use dyn_clone::DynClone; -use zerocopy::{big_endian::*, AsBytes, FromBytes, FromZeroes}; +use zerocopy::{big_endian::*, FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{io::MagicBytes, static_assert, Result}; @@ -38,7 +38,7 @@ pub const GCN_MAGIC: MagicBytes = [0xC2, 0x33, 0x9F, 0x3D]; /// Shared GameCube & Wii disc header. /// /// This header is always at the start of the disc image and within each Wii partition. -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct DiscHeader { /// Game ID (e.g. GM8E01 for Metroid Prime) @@ -97,7 +97,7 @@ impl DiscHeader { /// **GameCube**: Always follows the disc header. /// /// **Wii**: Follows the disc header within each partition. -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct PartitionHeader { /// Debug monitor offset @@ -169,7 +169,7 @@ impl PartitionHeader { } /// Apploader header. -#[derive(Debug, PartialEq, Clone, FromBytes, FromZeroes, AsBytes)] +#[derive(Debug, PartialEq, Clone, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct ApploaderHeader { /// Apploader build date @@ -198,7 +198,7 @@ pub const DOL_MAX_TEXT_SECTIONS: usize = 7; pub const DOL_MAX_DATA_SECTIONS: usize = 11; /// Dolphin executable (DOL) header. -#[derive(Debug, Clone, FromBytes, FromZeroes)] +#[derive(Debug, Clone, FromBytes, Immutable, KnownLayout)] pub struct DolHeader { /// Text section offsets pub text_offs: [U32; DOL_MAX_TEXT_SECTIONS], @@ -379,19 +379,19 @@ impl PartitionMeta { /// A view into the disc header. #[inline] pub fn header(&self) -> &DiscHeader { - DiscHeader::ref_from(&self.raw_boot[..size_of::()]).unwrap() + DiscHeader::ref_from_bytes(&self.raw_boot[..size_of::()]).unwrap() } /// A view into the partition header. #[inline] pub fn partition_header(&self) -> &PartitionHeader { - PartitionHeader::ref_from(&self.raw_boot[size_of::()..]).unwrap() + PartitionHeader::ref_from_bytes(&self.raw_boot[size_of::()..]).unwrap() } /// A view into the apploader header. #[inline] pub fn apploader_header(&self) -> &ApploaderHeader { - ApploaderHeader::ref_from_prefix(&self.raw_apploader).unwrap() + ApploaderHeader::ref_from_prefix(&self.raw_apploader).unwrap().0 } /// A view into the file system table (FST). @@ -400,18 +400,18 @@ impl PartitionMeta { /// A view into the DOL header. #[inline] - pub fn dol_header(&self) -> &DolHeader { DolHeader::ref_from_prefix(&self.raw_dol).unwrap() } + pub fn dol_header(&self) -> &DolHeader { DolHeader::ref_from_prefix(&self.raw_dol).unwrap().0 } /// A view into the ticket. (Wii only) #[inline] pub fn ticket(&self) -> Option<&Ticket> { - self.raw_ticket.as_ref().and_then(|v| Ticket::ref_from(v)) + self.raw_ticket.as_ref().and_then(|v| Ticket::ref_from_bytes(v).ok()) } /// A view into the TMD. (Wii only) #[inline] pub fn tmd_header(&self) -> Option<&TmdHeader> { - self.raw_tmd.as_ref().and_then(|v| TmdHeader::ref_from_prefix(v)) + self.raw_tmd.as_ref().and_then(|v| TmdHeader::ref_from_prefix(v).ok().map(|(v, _)| v)) } } diff --git a/nod/src/disc/reader.rs b/nod/src/disc/reader.rs index 52ff0a9..1cf154e 100644 --- a/nod/src/disc/reader.rs +++ b/nod/src/disc/reader.rs @@ -3,7 +3,7 @@ use std::{ io::{BufRead, Read, Seek, SeekFrom}, }; -use zerocopy::FromZeroes; +use zerocopy::FromZeros; use super::{ gcn::PartitionGC, @@ -43,9 +43,9 @@ impl Clone for DiscReader { Self { io: self.io.clone(), block: Block::default(), - block_buf: ::new_box_slice_zeroed(self.block_buf.len()), + block_buf: <[u8]>::new_box_zeroed_with_elems(self.block_buf.len()).unwrap(), block_idx: u32::MAX, - sector_buf: <[u8; SECTOR_SIZE]>::new_box_zeroed(), + sector_buf: <[u8; SECTOR_SIZE]>::new_box_zeroed().unwrap(), sector_idx: u32::MAX, pos: 0, mode: self.mode, @@ -63,9 +63,9 @@ impl DiscReader { let mut reader = Self { io: inner, block: Block::default(), - block_buf: ::new_box_slice_zeroed(block_size as usize), + block_buf: <[u8]>::new_box_zeroed_with_elems(block_size as usize)?, block_idx: u32::MAX, - sector_buf: <[u8; SECTOR_SIZE]>::new_box_zeroed(), + sector_buf: <[u8; SECTOR_SIZE]>::new_box_zeroed()?, sector_idx: u32::MAX, pos: 0, mode: if options.rebuild_encryption { @@ -73,7 +73,7 @@ impl DiscReader { } else { EncryptionMode::Decrypted }, - disc_header: DiscHeader::new_box_zeroed(), + disc_header: DiscHeader::new_box_zeroed()?, partitions: vec![], hash_tables: vec![], }; @@ -278,8 +278,8 @@ fn read_partition_info(reader: &mut DiscReader) -> Result> { data_end_sector: (data_end_offset / SECTOR_SIZE as u64) as u32, key, header, - disc_header: DiscHeader::new_box_zeroed(), - partition_header: PartitionHeader::new_box_zeroed(), + disc_header: DiscHeader::new_box_zeroed()?, + partition_header: PartitionHeader::new_box_zeroed()?, hash_table: None, }; diff --git a/nod/src/disc/wii.rs b/nod/src/disc/wii.rs index df3aac7..609c283 100644 --- a/nod/src/disc/wii.rs +++ b/nod/src/disc/wii.rs @@ -6,7 +6,7 @@ use std::{ }; use sha1::{Digest, Sha1}; -use zerocopy::{big_endian::*, AsBytes, FromBytes, FromZeroes}; +use zerocopy::{big_endian::*, FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; use super::{ gcn::{read_part_meta, PartitionGC}, @@ -55,7 +55,7 @@ const DEBUG_COMMON_KEYS: [KeyBytes; 3] = [ [0x2f, 0x5c, 0x1b, 0x29, 0x44, 0xe7, 0xfd, 0x6f, 0xc3, 0x97, 0x96, 0x4b, 0x05, 0x76, 0x91, 0xfa], ]; -#[derive(Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub(crate) struct WiiPartEntry { pub(crate) offset: U32, @@ -70,7 +70,7 @@ impl WiiPartEntry { pub(crate) const WII_PART_GROUP_OFF: u64 = 0x40000; -#[derive(Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub(crate) struct WiiPartGroup { pub(crate) part_count: U32, @@ -84,7 +84,7 @@ impl WiiPartGroup { } /// Signed blob header -#[derive(Debug, Clone, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Debug, Clone, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct SignedHeader { /// Signature type, always 0x00010001 (RSA-2048) @@ -97,7 +97,7 @@ pub struct SignedHeader { static_assert!(size_of::() == 0x140); /// Ticket limit -#[derive(Debug, Clone, PartialEq, Default, FromBytes, FromZeroes, AsBytes)] +#[derive(Debug, Clone, PartialEq, Default, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct TicketLimit { /// Limit type @@ -109,7 +109,7 @@ pub struct TicketLimit { static_assert!(size_of::() == 8); /// Wii ticket -#[derive(Debug, Clone, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Debug, Clone, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct Ticket { /// Signed blob header @@ -179,7 +179,7 @@ impl Ticket { } /// Title metadata header -#[derive(Debug, Clone, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Debug, Clone, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct TmdHeader { /// Signed blob header @@ -227,7 +227,7 @@ static_assert!(size_of::() == 0x1E4); pub const H3_TABLE_SIZE: usize = 0x18000; -#[derive(Debug, Clone, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Debug, Clone, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct WiiPartitionHeader { pub ticket: Ticket, @@ -281,9 +281,9 @@ impl Clone for PartitionWii { io: self.io.clone(), partition: self.partition.clone(), block: Block::default(), - block_buf: ::new_box_slice_zeroed(self.block_buf.len()), + block_buf: <[u8]>::new_box_zeroed_with_elems(self.block_buf.len()).unwrap(), block_idx: u32::MAX, - sector_buf: <[u8; SECTOR_SIZE]>::new_box_zeroed(), + sector_buf: <[u8; SECTOR_SIZE]>::new_box_zeroed().unwrap(), sector: u32::MAX, pos: 0, verify: self.verify, @@ -327,9 +327,9 @@ impl PartitionWii { io: reader.into_inner(), partition: partition.clone(), block: Block::default(), - block_buf: ::new_box_slice_zeroed(block_size as usize), + block_buf: <[u8]>::new_box_zeroed_with_elems(block_size as usize)?, block_idx: u32::MAX, - sector_buf: <[u8; SECTOR_SIZE]>::new_box_zeroed(), + sector_buf: <[u8; SECTOR_SIZE]>::new_box_zeroed()?, sector: u32::MAX, pos: 0, verify: options.validate_hashes, diff --git a/nod/src/io/ciso.rs b/nod/src/io/ciso.rs index 9a5dbfb..89b81f2 100644 --- a/nod/src/io/ciso.rs +++ b/nod/src/io/ciso.rs @@ -4,7 +4,7 @@ use std::{ mem::size_of, }; -use zerocopy::{little_endian::*, AsBytes, FromBytes, FromZeroes}; +use zerocopy::{little_endian::*, FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{ disc::SECTOR_SIZE, @@ -21,7 +21,7 @@ use crate::{ pub const CISO_MAP_SIZE: usize = SECTOR_SIZE - 8; /// CISO header (little endian) -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] struct CISOHeader { magic: MagicBytes, diff --git a/nod/src/io/gcz.rs b/nod/src/io/gcz.rs index 8570777..94ae326 100644 --- a/nod/src/io/gcz.rs +++ b/nod/src/io/gcz.rs @@ -6,7 +6,7 @@ use std::{ use adler::adler32_slice; use miniz_oxide::{inflate, inflate::core::inflate_flags}; -use zerocopy::{little_endian::*, AsBytes, FromBytes, FromZeroes}; +use zerocopy::{little_endian::*, FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; use zstd::zstd_safe::WriteBuf; use crate::{ @@ -20,7 +20,7 @@ use crate::{ }; /// GCZ header (little endian) -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] struct GCZHeader { magic: MagicBytes, @@ -49,7 +49,7 @@ impl Clone for DiscIOGCZ { header: self.header.clone(), block_map: self.block_map.clone(), block_hashes: self.block_hashes.clone(), - block_buf: ::new_box_slice_zeroed(self.block_buf.len()), + block_buf: <[u8]>::new_box_zeroed_with_elems(self.block_buf.len()).unwrap(), data_offset: self.data_offset, } } @@ -73,7 +73,7 @@ impl DiscIOGCZ { // header + block_count * (u64 + u32) let data_offset = size_of::() as u64 + block_count as u64 * 12; - let block_buf = ::new_box_slice_zeroed(header.block_size.get() as usize); + let block_buf = <[u8]>::new_box_zeroed_with_elems(header.block_size.get() as usize)?; Ok(Box::new(Self { inner, header, block_map, block_hashes, block_buf, data_offset })) } } diff --git a/nod/src/io/nfs.rs b/nod/src/io/nfs.rs index 1d486fc..776ecb7 100644 --- a/nod/src/io/nfs.rs +++ b/nod/src/io/nfs.rs @@ -6,7 +6,7 @@ use std::{ path::{Component, Path, PathBuf}, }; -use zerocopy::{big_endian::U32, AsBytes, FromBytes, FromZeroes}; +use zerocopy::{big_endian::U32, FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; use crate::{ disc::SECTOR_SIZE, @@ -23,14 +23,14 @@ use crate::{ pub const NFS_END_MAGIC: MagicBytes = *b"SGGE"; -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] struct LBARange { start_sector: U32, num_sectors: U32, } -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] struct NFSHeader { magic: MagicBytes, diff --git a/nod/src/io/tgc.rs b/nod/src/io/tgc.rs index 6f1a17b..1da150a 100644 --- a/nod/src/io/tgc.rs +++ b/nod/src/io/tgc.rs @@ -4,7 +4,7 @@ use std::{ mem::size_of, }; -use zerocopy::{big_endian::U32, AsBytes, FromBytes, FromZeroes}; +use zerocopy::{big_endian::U32, FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{ disc::SECTOR_SIZE, @@ -17,7 +17,7 @@ use crate::{ }; /// TGC header (big endian) -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] struct TGCHeader { /// Magic bytes @@ -75,11 +75,11 @@ impl DiscIOTGC { .context("Seeking to TGC FST")?; let mut fst = read_box_slice(inner.as_mut(), header.fst_size.get() as usize) .context("Reading TGC FST")?; - let root_node = Node::ref_from_prefix(&fst) - .ok_or_else(|| Error::DiscFormat("Invalid TGC FST".to_string()))?; + let (root_node, _) = Node::ref_from_prefix(&fst) + .map_err(|_| Error::DiscFormat("Invalid TGC FST".to_string()))?; let node_count = root_node.length() as usize; - let (nodes, _) = Node::mut_slice_from_prefix(&mut fst, node_count) - .ok_or_else(|| Error::DiscFormat("Invalid TGC FST".to_string()))?; + let (nodes, _) = <[Node]>::mut_from_prefix_with_elems(&mut fst, node_count) + .map_err(|_| Error::DiscFormat("Invalid TGC FST".to_string()))?; for node in nodes { if node.is_file() { node.offset = node.offset - header.gcm_user_offset @@ -116,7 +116,7 @@ impl BlockIO for DiscIOTGC { // Adjust internal GCM header if block == 0 { - let partition_header = PartitionHeader::mut_from( + let partition_header = PartitionHeader::mut_from_bytes( &mut out[size_of::() ..size_of::() + size_of::()], ) diff --git a/nod/src/io/wbfs.rs b/nod/src/io/wbfs.rs index 7fb1d80..d5c7327 100644 --- a/nod/src/io/wbfs.rs +++ b/nod/src/io/wbfs.rs @@ -4,7 +4,7 @@ use std::{ mem::size_of, }; -use zerocopy::{big_endian::*, AsBytes, FromBytes, FromZeroes}; +use zerocopy::{big_endian::*, FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{ io::{ @@ -16,7 +16,7 @@ use crate::{ Error, Result, ResultContext, }; -#[derive(Debug, Clone, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Debug, Clone, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] struct WBFSHeader { magic: MagicBytes, diff --git a/nod/src/io/wia.rs b/nod/src/io/wia.rs index d85d53c..f33eea0 100644 --- a/nod/src/io/wia.rs +++ b/nod/src/io/wia.rs @@ -4,7 +4,7 @@ use std::{ mem::size_of, }; -use zerocopy::{big_endian::*, AsBytes, FromBytes, FromZeroes}; +use zerocopy::{big_endian::*, FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{ disc::{ @@ -28,7 +28,7 @@ use crate::{ /// This struct is stored at offset 0x0 and is 0x48 bytes long. The wit source code says its format /// will never be changed. -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct WIAFileHeader { pub magic: MagicBytes, @@ -142,7 +142,7 @@ impl TryFrom for WIACompression { const DISC_HEAD_SIZE: usize = 0x80; /// This struct is stored at offset 0x48, immediately after [WIAFileHeader]. -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct WIADisc { /// The disc type. (1 = GameCube, 2 = Wii) @@ -236,7 +236,7 @@ impl WIADisc { } } -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct WIAPartitionData { /// The sector on the disc at which this data starts. @@ -271,7 +271,7 @@ impl WIAPartitionData { /// the reading program must first recalculate the hashes as done when creating a Wii disc image /// from scratch (see ), and must then apply the hash exceptions /// which are stored along with the data (see the [WIAExceptionList] section). -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct WIAPartition { /// The title key for this partition (128-bit AES), which can be used for re-encrypting the @@ -298,7 +298,7 @@ static_assert!(size_of::() == 0x30); /// should be read from [WIADisc] instead.) This should be handled by rounding the offset down to /// the previous multiple of 0x8000 (and adding the equivalent amount to the size so that the end /// offset stays the same), not by special casing the first [WIARawData]. -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct WIARawData { /// The offset on the disc at which this data starts. @@ -336,7 +336,7 @@ impl WIARawData { /// counting any [WIAExceptionList] structs. However, the last [WIAGroup] of a [WIAPartitionData] /// or [WIARawData] contains less data than that if `num_sectors * 0x8000` (for [WIAPartitionData]) /// or `raw_data_size` (for [WIARawData]) is not evenly divisible by `chunk_size`. -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct WIAGroup { /// The offset in the file where the compressed data is stored. @@ -351,7 +351,7 @@ pub struct WIAGroup { /// Compared to [WIAGroup], [RVZGroup] changes the meaning of the most significant bit of /// [data_size](Self::data_size) and adds one additional attribute. -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] pub struct RVZGroup { /// The offset in the file where the compressed data is stored, divided by 4. @@ -398,7 +398,7 @@ impl From<&WIAGroup> for RVZGroup { /// write [WIAException] structs for a padding area which is 32 bytes long, it writes one which /// covers the first 20 bytes of the padding area and one which covers the last 20 bytes of the /// padding area, generating 12 bytes of overlap between the [WIAException] structs. -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Clone, Debug, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(2))] pub struct WIAException { /// The offset among the hashes. The offsets 0x0000-0x0400 here map to the offsets 0x0000-0x0400 @@ -559,7 +559,7 @@ impl DiscIOWIA { .context("Reading WIA/RVZ disc header")?; verify_hash(&disc_buf, &header.disc_hash)?; disc_buf.resize(size_of::(), 0); - let disc = WIADisc::read_from(disc_buf.as_slice()).unwrap(); + let disc = WIADisc::read_from_bytes(disc_buf.as_slice()).unwrap(); disc.validate()?; // if !options.rebuild_hashes { // // If we're not rebuilding hashes, disable partition hashes in disc header diff --git a/nod/src/lib.rs b/nod/src/lib.rs index b726ee4..5a9f6d4 100644 --- a/nod/src/lib.rs +++ b/nod/src/lib.rs @@ -89,6 +89,9 @@ pub enum Error { /// An unknown error. #[error("error: {0}")] Other(String), + /// An error occurred while allocating memory. + #[error("allocation failed")] + Alloc(zerocopy::AllocError), } impl From<&str> for Error { @@ -101,6 +104,11 @@ impl From for Error { fn from(s: String) -> Error { Error::Other(s) } } +impl From for Error { + #[inline] + fn from(e: zerocopy::AllocError) -> Error { Error::Alloc(e) } +} + /// Helper result type for [`Error`]. pub type Result = core::result::Result; diff --git a/nod/src/util/lfg.rs b/nod/src/util/lfg.rs index 15c5039..211c84b 100644 --- a/nod/src/util/lfg.rs +++ b/nod/src/util/lfg.rs @@ -1,6 +1,6 @@ use std::{cmp::min, io, io::Read}; -use zerocopy::{transmute_ref, AsBytes}; +use zerocopy::{transmute_ref, IntoBytes}; use crate::disc::SECTOR_SIZE; @@ -64,7 +64,7 @@ impl LaggedFibonacci { pub fn init_with_reader(&mut self, reader: &mut R) -> io::Result<()> where R: Read + ?Sized { - reader.read_exact(self.buffer[..SEED_SIZE].as_bytes_mut())?; + reader.read_exact(self.buffer[..SEED_SIZE].as_mut_bytes())?; for x in self.buffer[..SEED_SIZE].iter_mut() { *x = u32::from_be(*x); } diff --git a/nod/src/util/read.rs b/nod/src/util/read.rs index df1d4dc..b0b30b8 100644 --- a/nod/src/util/read.rs +++ b/nod/src/util/read.rs @@ -1,48 +1,50 @@ use std::{io, io::Read}; -use zerocopy::{AsBytes, FromBytes, FromZeroes}; +use zerocopy::{FromBytes, FromZeros, IntoBytes}; #[inline(always)] pub fn read_from(reader: &mut R) -> io::Result where - T: FromBytes + FromZeroes + AsBytes, + T: FromBytes + IntoBytes, R: Read + ?Sized, { let mut ret = ::new_zeroed(); - reader.read_exact(ret.as_bytes_mut())?; + reader.read_exact(ret.as_mut_bytes())?; Ok(ret) } #[inline(always)] pub fn read_vec(reader: &mut R, count: usize) -> io::Result> where - T: FromBytes + FromZeroes + AsBytes, + T: FromBytes + IntoBytes, R: Read + ?Sized, { - let mut ret = ::new_vec_zeroed(count); - reader.read_exact(ret.as_mut_slice().as_bytes_mut())?; + let mut ret = + ::new_vec_zeroed(count).map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?; + reader.read_exact(ret.as_mut_slice().as_mut_bytes())?; Ok(ret) } #[inline(always)] pub fn read_box(reader: &mut R) -> io::Result> where - T: FromBytes + FromZeroes + AsBytes, + T: FromBytes + IntoBytes, R: Read + ?Sized, { - let mut ret = ::new_box_zeroed(); - reader.read_exact(ret.as_mut().as_bytes_mut())?; + let mut ret = ::new_box_zeroed().map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?; + reader.read_exact(ret.as_mut().as_mut_bytes())?; Ok(ret) } #[inline(always)] pub fn read_box_slice(reader: &mut R, count: usize) -> io::Result> where - T: FromBytes + FromZeroes + AsBytes, + T: FromBytes + IntoBytes, R: Read + ?Sized, { - let mut ret = ::new_box_slice_zeroed(count); - reader.read_exact(ret.as_mut().as_bytes_mut())?; + let mut ret = <[T]>::new_box_zeroed_with_elems(count) + .map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?; + reader.read_exact(ret.as_mut().as_mut_bytes())?; Ok(ret) } diff --git a/nodtool/Cargo.toml b/nodtool/Cargo.toml index 367723f..bae1f61 100644 --- a/nodtool/Cargo.toml +++ b/nodtool/Cargo.toml @@ -40,7 +40,7 @@ tracing = "0.1" tracing-attributes = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } xxhash-rust = { version = "0.8", features = ["xxh64"] } -zerocopy = { version = "0.7", features = ["alloc", "derive"] } +zerocopy = { version = "0.8", features = ["alloc", "derive"] } zstd = "0.13" [target.'cfg(target_env = "musl")'.dependencies] @@ -50,5 +50,5 @@ mimalloc = "0.1" hex = { version = "0.4", features = ["serde"] } quick-xml = { version = "0.36", features = ["serialize"] } serde = { version = "1.0", features = ["derive"] } -zerocopy = { version = "0.7", features = ["alloc", "derive"] } +zerocopy = { version = "0.8", features = ["alloc", "derive"] } zstd = "0.13" diff --git a/nodtool/build.rs b/nodtool/build.rs index def2bf7..b0b569b 100644 --- a/nodtool/build.rs +++ b/nodtool/build.rs @@ -8,10 +8,10 @@ use std::{ use hex::deserialize as deserialize_hex; use serde::Deserialize; -use zerocopy::AsBytes; +use zerocopy::{Immutable, IntoBytes, KnownLayout}; // Keep in sync with build.rs -#[derive(Clone, Debug, AsBytes)] +#[derive(Clone, Debug, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] struct Header { entry_count: u32, @@ -19,7 +19,7 @@ struct Header { } // Keep in sync with redump.rs -#[derive(Clone, Debug, AsBytes)] +#[derive(Clone, Debug, IntoBytes, Immutable, KnownLayout)] #[repr(C, align(4))] struct GameEntry { crc32: u32, diff --git a/nodtool/src/cmd/dat.rs b/nodtool/src/cmd/dat.rs index e38de37..fae8ef4 100644 --- a/nodtool/src/cmd/dat.rs +++ b/nodtool/src/cmd/dat.rs @@ -11,7 +11,7 @@ use std::{ use argp::FromArgs; use indicatif::{ProgressBar, ProgressState, ProgressStyle}; use nod::{Disc, OpenOptions, Result, ResultContext}; -use zerocopy::FromZeroes; +use zerocopy::FromZeros; use crate::util::{ digest::{digest_thread, DigestResult}, @@ -199,7 +199,7 @@ fn load_disc(path: &Path, name: &str, full_verify: bool) -> Result { }); let mut total_read = 0u64; - let mut buf = ::new_box_slice_zeroed(BUFFER_SIZE); + let mut buf = <[u8]>::new_box_zeroed_with_elems(BUFFER_SIZE)?; while total_read < disc_size { let read = min(BUFFER_SIZE as u64, disc_size - total_read) as usize; disc.read_exact(&mut buf[..read]).with_context(|| { diff --git a/nodtool/src/cmd/extract.rs b/nodtool/src/cmd/extract.rs index bcd8886..3869d36 100644 --- a/nodtool/src/cmd/extract.rs +++ b/nodtool/src/cmd/extract.rs @@ -13,7 +13,7 @@ use nod::{ ResultContext, }; use size::{Base, Size}; -use zerocopy::AsBytes; +use zerocopy::IntoBytes; use crate::util::{display, has_extension}; diff --git a/nodtool/src/util/redump.rs b/nodtool/src/util/redump.rs index bc07033..2bf5f52 100644 --- a/nodtool/src/util/redump.rs +++ b/nodtool/src/util/redump.rs @@ -10,7 +10,7 @@ use std::{ use hex::deserialize as deserialize_hex; use nod::{array_ref, Result}; use serde::Deserialize; -use zerocopy::{AsBytes, FromBytes, FromZeroes}; +use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; #[derive(Clone, Debug)] pub struct GameResult<'a> { @@ -33,18 +33,15 @@ impl<'a> Iterator for EntryIter<'a> { type Item = GameResult<'a>; fn next(&mut self) -> Option { - let header: &Header = Header::ref_from_prefix(self.data).unwrap(); + let (header, remaining) = Header::ref_from_prefix(self.data).ok()?; assert_eq!(header.entry_size as usize, size_of::()); if self.index >= header.entry_count as usize { return None; } let entries_size = header.entry_count as usize * size_of::(); - let entries: &[GameEntry] = GameEntry::slice_from( - &self.data[size_of::
()..size_of::
() + entries_size], - ) - .unwrap(); - let string_table: &[u8] = &self.data[size_of::
() + entries_size..]; + let entries = <[GameEntry]>::ref_from_bytes(&remaining[..entries_size]).ok()?; + let string_table = &self.data[size_of::
() + entries_size..]; let entry = &entries[self.index]; let offset = entry.string_table_offset as usize; @@ -57,14 +54,12 @@ impl<'a> Iterator for EntryIter<'a> { pub fn find_by_crc32(crc32: u32) -> Option> { let data = loaded_data(); - let header: &Header = Header::ref_from_prefix(data).unwrap(); + let (header, remaining) = Header::ref_from_prefix(data).ok()?; assert_eq!(header.entry_size as usize, size_of::()); let entries_size = header.entry_count as usize * size_of::(); - let entries: &[GameEntry] = - GameEntry::slice_from(&data[size_of::
()..size_of::
() + entries_size]) - .unwrap(); - let string_table: &[u8] = &data[size_of::
() + entries_size..]; + let (entries_buf, string_table) = remaining.split_at(entries_size); + let entries = <[GameEntry]>::ref_from_bytes(entries_buf).ok()?; // Binary search by CRC32 let index = entries.binary_search_by_key(&crc32, |entry| entry.crc32).ok()?; @@ -84,7 +79,7 @@ fn loaded_data() -> &'static [u8] { LOADED .get_or_init(|| { let size = zstd::zstd_safe::get_frame_content_size(BUILTIN).unwrap().unwrap() as usize; - let mut out = ::new_box_slice_zeroed(size); + let mut out = <[u8]>::new_box_zeroed_with_elems(size).unwrap(); let out_size = zstd::bulk::Decompressor::new() .unwrap() .decompress_to_buffer(BUILTIN, out.as_mut()) @@ -126,7 +121,7 @@ pub fn load_dats<'a>(paths: impl Iterator) -> Result<()> { let entries_size = entries.len() * size_of::(); let string_table_size = entries.iter().map(|(_, name)| name.len() + 4).sum::(); let total_size = size_of::
() + entries_size + string_table_size; - let mut result = ::new_box_slice_zeroed(total_size); + let mut result = <[u8]>::new_box_zeroed_with_elems(total_size)?; let mut out = Cursor::new(result.as_mut()); // Write game entries @@ -152,7 +147,7 @@ pub fn load_dats<'a>(paths: impl Iterator) -> Result<()> { } // Keep in sync with build.rs -#[derive(Clone, Debug, AsBytes, FromBytes, FromZeroes)] +#[derive(Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)] #[repr(C, align(4))] struct Header { entry_count: u32, @@ -160,7 +155,7 @@ struct Header { } // Keep in sync with build.rs -#[derive(Clone, Debug, AsBytes, FromBytes, FromZeroes)] +#[derive(Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)] #[repr(C, align(4))] struct GameEntry { crc32: u32, diff --git a/nodtool/src/util/shared.rs b/nodtool/src/util/shared.rs index db62444..52fde42 100644 --- a/nodtool/src/util/shared.rs +++ b/nodtool/src/util/shared.rs @@ -11,7 +11,7 @@ use std::{ use indicatif::{ProgressBar, ProgressState, ProgressStyle}; use nod::{Compression, Disc, DiscHeader, DiscMeta, OpenOptions, Result, ResultContext}; use size::Size; -use zerocopy::FromZeroes; +use zerocopy::FromZeros; use crate::util::{ digest::{digest_thread, DigestResult}, @@ -117,7 +117,7 @@ pub fn convert_and_verify(in_file: &Path, out_file: Option<&Path>, md5: bool) -> }); let mut total_read = 0u64; - let mut buf = ::new_box_slice_zeroed(BUFFER_SIZE); + let mut buf = <[u8]>::new_box_zeroed_with_elems(BUFFER_SIZE)?; while total_read < disc_size { let read = min(BUFFER_SIZE as u64, disc_size - total_read) as usize; disc.read_exact(&mut buf[..read]).with_context(|| {