lib3mf_core/error.rs
1//! Error handling for lib3mf-core.
2//!
3//! This module defines the error types returned by all fallible operations in the library.
4//!
5//! ## Design Philosophy
6//!
7//! The library follows a strict **no-panic** policy:
8//!
9//! - All errors are returned as `Result<T, Lib3mfError>`, never panicked
10//! - Invalid user input (malformed 3MF files, bad parameters) produces errors, not panics
11//! - Internal consistency violations are also returned as errors (via `InvalidStructure`)
12//!
13//! This makes the library safe to use in production environments where panics are unacceptable.
14//!
15//! ## Error Types
16//!
17//! [`Lib3mfError`] is the main error enum, with variants covering different failure modes:
18//!
19//! - **Io**: File system errors, network errors, ZIP reading failures
20//! - **Validation**: Model failed validation checks (see [`crate::validation`])
21//! - **ResourceNotFound**: Referenced resource ID doesn't exist in the model
22//! - **InvalidStructure**: Malformed XML, missing required elements, spec violations
23//! - **EncryptionError**: Cryptographic operations failed (wrong key, tampered data)
24//! - **FeatureNotEnabled**: Operation requires a cargo feature that wasn't enabled
25//!
26//! ## Usage
27//!
28//! The [`Result`] type alias is provided for convenience:
29//!
30//! ```
31//! use lib3mf_core::error::{Lib3mfError, Result};
32//!
33//! fn parse_something() -> Result<String> {
34//! // Use the ? operator to propagate errors
35//! Ok("success".to_string())
36//! }
37//! ```
38//!
39//! ## Error Context
40//!
41//! Most error variants include a `String` message with context about what failed:
42//!
43//! ```
44//! use lib3mf_core::error::Lib3mfError;
45//!
46//! let error = Lib3mfError::InvalidStructure(
47//! "Missing required 'unit' attribute on <model> element".to_string()
48//! );
49//!
50//! // Error messages are human-readable
51//! assert_eq!(
52//! error.to_string(),
53//! "Invalid 3MF structure: Missing required 'unit' attribute on <model> element"
54//! );
55//! ```
56
57use thiserror::Error;
58
59#[derive(Error, Debug)]
60pub enum Lib3mfError {
61 #[error("I/O error: {0}")]
62 Io(#[from] std::io::Error),
63
64 #[error("Validation failed: {0}")]
65 Validation(String),
66
67 #[error("Resource not found: {0}")]
68 ResourceNotFound(u32),
69
70 #[error("Invalid 3MF structure: {0}")]
71 InvalidStructure(String),
72 #[error("Encryption error: {0}")]
73 EncryptionError(String),
74
75 #[error("Feature not enabled: {0}. Rebuild with `cargo build --features {1}`")]
76 FeatureNotEnabled(String, String),
77}
78
79pub type Result<T> = std::result::Result<T, Lib3mfError>;