torii_core/error/
utilities.rs1use crate::{
2 Error,
3 error::{StorageError, ValidationError},
4};
5
6pub trait DatabaseResultExt<T> {
23 fn map_db_err(self) -> Result<T, Error>;
25
26 fn map_db_err_with_context(self, context: &str) -> Result<T, Error>;
28}
29
30impl<T, E: std::fmt::Display> DatabaseResultExt<T> for Result<T, E> {
31 fn map_db_err(self) -> Result<T, Error> {
32 self.map_err(|e| Error::Storage(StorageError::Database(e.to_string())))
33 }
34
35 fn map_db_err_with_context(self, context: &str) -> Result<T, Error> {
36 self.map_err(|e| Error::Storage(StorageError::Database(format!("{context}: {e}"))))
37 }
38}
39
40pub trait RequiredFieldExt<T> {
57 fn require_field(self, field_name: &str) -> Result<T, ValidationError>;
59}
60
61impl<T> RequiredFieldExt<T> for Option<T> {
62 fn require_field(self, field_name: &str) -> Result<T, ValidationError> {
63 self.ok_or_else(|| ValidationError::MissingField(format!("{field_name} is required")))
64 }
65}
66
67#[macro_export]
84macro_rules! map_storage_err {
85 ($result:expr) => {
86 $result.map_err(|e| {
87 $crate::Error::Storage($crate::error::StorageError::Database(e.to_string()))
88 })
89 };
90}
91
92#[macro_export]
102macro_rules! map_storage_err_with_context {
103 ($result:expr, $context:expr) => {
104 $result.map_err(|e| {
105 $crate::Error::Storage($crate::error::StorageError::Database(format!(
106 "{}: {}",
107 $context, e
108 )))
109 })
110 };
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116 use crate::error::{StorageError, ValidationError};
117
118 #[test]
119 fn test_database_result_ext() {
120 let error_result: Result<i32, &str> = Err("database connection failed");
121 let mapped = error_result.map_db_err();
122
123 assert!(mapped.is_err());
124 match mapped.unwrap_err() {
125 Error::Storage(StorageError::Database(msg)) => {
126 assert_eq!(msg, "database connection failed");
127 }
128 _ => panic!("Expected storage database error"),
129 }
130 }
131
132 #[test]
133 fn test_database_result_ext_with_context() {
134 let error_result: Result<i32, &str> = Err("timeout");
135 let mapped = error_result.map_db_err_with_context("Failed to save user");
136
137 assert!(mapped.is_err());
138 match mapped.unwrap_err() {
139 Error::Storage(StorageError::Database(msg)) => {
140 assert_eq!(msg, "Failed to save user: timeout");
141 }
142 _ => panic!("Expected storage database error"),
143 }
144 }
145
146 #[test]
147 fn test_required_field_ext_some() {
148 let some_value = Some("test@example.com".to_string());
149 let result = some_value.require_field("Email");
150
151 assert!(result.is_ok());
152 assert_eq!(result.unwrap(), "test@example.com");
153 }
154
155 #[test]
156 fn test_required_field_ext_none() {
157 let none_value: Option<String> = None;
158 let result = none_value.require_field("Email");
159
160 assert!(result.is_err());
161 match result.unwrap_err() {
162 ValidationError::MissingField(msg) => {
163 assert_eq!(msg, "Email is required");
164 }
165 _ => panic!("Expected missing field validation error"),
166 }
167 }
168
169 #[test]
170 fn test_map_storage_err_macro() {
171 let error_result: Result<i32, &str> = Err("query failed");
172 let mapped = map_storage_err!(error_result);
173
174 assert!(mapped.is_err());
175 match mapped.unwrap_err() {
176 Error::Storage(StorageError::Database(msg)) => {
177 assert_eq!(msg, "query failed");
178 }
179 _ => panic!("Expected storage database error"),
180 }
181 }
182
183 #[test]
184 fn test_map_storage_err_with_context_macro() {
185 let error_result: Result<i32, &str> = Err("foreign key constraint");
186 let mapped = map_storage_err_with_context!(error_result, "Creating user");
187
188 assert!(mapped.is_err());
189 match mapped.unwrap_err() {
190 Error::Storage(StorageError::Database(msg)) => {
191 assert_eq!(msg, "Creating user: foreign key constraint");
192 }
193 _ => panic!("Expected storage database error"),
194 }
195 }
196}