train_station/serialization/core/serializer.rs
1//! Core serializer for structured data serialization
2//!
3//! This module provides the `StructSerializer` which enables building complex serializable
4//! structures using a fluent interface without requiring trait imports. The serializer
5//! supports both JSON and binary formats with automatic type detection and field validation.
6//!
7//! # Purpose
8//!
9//! The serializer module provides:
10//! - Fluent interface for building structured data without trait imports
11//! - Automatic type detection and conversion through `ToFieldValue` trait
12//! - Support for both JSON and binary serialization formats
13//! - File I/O operations with proper error handling
14//! - Type-safe field registration with insertion order preservation
15//! - Memory-efficient serialization with pre-allocated capacity options
16//!
17//! # Usage Patterns
18//!
19//! The `StructSerializer` is designed for building complex data structures
20//! with automatic type detection and fluent method chaining.
21//!
22//! # Serialization Formats
23//!
24//! ## JSON Format
25//! - Human-readable text format for debugging and data exchange
26//! - UTF-8 encoded with proper escaping
27//! - Maintains field order and type information
28//! - Compatible with standard JSON parsers
29//!
30//! ## Binary Format
31//! - Compact binary representation for efficient storage
32//! - Platform-independent with proper endianness handling
33//! - Includes type information and field metadata
34//! - Optimized for fast serialization and deserialization
35//!
36//! # Field Types
37//!
38//! The serializer supports all types implementing `ToFieldValue`:
39//! - **Primitive types**: `bool`, `i8`, `i16`, `i32`, `i64`, `u8`, `u16`, `u32`, `u64`, `usize`, `f32`, `f64`
40//! - **String types**: `String`, `&str`
41//! - **Collections**: `Vec<T>`, `HashMap<String, String>`, `Option<T>`
42//! - **Custom types**: Any type implementing `ToFieldValue` trait
43//!
44//! # Error Handling
45//!
46//! All serialization operations return `SerializationResult<T>` which provides:
47//! - Detailed error messages for debugging
48//! - Type-specific error information
49//! - File I/O error propagation
50//! - Validation error reporting
51//!
52//! # Thread Safety
53//!
54//! The `StructSerializer` is not thread-safe and should not be shared between threads.
55//! Each thread should create its own serializer instance for concurrent operations.
56
57use super::error::SerializationResult;
58use super::traits::ToFieldValue;
59use super::types::FieldValue;
60use std::fs::OpenOptions;
61use std::io::{BufWriter, Write};
62use std::path::Path;
63
64/// Builder for serializing structured data with fluent interface
65///
66/// This struct provides a fluent interface for building complex serializable structures
67/// without requiring trait imports. It maintains type safety while allowing for future
68/// extensibility with field attributes and customization options.
69///
70/// The serializer supports both JSON and binary formats, with automatic type detection
71/// through the `ToFieldValue` trait. Fields are stored in insertion order to maintain
72/// consistent serialization output.
73///
74/// # Fields
75///
76/// * `fields` - Vector of field name-value pairs preserving insertion order
77///
78/// # Examples
79///
80/// The serializer provides a fluent interface for building structured data
81/// with automatic type detection and support for both JSON and binary formats.
82///
83/// # Thread Safety
84///
85/// This type is not thread-safe. Each thread should create its own instance
86/// for concurrent serialization operations.
87#[derive(Debug)]
88pub struct StructSerializer {
89 /// Field storage with insertion order preservation
90 ///
91 /// Vector of (field_name, field_value) pairs that maintains the order
92 /// in which fields were added to the serializer. This ensures consistent
93 /// output across multiple serialization runs.
94 pub(crate) fields: Vec<(String, FieldValue)>,
95}
96
97impl StructSerializer {
98 /// Creates a new empty struct serializer
99 ///
100 /// Returns a new `StructSerializer` with an empty field collection.
101 /// Use this constructor when you don't know the final number of fields
102 /// in advance.
103 ///
104 /// # Returns
105 ///
106 /// A new `StructSerializer` instance ready for field registration
107 ///
108 /// # Examples
109 ///
110 /// Creates a new empty serializer ready for field registration.
111 pub fn new() -> Self {
112 Self { fields: Vec::new() }
113 }
114
115 /// Creates a new struct serializer with pre-allocated capacity
116 ///
117 /// Returns a new `StructSerializer` with enough capacity to hold the specified
118 /// number of fields without reallocating. This is useful for performance-critical
119 /// applications where you know the number of fields in advance.
120 ///
121 /// # Arguments
122 ///
123 /// * `capacity` - Number of fields the serializer should be able to hold without reallocating
124 ///
125 /// # Returns
126 ///
127 /// A new `StructSerializer` instance with pre-allocated capacity
128 ///
129 /// # Examples
130 ///
131 /// Creates a serializer with pre-allocated capacity for performance optimization.
132 pub fn with_capacity(capacity: usize) -> Self {
133 Self {
134 fields: Vec::with_capacity(capacity),
135 }
136 }
137
138 /// Registers a field with automatic type detection
139 ///
140 /// Adds a field to the serializer with automatic type conversion through the
141 /// `ToFieldValue` trait. The field name is preserved as a string, and the value
142 /// is converted to a `FieldValue` for serialization.
143 ///
144 /// This method consumes `self` and returns a new `StructSerializer` with the
145 /// field added, enabling fluent method chaining.
146 ///
147 /// # Arguments
148 ///
149 /// * `name` - Field name as a string slice
150 /// * `value` - Field value that implements `ToFieldValue`
151 ///
152 /// # Returns
153 ///
154 /// A new `StructSerializer` with the field added
155 ///
156 /// # Examples
157 ///
158 /// Adds a field with automatic type conversion and enables fluent method chaining.
159 pub fn field<T>(mut self, name: &str, value: &T) -> Self
160 where
161 T: ToFieldValue,
162 {
163 let field_value = value.to_field_value();
164 self.fields.push((name.to_string(), field_value));
165 self
166 }
167
168 /// Converts the struct to a JSON string
169 ///
170 /// Serializes all registered fields to a JSON string format. The JSON output
171 /// is human-readable and maintains field order and type information.
172 ///
173 /// This method consumes the serializer, preventing further field additions.
174 ///
175 /// # Returns
176 ///
177 /// `Ok(String)` containing the JSON representation on success
178 /// `Err(SerializationError)` if serialization fails
179 ///
180 /// # Examples
181 ///
182 /// Serializes all fields to human-readable JSON format with proper escaping.
183 pub fn to_json(self) -> SerializationResult<String> {
184 crate::serialization::json::to_json_internal(self)
185 }
186
187 /// Converts the struct to binary data
188 ///
189 /// Serializes all registered fields to a compact binary format. The binary
190 /// output is platform-independent and optimized for fast serialization
191 /// and deserialization.
192 ///
193 /// This method consumes the serializer, preventing further field additions.
194 ///
195 /// # Returns
196 ///
197 /// `Ok(Vec<u8>)` containing the binary representation on success
198 /// `Err(SerializationError)` if serialization fails
199 ///
200 /// # Examples
201 ///
202 /// Serializes all fields to compact binary format for efficient storage.
203 pub fn to_binary(self) -> SerializationResult<Vec<u8>> {
204 crate::serialization::binary::to_binary_internal(self)
205 }
206
207 /// Saves the struct to a JSON file
208 ///
209 /// Serializes all registered fields to JSON format and writes the result
210 /// to the specified file path. The file is created if it doesn't exist,
211 /// or truncated if it already exists.
212 ///
213 /// This method consumes the serializer, preventing further field additions.
214 ///
215 /// # Arguments
216 ///
217 /// * `path` - File path where the JSON data should be written
218 ///
219 /// # Returns
220 ///
221 /// `Ok(())` on successful file write
222 /// `Err(SerializationError)` if serialization or file I/O fails
223 ///
224 /// # Examples
225 ///
226 /// Saves serialized data to a JSON file with proper file I/O handling.
227 pub fn save_json<P: AsRef<Path>>(self, path: P) -> SerializationResult<()> {
228 let json_string = self.to_json()?;
229
230 let file = OpenOptions::new()
231 .write(true)
232 .create(true)
233 .truncate(true)
234 .open(path)?;
235
236 let mut writer = BufWriter::new(file);
237 writer.write_all(json_string.as_bytes())?;
238 writer.flush()?;
239
240 Ok(())
241 }
242
243 /// Saves the struct to a binary file
244 ///
245 /// Serializes all registered fields to binary format and writes the result
246 /// to the specified file path. The file is created if it doesn't exist,
247 /// or truncated if it already exists.
248 ///
249 /// This method consumes the serializer, preventing further field additions.
250 ///
251 /// # Arguments
252 ///
253 /// * `path` - File path where the binary data should be written
254 ///
255 /// # Returns
256 ///
257 /// `Ok(())` on successful file write
258 /// `Err(SerializationError)` if serialization or file I/O fails
259 ///
260 /// # Examples
261 ///
262 /// Saves serialized data to a binary file with proper file I/O handling.
263 pub fn save_binary<P: AsRef<Path>>(self, path: P) -> SerializationResult<()> {
264 let binary_data = self.to_binary()?;
265
266 let file = OpenOptions::new()
267 .write(true)
268 .create(true)
269 .truncate(true)
270 .open(path)?;
271
272 let mut writer = BufWriter::new(file);
273 writer.write_all(&binary_data)?;
274 writer.flush()?;
275
276 Ok(())
277 }
278}
279
280impl Default for StructSerializer {
281 /// Creates a default struct serializer
282 ///
283 /// Returns a new `StructSerializer` with default settings, equivalent to
284 /// calling `StructSerializer::new()`.
285 ///
286 /// # Returns
287 ///
288 /// A new `StructSerializer` instance with empty field collection
289 ///
290 /// # Examples
291 ///
292 /// Creates a default serializer with empty field collection.
293 fn default() -> Self {
294 Self::new()
295 }
296}