1use rusqlite::Row;
4use serde_json::Value as JsonValue;
5
6pub trait FromSqliteRow: Sized {
10 fn from_row(row: &Row<'_>) -> Result<Self, FromSqliteRowError>;
12}
13
14#[derive(Debug)]
16pub struct FromSqliteRowError {
17 pub message: String,
19 pub column: Option<String>,
21}
22
23impl FromSqliteRowError {
24 pub fn new(message: impl Into<String>) -> Self {
26 Self {
27 message: message.into(),
28 column: None,
29 }
30 }
31
32 pub fn with_column(message: impl Into<String>, column: impl Into<String>) -> Self {
34 Self {
35 message: message.into(),
36 column: Some(column.into()),
37 }
38 }
39}
40
41impl std::fmt::Display for FromSqliteRowError {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 if let Some(ref column) = self.column {
44 write!(f, "column '{}': {}", column, self.message)
45 } else {
46 write!(f, "{}", self.message)
47 }
48 }
49}
50
51impl std::error::Error for FromSqliteRowError {}
52
53impl From<rusqlite::Error> for FromSqliteRowError {
54 fn from(err: rusqlite::Error) -> Self {
55 Self::new(err.to_string())
56 }
57}
58
59impl FromSqliteRow for JsonValue {
61 fn from_row(row: &Row<'_>) -> Result<Self, FromSqliteRowError> {
62 let column_count = row.as_ref().column_count();
63 let mut map = serde_json::Map::new();
64
65 for i in 0..column_count {
66 let name = row
67 .as_ref()
68 .column_name(i)
69 .map_err(|e| FromSqliteRowError::new(e.to_string()))?
70 .to_string();
71 let value = crate::types::get_value_at_index(row, i);
72 map.insert(name, value);
73 }
74
75 Ok(JsonValue::Object(map))
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn test_from_sqlite_row_error_new() {
85 let err = FromSqliteRowError::new("test error");
86 assert_eq!(err.message, "test error");
87 assert!(err.column.is_none());
88 }
89
90 #[test]
91 fn test_from_sqlite_row_error_with_column() {
92 let err = FromSqliteRowError::with_column("invalid type", "user_id");
93 assert_eq!(err.message, "invalid type");
94 assert_eq!(err.column, Some("user_id".to_string()));
95 }
96
97 #[test]
98 fn test_from_sqlite_row_error_display() {
99 let err = FromSqliteRowError::with_column("missing value", "email");
100 let display = format!("{}", err);
101 assert!(display.contains("email"));
102 assert!(display.contains("missing value"));
103 }
104}