printwell-pdf 0.1.3

PDF manipulation features (forms, signing) for Printwell
Documentation
//! Error types for printwell.

use thiserror::Error;

/// PDF manipulation error type.
#[derive(Debug, Error)]
pub enum Error {
    /// Form manipulation error.
    #[error("Form error: {0}")]
    Form(#[from] FormError),
    /// Digital signing error.
    #[error("Signing error: {0}")]
    Signing(#[from] SigningError),
    /// Encryption error.
    #[error("Encryption error: {0}")]
    Encryption(#[from] EncryptionError),
    /// Watermark error.
    #[error("Watermark error: {0}")]
    Watermark(#[from] WatermarkError),
    /// Bookmark error.
    #[error("Bookmark error: {0}")]
    Bookmark(#[from] BookmarkError),
    /// Annotation error.
    #[error("Annotation error: {0}")]
    Annotation(#[from] AnnotationError),
    /// PDF/A compliance error.
    #[error("PDF/A error: {0}")]
    PdfA(#[from] PdfAError),
    /// PDF/UA accessibility error.
    #[error("PDF/UA error: {0}")]
    PdfUA(#[from] PdfUAError),
    /// Invalid PDF structure.
    #[error("Invalid PDF: {0}")]
    InvalidPdf(String),
    /// Invalid parameter.
    #[error("Invalid parameter: {0}")]
    InvalidParameter(String),
    /// PDF operation error.
    #[error("PDF operation error: {0}")]
    PdfOperation(String),
    /// I/O error.
    #[error("IO error: {0}")]
    Io(#[from] std::io::Error),
    /// FFI error.
    #[error("FFI error: {0}")]
    Ffi(#[from] cxx::Exception),
}

/// Form-related errors.
#[derive(Debug, Error)]
pub enum FormError {
    /// Feature requires a commercial license.
    #[error(
        "PDF form manipulation requires a commercial license. Purchase at: https://printwell.dev/pricing"
    )]
    RequiresLicense,
    /// Failed to initialize form builder.
    #[error("failed to initialize form builder: {0}")]
    InitFailed(String),
    /// Failed to add a form field.
    #[error("failed to add {field_type} field '{name}': {reason}")]
    AddFieldFailed {
        /// The type of form field (e.g., "text", "checkbox", "dropdown").
        field_type: &'static str,
        /// The name of the field that failed to be added.
        name: String,
        /// The reason the field could not be added.
        reason: String,
    },
    /// Failed to build form.
    #[error("failed to build form: {0}")]
    BuildFailed(String),
    /// Field validation failed.
    #[error("validation failed for field '{field}': {reason}")]
    ValidationFailed {
        /// The name of the field that failed validation.
        field: String,
        /// The reason validation failed.
        reason: String,
    },
    /// Invalid field specification.
    #[error("invalid field specification: {0}")]
    InvalidSpec(String),
    /// PDF operation failed.
    #[error("{0}")]
    Operation(String),
}

/// Signing-related errors.
#[derive(Debug, Error)]
pub enum SigningError {
    /// Feature requires a commercial license.
    #[error(
        "Digital signing requires a commercial license. Purchase at: https://printwell.dev/pricing"
    )]
    RequiresLicense,
    /// Failed to load certificate.
    #[error("failed to load certificate: {0}")]
    CertificateLoadFailed(String),
    /// Invalid certificate format.
    #[error("invalid certificate format: {0}")]
    InvalidCertificate(String),
    /// Failed to prepare PDF for signing.
    #[error("failed to prepare PDF for signing: {0}")]
    PrepareFailed(String),
    /// Failed to create signature.
    #[error("failed to create signature: {0}")]
    SignatureFailed(String),
    /// Failed to embed signature.
    #[error("failed to embed signature in PDF: {0}")]
    EmbedFailed(String),
    /// No signer information found.
    #[error("no signer information found in signature")]
    NoSignerInfo,
    /// Signature verification failed.
    #[error("signature verification failed: {0}")]
    VerificationFailed(String),
    /// Timestamp operation failed.
    #[error("timestamp operation failed: {0}")]
    TimestampFailed(String),
    /// CMS/PKCS#7 parsing or encoding failed.
    #[error("CMS operation failed: {0}")]
    CmsFailed(String),
    /// Failed to extract signatures.
    #[error("failed to extract signatures: {0}")]
    ExtractionFailed(String),
    /// Generic signing operation error.
    #[error("{0}")]
    Operation(String),
}

/// Encryption-related errors.
#[derive(Debug, Error)]
pub enum EncryptionError {
    /// Feature requires a commercial license.
    #[error(
        "PDF encryption requires a commercial license. Purchase at: https://printwell.dev/pricing"
    )]
    RequiresLicense,
    /// Invalid password.
    #[error("invalid password")]
    InvalidPassword,
    /// Password too short.
    #[error("password too short (minimum {min} characters)")]
    PasswordTooShort {
        /// The minimum required password length.
        min: usize,
    },
    /// Unsupported encryption algorithm.
    #[error("unsupported encryption algorithm: {0}")]
    UnsupportedAlgorithm(String),
    /// Failed to encrypt PDF.
    #[error("failed to encrypt PDF: {0}")]
    EncryptFailed(String),
    /// Failed to decrypt PDF.
    #[error("failed to decrypt PDF: {0}")]
    DecryptFailed(String),
    /// PDF is already encrypted.
    #[error("PDF is already encrypted")]
    AlreadyEncrypted,
    /// PDF is not encrypted.
    #[error("PDF is not encrypted")]
    NotEncrypted,
    /// Generic encryption operation error.
    #[error("{0}")]
    Operation(String),
}

/// Watermark-related errors.
#[derive(Debug, Error)]
pub enum WatermarkError {
    /// No content specified.
    #[error("either text or image must be specified for watermark")]
    NoContent,
    /// Both text and image specified.
    #[error("cannot specify both text and image for watermark")]
    BothContentTypes,
    /// Invalid image data.
    #[error("invalid image data: {0}")]
    InvalidImage(String),
    /// Invalid opacity value.
    #[error("invalid opacity value {value}: must be between 0.0 and 1.0")]
    InvalidOpacity {
        /// The invalid opacity value that was provided.
        value: f32,
    },
    /// Invalid position.
    #[error("invalid position: {0}")]
    InvalidPosition(String),
    /// Failed to add watermark.
    #[error("failed to add watermark: {0}")]
    AddFailed(String),
    /// Generic watermark operation error.
    #[error("{0}")]
    Operation(String),
}

/// Bookmark-related errors.
#[derive(Debug, Error)]
pub enum BookmarkError {
    /// Invalid bookmark specification.
    #[error("invalid bookmark specification: {0}")]
    InvalidSpec(String),
    /// Invalid page number.
    #[error("invalid page number {page}: document has {total} pages")]
    InvalidPage {
        /// The invalid page number that was requested.
        page: u32,
        /// The total number of pages in the document.
        total: u32,
    },
    /// Failed to add bookmarks.
    #[error("failed to add bookmarks: {0}")]
    AddFailed(String),
    /// Failed to extract bookmarks.
    #[error("failed to extract bookmarks: {0}")]
    ExtractFailed(String),
    /// Generic bookmark operation error.
    #[error("{0}")]
    Operation(String),
}

/// Annotation-related errors.
#[derive(Debug, Error)]
pub enum AnnotationError {
    /// Invalid annotation type.
    #[error("invalid annotation type: {0}")]
    InvalidType(String),
    /// Invalid rectangle bounds.
    #[error("invalid rectangle bounds: {reason}")]
    InvalidRect {
        /// The reason the rectangle bounds are invalid.
        reason: String,
    },
    /// Invalid color specification.
    #[error("invalid color: {0}")]
    InvalidColor(String),
    /// Failed to add annotations.
    #[error("failed to add annotations: {0}")]
    AddFailed(String),
    /// Failed to list annotations.
    #[error("failed to list annotations: {0}")]
    ListFailed(String),
    /// Failed to remove annotations.
    #[error("failed to remove annotations: {0}")]
    RemoveFailed(String),
    /// Generic annotation operation error.
    #[error("{0}")]
    Operation(String),
}

/// PDF/A compliance errors.
#[derive(Debug, Error)]
pub enum PdfAError {
    /// Feature requires a commercial license.
    #[error(
        "PDF/A compliance features require a commercial license. Purchase at: https://printwell.dev/pricing"
    )]
    RequiresLicense,
    /// Invalid PDF/A level.
    #[error("invalid PDF/A level: {0}")]
    InvalidLevel(String),
    /// Validation failed.
    #[error("PDF/A validation failed: {error_count} errors, {warning_count} warnings")]
    ValidationFailed {
        /// The number of validation errors found.
        error_count: usize,
        /// The number of validation warnings found.
        warning_count: usize,
    },
    /// Failed to add metadata.
    #[error("failed to add PDF/A metadata: {0}")]
    MetadataFailed(String),
    /// Document has compliance issues.
    #[error("document has {count} compliance issues")]
    ComplianceIssues {
        /// The number of compliance issues found.
        count: usize,
    },
    /// Generic PDF/A operation error.
    #[error("{0}")]
    Operation(String),
}

/// PDF/UA accessibility errors.
#[derive(Debug, Error)]
pub enum PdfUAError {
    /// Feature requires a commercial license.
    #[error(
        "PDF/UA accessibility features require a commercial license. Purchase at: https://printwell.dev/pricing"
    )]
    RequiresLicense,
    /// Invalid PDF/UA level.
    #[error("invalid PDF/UA level: {0}")]
    InvalidLevel(String),
    /// Document missing required structure.
    #[error("document missing required structure: {0}")]
    MissingStructure(String),
    /// Accessibility issue detected.
    #[error("accessibility issue: {category} - {description}")]
    AccessibilityIssue {
        /// The category of the accessibility issue (e.g., "structure", "alt-text").
        category: String,
        /// A description of the accessibility issue.
        description: String,
    },
    /// Failed to add metadata.
    #[error("failed to add PDF/UA metadata: {0}")]
    MetadataFailed(String),
    /// Generic PDF/UA operation error.
    #[error("{0}")]
    Operation(String),
}

// Backward compatibility: Allow creating errors from strings for migration
impl From<String> for FormError {
    fn from(s: String) -> Self {
        Self::Operation(s)
    }
}

impl From<String> for SigningError {
    fn from(s: String) -> Self {
        Self::Operation(s)
    }
}

impl From<String> for EncryptionError {
    fn from(s: String) -> Self {
        Self::Operation(s)
    }
}

impl From<String> for WatermarkError {
    fn from(s: String) -> Self {
        Self::Operation(s)
    }
}

impl From<String> for BookmarkError {
    fn from(s: String) -> Self {
        Self::Operation(s)
    }
}

impl From<String> for AnnotationError {
    fn from(s: String) -> Self {
        Self::Operation(s)
    }
}

impl From<String> for PdfAError {
    fn from(s: String) -> Self {
        Self::Operation(s)
    }
}

impl From<String> for PdfUAError {
    fn from(s: String) -> Self {
        Self::Operation(s)
    }
}

/// Result type alias.
pub type Result<T> = std::result::Result<T, Error>;