1use thiserror::Error;
7
8#[derive(Debug, Error)]
10pub enum Error {
11 #[error("TOON serialization error: {0}")]
13 Serialize(String),
14
15 #[error("TOON deserialization error: {0}")]
17 Deserialize(String),
18
19 #[error("Invalid TOON table: {0}")]
21 InvalidTable(String),
22
23 #[error("Missing required column: {0}")]
25 MissingColumn(&'static str),
26
27 #[error("Conversion error: {0}")]
29 ConversionError(String),
30
31 #[error("Invalid value type: expected {expected}, got {got}")]
33 InvalidType {
34 expected: &'static str,
36 got: String,
38 },
39
40 #[error("Row index {index} out of bounds (table has {len} rows)")]
42 RowOutOfBounds {
43 index: usize,
45 len: usize,
47 },
48
49 #[error("Column index {index} out of bounds (table has {len} columns)")]
51 ColumnOutOfBounds {
52 index: usize,
54 len: usize,
56 },
57}
58
59pub type Result<T> = std::result::Result<T, Error>;
61
62impl From<serde_toon2::Error> for Error {
63 fn from(err: serde_toon2::Error) -> Self {
64 let msg = err.to_string();
67 if msg.contains("serialize") || msg.contains("Serialize") {
68 Error::Serialize(msg)
69 } else {
70 Error::Deserialize(msg)
71 }
72 }
73}
74
75impl Error {
76 pub fn serialize<S: Into<String>>(msg: S) -> Self {
78 Error::Serialize(msg.into())
79 }
80
81 pub fn deserialize<S: Into<String>>(msg: S) -> Self {
83 Error::Deserialize(msg.into())
84 }
85
86 pub fn invalid_table<S: Into<String>>(msg: S) -> Self {
88 Error::InvalidTable(msg.into())
89 }
90
91 pub fn missing_column(name: &'static str) -> Self {
93 Error::MissingColumn(name)
94 }
95
96 pub fn conversion<S: Into<String>>(msg: S) -> Self {
98 Error::ConversionError(msg.into())
99 }
100
101 pub fn invalid_type(expected: &'static str, got: impl std::fmt::Debug) -> Self {
103 Error::InvalidType {
104 expected,
105 got: format!("{:?}", got),
106 }
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn test_error_display() {
116 let err = Error::MissingColumn("id");
117 assert_eq!(err.to_string(), "Missing required column: id");
118
119 let err = Error::InvalidType {
120 expected: "string",
121 got: "number".to_string(),
122 };
123 assert!(err.to_string().contains("expected string"));
124 }
125
126 #[test]
127 fn test_error_constructors() {
128 let err = Error::serialize("failed to write");
129 assert!(matches!(err, Error::Serialize(_)));
130
131 let err = Error::invalid_table("missing header");
132 assert!(matches!(err, Error::InvalidTable(_)));
133 }
134}