csv_legacy2/csv_legacy2.rs
1#![cfg_attr(not(feature = "std"), no_std)]
2//! A fast, low-allocation CSV parser with optional serde support.
3//!
4//! # Quick start
5//!
6//! ```rust
7//! let data = b"name,age,city\nAlice,30,NYC\nBob,25,LA\n";
8//! let mut reader = csv::Reader::from_bytes(data);
9//!
10//! for row in reader.rows() {
11//! for field in row.fields().unwrap() {
12//! // field: &str — already unescaped, no surrounding quotes, `""` resolved
13//! }
14//! let fields: Vec<String> = row.all().unwrap();
15//! }
16//! ```
17//!
18//! # Features
19//!
20//! | Flag | Default | Description |
21//! |------|---------|-------------|
22//! | `std` | on | Enables `std::io::Read`, `Writer`, and `std::error::Error` impls. |
23//! | `serde` | off | Enables `Row::deserialize()` for `#[derive(Deserialize)]`. |
24//!
25//! # Streaming from `std::io::Read`
26//!
27//! ```no_run
28//! use std::fs::File;
29//! use csv::Reader;
30//!
31//! let file = File::open("data.csv")?;
32//! let mut reader = Reader::from_reader(file);
33//!
34//! for row in reader.rows() {
35//! let name = row.fields()?.next().unwrap();
36//! println!("{name}");
37//! }
38//! # Ok::<_, csv::ReadError>(())
39//! ```
40//!
41//! # Headers
42//!
43//! ```no_run
44//! use csv::Reader;
45//! let data = b"name,age\nAlice,30\n";
46//! let mut reader = Reader::from_reader(std::io::Cursor::new(data));
47//! let headers = reader.parse_headers()?;
48//! for row in reader.rows() {
49//! }
50//! # Ok::<_, csv::ReadError>(())
51//! ```
52//!
53//! # Serde (requires `serde` feature)
54//!
55//! ```no_run
56//! # #[cfg(feature = "serde")] {
57//! use csv::Reader;
58//! use serde::Deserialize;
59//!
60//! #[derive(Deserialize)]
61//! struct Record { name: String, age: u32 }
62//!
63//! let mut reader = Reader::from_reader(std::io::Cursor::new(b"name,age\nAlice,30\n"));
64//! reader.parse_headers()?;
65//!
66//! for row in reader.rows() {
67//! let rec: Record = row.deserialize()?;
68//! println!("{} is {}", rec.name, rec.age);
69//! }
70//! # }
71//! # Ok::<_, csv::ReadError>(())
72//! ```
73//!
74//! When [`parse_headers`] is called before iterating, struct fields are
75//! matched to CSV columns by name. Without it, fields are mapped positionally.
76//!
77//! # Writer
78//!
79//! ```no_run
80//! use csv::Writer;
81//!
82//! let mut w = Writer::new(Vec::new());
83//! w.write_row(["name", "age"])?;
84//! w.write_row(["Alice", "30"])?;
85//! let bytes = w.into_inner()?;
86//! # Ok::<_, csv::WriteError>(())
87//! ```
88//!
89//! # Design
90//!
91//! * **Zero per-row allocations**: `rows()` reuses internal buffers.
92//! * **Eager unescaping**: quotes are stripped and `""` resolved during parsing.
93//! * **SIMD scanning**: uses `memchr3` to bulk-scan for delimiters, quotes, and newlines.
94//! * **Borrowed rows**: `Row<'_>` borrows from the `Reader` and cannot outlive it.
95//! * **Streaming**: rows are parsed on-demand from `std::io::Read`.
96
97extern crate alloc;
98
99#[cfg(feature = "std")]
100extern crate std;
101
102mod error;
103mod reader;
104
105#[cfg(feature = "std")]
106mod writer;
107
108#[cfg(feature = "serde")]
109mod serde;
110
111pub use error::{ReadError, ReadErrorKind, WriteError};
112pub use reader::{Fields, Reader, Row, Rows};
113#[cfg(feature = "std")]
114pub use writer::Writer;