use super::types::{PdfALevel, ValidationResult};
use super::validators;
use crate::document::PdfDocument;
use crate::error::Result;
#[derive(Debug, Clone, Default)]
pub struct PdfAValidator {
stop_on_first_error: bool,
include_warnings: bool,
}
impl PdfAValidator {
pub fn new() -> Self {
Self {
stop_on_first_error: false,
include_warnings: true,
}
}
pub fn stop_on_first_error(mut self, stop: bool) -> Self {
self.stop_on_first_error = stop;
self
}
pub fn include_warnings(mut self, include: bool) -> Self {
self.include_warnings = include;
self
}
pub fn validate(
&self,
document: &mut PdfDocument,
level: PdfALevel,
) -> Result<ValidationResult> {
let mut result = ValidationResult::new(level);
macro_rules! run_validator {
($validator:expr) => {
$validator(document, level, &mut result)?;
if self.should_stop(&result) {
return Ok(self.finalize_result(result));
}
};
}
run_validator!(validators::validate_xmp_metadata);
run_validator!(validators::validate_fonts);
run_validator!(validators::validate_colors);
run_validator!(validators::validate_encryption);
run_validator!(validators::validate_transparency);
run_validator!(validators::validate_structure);
run_validator!(validators::validate_javascript);
run_validator!(validators::validate_embedded_files);
validators::validate_annotations(document, level, &mut result)?;
Ok(self.finalize_result(result))
}
pub fn check_fonts(
&self,
document: &mut PdfDocument,
level: PdfALevel,
) -> Result<ValidationResult> {
let mut result = ValidationResult::new(level);
validators::validate_fonts(document, level, &mut result)?;
Ok(self.finalize_result(result))
}
pub fn check_metadata(
&self,
document: &mut PdfDocument,
level: PdfALevel,
) -> Result<ValidationResult> {
let mut result = ValidationResult::new(level);
validators::validate_xmp_metadata(document, level, &mut result)?;
Ok(self.finalize_result(result))
}
pub fn check_colors(
&self,
document: &mut PdfDocument,
level: PdfALevel,
) -> Result<ValidationResult> {
let mut result = ValidationResult::new(level);
validators::validate_colors(document, level, &mut result)?;
Ok(self.finalize_result(result))
}
pub fn check_transparency(
&self,
document: &mut PdfDocument,
level: PdfALevel,
) -> Result<ValidationResult> {
let mut result = ValidationResult::new(level);
validators::validate_transparency(document, level, &mut result)?;
Ok(self.finalize_result(result))
}
pub fn check_structure(
&self,
document: &mut PdfDocument,
level: PdfALevel,
) -> Result<ValidationResult> {
let mut result = ValidationResult::new(level);
validators::validate_structure(document, level, &mut result)?;
Ok(self.finalize_result(result))
}
fn should_stop(&self, result: &ValidationResult) -> bool {
self.stop_on_first_error && result.has_errors()
}
fn finalize_result(&self, mut result: ValidationResult) -> ValidationResult {
result.is_compliant = !result.has_errors();
if !self.include_warnings {
result.warnings.clear();
}
result
}
}
pub fn validate_pdf_a(document: &mut PdfDocument, level: PdfALevel) -> Result<ValidationResult> {
PdfAValidator::new().validate(document, level)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validator_creation() {
let validator = PdfAValidator::new();
assert!(!validator.stop_on_first_error);
assert!(validator.include_warnings);
}
#[test]
fn test_validator_builder() {
let validator = PdfAValidator::new()
.stop_on_first_error(true)
.include_warnings(false);
assert!(validator.stop_on_first_error);
assert!(!validator.include_warnings);
}
#[test]
fn test_validation_result_finalization() {
let validator = PdfAValidator::new();
let result = ValidationResult::new(PdfALevel::A2b);
let finalized = validator.finalize_result(result);
assert!(finalized.is_compliant);
}
#[test]
fn test_validation_result_finalization_without_warnings() {
let validator = PdfAValidator::new().include_warnings(false);
let mut result = ValidationResult::new(PdfALevel::A2b);
result.add_warning(super::super::types::ComplianceWarning::new(
super::super::types::WarningCode::MissingRecommendedMetadata,
"Test warning",
));
let finalized = validator.finalize_result(result);
assert!(finalized.warnings.is_empty());
}
}