mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-05 00:39:31 +00:00
DirEntry now implements Bytes.
This commit is contained in:
parent
cd31c9d8ca
commit
982393bd64
@ -11,6 +11,7 @@ pub use error::DeserializeBytesError;
|
||||
use super::ptr::{DirPtr, FilePtr};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use chrono::NaiveDateTime;
|
||||
use dcb_bytes::Bytes;
|
||||
use dcb_util::{ascii_str_arr::AsciiChar, AsciiStrArr};
|
||||
use std::convert::TryInto;
|
||||
|
||||
@ -78,9 +79,12 @@ pub struct DirEntry {
|
||||
pub kind: DirEntryKind,
|
||||
}
|
||||
|
||||
impl DirEntry {
|
||||
/// Reads a directory entry reader from bytes
|
||||
pub fn deserialize_bytes(bytes: &[u8; 0x20]) -> Result<Option<Self>, DeserializeBytesError> {
|
||||
impl Bytes for DirEntry {
|
||||
type ByteArray = [u8; 0x20];
|
||||
type DeserializeError = DeserializeBytesError;
|
||||
type SerializeError = !;
|
||||
|
||||
fn deserialize_bytes(bytes: &Self::ByteArray) -> Result<Self, Self::DeserializeError> {
|
||||
let bytes = dcb_util::array_split!(bytes,
|
||||
kind : 0x1,
|
||||
extension : [0x3],
|
||||
@ -90,19 +94,6 @@ impl DirEntry {
|
||||
name : [0x10],
|
||||
);
|
||||
|
||||
// Special case some files which cause problems and return early, as if we encountered the final entry.
|
||||
#[allow(clippy::single_match)] // We might add more matches in the future
|
||||
match bytes.name {
|
||||
[0x83, 0x52, 0x83, 0x53, 0x81, 0x5B, 0x20, 0x81, 0x60, 0x20, 0x43, 0x41, 0x52, 0x44, 0x32, 0x00] => {
|
||||
log::warn!(
|
||||
"Ignoring special directory entry: {:?}",
|
||||
String::from_utf8_lossy(bytes.name)
|
||||
);
|
||||
return Ok(None);
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
||||
// Then get the name and extension
|
||||
let mut name = AsciiStrArr::from_bytes(bytes.name).map_err(DeserializeBytesError::Name)?;
|
||||
name.trim_end(AsciiChar::Null);
|
||||
@ -116,7 +107,6 @@ impl DirEntry {
|
||||
|
||||
// Check kind
|
||||
let kind = match bytes.kind {
|
||||
0x0 => return Ok(None),
|
||||
0x1 => DirEntryKind::File {
|
||||
extension,
|
||||
ptr: FilePtr { sector_pos, size },
|
||||
@ -131,11 +121,10 @@ impl DirEntry {
|
||||
&kind => return Err(DeserializeBytesError::InvalidKind(kind)),
|
||||
};
|
||||
|
||||
Ok(Some(Self { name, date, kind }))
|
||||
Ok(Self { name, date, kind })
|
||||
}
|
||||
|
||||
/// Writes this entry to bytes.
|
||||
pub fn serialize_bytes(&self, bytes: &mut [u8; 0x20]) {
|
||||
fn serialize_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::SerializeError> {
|
||||
let bytes = dcb_util::array_split_mut!(bytes,
|
||||
kind : 0x1,
|
||||
extension : [0x3],
|
||||
@ -174,5 +163,7 @@ impl DirEntry {
|
||||
.try_into()
|
||||
.expect("Seconds didn't fit into date");
|
||||
LittleEndian::write_u32(bytes.date, date);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,15 @@
|
||||
#![doc(include = "lib.md")]
|
||||
// Features
|
||||
#![feature(external_doc, seek_stream_len, try_blocks, associated_type_bounds)]
|
||||
#![feature(
|
||||
external_doc,
|
||||
seek_stream_len,
|
||||
try_blocks,
|
||||
associated_type_bounds,
|
||||
never_type,
|
||||
unwrap_infallible,
|
||||
format_args_capture,
|
||||
str_internals
|
||||
)]
|
||||
// Lints
|
||||
#![warn(clippy::restriction, clippy::pedantic, clippy::nursery)]
|
||||
// We'll disable the ones we don't need
|
||||
|
||||
@ -12,6 +12,8 @@ pub use error::{
|
||||
use super::DirEntry;
|
||||
use crate::DirEntryKind;
|
||||
use ascii::AsciiStr;
|
||||
use core::str::lossy::Utf8Lossy;
|
||||
use dcb_bytes::Bytes;
|
||||
use dcb_util::IoCursor;
|
||||
use std::io::{self, SeekFrom};
|
||||
|
||||
@ -93,11 +95,26 @@ impl DirPtr {
|
||||
let iter = std::iter::from_fn(move || {
|
||||
let entry: Result<_, _> = try {
|
||||
// Read the bytes
|
||||
let mut entry_bytes = [0; 0x20];
|
||||
reader.read_exact(&mut entry_bytes).map_err(ReadEntryError::ReadEntry)?;
|
||||
let mut bytes = [0; 0x20];
|
||||
reader.read_exact(&mut bytes).map_err(ReadEntryError::ReadEntry)?;
|
||||
|
||||
// And parse it
|
||||
DirEntry::deserialize_bytes(&entry_bytes).map_err(ReadEntryError::ParseEntry)?
|
||||
// If all bytes are null, we're finished
|
||||
if bytes == [0; 0x20] {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Special case some entries which cause problems
|
||||
#[allow(clippy::single_match)] // We might add more matches in the future
|
||||
match &bytes {
|
||||
b"\x01CDD\xd5/\x00\x00\xf0?\x01\x00\xe6u\xad:\x83R\x83S\x81[ \x81` CARD2\x00" => {
|
||||
log::warn!("Ignoring special directory entry: {:?}", Utf8Lossy::from_bytes(&bytes));
|
||||
return None;
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
||||
// Else parse it
|
||||
Some(DirEntry::deserialize_bytes(&bytes).map_err(ReadEntryError::ParseEntry)?)
|
||||
};
|
||||
|
||||
entry.transpose()
|
||||
@ -150,7 +167,7 @@ impl DirPtr {
|
||||
for entry in entries {
|
||||
// Put the entry into bytes
|
||||
let mut entry_bytes = [0; 0x20];
|
||||
entry.serialize_bytes(&mut entry_bytes);
|
||||
entry.serialize_bytes(&mut entry_bytes).into_ok();
|
||||
|
||||
// Then write it
|
||||
writer.write_all(&entry_bytes).map_err(WriteEntriesError::WriteEntry)?;
|
||||
@ -191,7 +208,7 @@ impl DirEntryPtr {
|
||||
|
||||
// Then write the entry
|
||||
let mut entry_bytes = [0; 0x20];
|
||||
entry.serialize_bytes(&mut entry_bytes);
|
||||
entry.serialize_bytes(&mut entry_bytes).into_ok();
|
||||
|
||||
// Then write it
|
||||
writer.write_all(&entry_bytes).map_err(WriteEntryError::WriteEntry)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user