Skip to main content

formualizer_workbook/
error.rs

1use formualizer_common::error::ExcelError;
2use thiserror::Error;
3
4#[derive(Error, Debug)]
5pub enum IoError {
6    #[error("Backend error in {backend}: {message}")]
7    Backend { backend: String, message: String },
8
9    #[error("Engine error: {0}")]
10    Engine(#[from] ExcelError),
11
12    #[error("Formula parse error at {sheet}!{col}{row}: {message}")]
13    FormulaParser {
14        sheet: String,
15        row: u32,
16        col: String,
17        message: String,
18    },
19
20    #[error("Schema error: {message}")]
21    Schema {
22        message: String,
23        #[source]
24        source: Option<Box<dyn std::error::Error + Send + Sync>>,
25    },
26
27    #[error("Unsupported feature: {feature} in {context}")]
28    Unsupported { feature: String, context: String },
29
30    #[error("Cell error at {sheet}!{col}{row}: {message}")]
31    CellError {
32        sheet: String,
33        row: u32,
34        col: String,
35        message: String,
36    },
37
38    #[error("Workbook load budget exceeded in {backend} for sheet {sheet}: {message}")]
39    LoadBudgetExceeded {
40        backend: String,
41        sheet: String,
42        message: String,
43    },
44
45    #[error("IO error: {0}")]
46    Io(#[from] std::io::Error),
47
48    #[cfg(feature = "json")]
49    #[error("JSON error: {0}")]
50    Json(#[from] serde_json::Error),
51
52    #[cfg(feature = "calamine")]
53    #[error("Calamine error: {0}")]
54    Calamine(#[from] calamine::Error),
55}
56
57impl IoError {
58    pub fn from_backend<E: std::error::Error>(backend: &str, err: E) -> Self {
59        IoError::Backend {
60            backend: backend.to_string(),
61            message: err.to_string(),
62        }
63    }
64
65    pub fn load_budget_exceeded(backend: &str, sheet: &str, message: String) -> Self {
66        IoError::LoadBudgetExceeded {
67            backend: backend.to_string(),
68            sheet: sheet.to_string(),
69            message,
70        }
71    }
72}
73
74pub fn with_cell_context(err: impl std::error::Error, sheet: &str, row: u32, col: u32) -> IoError {
75    IoError::CellError {
76        sheet: sheet.to_string(),
77        row,
78        col: col_to_a1(col),
79        message: err.to_string(),
80    }
81}
82
83pub fn col_to_a1(col: u32) -> String {
84    let mut result = String::new();
85    let mut n = col - 1; // Convert to 0-based
86
87    loop {
88        result.insert(0, (b'A' + (n % 26) as u8) as char);
89        n /= 26;
90        if n == 0 {
91            break;
92        }
93        n -= 1;
94    }
95
96    result
97}