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("IO error: {0}")]
39    Io(#[from] std::io::Error),
40
41    #[cfg(feature = "json")]
42    #[error("JSON error: {0}")]
43    Json(#[from] serde_json::Error),
44
45    #[cfg(feature = "calamine")]
46    #[error("Calamine error: {0}")]
47    Calamine(#[from] calamine::Error),
48}
49
50impl IoError {
51    pub fn from_backend<E: std::error::Error>(backend: &str, err: E) -> Self {
52        IoError::Backend {
53            backend: backend.to_string(),
54            message: err.to_string(),
55        }
56    }
57}
58
59pub fn with_cell_context(err: impl std::error::Error, sheet: &str, row: u32, col: u32) -> IoError {
60    IoError::CellError {
61        sheet: sheet.to_string(),
62        row,
63        col: col_to_a1(col),
64        message: err.to_string(),
65    }
66}
67
68pub fn col_to_a1(col: u32) -> String {
69    let mut result = String::new();
70    let mut n = col - 1; // Convert to 0-based
71
72    loop {
73        result.insert(0, (b'A' + (n % 26) as u8) as char);
74        n /= 26;
75        if n == 0 {
76            break;
77        }
78        n -= 1;
79    }
80
81    result
82}