csv/csv.rs
1#![cfg_attr(not(feature = "std"), no_std)]
2
3//! A fast, low-allocation CSV parser with `no_std` and serde support.
4//!
5//! # Quick start
6//!
7//! ```rust
8//! let data: &[u8] = b"name,age,city\nAlice,30,NYC\nBob,25,LA\n";
9//! let mut reader = csv::Reader::new(data);
10//!
11//! for row in reader.rows() {
12//! for field in row.iter() {
13//! let field: &str = field.unwrap();
14//! }
15//! let fields: Vec<&str> = row.to_vec().unwrap();
16//! }
17//! ```
18//!
19//! # Features
20//!
21//! | Flag | Default | Description |
22//! |------|---------|-------------|
23//! | `std` | on | Enables `std::io::Read` support for `Reader`, `Writer`, and `std::error::Error` impls. |
24//! | `serde` | off | Enables `Row::deserialize()` + `Writer::serialize()` for serde support. |
25//!
26//! # Streaming from any [`Read`] source
27//!
28//! ```no_run
29//! use std::fs::File;
30//! use csv::Reader;
31//!
32//! let file = File::open("data.csv")?;
33//! let mut reader = Reader::new(file);
34//!
35//! for row in reader.rows() {
36//! let name = row.get(0).unwrap().unwrap();
37//! println!("{name}");
38//! }
39//! # Ok::<_, csv::ReadError>(())
40//! ```
41//!
42//! # Headers
43//!
44//! ```no_run
45//! use csv::Reader;
46//! let data = b"name,age\nAlice,30\n";
47//! let mut reader = Reader::new(std::io::Cursor::new(data));
48//! let headers = reader.parse_headers()?;
49//! for row in reader.rows() {
50//! }
51//! # Ok::<_, csv::ReadError>(())
52//! ```
53//!
54//! # Serde (requires `serde` feature)
55//!
56//! ```no_run
57//! # #[cfg(feature = "serde")] {
58//! use csv::Reader;
59//! use serde::Deserialize;
60//!
61//! #[derive(Deserialize)]
62//! struct Record {
63//! name: String,
64//! age: u32,
65//! }
66//!
67//! let mut reader = Reader::new(std::io::Cursor::new(b"name,age\nAlice,30\n"));
68//! reader.parse_headers()?;
69//!
70//! for row in reader.rows() {
71//! let rec: Record = row.deserialize()?;
72//! println!("{} is {}", rec.name, rec.age);
73//! }
74//! # }
75//! # Ok::<_, csv::ReadError>(())
76//! ```
77//!
78//! # Writer
79//!
80//! ```no_run
81//! use csv::Writer;
82//!
83//! let mut w = Writer::new(Vec::new());
84//! w.write_headers(["name", "age"])?;
85//! w.write_row(["Alice", "30"])?;
86//! let bytes = w.into_inner()?;
87//! # Ok::<_, csv::WriteError>(())
88//! ```
89//!
90//! With serde:
91//!
92//! ```no_run
93//! # #[cfg(feature = "serde")] {
94//! use csv::Writer;
95//! use serde::Serialize;
96//!
97//! #[derive(Serialize)]
98//! struct Person { name: String, age: u32 }
99//!
100//! let mut w = Writer::new(Vec::new())
101//! .set_headers(vec!["name".into(), "age".into()]);
102//! let p = Person { name: "Alice".into(), age: 30 };
103//! w.serialize(&p)?;
104//! # }
105//! # Ok::<_, csv::WriteError>(())
106//! ```
107//!
108//! # Design
109//!
110//! * **Owned rows**: `Row` and `BytesRow` own their data. Rows can outlive the `Reader`.
111//! * **Single buffer**: Each row stores all fields contiguously in one `Vec<u8>`.
112//! * **SIMD scanning**: uses `memchr3` to bulk-scan for delimiters, quotes, and newlines.
113//! * **Deferred errors**: Row parsing errors are stored in the row and surfaced on access.
114//! * **BytesRow / Row split**: `BytesRow` works with raw bytes; `Row` adds UTF-8 validation.
115//! * **Streaming**: rows are parsed on-demand from any [`Read`] source.
116
117extern crate alloc;
118
119#[cfg(feature = "std")]
120extern crate std;
121
122mod error;
123mod reader;
124
125mod writer;
126
127#[cfg(feature = "serde")]
128mod serde;
129
130pub use error::{ReadError, ReadErrorKind, WriteError};
131pub use reader::{BytesFields, BytesRow, BytesRows, FieldRange, Fields, Read, Reader, Row, Rows};
132pub use writer::{Write, Writer};