bq_schema_gen/
error.rs

1//! Error types for the BigQuery schema generator.
2
3use thiserror::Error;
4
5/// Main error type for the schema generator.
6#[derive(Error, Debug)]
7pub enum Error {
8    #[error("Invalid record: {0}")]
9    InvalidRecord(String),
10
11    #[error("JSON parse error on line {line}: {message}")]
12    JsonParse { line: usize, message: String },
13
14    #[error("CSV parse error: {0}")]
15    CsvParse(String),
16
17    #[error("IO error: {0}")]
18    Io(#[from] std::io::Error),
19
20    #[error("Schema file error: {0}")]
21    SchemaFile(String),
22}
23
24/// Result type alias for this crate.
25pub type Result<T> = std::result::Result<T, Error>;
26
27/// An error log entry for non-fatal issues during schema generation.
28#[derive(Debug, Clone)]
29pub struct ErrorLog {
30    /// Line number where the error occurred
31    pub line_number: usize,
32    /// Error message
33    pub msg: String,
34}
35
36impl std::fmt::Display for ErrorLog {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        write!(f, "Line {}: {}", self.line_number, self.msg)
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    #[test]
47    fn test_error_log_display() {
48        let error = ErrorLog {
49            line_number: 42,
50            msg: "test error".to_string(),
51        };
52        assert_eq!(format!("{}", error), "Line 42: test error");
53    }
54
55    #[test]
56    fn test_error_log_display_line_one() {
57        let error = ErrorLog {
58            line_number: 1,
59            msg: "first line error".to_string(),
60        };
61        assert_eq!(format!("{}", error), "Line 1: first line error");
62    }
63
64    #[test]
65    fn test_error_log_display_large_line_number() {
66        let error = ErrorLog {
67            line_number: 1_000_000,
68            msg: "large line".to_string(),
69        };
70        assert_eq!(format!("{}", error), "Line 1000000: large line");
71    }
72
73    #[test]
74    fn test_error_log_display_empty_message() {
75        let error = ErrorLog {
76            line_number: 10,
77            msg: String::new(),
78        };
79        assert_eq!(format!("{}", error), "Line 10: ");
80    }
81
82    #[test]
83    fn test_error_invalid_record_display() {
84        let error = Error::InvalidRecord("not an object".to_string());
85        assert_eq!(format!("{}", error), "Invalid record: not an object");
86    }
87
88    #[test]
89    fn test_error_json_parse_display() {
90        let error = Error::JsonParse {
91            line: 5,
92            message: "unexpected token".to_string(),
93        };
94        assert_eq!(
95            format!("{}", error),
96            "JSON parse error on line 5: unexpected token"
97        );
98    }
99
100    #[test]
101    fn test_error_csv_parse_display() {
102        let error = Error::CsvParse("invalid CSV".to_string());
103        assert_eq!(format!("{}", error), "CSV parse error: invalid CSV");
104    }
105
106    #[test]
107    fn test_error_io_display() {
108        let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
109        let error = Error::Io(io_error);
110        assert!(format!("{}", error).contains("IO error"));
111        assert!(format!("{}", error).contains("file not found"));
112    }
113
114    #[test]
115    fn test_error_schema_file_display() {
116        let error = Error::SchemaFile("invalid schema format".to_string());
117        assert_eq!(
118            format!("{}", error),
119            "Schema file error: invalid schema format"
120        );
121    }
122
123    #[test]
124    fn test_error_from_io_error() {
125        let io_error = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "access denied");
126        let error: Error = io_error.into();
127        assert!(matches!(error, Error::Io(_)));
128    }
129}