aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 05:05:04 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 05:05:04 +0000
commit56cf3fc90364ce0b30a1c219d8d90c63da5ffc25 (patch)
tree54a419676109a710f3f0e89202a8dbacf17ddd18
parent36cb314b006d36d6bd7762bbe56361ae6f80e554 (diff)
parent3e92abfbfe16baad364fafce8b86d28481b2a50a (diff)
downloadcsv-android14-mainline-os-statsd-release.tar.gz
Change-Id: If5b84136edb6cec4cf5481329ca5477a4dc3807e
-rw-r--r--.cargo_vcs_info.json7
-rw-r--r--Android.bp11
-rw-r--r--Cargo.toml58
-rw-r--r--Cargo.toml.orig20
-rw-r--r--METADATA14
-rw-r--r--README.md19
-rw-r--r--examples/cookbook-read-basic.rs4
-rw-r--r--examples/cookbook-read-colon.rs4
-rw-r--r--examples/cookbook-read-no-headers.rs4
-rw-r--r--examples/cookbook-read-serde.rs5
-rw-r--r--examples/cookbook-write-basic.rs4
-rw-r--r--examples/cookbook-write-serde.rs4
-rw-r--r--examples/tutorial-error-02.rs3
-rw-r--r--examples/tutorial-error-03.rs4
-rw-r--r--examples/tutorial-error-04.rs4
-rw-r--r--examples/tutorial-perf-alloc-01.rs4
-rw-r--r--examples/tutorial-perf-alloc-02.rs4
-rw-r--r--examples/tutorial-perf-alloc-03.rs4
-rw-r--r--examples/tutorial-perf-serde-01.rs5
-rw-r--r--examples/tutorial-perf-serde-02.rs6
-rw-r--r--examples/tutorial-perf-serde-03.rs5
-rw-r--r--examples/tutorial-pipeline-pop-01.rs5
-rw-r--r--examples/tutorial-pipeline-search-01.rs5
-rw-r--r--examples/tutorial-pipeline-search-02.rs5
-rw-r--r--examples/tutorial-read-01.rs6
-rw-r--r--examples/tutorial-read-delimiter-01.rs4
-rw-r--r--examples/tutorial-read-headers-01.rs4
-rw-r--r--examples/tutorial-read-headers-02.rs4
-rw-r--r--examples/tutorial-read-serde-01.rs4
-rw-r--r--examples/tutorial-read-serde-02.rs4
-rw-r--r--examples/tutorial-read-serde-03.rs4
-rw-r--r--examples/tutorial-read-serde-04.rs5
-rw-r--r--examples/tutorial-read-serde-invalid-01.rs5
-rw-r--r--examples/tutorial-read-serde-invalid-02.rs5
-rw-r--r--examples/tutorial-write-01.rs4
-rw-r--r--examples/tutorial-write-02.rs5
-rw-r--r--examples/tutorial-write-delimiter-01.rs4
-rw-r--r--examples/tutorial-write-serde-01.rs4
-rw-r--r--examples/tutorial-write-serde-02.rs4
-rw-r--r--src/byte_record.rs65
-rw-r--r--src/cookbook.rs25
-rw-r--r--src/debug.rs80
-rw-r--r--src/deserializer.rs59
-rw-r--r--src/error.rs39
-rw-r--r--src/lib.rs44
-rw-r--r--src/reader.rs95
-rw-r--r--src/serializer.rs47
-rw-r--r--src/string_record.rs30
-rw-r--r--src/tutorial.rs131
-rw-r--r--src/writer.rs57
50 files changed, 461 insertions, 485 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 3af53d7..727eb00 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
{
"git": {
- "sha1": "d1fe79738d4948d3167f8f3331d4eed4b67c4a10"
- }
-}
+ "sha1": "fa01b78533a58d6c1087990a79a42c97c6edd069"
+ },
+ "path_in_vcs": ""
+} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index bc895d5..5409e26 100644
--- a/Android.bp
+++ b/Android.bp
@@ -42,14 +42,19 @@ rust_library {
host_supported: true,
crate_name: "csv",
cargo_env_compat: true,
- cargo_pkg_version: "1.1.6",
+ cargo_pkg_version: "1.2.0",
srcs: ["src/lib.rs"],
- edition: "2018",
+ edition: "2021",
rustlibs: [
- "libbstr",
"libcsv_core",
"libitoa",
"libryu",
"libserde",
],
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
+ product_available: true,
+ vendor_available: true,
}
diff --git a/Cargo.toml b/Cargo.toml
index 707e4e2..56e3597 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,27 +3,42 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
-edition = "2018"
+edition = "2021"
+rust-version = "1.60"
name = "csv"
-version = "1.1.6"
+version = "1.2.0"
authors = ["Andrew Gallant <jamslam@gmail.com>"]
-exclude = ["/.travis.yml", "/appveyor.yml", "/ci/*", "/scripts/*"]
+exclude = [
+ "/.github",
+ "/ci/*",
+ "/scripts/*",
+]
description = "Fast CSV parsing with support for serde."
homepage = "https://github.com/BurntSushi/rust-csv"
-documentation = "http://burntsushi.net/rustdoc/csv/"
+documentation = "https://docs.rs/csv"
readme = "README.md"
-keywords = ["csv", "comma", "parser", "delimited", "serde"]
-categories = ["encoding", "parser-implementations"]
+keywords = [
+ "csv",
+ "comma",
+ "parser",
+ "delimited",
+ "serde",
+]
+categories = [
+ "encoding",
+ "parser-implementations",
+]
license = "Unlicense/MIT"
repository = "https://github.com/BurntSushi/rust-csv"
+resolver = "2"
+
[profile.bench]
debug = true
@@ -32,26 +47,27 @@ debug = true
[lib]
bench = false
-[dependencies.bstr]
-version = "0.2.1"
-features = ["serde1"]
[dependencies.csv-core]
-version = "0.1.6"
+version = "0.1.10"
[dependencies.itoa]
-version = "0.4.3"
+version = "1"
[dependencies.ryu]
version = "1"
[dependencies.serde]
version = "1.0.55"
+
+[dev-dependencies.bstr]
+version = "1.2.0"
+features = [
+ "alloc",
+ "serde",
+]
+default-features = false
+
[dev-dependencies.serde]
version = "1.0.55"
features = ["derive"]
-[badges.appveyor]
-repository = "BurntSushi/rust-csv"
-
-[badges.travis-ci]
-repository = "BurntSushi/rust-csv"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 628e8cd..0f60210 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,21 +1,19 @@
[package]
name = "csv"
-version = "1.1.6" #:version
+version = "1.2.0" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = "Fast CSV parsing with support for serde."
-documentation = "http://burntsushi.net/rustdoc/csv/"
+documentation = "https://docs.rs/csv"
homepage = "https://github.com/BurntSushi/rust-csv"
repository = "https://github.com/BurntSushi/rust-csv"
readme = "README.md"
keywords = ["csv", "comma", "parser", "delimited", "serde"]
license = "Unlicense/MIT"
categories = ["encoding", "parser-implementations"]
-exclude = ["/.travis.yml", "/appveyor.yml", "/ci/*", "/scripts/*"]
-edition = "2018"
-
-[badges]
-travis-ci = { repository = "BurntSushi/rust-csv" }
-appveyor = { repository = "BurntSushi/rust-csv" }
+exclude = ["/.github", "/ci/*", "/scripts/*"]
+edition = "2021"
+resolver = "2"
+rust-version = "1.60"
[workspace]
members = ["csv-core", "csv-index"]
@@ -24,13 +22,13 @@ members = ["csv-core", "csv-index"]
bench = false
[dependencies]
-bstr = { version = "0.2.1", features = ["serde1"] }
-csv-core = { path = "csv-core", version = "0.1.6" }
-itoa = "0.4.3"
+csv-core = { path = "csv-core", version = "0.1.10" }
+itoa = "1"
ryu = "1"
serde = "1.0.55"
[dev-dependencies]
+bstr = { version = "1.2.0", default-features = false, features = ["alloc", "serde"] }
serde = { version = "1.0.55", features = ["derive"] }
[profile.release]
diff --git a/METADATA b/METADATA
index 472afd9..9bef55d 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/csv
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
name: "csv"
description: "Fast CSV parsing with support for serde."
third_party {
@@ -7,13 +11,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/csv/csv-1.1.6.crate"
+ value: "https://static.crates.io/crates/csv/csv-1.2.0.crate"
}
- version: "1.1.6"
+ version: "1.2.0"
license_type: NOTICE
last_upgrade_date {
- year: 2021
- month: 4
- day: 1
+ year: 2023
+ month: 2
+ day: 15
}
}
diff --git a/README.md b/README.md
index b1c5727..83f3ea0 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,8 @@ csv
===
A fast and flexible CSV reader and writer for Rust, with support for Serde.
-[![Linux build status](https://api.travis-ci.org/BurntSushi/rust-csv.svg)](https://travis-ci.org/BurntSushi/rust-csv)
-[![Windows build status](https://ci.appveyor.com/api/projects/status/github/BurntSushi/rust-csv?svg=true)](https://ci.appveyor.com/project/BurntSushi/rust-csv)
-[![](http://meritbadge.herokuapp.com/csv)](https://crates.io/crates/csv)
+[![Build status](https://github.com/BurntSushi/csv/workflows/ci/badge.svg)](https://github.com/BurntSushi/csv/actions)
+[![crates.io](https://img.shields.io/crates/v/csv.svg)](https://crates.io/crates/csv)
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
@@ -24,7 +23,7 @@ Add this to your `Cargo.toml`:
```toml
[dependencies]
-csv = "1.1"
+csv = "1.2"
```
### Example
@@ -36,9 +35,7 @@ There are more examples in the
[cookbook](https://docs.rs/csv/1.0.0/csv/cookbook/index.html).
```rust
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn example() -> Result<(), Box<dyn Error>> {
// Build the CSV reader and iterate over each record.
@@ -75,13 +72,9 @@ By default, the member names of the struct are matched with the values in the
header record of your CSV data.
```rust
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
-use serde::Deserialize;
-
-#[derive(Debug, Deserialize)]
+#[derive(Debug, serde::Deserialize)]
struct Record {
city: String,
region: String,
diff --git a/examples/cookbook-read-basic.rs b/examples/cookbook-read-basic.rs
index a69b0e2..c7d4c4a 100644
--- a/examples/cookbook-read-basic.rs
+++ b/examples/cookbook-read-basic.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn example() -> Result<(), Box<dyn Error>> {
// Build the CSV reader and iterate over each record.
diff --git a/examples/cookbook-read-colon.rs b/examples/cookbook-read-colon.rs
index 457cff3..ce57095 100644
--- a/examples/cookbook-read-colon.rs
+++ b/examples/cookbook-read-colon.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn example() -> Result<(), Box<dyn Error>> {
let mut rdr =
diff --git a/examples/cookbook-read-no-headers.rs b/examples/cookbook-read-no-headers.rs
index 29812cb..2c558fc 100644
--- a/examples/cookbook-read-no-headers.rs
+++ b/examples/cookbook-read-no-headers.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn example() -> Result<(), Box<dyn Error>> {
let mut rdr =
diff --git a/examples/cookbook-read-serde.rs b/examples/cookbook-read-serde.rs
index 420e0f7..20a8399 100644
--- a/examples/cookbook-read-serde.rs
+++ b/examples/cookbook-read-serde.rs
@@ -1,6 +1,5 @@
-use std::error::Error;
-use std::io;
-use std::process;
+#![allow(dead_code)]
+use std::{error::Error, io, process};
use serde::Deserialize;
diff --git a/examples/cookbook-write-basic.rs b/examples/cookbook-write-basic.rs
index 199d94b..2c78d17 100644
--- a/examples/cookbook-write-basic.rs
+++ b/examples/cookbook-write-basic.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn example() -> Result<(), Box<dyn Error>> {
let mut wtr = csv::Writer::from_writer(io::stdout());
diff --git a/examples/cookbook-write-serde.rs b/examples/cookbook-write-serde.rs
index 54e85a5..b6c3cbb 100644
--- a/examples/cookbook-write-serde.rs
+++ b/examples/cookbook-write-serde.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
use serde::Serialize;
diff --git a/examples/tutorial-error-02.rs b/examples/tutorial-error-02.rs
index e2b5dfe..c3fc191 100644
--- a/examples/tutorial-error-02.rs
+++ b/examples/tutorial-error-02.rs
@@ -1,5 +1,4 @@
-use std::io;
-use std::process;
+use std::{io, process};
fn main() {
let mut rdr = csv::Reader::from_reader(io::stdin());
diff --git a/examples/tutorial-error-03.rs b/examples/tutorial-error-03.rs
index 6bfcc7a..f2db45d 100644
--- a/examples/tutorial-error-03.rs
+++ b/examples/tutorial-error-03.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn main() {
if let Err(err) = run() {
diff --git a/examples/tutorial-error-04.rs b/examples/tutorial-error-04.rs
index 67eb4f2..272e134 100644
--- a/examples/tutorial-error-04.rs
+++ b/examples/tutorial-error-04.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn main() {
if let Err(err) = run() {
diff --git a/examples/tutorial-perf-alloc-01.rs b/examples/tutorial-perf-alloc-01.rs
index d3020cc..4099534 100644
--- a/examples/tutorial-perf-alloc-01.rs
+++ b/examples/tutorial-perf-alloc-01.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn run() -> Result<u64, Box<dyn Error>> {
let mut rdr = csv::Reader::from_reader(io::stdin());
diff --git a/examples/tutorial-perf-alloc-02.rs b/examples/tutorial-perf-alloc-02.rs
index a3099a1..fc7a8e5 100644
--- a/examples/tutorial-perf-alloc-02.rs
+++ b/examples/tutorial-perf-alloc-02.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn run() -> Result<u64, Box<dyn Error>> {
let mut rdr = csv::Reader::from_reader(io::stdin());
diff --git a/examples/tutorial-perf-alloc-03.rs b/examples/tutorial-perf-alloc-03.rs
index 08edf5a..4bbf167 100644
--- a/examples/tutorial-perf-alloc-03.rs
+++ b/examples/tutorial-perf-alloc-03.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn run() -> Result<u64, Box<dyn Error>> {
let mut rdr = csv::Reader::from_reader(io::stdin());
diff --git a/examples/tutorial-perf-serde-01.rs b/examples/tutorial-perf-serde-01.rs
index c64538b..6578152 100644
--- a/examples/tutorial-perf-serde-01.rs
+++ b/examples/tutorial-perf-serde-01.rs
@@ -1,6 +1,5 @@
-use std::error::Error;
-use std::io;
-use std::process;
+#![allow(dead_code)]
+use std::{error::Error, io, process};
use serde::Deserialize;
diff --git a/examples/tutorial-perf-serde-02.rs b/examples/tutorial-perf-serde-02.rs
index 44202f8..b510ee9 100644
--- a/examples/tutorial-perf-serde-02.rs
+++ b/examples/tutorial-perf-serde-02.rs
@@ -1,8 +1,6 @@
-use std::error::Error;
-use std::io;
-use std::process;
-
+#![allow(dead_code)]
use serde::Deserialize;
+use std::{error::Error, io, process};
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
diff --git a/examples/tutorial-perf-serde-03.rs b/examples/tutorial-perf-serde-03.rs
index 8c8b5f2..1b9b5fa 100644
--- a/examples/tutorial-perf-serde-03.rs
+++ b/examples/tutorial-perf-serde-03.rs
@@ -1,6 +1,5 @@
-use std::error::Error;
-use std::io;
-use std::process;
+#![allow(dead_code)]
+use std::{error::Error, io, process};
use serde::Deserialize;
diff --git a/examples/tutorial-pipeline-pop-01.rs b/examples/tutorial-pipeline-pop-01.rs
index f10cd43..19ad986 100644
--- a/examples/tutorial-pipeline-pop-01.rs
+++ b/examples/tutorial-pipeline-pop-01.rs
@@ -1,7 +1,4 @@
-use std::env;
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{env, error::Error, io, process};
use serde::{Deserialize, Serialize};
diff --git a/examples/tutorial-pipeline-search-01.rs b/examples/tutorial-pipeline-search-01.rs
index 3bfb8ea..d2cf5c1 100644
--- a/examples/tutorial-pipeline-search-01.rs
+++ b/examples/tutorial-pipeline-search-01.rs
@@ -1,7 +1,4 @@
-use std::env;
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{env, error::Error, io, process};
fn run() -> Result<(), Box<dyn Error>> {
// Get the query from the positional arguments.
diff --git a/examples/tutorial-pipeline-search-02.rs b/examples/tutorial-pipeline-search-02.rs
index ab03385..76c1045 100644
--- a/examples/tutorial-pipeline-search-02.rs
+++ b/examples/tutorial-pipeline-search-02.rs
@@ -1,7 +1,4 @@
-use std::env;
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{env, error::Error, io, process};
fn run() -> Result<(), Box<dyn Error>> {
let query = match env::args().nth(1) {
diff --git a/examples/tutorial-read-01.rs b/examples/tutorial-read-01.rs
index 9fc9293..6d75f79 100644
--- a/examples/tutorial-read-01.rs
+++ b/examples/tutorial-read-01.rs
@@ -1,8 +1,4 @@
-use std::env;
-use std::error::Error;
-use std::ffi::OsString;
-use std::fs::File;
-use std::process;
+use std::{env, error::Error, ffi::OsString, fs::File, process};
fn run() -> Result<(), Box<dyn Error>> {
let file_path = get_first_arg()?;
diff --git a/examples/tutorial-read-delimiter-01.rs b/examples/tutorial-read-delimiter-01.rs
index 10a93e1..8a5536b 100644
--- a/examples/tutorial-read-delimiter-01.rs
+++ b/examples/tutorial-read-delimiter-01.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn run() -> Result<(), Box<dyn Error>> {
let mut rdr = csv::ReaderBuilder::new()
diff --git a/examples/tutorial-read-headers-01.rs b/examples/tutorial-read-headers-01.rs
index d5b1c7b..afd27da 100644
--- a/examples/tutorial-read-headers-01.rs
+++ b/examples/tutorial-read-headers-01.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn run() -> Result<(), Box<dyn Error>> {
let mut rdr =
diff --git a/examples/tutorial-read-headers-02.rs b/examples/tutorial-read-headers-02.rs
index ddaa756..951473a 100644
--- a/examples/tutorial-read-headers-02.rs
+++ b/examples/tutorial-read-headers-02.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn run() -> Result<(), Box<dyn Error>> {
let mut rdr = csv::Reader::from_reader(io::stdin());
diff --git a/examples/tutorial-read-serde-01.rs b/examples/tutorial-read-serde-01.rs
index a073157..afc23f1 100644
--- a/examples/tutorial-read-serde-01.rs
+++ b/examples/tutorial-read-serde-01.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn run() -> Result<(), Box<dyn Error>> {
let mut rdr = csv::Reader::from_reader(io::stdin());
diff --git a/examples/tutorial-read-serde-02.rs b/examples/tutorial-read-serde-02.rs
index d9114fb..2cdcd91 100644
--- a/examples/tutorial-read-serde-02.rs
+++ b/examples/tutorial-read-serde-02.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
// This introduces a type alias so that we can conveniently reference our
// record type.
diff --git a/examples/tutorial-read-serde-03.rs b/examples/tutorial-read-serde-03.rs
index a4c31f0..022e246 100644
--- a/examples/tutorial-read-serde-03.rs
+++ b/examples/tutorial-read-serde-03.rs
@@ -1,7 +1,5 @@
use std::collections::HashMap;
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
// This introduces a type alias so that we can conveniently reference our
// record type.
diff --git a/examples/tutorial-read-serde-04.rs b/examples/tutorial-read-serde-04.rs
index e01d355..796040c 100644
--- a/examples/tutorial-read-serde-04.rs
+++ b/examples/tutorial-read-serde-04.rs
@@ -1,6 +1,5 @@
-use std::error::Error;
-use std::io;
-use std::process;
+#![allow(dead_code)]
+use std::{error::Error, io, process};
// This lets us write `#[derive(Deserialize)]`.
use serde::Deserialize;
diff --git a/examples/tutorial-read-serde-invalid-01.rs b/examples/tutorial-read-serde-invalid-01.rs
index 604b384..3ea836d 100644
--- a/examples/tutorial-read-serde-invalid-01.rs
+++ b/examples/tutorial-read-serde-invalid-01.rs
@@ -1,6 +1,5 @@
-use std::error::Error;
-use std::io;
-use std::process;
+#![allow(dead_code)]
+use std::{error::Error, io, process};
use serde::Deserialize;
diff --git a/examples/tutorial-read-serde-invalid-02.rs b/examples/tutorial-read-serde-invalid-02.rs
index 3723496..b4426cf 100644
--- a/examples/tutorial-read-serde-invalid-02.rs
+++ b/examples/tutorial-read-serde-invalid-02.rs
@@ -1,6 +1,5 @@
-use std::error::Error;
-use std::io;
-use std::process;
+#![allow(dead_code)]
+use std::{error::Error, io, process};
use serde::Deserialize;
#[derive(Debug, Deserialize)]
diff --git a/examples/tutorial-write-01.rs b/examples/tutorial-write-01.rs
index 229470d..e72c826 100644
--- a/examples/tutorial-write-01.rs
+++ b/examples/tutorial-write-01.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn run() -> Result<(), Box<dyn Error>> {
let mut wtr = csv::Writer::from_writer(io::stdout());
diff --git a/examples/tutorial-write-02.rs b/examples/tutorial-write-02.rs
index 76b5755..692a123 100644
--- a/examples/tutorial-write-02.rs
+++ b/examples/tutorial-write-02.rs
@@ -1,7 +1,4 @@
-use std::env;
-use std::error::Error;
-use std::ffi::OsString;
-use std::process;
+use std::{env, error::Error, ffi::OsString, process};
fn run() -> Result<(), Box<dyn Error>> {
let file_path = get_first_arg()?;
diff --git a/examples/tutorial-write-delimiter-01.rs b/examples/tutorial-write-delimiter-01.rs
index 795fd0a..a8f3ceb 100644
--- a/examples/tutorial-write-delimiter-01.rs
+++ b/examples/tutorial-write-delimiter-01.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn run() -> Result<(), Box<dyn Error>> {
let mut wtr = csv::WriterBuilder::new()
diff --git a/examples/tutorial-write-serde-01.rs b/examples/tutorial-write-serde-01.rs
index 595b31f..c6c4a97 100644
--- a/examples/tutorial-write-serde-01.rs
+++ b/examples/tutorial-write-serde-01.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn run() -> Result<(), Box<dyn Error>> {
let mut wtr = csv::Writer::from_writer(io::stdout());
diff --git a/examples/tutorial-write-serde-02.rs b/examples/tutorial-write-serde-02.rs
index 455de3a..8d298fd 100644
--- a/examples/tutorial-write-serde-02.rs
+++ b/examples/tutorial-write-serde-02.rs
@@ -1,6 +1,4 @@
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
use serde::Serialize;
diff --git a/src/byte_record.rs b/src/byte_record.rs
index 4ccbb96..3a676d4 100644
--- a/src/byte_record.rs
+++ b/src/byte_record.rs
@@ -1,15 +1,17 @@
-use std::cmp;
-use std::fmt;
-use std::iter::FromIterator;
-use std::ops::{self, Range};
-use std::result;
+use std::{
+ cmp, fmt,
+ iter::FromIterator,
+ ops::{self, Range},
+ result,
+};
-use bstr::{BString, ByteSlice};
use serde::de::Deserialize;
-use crate::deserializer::deserialize_byte_record;
-use crate::error::{new_utf8_error, Result, Utf8Error};
-use crate::string_record::StringRecord;
+use crate::{
+ deserializer::deserialize_byte_record,
+ error::{new_utf8_error, Result, Utf8Error},
+ string_record::StringRecord,
+};
/// A single CSV record stored as raw bytes.
///
@@ -68,11 +70,12 @@ impl<'a, T: AsRef<[u8]>> PartialEq<[T]> for &'a ByteRecord {
impl fmt::Debug for ByteRecord {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let mut fields = vec![];
- for field in self {
- fields.push(BString::from(field.to_vec()));
- }
- write!(f, "ByteRecord({:?})", fields)
+ write!(f, "ByteRecord(")?;
+ f.debug_list()
+ .entries(self.iter().map(crate::debug::Bytes))
+ .finish()?;
+ write!(f, ")")?;
+ Ok(())
}
}
@@ -370,8 +373,8 @@ impl ByteRecord {
let mut trimmed =
ByteRecord::with_capacity(self.as_slice().len(), self.len());
trimmed.set_position(self.position().cloned());
- for field in &*self {
- trimmed.push_field(field.trim());
+ for field in self.iter() {
+ trimmed.push_field(trim_ascii(field));
}
*self = trimmed;
}
@@ -547,7 +550,7 @@ impl ByteRecord {
// Otherwise, we must check each field individually to ensure that
// it's valid UTF-8.
for (i, field) in self.iter().enumerate() {
- if let Err(err) = field.to_str() {
+ if let Err(err) = std::str::from_utf8(field) {
return Err(new_utf8_error(i, err.valid_up_to()));
}
}
@@ -681,7 +684,7 @@ impl Bounds {
None => 0,
Some(&start) => start,
};
- Some(ops::Range { start: start, end: end })
+ Some(ops::Range { start, end })
}
/// Returns a slice of ending positions of all fields.
@@ -852,6 +855,32 @@ impl<'r> DoubleEndedIterator for ByteRecordIter<'r> {
}
}
+fn trim_ascii(bytes: &[u8]) -> &[u8] {
+ trim_ascii_start(trim_ascii_end(bytes))
+}
+
+fn trim_ascii_start(mut bytes: &[u8]) -> &[u8] {
+ while let [first, rest @ ..] = bytes {
+ if first.is_ascii_whitespace() {
+ bytes = rest;
+ } else {
+ break;
+ }
+ }
+ bytes
+}
+
+fn trim_ascii_end(mut bytes: &[u8]) -> &[u8] {
+ while let [rest @ .., last] = bytes {
+ if last.is_ascii_whitespace() {
+ bytes = rest;
+ } else {
+ break;
+ }
+ }
+ bytes
+}
+
#[cfg(test)]
mod tests {
use crate::string_record::StringRecord;
diff --git a/src/cookbook.rs b/src/cookbook.rs
index a28dc72..1430375 100644
--- a/src/cookbook.rs
+++ b/src/cookbook.rs
@@ -31,9 +31,7 @@ stdout.
```no_run
# //cookbook-read-basic.rs
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn example() -> Result<(), Box<dyn Error>> {
// Build the CSV reader and iterate over each record.
@@ -74,9 +72,8 @@ method.
```no_run
# //cookbook-read-serde.rs
-use std::error::Error;
-use std::io;
-use std::process;
+# #![allow(dead_code)]
+use std::{error::Error, io, process};
use serde::Deserialize;
@@ -124,9 +121,7 @@ by `:` instead of `,`.
```no_run
# //cookbook-read-colon.rs
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn example() -> Result<(), Box<dyn Error>> {
let mut rdr = csv::ReaderBuilder::new()
@@ -164,9 +159,7 @@ first record is not skipped. This example shows how to disable that setting.
```no_run
# //cookbook-read-no-headers.rs
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn example() -> Result<(), Box<dyn Error>> {
let mut rdr = csv::ReaderBuilder::new()
@@ -201,9 +194,7 @@ This example shows how to write CSV data to stdout.
```no_run
# //cookbook-write-basic.rs
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn example() -> Result<(), Box<dyn Error>> {
let mut wtr = csv::Writer::from_writer(io::stdout());
@@ -241,9 +232,7 @@ headers are written automatically.
```no_run
# //cookbook-write-serde.rs
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
use serde::Serialize;
diff --git a/src/debug.rs b/src/debug.rs
new file mode 100644
index 0000000..9882ea2
--- /dev/null
+++ b/src/debug.rs
@@ -0,0 +1,80 @@
+/// A type that provides a human readable debug impl for arbitrary bytes.
+///
+/// This generally works best when the bytes are presumed to be mostly UTF-8,
+/// but will work for anything.
+///
+/// N.B. This is copied nearly verbatim from regex-automata. Sigh.
+pub(crate) struct Bytes<'a>(pub(crate) &'a [u8]);
+
+impl<'a> core::fmt::Debug for Bytes<'a> {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ write!(f, "\"")?;
+ // This is a sad re-implementation of a similar impl found in bstr.
+ let mut bytes = self.0;
+ while let Some(result) = utf8_decode(bytes) {
+ let ch = match result {
+ Ok(ch) => ch,
+ Err(byte) => {
+ write!(f, r"\x{:02x}", byte)?;
+ bytes = &bytes[1..];
+ continue;
+ }
+ };
+ bytes = &bytes[ch.len_utf8()..];
+ match ch {
+ '\0' => write!(f, "\\0")?,
+ // ASCII control characters except \0, \n, \r, \t
+ '\x01'..='\x08'
+ | '\x0b'
+ | '\x0c'
+ | '\x0e'..='\x19'
+ | '\x7f' => {
+ write!(f, "\\x{:02x}", u32::from(ch))?;
+ }
+ '\n' | '\r' | '\t' | _ => {
+ write!(f, "{}", ch.escape_debug())?;
+ }
+ }
+ }
+ write!(f, "\"")?;
+ Ok(())
+ }
+}
+
+/// Decodes the next UTF-8 encoded codepoint from the given byte slice.
+///
+/// If no valid encoding of a codepoint exists at the beginning of the given
+/// byte slice, then the first byte is returned instead.
+///
+/// This returns `None` if and only if `bytes` is empty.
+pub(crate) fn utf8_decode(bytes: &[u8]) -> Option<Result<char, u8>> {
+ fn len(byte: u8) -> Option<usize> {
+ if byte <= 0x7F {
+ return Some(1);
+ } else if byte & 0b1100_0000 == 0b1000_0000 {
+ return None;
+ } else if byte <= 0b1101_1111 {
+ Some(2)
+ } else if byte <= 0b1110_1111 {
+ Some(3)
+ } else if byte <= 0b1111_0111 {
+ Some(4)
+ } else {
+ None
+ }
+ }
+
+ if bytes.is_empty() {
+ return None;
+ }
+ let len = match len(bytes[0]) {
+ None => return Some(Err(bytes[0])),
+ Some(len) if len > bytes.len() => return Some(Err(bytes[0])),
+ Some(1) => return Some(Ok(char::from(bytes[0]))),
+ Some(len) => len,
+ };
+ match core::str::from_utf8(&bytes[..len]) {
+ Ok(s) => Some(Ok(s.chars().next().unwrap())),
+ Err(_) => Some(Err(bytes[0])),
+ }
+}
diff --git a/src/deserializer.rs b/src/deserializer.rs
index 4ee1a67..2448c5a 100644
--- a/src/deserializer.rs
+++ b/src/deserializer.rs
@@ -1,20 +1,20 @@
-use std::error::Error as StdError;
-use std::fmt;
-use std::iter;
-use std::num;
-use std::str;
-
-use serde::de::value::BorrowedBytesDeserializer;
-use serde::de::{
- Deserialize, DeserializeSeed, Deserializer, EnumAccess,
- Error as SerdeError, IntoDeserializer, MapAccess, SeqAccess, Unexpected,
- VariantAccess, Visitor,
+use std::{error::Error as StdError, fmt, iter, num, str};
+
+use serde::{
+ de::value::BorrowedBytesDeserializer,
+ de::{
+ Deserialize, DeserializeSeed, Deserializer, EnumAccess,
+ Error as SerdeError, IntoDeserializer, MapAccess, SeqAccess,
+ Unexpected, VariantAccess, Visitor,
+ },
+ serde_if_integer128,
};
-use serde::serde_if_integer128;
-use crate::byte_record::{ByteRecord, ByteRecordIter};
-use crate::error::{Error, ErrorKind};
-use crate::string_record::{StringRecord, StringRecordIter};
+use crate::{
+ byte_record::{ByteRecord, ByteRecordIter},
+ error::{Error, ErrorKind},
+ string_record::{StringRecord, StringRecordIter},
+};
use self::DeserializeErrorKind as DEK;
@@ -30,7 +30,7 @@ pub fn deserialize_string_record<'de, D: Deserialize<'de>>(
D::deserialize(&mut deser).map_err(|err| {
Error::new(ErrorKind::Deserialize {
pos: record.position().map(Clone::clone),
- err: err,
+ err,
})
})
}
@@ -47,7 +47,7 @@ pub fn deserialize_byte_record<'de, D: Deserialize<'de>>(
D::deserialize(&mut deser).map_err(|err| {
Error::new(ErrorKind::Deserialize {
pos: record.position().map(Clone::clone),
- err: err,
+ err,
})
})
}
@@ -197,10 +197,7 @@ impl<'r> DeRecord<'r> for DeStringRecord<'r> {
}
fn error(&self, kind: DeserializeErrorKind) -> DeserializeError {
- DeserializeError {
- field: Some(self.field.saturating_sub(1)),
- kind: kind,
- }
+ DeserializeError { field: Some(self.field.saturating_sub(1)), kind }
}
fn infer_deserialize<'de, V: Visitor<'de>>(
@@ -291,10 +288,7 @@ impl<'r> DeRecord<'r> for DeByteRecord<'r> {
}
fn error(&self, kind: DeserializeErrorKind) -> DeserializeError {
- DeserializeError {
- field: Some(self.field.saturating_sub(1)),
- kind: kind,
- }
+ DeserializeError { field: Some(self.field.saturating_sub(1)), kind }
}
fn infer_deserialize<'de, V: Visitor<'de>>(
@@ -801,13 +795,16 @@ fn try_float_bytes(s: &[u8]) -> Option<f64> {
mod tests {
use std::collections::HashMap;
- use bstr::BString;
- use serde::{de::DeserializeOwned, serde_if_integer128, Deserialize};
+ use {
+ bstr::BString,
+ serde::{de::DeserializeOwned, serde_if_integer128, Deserialize},
+ };
+
+ use crate::{
+ byte_record::ByteRecord, error::Error, string_record::StringRecord,
+ };
use super::{deserialize_byte_record, deserialize_string_record};
- use crate::byte_record::ByteRecord;
- use crate::error::Error;
- use crate::string_record::StringRecord;
fn de<D: DeserializeOwned>(fields: &[&str]) -> Result<D, Error> {
let record = StringRecord::from(fields);
@@ -913,7 +910,7 @@ mod tests {
struct Foo;
#[derive(Deserialize, Debug, PartialEq)]
- struct Bar {};
+ struct Bar {}
let got = de_headers::<Foo>(&[], &[]);
assert_eq!(got.unwrap(), Foo);
diff --git a/src/error.rs b/src/error.rs
index 793ad3e..ae2a6d8 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,10 +1,9 @@
-use std::error::Error as StdError;
-use std::fmt;
-use std::io;
-use std::result;
+use std::{error::Error as StdError, fmt, io, result};
-use crate::byte_record::{ByteRecord, Position};
-use crate::deserializer::DeserializeError;
+use crate::{
+ byte_record::{ByteRecord, Position},
+ deserializer::DeserializeError,
+};
/// A type alias for `Result<T, csv::Error>`.
pub type Result<T> = result::Result<T, Error>;
@@ -134,19 +133,7 @@ impl From<Error> for io::Error {
}
}
-impl StdError for Error {
- fn source(&self) -> Option<&(dyn StdError + 'static)> {
- match *self.0 {
- ErrorKind::Io(ref err) => Some(err),
- ErrorKind::Utf8 { ref err, .. } => Some(err),
- ErrorKind::UnequalLengths { .. } => None,
- ErrorKind::Seek => None,
- ErrorKind::Serialize(_) => None,
- ErrorKind::Deserialize { ref err, .. } => Some(err),
- _ => unreachable!(),
- }
- }
-}
+impl StdError for Error {}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -227,8 +214,8 @@ pub struct FromUtf8Error {
impl FromUtf8Error {
/// Create a new FromUtf8Error.
- pub(crate) fn new(rec: ByteRecord, err: Utf8Error) -> FromUtf8Error {
- FromUtf8Error { record: rec, err: err }
+ pub(crate) fn new(record: ByteRecord, err: Utf8Error) -> FromUtf8Error {
+ FromUtf8Error { record, err }
}
/// Access the underlying `ByteRecord` that failed UTF-8 validation.
@@ -271,7 +258,7 @@ pub struct Utf8Error {
/// Create a new UTF-8 error.
pub fn new_utf8_error(field: usize, valid_up_to: usize) -> Utf8Error {
- Utf8Error { field: field, valid_up_to: valid_up_to }
+ Utf8Error { field, valid_up_to }
}
impl Utf8Error {
@@ -315,7 +302,7 @@ impl<W> IntoInnerError<W> {
/// (This is a visibility hack. It's public in this module, but not in the
/// crate.)
pub(crate) fn new(wtr: W, err: io::Error) -> IntoInnerError<W> {
- IntoInnerError { wtr: wtr, err: err }
+ IntoInnerError { wtr, err }
}
/// Returns the error which caused the call to `into_inner` to fail.
@@ -334,11 +321,7 @@ impl<W> IntoInnerError<W> {
}
}
-impl<W: std::any::Any> StdError for IntoInnerError<W> {
- fn source(&self) -> Option<&(dyn StdError + 'static)> {
- self.err.source()
- }
-}
+impl<W: std::any::Any> StdError for IntoInnerError<W> {}
impl<W> fmt::Display for IntoInnerError<W> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
diff --git a/src/lib.rs b/src/lib.rs
index 3c771c9..eb7fe5f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -65,9 +65,7 @@ stdout.
There are more examples in the [cookbook](cookbook/index.html).
```no_run
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn example() -> Result<(), Box<dyn Error>> {
// Build the CSV reader and iterate over each record.
@@ -104,13 +102,9 @@ By default, the member names of the struct are matched with the values in the
header record of your CSV data.
```no_run
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
-use serde::Deserialize;
-
-#[derive(Debug, Deserialize)]
+#[derive(Debug, serde::Deserialize)]
struct Record {
city: String,
region: String,
@@ -153,21 +147,24 @@ use std::result;
use serde::{Deserialize, Deserializer};
-pub use crate::byte_record::{ByteRecord, ByteRecordIter, Position};
-pub use crate::deserializer::{DeserializeError, DeserializeErrorKind};
-pub use crate::error::{
- Error, ErrorKind, FromUtf8Error, IntoInnerError, Result, Utf8Error,
-};
-pub use crate::reader::{
- ByteRecordsIntoIter, ByteRecordsIter, DeserializeRecordsIntoIter,
- DeserializeRecordsIter, Reader, ReaderBuilder, StringRecordsIntoIter,
- StringRecordsIter,
+pub use crate::{
+ byte_record::{ByteRecord, ByteRecordIter, Position},
+ deserializer::{DeserializeError, DeserializeErrorKind},
+ error::{
+ Error, ErrorKind, FromUtf8Error, IntoInnerError, Result, Utf8Error,
+ },
+ reader::{
+ ByteRecordsIntoIter, ByteRecordsIter, DeserializeRecordsIntoIter,
+ DeserializeRecordsIter, Reader, ReaderBuilder, StringRecordsIntoIter,
+ StringRecordsIter,
+ },
+ string_record::{StringRecord, StringRecordIter},
+ writer::{Writer, WriterBuilder},
};
-pub use crate::string_record::{StringRecord, StringRecordIter};
-pub use crate::writer::{Writer, WriterBuilder};
mod byte_record;
pub mod cookbook;
+mod debug;
mod deserializer;
mod error;
mod reader;
@@ -321,10 +318,7 @@ impl Default for Trim {
/// ```
/// use std::error::Error;
///
-/// use csv::Reader;
-/// use serde::Deserialize;
-///
-/// #[derive(Debug, Deserialize, Eq, PartialEq)]
+/// #[derive(Debug, serde::Deserialize, Eq, PartialEq)]
/// struct Row {
/// #[serde(deserialize_with = "csv::invalid_option")]
/// a: Option<i32>,
@@ -340,7 +334,7 @@ impl Default for Trim {
/// a,b,c
/// 5,\"\",xyz
/// ";
-/// let mut rdr = Reader::from_reader(data.as_bytes());
+/// let mut rdr = csv::Reader::from_reader(data.as_bytes());
/// if let Some(result) = rdr.deserialize().next() {
/// let record: Row = result?;
/// assert_eq!(record, Row { a: Some(5), b: None, c: None });
diff --git a/src/reader.rs b/src/reader.rs
index 3d66eea..82f5d2c 100644
--- a/src/reader.rs
+++ b/src/reader.rs
@@ -1,16 +1,22 @@
-use std::fs::File;
-use std::io::{self, BufRead, Seek};
-use std::marker::PhantomData;
-use std::path::Path;
-use std::result;
-
-use csv_core::{Reader as CoreReader, ReaderBuilder as CoreReaderBuilder};
-use serde::de::DeserializeOwned;
-
-use crate::byte_record::{ByteRecord, Position};
-use crate::error::{Error, ErrorKind, Result, Utf8Error};
-use crate::string_record::StringRecord;
-use crate::{Terminator, Trim};
+use std::{
+ fs::File,
+ io::{self, BufRead, Seek},
+ marker::PhantomData,
+ path::Path,
+ result,
+};
+
+use {
+ csv_core::{Reader as CoreReader, ReaderBuilder as CoreReaderBuilder},
+ serde::de::DeserializeOwned,
+};
+
+use crate::{
+ byte_record::{ByteRecord, Position},
+ error::{Error, ErrorKind, Result, Utf8Error},
+ string_record::StringRecord,
+ {Terminator, Trim},
+};
/// Builds a CSV reader with various configuration knobs.
///
@@ -885,10 +891,7 @@ impl<R: io::Read> Reader<R> {
/// ```
/// use std::error::Error;
///
- /// use csv::Reader;
- /// use serde::Deserialize;
- ///
- /// #[derive(Debug, Deserialize, Eq, PartialEq)]
+ /// #[derive(Debug, serde::Deserialize, Eq, PartialEq)]
/// struct Row {
/// city: String,
/// country: String,
@@ -902,7 +905,7 @@ impl<R: io::Read> Reader<R> {
/// city,country,popcount
/// Boston,United States,4628910
/// ";
- /// let mut rdr = Reader::from_reader(data.as_bytes());
+ /// let mut rdr = csv::Reader::from_reader(data.as_bytes());
/// let mut iter = rdr.deserialize();
///
/// if let Some(result) = iter.next() {
@@ -942,10 +945,7 @@ impl<R: io::Read> Reader<R> {
/// ```
/// use std::error::Error;
///
- /// use csv::ReaderBuilder;
- /// use serde::Deserialize;
- ///
- /// #[derive(Debug, Deserialize, Eq, PartialEq)]
+ /// #[derive(Debug, serde::Deserialize, Eq, PartialEq)]
/// struct Row {
/// label: String,
/// values: Vec<i32>,
@@ -954,7 +954,7 @@ impl<R: io::Read> Reader<R> {
/// # fn main() { example().unwrap(); }
/// fn example() -> Result<(), Box<dyn Error>> {
/// let data = "foo,1,2,3";
- /// let mut rdr = ReaderBuilder::new()
+ /// let mut rdr = csv::ReaderBuilder::new()
/// .has_headers(false)
/// .from_reader(data.as_bytes());
/// let mut iter = rdr.deserialize();
@@ -989,23 +989,20 @@ impl<R: io::Read> Reader<R> {
/// ```
/// use std::error::Error;
///
- /// use csv::Reader;
- /// use serde::Deserialize;
- ///
- /// #[derive(Debug, Deserialize, PartialEq)]
+ /// #[derive(Debug, serde::Deserialize, PartialEq)]
/// struct Row {
/// label: Label,
/// value: Number,
/// }
///
- /// #[derive(Debug, Deserialize, PartialEq)]
+ /// #[derive(Debug, serde::Deserialize, PartialEq)]
/// #[serde(rename_all = "lowercase")]
/// enum Label {
/// Celsius,
/// Fahrenheit,
/// }
///
- /// #[derive(Debug, Deserialize, PartialEq)]
+ /// #[derive(Debug, serde::Deserialize, PartialEq)]
/// #[serde(untagged)]
/// enum Number {
/// Integer(i64),
@@ -1019,7 +1016,7 @@ impl<R: io::Read> Reader<R> {
/// celsius,22.2222
/// fahrenheit,72
/// ";
- /// let mut rdr = Reader::from_reader(data.as_bytes());
+ /// let mut rdr = csv::Reader::from_reader(data.as_bytes());
/// let mut iter = rdr.deserialize();
///
/// // Read the first record.
@@ -1078,10 +1075,7 @@ impl<R: io::Read> Reader<R> {
/// ```
/// use std::error::Error;
///
- /// use csv::Reader;
- /// use serde::Deserialize;
- ///
- /// #[derive(Debug, Deserialize, Eq, PartialEq)]
+ /// #[derive(Debug, serde::Deserialize, Eq, PartialEq)]
/// struct Row {
/// city: String,
/// country: String,
@@ -1095,7 +1089,7 @@ impl<R: io::Read> Reader<R> {
/// city,country,popcount
/// Boston,United States,4628910
/// ";
- /// let rdr = Reader::from_reader(data.as_bytes());
+ /// let rdr = csv::Reader::from_reader(data.as_bytes());
/// let mut iter = rdr.into_deserialize();
///
/// if let Some(result) = iter.next() {
@@ -1687,8 +1681,7 @@ impl<R: io::Read> Reader<R> {
/// # Example: reading the position
///
/// ```
- /// use std::error::Error;
- /// use std::io;
+ /// use std::{error::Error, io};
/// use csv::{Reader, Position};
///
/// # fn main() { example().unwrap(); }
@@ -1730,8 +1723,7 @@ impl<R: io::Read> Reader<R> {
/// # Example
///
/// ```
- /// use std::error::Error;
- /// use std::io;
+ /// use std::{error::Error, io};
/// use csv::{Reader, Position};
///
/// # fn main() { example().unwrap(); }
@@ -1806,8 +1798,7 @@ impl<R: io::Read + io::Seek> Reader<R> {
/// # Example: seek to parse a record twice
///
/// ```
- /// use std::error::Error;
- /// use std::io;
+ /// use std::{error::Error, io};
/// use csv::{Reader, Position};
///
/// # fn main() { example().unwrap(); }
@@ -1927,9 +1918,9 @@ impl<R: io::Read, D: DeserializeOwned> DeserializeRecordsIntoIter<R, D> {
rdr.headers().ok().map(Clone::clone)
};
DeserializeRecordsIntoIter {
- rdr: rdr,
+ rdr,
rec: StringRecord::new(),
- headers: headers,
+ headers,
_priv: PhantomData,
}
}
@@ -1985,9 +1976,9 @@ impl<'r, R: io::Read, D: DeserializeOwned> DeserializeRecordsIter<'r, R, D> {
rdr.headers().ok().map(Clone::clone)
};
DeserializeRecordsIter {
- rdr: rdr,
+ rdr,
rec: StringRecord::new(),
- headers: headers,
+ headers,
_priv: PhantomData,
}
}
@@ -2025,7 +2016,7 @@ pub struct StringRecordsIntoIter<R> {
impl<R: io::Read> StringRecordsIntoIter<R> {
fn new(rdr: Reader<R>) -> StringRecordsIntoIter<R> {
- StringRecordsIntoIter { rdr: rdr, rec: StringRecord::new() }
+ StringRecordsIntoIter { rdr, rec: StringRecord::new() }
}
/// Return a reference to the underlying CSV reader.
@@ -2067,7 +2058,7 @@ pub struct StringRecordsIter<'r, R: 'r> {
impl<'r, R: io::Read> StringRecordsIter<'r, R> {
fn new(rdr: &'r mut Reader<R>) -> StringRecordsIter<'r, R> {
- StringRecordsIter { rdr: rdr, rec: StringRecord::new() }
+ StringRecordsIter { rdr, rec: StringRecord::new() }
}
/// Return a reference to the underlying CSV reader.
@@ -2101,7 +2092,7 @@ pub struct ByteRecordsIntoIter<R> {
impl<R: io::Read> ByteRecordsIntoIter<R> {
fn new(rdr: Reader<R>) -> ByteRecordsIntoIter<R> {
- ByteRecordsIntoIter { rdr: rdr, rec: ByteRecord::new() }
+ ByteRecordsIntoIter { rdr, rec: ByteRecord::new() }
}
/// Return a reference to the underlying CSV reader.
@@ -2143,7 +2134,7 @@ pub struct ByteRecordsIter<'r, R: 'r> {
impl<'r, R: io::Read> ByteRecordsIter<'r, R> {
fn new(rdr: &'r mut Reader<R>) -> ByteRecordsIter<'r, R> {
- ByteRecordsIter { rdr: rdr, rec: ByteRecord::new() }
+ ByteRecordsIter { rdr, rec: ByteRecord::new() }
}
/// Return a reference to the underlying CSV reader.
@@ -2173,9 +2164,9 @@ impl<'r, R: io::Read> Iterator for ByteRecordsIter<'r, R> {
mod tests {
use std::io;
- use crate::byte_record::ByteRecord;
- use crate::error::ErrorKind;
- use crate::string_record::StringRecord;
+ use crate::{
+ byte_record::ByteRecord, error::ErrorKind, string_record::StringRecord,
+ };
use super::{Position, ReaderBuilder, Trim};
diff --git a/src/serializer.rs b/src/serializer.rs
index 40c94f2..1085424 100644
--- a/src/serializer.rs
+++ b/src/serializer.rs
@@ -1,18 +1,21 @@
-use std::fmt;
-use std::io;
-use std::mem;
-
-use itoa;
-use ryu;
-use serde::ser::{
- Error as SerdeError, Serialize, SerializeMap, SerializeSeq,
- SerializeStruct, SerializeStructVariant, SerializeTuple,
- SerializeTupleStruct, SerializeTupleVariant, Serializer,
+use std::{fmt, io, mem};
+
+use {
+ itoa, ryu,
+ serde::{
+ ser::{
+ Error as SerdeError, Serialize, SerializeMap, SerializeSeq,
+ SerializeStruct, SerializeStructVariant, SerializeTuple,
+ SerializeTupleStruct, SerializeTupleVariant, Serializer,
+ },
+ serde_if_integer128,
+ },
};
-use serde::serde_if_integer128;
-use crate::error::{Error, ErrorKind};
-use crate::writer::Writer;
+use crate::{
+ error::{Error, ErrorKind},
+ writer::Writer,
+};
/// Serialize the given value to the given writer, and return an error if
/// anything went wrong.
@@ -20,7 +23,7 @@ pub fn serialize<S: Serialize, W: io::Write>(
wtr: &mut Writer<W>,
value: S,
) -> Result<(), Error> {
- value.serialize(&mut SeRecord { wtr: wtr })
+ value.serialize(&mut SeRecord { wtr })
}
struct SeRecord<'w, W: 'w + io::Write> {
@@ -452,7 +455,7 @@ struct SeHeader<'w, W: 'w + io::Write> {
impl<'w, W: io::Write> SeHeader<'w, W> {
fn new(wtr: &'w mut Writer<W>) -> Self {
- SeHeader { wtr: wtr, state: HeaderState::Write }
+ SeHeader { wtr, state: HeaderState::Write }
}
fn wrote_header(&self) -> bool {
@@ -818,11 +821,15 @@ impl<'a, 'w, W: io::Write> SerializeStructVariant for &'a mut SeHeader<'w, W> {
#[cfg(test)]
mod tests {
- use bstr::ByteSlice;
- use serde::{serde_if_integer128, Serialize};
-
- use crate::error::{Error, ErrorKind};
- use crate::writer::Writer;
+ use {
+ bstr::ByteSlice,
+ serde::{serde_if_integer128, Serialize},
+ };
+
+ use crate::{
+ error::{Error, ErrorKind},
+ writer::Writer,
+ };
use super::{SeHeader, SeRecord};
diff --git a/src/string_record.rs b/src/string_record.rs
index 4e758f3..4df5884 100644
--- a/src/string_record.rs
+++ b/src/string_record.rs
@@ -1,16 +1,18 @@
-use std::fmt;
-use std::io;
-use std::iter::FromIterator;
-use std::ops::{self, Range};
-use std::result;
-use std::str;
+use std::{
+ fmt, io,
+ iter::FromIterator,
+ ops::{self, Range},
+ result, str,
+};
use serde::de::Deserialize;
-use crate::byte_record::{ByteRecord, ByteRecordIter, Position};
-use crate::deserializer::deserialize_string_record;
-use crate::error::{Error, ErrorKind, FromUtf8Error, Result};
-use crate::reader::Reader;
+use crate::{
+ byte_record::{ByteRecord, ByteRecordIter, Position},
+ deserializer::deserialize_string_record,
+ error::{Error, ErrorKind, FromUtf8Error, Result},
+ reader::Reader,
+};
/// A single CSV record stored as valid UTF-8 bytes.
///
@@ -226,9 +228,8 @@ impl StringRecord {
/// use std::error::Error;
///
/// use csv::StringRecord;
- /// use serde::Deserialize;
///
- /// #[derive(Deserialize)]
+ /// #[derive(serde::Deserialize)]
/// struct Row<'a> {
/// city: &'a str,
/// country: &'a str,
@@ -262,9 +263,8 @@ impl StringRecord {
/// use std::error::Error;
///
/// use csv::StringRecord;
- /// use serde::Deserialize;
///
- /// #[derive(Deserialize)]
+ /// #[derive(serde::Deserialize)]
/// struct Row {
/// city: String,
/// country: String,
@@ -646,7 +646,7 @@ impl StringRecord {
match (read_res, utf8_res) {
(Err(err), _) => Err(err),
(Ok(_), Err(err)) => {
- Err(Error::new(ErrorKind::Utf8 { pos: Some(pos), err: err }))
+ Err(Error::new(ErrorKind::Utf8 { pos: Some(pos), err }))
}
(Ok(eof), Ok(())) => Ok(eof),
}
diff --git a/src/tutorial.rs b/src/tutorial.rs
index 9d5e607..7bce7c0 100644
--- a/src/tutorial.rs
+++ b/src/tutorial.rs
@@ -281,8 +281,7 @@ let's get rid of the panic and print an error message manually:
```no_run
//tutorial-error-02.rs
-use std::io;
-use std::process;
+use std::{io, process};
fn main() {
let mut rdr = csv::Reader::from_reader(io::stdin());
@@ -320,9 +319,7 @@ error, which our `main` function can then inspect and decide what to do with.
```no_run
//tutorial-error-03.rs
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn main() {
if let Err(err) = run() {
@@ -360,9 +357,7 @@ special Rust language feature: the question mark.
```no_run
//tutorial-error-04.rs
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn main() {
if let Err(err) = run() {
@@ -416,11 +411,13 @@ path argument instead of stdin.
```no_run
//tutorial-read-01.rs
-use std::env;
-use std::error::Error;
-use std::ffi::OsString;
-use std::fs::File;
-use std::process;
+use std::{
+ env,
+ error::Error,
+ ffi::OsString,
+ fs::File,
+ process,
+};
fn run() -> Result<(), Box<dyn Error>> {
let file_path = get_first_arg()?;
@@ -524,9 +521,7 @@ produces terser examples.)
```no_run
//tutorial-read-headers-01.rs
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# use std::{error::Error, io, process};
#
fn run() -> Result<(), Box<dyn Error>> {
let mut rdr = csv::ReaderBuilder::new()
@@ -565,9 +560,7 @@ method like so:
```no_run
//tutorial-read-headers-02.rs
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# use std::{error::Error, io, process};
#
fn run() -> Result<(), Box<dyn Error>> {
let mut rdr = csv::Reader::from_reader(io::stdin());
@@ -646,9 +639,7 @@ as seen in the following example:
```no_run
//tutorial-read-delimiter-01.rs
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# use std::{error::Error, io, process};
#
fn run() -> Result<(), Box<dyn Error>> {
let mut rdr = csv::ReaderBuilder::new()
@@ -734,9 +725,7 @@ a lot of manual work. This next example shows how.
```no_run
//tutorial-read-serde-01.rs
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# use std::{error::Error, io, process};
#
fn run() -> Result<(), Box<dyn Error>> {
let mut rdr = csv::Reader::from_reader(io::stdin());
@@ -777,9 +766,7 @@ type: `(String, String, Option<u64>, f64, f64)`.
```no_run
//tutorial-read-serde-02.rs
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# use std::{error::Error, io, process};
#
// This introduces a type alias so that we can conveniently reference our
// record type.
@@ -831,9 +818,7 @@ a new `use` statement that imports `HashMap` from the standard library:
```no_run
//tutorial-read-serde-03.rs
use std::collections::HashMap;
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# use std::{error::Error, io, process};
// This introduces a type alias so that we can conveniently reference our
// record type.
@@ -889,9 +874,8 @@ how. Don't miss the new Serde imports!
```no_run
//tutorial-read-serde-04.rs
-use std::error::Error;
-use std::io;
-use std::process;
+# #![allow(dead_code)]
+# use std::{error::Error, io, process};
// This lets us write `#[derive(Deserialize)]`.
use serde::Deserialize;
@@ -1027,9 +1011,8 @@ Let's start by running our program from the previous section:
```no_run
//tutorial-read-serde-invalid-01.rs
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# #![allow(dead_code)]
+# use std::{error::Error, io, process};
#
# use serde::Deserialize;
#
@@ -1096,9 +1079,8 @@ to a `None` value, as shown in this next example:
```no_run
//tutorial-read-serde-invalid-02.rs
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# #![allow(dead_code)]
+# use std::{error::Error, io, process};
#
# use serde::Deserialize;
#[derive(Debug, Deserialize)]
@@ -1164,9 +1146,7 @@ Let's start with the most basic example: writing a few CSV records to `stdout`.
```no_run
//tutorial-write-01.rs
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn run() -> Result<(), Box<dyn Error>> {
let mut wtr = csv::Writer::from_writer(io::stdout());
@@ -1273,10 +1253,12 @@ of `stdout`:
```no_run
//tutorial-write-02.rs
-use std::env;
-use std::error::Error;
-use std::ffi::OsString;
-use std::process;
+use std::{
+ env,
+ error::Error,
+ ffi::OsString,
+ process,
+};
fn run() -> Result<(), Box<dyn Error>> {
let file_path = get_first_arg()?;
@@ -1334,9 +1316,7 @@ Here's an example:
```no_run
//tutorial-write-delimiter-01.rs
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# use std::{error::Error, io, process};
#
fn run() -> Result<(), Box<dyn Error>> {
let mut wtr = csv::WriterBuilder::new()
@@ -1390,9 +1370,7 @@ As with reading, let's start by seeing how we can serialize a Rust tuple.
```no_run
//tutorial-write-serde-01.rs
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# use std::{error::Error, io, process};
#
fn run() -> Result<(), Box<dyn Error>> {
let mut wtr = csv::Writer::from_writer(io::stdout());
@@ -1460,9 +1438,7 @@ shown in the example:
```no_run
//tutorial-write-serde-02.rs
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
use serde::Serialize;
@@ -1589,10 +1565,7 @@ rows with a field that matches the query.
```no_run
//tutorial-pipeline-search-01.rs
-use std::env;
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{env, error::Error, io, process};
fn run() -> Result<(), Box<dyn Error>> {
// Get the query from the positional arguments.
@@ -1709,10 +1682,7 @@ change:
```no_run
//tutorial-pipeline-search-02.rs
-# use std::env;
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# use std::{env, error::Error, io, process};
#
fn run() -> Result<(), Box<dyn Error>> {
let query = match env::args().nth(1) {
@@ -1781,10 +1751,7 @@ Now here's the code:
```no_run
//tutorial-pipeline-pop-01.rs
-use std::env;
-use std::error::Error;
-use std::io;
-use std::process;
+# use std::{env, error::Error, io, process};
use serde::{Deserialize, Serialize};
@@ -1914,9 +1881,7 @@ adapting a previous example to count the number of records in
```no_run
//tutorial-perf-alloc-01.rs
-use std::error::Error;
-use std::io;
-use std::process;
+use std::{error::Error, io, process};
fn run() -> Result<u64, Box<dyn Error>> {
let mut rdr = csv::Reader::from_reader(io::stdin());
@@ -1972,9 +1937,7 @@ shown in the next example:
```no_run
//tutorial-perf-alloc-02.rs
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# use std::{error::Error, io, process};
#
fn run() -> Result<u64, Box<dyn Error>> {
let mut rdr = csv::Reader::from_reader(io::stdin());
@@ -2055,9 +2018,7 @@ method.
```no_run
//tutorial-perf-alloc-03.rs
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# use std::{error::Error, io, process};
#
fn run() -> Result<u64, Box<dyn Error>> {
let mut rdr = csv::Reader::from_reader(io::stdin());
@@ -2136,9 +2097,8 @@ example using Serde in a previous section:
```no_run
//tutorial-perf-serde-01.rs
-use std::error::Error;
-use std::io;
-use std::process;
+# #![allow(dead_code)]
+use std::{error::Error, io, process};
use serde::Deserialize;
@@ -2205,10 +2165,8 @@ like:
```no_run
//tutorial-perf-serde-02.rs
-# use std::error::Error;
-# use std::io;
-# use std::process;
-#
+# #![allow(dead_code)]
+# use std::{error::Error, io, process};
# use serde::Deserialize;
#
#[derive(Debug, Deserialize)]
@@ -2292,9 +2250,8 @@ of `StringRecord`:
```no_run
//tutorial-perf-serde-03.rs
-# use std::error::Error;
-# use std::io;
-# use std::process;
+# #![allow(dead_code)]
+# use std::{error::Error, io, process};
#
# use serde::Deserialize;
#
diff --git a/src/writer.rs b/src/writer.rs
index a329d8d..42c85c1 100644
--- a/src/writer.rs
+++ b/src/writer.rs
@@ -1,18 +1,19 @@
-use std::fs::File;
-use std::io;
-use std::path::Path;
-use std::result;
-
-use csv_core::{
- self, WriteResult, Writer as CoreWriter,
- WriterBuilder as CoreWriterBuilder,
+use std::{fs::File, io, path::Path, result};
+
+use {
+ csv_core::{
+ self, WriteResult, Writer as CoreWriter,
+ WriterBuilder as CoreWriterBuilder,
+ },
+ serde::Serialize,
};
-use serde::Serialize;
-use crate::byte_record::ByteRecord;
-use crate::error::{Error, ErrorKind, IntoInnerError, Result};
-use crate::serializer::{serialize, serialize_header};
-use crate::{QuoteStyle, Terminator};
+use crate::{
+ byte_record::ByteRecord,
+ error::{Error, ErrorKind, IntoInnerError, Result},
+ serializer::{serialize, serialize_header},
+ {QuoteStyle, Terminator},
+};
/// Builds a CSV writer with various configuration knobs.
///
@@ -166,9 +167,8 @@ impl WriterBuilder {
/// use std::error::Error;
///
/// use csv::WriterBuilder;
- /// use serde::Serialize;
///
- /// #[derive(Serialize)]
+ /// #[derive(serde::Serialize)]
/// struct Row<'a> {
/// city: &'a str,
/// country: &'a str,
@@ -478,7 +478,7 @@ impl WriterBuilder {
}
}
-/// A already configured CSV writer.
+/// An already configured CSV writer.
///
/// A CSV writer takes as input Rust values and writes those values in a valid
/// CSV format as output.
@@ -518,7 +518,7 @@ struct WriterState {
header: HeaderState,
/// Whether inconsistent record lengths are allowed.
flexible: bool,
- /// The number of fields writtein in the first record. This is compared
+ /// The number of fields written in the first record. This is compared
/// with `fields_written` on all subsequent records to check for
/// inconsistent record lengths.
first_field_count: Option<u64>,
@@ -536,7 +536,7 @@ struct WriterState {
enum HeaderState {
/// Indicates that we should attempt to write a header.
Write,
- /// Indicates that writing a header was attempt, and a header was written.
+ /// Indicates that writing a header was attempted, and a header was written.
DidWrite,
/// Indicates that writing a header was attempted, but no headers were
/// written or the attempt failed.
@@ -655,9 +655,8 @@ impl<W: io::Write> Writer<W> {
/// use std::error::Error;
///
/// use csv::Writer;
- /// use serde::Serialize;
///
- /// #[derive(Serialize)]
+ /// #[derive(serde::Serialize)]
/// struct Row<'a> {
/// city: &'a str,
/// country: &'a str,
@@ -738,15 +737,14 @@ impl<W: io::Write> Writer<W> {
/// use std::error::Error;
///
/// use csv::Writer;
- /// use serde::Serialize;
///
- /// #[derive(Serialize)]
+ /// #[derive(serde::Serialize)]
/// struct Row {
/// label: String,
/// value: Value,
/// }
///
- /// #[derive(Serialize)]
+ /// #[derive(serde::Serialize)]
/// enum Value {
/// Integer(i64),
/// Float(f64),
@@ -804,9 +802,8 @@ impl<W: io::Write> Writer<W> {
/// use std::error::Error;
///
/// use csv::WriterBuilder;
- /// use serde::Serialize;
///
- /// #[derive(Serialize)]
+ /// #[derive(serde::Serialize)]
/// struct Row {
/// label: String,
/// values: Vec<f64>,
@@ -1184,13 +1181,13 @@ impl Buffer {
#[cfg(test)]
mod tests {
- use serde::{serde_if_integer128, Serialize};
-
use std::io::{self, Write};
- use crate::byte_record::ByteRecord;
- use crate::error::ErrorKind;
- use crate::string_record::StringRecord;
+ use serde::{serde_if_integer128, Serialize};
+
+ use crate::{
+ byte_record::ByteRecord, error::ErrorKind, string_record::StringRecord,
+ };
use super::{Writer, WriterBuilder};