formualizer_workbook/
error.rs1use 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; 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}