Skip to main content

reinhardt_core/serializers/
serializer.rs

1//! Core serialization traits and implementations
2//!
3//! Provides the foundational `Serializer` and `Deserializer` traits along with
4//! error types for serialization operations.
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9/// Core serializer trait for converting between input and output representations
10///
11/// # Type Parameters
12///
13/// - `Input`: The source type to serialize
14/// - `Output`: The target serialized representation
15///
16/// # Examples
17///
18/// ```
19/// use reinhardt_core::serializers::{Serializer, JsonSerializer};
20/// use serde::{Serialize, Deserialize};
21///
22/// #[derive(Serialize, Deserialize)]
23/// struct User { id: i64, name: String }
24///
25/// let user = User { id: 1, name: "Alice".to_string() };
26/// let serializer = JsonSerializer::<User>::new();
27/// let json = serializer.serialize(&user).unwrap();
28/// assert!(json.contains("Alice"));
29/// ```
30pub trait Serializer {
31	type Input;
32	type Output;
33
34	fn serialize(&self, input: &Self::Input) -> Result<Self::Output, SerializerError>;
35	fn deserialize(&self, output: &Self::Output) -> Result<Self::Input, SerializerError>;
36}
37
38/// Errors that can occur during validation
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub enum ValidatorError {
41	/// Unique constraint violation
42	UniqueViolation {
43		field_name: String,
44		value: String,
45		message: String,
46	},
47	/// Unique together constraint violation
48	UniqueTogetherViolation {
49		field_names: Vec<String>,
50		values: HashMap<String, String>,
51		message: String,
52	},
53	/// Required field missing
54	RequiredField { field_name: String, message: String },
55	/// Field validation error
56	FieldValidation {
57		field_name: String,
58		value: String,
59		constraint: String,
60		message: String,
61	},
62	/// Database error
63	DatabaseError {
64		message: String,
65		source: Option<String>,
66	},
67	/// Custom validation error
68	Custom { message: String },
69}
70
71impl std::fmt::Display for ValidatorError {
72	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73		match self {
74			ValidatorError::UniqueViolation {
75				field_name,
76				value,
77				message,
78			} => write!(
79				f,
80				"Unique violation on field '{}' with value '{}': {}",
81				field_name, value, message
82			),
83			ValidatorError::UniqueTogetherViolation {
84				field_names,
85				values,
86				message,
87			} => {
88				// Format field_names as [username, email]
89				let fields_str = format!("[{}]", field_names.join(", "));
90				// Format values as (username=alice, email=alice@example.com)
91				// Sort by key to ensure deterministic order
92				let mut sorted_values: Vec<_> = values.iter().collect();
93				sorted_values.sort_by_key(|(k, _)| *k);
94				let values_str = sorted_values
95					.into_iter()
96					.map(|(k, v)| format!("{}={}", k, v))
97					.collect::<Vec<_>>()
98					.join(", ");
99				write!(
100					f,
101					"Unique together violation on fields {} with values ({}): {}",
102					fields_str, values_str, message
103				)
104			}
105			ValidatorError::RequiredField {
106				field_name,
107				message,
108			} => write!(f, "Required field '{}': {}", field_name, message),
109			ValidatorError::FieldValidation {
110				field_name,
111				value,
112				constraint,
113				message,
114			} => write!(
115				f,
116				"Field '{}' with value '{}' failed constraint '{}': {}",
117				field_name, value, constraint, message
118			),
119			ValidatorError::DatabaseError { message, source } => {
120				if let Some(src) = source {
121					write!(f, "Database error: {} (source: {})", message, src)
122				} else {
123					write!(f, "Database error: {}", message)
124				}
125			}
126			ValidatorError::Custom { message } => write!(f, "Validation error: {}", message),
127		}
128	}
129}
130
131impl std::error::Error for ValidatorError {}
132
133impl ValidatorError {
134	/// Returns the error message
135	pub fn message(&self) -> &str {
136		match self {
137			ValidatorError::UniqueViolation { message, .. } => message,
138			ValidatorError::UniqueTogetherViolation { message, .. } => message,
139			ValidatorError::RequiredField { message, .. } => message,
140			ValidatorError::FieldValidation { message, .. } => message,
141			ValidatorError::DatabaseError { message, .. } => message,
142			ValidatorError::Custom { message } => message,
143		}
144	}
145
146	/// Returns the field names involved in this error
147	pub fn field_names(&self) -> Vec<&str> {
148		match self {
149			ValidatorError::UniqueViolation { field_name, .. } => vec![field_name.as_str()],
150			ValidatorError::UniqueTogetherViolation { field_names, .. } => {
151				field_names.iter().map(|s| s.as_str()).collect()
152			}
153			ValidatorError::RequiredField { field_name, .. } => vec![field_name.as_str()],
154			ValidatorError::FieldValidation { field_name, .. } => vec![field_name.as_str()],
155			ValidatorError::DatabaseError { .. } => vec![],
156			ValidatorError::Custom { .. } => vec![],
157		}
158	}
159
160	/// Check if this is a uniqueness violation error
161	pub fn is_uniqueness_violation(&self) -> bool {
162		matches!(
163			self,
164			ValidatorError::UniqueViolation { .. } | ValidatorError::UniqueTogetherViolation { .. }
165		)
166	}
167
168	/// Check if this is a database error
169	pub fn is_database_error(&self) -> bool {
170		matches!(self, ValidatorError::DatabaseError { .. })
171	}
172}
173
174/// Errors that can occur during serialization
175#[derive(Debug, Clone)]
176pub enum SerializerError {
177	/// Validation error
178	Validation(ValidatorError),
179	/// Serde serialization/deserialization error
180	Serde { message: String },
181	/// Other error
182	Other { message: String },
183}
184
185impl std::fmt::Display for SerializerError {
186	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187		match self {
188			SerializerError::Validation(e) => write!(f, "{}", e),
189			SerializerError::Serde { message } => write!(f, "Serde error: {}", message),
190			SerializerError::Other { message } => write!(f, "Serialization error: {}", message),
191		}
192	}
193}
194
195impl std::error::Error for SerializerError {
196	fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
197		match self {
198			SerializerError::Validation(e) => Some(e),
199			_ => None,
200		}
201	}
202}
203
204impl From<ValidatorError> for SerializerError {
205	fn from(err: ValidatorError) -> Self {
206		SerializerError::Validation(err)
207	}
208}
209
210impl SerializerError {
211	/// Create a new generic serializer error
212	pub fn new(message: String) -> Self {
213		SerializerError::Other { message }
214	}
215
216	/// Create a validation error from a ValidatorError
217	pub fn validation(error: ValidatorError) -> Self {
218		SerializerError::Validation(error)
219	}
220
221	/// Create a unique violation error
222	pub fn unique_violation(field_name: String, value: String, message: String) -> Self {
223		SerializerError::Validation(ValidatorError::UniqueViolation {
224			field_name,
225			value,
226			message,
227		})
228	}
229
230	/// Create a unique together violation error
231	pub fn unique_together_violation(
232		field_names: Vec<String>,
233		values: HashMap<String, String>,
234		message: String,
235	) -> Self {
236		SerializerError::Validation(ValidatorError::UniqueTogetherViolation {
237			field_names,
238			values,
239			message,
240		})
241	}
242
243	/// Create a required field error
244	pub fn required_field(field_name: String, message: String) -> Self {
245		SerializerError::Validation(ValidatorError::RequiredField {
246			field_name,
247			message,
248		})
249	}
250
251	/// Create a field validation error
252	pub fn field_validation(
253		field_name: String,
254		value: String,
255		constraint: String,
256		message: String,
257	) -> Self {
258		SerializerError::Validation(ValidatorError::FieldValidation {
259			field_name,
260			value,
261			constraint,
262			message,
263		})
264	}
265
266	/// Create a database error
267	pub fn database_error(message: String, source: Option<String>) -> Self {
268		SerializerError::Validation(ValidatorError::DatabaseError { message, source })
269	}
270
271	/// Check if this is a validation error
272	pub fn is_validation_error(&self) -> bool {
273		matches!(self, SerializerError::Validation(_))
274	}
275
276	/// Returns the error message
277	pub fn message(&self) -> String {
278		match self {
279			SerializerError::Validation(e) => e.message().to_string(),
280			SerializerError::Serde { message } => message.clone(),
281			SerializerError::Other { message } => message.clone(),
282		}
283	}
284
285	/// Try to convert to ValidatorError if this is a validation error
286	pub fn as_validator_error(&self) -> Option<&ValidatorError> {
287		match self {
288			SerializerError::Validation(e) => Some(e),
289			_ => None,
290		}
291	}
292}
293
294// Integration with reinhardt_exception is moved to REST layer
295// Base layer remains exception-agnostic
296
297/// JSON serializer implementation
298///
299/// Provides JSON serialization/deserialization using serde_json.
300///
301/// # Examples
302///
303/// ```
304/// use reinhardt_core::serializers::{Serializer, JsonSerializer};
305/// use serde::{Serialize, Deserialize};
306///
307/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
308/// struct User { id: i64, name: String }
309///
310/// let user = User { id: 1, name: "Alice".to_string() };
311/// let serializer = JsonSerializer::<User>::new();
312///
313/// let json = serializer.serialize(&user).unwrap();
314/// let deserialized = serializer.deserialize(&json).unwrap();
315/// assert_eq!(user.id, deserialized.id);
316/// ```
317pub struct JsonSerializer<T> {
318	_phantom: std::marker::PhantomData<T>,
319}
320
321impl<T> JsonSerializer<T> {
322	/// Create a new JSON serializer
323	pub fn new() -> Self {
324		Self {
325			_phantom: std::marker::PhantomData,
326		}
327	}
328}
329
330impl<T> Default for JsonSerializer<T> {
331	fn default() -> Self {
332		Self::new()
333	}
334}
335
336impl<T> Serializer for JsonSerializer<T>
337where
338	T: Serialize + for<'de> Deserialize<'de>,
339{
340	type Input = T;
341	type Output = String;
342
343	fn serialize(&self, input: &Self::Input) -> Result<Self::Output, SerializerError> {
344		serde_json::to_string(input).map_err(|e| SerializerError::Serde {
345			message: format!("Serialization error: {}", e),
346		})
347	}
348
349	fn deserialize(&self, output: &Self::Output) -> Result<Self::Input, SerializerError> {
350		serde_json::from_str(output).map_err(|e| SerializerError::Serde {
351			message: format!("Deserialization error: {}", e),
352		})
353	}
354}
355
356/// Deserializer trait for one-way deserialization
357///
358/// # Examples
359///
360/// ```
361/// use reinhardt_core::serializers::Deserializer;
362/// use serde::{Deserialize, Serialize};
363///
364/// struct JsonDeserializer;
365///
366/// impl Deserializer for JsonDeserializer {
367///     type Input = String;
368///     type Output = serde_json::Value;
369///
370///     fn deserialize(&self, input: &Self::Input) -> Result<Self::Output, reinhardt_core::serializers::SerializerError> {
371///         serde_json::from_str(input).map_err(|e| reinhardt_core::serializers::SerializerError::Serde {
372///             message: format!("Deserialization error: {}", e),
373///         })
374///     }
375/// }
376/// ```
377pub trait Deserializer {
378	type Input;
379	type Output;
380
381	fn deserialize(&self, input: &Self::Input) -> Result<Self::Output, SerializerError>;
382}
383
384#[cfg(test)]
385mod tests {
386	use super::*;
387
388	#[derive(Serialize, Deserialize, PartialEq, Debug)]
389	struct TestUser {
390		id: i64,
391		name: String,
392	}
393
394	#[test]
395	fn test_json_serializer_roundtrip() {
396		let user = TestUser {
397			id: 1,
398			name: "Alice".to_string(),
399		};
400		let serializer = JsonSerializer::<TestUser>::new();
401
402		let json = serializer.serialize(&user).unwrap();
403		let deserialized = serializer.deserialize(&json).unwrap();
404
405		assert_eq!(user.id, deserialized.id);
406		assert_eq!(user.name, deserialized.name);
407	}
408
409	#[test]
410	fn test_json_serializer_serialize() {
411		let user = TestUser {
412			id: 1,
413			name: "Alice".to_string(),
414		};
415		let serializer = JsonSerializer::<TestUser>::new();
416
417		let json = serializer.serialize(&user).unwrap();
418		assert!(json.contains("Alice"));
419		assert!(json.contains("\"id\":1"));
420	}
421
422	#[test]
423	fn test_json_serializer_deserialize() {
424		let json = r#"{"id":1,"name":"Alice"}"#.to_string();
425		let serializer = JsonSerializer::<TestUser>::new();
426
427		let user = serializer.deserialize(&json).unwrap();
428		assert_eq!(user.id, 1);
429		assert_eq!(user.name, "Alice");
430	}
431
432	#[test]
433	fn test_json_serializer_deserialize_error() {
434		let invalid_json = r#"{"invalid"}"#.to_string();
435		let serializer = JsonSerializer::<TestUser>::new();
436
437		let result = serializer.deserialize(&invalid_json);
438		assert!(result.is_err());
439	}
440
441	#[test]
442	fn test_validator_error_display() {
443		let err = ValidatorError::UniqueViolation {
444			field_name: "email".to_string(),
445			value: "test@example.com".to_string(),
446			message: "Email already exists".to_string(),
447		};
448		assert!(err.to_string().contains("email"));
449		assert!(err.to_string().contains("test@example.com"));
450	}
451
452	#[test]
453	fn test_serializer_error_from_validator_error() {
454		let validator_err = ValidatorError::Custom {
455			message: "test error".to_string(),
456		};
457		let serializer_err: SerializerError = validator_err.into();
458
459		match serializer_err {
460			SerializerError::Validation(_) => {}
461			_ => panic!("Expected Validation error"),
462		}
463	}
464}