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}