Skip to content

Commit

Permalink
implement matching logic except for --match
Browse files Browse the repository at this point in the history
  • Loading branch information
cosmicexplorer committed Aug 22, 2024
1 parent 58b088c commit 0039b06
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 6 deletions.
43 changes: 37 additions & 6 deletions cli/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,8 @@ pub mod info {
pub mod extract {
use super::{ArgParseError, CommandFormat};

use zip::CompressionMethod;

use std::{collections::VecDeque, ffi::OsString, mem, path::PathBuf};

#[derive(Debug)]
Expand Down Expand Up @@ -821,11 +823,8 @@ pub mod extract {

#[derive(Debug)]
pub enum EntryType {
/// file
File,
/// dir
Dir,
/// symlink
Symlink,
}

Expand All @@ -842,13 +841,11 @@ pub mod extract {

#[derive(Debug, PartialEq, Eq)]
pub enum NonSpecificCompressionMethodArg {
/// any
Any,
/// known
Known,
}

#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum SpecificCompressionMethodArg {
Stored,
Deflated,
Expand All @@ -864,6 +861,40 @@ pub mod extract {
Xz,
}

impl SpecificCompressionMethodArg {
pub const KNOWN_COMPRESSION_METHODS: &[CompressionMethod] = &[
CompressionMethod::Stored,
CompressionMethod::Deflated,
#[cfg(feature = "deflate64")]
CompressionMethod::Deflate64,
#[cfg(feature = "bzip2")]
CompressionMethod::Bzip2,
#[cfg(feature = "zstd")]
CompressionMethod::Zstd,
#[cfg(feature = "lzma")]
CompressionMethod::Lzma,
#[cfg(feature = "xz")]
CompressionMethod::Xz,
];

pub fn translate_to_zip(self) -> CompressionMethod {
match self {
Self::Stored => CompressionMethod::Stored,
Self::Deflated => CompressionMethod::Deflated,
#[cfg(feature = "deflate64")]
Self::Deflate64 => CompressionMethod::Deflate64,
#[cfg(feature = "bzip2")]
Self::Bzip2 => CompressionMethod::Bzip2,
#[cfg(feature = "zstd")]
Self::Zstd => CompressionMethod::Zstd,
#[cfg(feature = "lzma")]
Self::Lzma => CompressionMethod::Lzma,
#[cfg(feature = "xz")]
Self::Xz => CompressionMethod::Xz,
}
}
}

#[derive(Debug, PartialEq, Eq)]
pub enum CompressionMethodArg {
NonSpecific(NonSpecificCompressionMethodArg),
Expand Down
75 changes: 75 additions & 0 deletions cli/src/extract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,81 @@ where
}
}

struct Matcher<W> {
err: RefCell<W>,
expr: MatchExpression,
}

impl<W> Matcher<W>
where
W: Write,
{
pub fn evaluate(&self, entry: &ZipFile) -> Result<bool, CommandError> {
let Self { err, expr } = self;
Self::recursive_match(err, &expr, entry)
}

fn recursive_match(
err: &RefCell<W>,
expr: &MatchExpression,
entry: &ZipFile,
) -> Result<bool, CommandError> {
match expr {
MatchExpression::PrimitivePredicate(predicate) => match predicate {
Predicate::Trivial(trivial) => match trivial {
TrivialPredicate::True => Ok(true),
TrivialPredicate::False => Ok(false),
},
Predicate::EntryType(entry_type) => match entry_type {
EntryType::File => Ok(!entry.is_dir() && !entry.is_symlink()),
EntryType::Dir => Ok(entry.is_dir()),
EntryType::Symlink => Ok(entry.is_symlink()),
},
Predicate::CompressionMethod(method_arg) => match method_arg {
CompressionMethodArg::NonSpecific(nonspecific_arg) => match nonspecific_arg {
NonSpecificCompressionMethodArg::Any => Ok(true),
NonSpecificCompressionMethodArg::Known => {
Ok(SpecificCompressionMethodArg::KNOWN_COMPRESSION_METHODS
.contains(&entry.compression()))
}
},
CompressionMethodArg::Specific(specific_arg) => {
Ok(specific_arg.translate_to_zip() == entry.compression())
}
},
Predicate::DepthLimit(limit_arg) => match limit_arg {
DepthLimitArg::Max(max) => {
let max: usize = (*max).into();
Ok(entry.name().split('/').count() <= max)
}
DepthLimitArg::Min(min) => {
let min: usize = (*min).into();
Ok(entry.name().split('/').count() >= min)
}
},
Predicate::Match(match_arg) => todo!("{match_arg:?}"),
},
MatchExpression::Negated(inner) => {
Self::recursive_match(err, inner.as_ref(), entry).map(|result| !result)
}
MatchExpression::And {
explicit: _,
left,
right,
} => {
/* Short-circuiting, so do left first. */
Ok(Self::recursive_match(err, left.as_ref(), entry)?
&& Self::recursive_match(err, right.as_ref(), entry)?)
}
MatchExpression::Or { left, right } => {
Ok(Self::recursive_match(err, left.as_ref(), entry)?
|| Self::recursive_match(err, right.as_ref(), entry)?)
}
MatchExpression::Grouped(inner) => Self::recursive_match(err, inner.as_ref(), entry),
}
}
}

struct ZipFileInput<W> {
err: RefCell<W>,
inner: ZipArchive<fs::File>,
Expand Down

0 comments on commit 0039b06

Please sign in to comment.