1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! CSV processing library inspired by [csvsc](https://crates.io/crates/csvsc)
//!
//! ## Get started
//!
//! The first thing you need is to create a [`Pipeline`]. This can be done by calling [`Pipeline::from_reader`] with a [`csv::Reader`], or [`Pipeline::from_path`] with a path.
//!
//! Once you have a pipeline, there are various methods available which let you add your desired processing steps. Check the [`Pipeline`] for more details and examples.
//!
//! In the end, you may want to write the result somewhere. To do that, you can [flush](Pipeline::flush) into a [`Target`].
//!
//! Finally, you probably want to run the pipeline. There are a few options:
//! - [`Pipeline::build`] gives you a [`PipelineIter`] which you can iterate through
//! - [`Pipeline::run`] runs through the pipeline until it finds an error, or the end
//! - [`Pipeline::collect_into_string`] runs the pipeline and returns the csv as a `Result<String, Error>`. Can be a convenient alternative to flushing to a [`StringTarget`](target::StringTarget).
//!
//! ## Basic Example
//!
//! ```
//! use csv_pipeline::{Pipeline, Transformer};
//!
//! // First create a pipeline from a CSV file path
//! let csv = Pipeline::from_path("test/Countries.csv")
//! .unwrap()
//! // Add a column with values computed from a closure
//! .add_col("Language", |headers, row| {
//! match headers.get_field(row, "Country") {
//! Some("Norway") => Ok("Norwegian".into()),
//! _ => Ok("Unknown".into()),
//! }
//! })
//! // Make the "Country" column uppercase
//! .rename_col("Country", "COUNTRY")
//! .map_col("COUNTRY", |id_str| Ok(id_str.to_uppercase()))
//! // Collect the csv into a string
//! .collect_into_string()
//! .unwrap();
//!
//! assert_eq!(
//! csv,
//! "ID,COUNTRY,Language\n\
//! 1,NORWAY,Norwegian\n\
//! 2,TUVALU,Unknown\n"
//! );
//! ```
//!
//! ## Transform Example
//! ```
//! use csv_pipeline::{Pipeline, Transformer};
//!
//! let source = "\
//! Person,Score\n\
//! A,1\n\
//! A,8\n\
//! B,3\n\
//! B,4\n";
//! let reader = csv::Reader::from_reader(source.as_bytes());
//! let csv = Pipeline::from_reader(reader)
//! .unwrap()
//! .map(|_headers, row| Ok(row))
//! // Transform into a new csv
//! .transform_into(|| {
//! vec![
//! // Keep every Person
//! Transformer::new("Person").keep_unique(),
//! // Sum the scores into a "Total score" column
//! Transformer::new("Total score").from_col("Score").sum(0),
//! ]
//! })
//! .collect_into_string()
//! .unwrap();
//!
//! assert_eq!(
//! csv,
//! "Person,Total score\n\
//! A,9\n\
//! B,7\n"
//! );
//! ```
//!
use PathBuf;
pub use Headers;
pub use ;
pub use ;
/// Helper for building a target to flush data into
/// Alias of [`csv::StringRecord`]
pub type Row = StringRecord;
/// Alias of `Result<Row, Error>`
pub type RowResult = ;
/// Error originating from the specified pipeline source index