Skip to main content

spring_batch_rs/item/csv/
mod.rs

1/// CSV support for reading and writing tabular data.
2///
3/// This module provides components for reading from and writing to CSV files with configurable
4/// options for delimiters, headers, and other formatting preferences.
5///
6/// # Module Architecture
7///
8/// The CSV module consists of two main components:
9///
10/// 1. **CsvItemReader**: A reader that deserializes CSV data into Rust structs
11///    using serde's deserialization capabilities. It supports reading CSV data
12///    from files, strings, or any source implementing the `Read` trait.
13///
14/// 2. **CsvItemWriter**: A writer that serializes Rust structs into CSV format
15///    with configurable options like custom delimiters and header handling.
16///
17/// Both components follow the builder pattern for easy configuration.
18///
19/// # Integration with Spring Batch
20///
21/// These components implement the core `ItemReader` and `ItemWriter` traits from the Spring Batch framework,
22/// allowing them to be used in batch processing steps and pipelines. The design follows the Spring Batch
23/// philosophy of modular, configurable components that can be combined in various ways.
24///
25/// # Ownership and Borrowing Considerations
26///
27/// When using the CSV writers, be aware of Rust's ownership rules:
28/// - Writers borrow their destination (file, buffer, etc.) and hold that borrow until dropped
29/// - To read from a buffer after writing to it, either:
30///   1. Create a separate scope for the writer so it's dropped before reading the buffer
31///   2. Clone the buffer before reading from it (less efficient)
32///
33/// # Features
34///
35/// - Read CSV data with or without headers
36/// - Write data to CSV files with custom formatting
37/// - Support for custom delimiters and terminators
38/// - Flexible trimming options
39/// - Integration with Serde for serialization/deserialization
40///
41/// # Examples
42///
43/// ## Reading from CSV
44///
45/// ```
46/// use spring_batch_rs::item::csv::csv_reader::CsvItemReaderBuilder;
47/// use spring_batch_rs::core::item::ItemReader;
48/// use serde::Deserialize;
49///
50/// // Define a data structure matching our CSV format
51/// #[derive(Debug, Deserialize, PartialEq)]
52/// struct City {
53///     city: String,
54///     country: String,
55///     pop: u32,
56/// }
57///
58/// // Sample CSV data
59/// let csv_data = "\
60/// city,country,pop
61/// Boston,United States,4628910
62/// Concord,United States,42695
63/// ";
64///
65/// // Create a reader from our CSV
66/// let reader = CsvItemReaderBuilder::<City>::new()
67///     .has_headers(true)
68///     .delimiter(b',')
69///     .from_reader(csv_data.as_bytes());
70///
71/// // Read and process the cities
72/// let mut cities: Vec<City> = Vec::new();
73/// while let Some(city) = reader.read().unwrap() {
74///     cities.push(city);
75/// }
76///
77/// // Verify results
78/// assert_eq!(cities.len(), 2);
79/// assert_eq!(cities[0].city, "Boston");
80/// assert_eq!(cities[0].country, "United States");
81/// assert_eq!(cities[0].pop, 4628910);
82///
83/// assert_eq!(cities[1].city, "Concord");
84/// assert_eq!(cities[1].country, "United States");
85/// assert_eq!(cities[1].pop, 42695);
86/// ```
87///
88/// ## Writing to CSV
89///
90/// ```
91/// use spring_batch_rs::item::csv::csv_writer::CsvItemWriterBuilder;
92/// use spring_batch_rs::core::item::ItemWriter;
93/// use serde::Serialize;
94///
95/// // Define a data structure for serialization
96/// #[derive(Serialize)]
97/// struct Person {
98///     name: String,
99///     age: u8,
100///     occupation: String,
101/// }
102///
103/// // Create some people
104/// let people = vec![
105///     Person {
106///         name: "Alice".to_string(),
107///         age: 28,
108///         occupation: "Engineer".to_string(),
109///     },
110///     Person {
111///         name: "Bob".to_string(),
112///         age: 35,
113///         occupation: "Designer".to_string(),
114///     },
115/// ];
116///
117/// // Create a writer with a vector buffer (could also use a file)
118/// let mut buffer = Vec::new();
119/// {
120///     let writer = CsvItemWriterBuilder::<Person>::new()
121///         .has_headers(true)
122///         .delimiter(b',')
123///         .from_writer(&mut buffer);
124///
125///     // Write the people to CSV
126///     writer.write(&people).unwrap();
127///     // Use explicit type parameter with flush to help type inference
128///     ItemWriter::<Person>::flush(&writer).unwrap();
129/// } // writer is dropped here, releasing the borrow
130///
131/// // Convert buffer to string to see the output
132/// let csv_output = String::from_utf8(buffer).unwrap();
133///
134/// // Output will be:
135/// // name,age,occupation
136/// // Alice,28,Engineer
137/// // Bob,35,Designer
138/// ```
139///
140/// ## Converting data between CSV and other formats
141///
142/// The CSV module can be used in combination with other modules to build
143/// data processing pipelines:
144///
145/// ```
146/// use spring_batch_rs::item::csv::csv_reader::CsvItemReaderBuilder;
147/// use spring_batch_rs::item::csv::csv_writer::CsvItemWriterBuilder;
148/// use spring_batch_rs::core::item::{ItemReader, ItemWriter};
149/// use spring_batch_rs::core::step::StepBuilder;
150/// use spring_batch_rs::core::job::{JobBuilder, Job};
151/// use serde::{Deserialize, Serialize};
152/// use std::fs::File;
153///
154/// // This example shows how to use CSV reader and writer in a batch job
155/// // that reads data, transforms it, and writes it back
156///
157/// #[derive(Debug, Deserialize, Serialize)]
158/// struct Record {
159///     id: u32,
160///     value: String,
161/// }
162///
163/// // In a real application, you would:
164/// // 1. Set up input and output files
165/// // 2. Configure readers and writers
166/// // 3. Build and run the job
167///
168/// // Example (not actually executed in doctest):
169/// // let reader = CsvItemReaderBuilder::<Record>::new()
170/// //     .has_headers(true)
171/// //     .from_path("input.csv");
172/// //
173/// // let writer = CsvItemWriterBuilder::<Record>::new()
174/// //     .has_headers(true)
175/// //     .from_path("output.csv");
176/// //
177/// // let step = StepBuilder::new("step")
178/// //     .chunk(10)
179/// //     .reader(&reader)
180/// //     .processor(&processor)
181/// //     .writer(&writer)
182/// //     .build();
183/// //
184/// // let job = JobBuilder::new().start(&step).build();
185/// // job.run().unwrap();
186/// ```
187///
188/// A module providing facilities for reading CSV data records.
189pub mod csv_reader;
190
191/// A module providing facilities for writing CSV data records.
192pub mod csv_writer;