Skip to content

Commit

Permalink
Now to use all those parsers
Browse files Browse the repository at this point in the history
  • Loading branch information
fasterthanlime committed Jan 30, 2024
1 parent 581335a commit 35342b2
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 83 deletions.
4 changes: 2 additions & 2 deletions crates/rc-zip/src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl From<std::str::Utf8Error> for DecodingError {
}

impl Encoding {
pub(crate) fn decode(&self, i: &mut Partial<&'_ [u8]>) -> Result<String, DecodingError> {
pub(crate) fn decode(&self, i: &[u8]) -> Result<String, DecodingError> {
match self {
Encoding::Utf8 => {
let s = std::str::from_utf8(i)?;
Expand All @@ -69,7 +69,7 @@ impl Encoding {

fn decode_as(
&self,
i: &mut Partial<&'_ [u8]>,
i: &[u8],
encoding: &'static encoding_rs::Encoding,
) -> Result<String, DecodingError> {
let mut decoder = encoding.new_decoder();
Expand Down
4 changes: 2 additions & 2 deletions crates/rc-zip/src/format/date_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ impl fmt::Debug for MsdosTimestamp {

impl MsdosTimestamp {
pub fn parser(i: &mut Partial<&'_ [u8]>) -> PResult<Self> {
seq!(Self {
seq! {Self {
time: le_u16,
date: le_u16,
})
}}
.parse_next(i)
}

Expand Down
7 changes: 3 additions & 4 deletions crates/rc-zip/src/format/directory_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,10 @@ impl DirectoryHeader {
needs_header_offset: self.header_offset == !0u32,
};

let mut slice = &self.extra.0[..];
let mut slice = Partial::new(&self.extra.0[..]);
while !slice.is_empty() {
match ExtraField::parse(slice, &settings) {
Ok((remaining, ef)) => {
match ExtraField::mk_parser(settings).parse_next(&mut slice) {
Ok(ef) => {
match &ef {
ExtraField::Zip64(z64) => {
if let Some(n) = z64.uncompressed_size {
Expand Down Expand Up @@ -185,7 +185,6 @@ impl DirectoryHeader {
_ => {}
};
extra_fields.push(ef);
slice = remaining;
}
Err(e) => {
trace!("extra field error: {:#?}", e);
Expand Down
8 changes: 4 additions & 4 deletions crates/rc-zip/src/format/eocd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ impl EndOfCentralDirectory64Locator {

pub fn parser(i: &mut Partial<&'_ [u8]>) -> PResult<Self> {
_ = tag(Self::SIGNATURE).parse_next(i)?;
seq!(Self {
seq! {Self {
dir_disk_number: le_u32,
directory_offset: le_u64,
total_disks: le_u32,
})
}}
.parse_next(i)
}
}
Expand Down Expand Up @@ -114,7 +114,7 @@ impl EndOfCentralDirectory64Record {

pub fn parser(i: &mut Partial<&'_ [u8]>) -> PResult<Self> {
_ = tag(Self::SIGNATURE).parse_next(i)?;
seq!(Self {
seq! {Self {
record_size: le_u64,
creator_version: le_u16,
reader_version: le_u16,
Expand All @@ -124,7 +124,7 @@ impl EndOfCentralDirectory64Record {
directory_records: le_u64,
directory_size: le_u64,
directory_offset: le_u64,
})
}}
.parse_next(i)
}
}
Expand Down
26 changes: 14 additions & 12 deletions crates/rc-zip/src/format/extra_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ pub(crate) struct ExtraFieldRecord<'a> {

impl<'a> ExtraFieldRecord<'a> {
pub(crate) fn parser(i: &mut Partial<&'_ [u8]>) -> PResult<Self> {
seq!(Self {
seq! {Self {
tag: le_u16,
payload: length_take(le_u16),
})
}}
.parse_next(i)
}
}
Expand Down Expand Up @@ -70,17 +70,19 @@ impl ExtraField {

let variant = match rec.tag {
ExtraZip64Field::TAG => {
opt(ExtraZip64Field::mk_parser(settings).map(EF::Zip64)).parse_next(payload)
opt(ExtraZip64Field::mk_parser(settings).map(EF::Zip64)).parse_next(payload)?
}
ExtraTimestampField::TAG => {
opt(ExtraTimestampField::parser.map(EF::Timestamp)).parse_next(payload)
opt(ExtraTimestampField::parser.map(EF::Timestamp)).parse_next(payload)?
}
ExtraNtfsField::TAG => {
opt(ExtraNtfsField::parse.map(EF::Ntfs)).parse_next(payload)?
}
ExtraNtfsField::TAG => opt(ExtraNtfsField::parse.map(EF::Ntfs)).parse_next(payload),
ExtraUnixField::TAG | ExtraUnixField::TAG_INFOZIP => {
opt(ExtraUnixField::parser.map(EF::Unix)).parse_next(payload)
opt(ExtraUnixField::parser.map(EF::Unix)).parse_next(payload)?
}
ExtraNewUnixField::TAG => {
opt(ExtraNewUnixField::parser.map(EF::NewUnix)).parse_next(payload)
opt(ExtraNewUnixField::parser.map(EF::NewUnix)).parse_next(payload)?
}
_ => None,
}
Expand All @@ -107,11 +109,11 @@ impl ExtraZip64Field {
) -> impl FnMut(&mut Partial<&'_ [u8]>) -> PResult<Self> {
move |i| {
// N.B: we ignore "disk start number"
seq!(Self {
seq! {Self {
uncompressed_size: cond(settings.needs_uncompressed_size, le_u64),
compressed_size: cond(settings.needs_compressed_size, le_u64),
header_offset: cond(settings.needs_header_offset, le_u64),
})
}}
.parse_next(i)
}
}
Expand All @@ -131,7 +133,7 @@ impl ExtraTimestampField {
preceded(
// 1 byte of flags, if bit 0 is set, modification time is present
le_u8.verify(|x| x & 0b1 != 0),
seq!(Self { mtime: le_u32 }),
seq! {Self { mtime: le_u32 }},
)
.parse_next(i)
}
Expand Down Expand Up @@ -268,11 +270,11 @@ pub struct NtfsAttr1 {

impl NtfsAttr1 {
fn parser(i: &mut Partial<&'_ [u8]>) -> PResult<Self> {
seq!(Self {
seq! {Self {
mtime: NtfsTimestamp::parser,
atime: NtfsTimestamp::parser,
ctime: NtfsTimestamp::parser,
})
}}
.parse_next(i)
}
}
109 changes: 56 additions & 53 deletions crates/rc-zip/src/format/local.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::{fields, format::*};
use crate::format::*;
use winnow::{
bytes::streaming::tag,
binary::{le_u16, le_u32, le_u64},
combinator::opt,
number::streaming::{le_u16, le_u32, le_u64},
sequence::preceded,
seq,
token::tag,
PResult, Parser, Partial,
};

#[derive(Debug)]
Expand Down Expand Up @@ -32,34 +33,34 @@ pub struct LocalFileHeaderRecord {
impl LocalFileHeaderRecord {
pub const SIGNATURE: &'static str = "PK\x03\x04";

pub fn parse(i: &mut Partial<&'_ [u8]>) -> PResult<Self> {
preceded(
tag(Self::SIGNATURE),
fields!({
reader_version: Version::parse,
flags: le_u16,
method: le_u16,
modified: MsdosTimestamp::parse,
crc32: le_u32,
compressed_size: le_u32,
uncompressed_size: le_u32,
name_len: le_u16,
extra_len: le_u16,
} chain fields!({
name: ZipString::parser(name_len),
extra: ZipBytes::parser(extra_len),
} map Self {
reader_version,
flags,
method,
modified,
crc32,
compressed_size,
uncompressed_size,
name,
extra,
})),
)(i)
pub fn parser(i: &mut Partial<&'_ [u8]>) -> PResult<Self> {
let _ = tag(Self::SIGNATURE).parse_next(i)?;

let reader_version = Version::parser.parse_next(i)?;
let flags = le_u16.parse_next(i)?;
let method = le_u16.parse_next(i)?;
let modified = MsdosTimestamp::parser.parse_next(i)?;
let crc32 = le_u32.parse_next(i)?;
let compressed_size = le_u32.parse_next(i)?;
let uncompressed_size = le_u32.parse_next(i)?;

let name_len = le_u16.parse_next(i)?;
let extra_len = le_u16.parse_next(i)?;

let name = ZipString::parser(name_len).parse_next(i)?;
let extra = ZipBytes::parser(extra_len).parse_next(i)?;

Ok(Self {
reader_version,
flags,
method,
modified,
crc32,
compressed_size,
uncompressed_size,
name,
extra,
})
}

pub fn has_data_descriptor(&self) -> bool {
Expand All @@ -83,29 +84,31 @@ pub struct DataDescriptorRecord {
impl DataDescriptorRecord {
const SIGNATURE: &'static str = "PK\x07\x08";

pub fn parse(i: &mut Partial<&'_ [u8]>, is_zip64: bool) -> PResult<Self> {
pub fn parser(i: &mut Partial<&'_ [u8]>, is_zip64: bool) -> PResult<Self> {
// From appnote.txt:
//
// 4.3.9.3 Although not originally assigned a signature, the value
// 0x08074b50 has commonly been adopted as a signature value for the
// data descriptor record. Implementers SHOULD be aware that ZIP files
// MAY be encountered with or without this signature marking data
// descriptors and SHOULD account for either case when reading ZIP files
// to ensure compatibility.
let _ = opt(tag(Self::SIGNATURE)).parse_next(i)?;

if is_zip64 {
preceded(
opt(tag(Self::SIGNATURE)),
fields!(Self {
crc32: le_u32,
compressed_size: le_u64,
uncompressed_size: le_u64,
}),
)(i)
seq! {Self {
crc32: le_u32,
compressed_size: le_u64,
uncompressed_size: le_u64,
}}
.parse_next(i)
} else {
preceded(
opt(tag(Self::SIGNATURE)),
fields!({
crc32: le_u32,
compressed_size: le_u32,
uncompressed_size: le_u32,
} map Self {
crc32,
compressed_size: compressed_size as u64,
uncompressed_size: uncompressed_size as u64,
}),
)(i)
seq! {Self {
crc32: le_u32,
compressed_size: le_u32.map(|x| x as u64),
uncompressed_size: le_u32.map(|x| x as u64),
}}
.parse_next(i)
}
}
}
3 changes: 1 addition & 2 deletions crates/rc-zip/src/format/version.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::format::*;
use std::fmt;
use winnow::{combinator::map, number::streaming::le_u16, PResult, Partial};
use winnow::{binary::le_u16, PResult, Parser, Partial};

/// A zip version (either created by, or required when reading an archive).
///
Expand Down
2 changes: 1 addition & 1 deletion crates/rc-zip/src/reader/archive_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{encoding::Encoding, error::*, format::*, reader::buffer::*, transiti

use std::io::Read;
use tracing::trace;
use winnow::Offset;
use winnow::stream::Offset;

/// ArchiveReader parses a valid zip archive into an [Archive][]. In particular, this struct finds
/// an end of central directory record, parses the entire central directory, detects text encoding,
Expand Down
6 changes: 3 additions & 3 deletions crates/rc-zip/src/reader/sync/entry_reader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use cfg_if::cfg_if;
use oval::Buffer;
use std::io;
use tracing::trace;
use winnow::Offset;
use winnow::stream::Offset;

struct EntryReadMetrics {
uncompressed_size: u64,
Expand Down Expand Up @@ -77,7 +77,7 @@ where
let read_bytes = self.rd.read(buffer.space())?;
buffer.fill(read_bytes);

match LocalFileHeaderRecord::parse(buffer.data()) {
match LocalFileHeaderRecord::parser(buffer.data()) {
Ok((remaining, header)) => {
let consumed = buffer.data().offset(remaining);
buffer.consume(consumed);
Expand Down Expand Up @@ -168,7 +168,7 @@ where
buffer.available_space()
);

match DataDescriptorRecord::parse(buffer.data(), self.inner.is_zip64) {
match DataDescriptorRecord::parser(buffer.data(), self.inner.is_zip64) {
Ok((_remaining, descriptor)) => {
trace!("data descriptor = {:#?}", descriptor);
transition!(self.state => (S::ReadDataDescriptor { metrics, header, .. }) {
Expand Down

0 comments on commit 35342b2

Please sign in to comment.