Skip to content

Commit

Permalink
ref(dif): Create type for DIF validation errors
Browse files Browse the repository at this point in the history
Having a type for DIF validation errors will give us more flexible error handling abilities.
  • Loading branch information
szokeasaurusrex committed Jan 2, 2025
1 parent c08be9a commit 04f434e
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 17 deletions.
28 changes: 28 additions & 0 deletions src/utils/dif_upload/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//! Error types for the dif_upload module.
use thiserror::Error;

/// Represents an error that makes a DIF invalid.
#[derive(Debug, Error)]
pub enum ValidationError {
#[error("Invalid format")]
InvalidFormat,
#[error("Invalid features")]
InvalidFeatures,
#[error("Invalid debug ID")]
InvalidDebugId,
#[error("Too large: {size} bytes exceeds the maximum size of {max_size} bytes")]
TooLarge { size: usize, max_size: u64 },
}

/// Handles a DIF validation error by logging it to console
/// at the appropriate log level.
pub fn handle(dif_name: &str, error: &ValidationError) {
let message = format!("Skipping {}: {}", dif_name, error);
match error {
ValidationError::InvalidFormat
| ValidationError::InvalidFeatures
| ValidationError::InvalidDebugId => log::debug!("{message}"),
ValidationError::TooLarge { .. } => log::warn!("{message}"),
}
}
37 changes: 20 additions & 17 deletions src/utils/dif_upload.rs → src/utils/dif_upload/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Searches, processes and uploads debug information files (DIFs). See
//! `DifUpload` for more information.
mod error;

use std::borrow::Cow;
use std::collections::{BTreeMap, BTreeSet};
use std::convert::TryInto;
Expand Down Expand Up @@ -32,6 +34,7 @@ use which::which;
use zip::result::ZipError;
use zip::{write::FileOptions, ZipArchive, ZipWriter};

use self::error::ValidationError;
use crate::api::{Api, ChunkServerOptions, ChunkUploadCapability};
use crate::config::Config;
use crate::constants::{DEFAULT_MAX_DIF_SIZE, DEFAULT_MAX_WAIT};
Expand Down Expand Up @@ -767,7 +770,8 @@ fn collect_auxdif<'a>(
};

// Skip this file if we don't want to process it.
if !options.validate_dif(&dif) {
if let Err(e) = options.validate_dif(&dif) {
error::handle(&name, &e);
return None;
}

Expand Down Expand Up @@ -836,7 +840,9 @@ fn collect_object_dif<'a>(
// If this is a PE file with an embedded Portable PDB, we extract and process the PPDB separately.
if let Object::Pe(pe) = &object {
if let Ok(Some(ppdb_dif)) = extract_embedded_ppdb(pe, name.as_str()) {
if options.validate_dif(&ppdb_dif) {
if let Err(e) = options.validate_dif(&ppdb_dif) {
error::handle(&ppdb_dif.name, &e);
} else {
collected.push(ppdb_dif);
}
}
Expand Down Expand Up @@ -878,7 +884,9 @@ fn collect_object_dif<'a>(
};

// Skip this file if we don't want to process it.
if !options.validate_dif(&dif) {
if let Err(e) = options.validate_dif(&dif) {
error::handle(&name, &e);
// TODO: Check if we have a size error, and error if so.
continue;
}

Expand Down Expand Up @@ -1745,33 +1753,28 @@ impl<'a> DifUpload<'a> {
/// This takes all the filters configured in the [`DifUpload`] into account and returns
/// whether a file should be skipped or not. It also takes care of logging such a skip
/// if required.
fn validate_dif(&self, dif: &DifMatch) -> bool {
// Skip if we didn't want this kind of DIF.
fn validate_dif(&self, dif: &DifMatch) -> Result<(), ValidationError> {
if !self.valid_format(dif.format()) {
debug!("skipping {} because of format", dif.name);
return false;
return Err(ValidationError::InvalidFormat);
}

// Skip if this DIF does not have features we want.
if !self.valid_features(dif) {
debug!("skipping {} because of features", dif.name);
return false;
return Err(ValidationError::InvalidFeatures);
}

// Skip if this DIF has no DebugId or we are only looking for certain IDs.
let id = dif.debug_id.unwrap_or_default();
if id.is_nil() || !self.valid_id(id) {
debug!("skipping {} because of debugid", dif.name);
return false;
return Err(ValidationError::InvalidDebugId);
}

// Skip if file exceeds the maximum allowed file size.
if !self.valid_size(&dif.name, dif.data().len()) {
debug!("skipping {} because of size", dif.name);
return false;
return Err(ValidationError::TooLarge {
size: dif.data().len(),
max_size: self.max_file_size,
});
}

true
Ok(())
}

fn into_chunk_options(self, server_options: ChunkServerOptions) -> ChunkOptions<'a> {
Expand Down

0 comments on commit 04f434e

Please sign in to comment.