From 98e901282b7dc46b1401f5da05dba985b60d0a07 Mon Sep 17 00:00:00 2001 From: Jeff Vander Stoep Date: Wed, 15 Feb 2023 20:12:43 +0100 Subject: Upgrade csv to 1.2.0 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 Test: TreeHugger Change-Id: I95550d755615eea05290fd6dcdfe9d4330a002cb --- .cargo_vcs_info.json | 7 +- Android.bp | 9 +- Cargo.toml | 58 ++++++++----- Cargo.toml.orig | 20 ++--- METADATA | 14 +-- README.md | 19 ++--- examples/cookbook-read-basic.rs | 4 +- examples/cookbook-read-colon.rs | 4 +- examples/cookbook-read-no-headers.rs | 4 +- examples/cookbook-read-serde.rs | 5 +- examples/cookbook-write-basic.rs | 4 +- examples/cookbook-write-serde.rs | 4 +- examples/tutorial-error-02.rs | 3 +- examples/tutorial-error-03.rs | 4 +- examples/tutorial-error-04.rs | 4 +- examples/tutorial-perf-alloc-01.rs | 4 +- examples/tutorial-perf-alloc-02.rs | 4 +- examples/tutorial-perf-alloc-03.rs | 4 +- examples/tutorial-perf-serde-01.rs | 5 +- examples/tutorial-perf-serde-02.rs | 6 +- examples/tutorial-perf-serde-03.rs | 5 +- examples/tutorial-pipeline-pop-01.rs | 5 +- examples/tutorial-pipeline-search-01.rs | 5 +- examples/tutorial-pipeline-search-02.rs | 5 +- examples/tutorial-read-01.rs | 6 +- examples/tutorial-read-delimiter-01.rs | 4 +- examples/tutorial-read-headers-01.rs | 4 +- examples/tutorial-read-headers-02.rs | 4 +- examples/tutorial-read-serde-01.rs | 4 +- examples/tutorial-read-serde-02.rs | 4 +- examples/tutorial-read-serde-03.rs | 4 +- examples/tutorial-read-serde-04.rs | 5 +- examples/tutorial-read-serde-invalid-01.rs | 5 +- examples/tutorial-read-serde-invalid-02.rs | 5 +- examples/tutorial-write-01.rs | 4 +- examples/tutorial-write-02.rs | 5 +- examples/tutorial-write-delimiter-01.rs | 4 +- examples/tutorial-write-serde-01.rs | 4 +- examples/tutorial-write-serde-02.rs | 4 +- src/byte_record.rs | 65 ++++++++++---- src/cookbook.rs | 25 ++---- src/debug.rs | 80 ++++++++++++++++++ src/deserializer.rs | 59 ++++++------- src/error.rs | 39 +++------ src/lib.rs | 44 +++++----- src/reader.rs | 95 ++++++++++----------- src/serializer.rs | 47 ++++++----- src/string_record.rs | 30 +++---- src/tutorial.rs | 131 ++++++++++------------------- src/writer.rs | 57 ++++++------- 50 files changed, 459 insertions(+), 485 deletions(-) create mode 100644 src/debug.rs 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..f6ff416 100644 --- a/Android.bp +++ b/Android.bp @@ -42,14 +42,17 @@ 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", + ], } 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 "] -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 "] 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> { // 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> { // 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> { 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> { 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> { 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> { 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> { 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> { 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> { // 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> { 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> { 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> { 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> { 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> { 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> { 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> { 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> { 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> { 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> { 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> { // 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> { 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> { 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> { 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> { + fn len(byte: u8) -> Option { + 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 { 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(fields: &[&str]) -> Result { 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::(&[], &[]); 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`. pub type Result = result::Result; @@ -134,19 +133,7 @@ impl From 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 IntoInnerError { /// (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 { - 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 IntoInnerError { } } -impl StdError for IntoInnerError { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - self.err.source() - } -} +impl StdError for IntoInnerError {} impl fmt::Display for IntoInnerError { 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> { // 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, @@ -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 Reader { /// ``` /// 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 Reader { /// 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 Reader { /// ``` /// 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, @@ -954,7 +954,7 @@ impl Reader { /// # fn main() { example().unwrap(); } /// fn example() -> Result<(), Box> { /// 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 Reader { /// ``` /// 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 Reader { /// 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 Reader { /// ``` /// 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 Reader { /// 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 Reader { /// # 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 Reader { /// # 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 Reader { /// # 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 DeserializeRecordsIntoIter { 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 { impl StringRecordsIntoIter { fn new(rdr: Reader) -> StringRecordsIntoIter { - 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) -> 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 { impl ByteRecordsIntoIter { fn new(rdr: Reader) -> ByteRecordsIntoIter { - 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) -> 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( wtr: &mut Writer, 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) -> 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> { 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> { 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> { 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> { 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> { let mut rdr = csv::Reader::from_reader(io::stdin()); @@ -777,9 +766,7 @@ type: `(String, String, Option, 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> { 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> { 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> { 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> { 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> { // 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> { 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> { 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> { 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> { 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, @@ -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 Writer { /// 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 Writer { /// 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 Writer { /// use std::error::Error; /// /// use csv::WriterBuilder; - /// use serde::Serialize; /// - /// #[derive(Serialize)] + /// #[derive(serde::Serialize)] /// struct Row { /// label: String, /// values: Vec, @@ -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}; -- cgit v1.2.3