diff -Nru rust-csv-1.0.5/benches/bench.rs rust-csv-1.1.1/benches/bench.rs --- rust-csv-1.0.5/benches/bench.rs 2018-09-15 11:44:13.000000000 +0000 +++ rust-csv-1.1.1/benches/bench.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,22 +1,19 @@ #![feature(test)] -extern crate csv; -extern crate serde; -#[macro_use] -extern crate serde_derive; extern crate test; use std::io; -use serde::de::DeserializeOwned; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use test::Bencher; -use csv::{ByteRecord, Reader, ReaderBuilder, StringRecord, Writer, WriterBuilder, Trim}; +use csv::{ + ByteRecord, Reader, ReaderBuilder, StringRecord, Trim, Writer, + WriterBuilder, +}; -static NFL: &'static str = - include_str!("../examples/data/bench/nfl.csv"); -static GAME: &'static str = - include_str!("../examples/data/bench/game.csv"); +static NFL: &'static str = include_str!("../examples/data/bench/nfl.csv"); +static GAME: &'static str = include_str!("../examples/data/bench/game.csv"); static POP: &'static str = include_str!("../examples/data/bench/worldcitiespop.csv"); static MBTA: &'static str = @@ -114,14 +111,16 @@ #[derive(Default)] struct ByteCounter { - count: usize + count: usize, } impl io::Write for ByteCounter { fn write(&mut self, data: &[u8]) -> io::Result { self.count += data.len(); Ok(data.len()) } - fn flush(&mut self) -> io::Result<()> { Ok(()) } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } } macro_rules! bench { @@ -131,9 +130,8 @@ let data = $data.as_bytes(); b.bytes = data.len() as u64; b.iter(|| { - let mut rdr = ReaderBuilder::new() - .has_headers(false) - .from_reader(data); + let mut rdr = + ReaderBuilder::new().has_headers(false).from_reader(data); assert_eq!($counter(&mut rdr), $result); }) } @@ -157,7 +155,6 @@ }; } - macro_rules! bench_serde { (no_headers, $name_de:ident, $name_ser:ident, $data:ident, $counter:ident, $type:ty, $result:expr) => { @@ -166,9 +163,8 @@ let data = $data.as_bytes(); b.bytes = data.len() as u64; b.iter(|| { - let mut rdr = ReaderBuilder::new() - .has_headers(false) - .from_reader(data); + let mut rdr = + ReaderBuilder::new().has_headers(false).from_reader(data); assert_eq!($counter::<_, $type>(&mut rdr), $result); }) } @@ -204,9 +200,8 @@ let data = $data.as_bytes(); b.bytes = data.len() as u64; b.iter(|| { - let mut rdr = ReaderBuilder::new() - .has_headers(true) - .from_reader(data); + let mut rdr = + ReaderBuilder::new().has_headers(true).from_reader(data); assert_eq!($counter::<_, $type>(&mut rdr), $result); }) } @@ -257,7 +252,7 @@ count }) } - } + }; } macro_rules! bench_serde_borrowed_str { @@ -279,21 +274,39 @@ count }) } - } + }; } bench_serde!( count_nfl_deserialize_owned_bytes, count_nfl_serialize_owned_bytes, - NFL, count_deserialize_owned_bytes, NFLRowOwned, 9999); + NFL, + count_deserialize_owned_bytes, + NFLRowOwned, + 9999 +); bench_serde!( count_nfl_deserialize_owned_str, count_nfl_serialize_owned_str, - NFL, count_deserialize_owned_str, NFLRowOwned, 9999); + NFL, + count_deserialize_owned_str, + NFLRowOwned, + 9999 +); bench_serde_borrowed_bytes!( - count_nfl_deserialize_borrowed_bytes, NFL, NFLRowBorrowed, true, 9999); + count_nfl_deserialize_borrowed_bytes, + NFL, + NFLRowBorrowed, + true, + 9999 +); bench_serde_borrowed_str!( - count_nfl_deserialize_borrowed_str, NFL, NFLRowBorrowed, true, 9999); + count_nfl_deserialize_borrowed_str, + NFL, + NFLRowBorrowed, + true, + 9999 +); bench!(count_nfl_iter_bytes, NFL, count_iter_bytes, 130000); bench_trimmed!(count_nfl_iter_bytes_trimmed, NFL, count_iter_bytes, 130000); bench!(count_nfl_iter_str, NFL, count_iter_str, 130000); @@ -304,18 +317,34 @@ no_headers, count_game_deserialize_owned_bytes, count_game_serialize_owned_bytes, - GAME, count_deserialize_owned_bytes, GAMERowOwned, 100000); + GAME, + count_deserialize_owned_bytes, + GAMERowOwned, + 100000 +); bench_serde!( no_headers, count_game_deserialize_owned_str, count_game_serialize_owned_str, - GAME, count_deserialize_owned_str, GAMERowOwned, 100000); + GAME, + count_deserialize_owned_str, + GAMERowOwned, + 100000 +); bench_serde_borrowed_bytes!( count_game_deserialize_borrowed_bytes, - GAME, GAMERowBorrowed, true, 100000); + GAME, + GAMERowBorrowed, + true, + 100000 +); bench_serde_borrowed_str!( count_game_deserialize_borrowed_str, - GAME, GAMERowBorrowed, true, 100000); + GAME, + GAMERowBorrowed, + true, + 100000 +); bench!(count_game_iter_bytes, GAME, count_iter_bytes, 600000); bench!(count_game_iter_str, GAME, count_iter_str, 600000); bench!(count_game_read_bytes, GAME, count_read_bytes, 600000); @@ -323,17 +352,33 @@ bench_serde!( count_pop_deserialize_owned_bytes, count_pop_serialize_owned_bytes, - POP, count_deserialize_owned_bytes, POPRowOwned, 20000); + POP, + count_deserialize_owned_bytes, + POPRowOwned, + 20000 +); bench_serde!( count_pop_deserialize_owned_str, count_pop_serialize_owned_str, - POP, count_deserialize_owned_str, POPRowOwned, 20000); + POP, + count_deserialize_owned_str, + POPRowOwned, + 20000 +); bench_serde_borrowed_bytes!( count_pop_deserialize_borrowed_bytes, - POP, POPRowBorrowed, true, 20000); + POP, + POPRowBorrowed, + true, + 20000 +); bench_serde_borrowed_str!( count_pop_deserialize_borrowed_str, - POP, POPRowBorrowed, true, 20000); + POP, + POPRowBorrowed, + true, + 20000 +); bench!(count_pop_iter_bytes, POP, count_iter_bytes, 140007); bench!(count_pop_iter_str, POP, count_iter_str, 140007); bench!(count_pop_read_bytes, POP, count_read_bytes, 140007); @@ -341,17 +386,33 @@ bench_serde!( count_mbta_deserialize_owned_bytes, count_mbta_serialize_owned_bytes, - MBTA, count_deserialize_owned_bytes, MBTARowOwned, 9999); + MBTA, + count_deserialize_owned_bytes, + MBTARowOwned, + 9999 +); bench_serde!( count_mbta_deserialize_owned_str, count_mbta_serialize_owned_str, - MBTA, count_deserialize_owned_str, MBTARowOwned, 9999); + MBTA, + count_deserialize_owned_str, + MBTARowOwned, + 9999 +); bench_serde_borrowed_bytes!( count_mbta_deserialize_borrowed_bytes, - MBTA, MBTARowBorrowed, true, 9999); + MBTA, + MBTARowBorrowed, + true, + 9999 +); bench_serde_borrowed_str!( count_mbta_deserialize_borrowed_str, - MBTA, MBTARowBorrowed, true, 9999); + MBTA, + MBTARowBorrowed, + true, + 9999 +); bench!(count_mbta_iter_bytes, MBTA, count_iter_bytes, 90000); bench!(count_mbta_iter_str, MBTA, count_iter_str, 90000); bench!(count_mbta_read_bytes, MBTA, count_read_bytes, 90000); @@ -373,7 +434,7 @@ assert!(wtr.flush().is_ok()); }) } - } + }; } macro_rules! bench_write_bytes { @@ -392,14 +453,16 @@ assert!(wtr.flush().is_ok()); }) } - } + }; } bench_write!(write_nfl_record, NFL); bench_write_bytes!(write_nfl_bytes, NFL); fn count_deserialize_owned_bytes(rdr: &mut Reader) -> u64 - where R: io::Read, D: DeserializeOwned +where + R: io::Read, + D: DeserializeOwned, { let mut count = 0; let mut rec = ByteRecord::new(); @@ -411,7 +474,9 @@ } fn count_deserialize_owned_str(rdr: &mut Reader) -> u64 - where R: io::Read, D: DeserializeOwned +where + R: io::Read, + D: DeserializeOwned, { let mut count = 0; for rec in rdr.deserialize::() { @@ -456,10 +521,6 @@ } fn collect_records(data: &[u8]) -> Vec { - let mut rdr = ReaderBuilder::new() - .has_headers(false) - .from_reader(data); - rdr.byte_records() - .collect::, _>>() - .unwrap() + let mut rdr = ReaderBuilder::new().has_headers(false).from_reader(data); + rdr.byte_records().collect::, _>>().unwrap() } diff -Nru rust-csv-1.0.5/Cargo.lock rust-csv-1.1.1/Cargo.lock --- rust-csv-1.0.5/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ rust-csv-1.1.1/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 @@ -0,0 +1,138 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "bstr" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-automata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.93 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byteorder" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "csv" +version = "1.1.1" +dependencies = [ + "bstr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.93 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-automata" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ryu" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.93 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.38 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum bstr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc0572e02f76cb335f309b19e0a0d585b4f62788f7d26de2a13a836a637385f" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" +"checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" +"checksum regex-automata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ed09217220c272b29ef237a974ad58515bde75f194e3ffa7e6d0bf0f3b01f86" +"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum serde 1.0.93 (registry+https://github.com/rust-lang/crates.io-index)" = "960e29cf7004b3b6e65fc5002981400eb3ccc017a08a2406940823e58e7179a9" +"checksum serde_derive 1.0.93 (registry+https://github.com/rust-lang/crates.io-index)" = "c4cce6663696bd38272e90bf34a0267e1226156c33f52d3f3915a2dd5d802085" +"checksum syn 0.15.38 (registry+https://github.com/rust-lang/crates.io-index)" = "37ea458a750f59ab679b47fef9b6722c586c5742f4cfe18a120bbc807e5e01fd" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" diff -Nru rust-csv-1.0.5/Cargo.toml rust-csv-1.1.1/Cargo.toml --- rust-csv-1.0.5/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ rust-csv-1.1.1/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 @@ -11,8 +11,9 @@ # will likely look very different (and much more reasonable) [package] +edition = "2018" name = "csv" -version = "1.0.5" +version = "1.1.1" authors = ["Andrew Gallant "] exclude = ["/.travis.yml", "/appveyor.yml", "/ci/*", "/scripts/*"] description = "Fast CSV parsing with support for serde." @@ -31,16 +32,24 @@ [lib] bench = false +[dependencies.bstr] +version = "0.2.1" +features = ["serde1"] + [dependencies.csv-core] -version = "0.1.4" +version = "0.1.6" + +[dependencies.itoa] +version = "0.4.3" + +[dependencies.ryu] +version = "1" [dependencies.serde] version = "1.0.55" -[dev-dependencies.serde_bytes] -version = "0.10.4" - -[dev-dependencies.serde_derive] +[dev-dependencies.serde] version = "1.0.55" +features = ["derive"] [badges.appveyor] repository = "BurntSushi/rust-csv" diff -Nru rust-csv-1.0.5/Cargo.toml.orig rust-csv-1.1.1/Cargo.toml.orig --- rust-csv-1.0.5/Cargo.toml.orig 2018-12-16 13:07:17.000000000 +0000 +++ rust-csv-1.1.1/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +1,57 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# 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 +# +# 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) + [package] +edition = "2018" name = "csv" -version = "1.0.5" #:version +version = "1.1.1" authors = ["Andrew Gallant "] +exclude = ["/.travis.yml", "/appveyor.yml", "/ci/*", "/scripts/*"] description = "Fast CSV parsing with support for serde." -documentation = "http://burntsushi.net/rustdoc/csv/" homepage = "https://github.com/BurntSushi/rust-csv" -repository = "https://github.com/BurntSushi/rust-csv" +documentation = "http://burntsushi.net/rustdoc/csv/" readme = "README.md" keywords = ["csv", "comma", "parser", "delimited", "serde"] -license = "Unlicense/MIT" categories = ["encoding", "parser-implementations"] -exclude = ["/.travis.yml", "/appveyor.yml", "/ci/*", "/scripts/*"] - -[badges] -travis-ci = { repository = "BurntSushi/rust-csv" } -appveyor = { repository = "BurntSushi/rust-csv" } +license = "Unlicense/MIT" +repository = "https://github.com/BurntSushi/rust-csv" +[profile.bench] +debug = true -[workspace] -members = ["csv-core", "csv-index"] +[profile.release] +debug = true [lib] bench = false +[dependencies.bstr] +version = "0.2.1" +features = ["serde1"] + +[dependencies.csv-core] +version = "0.1.6" + +[dependencies.itoa] +version = "0.4.3" + +[dependencies.ryu] +version = "1" + +[dependencies.serde] +version = "1.0.55" +[dev-dependencies.serde] +version = "1.0.55" +features = ["derive"] +[badges.appveyor] +repository = "BurntSushi/rust-csv" -[dependencies] -csv-core = { path = "csv-core", version = "0.1.4" } -serde = "1.0.55" - -[dev-dependencies] -serde_derive = "1.0.55" -serde_bytes = "0.10.4" - -[profile.release] -debug = true - -[profile.bench] -debug = true +[badges.travis-ci] +repository = "BurntSushi/rust-csv" diff -Nru rust-csv-1.0.5/.cargo_vcs_info.json rust-csv-1.1.1/.cargo_vcs_info.json --- rust-csv-1.0.5/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ rust-csv-1.1.1/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +1,5 @@ { "git": { - "sha1": "0c65da3e72146a39648a41b974ecc626797c60b8" + "sha1": "26c737cc85dc2e5fe1df9e7000ab0e3de3203e6b" } } diff -Nru rust-csv-1.0.5/debian/cargo-checksum.json rust-csv-1.1.1/debian/cargo-checksum.json --- rust-csv-1.0.5/debian/cargo-checksum.json 2019-01-04 09:36:50.000000000 +0000 +++ rust-csv-1.1.1/debian/cargo-checksum.json 2019-08-25 22:06:59.000000000 +0000 @@ -1 +1 @@ -{"package":"9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04","files":{}} +{"package":"37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d","files":{}} diff -Nru rust-csv-1.0.5/debian/changelog rust-csv-1.1.1/debian/changelog --- rust-csv-1.0.5/debian/changelog 2019-01-04 09:36:50.000000000 +0000 +++ rust-csv-1.1.1/debian/changelog 2019-08-25 22:06:59.000000000 +0000 @@ -1,3 +1,15 @@ +rust-csv (1.1.1-1) unstable; urgency=medium + + * Package csv 1.1.1 from crates.io using debcargo 2.2.10 + + -- Paride Legovini Sun, 25 Aug 2019 22:06:59 +0000 + +rust-csv (1.0.7-1) experimental; urgency=medium + + * Package csv 1.0.7 from crates.io using debcargo 2.2.10 + + -- Paride Legovini Fri, 31 May 2019 19:05:02 +0000 + rust-csv (1.0.5-1) unstable; urgency=medium * Package csv 1.0.5 from crates.io using debcargo 2.2.9 diff -Nru rust-csv-1.0.5/debian/control rust-csv-1.1.1/debian/control --- rust-csv-1.0.5/debian/control 2019-01-04 09:36:50.000000000 +0000 +++ rust-csv-1.1.1/debian/control 2019-08-25 22:06:59.000000000 +0000 @@ -2,11 +2,15 @@ Section: rust Priority: optional Build-Depends: debhelper (>= 11), - dh-cargo (>= 10), + dh-cargo (>= 15), cargo:native , rustc:native , libstd-rust-dev , - librust-csv-core-0.1+default-dev (>= 0.1.4-~~) , + librust-bstr-0.2+default-dev (>= 0.2.1-~~) , + librust-bstr-0.2+serde1-dev (>= 0.2.1-~~) , + librust-csv-core-0.1+default-dev (>= 0.1.6-~~) , + librust-itoa-0.4+default-dev (>= 0.4.3-~~) , + librust-ryu-1+default-dev , librust-serde-1+default-dev (>= 1.0.55-~~) Maintainer: Debian Rust Maintainers Uploaders: @@ -21,16 +25,20 @@ Multi-Arch: same Depends: ${misc:Depends}, - librust-csv-core-0.1+default-dev (>= 0.1.4-~~), + librust-bstr-0.2+default-dev (>= 0.2.1-~~), + librust-bstr-0.2+serde1-dev (>= 0.2.1-~~), + librust-csv-core-0.1+default-dev (>= 0.1.6-~~), + librust-itoa-0.4+default-dev (>= 0.4.3-~~), + librust-ryu-1+default-dev, librust-serde-1+default-dev (>= 1.0.55-~~) Provides: librust-csv+default-dev (= ${binary:Version}), librust-csv-1-dev (= ${binary:Version}), librust-csv-1+default-dev (= ${binary:Version}), - librust-csv-1.0-dev (= ${binary:Version}), - librust-csv-1.0+default-dev (= ${binary:Version}), - librust-csv-1.0.5-dev (= ${binary:Version}), - librust-csv-1.0.5+default-dev (= ${binary:Version}) + librust-csv-1.1-dev (= ${binary:Version}), + librust-csv-1.1+default-dev (= ${binary:Version}), + librust-csv-1.1.1-dev (= ${binary:Version}), + librust-csv-1.1.1+default-dev (= ${binary:Version}) Description: Fast CSV parsing with support for serde - Rust source code This package contains the source for the Rust csv crate, packaged by debcargo for use with cargo and dh-cargo. diff -Nru rust-csv-1.0.5/examples/cookbook-read-basic.rs rust-csv-1.1.1/examples/cookbook-read-basic.rs --- rust-csv-1.0.5/examples/cookbook-read-basic.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/cookbook-read-basic.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,10 +1,8 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { // Build the CSV reader and iterate over each record. let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.records() { diff -Nru rust-csv-1.0.5/examples/cookbook-read-colon.rs rust-csv-1.1.1/examples/cookbook-read-colon.rs --- rust-csv-1.0.5/examples/cookbook-read-colon.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/cookbook-read-colon.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,13 +1,10 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn example() -> Result<(), Box> { - let mut rdr = csv::ReaderBuilder::new() - .delimiter(b':') - .from_reader(io::stdin()); +fn example() -> Result<(), Box> { + let mut rdr = + csv::ReaderBuilder::new().delimiter(b':').from_reader(io::stdin()); for result in rdr.records() { let record = result?; println!("{:?}", record); diff -Nru rust-csv-1.0.5/examples/cookbook-read-no-headers.rs rust-csv-1.1.1/examples/cookbook-read-no-headers.rs --- rust-csv-1.0.5/examples/cookbook-read-no-headers.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/cookbook-read-no-headers.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,13 +1,10 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn example() -> Result<(), Box> { - let mut rdr = csv::ReaderBuilder::new() - .has_headers(false) - .from_reader(io::stdin()); +fn example() -> Result<(), Box> { + let mut rdr = + csv::ReaderBuilder::new().has_headers(false).from_reader(io::stdin()); for result in rdr.records() { let record = result?; println!("{:?}", record); diff -Nru rust-csv-1.0.5/examples/cookbook-read-serde.rs rust-csv-1.1.1/examples/cookbook-read-serde.rs --- rust-csv-1.0.5/examples/cookbook-read-serde.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/cookbook-read-serde.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,14 +1,12 @@ -extern crate csv; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +use serde::Deserialize; + // By default, struct field names are deserialized based on the position of // a corresponding field in the CSV data's header record. -#[derive(Debug,Deserialize)] +#[derive(Debug, Deserialize)] struct Record { city: String, region: String, @@ -16,7 +14,7 @@ population: Option, } -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.deserialize() { // Notice that we need to provide a type hint for automatic diff -Nru rust-csv-1.0.5/examples/cookbook-write-basic.rs rust-csv-1.1.1/examples/cookbook-write-basic.rs --- rust-csv-1.0.5/examples/cookbook-write-basic.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/cookbook-write-basic.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,10 +1,8 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { let mut wtr = csv::Writer::from_writer(io::stdout()); // When writing records without Serde, the header record is written just diff -Nru rust-csv-1.0.5/examples/cookbook-write-serde.rs rust-csv-1.1.1/examples/cookbook-write-serde.rs --- rust-csv-1.0.5/examples/cookbook-write-serde.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/cookbook-write-serde.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,11 +1,9 @@ -extern crate csv; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +use serde::Serialize; + #[derive(Debug, Serialize)] struct Record { city: String, @@ -14,7 +12,7 @@ population: Option, } -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { let mut wtr = csv::Writer::from_writer(io::stdout()); // When writing records with Serde using structs, the header row is written diff -Nru rust-csv-1.0.5/examples/tutorial-error-01.rs rust-csv-1.1.1/examples/tutorial-error-01.rs --- rust-csv-1.0.5/examples/tutorial-error-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-error-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,5 +1,3 @@ -extern crate csv; - use std::io; fn main() { diff -Nru rust-csv-1.0.5/examples/tutorial-error-02.rs rust-csv-1.1.1/examples/tutorial-error-02.rs --- rust-csv-1.0.5/examples/tutorial-error-02.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-error-02.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,5 +1,3 @@ -extern crate csv; - use std::io; use std::process; diff -Nru rust-csv-1.0.5/examples/tutorial-error-03.rs rust-csv-1.1.1/examples/tutorial-error-03.rs --- rust-csv-1.0.5/examples/tutorial-error-03.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-error-03.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,5 +1,3 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; @@ -11,16 +9,16 @@ } } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.records() { // Examine our Result. // If there was no problem, print the record. - // Otherwise, convert our error to a Box and return it. + // Otherwise, convert our error to a Box and return it. match result { Err(err) => return Err(From::from(err)), Ok(record) => { - println!("{:?}", record); + println!("{:?}", record); } } } diff -Nru rust-csv-1.0.5/examples/tutorial-error-04.rs rust-csv-1.1.1/examples/tutorial-error-04.rs --- rust-csv-1.0.5/examples/tutorial-error-04.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-error-04.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,5 +1,3 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; @@ -11,7 +9,7 @@ } } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.records() { // This is effectively the same code as our `match` in the diff -Nru rust-csv-1.0.5/examples/tutorial-perf-alloc-01.rs rust-csv-1.1.1/examples/tutorial-perf-alloc-01.rs --- rust-csv-1.0.5/examples/tutorial-perf-alloc-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-perf-alloc-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,10 +1,8 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn run() -> Result> { +fn run() -> Result> { let mut rdr = csv::Reader::from_reader(io::stdin()); let mut count = 0; diff -Nru rust-csv-1.0.5/examples/tutorial-perf-alloc-02.rs rust-csv-1.1.1/examples/tutorial-perf-alloc-02.rs --- rust-csv-1.0.5/examples/tutorial-perf-alloc-02.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-perf-alloc-02.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,10 +1,8 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn run() -> Result> { +fn run() -> Result> { let mut rdr = csv::Reader::from_reader(io::stdin()); let mut count = 0; @@ -18,13 +16,13 @@ } fn main() { -match run() { -Ok(count) => { -println!("{}", count); -} -Err(err) => { -println!("{}", err); -process::exit(1); -} -} + match run() { + Ok(count) => { + println!("{}", count); + } + Err(err) => { + println!("{}", err); + process::exit(1); + } + } } diff -Nru rust-csv-1.0.5/examples/tutorial-perf-alloc-03.rs rust-csv-1.1.1/examples/tutorial-perf-alloc-03.rs --- rust-csv-1.0.5/examples/tutorial-perf-alloc-03.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-perf-alloc-03.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,10 +1,8 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn run() -> Result> { +fn run() -> Result> { let mut rdr = csv::Reader::from_reader(io::stdin()); let mut record = csv::ByteRecord::new(); @@ -18,13 +16,13 @@ } fn main() { -match run() { -Ok(count) => { -println!("{}", count); -} -Err(err) => { -println!("{}", err); -process::exit(1); -} -} + match run() { + Ok(count) => { + println!("{}", count); + } + Err(err) => { + println!("{}", err); + process::exit(1); + } + } } diff -Nru rust-csv-1.0.5/examples/tutorial-perf-core-01.rs rust-csv-1.1.1/examples/tutorial-perf-core-01.rs --- rust-csv-1.0.5/examples/tutorial-perf-core-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-perf-core-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,9 +1,7 @@ -extern crate csv_core; - use std::io::{self, Read}; use std::process; -use csv_core::{Reader, ReadFieldResult}; +use csv_core::{ReadFieldResult, Reader}; fn run(mut data: &[u8]) -> Option { let mut rdr = Reader::new(); diff -Nru rust-csv-1.0.5/examples/tutorial-perf-serde-01.rs rust-csv-1.1.1/examples/tutorial-perf-serde-01.rs --- rust-csv-1.0.5/examples/tutorial-perf-serde-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-perf-serde-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,12 +1,9 @@ -extern crate csv; -extern crate serde; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +use serde::Deserialize; + #[derive(Debug, Deserialize)] #[serde(rename_all = "PascalCase")] struct Record { @@ -19,7 +16,7 @@ longitude: f64, } -fn run() -> Result> { +fn run() -> Result> { let mut rdr = csv::Reader::from_reader(io::stdin()); let mut count = 0; diff -Nru rust-csv-1.0.5/examples/tutorial-perf-serde-02.rs rust-csv-1.1.1/examples/tutorial-perf-serde-02.rs --- rust-csv-1.0.5/examples/tutorial-perf-serde-02.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-perf-serde-02.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,12 +1,9 @@ -extern crate csv; -extern crate serde; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +use serde::Deserialize; + #[derive(Debug, Deserialize)] #[serde(rename_all = "PascalCase")] struct Record<'a> { @@ -19,7 +16,7 @@ longitude: f64, } -fn run() -> Result> { +fn run() -> Result> { let mut rdr = csv::Reader::from_reader(io::stdin()); let mut raw_record = csv::StringRecord::new(); let headers = rdr.headers()?.clone(); @@ -35,13 +32,13 @@ } fn main() { -match run() { -Ok(count) => { -println!("{}", count); -} -Err(err) => { -println!("{}", err); -process::exit(1); -} -} + match run() { + Ok(count) => { + println!("{}", count); + } + Err(err) => { + println!("{}", err); + process::exit(1); + } + } } diff -Nru rust-csv-1.0.5/examples/tutorial-perf-serde-03.rs rust-csv-1.1.1/examples/tutorial-perf-serde-03.rs --- rust-csv-1.0.5/examples/tutorial-perf-serde-03.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-perf-serde-03.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,12 +1,9 @@ -extern crate csv; -extern crate serde; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +use serde::Deserialize; + #[derive(Debug, Deserialize)] #[serde(rename_all = "PascalCase")] struct Record<'a> { @@ -19,7 +16,7 @@ longitude: f64, } -fn run() -> Result> { +fn run() -> Result> { let mut rdr = csv::Reader::from_reader(io::stdin()); let mut raw_record = csv::ByteRecord::new(); let headers = rdr.byte_headers()?.clone(); @@ -35,13 +32,13 @@ } fn main() { -match run() { -Ok(count) => { -println!("{}", count); -} -Err(err) => { -println!("{}", err); -process::exit(1); -} -} + match run() { + Ok(count) => { + println!("{}", count); + } + Err(err) => { + println!("{}", err); + process::exit(1); + } + } } diff -Nru rust-csv-1.0.5/examples/tutorial-pipeline-pop-01.rs rust-csv-1.1.1/examples/tutorial-pipeline-pop-01.rs --- rust-csv-1.0.5/examples/tutorial-pipeline-pop-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-pipeline-pop-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,13 +1,10 @@ -extern crate csv; -extern crate serde; -#[macro_use] -extern crate serde_derive; - use std::env; use std::error::Error; use std::io; use std::process; +use serde::{Deserialize, Serialize}; + // Unlike previous examples, we derive both Deserialize and Serialize. This // means we'll be able to automatically deserialize and serialize this type. #[derive(Debug, Deserialize, Serialize)] @@ -20,7 +17,7 @@ longitude: f64, } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { // Get the query from the positional arguments. // If one doesn't exist or isn't an integer, return an error. let minimum_pop: u64 = match env::args().nth(1) { diff -Nru rust-csv-1.0.5/examples/tutorial-pipeline-search-01.rs rust-csv-1.1.1/examples/tutorial-pipeline-search-01.rs --- rust-csv-1.0.5/examples/tutorial-pipeline-search-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-pipeline-search-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,11 +1,9 @@ -extern crate csv; - use std::env; use std::error::Error; use std::io; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { // Get the query from the positional arguments. // If one doesn't exist, return an error. let query = match env::args().nth(1) { diff -Nru rust-csv-1.0.5/examples/tutorial-pipeline-search-02.rs rust-csv-1.1.1/examples/tutorial-pipeline-search-02.rs --- rust-csv-1.0.5/examples/tutorial-pipeline-search-02.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-pipeline-search-02.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,11 +1,9 @@ -extern crate csv; - use std::env; use std::error::Error; use std::io; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let query = match env::args().nth(1) { None => return Err(From::from("expected 1 argument, but got none")), Some(query) => query, @@ -30,8 +28,8 @@ } fn main() { -if let Err(err) = run() { -println!("{}", err); -process::exit(1); -} + if let Err(err) = run() { + println!("{}", err); + process::exit(1); + } } diff -Nru rust-csv-1.0.5/examples/tutorial-read-01.rs rust-csv-1.1.1/examples/tutorial-read-01.rs --- rust-csv-1.0.5/examples/tutorial-read-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-read-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,12 +1,10 @@ -extern crate csv; - use std::env; use std::error::Error; use std::ffi::OsString; use std::fs::File; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let file_path = get_first_arg()?; let file = File::open(file_path)?; let mut rdr = csv::Reader::from_reader(file); @@ -19,7 +17,7 @@ /// Returns the first positional argument sent to this process. If there are no /// positional arguments, then this returns an error. -fn get_first_arg() -> Result> { +fn get_first_arg() -> Result> { match env::args_os().nth(1) { None => Err(From::from("expected 1 argument, but got none")), Some(file_path) => Ok(file_path), diff -Nru rust-csv-1.0.5/examples/tutorial-read-delimiter-01.rs rust-csv-1.1.1/examples/tutorial-read-delimiter-01.rs --- rust-csv-1.0.5/examples/tutorial-read-delimiter-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-read-delimiter-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,10 +1,8 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::ReaderBuilder::new() .has_headers(false) .delimiter(b';') @@ -21,8 +19,8 @@ } fn main() { -if let Err(err) = run() { -println!("{}", err); -process::exit(1); -} + if let Err(err) = run() { + println!("{}", err); + process::exit(1); + } } diff -Nru rust-csv-1.0.5/examples/tutorial-read-headers-01.rs rust-csv-1.1.1/examples/tutorial-read-headers-01.rs --- rust-csv-1.0.5/examples/tutorial-read-headers-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-read-headers-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,13 +1,10 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn run() -> Result<(), Box> { - let mut rdr = csv::ReaderBuilder::new() - .has_headers(false) - .from_reader(io::stdin()); +fn run() -> Result<(), Box> { + let mut rdr = + csv::ReaderBuilder::new().has_headers(false).from_reader(io::stdin()); for result in rdr.records() { let record = result?; println!("{:?}", record); @@ -16,8 +13,8 @@ } fn main() { -if let Err(err) = run() { -println!("{}", err); -process::exit(1); -} + if let Err(err) = run() { + println!("{}", err); + process::exit(1); + } } diff -Nru rust-csv-1.0.5/examples/tutorial-read-headers-02.rs rust-csv-1.1.1/examples/tutorial-read-headers-02.rs --- rust-csv-1.0.5/examples/tutorial-read-headers-02.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-read-headers-02.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,10 +1,8 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); { // We nest this call in its own scope because of lifetimes. @@ -23,8 +21,8 @@ } fn main() { -if let Err(err) = run() { -println!("{}", err); -process::exit(1); -} + if let Err(err) = run() { + println!("{}", err); + process::exit(1); + } } diff -Nru rust-csv-1.0.5/examples/tutorial-read-serde-01.rs rust-csv-1.1.1/examples/tutorial-read-serde-01.rs --- rust-csv-1.0.5/examples/tutorial-read-serde-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-read-serde-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,10 +1,8 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.records() { let record = result?; @@ -23,14 +21,15 @@ println!( "city: {:?}, state: {:?}, \ pop: {:?}, latitude: {:?}, longitude: {:?}", - city, state, pop, latitude, longitude); + city, state, pop, latitude, longitude + ); } Ok(()) } fn main() { -if let Err(err) = run() { -println!("{}", err); -process::exit(1); -} + if let Err(err) = run() { + println!("{}", err); + process::exit(1); + } } diff -Nru rust-csv-1.0.5/examples/tutorial-read-serde-02.rs rust-csv-1.1.1/examples/tutorial-read-serde-02.rs --- rust-csv-1.0.5/examples/tutorial-read-serde-02.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-read-serde-02.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,5 +1,3 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; @@ -8,7 +6,7 @@ // record type. type Record = (String, String, Option, f64, f64); -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); // Instead of creating an iterator with the `records` method, we create // an iterator with the `deserialize` method. @@ -21,8 +19,8 @@ } fn main() { -if let Err(err) = run() { -println!("{}", err); -process::exit(1); -} + if let Err(err) = run() { + println!("{}", err); + process::exit(1); + } } diff -Nru rust-csv-1.0.5/examples/tutorial-read-serde-03.rs rust-csv-1.1.1/examples/tutorial-read-serde-03.rs --- rust-csv-1.0.5/examples/tutorial-read-serde-03.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-read-serde-03.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,5 +1,3 @@ -extern crate csv; - use std::collections::HashMap; use std::error::Error; use std::io; @@ -9,7 +7,7 @@ // record type. type Record = HashMap; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.deserialize() { let record: Record = result?; @@ -19,8 +17,8 @@ } fn main() { -if let Err(err) = run() { -println!("{}", err); -process::exit(1); -} + if let Err(err) = run() { + println!("{}", err); + process::exit(1); + } } diff -Nru rust-csv-1.0.5/examples/tutorial-read-serde-04.rs rust-csv-1.1.1/examples/tutorial-read-serde-04.rs --- rust-csv-1.0.5/examples/tutorial-read-serde-04.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-read-serde-04.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,13 +1,10 @@ -extern crate csv; -extern crate serde; -// This lets us write `#[derive(Deserialize)]`. -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +// This lets us write `#[derive(Deserialize)]`. +use serde::Deserialize; + // We don't need to derive `Debug` (which doesn't require Serde), but it's a // good habit to do it for all your types. // @@ -23,7 +20,7 @@ state: String, } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.deserialize() { let record: Record = result?; diff -Nru rust-csv-1.0.5/examples/tutorial-read-serde-invalid-01.rs rust-csv-1.1.1/examples/tutorial-read-serde-invalid-01.rs --- rust-csv-1.0.5/examples/tutorial-read-serde-invalid-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-read-serde-invalid-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,11 +1,9 @@ -extern crate csv; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +use serde::Deserialize; + #[derive(Debug, Deserialize)] #[serde(rename_all = "PascalCase")] struct Record { @@ -16,7 +14,7 @@ state: String, } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.deserialize() { let record: Record = result?; @@ -26,8 +24,8 @@ } fn main() { -if let Err(err) = run() { -println!("{}", err); -process::exit(1); -} + if let Err(err) = run() { + println!("{}", err); + process::exit(1); + } } diff -Nru rust-csv-1.0.5/examples/tutorial-read-serde-invalid-02.rs rust-csv-1.1.1/examples/tutorial-read-serde-invalid-02.rs --- rust-csv-1.0.5/examples/tutorial-read-serde-invalid-02.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-read-serde-invalid-02.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,11 +1,8 @@ -extern crate csv; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +use serde::Deserialize; #[derive(Debug, Deserialize)] #[serde(rename_all = "PascalCase")] struct Record { @@ -17,7 +14,7 @@ state: String, } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.deserialize() { let record: Record = result?; @@ -27,8 +24,8 @@ } fn main() { -if let Err(err) = run() { -println!("{}", err); -process::exit(1); -} + if let Err(err) = run() { + println!("{}", err); + process::exit(1); + } } diff -Nru rust-csv-1.0.5/examples/tutorial-setup-01.rs rust-csv-1.1.1/examples/tutorial-setup-01.rs --- rust-csv-1.0.5/examples/tutorial-setup-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-setup-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,6 +1,3 @@ -// This makes the csv crate accessible to your program. -extern crate csv; - // Import the standard library's I/O module so we can read from stdin. use std::io; diff -Nru rust-csv-1.0.5/examples/tutorial-write-01.rs rust-csv-1.1.1/examples/tutorial-write-01.rs --- rust-csv-1.0.5/examples/tutorial-write-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-write-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,16 +1,26 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut wtr = csv::Writer::from_writer(io::stdout()); // Since we're writing records manually, we must explicitly write our // header record. A header record is written the same way that other // records are written. - wtr.write_record(&["City", "State", "Population", "Latitude", "Longitude"])?; - wtr.write_record(&["Davidsons Landing", "AK", "", "65.2419444", "-165.2716667"])?; + wtr.write_record(&[ + "City", + "State", + "Population", + "Latitude", + "Longitude", + ])?; + wtr.write_record(&[ + "Davidsons Landing", + "AK", + "", + "65.2419444", + "-165.2716667", + ])?; wtr.write_record(&["Kenai", "AK", "7610", "60.5544444", "-151.2583333"])?; wtr.write_record(&["Oakman", "AL", "", "33.7133333", "-87.3886111"])?; diff -Nru rust-csv-1.0.5/examples/tutorial-write-02.rs rust-csv-1.1.1/examples/tutorial-write-02.rs --- rust-csv-1.0.5/examples/tutorial-write-02.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-write-02.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,16 +1,26 @@ -extern crate csv; - use std::env; use std::error::Error; use std::ffi::OsString; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let file_path = get_first_arg()?; let mut wtr = csv::Writer::from_path(file_path)?; - wtr.write_record(&["City", "State", "Population", "Latitude", "Longitude"])?; - wtr.write_record(&["Davidsons Landing", "AK", "", "65.2419444", "-165.2716667"])?; + wtr.write_record(&[ + "City", + "State", + "Population", + "Latitude", + "Longitude", + ])?; + wtr.write_record(&[ + "Davidsons Landing", + "AK", + "", + "65.2419444", + "-165.2716667", + ])?; wtr.write_record(&["Kenai", "AK", "7610", "60.5544444", "-151.2583333"])?; wtr.write_record(&["Oakman", "AL", "", "33.7133333", "-87.3886111"])?; @@ -20,7 +30,7 @@ /// Returns the first positional argument sent to this process. If there are no /// positional arguments, then this returns an error. -fn get_first_arg() -> Result> { +fn get_first_arg() -> Result> { match env::args_os().nth(1) { None => Err(From::from("expected 1 argument, but got none")), Some(file_path) => Ok(file_path), diff -Nru rust-csv-1.0.5/examples/tutorial-write-delimiter-01.rs rust-csv-1.1.1/examples/tutorial-write-delimiter-01.rs --- rust-csv-1.0.5/examples/tutorial-write-delimiter-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-write-delimiter-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,17 +1,27 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut wtr = csv::WriterBuilder::new() .delimiter(b'\t') .quote_style(csv::QuoteStyle::NonNumeric) .from_writer(io::stdout()); - wtr.write_record(&["City", "State", "Population", "Latitude", "Longitude"])?; - wtr.write_record(&["Davidsons Landing", "AK", "", "65.2419444", "-165.2716667"])?; + wtr.write_record(&[ + "City", + "State", + "Population", + "Latitude", + "Longitude", + ])?; + wtr.write_record(&[ + "Davidsons Landing", + "AK", + "", + "65.2419444", + "-165.2716667", + ])?; wtr.write_record(&["Kenai", "AK", "7610", "60.5544444", "-151.2583333"])?; wtr.write_record(&["Oakman", "AL", "", "33.7133333", "-87.3886111"])?; @@ -20,8 +30,8 @@ } fn main() { -if let Err(err) = run() { -println!("{}", err); -process::exit(1); -} + if let Err(err) = run() { + println!("{}", err); + process::exit(1); + } } diff -Nru rust-csv-1.0.5/examples/tutorial-write-serde-01.rs rust-csv-1.1.1/examples/tutorial-write-serde-01.rs --- rust-csv-1.0.5/examples/tutorial-write-serde-01.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-write-serde-01.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,14 +1,18 @@ -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut wtr = csv::Writer::from_writer(io::stdout()); // We still need to write headers manually. - wtr.write_record(&["City", "State", "Population", "Latitude", "Longitude"])?; + wtr.write_record(&[ + "City", + "State", + "Population", + "Latitude", + "Longitude", + ])?; // But now we can write records by providing a normal Rust value. // @@ -16,7 +20,13 @@ // its own doesn't have a concrete type, but Serde needs a concrete type // in order to serialize it. That is, `None` has type `Option` but // `None::` has type `Option`. - wtr.serialize(("Davidsons Landing", "AK", None::, 65.2419444, -165.2716667))?; + wtr.serialize(( + "Davidsons Landing", + "AK", + None::, + 65.2419444, + -165.2716667, + ))?; wtr.serialize(("Kenai", "AK", Some(7610), 60.5544444, -151.2583333))?; wtr.serialize(("Oakman", "AL", None::, 33.7133333, -87.3886111))?; @@ -25,8 +35,8 @@ } fn main() { -if let Err(err) = run() { -println!("{}", err); -process::exit(1); -} + if let Err(err) = run() { + println!("{}", err); + process::exit(1); + } } diff -Nru rust-csv-1.0.5/examples/tutorial-write-serde-02.rs rust-csv-1.1.1/examples/tutorial-write-serde-02.rs --- rust-csv-1.0.5/examples/tutorial-write-serde-02.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/examples/tutorial-write-serde-02.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,12 +1,9 @@ -extern crate csv; -extern crate serde; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +use serde::Serialize; + // Note that structs can derive both Serialize and Deserialize! #[derive(Debug, Serialize)] #[serde(rename_all = "PascalCase")] @@ -18,7 +15,7 @@ longitude: f64, } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut wtr = csv::Writer::from_writer(io::stdout()); wtr.serialize(Record { diff -Nru rust-csv-1.0.5/README.md rust-csv-1.1.1/README.md --- rust-csv-1.0.5/README.md 2018-05-12 13:55:37.000000000 +0000 +++ rust-csv-1.1.1/README.md 2019-06-26 23:51:53.000000000 +0000 @@ -24,13 +24,7 @@ ```toml [dependencies] -csv = "1" -``` - -and this to your crate root: - -```rust -extern crate csv; +csv = "1.1" ``` ### Example @@ -42,13 +36,11 @@ [cookbook](https://docs.rs/csv/1.0.0/csv/cookbook/index.html). ```rust -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { // Build the CSV reader and iterate over each record. let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.records() { @@ -83,15 +75,13 @@ header record of your CSV data. ```rust -extern crate csv; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; -#[derive(Debug,Deserialize)] +use serde::Deserialize; + +#[derive(Debug, Deserialize)] struct Record { city: String, region: String, @@ -99,7 +89,7 @@ population: Option, } -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.deserialize() { // Notice that we need to provide a type hint for automatic diff -Nru rust-csv-1.0.5/rustfmt.toml rust-csv-1.1.1/rustfmt.toml --- rust-csv-1.0.5/rustfmt.toml 1970-01-01 00:00:00.000000000 +0000 +++ rust-csv-1.1.1/rustfmt.toml 2019-06-26 23:51:53.000000000 +0000 @@ -0,0 +1,2 @@ +max_width = 79 +use_small_heuristics = "max" diff -Nru rust-csv-1.0.5/src/byte_record.rs rust-csv-1.1.1/src/byte_record.rs --- rust-csv-1.0.5/src/byte_record.rs 2018-12-16 13:05:40.000000000 +0000 +++ rust-csv-1.1.1/src/byte_record.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,89 +1,15 @@ -use std::ascii; use std::cmp; use std::fmt; use std::iter::FromIterator; use std::ops::{self, Range}; use std::result; -use std::str; +use bstr::{BString, ByteSlice}; use serde::de::Deserialize; -use deserializer::deserialize_byte_record; -use error::{Result, Utf8Error, new_utf8_error}; -use string_record::StringRecord; - -/// Retrieve the underlying parts of a byte record. -#[inline] -pub fn as_parts( - record: &mut ByteRecord, -) -> (&mut Vec, &mut Vec) { - // TODO(burntsushi): Use `pub(crate)` when it stabilizes. - // (&mut record.fields, &mut record.bounds.ends) - let inner = &mut *record.0; - (&mut inner.fields, &mut inner.bounds.ends) -} - -/// Set the number of fields in the given record record. -#[inline] -pub fn set_len(record: &mut ByteRecord, len: usize) { - // TODO(burntsushi): Use `pub(crate)` when it stabilizes. - record.0.bounds.len = len; -} - -/// Expand the capacity for storing fields. -#[inline] -pub fn expand_fields(record: &mut ByteRecord) { - // TODO(burntsushi): Use `pub(crate)` when it stabilizes. - let new_len = record.0.fields.len().checked_mul(2).unwrap(); - record.0.fields.resize(cmp::max(4, new_len), 0); -} - -/// Expand the capacity for storing field ending positions. -#[inline] -pub fn expand_ends(record: &mut ByteRecord) { - // TODO(burntsushi): Use `pub(crate)` when it stabilizes. - record.0.bounds.expand(); -} - -/// Validate the given record as UTF-8. -/// -/// If it's not UTF-8, return an error. -#[inline] -pub fn validate(record: &ByteRecord) -> result::Result<(), Utf8Error> { - // TODO(burntsushi): Use `pub(crate)` when it stabilizes. - - // If the entire buffer is ASCII, then we have nothing to fear. - if record.0.fields[..record.0.bounds.end()].iter().all(|&b| b <= 0x7F) { - return Ok(()); - } - // Otherwise, we must check each field individually to ensure that - // it's valid UTF-8. - for (i, field) in record.iter().enumerate() { - if let Err(err) = str::from_utf8(field) { - return Err(new_utf8_error(i, err.valid_up_to())); - } - } - Ok(()) -} - -/// Compare the given byte record with the iterator of fields for equality. -pub fn eq(record: &ByteRecord, other: I) -> bool - where I: IntoIterator, T: AsRef<[u8]> -{ - let mut it_record = record.iter(); - let mut it_other = other.into_iter(); - loop { - match (it_record.next(), it_other.next()) { - (None, None) => return true, - (None, Some(_)) | (Some(_), None) => return false, - (Some(x), Some(y)) => { - if x != y.as_ref() { - return false; - } - } - } - } -} +use crate::deserializer::deserialize_byte_record; +use crate::error::{new_utf8_error, Result, Utf8Error}; +use crate::string_record::StringRecord; /// A single CSV record stored as raw bytes. /// @@ -118,25 +44,25 @@ impl> PartialEq> for ByteRecord { fn eq(&self, other: &Vec) -> bool { - eq(self, other) + self.iter_eq(other) } } impl<'a, T: AsRef<[u8]>> PartialEq> for &'a ByteRecord { fn eq(&self, other: &Vec) -> bool { - eq(self, other) + self.iter_eq(other) } } impl> PartialEq<[T]> for ByteRecord { fn eq(&self, other: &[T]) -> bool { - eq(self, other) + self.iter_eq(other) } } impl<'a, T: AsRef<[u8]>> PartialEq<[T]> for &'a ByteRecord { fn eq(&self, other: &[T]) -> bool { - eq(self, other) + self.iter_eq(other) } } @@ -144,11 +70,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut fields = vec![]; for field in self { - let escaped: Vec = field - .iter() - .flat_map(|&b| ascii::escape_default(b)) - .collect(); - fields.push(String::from_utf8(escaped).unwrap()); + fields.push(BString::from(field.to_vec())); } write!(f, "ByteRecord({:?})", fields) } @@ -238,12 +160,10 @@ /// deserialization. /// /// ``` - /// extern crate csv; - /// #[macro_use] - /// extern crate serde_derive; - /// /// use std::error::Error; + /// /// use csv::ByteRecord; + /// use serde::Deserialize; /// /// #[derive(Deserialize)] /// struct Row<'a> { @@ -253,7 +173,7 @@ /// } /// /// # fn main() { example().unwrap() } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let record = ByteRecord::from(vec![ /// "Boston", "United States", "4628910", /// ]); @@ -276,12 +196,10 @@ /// types (e.g., `String`) instead of borrowed data types (e.g., `&str`). /// /// ``` - /// extern crate csv; - /// #[macro_use] - /// extern crate serde_derive; - /// /// use std::error::Error; + /// /// use csv::ByteRecord; + /// use serde::Deserialize; /// /// #[derive(Deserialize)] /// struct Row { @@ -291,7 +209,7 @@ /// } /// /// # fn main() { example().unwrap() } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// // Notice that the fields are not in the same order /// // as the fields in the struct! /// let header = ByteRecord::from(vec![ @@ -444,39 +362,18 @@ /// assert_eq!(record, vec!["", "foo", "bar", "b a z"]); /// ``` pub fn trim(&mut self) { - let mut trimmed = 0; - for field in 0..self.len() { - self.0.bounds.ends[field] -= trimmed; - let bound = self.0.bounds.get(field).unwrap(); - let front_space = self.count_leading_whitespace(bound.clone()); - let back_space = - if front_space < bound.end - bound.start { - self.count_leading_whitespace(bound.clone().rev()) - } else { - 0 - }; - - self.0.fields.drain(bound.end - back_space..bound.end); - self.0.fields.drain(bound.start..bound.start + front_space); - self.0.bounds.ends[field] -= front_space + back_space; - trimmed += front_space + back_space; + let length = self.len(); + if length == 0 { + return; } - } - - /// Returns amount of leading whitespace starting in the given range. - /// Whitespace is not counted past the end of the range. - fn count_leading_whitespace(&self, range: R) -> usize - where R: Iterator - { - let mut count = 0; - for i in range { - match self.0.fields[i] { - b'\t' | b'\n' | b'\x0B' | b'\x0C' | b'\r' | b' ' => {} - _ => break, - } - count += 1; + // TODO: We could likely do this in place, but for now, we allocate. + 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()); } - count + *self = trimmed; } /// Add a new field to this record. @@ -494,7 +391,7 @@ pub fn push_field(&mut self, field: &[u8]) { let (s, e) = (self.0.bounds.end(), self.0.bounds.end() + field.len()); while e > self.0.fields.len() { - expand_fields(self); + self.expand_fields(); } self.0.fields[s..e].copy_from_slice(field); self.0.bounds.add(e); @@ -505,13 +402,12 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; + /// /// use csv::{ByteRecord, ReaderBuilder}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut record = ByteRecord::new(); /// let mut rdr = ReaderBuilder::new() /// .has_headers(false) @@ -600,6 +496,72 @@ pub fn as_slice(&self) -> &[u8] { &self.0.fields[..self.0.bounds.end()] } + + /// Retrieve the underlying parts of a byte record. + #[inline] + pub(crate) fn as_parts(&mut self) -> (&mut Vec, &mut Vec) { + let inner = &mut *self.0; + (&mut inner.fields, &mut inner.bounds.ends) + } + + /// Set the number of fields in the given record record. + #[inline] + pub(crate) fn set_len(&mut self, len: usize) { + self.0.bounds.len = len; + } + + /// Expand the capacity for storing fields. + #[inline] + pub(crate) fn expand_fields(&mut self) { + let new_len = self.0.fields.len().checked_mul(2).unwrap(); + self.0.fields.resize(cmp::max(4, new_len), 0); + } + + /// Expand the capacity for storing field ending positions. + #[inline] + pub(crate) fn expand_ends(&mut self) { + self.0.bounds.expand(); + } + + /// Validate the given record as UTF-8. + /// + /// If it's not UTF-8, return an error. + #[inline] + pub(crate) fn validate(&self) -> result::Result<(), Utf8Error> { + // If the entire buffer is ASCII, then we have nothing to fear. + if self.0.fields[..self.0.bounds.end()].is_ascii() { + return Ok(()); + } + // 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() { + return Err(new_utf8_error(i, err.valid_up_to())); + } + } + Ok(()) + } + + /// Compare the given byte record with the iterator of fields for equality. + pub(crate) fn iter_eq(&self, other: I) -> bool + where + I: IntoIterator, + T: AsRef<[u8]>, + { + let mut it_record = self.iter(); + let mut it_other = other.into_iter(); + loop { + match (it_record.next(), it_other.next()) { + (None, None) => return true, + (None, Some(_)) | (Some(_), None) => return false, + (Some(x), Some(y)) => { + if x != y.as_ref() { + return false; + } + } + } + } + } } /// A position in CSV data. @@ -625,11 +587,20 @@ } /// The byte offset, starting at `0`, of this position. - #[inline] pub fn byte(&self) -> u64 { self.byte } + #[inline] + pub fn byte(&self) -> u64 { + self.byte + } /// The line number, starting at `1`, of this position. - #[inline] pub fn line(&self) -> u64 { self.line } + #[inline] + pub fn line(&self) -> u64 { + self.line + } /// The record index, starting with the first record at `0`. - #[inline] pub fn record(&self) -> u64 { self.record } + #[inline] + pub fn record(&self) -> u64 { + self.record + } /// Set the byte offset of this position. #[inline] @@ -742,12 +713,16 @@ impl ops::Index for ByteRecord { type Output = [u8]; #[inline] - fn index(&self, i: usize) -> &[u8] { self.get(i).unwrap() } + fn index(&self, i: usize) -> &[u8] { + self.get(i).unwrap() + } } impl From for ByteRecord { #[inline] - fn from(record: StringRecord) -> ByteRecord { record.into_byte_record() } + fn from(record: StringRecord) -> ByteRecord { + record.into_byte_record() + } } impl> From> for ByteRecord { @@ -766,7 +741,7 @@ impl> FromIterator for ByteRecord { #[inline] - fn from_iter>(iter: I) -> ByteRecord { + fn from_iter>(iter: I) -> ByteRecord { let mut record = ByteRecord::new(); record.extend(iter); record @@ -775,7 +750,7 @@ impl> Extend for ByteRecord { #[inline] - fn extend>(&mut self, iter: I) { + fn extend>(&mut self, iter: I) { for x in iter { self.push_field(x.as_ref()); } @@ -852,7 +827,8 @@ None } else { self.i_reverse -= 1; - let start = self.i_reverse + let start = self + .i_reverse .checked_sub(1) .map(|i| self.r.0.bounds.ends()[i]) .unwrap_or(0); @@ -865,11 +841,13 @@ #[cfg(test)] mod tests { - use string_record::StringRecord; + use crate::string_record::StringRecord; use super::ByteRecord; - fn b(s: &str) -> &[u8] { s.as_bytes() } + fn b(s: &str) -> &[u8] { + s.as_bytes() + } #[test] fn record_1() { @@ -1115,9 +1093,8 @@ fn iter() { let data = vec!["foo", "bar", "baz", "quux", "wat"]; let rec = ByteRecord::from(&*data); - let got: Vec<&str> = rec.iter() - .map(|x| ::std::str::from_utf8(x).unwrap()) - .collect(); + let got: Vec<&str> = + rec.iter().map(|x| ::std::str::from_utf8(x).unwrap()).collect(); assert_eq!(data, got); } @@ -1125,7 +1102,8 @@ fn iter_reverse() { let mut data = vec!["foo", "bar", "baz", "quux", "wat"]; let rec = ByteRecord::from(&*data); - let got: Vec<&str> = rec.iter() + let got: Vec<&str> = rec + .iter() .rev() .map(|x| ::std::str::from_utf8(x).unwrap()) .collect(); @@ -1153,8 +1131,8 @@ // Regression test for #138. #[test] fn eq_field_boundaries() { - let test1 = ByteRecord::from(vec!["12","34"]); - let test2 = ByteRecord::from(vec!["123","4"]); + let test1 = ByteRecord::from(vec!["12", "34"]); + let test2 = ByteRecord::from(vec!["123", "4"]); assert_ne!(test1, test2); } @@ -1164,8 +1142,8 @@ // Regression test for #138. #[test] fn eq_record_len() { - let test1 = ByteRecord::from(vec!["12","34", "56"]); - let test2 = ByteRecord::from(vec!["12","34"]); + let test1 = ByteRecord::from(vec!["12", "34", "56"]); + let test2 = ByteRecord::from(vec!["12", "34"]); assert_ne!(test1, test2); } } diff -Nru rust-csv-1.0.5/src/cookbook.rs rust-csv-1.1.1/src/cookbook.rs --- rust-csv-1.0.5/src/cookbook.rs 2018-07-18 23:46:48.000000000 +0000 +++ rust-csv-1.1.1/src/cookbook.rs 2019-06-26 23:51:53.000000000 +0000 @@ -31,13 +31,11 @@ ```no_run # //cookbook-read-basic.rs -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { // Build the CSV reader and iterate over each record. let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.records() { @@ -76,17 +74,15 @@ ```no_run # //cookbook-read-serde.rs -extern crate csv; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +use serde::Deserialize; + // By default, struct field names are deserialized based on the position of // a corresponding field in the CSV data's header record. -#[derive(Debug,Deserialize)] +#[derive(Debug, Deserialize)] struct Record { city: String, region: String, @@ -94,7 +90,7 @@ population: Option, } -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.deserialize() { // Notice that we need to provide a type hint for automatic @@ -128,13 +124,11 @@ ```no_run # //cookbook-read-colon.rs -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { let mut rdr = csv::ReaderBuilder::new() .delimiter(b':') .from_reader(io::stdin()); @@ -170,13 +164,11 @@ ```no_run # //cookbook-read-no-headers.rs -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { let mut rdr = csv::ReaderBuilder::new() .has_headers(false) .from_reader(io::stdin()); @@ -209,13 +201,11 @@ ```no_run # //cookbook-write-basic.rs -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { let mut wtr = csv::Writer::from_writer(io::stdout()); // When writing records without Serde, the header record is written just @@ -251,14 +241,12 @@ ```no_run # //cookbook-write-serde.rs -extern crate csv; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +use serde::Serialize; + #[derive(Debug, Serialize)] struct Record { city: String, @@ -267,7 +255,7 @@ population: Option, } -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { let mut wtr = csv::Writer::from_writer(io::stdout()); // When writing records with Serde using structs, the header row is written diff -Nru rust-csv-1.0.5/src/deserializer.rs rust-csv-1.1.1/src/deserializer.rs --- rust-csv-1.0.5/src/deserializer.rs 2018-12-15 15:15:18.000000000 +0000 +++ rust-csv-1.1.1/src/deserializer.rs 2019-07-01 15:46:38.000000000 +0000 @@ -1,19 +1,20 @@ -use std::error::{Error as StdError}; +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::{ - Deserializer, DeserializeSeed, Deserialize, IntoDeserializer, - Error as SerdeError, Unexpected, - Visitor, EnumAccess, VariantAccess, MapAccess, SeqAccess, + Deserialize, DeserializeSeed, Deserializer, EnumAccess, + Error as SerdeError, IntoDeserializer, MapAccess, SeqAccess, Unexpected, + VariantAccess, Visitor, }; -use serde::de::value::BorrowedBytesDeserializer; +use serde::serde_if_integer128; -use byte_record::{ByteRecord, ByteRecordIter}; -use error::{Error, ErrorKind, new_error}; -use string_record::{StringRecord, StringRecordIter}; +use crate::byte_record::{ByteRecord, ByteRecordIter}; +use crate::error::{Error, ErrorKind}; +use crate::string_record::{StringRecord, StringRecordIter}; use self::DeserializeErrorKind as DEK; @@ -27,7 +28,7 @@ field: 0, }); D::deserialize(&mut deser).map_err(|err| { - new_error(ErrorKind::Deserialize { + Error::new(ErrorKind::Deserialize { pos: record.position().map(Clone::clone), err: err, }) @@ -44,7 +45,7 @@ field: 0, }); D::deserialize(&mut deser).map_err(|err| { - new_error(ErrorKind::Deserialize { + Error::new(ErrorKind::Deserialize { pos: record.position().map(Clone::clone), err: err, }) @@ -181,7 +182,7 @@ None => Err(DeserializeError { field: None, kind: DEK::UnexpectedEndOfRow, - }) + }), } } @@ -208,14 +209,22 @@ ) -> Result { let x = self.next_field()?; if x == "true" { - visitor.visit_bool(true) + return visitor.visit_bool(true); } else if x == "false" { - visitor.visit_bool(false) - } else if let Some(n) = try_positive_integer(x) { - visitor.visit_u64(n) - } else if let Some(n) = try_negative_integer(x) { - visitor.visit_i64(n) - } else if let Some(n) = try_float(x) { + return visitor.visit_bool(false); + } else if let Some(n) = try_positive_integer64(x) { + return visitor.visit_u64(n); + } else if let Some(n) = try_negative_integer64(x) { + return visitor.visit_i64(n); + } + serde_if_integer128! { + if let Some(n) = try_positive_integer128(x) { + return visitor.visit_u128(n); + } else if let Some(n) = try_negative_integer128(x) { + return visitor.visit_i128(n); + } + } + if let Some(n) = try_float(x) { visitor.visit_f64(n) } else { visitor.visit_str(x) @@ -238,9 +247,10 @@ #[inline] fn next_header(&mut self) -> Result, DeserializeError> { match self.next_header_bytes() { - Ok(Some(field)) => Ok(Some(str::from_utf8(field).map_err(|err| { - self.error(DEK::InvalidUtf8(err)) - })?)), + Ok(Some(field)) => Ok(Some( + str::from_utf8(field) + .map_err(|err| self.error(DEK::InvalidUtf8(err)))?, + )), Ok(None) => Ok(None), Err(err) => Err(err), } @@ -256,9 +266,8 @@ #[inline] fn next_field(&mut self) -> Result<&'r str, DeserializeError> { self.next_field_bytes().and_then(|field| { - str::from_utf8(field).map_err(|err| { - self.error(DEK::InvalidUtf8(err)) - }) + str::from_utf8(field) + .map_err(|err| self.error(DEK::InvalidUtf8(err))) }) } @@ -272,7 +281,7 @@ None => Err(DeserializeError { field: None, kind: DEK::UnexpectedEndOfRow, - }) + }), } } @@ -294,14 +303,22 @@ ) -> Result { let x = self.next_field_bytes()?; if x == b"true" { - visitor.visit_bool(true) + return visitor.visit_bool(true); } else if x == b"false" { - visitor.visit_bool(false) - } else if let Some(n) = try_positive_integer_bytes(x) { - visitor.visit_u64(n) - } else if let Some(n) = try_negative_integer_bytes(x) { - visitor.visit_i64(n) - } else if let Some(n) = try_float_bytes(x) { + return visitor.visit_bool(false); + } else if let Some(n) = try_positive_integer64_bytes(x) { + return visitor.visit_u64(n); + } else if let Some(n) = try_negative_integer64_bytes(x) { + return visitor.visit_i64(n); + } + serde_if_integer128! { + if let Some(n) = try_positive_integer128_bytes(x) { + return visitor.visit_u128(n); + } else if let Some(n) = try_negative_integer128_bytes(x) { + return visitor.visit_i128(n); + } + } + if let Some(n) = try_float_bytes(x) { visitor.visit_f64(n) } else if let Ok(s) = str::from_utf8(x) { visitor.visit_str(s) @@ -312,14 +329,19 @@ } macro_rules! deserialize_int { - ($method:ident, $visit:ident) => { + ($method:ident, $visit:ident, $inttype:ty) => { fn $method>( self, visitor: V, ) -> Result { - visitor.$visit( - self.next_field()? - .parse().map_err(|err| self.error(DEK::ParseInt(err)))?) + let field = self.next_field()?; + let num = + if field.starts_with("0x") { + <$inttype>::from_str_radix(&field[2..], 16) + } else { + field.parse() + }; + visitor.$visit(num.map_err(|err| self.error(DEK::ParseInt(err)))?) } } } @@ -342,25 +364,35 @@ ) -> Result { visitor.visit_bool( self.next_field()? - .parse().map_err(|err| self.error(DEK::ParseBool(err)))?) + .parse() + .map_err(|err| self.error(DEK::ParseBool(err)))?, + ) + } + + deserialize_int!(deserialize_u8, visit_u8, u8); + deserialize_int!(deserialize_u16, visit_u16, u16); + deserialize_int!(deserialize_u32, visit_u32, u32); + deserialize_int!(deserialize_u64, visit_u64, u64); + serde_if_integer128! { + deserialize_int!(deserialize_u128, visit_u128, u128); + } + deserialize_int!(deserialize_i8, visit_i8, i8); + deserialize_int!(deserialize_i16, visit_i16, i16); + deserialize_int!(deserialize_i32, visit_i32, i32); + deserialize_int!(deserialize_i64, visit_i64, i64); + serde_if_integer128! { + deserialize_int!(deserialize_i128, visit_i128, i128); } - deserialize_int!(deserialize_u8, visit_u8); - deserialize_int!(deserialize_u16, visit_u16); - deserialize_int!(deserialize_u32, visit_u32); - deserialize_int!(deserialize_u64, visit_u64); - deserialize_int!(deserialize_i8, visit_i8); - deserialize_int!(deserialize_i16, visit_i16); - deserialize_int!(deserialize_i32, visit_i32); - deserialize_int!(deserialize_i64, visit_i64); - fn deserialize_f32>( self, visitor: V, ) -> Result { visitor.visit_f32( self.next_field()? - .parse().map_err(|err| self.error(DEK::ParseFloat(err)))?) + .parse() + .map_err(|err| self.error(DEK::ParseFloat(err)))?, + ) } fn deserialize_f64>( @@ -369,7 +401,9 @@ ) -> Result { visitor.visit_f64( self.next_field()? - .parse().map_err(|err| self.error(DEK::ParseFloat(err)))?) + .parse() + .map_err(|err| self.error(DEK::ParseFloat(err)))?, + ) } fn deserialize_char>( @@ -381,7 +415,8 @@ if len != 1 { return Err(self.error(DEK::Message(format!( "expected single character but got {} characters in '{}'", - len, field)))); + len, field + )))); } visitor.visit_char(field.chars().next().unwrap()) } @@ -404,9 +439,7 @@ self, visitor: V, ) -> Result { - self.next_field_bytes().and_then(|f| { - visitor.visit_borrowed_bytes(f) - }) + self.next_field_bytes().and_then(|f| visitor.visit_borrowed_bytes(f)) } fn deserialize_byte_buf>( @@ -545,8 +578,8 @@ } } -impl<'a, 'de: 'a, T: DeRecord<'de>> - VariantAccess<'de> for &'a mut DeRecordWrap +impl<'a, 'de: 'a, T: DeRecord<'de>> VariantAccess<'de> + for &'a mut DeRecordWrap { type Error = DeserializeError; @@ -581,8 +614,8 @@ } } -impl<'a, 'de: 'a, T: DeRecord<'de>> - SeqAccess<'de> for &'a mut DeRecordWrap +impl<'a, 'de: 'a, T: DeRecord<'de>> SeqAccess<'de> + for &'a mut DeRecordWrap { type Error = DeserializeError; @@ -598,8 +631,8 @@ } } -impl<'a, 'de: 'a, T: DeRecord<'de>> - MapAccess<'de> for &'a mut DeRecordWrap +impl<'a, 'de: 'a, T: DeRecord<'de>> MapAccess<'de> + for &'a mut DeRecordWrap { type Error = DeserializeError; @@ -654,10 +687,7 @@ impl SerdeError for DeserializeError { fn custom(msg: T) -> DeserializeError { - DeserializeError { - field: None, - kind: DEK::Message(msg.to_string()), - } + DeserializeError { field: None, kind: DEK::Message(msg.to_string()) } } } @@ -723,11 +753,21 @@ } } -fn try_positive_integer(s: &str) -> Option { +serde_if_integer128! { + fn try_positive_integer128(s: &str) -> Option { + s.parse().ok() + } + + fn try_negative_integer128(s: &str) -> Option { + s.parse().ok() + } +} + +fn try_positive_integer64(s: &str) -> Option { s.parse().ok() } -fn try_negative_integer(s: &str) -> Option { +fn try_negative_integer64(s: &str) -> Option { s.parse().ok() } @@ -735,14 +775,24 @@ s.parse().ok() } -fn try_positive_integer_bytes(s: &[u8]) -> Option { +fn try_positive_integer64_bytes(s: &[u8]) -> Option { str::from_utf8(s).ok().and_then(|s| s.parse().ok()) } -fn try_negative_integer_bytes(s: &[u8]) -> Option { +fn try_negative_integer64_bytes(s: &[u8]) -> Option { str::from_utf8(s).ok().and_then(|s| s.parse().ok()) } +serde_if_integer128! { + fn try_positive_integer128_bytes(s: &[u8]) -> Option { + str::from_utf8(s).ok().and_then(|s| s.parse().ok()) + } + + fn try_negative_integer128_bytes(s: &[u8]) -> Option { + str::from_utf8(s).ok().and_then(|s| s.parse().ok()) + } +} + fn try_float_bytes(s: &[u8]) -> Option { str::from_utf8(s).ok().and_then(|s| s.parse().ok()) } @@ -751,17 +801,15 @@ mod tests { use std::collections::HashMap; - use serde::de::DeserializeOwned; - use serde_bytes::{self, ByteBuf}; + use bstr::BString; + use serde::{de::DeserializeOwned, serde_if_integer128, Deserialize}; - use byte_record::ByteRecord; - use error::Error; - use 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 { + fn de(fields: &[&str]) -> Result { let record = StringRecord::from(fields); deserialize_string_record(&record, None) } @@ -788,10 +836,8 @@ x: String, } - let got: Foo = de_headers( - &["x", "y", "z"], - &["hi", "42", "1.3"], - ).unwrap(); + let got: Foo = + de_headers(&["x", "y", "z"], &["hi", "42", "1.3"]).unwrap(); assert_eq!(got, Foo { x: "hi".into(), y: 42, z: 1.3 }); } @@ -807,7 +853,8 @@ assert!(de_headers::( &["a", "x", "y", "z"], &["foo", "hi", "42", "1.3"], - ).is_err()); + ) + .is_err()); } #[test] @@ -818,10 +865,7 @@ y: i32, x: String, } - assert!(de_headers::( - &["y", "z"], - &["42", "1.3"], - ).is_err()); + assert!(de_headers::(&["y", "z"], &["42", "1.3"],).is_err()); } #[test] @@ -833,10 +877,7 @@ x: Option, } - let got: Foo = de_headers( - &["y", "z"], - &["42", "1.3"], - ).unwrap(); + let got: Foo = de_headers(&["y", "z"], &["42", "1.3"]).unwrap(); assert_eq!(got, Foo { x: None, y: 42, z: 1.3 }); } @@ -878,7 +919,7 @@ assert_eq!(got.unwrap(), Foo); let got = de_headers::(&[], &[]); - assert_eq!(got.unwrap(), Bar{}); + assert_eq!(got.unwrap(), Bar {}); let got = de_headers::<()>(&[], &[]); assert_eq!(got.unwrap(), ()); @@ -908,6 +949,14 @@ assert_eq!(got, 42); } + serde_if_integer128! { + #[test] + fn one_field_128() { + let got: i128 = de(&["2010223372036854775808"]).unwrap(); + assert_eq!(got, 2010223372036854775808); + } + } + #[test] fn two_fields() { let got: (i32, bool) = de(&["42", "true"]).unwrap(); @@ -954,6 +1003,23 @@ } #[test] + fn simple_hex_seq() { + let got: Vec = de(&["0x7F", "0xA9", "0x10"]).unwrap(); + assert_eq!(got, vec![0x7F, 0xA9, 0x10]); + } + + #[test] + fn mixed_hex_seq() { + let got: Vec = de(&["0x7F", "0xA9", "10"]).unwrap(); + assert_eq!(got, vec![0x7F, 0xA9, 10]); + } + + #[test] + fn bad_hex_seq() { + assert!(de::>(&["7F", "0xA9", "10"]).is_err()); + } + + #[test] fn seq_in_struct() { #[derive(Deserialize, Debug, PartialEq)] struct Foo { @@ -992,7 +1058,7 @@ #[test] fn bytes() { - let got: Vec = de::(&["foobar"]).unwrap().into(); + let got: Vec = de::(&["foobar"]).unwrap().into(); assert_eq!(got, b"foobar".to_vec()); } @@ -1040,15 +1106,16 @@ String(String), } - let got: Row = de_headers( - &["x", "y", "z"], - &["true", "null", "1"], - ).unwrap(); - assert_eq!(got, Row { - x: Boolish::Bool(true), - y: Boolish::String("null".into()), - z: Boolish::Number(1), - }); + let got: Row = + de_headers(&["x", "y", "z"], &["true", "null", "1"]).unwrap(); + assert_eq!( + got, + Row { + x: Boolish::Bool(true), + y: Boolish::String("null".into()), + z: Boolish::Number(1), + } + ); } #[test] @@ -1060,10 +1127,8 @@ c: Option, } - let got: Foo = de_headers( - &["a", "b", "c"], - &["", "foo", "5"], - ).unwrap(); + let got: Foo = + de_headers(&["a", "b", "c"], &["", "foo", "5"]).unwrap(); assert_eq!(got, Foo { a: None, b: "foo".into(), c: Some(5) }); } @@ -1071,18 +1136,16 @@ fn option_invalid_field() { #[derive(Deserialize, Debug, PartialEq)] struct Foo { - #[serde(deserialize_with = "::invalid_option")] + #[serde(deserialize_with = "crate::invalid_option")] a: Option, - #[serde(deserialize_with = "::invalid_option")] + #[serde(deserialize_with = "crate::invalid_option")] b: Option, - #[serde(deserialize_with = "::invalid_option")] + #[serde(deserialize_with = "crate::invalid_option")] c: Option, } - let got: Foo = de_headers( - &["a", "b", "c"], - &["xyz", "", "5"], - ).unwrap(); + let got: Foo = + de_headers(&["a", "b", "c"], &["xyz", "", "5"]).unwrap(); assert_eq!(got, Foo { a: None, b: None, c: Some(5) }); } @@ -1097,8 +1160,8 @@ let headers = StringRecord::from(vec!["a", "b", "c"]); let record = StringRecord::from(vec!["foo", "5", "bar"]); - let got: Foo = deserialize_string_record( - &record, Some(&headers)).unwrap(); + let got: Foo = + deserialize_string_record(&record, Some(&headers)).unwrap(); assert_eq!(got, Foo { a: "foo", b: 5, c: "bar" }); } @@ -1108,13 +1171,11 @@ let headers = StringRecord::from(vec!["a", "b", "c"]); let record = StringRecord::from(vec!["aardvark", "bee", "cat"]); - let got: HashMap<&str, &str> = deserialize_string_record( - &record, Some(&headers)).unwrap(); + let got: HashMap<&str, &str> = + deserialize_string_record(&record, Some(&headers)).unwrap(); - let expected: HashMap<&str, &str> = headers - .iter() - .zip(&record) - .collect(); + let expected: HashMap<&str, &str> = + headers.iter().zip(&record).collect(); assert_eq!(got, expected); } @@ -1124,13 +1185,11 @@ let headers = ByteRecord::from(vec![b"a", b"\xFF", b"c"]); let record = ByteRecord::from(vec!["aardvark", "bee", "cat"]); - let got: HashMap<&[u8], &[u8]> = deserialize_byte_record( - &record, Some(&headers)).unwrap(); + let got: HashMap<&[u8], &[u8]> = + deserialize_byte_record(&record, Some(&headers)).unwrap(); - let expected: HashMap<&[u8], &[u8]> = headers - .iter() - .zip(&record) - .collect(); + let expected: HashMap<&[u8], &[u8]> = + headers.iter().zip(&record).collect(); assert_eq!(got, expected); } @@ -1159,10 +1218,13 @@ let header = StringRecord::from(vec!["x", "y", "prop1", "prop2"]); let record = StringRecord::from(vec!["1", "2", "3", "4"]); let got: Row = record.deserialize(Some(&header)).unwrap(); - assert_eq!(got, Row { - input: Input { x: 1.0, y: 2.0 }, - properties: Properties { prop1: 3.0, prop2: 4.0 }, - }); + assert_eq!( + got, + Row { + input: Input { x: 1.0, y: 2.0 }, + properties: Properties { prop1: 3.0, prop2: 4.0 }, + } + ); } #[test] @@ -1170,22 +1232,22 @@ #[derive(Debug, Deserialize, PartialEq)] struct Row { h1: String, - #[serde(with = "serde_bytes")] - h2: Vec, + h2: BString, h3: String, } let headers = ByteRecord::from(vec![b"h1", b"h2", b"h3"]); - let record = ByteRecord::from(vec![ - b(b"baz"), b(b"foo\xFFbar"), b(b"quux"), - ]); - let got: Row = deserialize_byte_record( - &record, Some(&headers), - ).unwrap(); - assert_eq!(got, Row { - h1: "baz".to_string(), - h2: b"foo\xFFbar".to_vec(), - h3: "quux".to_string(), - }); + let record = + ByteRecord::from(vec![b(b"baz"), b(b"foo\xFFbar"), b(b"quux")]); + let got: Row = + deserialize_byte_record(&record, Some(&headers)).unwrap(); + assert_eq!( + got, + Row { + h1: "baz".to_string(), + h2: BString::from(b"foo\xFFbar".to_vec()), + h3: "quux".to_string(), + } + ); } } diff -Nru rust-csv-1.0.5/src/error.rs rust-csv-1.1.1/src/error.rs --- rust-csv-1.0.5/src/error.rs 2017-07-13 14:35:12.000000000 +0000 +++ rust-csv-1.1.1/src/error.rs 2019-06-26 23:51:53.000000000 +0000 @@ -2,16 +2,9 @@ use std::fmt; use std::io; use std::result; -use std::str; -use byte_record::{ByteRecord, Position}; -use deserializer::DeserializeError; - -/// A crate private constructor for `Error`. -pub fn new_error(kind: ErrorKind) -> Error { - // TODO(burntsushi): Use `pub(crate)` when it stabilizes. - Error(Box::new(kind)) -} +use crate::byte_record::{ByteRecord, Position}; +use crate::deserializer::DeserializeError; /// A type alias for `Result`. pub type Result = result::Result; @@ -28,6 +21,11 @@ pub struct Error(Box); impl Error { + /// A crate private constructor for `Error`. + pub(crate) fn new(kind: ErrorKind) -> Error { + Error(Box::new(kind)) + } + /// Return the specific type of this error. pub fn kind(&self) -> &ErrorKind { &self.0 @@ -48,6 +46,14 @@ _ => false, } } + + /// Return the position for this error, if one exists. + /// + /// This is a convenience function that permits callers to easily access + /// the position on an error without doing case analysis on `ErrorKind`. + pub fn position(&self) -> Option<&Position> { + self.0.position() + } } /// The specific type of an error. @@ -101,9 +107,24 @@ __Nonexhaustive, } +impl ErrorKind { + /// Return the position for this error, if one exists. + /// + /// This is a convenience function that permits callers to easily access + /// the position on an error without doing case analysis on `ErrorKind`. + pub fn position(&self) -> Option<&Position> { + match *self { + ErrorKind::Utf8 { ref pos, .. } => pos.as_ref(), + ErrorKind::UnequalLengths { ref pos, .. } => pos.as_ref(), + ErrorKind::Deserialize { ref pos, .. } => pos.as_ref(), + _ => None, + } + } +} + impl From for Error { fn from(err: io::Error) -> Error { - new_error(ErrorKind::Io(err)) + Error::new(ErrorKind::Io(err)) } } @@ -114,23 +135,11 @@ } impl StdError for Error { - fn description(&self) -> &str { - match *self.0 { - ErrorKind::Io(ref err) => err.description(), - ErrorKind::Utf8 { ref err, .. } => err.description(), - ErrorKind::UnequalLengths{..} => "record of different length found", - ErrorKind::Seek => "headers unavailable on seeked CSV reader", - ErrorKind::Serialize(ref err) => err, - ErrorKind::Deserialize { ref err, .. } => err.description(), - _ => unreachable!(), - } - } - - fn cause(&self) -> Option<&StdError> { + 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::UnequalLengths { .. } => None, ErrorKind::Seek => None, ErrorKind::Serialize(_) => None, ErrorKind::Deserialize { ref err, .. } => Some(err), @@ -146,47 +155,61 @@ ErrorKind::Utf8 { pos: None, ref err } => { write!(f, "CSV parse error: field {}: {}", err.field(), err) } - ErrorKind::Utf8 { pos: Some(ref pos), ref err } => { - write!( - f, - "CSV parse error: record {} \ - (line {}, field: {}, byte: {}): {}", - pos.record(), pos.line(), err.field(), pos.byte(), err) - } + ErrorKind::Utf8 { pos: Some(ref pos), ref err } => write!( + f, + "CSV parse error: record {} \ + (line {}, field: {}, byte: {}): {}", + pos.record(), + pos.line(), + err.field(), + pos.byte(), + err + ), ErrorKind::UnequalLengths { pos: None, expected_len, len } => { write!( - f, "CSV error: \ - found record with {} fields, but the previous record \ - has {} fields", - len, expected_len) + f, + "CSV error: \ + found record with {} fields, but the previous record \ + has {} fields", + len, expected_len + ) } ErrorKind::UnequalLengths { - pos: Some(ref pos), expected_len, len - } => { - write!( - f, "CSV error: record {} (line: {}, byte: {}): \ - found record with {} fields, but the previous record \ - has {} fields", - pos.record(), pos.line(), pos.byte(), len, expected_len) - } - ErrorKind::Seek => { - write!(f, "CSV error: cannot access headers of CSV data \ - when the parser was seeked before the first record \ - could be read") - } + pos: Some(ref pos), + expected_len, + len, + } => write!( + f, + "CSV error: record {} (line: {}, byte: {}): \ + found record with {} fields, but the previous record \ + has {} fields", + pos.record(), + pos.line(), + pos.byte(), + len, + expected_len + ), + ErrorKind::Seek => write!( + f, + "CSV error: cannot access headers of CSV data \ + when the parser was seeked before the first record \ + could be read" + ), ErrorKind::Serialize(ref err) => { write!(f, "CSV write error: {}", err) } ErrorKind::Deserialize { pos: None, ref err } => { write!(f, "CSV deserialize error: {}", err) } - ErrorKind::Deserialize { pos: Some(ref pos), ref err } => { - write!( - f, - "CSV deserialize error: record {} \ - (line: {}, byte: {}): {}", - pos.record(), pos.line(), pos.byte(), err) - } + ErrorKind::Deserialize { pos: Some(ref pos), ref err } => write!( + f, + "CSV deserialize error: record {} \ + (line: {}, byte: {}): {}", + pos.record(), + pos.line(), + pos.byte(), + err + ), _ => unreachable!(), } } @@ -202,12 +225,12 @@ err: Utf8Error, } -/// Create a new FromUtf8Error. -pub fn new_from_utf8_error(rec: ByteRecord, err: Utf8Error) -> FromUtf8Error { - FromUtf8Error { record: rec, err: err } -} - impl FromUtf8Error { + /// Create a new FromUtf8Error. + pub(crate) fn new(rec: ByteRecord, err: Utf8Error) -> FromUtf8Error { + FromUtf8Error { record: rec, err: err } + } + /// Access the underlying `ByteRecord` that failed UTF-8 validation. pub fn into_byte_record(self) -> ByteRecord { self.record @@ -226,8 +249,9 @@ } impl StdError for FromUtf8Error { - fn description(&self) -> &str { self.err.description() } - fn cause(&self) -> Option<&StdError> { Some(&self.err) } + fn source(&self) -> Option<&(dyn StdError + 'static)> { + Some(&self.err) + } } /// A UTF-8 validation error. @@ -252,22 +276,24 @@ impl Utf8Error { /// The field index of a byte record in which UTF-8 validation failed. - pub fn field(&self) -> usize { self.field } + pub fn field(&self) -> usize { + self.field + } /// The index into the given field up to which valid UTF-8 was verified. - pub fn valid_up_to(&self) -> usize { self.valid_up_to } + pub fn valid_up_to(&self) -> usize { + self.valid_up_to + } } -impl StdError for Utf8Error { - fn description(&self) -> &str { "invalid utf-8 in CSV record" } -} +impl StdError for Utf8Error {} impl fmt::Display for Utf8Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "invalid utf-8: invalid UTF-8 in field {} near byte index {}", - self.field, - self.valid_up_to) + self.field, self.valid_up_to + ) } } @@ -283,15 +309,15 @@ err: io::Error, } -/// Creates a new `IntoInnerError`. -/// -/// (This is a visibility hack. It's public in this module, but not in the -/// crate.) -pub fn new_into_inner_error(wtr: W, err: io::Error) -> IntoInnerError { - IntoInnerError { wtr: wtr, err: err } -} - impl IntoInnerError { + /// Creates a new `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 } + } + /// Returns the error which caused the call to `into_inner` to fail. /// /// This error was returned when attempting to flush the internal buffer. @@ -308,13 +334,9 @@ } } -impl StdError for IntoInnerError { - fn description(&self) -> &str { - self.err.description() - } - - fn cause(&self) -> Option<&StdError> { - self.err.cause() +impl StdError for IntoInnerError { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + self.err.source() } } diff -Nru rust-csv-1.0.5/src/lib.rs rust-csv-1.1.1/src/lib.rs --- rust-csv-1.0.5/src/lib.rs 2018-05-12 13:55:32.000000000 +0000 +++ rust-csv-1.1.1/src/lib.rs 2019-06-26 23:51:53.000000000 +0000 @@ -34,7 +34,7 @@ For data that may be invalid UTF-8, `ByteRecord` is suitable. Finally, the set of errors is described by the -[`Error`](enum.Error.html) +[`Error`](struct.Error.html) type. The rest of the types in this crate mostly correspond to more detailed errors, @@ -46,13 +46,7 @@ ```toml [dependencies] -csv = "1" -``` - -and this to your crate root: - -```rust -extern crate csv; +csv = "1.1" ``` If you want to use Serde's custom derive functionality on your custom structs, @@ -60,16 +54,7 @@ ```toml [dependencies] -serde = "1" -serde_derive = "1" -``` - -and this to your crate root: - -```ignore -extern crate serde; -#[macro_use] -extern crate serde_derive; +serde = { version = "1", features = ["derive"] } ``` # Example @@ -80,13 +65,11 @@ There are more examples in the [cookbook](cookbook/index.html). ```no_run -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { // Build the CSV reader and iterate over each record. let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.records() { @@ -121,15 +104,13 @@ header record of your CSV data. ```no_run -extern crate csv; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; -#[derive(Debug,Deserialize)] +use serde::Deserialize; + +#[derive(Debug, Deserialize)] struct Record { city: String, region: String, @@ -137,7 +118,7 @@ population: Option, } -fn example() -> Result<(), Box> { +fn example() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.deserialize() { // Notice that we need to provide a type hint for automatic @@ -168,36 +149,27 @@ #![deny(missing_docs)] -extern crate csv_core; -extern crate serde; -#[cfg(test)] -extern crate serde_bytes; -#[cfg(test)] -#[macro_use] -extern crate serde_derive; - use std::result; use serde::{Deserialize, Deserializer}; -pub use byte_record::{ByteRecord, ByteRecordIter, Position}; -pub use deserializer::{DeserializeError, DeserializeErrorKind}; -pub use error::{ +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 reader::{ - Reader, ReaderBuilder, - DeserializeRecordsIntoIter, DeserializeRecordsIter, - StringRecordsIntoIter, StringRecordsIter, - ByteRecordsIntoIter, ByteRecordsIter, +pub use crate::reader::{ + ByteRecordsIntoIter, ByteRecordsIter, DeserializeRecordsIntoIter, + DeserializeRecordsIter, Reader, ReaderBuilder, StringRecordsIntoIter, + StringRecordsIter, }; -pub use string_record::{StringRecord, StringRecordIter}; -pub use writer::{Writer, WriterBuilder}; +pub use crate::string_record::{StringRecord, StringRecordIter}; +pub use crate::writer::{Writer, WriterBuilder}; mod byte_record; +pub mod cookbook; mod deserializer; mod error; -pub mod cookbook; mod reader; mod serializer; mod string_record; @@ -347,12 +319,10 @@ /// an error. /// /// ``` -/// extern crate csv; -/// #[macro_use] -/// extern crate serde_derive; -/// /// use std::error::Error; +/// /// use csv::Reader; +/// use serde::Deserialize; /// /// #[derive(Debug, Deserialize, Eq, PartialEq)] /// struct Row { @@ -365,7 +335,7 @@ /// } /// /// # fn main() { example().unwrap(); } -/// fn example() -> Result<(), Box> { +/// fn example() -> Result<(), Box> { /// let data = "\ /// a,b,c /// 5,\"\",xyz @@ -381,7 +351,9 @@ /// } /// ``` pub fn invalid_option<'de, D, T>(de: D) -> result::Result, D::Error> - where D: Deserializer<'de>, Option: Deserialize<'de> +where + D: Deserializer<'de>, + Option: Deserialize<'de>, { Option::::deserialize(de).or_else(|_| Ok(None)) } diff -Nru rust-csv-1.0.5/src/reader.rs rust-csv-1.1.1/src/reader.rs --- rust-csv-1.0.5/src/reader.rs 2018-12-15 14:19:23.000000000 +0000 +++ rust-csv-1.1.1/src/reader.rs 2019-06-26 23:51:53.000000000 +0000 @@ -4,15 +4,13 @@ use std::path::Path; use std::result; -use csv_core::{ - Reader as CoreReader, ReaderBuilder as CoreReaderBuilder, -}; +use csv_core::{Reader as CoreReader, ReaderBuilder as CoreReaderBuilder}; use serde::de::DeserializeOwned; -use byte_record::{self, ByteRecord, Position}; -use error::{ErrorKind, Result, Utf8Error, new_error}; -use string_record::{self, StringRecord}; -use {Terminator, Trim}; +use crate::byte_record::{ByteRecord, Position}; +use crate::error::{Error, ErrorKind, Result, Utf8Error}; +use crate::string_record::StringRecord; +use crate::{Terminator, Trim}; /// Builds a CSV reader with various configuration knobs. /// @@ -36,7 +34,7 @@ impl Default for ReaderBuilder { fn default() -> ReaderBuilder { ReaderBuilder { - capacity: 8 * (1<<10), + capacity: 8 * (1 << 10), flexible: false, has_headers: true, trim: Trim::default(), @@ -54,13 +52,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{ReaderBuilder, StringRecord}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -91,13 +87,11 @@ /// # Example /// /// ```no_run - /// extern crate csv; - /// /// use std::error::Error; /// use csv::ReaderBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut rdr = ReaderBuilder::new().from_path("foo.csv")?; /// for result in rdr.records() { /// let record = result?; @@ -118,13 +112,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::ReaderBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -149,13 +141,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::ReaderBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city;country;pop /// Boston;United States;4628910 @@ -194,13 +184,11 @@ /// Namely, the first row is treated just like any other row. /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::ReaderBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -246,13 +234,11 @@ /// # Example: flexible records enabled /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::ReaderBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// // Notice that the first row is missing the population count. /// let data = "\ /// city,country,pop @@ -279,13 +265,11 @@ /// default). /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{ErrorKind, ReaderBuilder}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// // Notice that the first row is missing the population count. /// let data = "\ /// city,country,pop @@ -343,13 +327,11 @@ /// This example shows what happens when all values are trimmed. /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{ReaderBuilder, StringRecord, Trim}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city , country , pop /// Boston,\" @@ -383,13 +365,11 @@ /// # Example: `$` as a record terminator /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{ReaderBuilder, Terminator}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "city,country,pop$Boston,United States,4628910"; /// let mut rdr = ReaderBuilder::new() /// .terminator(Terminator::Any(b'$')) @@ -404,10 +384,7 @@ /// } /// } /// ``` - pub fn terminator( - &mut self, - term: Terminator, - ) -> &mut ReaderBuilder { + pub fn terminator(&mut self, term: Terminator) -> &mut ReaderBuilder { self.builder.terminator(term.to_core()); self } @@ -419,13 +396,11 @@ /// # Example: single quotes instead of double quotes /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::ReaderBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,'United States',4628910 @@ -458,13 +433,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::ReaderBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,\"The \\\"United\\\" States\",4628910 @@ -497,13 +470,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::ReaderBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,\"The \"\"United\"\" States\",4628910 @@ -536,13 +507,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::ReaderBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,\"The United States,4628910 @@ -577,13 +546,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::ReaderBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// #Concord,United States,42695 @@ -616,13 +583,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::ReaderBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city\x1Fcountry\x1Fpop\x1EBoston\x1FUnited States\x1F4628910"; /// let mut rdr = ReaderBuilder::new() @@ -679,13 +644,11 @@ /// a `Reader`. For example, to change the field delimiter: /// /// ``` -/// extern crate csv; -/// /// use std::error::Error; /// use csv::ReaderBuilder; /// /// # fn main() { example().unwrap(); } -/// fn example() -> Result<(), Box> { +/// fn example() -> Result<(), Box> { /// let data = "\ /// city;country;pop /// Boston;United States;4628910 @@ -801,13 +764,11 @@ /// # Example /// /// ```no_run - /// extern crate csv; - /// /// use std::error::Error; /// use csv::Reader; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut rdr = Reader::from_path("foo.csv")?; /// for result in rdr.records() { /// let record = result?; @@ -850,13 +811,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::Reader; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -893,12 +852,10 @@ /// to the fields of the struct. /// /// ``` - /// extern crate csv; - /// #[macro_use] - /// extern crate serde_derive; - /// /// use std::error::Error; + /// /// use csv::Reader; + /// use serde::Deserialize; /// /// #[derive(Debug, Deserialize, Eq, PartialEq)] /// struct Row { @@ -909,7 +866,7 @@ /// } /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,popcount /// Boston,United States,4628910 @@ -952,12 +909,10 @@ /// a "tail" of fields in a record: /// /// ``` - /// extern crate csv; - /// #[macro_use] - /// extern crate serde_derive; - /// /// use std::error::Error; + /// /// use csv::ReaderBuilder; + /// use serde::Deserialize; /// /// #[derive(Debug, Deserialize, Eq, PartialEq)] /// struct Row { @@ -966,7 +921,7 @@ /// } /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "foo,1,2,3"; /// let mut rdr = ReaderBuilder::new() /// .has_headers(false) @@ -1001,12 +956,10 @@ /// following example shows both forms in action: /// /// ``` - /// extern crate csv; - /// #[macro_use] - /// extern crate serde_derive; - /// /// use std::error::Error; + /// /// use csv::Reader; + /// use serde::Deserialize; /// /// #[derive(Debug, Deserialize, PartialEq)] /// struct Row { @@ -1029,7 +982,7 @@ /// } /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// label,value /// celsius,22.2222 @@ -1065,7 +1018,8 @@ /// } /// ``` pub fn deserialize(&mut self) -> DeserializeRecordsIter - where D: DeserializeOwned + where + D: DeserializeOwned, { DeserializeRecordsIter::new(self) } @@ -1091,12 +1045,10 @@ /// # Example /// /// ``` - /// extern crate csv; - /// #[macro_use] - /// extern crate serde_derive; - /// /// use std::error::Error; + /// /// use csv::Reader; + /// use serde::Deserialize; /// /// #[derive(Debug, Deserialize, Eq, PartialEq)] /// struct Row { @@ -1107,7 +1059,7 @@ /// } /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,popcount /// Boston,United States,4628910 @@ -1129,7 +1081,8 @@ /// } /// ``` pub fn into_deserialize(self) -> DeserializeRecordsIntoIter - where D: DeserializeOwned + where + D: DeserializeOwned, { DeserializeRecordsIntoIter::new(self) } @@ -1146,13 +1099,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::Reader; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -1188,13 +1139,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::Reader; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -1227,13 +1176,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::Reader; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -1269,13 +1216,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::Reader; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -1316,13 +1261,11 @@ /// the header row does not appear as a record in the iterator! /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::Reader; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -1361,7 +1304,7 @@ let headers = self.state.headers.as_ref().unwrap(); match headers.string_record { Ok(ref record) => Ok(record), - Err(ref err) => Err(new_error(ErrorKind::Utf8 { + Err(ref err) => Err(Error::new(ErrorKind::Utf8 { pos: headers.byte_record.position().map(Clone::clone), err: err.clone(), })), @@ -1387,13 +1330,11 @@ /// the header row does not appear as a record in the iterator! /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::Reader; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -1441,13 +1382,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{Reader, StringRecord}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -1474,13 +1413,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{Reader, ByteRecord}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -1545,13 +1482,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{Reader, StringRecord}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -1568,7 +1503,7 @@ /// } /// ``` pub fn read_record(&mut self, record: &mut StringRecord) -> Result { - let result = string_record::read(self, record); + let result = record.read(self); // We need to trim again because trimming string records includes // Unicode whitespace. (ByteRecord trimming only includes ASCII // whitespace.) @@ -1595,13 +1530,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{ByteRecord, Reader}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,pop /// Boston,United States,4628910 @@ -1672,13 +1605,17 @@ loop { let (res, nin, nout, nend) = { let input = self.rdr.fill_buf()?; - let (fields, ends) = byte_record::as_parts(record); + let (fields, ends) = record.as_parts(); self.core.read_record( - input, &mut fields[outlen..], &mut ends[endlen..]) + input, + &mut fields[outlen..], + &mut ends[endlen..], + ) }; self.rdr.consume(nin); let byte = self.state.cur_pos.byte(); - self.state.cur_pos + self.state + .cur_pos .set_byte(byte + nin as u64) .set_line(self.core.line()); outlen += nout; @@ -1686,15 +1623,15 @@ match res { InputEmpty => continue, OutputFull => { - byte_record::expand_fields(record); + record.expand_fields(); continue; } OutputEndsFull => { - byte_record::expand_ends(record); + record.expand_ends(); continue; } Record => { - byte_record::set_len(record, endlen); + record.set_len(endlen); self.state.add_record(record)?; return Ok(true); } @@ -1715,14 +1652,12 @@ /// # Example: reading the position /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use std::io; /// use csv::{Reader, Position}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,popcount /// Boston,United States,4628910 @@ -1760,14 +1695,12 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use std::io; /// use csv::{Reader, Position}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,popcount /// Boston,United States,4628910 @@ -1838,14 +1771,12 @@ /// # Example: seek to parse a record twice /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use std::io; /// use csv::{Reader, Position}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let data = "\ /// city,country,popcount /// Boston,United States,4628910 @@ -1929,7 +1860,7 @@ None => self.first_field_count = Some(record.len() as u64), Some(expected) => { if record.len() as u64 != expected { - return Err(new_error(ErrorKind::UnequalLengths { + return Err(Error::new(ErrorKind::UnequalLengths { pos: record.position().map(Clone::clone), expected_len: expected, len: record.len() as u64, @@ -1955,12 +1886,11 @@ impl DeserializeRecordsIntoIter { fn new(mut rdr: Reader) -> DeserializeRecordsIntoIter { - let headers = - if !rdr.state.has_headers { - None - } else { - rdr.headers().ok().map(Clone::clone) - }; + let headers = if !rdr.state.has_headers { + None + } else { + rdr.headers().ok().map(Clone::clone) + }; DeserializeRecordsIntoIter { rdr: rdr, rec: StringRecord::new(), @@ -1985,8 +1915,8 @@ } } -impl - Iterator for DeserializeRecordsIntoIter +impl Iterator + for DeserializeRecordsIntoIter { type Item = Result; @@ -2014,12 +1944,11 @@ impl<'r, R: io::Read, D: DeserializeOwned> DeserializeRecordsIter<'r, R, D> { fn new(rdr: &'r mut Reader) -> DeserializeRecordsIter<'r, R, D> { - let headers = - if !rdr.state.has_headers { - None - } else { - rdr.headers().ok().map(Clone::clone) - }; + let headers = if !rdr.state.has_headers { + None + } else { + rdr.headers().ok().map(Clone::clone) + }; DeserializeRecordsIter { rdr: rdr, rec: StringRecord::new(), @@ -2039,8 +1968,8 @@ } } -impl<'r, R: io::Read, D: DeserializeOwned> - Iterator for DeserializeRecordsIter<'r, R, D> +impl<'r, R: io::Read, D: DeserializeOwned> Iterator + for DeserializeRecordsIter<'r, R, D> { type Item = Result; @@ -2209,14 +2138,18 @@ mod tests { use std::io; - use byte_record::ByteRecord; - use error::ErrorKind; - use string_record::StringRecord; + use crate::byte_record::ByteRecord; + use crate::error::ErrorKind; + use crate::string_record::StringRecord; - use super::{ReaderBuilder, Position, Trim}; + use super::{Position, ReaderBuilder, Trim}; - fn b(s: &str) -> &[u8] { s.as_bytes() } - fn s(b: &[u8]) -> &str { ::std::str::from_utf8(b).unwrap() } + fn b(s: &str) -> &[u8] { + s.as_bytes() + } + fn s(b: &[u8]) -> &str { + ::std::str::from_utf8(b).unwrap() + } fn newpos(byte: u64, line: u64, record: u64) -> Position { let mut p = Position::new(); @@ -2227,9 +2160,8 @@ #[test] fn read_byte_record() { let data = b("foo,\"b,ar\",baz\nabc,mno,xyz"); - let mut rdr = ReaderBuilder::new() - .has_headers(false) - .from_reader(data); + let mut rdr = + ReaderBuilder::new().has_headers(false).from_reader(data); let mut rec = ByteRecord::new(); assert!(rdr.read_byte_record(&mut rec).unwrap()); @@ -2303,8 +2235,9 @@ .from_reader(data); let mut rec = StringRecord::new(); - let _ = rdr.read_record(&mut rec); // force the headers to be read - // Check the byte headers are trimmed and string headers are still errors + // force the headers to be read + let _ = rdr.read_record(&mut rec); + // Check the byte headers are trimmed { let headers = rdr.byte_headers().unwrap(); assert_eq!(3, headers.len()); @@ -2346,9 +2279,8 @@ #[test] fn read_record_unequal_fails() { let data = b("foo\nbar,baz"); - let mut rdr = ReaderBuilder::new() - .has_headers(false) - .from_reader(data); + let mut rdr = + ReaderBuilder::new().has_headers(false).from_reader(data); let mut rec = ByteRecord::new(); assert!(rdr.read_byte_record(&mut rec).unwrap()); @@ -2356,18 +2288,16 @@ assert_eq!("foo", s(&rec[0])); match rdr.read_byte_record(&mut rec) { - Err(err) => { - match *err.kind() { - ErrorKind::UnequalLengths { - expected_len: 1, - ref pos, - len: 2, - } => { - assert_eq!(pos, &Some(newpos(4, 2, 1))); - } - ref wrong => panic!("match failed, got {:?}", wrong), + Err(err) => match *err.kind() { + ErrorKind::UnequalLengths { + expected_len: 1, + ref pos, + len: 2, + } => { + assert_eq!(pos, &Some(newpos(4, 2, 1))); } - } + ref wrong => panic!("match failed, got {:?}", wrong), + }, wrong => panic!("match failed, got {:?}", wrong), } } @@ -2398,9 +2328,8 @@ #[test] fn read_record_unequal_continue() { let data = b("foo\nbar,baz\nquux"); - let mut rdr = ReaderBuilder::new() - .has_headers(false) - .from_reader(data); + let mut rdr = + ReaderBuilder::new().has_headers(false).from_reader(data); let mut rec = ByteRecord::new(); assert!(rdr.read_byte_record(&mut rec).unwrap()); @@ -2408,18 +2337,16 @@ assert_eq!("foo", s(&rec[0])); match rdr.read_byte_record(&mut rec) { - Err(err) => { - match err.kind() { - &ErrorKind::UnequalLengths { - expected_len: 1, - ref pos, - len: 2, - } => { - assert_eq!(pos, &Some(newpos(4, 2, 1))); - } - wrong => panic!("match failed, got {:?}", wrong), + Err(err) => match err.kind() { + &ErrorKind::UnequalLengths { + expected_len: 1, + ref pos, + len: 2, + } => { + assert_eq!(pos, &Some(newpos(4, 2, 1))); } - } + wrong => panic!("match failed, got {:?}", wrong), + }, wrong => panic!("match failed, got {:?}", wrong), } @@ -2500,9 +2427,8 @@ #[test] fn read_record_no_headers_before() { let data = b("foo,bar,baz\na,b,c\nd,e,f"); - let mut rdr = ReaderBuilder::new() - .has_headers(false) - .from_reader(data); + let mut rdr = + ReaderBuilder::new().has_headers(false).from_reader(data); let mut rec = StringRecord::new(); { @@ -2531,9 +2457,8 @@ #[test] fn read_record_no_headers_after() { let data = b("foo,bar,baz\na,b,c\nd,e,f"); - let mut rdr = ReaderBuilder::new() - .has_headers(false) - .from_reader(data); + let mut rdr = + ReaderBuilder::new().has_headers(false).from_reader(data); let mut rec = StringRecord::new(); assert!(rdr.read_record(&mut rec).unwrap()); @@ -2560,8 +2485,7 @@ #[test] fn seek() { let data = b("foo,bar,baz\na,b,c\nd,e,f\ng,h,i"); - let mut rdr = ReaderBuilder::new() - .from_reader(io::Cursor::new(data)); + let mut rdr = ReaderBuilder::new().from_reader(io::Cursor::new(data)); rdr.seek(newpos(18, 3, 2)).unwrap(); let mut rec = StringRecord::new(); @@ -2586,8 +2510,7 @@ #[test] fn seek_headers_after() { let data = b("foo,bar,baz\na,b,c\nd,e,f\ng,h,i"); - let mut rdr = ReaderBuilder::new() - .from_reader(io::Cursor::new(data)); + let mut rdr = ReaderBuilder::new().from_reader(io::Cursor::new(data)); rdr.seek(newpos(18, 3, 2)).unwrap(); assert_eq!(rdr.headers().unwrap(), vec!["foo", "bar", "baz"]); } @@ -2597,8 +2520,7 @@ #[test] fn seek_headers_before_after() { let data = b("foo,bar,baz\na,b,c\nd,e,f\ng,h,i"); - let mut rdr = ReaderBuilder::new() - .from_reader(io::Cursor::new(data)); + let mut rdr = ReaderBuilder::new().from_reader(io::Cursor::new(data)); let headers = rdr.headers().unwrap().clone(); rdr.seek(newpos(18, 3, 2)).unwrap(); assert_eq!(&headers, rdr.headers().unwrap()); @@ -2610,8 +2532,7 @@ #[test] fn seek_headers_no_actual_seek() { let data = b("foo,bar,baz\na,b,c\nd,e,f\ng,h,i"); - let mut rdr = ReaderBuilder::new() - .from_reader(io::Cursor::new(data)); + let mut rdr = ReaderBuilder::new().from_reader(io::Cursor::new(data)); rdr.seek(Position::new()).unwrap(); assert_eq!("foo", &rdr.headers().unwrap()[0]); } @@ -2660,9 +2581,8 @@ // Test that reading the first record on empty data works. #[test] fn no_headers_on_empty_data() { - let mut rdr = ReaderBuilder::new() - .has_headers(false) - .from_reader("".as_bytes()); + let mut rdr = + ReaderBuilder::new().has_headers(false).from_reader("".as_bytes()); assert_eq!(rdr.records().count(), 0); } @@ -2670,9 +2590,8 @@ // we've tried to read headers before hand. #[test] fn no_headers_on_empty_data_after_headers() { - let mut rdr = ReaderBuilder::new() - .has_headers(false) - .from_reader("".as_bytes()); + let mut rdr = + ReaderBuilder::new().has_headers(false).from_reader("".as_bytes()); assert_eq!(rdr.headers().unwrap().len(), 0); assert_eq!(rdr.records().count(), 0); } diff -Nru rust-csv-1.0.5/src/serializer.rs rust-csv-1.1.1/src/serializer.rs --- rust-csv-1.0.5/src/serializer.rs 2018-08-23 11:47:48.000000000 +0000 +++ rust-csv-1.1.1/src/serializer.rs 2019-07-01 15:47:59.000000000 +0000 @@ -1,21 +1,25 @@ -use std::fmt::{self, Write}; +use std::fmt; use std::io; use std::mem; +use itoa; +use ryu; use serde::ser::{ - Error as SerdeError, - Serialize, Serializer, - SerializeSeq, SerializeTuple, SerializeTupleStruct, - SerializeTupleVariant, SerializeMap, SerializeStruct, - SerializeStructVariant, + Error as SerdeError, Serialize, SerializeMap, SerializeSeq, + SerializeStruct, SerializeStructVariant, SerializeTuple, + SerializeTupleStruct, SerializeTupleVariant, Serializer, }; +use serde::serde_if_integer128; -use error::{Error, ErrorKind, new_error}; -use writer::{Writer, SingleFieldWriter}; +use crate::error::{Error, ErrorKind}; +use crate::writer::Writer; /// Serialize the given value to the given writer, and return an error if /// anything went wrong. -pub fn serialize(wtr: &mut Writer, value: S) -> Result<(), Error> { +pub fn serialize( + wtr: &mut Writer, + value: S, +) -> Result<(), Error> { value.serialize(&mut SeRecord { wtr: wtr }) } @@ -34,12 +38,6 @@ type SerializeStruct = Self; type SerializeStructVariant = Self; - fn collect_str(self, v: &T) -> Result<(), Error> { - let mut sfw = SingleFieldWriter::start_field(self.wtr)?; - let _ = write!(sfw, "{}", v); - sfw.take_formatting_error() - } - fn serialize_bool(self, v: bool) -> Result { if v { self.wtr.write_field("true") @@ -49,47 +47,69 @@ } fn serialize_i8(self, v: i8) -> Result { - self.collect_str(&v) + let mut buffer = itoa::Buffer::new(); + self.wtr.write_field(buffer.format(v)) } fn serialize_i16(self, v: i16) -> Result { - self.collect_str(&v) + let mut buffer = itoa::Buffer::new(); + self.wtr.write_field(buffer.format(v)) } fn serialize_i32(self, v: i32) -> Result { - self.collect_str(&v) + let mut buffer = itoa::Buffer::new(); + self.wtr.write_field(buffer.format(v)) } fn serialize_i64(self, v: i64) -> Result { - self.collect_str(&v) + let mut buffer = itoa::Buffer::new(); + self.wtr.write_field(buffer.format(v)) + } + + serde_if_integer128! { + fn serialize_i128(self, v: i128) -> Result { + self.collect_str(&v) + } } fn serialize_u8(self, v: u8) -> Result { - self.collect_str(&v) + let mut buffer = itoa::Buffer::new(); + self.wtr.write_field(buffer.format(v)) } fn serialize_u16(self, v: u16) -> Result { - self.collect_str(&v) + let mut buffer = itoa::Buffer::new(); + self.wtr.write_field(buffer.format(v)) } fn serialize_u32(self, v: u32) -> Result { - self.collect_str(&v) + let mut buffer = itoa::Buffer::new(); + self.wtr.write_field(buffer.format(v)) } fn serialize_u64(self, v: u64) -> Result { - self.collect_str(&v) + let mut buffer = itoa::Buffer::new(); + self.wtr.write_field(buffer.format(v)) + } + + serde_if_integer128! { + fn serialize_u128(self, v: u128) -> Result { + self.collect_str(&v) + } } fn serialize_f32(self, v: f32) -> Result { - self.collect_str(&v) + let mut buffer = ryu::Buffer::new(); + self.wtr.write_field(buffer.format(v)) } fn serialize_f64(self, v: f64) -> Result { - self.collect_str(&v) + let mut buffer = ryu::Buffer::new(); + self.wtr.write_field(buffer.format(v)) } fn serialize_char(self, v: char) -> Result { - self.collect_str(&v) + self.wtr.write_field(v.encode_utf8(&mut [0; 4])) } fn serialize_str(self, value: &str) -> Result { @@ -189,7 +209,8 @@ Err(Error::custom( "serializing maps is not supported, \ if you have a use case, please file an issue at \ - https://github.com/BurntSushi/rust-csv")) + https://github.com/BurntSushi/rust-csv", + )) } fn serialize_struct( @@ -334,20 +355,22 @@ impl SerdeError for Error { fn custom(msg: T) -> Error { - new_error(ErrorKind::Serialize(msg.to_string())) + Error::new(ErrorKind::Serialize(msg.to_string())) } } fn error_scalar_outside_struct(name: T) -> Error { Error::custom(format!( - "cannot serialize {} scalar outside struct when writing headers from structs", + "cannot serialize {} scalar outside struct \ + when writing headers from structs", name )) } fn error_container_inside_struct(name: T) -> Error { Error::custom(format!( - "cannot serialize {} container inside struct when writing headers from structs", + "cannot serialize {} container inside struct \ + when writing headers from structs", name )) } @@ -415,7 +438,8 @@ /// The serializer still has not encountered a struct field. If one is /// encountered (headers need to be written), return the enclosed error. ErrorIfWrite(Error), - /// The serializer encountered one or more struct fields (and wrote their names). + /// The serializer encountered one or more struct fields (and wrote their + /// names). EncounteredStructField, /// The serializer is currently in a struct field value. InStructField, @@ -428,10 +452,7 @@ impl<'w, W: io::Write> SeHeader<'w, W> { fn new(wtr: &'w mut Writer) -> Self { - SeHeader { - wtr: wtr, - state: HeaderState::Write, - } + SeHeader { wtr: wtr, state: HeaderState::Write } } fn wrote_header(&self) -> bool { @@ -442,8 +463,12 @@ } } - fn handle_scalar(&mut self, name: T) -> Result<(), Error> { + fn handle_scalar( + &mut self, + name: T, + ) -> Result<(), Error> { use self::HeaderState::*; + match self.state { Write => { self.state = ErrorIfWrite(error_scalar_outside_struct(name)); @@ -454,7 +479,10 @@ } } - fn handle_container(&mut self, name: T) -> Result<&mut Self, Error> { + fn handle_container( + &mut self, + name: T, + ) -> Result<&mut Self, Error> { if let HeaderState::InStructField = self.state { Err(error_container_inside_struct(name)) } else { @@ -494,6 +522,12 @@ self.handle_scalar(v) } + serde_if_integer128! { + fn serialize_i128(self, v: i128) -> Result { + self.handle_scalar(v) + } + } + fn serialize_u8(self, v: u8) -> Result { self.handle_scalar(v) } @@ -510,6 +544,12 @@ self.handle_scalar(v) } + serde_if_integer128! { + fn serialize_u128(self, v: u128) -> Result { + self.handle_scalar(v) + } + } + fn serialize_f32(self, v: f32) -> Result { self.handle_scalar(v) } @@ -534,7 +574,10 @@ self.handle_scalar("None") } - fn serialize_some(self, _value: &T) -> Result { + fn serialize_some( + self, + _value: &T, + ) -> Result { self.handle_scalar("Some(_)") } @@ -542,7 +585,10 @@ self.handle_scalar("()") } - fn serialize_unit_struct(self, name: &'static str) -> Result { + fn serialize_unit_struct( + self, + name: &'static str, + ) -> Result { self.handle_scalar(name) } @@ -573,11 +619,17 @@ self.handle_scalar(format!("{}::{}(_)", name, variant)) } - fn serialize_seq(self, _len: Option) -> Result { + fn serialize_seq( + self, + _len: Option, + ) -> Result { self.handle_container("sequence") } - fn serialize_tuple(self, _len: usize) -> Result { + fn serialize_tuple( + self, + _len: usize, + ) -> Result { self.handle_container("tuple") } @@ -596,12 +648,13 @@ _variant: &'static str, _len: usize, ) -> Result { - Err(Error::custom( - "serializing enum tuple variants is not supported", - )) + Err(Error::custom("serializing enum tuple variants is not supported")) } - fn serialize_map(self, _len: Option) -> Result { + fn serialize_map( + self, + _len: Option, + ) -> Result { // The right behavior for serializing maps isn't clear. Err(Error::custom( "serializing maps is not supported, \ @@ -625,9 +678,7 @@ _variant: &'static str, _len: usize, ) -> Result { - Err(Error::custom( - "serializing enum struct variants is not supported", - )) + Err(Error::custom("serializing enum struct variants is not supported")) } } @@ -635,7 +686,10 @@ type Ok = (); type Error = Error; - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> { + fn serialize_element( + &mut self, + value: &T, + ) -> Result<(), Self::Error> { value.serialize(&mut **self) } @@ -648,7 +702,10 @@ type Ok = (); type Error = Error; - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> { + fn serialize_element( + &mut self, + value: &T, + ) -> Result<(), Self::Error> { value.serialize(&mut **self) } @@ -661,7 +718,10 @@ type Ok = (); type Error = Error; - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> { + fn serialize_field( + &mut self, + value: &T, + ) -> Result<(), Self::Error> { value.serialize(&mut **self) } @@ -674,7 +734,10 @@ type Ok = (); type Error = Error; - fn serialize_field(&mut self, _value: &T) -> Result<(), Self::Error> { + fn serialize_field( + &mut self, + _value: &T, + ) -> Result<(), Self::Error> { unreachable!() } @@ -687,11 +750,17 @@ type Ok = (); type Error = Error; - fn serialize_key(&mut self, _key: &T) -> Result<(), Self::Error> { + fn serialize_key( + &mut self, + _key: &T, + ) -> Result<(), Self::Error> { unreachable!() } - fn serialize_value(&mut self, _value: &T) -> Result<(), Self::Error> { + fn serialize_value( + &mut self, + _value: &T, + ) -> Result<(), Self::Error> { unreachable!() } @@ -710,7 +779,8 @@ value: &T, ) -> Result<(), Self::Error> { // Grab old state and update state to `EncounteredStructField`. - let old_state = mem::replace(&mut self.state, HeaderState::EncounteredStructField); + let old_state = + mem::replace(&mut self.state, HeaderState::EncounteredStructField); if let HeaderState::ErrorIfWrite(err) = old_state { return Err(err); } @@ -748,11 +818,11 @@ #[cfg(test)] mod tests { - use serde::Serialize; - use serde_bytes::Bytes; + use bstr::ByteSlice; + use serde::{serde_if_integer128, Serialize}; - use error::{Error, ErrorKind}; - use writer::Writer; + use crate::error::{Error, ErrorKind}; + use crate::writer::Writer; use super::{SeHeader, SeRecord}; @@ -803,6 +873,26 @@ assert_eq!(got, ""); } + serde_if_integer128! { + #[test] + fn integer_u128() { + let got = serialize(i128::max_value() as u128 + 1); + assert_eq!(got, "170141183460469231731687303715884105728\n"); + let (wrote, got) = serialize_header(12345); + assert!(!wrote); + assert_eq!(got, ""); + } + + #[test] + fn integer_i128() { + let got = serialize(i128::max_value()); + assert_eq!(got, "170141183460469231731687303715884105727\n"); + let (wrote, got) = serialize_header(12345); + assert!(!wrote); + assert_eq!(got, ""); + } + } + #[test] fn float() { let got = serialize(1.23); @@ -813,6 +903,15 @@ } #[test] + fn float_nan() { + let got = serialize(::std::f64::NAN); + assert_eq!(got, "NaN\n"); + let (wrote, got) = serialize_header(::std::f64::NAN); + assert!(!wrote); + assert_eq!(got, ""); + } + + #[test] fn char() { let got = serialize('☃'); assert_eq!(got, "☃\n"); @@ -832,7 +931,7 @@ #[test] fn bytes() { - let got = serialize(Bytes::new(&b"how\nare\n\"you\"?"[..])); + let got = serialize(b"how\nare\n\"you\"?".as_bstr()); assert_eq!(got, "\"how\nare\n\"\"you\"\"?\"\n"); let (wrote, got) = serialize_header(&b"how\nare\n\"you\"?"[..]); assert!(!wrote); @@ -896,7 +995,11 @@ #[test] fn enum_units() { #[derive(Serialize)] - enum Wat { Foo, Bar, Baz } + enum Wat { + Foo, + Bar, + Baz, + } let got = serialize(Wat::Foo); assert_eq!(got, "Foo\n"); @@ -920,7 +1023,11 @@ #[test] fn enum_newtypes() { #[derive(Serialize)] - enum Wat { Foo(i32), Bar(f32), Baz(bool) } + enum Wat { + Foo(i32), + Bar(f32), + Baz(bool), + } let got = serialize(Wat::Foo(5)); assert_eq!(got, "5\n"); @@ -1033,6 +1140,25 @@ assert_eq!(got, "true,5,hi\n"); } + serde_if_integer128! { + #[test] + fn struct_no_headers_128() { + #[derive(Serialize)] + struct Foo { + x: i128, + y: u128, + } + + let got = + serialize(Foo { x: i128::max_value(), y: u128::max_value() }); + assert_eq!( + got, + "170141183460469231731687303715884105727,\ + 340282366920938463463374607431768211455\n" + ); + } + } + #[test] fn struct_headers() { #[derive(Clone, Serialize)] @@ -1065,10 +1191,7 @@ let row = Foo { label: "foo".into(), - nest: Nested { - label2: "bar".into(), - value: 5, - }, + nest: Nested { label2: "bar".into(), value: 5 }, }; let got = serialize(row.clone()); @@ -1114,23 +1237,13 @@ empty: (), } let row = ( - Foo { - label: "hi".to_string(), - num: 5., - }, - Bar { - label2: true, - value: 3, - empty: (), - }, - Foo { - label: "baz".to_string(), - num: 2.3, - }, + Foo { label: "hi".to_string(), num: 5.0 }, + Bar { label2: true, value: 3, empty: () }, + Foo { label: "baz".to_string(), num: 2.3 }, ); let got = serialize(row.clone()); - assert_eq!(got, "hi,5,true,3,,baz,2.3\n"); + assert_eq!(got, "hi,5.0,true,3,,baz,2.3\n"); let (wrote, got) = serialize_header(row.clone()); assert!(wrote); @@ -1144,16 +1257,10 @@ label: String, num: f64, } - let row = ( - 3.14, - Foo { - label: "hi".to_string(), - num: 5., - }, - ); + let row = (3.14, Foo { label: "hi".to_string(), num: 5.0 }); let got = serialize(row.clone()); - assert_eq!(got, "3.14,hi,5\n"); + assert_eq!(got, "3.14,hi,5.0\n"); let err = serialize_header_err(row.clone()); match *err.kind() { @@ -1169,16 +1276,10 @@ label: String, num: f64, } - let row = ( - Foo { - label: "hi".to_string(), - num: 5., - }, - 3.14, - ); + let row = (Foo { label: "hi".to_string(), num: 5.0 }, 3.14); let got = serialize(row.clone()); - assert_eq!(got, "hi,5,3.14\n"); + assert_eq!(got, "hi,5.0,3.14\n"); let err = serialize_header_err(row.clone()); match *err.kind() { @@ -1195,18 +1296,12 @@ num: f64, } let row = vec![ - Foo { - label: "hi".to_string(), - num: 5., - }, - Foo { - label: "baz".to_string(), - num: 2.3, - }, + Foo { label: "hi".to_string(), num: 5.0 }, + Foo { label: "baz".to_string(), num: 2.3 }, ]; let got = serialize(row.clone()); - assert_eq!(got, "hi,5,baz,2.3\n"); + assert_eq!(got, "hi,5.0,baz,2.3\n"); let (wrote, got) = serialize_header(row.clone()); assert!(wrote); @@ -1230,26 +1325,14 @@ struct Baz(bool); let row = ( ( - Foo { - label: "hi".to_string(), - num: 5., - }, - Bar { - label2: Baz(true), - value: 3, - empty: (), - }, + Foo { label: "hi".to_string(), num: 5.0 }, + Bar { label2: Baz(true), value: 3, empty: () }, ), - vec![ - (Foo { - label: "baz".to_string(), - num: 2.3, - },), - ], + vec![(Foo { label: "baz".to_string(), num: 2.3 },)], ); let got = serialize(row.clone()); - assert_eq!(got, "hi,5,true,3,,baz,2.3\n"); + assert_eq!(got, "hi,5.0,true,3,,baz,2.3\n"); let (wrote, got) = serialize_header(row.clone()); assert!(wrote); diff -Nru rust-csv-1.0.5/src/string_record.rs rust-csv-1.1.1/src/string_record.rs --- rust-csv-1.0.5/src/string_record.rs 2018-12-16 13:05:36.000000000 +0000 +++ rust-csv-1.1.1/src/string_record.rs 2019-06-26 23:51:53.000000000 +0000 @@ -7,47 +7,10 @@ use serde::de::Deserialize; -use deserializer::deserialize_string_record; -use error::{ErrorKind, FromUtf8Error, Result, new_error, new_from_utf8_error}; -use reader::Reader; -use byte_record::{self, ByteRecord, ByteRecordIter, Position}; - -/// A safe function for reading CSV data into a `StringRecord`. -/// -/// This relies on the internal representation of `StringRecord`. -#[inline(always)] -pub fn read( - rdr: &mut Reader, - record: &mut StringRecord, -) -> Result { - // TODO(burntsushi): Define this as a method using `pub(crate)` when that - // stabilizes. - - // SAFETY: Note that despite the absence of `unsafe` in this function, this - // code is critical to upholding the safety of other `unsafe` blocks in - // this module. Namely, after calling `read_byte_record`, it is possible - // for `record` to contain invalid UTF-8. We check for this in the - // `validate` method, and if it does have invalid UTF-8, we clear the - // record. (It is bad for `record` to contain invalid UTF-8 because other - // accessor methods, like `get`, assume that every field is valid UTF-8.) - let pos = rdr.position().clone(); - let read_res = rdr.read_byte_record(&mut record.0); - let utf8_res = match byte_record::validate(&record.0) { - Ok(()) => Ok(()), - Err(err) => { - // If this record isn't valid UTF-8, then completely wipe it. - record.0.clear(); - Err(err) - } - }; - match (read_res, utf8_res) { - (Err(err), _) => Err(err), - (Ok(_), Err(err)) => { - Err(new_error(ErrorKind::Utf8 { pos: Some(pos), err: err })) - } - (Ok(eof), Ok(())) => Ok(eof), - } -} +use crate::byte_record::{ByteRecord, ByteRecordIter, Position}; +use crate::deserializer::deserialize_string_record; +use crate::error::{Error, ErrorKind, FromUtf8Error, Result}; +use crate::reader::Reader; /// A single CSV record stored as valid UTF-8 bytes. /// @@ -74,31 +37,31 @@ impl PartialEq for StringRecord { fn eq(&self, other: &StringRecord) -> bool { - byte_record::eq(&self.0, &other.0) + self.0.iter_eq(&other.0) } } impl> PartialEq> for StringRecord { fn eq(&self, other: &Vec) -> bool { - byte_record::eq(&self.0, other) + self.0.iter_eq(other) } } impl<'a, T: AsRef<[u8]>> PartialEq> for &'a StringRecord { fn eq(&self, other: &Vec) -> bool { - byte_record::eq(&self.0, other) + self.0.iter_eq(other) } } impl> PartialEq<[T]> for StringRecord { fn eq(&self, other: &[T]) -> bool { - byte_record::eq(&self.0, other) + self.0.iter_eq(other) } } impl<'a, T: AsRef<[u8]>> PartialEq<[T]> for &'a StringRecord { fn eq(&self, other: &[T]) -> bool { - byte_record::eq(&self.0, other) + self.0.iter_eq(other) } } @@ -163,13 +126,11 @@ /// # Example: valid UTF-8 /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{ByteRecord, StringRecord}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let byte_record = ByteRecord::from(vec!["a", "b", "c"]); /// let str_record = StringRecord::from_byte_record(byte_record)?; /// assert_eq!(str_record.len(), 3); @@ -193,9 +154,9 @@ pub fn from_byte_record( record: ByteRecord, ) -> result::Result { - match byte_record::validate(&record) { + match record.validate() { Ok(()) => Ok(StringRecord(record)), - Err(err) => Err(new_from_utf8_error(record, err)), + Err(err) => Err(FromUtf8Error::new(record, err)), } } @@ -231,12 +192,12 @@ #[inline] pub fn from_byte_record_lossy(record: ByteRecord) -> StringRecord { // If the record is valid UTF-8, then take the easy path. - if let Ok(()) = byte_record::validate(&record) { + if let Ok(()) = record.validate() { return StringRecord(record); } // TODO: We can be faster here. Not sure if it's worth it. - let mut str_record = StringRecord::with_capacity( - record.as_slice().len(), record.len()); + let mut str_record = + StringRecord::with_capacity(record.as_slice().len(), record.len()); for field in &record { str_record.push_field(&String::from_utf8_lossy(field)); } @@ -262,12 +223,10 @@ /// deserialization. /// /// ``` - /// extern crate csv; - /// #[macro_use] - /// extern crate serde_derive; - /// /// use std::error::Error; + /// /// use csv::StringRecord; + /// use serde::Deserialize; /// /// #[derive(Deserialize)] /// struct Row<'a> { @@ -277,7 +236,7 @@ /// } /// /// # fn main() { example().unwrap() } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let record = StringRecord::from(vec![ /// "Boston", "United States", "4628910", /// ]); @@ -300,12 +259,10 @@ /// types (e.g., `String`) instead of borrowed data types (e.g., `&str`). /// /// ``` - /// extern crate csv; - /// #[macro_use] - /// extern crate serde_derive; - /// /// use std::error::Error; + /// /// use csv::StringRecord; + /// use serde::Deserialize; /// /// #[derive(Deserialize)] /// struct Row { @@ -315,7 +272,7 @@ /// } /// /// # fn main() { example().unwrap() } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// // Notice that the fields are not in the same order /// // as the fields in the struct! /// let header = StringRecord::from(vec![ @@ -473,9 +430,10 @@ return; } // TODO: We could likely do this in place, but for now, we allocate. - let mut trimmed = StringRecord::with_capacity( - self.as_slice().len(), self.len()); - for mut field in &*self { + let mut trimmed = + StringRecord::with_capacity(self.as_slice().len(), self.len()); + trimmed.set_position(self.position().cloned()); + for field in &*self { trimmed.push_field(field.trim()); } *self = trimmed; @@ -502,13 +460,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{StringRecord, ReaderBuilder}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut record = StringRecord::new(); /// let mut rdr = ReaderBuilder::new() /// .has_headers(false) @@ -651,12 +607,49 @@ pub fn into_byte_record(self) -> ByteRecord { self.0 } + + /// A safe function for reading CSV data into a `StringRecord`. + /// + /// This relies on the internal representation of `StringRecord`. + #[inline(always)] + pub(crate) fn read( + &mut self, + rdr: &mut Reader, + ) -> Result { + // SAFETY: Note that despite the absence of `unsafe` in this function, + // this code is critical to upholding the safety of other `unsafe` + // blocks in this module. Namely, after calling `read_byte_record`, + // it is possible for `record` to contain invalid UTF-8. We check for + // this in the `validate` method, and if it does have invalid UTF-8, we + // clear the record. (It is bad for `record` to contain invalid UTF-8 + // because other accessor methods, like `get`, assume that every field + // is valid UTF-8.) + let pos = rdr.position().clone(); + let read_res = rdr.read_byte_record(&mut self.0); + let utf8_res = match self.0.validate() { + Ok(()) => Ok(()), + Err(err) => { + // If this record isn't valid UTF-8, then completely wipe it. + self.0.clear(); + Err(err) + } + }; + match (read_res, utf8_res) { + (Err(err), _) => Err(err), + (Ok(_), Err(err)) => { + Err(Error::new(ErrorKind::Utf8 { pos: Some(pos), err: err })) + } + (Ok(eof), Ok(())) => Ok(eof), + } + } } impl ops::Index for StringRecord { type Output = str; #[inline] - fn index(&self, i: usize) -> &str { self.get(i).unwrap() } + fn index(&self, i: usize) -> &str { + self.get(i).unwrap() + } } impl> From> for StringRecord { @@ -675,7 +668,7 @@ impl> FromIterator for StringRecord { #[inline] - fn from_iter>(iter: I) -> StringRecord { + fn from_iter>(iter: I) -> StringRecord { let mut record = StringRecord::new(); record.extend(iter); record @@ -684,7 +677,7 @@ impl> Extend for StringRecord { #[inline] - fn extend>(&mut self, iter: I) { + fn extend>(&mut self, iter: I) { for x in iter { self.push_field(x.as_ref()); } @@ -741,7 +734,7 @@ #[cfg(test)] mod tests { - use string_record::StringRecord; + use crate::string_record::StringRecord; #[test] fn trim_front() { @@ -815,8 +808,8 @@ // Regression test for #138. #[test] fn eq_field_boundaries() { - let test1 = StringRecord::from(vec!["12","34"]); - let test2 = StringRecord::from(vec!["123","4"]); + let test1 = StringRecord::from(vec!["12", "34"]); + let test2 = StringRecord::from(vec!["123", "4"]); assert_ne!(test1, test2); } @@ -826,8 +819,8 @@ // Regression test for #138. #[test] fn eq_record_len() { - let test1 = StringRecord::from(vec!["12","34", "56"]); - let test2 = StringRecord::from(vec!["12","34"]); + let test1 = StringRecord::from(vec!["12", "34", "56"]); + let test2 = StringRecord::from(vec!["12", "34"]); assert_ne!(test1, test2); } } diff -Nru rust-csv-1.0.5/src/tutorial.rs rust-csv-1.1.1/src/tutorial.rs --- rust-csv-1.0.5/src/tutorial.rs 2018-05-12 13:56:26.000000000 +0000 +++ rust-csv-1.1.1/src/tutorial.rs 2019-06-26 23:51:53.000000000 +0000 @@ -53,7 +53,7 @@ ``` Once inside `csvtutor`, open `Cargo.toml` in your favorite text editor and add -`csv = "1"` to your `[dependencies]` section. At this point, your +`csv = "1.1"` to your `[dependencies]` section. At this point, your `Cargo.toml` should look something like this: ```text @@ -63,7 +63,7 @@ authors = ["Your Name"] [dependencies] -csv = "1" +csv = "1.1" ``` Next, let's build your project. Since you added the `csv` crate as a @@ -89,9 +89,6 @@ ```no_run //tutorial-setup-01.rs -// This makes the csv crate accessible to your program. -extern crate csv; - // Import the standard library's I/O module so we can read from stdin. use std::io; @@ -191,8 +188,6 @@ ```no_run //tutorial-error-01.rs -extern crate csv; - use std::io; fn main() { @@ -286,8 +281,6 @@ ```no_run //tutorial-error-02.rs -extern crate csv; - use std::io; use std::process; @@ -327,8 +320,6 @@ ```no_run //tutorial-error-03.rs -extern crate csv; - use std::error::Error; use std::io; use std::process; @@ -340,12 +331,12 @@ } } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.records() { // Examine our Result. // If there was no problem, print the record. - // Otherwise, convert our error to a Box and return it. + // Otherwise, convert our error to a Box and return it. match result { Err(err) => return Err(From::from(err)), Ok(record) => { @@ -357,10 +348,10 @@ } ``` -Our new function, `run`, has a return type of `Result<(), Box>`. In +Our new function, `run`, has a return type of `Result<(), Box>`. In simple terms, this says that `run` either returns nothing when successful, or -if an error occurred, it returns a `Box`, which stands for "any kind of -error." A `Box` is hard to inspect if we cared about the specific error +if an error occurred, it returns a `Box`, which stands for "any kind of +error." A `Box` is hard to inspect if we cared about the specific error that occurred. But for our purposes, all we need to do is gracefully print an error message and exit the program. @@ -369,8 +360,6 @@ ```no_run //tutorial-error-04.rs -extern crate csv; - use std::error::Error; use std::io; use std::process; @@ -382,7 +371,7 @@ } } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.records() { // This is effectively the same code as our `match` in the @@ -400,7 +389,7 @@ important to note that it can **only be used in functions that return `Result`.** -We'll end this section with a word of caution: using `Box` as our error +We'll end this section with a word of caution: using `Box` as our error type is the minimally acceptable thing we can do here. Namely, while it allows our program to gracefully handle errors, it makes it hard for callers to inspect the specific error condition that occurred. However, since this is a @@ -427,15 +416,13 @@ ```no_run //tutorial-read-01.rs -extern crate csv; - use std::env; use std::error::Error; use std::ffi::OsString; use std::fs::File; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let file_path = get_first_arg()?; let file = File::open(file_path)?; let mut rdr = csv::Reader::from_reader(file); @@ -448,7 +435,7 @@ /// Returns the first positional argument sent to this process. If there are no /// positional arguments, then this returns an error. -fn get_first_arg() -> Result> { +fn get_first_arg() -> Result> { match env::args_os().nth(1) { None => Err(From::from("expected 1 argument, but got none")), Some(file_path) => Ok(file_path), @@ -537,13 +524,11 @@ ```no_run //tutorial-read-headers-01.rs -# extern crate csv; -# # use std::error::Error; # use std::io; # use std::process; # -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::ReaderBuilder::new() .has_headers(false) .from_reader(io::stdin()); @@ -580,13 +565,11 @@ ```no_run //tutorial-read-headers-02.rs -# extern crate csv; -# # use std::error::Error; # use std::io; # use std::process; # -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); { // We nest this call in its own scope because of lifetimes. @@ -663,13 +646,11 @@ ```no_run //tutorial-read-delimiter-01.rs -# extern crate csv; -# # use std::error::Error; # use std::io; # use std::process; # -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::ReaderBuilder::new() .has_headers(false) .delimiter(b';') @@ -753,13 +734,11 @@ ```no_run //tutorial-read-serde-01.rs -# extern crate csv; -# # use std::error::Error; # use std::io; # use std::process; # -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.records() { let record = result?; @@ -798,8 +777,6 @@ ```no_run //tutorial-read-serde-02.rs -# extern crate csv; -# # use std::error::Error; # use std::io; # use std::process; @@ -808,7 +785,7 @@ // record type. type Record = (String, String, Option, f64, f64); -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); // Instead of creating an iterator with the `records` method, we create // an iterator with the `deserialize` method. @@ -853,8 +830,6 @@ ```no_run //tutorial-read-serde-03.rs -# extern crate csv; -# use std::collections::HashMap; # use std::error::Error; # use std::io; @@ -864,7 +839,7 @@ // record type. type Record = HashMap; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.deserialize() { let record: Record = result?; @@ -894,37 +869,33 @@ This method works especially well if you need to read CSV data with header records, but whose exact structure isn't known until your program runs. -However, in our case, we know the structure of the data in `uspop.csv`. -In particular, with the `HashMap` approach, we've lost the specific types -we had for each field in the previous example when we deserialized each record -into a `(String, String, Option, f64, f64)`. Is there a way to identify -fields by their corresponding header name *and* assign each field its own -unique type? The answer is yes, but we'll need to bring in a new crate called -`serde_derive` first. You can do that by adding this to the `[dependencies]` -section of your `Cargo.toml` file: +However, in our case, we know the structure of the data in `uspop.csv`. In +particular, with the `HashMap` approach, we've lost the specific types we had +for each field in the previous example when we deserialized each record into a +`(String, String, Option, f64, f64)`. Is there a way to identify fields +by their corresponding header name *and* assign each field its own unique +type? The answer is yes, but we'll need to bring in Serde's `derive` feature +first. You can do that by adding this to the `[dependencies]` section of your +`Cargo.toml` file: ```text -serde = "1" -serde_derive = "1" +serde = { version = "1", features = ["derive"] } ``` With these crates added to our project, we can now define our own custom struct that represents our record. We then ask Serde to automatically write the glue code required to populate our struct from a CSV record. The next example shows -how. Don't miss the new `extern crate` lines! +how. Don't miss the new Serde imports! ```no_run //tutorial-read-serde-04.rs -extern crate csv; -extern crate serde; -// This lets us write `#[derive(Deserialize)]`. -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +// This lets us write `#[derive(Deserialize)]`. +use serde::Deserialize; + // We don't need to derive `Debug` (which doesn't require Serde), but it's a // good habit to do it for all your types. // @@ -940,7 +911,7 @@ state: String, } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.deserialize() { let record: Record = result?; @@ -972,14 +943,13 @@ Once again, we didn't need to change our `run` function at all: we're still iterating over records using the `deserialize` iterator that we started with in the beginning of this section. The only thing that changed in this example -was the definition of the `Record` type and a couple new `extern crate` -statements. Our `Record` type is now a custom struct that we defined instead -of a type alias, and as a result, Serde doesn't know how to deserialize it by -default. However, a special compiler plugin called `serde_derive` is available, -which will read your struct definition at compile time and generate code that -will deserialize a CSV record into a `Record` value. To see what happens if you -leave out the automatic derive, change `#[derive(Debug, Deserialize)]` to -`#[derive(Debug)]`. +was the definition of the `Record` type and a new `use` statement. Our `Record` +type is now a custom struct that we defined instead of a type alias, and as a +result, Serde doesn't know how to deserialize it by default. However, a special +compiler plugin provided by Serde is available, which will read your struct +definition at compile time and generate code that will deserialize a CSV record +into a `Record` value. To see what happens if you leave out the automatic +derive, change `#[derive(Debug, Deserialize)]` to `#[derive(Debug)]`. One other thing worth mentioning in this example is the use of `#[serde(rename_all = "PascalCase")]`. This directive helps Serde map your @@ -1057,14 +1027,12 @@ ```no_run //tutorial-read-serde-invalid-01.rs -# extern crate csv; -# #[macro_use] -# extern crate serde_derive; -# # use std::error::Error; # use std::io; # use std::process; # +# use serde::Deserialize; +# #[derive(Debug, Deserialize)] #[serde(rename_all = "PascalCase")] struct Record { @@ -1075,7 +1043,7 @@ state: String, } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.deserialize() { let record: Record = result?; @@ -1128,14 +1096,11 @@ ```no_run //tutorial-read-serde-invalid-02.rs -# extern crate csv; -# #[macro_use] -# extern crate serde_derive; -# # use std::error::Error; # use std::io; # use std::process; # +# use serde::Deserialize; #[derive(Debug, Deserialize)] #[serde(rename_all = "PascalCase")] struct Record { @@ -1147,7 +1112,7 @@ state: String, } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut rdr = csv::Reader::from_reader(io::stdin()); for result in rdr.deserialize() { let record: Record = result?; @@ -1199,13 +1164,11 @@ ```no_run //tutorial-write-01.rs -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut wtr = csv::Writer::from_writer(io::stdout()); // Since we're writing records manually, we must explicitly write our // header record. A header record is written the same way that other @@ -1310,14 +1273,12 @@ ```no_run //tutorial-write-02.rs -extern crate csv; - use std::env; use std::error::Error; use std::ffi::OsString; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let file_path = get_first_arg()?; let mut wtr = csv::Writer::from_path(file_path)?; @@ -1332,7 +1293,7 @@ /// Returns the first positional argument sent to this process. If there are no /// positional arguments, then this returns an error. -fn get_first_arg() -> Result> { +fn get_first_arg() -> Result> { match env::args_os().nth(1) { None => Err(From::from("expected 1 argument, but got none")), Some(file_path) => Ok(file_path), @@ -1373,13 +1334,11 @@ ```no_run //tutorial-write-delimiter-01.rs -# extern crate csv; -# # use std::error::Error; # use std::io; # use std::process; # -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut wtr = csv::WriterBuilder::new() .delimiter(b'\t') .quote_style(csv::QuoteStyle::NonNumeric) @@ -1431,13 +1390,11 @@ ```no_run //tutorial-write-serde-01.rs -# extern crate csv; -# # use std::error::Error; # use std::io; # use std::process; # -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut wtr = csv::Writer::from_writer(io::stdout()); // We still need to write headers manually. @@ -1488,31 +1445,27 @@ bonus, the fields in a struct will automatically be written as a header record! -To write custom structs as CSV records, we'll need to make use of the -`serde_derive` crate again. As in the +To write custom structs as CSV records, we'll need to make use of Serde's +automatic `derive` feature again. As in the [previous section on reading with Serde](#reading-with-serde), we'll need to add a couple crates to our `[dependencies]` section in our `Cargo.toml` (if they aren't already there): ```text -serde = "1" -serde_derive = "1" +serde = { version = "1", features = ["derive"] } ``` -And we'll also need to add a couple extra `extern crate` statements to our -code, as shown in the example: +And we'll also need to add a new `use` statement to our code, for Serde, as +shown in the example: ```no_run //tutorial-write-serde-02.rs -extern crate csv; -extern crate serde; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +use serde::Serialize; + // Note that structs can derive both Serialize and Deserialize! #[derive(Debug, Serialize)] #[serde(rename_all = "PascalCase")] @@ -1524,7 +1477,7 @@ longitude: f64, } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let mut wtr = csv::Writer::from_writer(io::stdout()); wtr.serialize(Record { @@ -1636,14 +1589,12 @@ ```no_run //tutorial-pipeline-search-01.rs -extern crate csv; - use std::env; use std::error::Error; use std::io; use std::process; -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { // Get the query from the positional arguments. // If one doesn't exist, return an error. let query = match env::args().nth(1) { @@ -1758,14 +1709,12 @@ ```no_run //tutorial-pipeline-search-02.rs -# extern crate csv; -# # use std::env; # use std::error::Error; # use std::io; # use std::process; # -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let query = match env::args().nth(1) { None => return Err(From::from("expected 1 argument, but got none")), Some(query) => query, @@ -1825,24 +1774,20 @@ aren't already there: ```text -serde = "1" -serde_derive = "1" +serde = { version = "1", features = ["derive"] } ``` Now here's the code: ```no_run //tutorial-pipeline-pop-01.rs -extern crate csv; -extern crate serde; -#[macro_use] -extern crate serde_derive; - use std::env; use std::error::Error; use std::io; use std::process; +use serde::{Deserialize, Serialize}; + // Unlike previous examples, we derive both Deserialize and Serialize. This // means we'll be able to automatically deserialize and serialize this type. #[derive(Debug, Deserialize, Serialize)] @@ -1855,7 +1800,7 @@ longitude: f64, } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { // Get the query from the positional arguments. // If one doesn't exist or isn't an integer, return an error. let minimum_pop: u64 = match env::args().nth(1) { @@ -1969,13 +1914,11 @@ ```no_run //tutorial-perf-alloc-01.rs -extern crate csv; - use std::error::Error; use std::io; use std::process; -fn run() -> Result> { +fn run() -> Result> { let mut rdr = csv::Reader::from_reader(io::stdin()); let mut count = 0; @@ -2029,13 +1972,11 @@ ```no_run //tutorial-perf-alloc-02.rs -# extern crate csv; -# # use std::error::Error; # use std::io; # use std::process; # -fn run() -> Result> { +fn run() -> Result> { let mut rdr = csv::Reader::from_reader(io::stdin()); let mut count = 0; @@ -2114,13 +2055,11 @@ ```no_run //tutorial-perf-alloc-03.rs -# extern crate csv; -# # use std::error::Error; # use std::io; # use std::process; # -fn run() -> Result> { +fn run() -> Result> { let mut rdr = csv::Reader::from_reader(io::stdin()); let mut record = csv::ByteRecord::new(); @@ -2197,15 +2136,12 @@ ```no_run //tutorial-perf-serde-01.rs -extern crate csv; -extern crate serde; -#[macro_use] -extern crate serde_derive; - use std::error::Error; use std::io; use std::process; +use serde::Deserialize; + #[derive(Debug, Deserialize)] #[serde(rename_all = "PascalCase")] struct Record { @@ -2218,7 +2154,7 @@ longitude: f64, } -fn run() -> Result> { +fn run() -> Result> { let mut rdr = csv::Reader::from_reader(io::stdin()); let mut count = 0; @@ -2269,15 +2205,12 @@ ```no_run //tutorial-perf-serde-02.rs -# extern crate csv; -# extern crate serde; -# #[macro_use] -# extern crate serde_derive; -# # use std::error::Error; # use std::io; # use std::process; # +# use serde::Deserialize; +# #[derive(Debug, Deserialize)] #[serde(rename_all = "PascalCase")] struct Record<'a> { @@ -2290,7 +2223,7 @@ longitude: f64, } -fn run() -> Result> { +fn run() -> Result> { let mut rdr = csv::Reader::from_reader(io::stdin()); let mut raw_record = csv::StringRecord::new(); let headers = rdr.headers()?.clone(); @@ -2359,15 +2292,12 @@ ```no_run //tutorial-perf-serde-03.rs -# extern crate csv; -# extern crate serde; -# #[macro_use] -# extern crate serde_derive; -# # use std::error::Error; # use std::io; # use std::process; # +# use serde::Deserialize; +# #[derive(Debug, Deserialize)] #[serde(rename_all = "PascalCase")] struct Record<'a> { @@ -2380,7 +2310,7 @@ longitude: f64, } -fn run() -> Result> { +fn run() -> Result> { let mut rdr = csv::Reader::from_reader(io::stdin()); let mut raw_record = csv::ByteRecord::new(); let headers = rdr.byte_headers()?.clone(); @@ -2459,8 +2389,6 @@ ```no_run //tutorial-perf-core-01.rs -extern crate csv_core; - use std::io::{self, Read}; use std::process; diff -Nru rust-csv-1.0.5/src/writer.rs rust-csv-1.1.1/src/writer.rs --- rust-csv-1.0.5/src/writer.rs 2018-08-23 11:47:48.000000000 +0000 +++ rust-csv-1.1.1/src/writer.rs 2019-07-01 15:41:15.000000000 +0000 @@ -1,25 +1,18 @@ -use std::fmt; use std::fs::File; use std::io; -use std::mem; use std::path::Path; use std::result; use csv_core::{ - self, - Writer as CoreWriter, + self, WriteResult, Writer as CoreWriter, WriterBuilder as CoreWriterBuilder, - WriteResult, }; use serde::Serialize; -use byte_record::ByteRecord; -use error::{ - ErrorKind, Result, IntoInnerError, - new_error, new_into_inner_error, -}; -use serializer::{serialize, serialize_header}; -use {QuoteStyle, Terminator}; +use crate::byte_record::ByteRecord; +use crate::error::{Error, ErrorKind, IntoInnerError, Result}; +use crate::serializer::{serialize, serialize_header}; +use crate::{QuoteStyle, Terminator}; /// Builds a CSV writer with various configuration knobs. /// @@ -38,7 +31,7 @@ fn default() -> WriterBuilder { WriterBuilder { builder: CoreWriterBuilder::default(), - capacity: 8 * (1<<10), + capacity: 8 * (1 << 10), flexible: false, has_headers: true, } @@ -54,13 +47,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::WriterBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new().from_writer(vec![]); /// wtr.write_record(&["a", "b", "c"])?; /// wtr.write_record(&["x", "y", "z"])?; @@ -83,13 +74,11 @@ /// # Example /// /// ```no_run - /// extern crate csv; - /// /// use std::error::Error; /// use csv::WriterBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new().from_path("foo.csv")?; /// wtr.write_record(&["a", "b", "c"])?; /// wtr.write_record(&["x", "y", "z"])?; @@ -109,13 +98,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::WriterBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new().from_writer(vec![]); /// wtr.write_record(&["a", "b", "c"])?; /// wtr.write_record(&["x", "y", "z"])?; @@ -136,13 +123,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::WriterBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new() /// .delimiter(b';') /// .from_writer(vec![]); @@ -178,12 +163,10 @@ /// names of a struct. /// /// ``` - /// extern crate csv; - /// #[macro_use] - /// extern crate serde_derive; - /// /// use std::error::Error; + /// /// use csv::WriterBuilder; + /// use serde::Serialize; /// /// #[derive(Serialize)] /// struct Row<'a> { @@ -196,7 +179,7 @@ /// } /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new().from_writer(vec![]); /// wtr.serialize(Row { /// city: "Boston", @@ -227,13 +210,11 @@ /// explicitly want to both write custom headers and serialize structs. /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::WriterBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new().from_writer(vec![]); /// wtr.serialize(("Boston", "United States", 4628910))?; /// wtr.serialize(("Concord", "United States", 42695))?; @@ -262,13 +243,11 @@ /// # Example: writing flexible records /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::WriterBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new() /// .flexible(true) /// .from_writer(vec![]); @@ -284,13 +263,11 @@ /// # Example: error when `flexible` is disabled /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::WriterBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new() /// .flexible(false) /// .from_writer(vec![]); @@ -325,13 +302,11 @@ /// This shows how to use RFC 4180 compliant record terminators. /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{Terminator, WriterBuilder}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new() /// .terminator(Terminator::CRLF) /// .from_writer(vec![]); @@ -343,10 +318,7 @@ /// Ok(()) /// } /// ``` - pub fn terminator( - &mut self, - term: Terminator, - ) -> &mut WriterBuilder { + pub fn terminator(&mut self, term: Terminator) -> &mut WriterBuilder { self.builder.terminator(term.to_core()); self } @@ -364,13 +336,11 @@ /// This shows how to quote non-numeric fields only. /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{QuoteStyle, WriterBuilder}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new() /// .quote_style(QuoteStyle::NonNumeric) /// .from_writer(vec![]); @@ -389,13 +359,11 @@ /// if it sacrifices the integrity of the data. /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{QuoteStyle, WriterBuilder}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new() /// .quote_style(QuoteStyle::Never) /// .from_writer(vec![]); @@ -419,13 +387,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::WriterBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new() /// .quote(b'\'') /// .from_writer(vec![]); @@ -450,13 +416,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::WriterBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new() /// .double_quote(false) /// .from_writer(vec![]); @@ -484,13 +448,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::WriterBuilder; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new() /// .double_quote(false) /// .escape(b'$') @@ -614,13 +576,11 @@ /// # Example /// /// ```no_run - /// extern crate csv; - /// /// use std::error::Error; /// use csv::Writer; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = Writer::from_path("foo.csv")?; /// wtr.write_record(&["a", "b", "c"])?; /// wtr.write_record(&["x", "y", "z"])?; @@ -635,19 +595,15 @@ impl Writer { fn new(builder: &WriterBuilder, wtr: W) -> Writer { - let header_state = - if builder.has_headers { - HeaderState::Write - } else { - HeaderState::None - }; + let header_state = if builder.has_headers { + HeaderState::Write + } else { + HeaderState::None + }; Writer { core: builder.builder.build(), wtr: Some(wtr), - buf: Buffer { - buf: vec![0; builder.capacity], - len: 0, - }, + buf: Buffer { buf: vec![0; builder.capacity], len: 0 }, state: WriterState { header: header_state, flexible: builder.flexible, @@ -667,13 +623,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::Writer; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = Writer::from_writer(vec![]); /// wtr.write_record(&["a", "b", "c"])?; /// wtr.write_record(&["x", "y", "z"])?; @@ -698,12 +652,10 @@ /// calling the `has_headers` method.) /// /// ``` - /// extern crate csv; - /// #[macro_use] - /// extern crate serde_derive; - /// /// use std::error::Error; + /// /// use csv::Writer; + /// use serde::Serialize; /// /// #[derive(Serialize)] /// struct Row<'a> { @@ -716,7 +668,7 @@ /// } /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = Writer::from_writer(vec![]); /// wtr.serialize(Row { /// city: "Boston", @@ -765,7 +717,7 @@ /// | Name | Example Type | Example Value | Output | /// | ---- | ---- | ---- | ---- | /// | boolean | `bool` | `true` | `true` | - /// | integers | `i8`, `i16`, `i32`, `i64`, `u8`, `u16`, `u32`, `u64` | `5` | `5` | + /// | integers | `i8`, `i16`, `i32`, `i64`, `i128`, `u8`, `u16`, `u32`, `u64`, `u128` | `5` | `5` | /// | floats | `f32`, `f64` | `3.14` | `3.14` | /// | character | `char` | `'☃'` | `☃` | /// | string | `&str` | `"hi"` | `hi` | @@ -783,12 +735,10 @@ /// this: /// /// ``` - /// extern crate csv; - /// #[macro_use] - /// extern crate serde_derive; - /// /// use std::error::Error; + /// /// use csv::Writer; + /// use serde::Serialize; /// /// #[derive(Serialize)] /// struct Row { @@ -803,7 +753,7 @@ /// } /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = Writer::from_writer(vec![]); /// wtr.serialize(Row { /// label: "foo".to_string(), @@ -851,12 +801,10 @@ /// types can be nested arbitrarily. For example: /// /// ``` - /// extern crate csv; - /// #[macro_use] - /// extern crate serde_derive; - /// /// use std::error::Error; + /// /// use csv::WriterBuilder; + /// use serde::Serialize; /// /// #[derive(Serialize)] /// struct Row { @@ -865,7 +813,7 @@ /// } /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = WriterBuilder::new() /// .has_headers(false) /// .from_writer(vec![]); @@ -928,13 +876,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::Writer; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = Writer::from_writer(vec![]); /// wtr.write_record(&["a", "b", "c"])?; /// wtr.write_record(&["x", "y", "z"])?; @@ -945,7 +891,9 @@ /// } /// ``` pub fn write_record(&mut self, record: I) -> Result<()> - where I: IntoIterator, T: AsRef<[u8]> + where + I: IntoIterator, + T: AsRef<[u8]>, { for field in record.into_iter() { self.write_field_impl(field)?; @@ -969,13 +917,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::{ByteRecord, Writer}; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = Writer::from_writer(vec![]); /// wtr.write_byte_record(&ByteRecord::from(&["a", "b", "c"][..]))?; /// wtr.write_byte_record(&ByteRecord::from(&["x", "y", "z"][..]))?; @@ -1029,7 +975,8 @@ self.buf.writable(), self.core.get_quote(), self.core.get_escape(), - self.core.get_double_quote()); + self.core.get_double_quote(), + ); debug_assert!(res == WriteResult::InputEmpty); debug_assert!(nin == field.len()); self.buf.written(nout); @@ -1053,13 +1000,11 @@ /// # Example /// /// ``` - /// extern crate csv; - /// /// use std::error::Error; /// use csv::Writer; /// /// # fn main() { example().unwrap(); } - /// fn example() -> Result<(), Box> { + /// fn example() -> Result<(), Box> { /// let mut wtr = Writer::from_writer(vec![]); /// wtr.write_field("a")?; /// wtr.write_field("b")?; @@ -1085,8 +1030,22 @@ /// into write_record. #[inline(always)] fn write_field_impl>(&mut self, field: T) -> Result<()> { - let mut sfw = SingleFieldWriter::start_field(self)?; - sfw.append(field.as_ref()) + if self.state.fields_written > 0 { + self.write_delimiter()?; + } + let mut field = field.as_ref(); + loop { + let (res, nin, nout) = self.core.field(field, self.buf.writable()); + field = &field[nin..]; + self.buf.written(nout); + match res { + WriteResult::InputEmpty => { + self.state.fields_written += 1; + return Ok(()); + } + WriteResult::OutputFull => self.flush()?, + } + } } /// Flush the contents of the internal buffer to the underlying writer. @@ -1112,7 +1071,7 @@ ) -> result::Result>> { match self.flush() { Ok(()) => Ok(self.wtr.take().unwrap()), - Err(err) => Err(new_into_inner_error(self, err)), + Err(err) => Err(IntoInnerError::new(self, err)), } } @@ -1173,7 +1132,7 @@ Some(self.state.fields_written); } Some(expected) if expected != self.state.fields_written => { - return Err(new_error(ErrorKind::UnequalLengths { + return Err(Error::new(ErrorKind::UnequalLengths { pos: None, expected_len: expected, len: self.state.fields_written, @@ -1186,67 +1145,6 @@ } } -/// A structure to allow progressively writing a single field, and thus -/// constructing a field from types implementing fmt::* traits directly -/// into a Writer's internal buffer. -/// -/// This is public within this module so it can be used elsewhere -/// within this crate (serialization, in particular), but isn't -/// exposed for public use. If an error occurs using the fmt -/// interface, the csv::Error is saved inside this type in a sticky -/// way (i.e. further formatting calls do nothing and return -/// fmt::Error too) and is accessible via take_formatting_error, which -/// clears it. -pub struct SingleFieldWriter<'a, W: io::Write + 'a> { - wtr: &'a mut Writer, - error: Result<()>, -} - -impl<'a, W: io::Write> SingleFieldWriter<'a, W> { - pub fn start_field(wtr: &'a mut Writer) -> Result { - if wtr.state.fields_written > 0 { - wtr.write_delimiter()?; - } - - Ok(SingleFieldWriter { wtr: wtr, error: Ok(()) }) - } - - pub fn append(&mut self, mut data: &[u8]) -> Result<()> { - loop { - let (res, nin, nout) = self.wtr.core.field(data, self.wtr.buf.writable()); - data = &data[nin..]; - self.wtr.buf.written(nout); - match res { - WriteResult::InputEmpty => { - return Ok(()); - } - WriteResult::OutputFull => self.wtr.flush()?, - } - } - } - - pub fn take_formatting_error(&mut self) -> Result<()> { - mem::replace(&mut self.error, Ok(())) - } -} -impl<'a, W: io::Write> fmt::Write for SingleFieldWriter<'a, W> { - fn write_str(&mut self, s: &str) -> fmt::Result { - if self.error.is_err() { return Err(fmt::Error) } - - self.error = self.append(s.as_bytes()); - if self.error.is_ok() { - Ok(()) - } else { - Err(fmt::Error) - } - } -} -impl<'a, W: io::Write> Drop for SingleFieldWriter<'a, W> { - fn drop(&mut self) { - self.wtr.state.fields_written += 1; - } -} - impl Buffer { /// Returns a slice of the buffer's current contents. /// @@ -1279,9 +1177,11 @@ #[cfg(test)] mod tests { - use byte_record::ByteRecord; - use error::ErrorKind; - use string_record::StringRecord; + use serde::{serde_if_integer128, Serialize}; + + use crate::byte_record::ByteRecord; + use crate::error::ErrorKind; + use crate::string_record::StringRecord; use super::{Writer, WriterBuilder}; @@ -1376,8 +1276,8 @@ fn raw_unequal_records_bad() { let mut wtr = WriterBuilder::new().from_writer(vec![]); wtr.write_byte_record(&ByteRecord::from(vec!["a", "b", "c"])).unwrap(); - let err = wtr.write_byte_record( - &ByteRecord::from(vec!["a"])).unwrap_err(); + let err = + wtr.write_byte_record(&ByteRecord::from(vec!["a"])).unwrap_err(); match *err.kind() { ErrorKind::UnequalLengths { ref pos, expected_len, len } => { assert!(pos.is_none()); @@ -1429,13 +1329,33 @@ baz: bool, } - let mut wtr = WriterBuilder::new() - .has_headers(false) - .from_writer(vec![]); + let mut wtr = + WriterBuilder::new().has_headers(false).from_writer(vec![]); wtr.serialize(Row { foo: 42, bar: 42.5, baz: true }).unwrap(); assert_eq!(wtr_as_string(wtr), "42,42.5,true\n"); } + serde_if_integer128! { + #[test] + fn serialize_no_headers_128() { + #[derive(Serialize)] + struct Row { + foo: i128, + bar: f64, + baz: bool, + } + + let mut wtr = + WriterBuilder::new().has_headers(false).from_writer(vec![]); + wtr.serialize(Row { + foo: 9_223_372_036_854_775_808, + bar: 42.5, + baz: true, + }).unwrap(); + assert_eq!(wtr_as_string(wtr), "9223372036854775808,42.5,true\n"); + } + } + #[test] fn serialize_tuple() { let mut wtr = WriterBuilder::new().from_writer(vec![]); diff -Nru rust-csv-1.0.5/tests/tests.rs rust-csv-1.1.1/tests/tests.rs --- rust-csv-1.0.5/tests/tests.rs 2018-12-16 13:02:51.000000000 +0000 +++ rust-csv-1.1.1/tests/tests.rs 2019-06-26 23:51:53.000000000 +0000 @@ -1,7 +1,5 @@ #![allow(dead_code)] -extern crate csv; - use std::env; use std::io::{self, Write}; use std::path::PathBuf; @@ -9,12 +7,17 @@ static STRANGE: &'static str = include_str!("../examples/data/strange.csv"); static USPOP: &'static str = include_str!("../examples/data/uspop.csv"); -static USPOP_NULL: &'static str = include_str!("../examples/data/uspop-null.csv"); -static USPOP_LATIN1: &'static [u8] = include_bytes!("../examples/data/uspop-latin1.csv"); -static WORLDPOP: &'static str = include_str!("../examples/data/bench/worldcitiespop.csv"); +static USPOP_NULL: &'static str = + include_str!("../examples/data/uspop-null.csv"); +static USPOP_LATIN1: &'static [u8] = + include_bytes!("../examples/data/uspop-latin1.csv"); +static WORLDPOP: &'static str = + include_str!("../examples/data/bench/worldcitiespop.csv"); static SMALLPOP: &'static str = include_str!("../examples/data/smallpop.csv"); -static SMALLPOP_COLON: &'static str = include_str!("../examples/data/smallpop-colon.csv"); -static SMALLPOP_NO_HEADERS: &'static str = include_str!("../examples/data/smallpop-no-headers.csv"); +static SMALLPOP_COLON: &'static str = + include_str!("../examples/data/smallpop-colon.csv"); +static SMALLPOP_NO_HEADERS: &'static str = + include_str!("../examples/data/smallpop-no-headers.csv"); #[test] fn cookbook_read_basic() { @@ -412,12 +415,11 @@ /// /// If the command has a non-zero exit code, then this function panics. fn new(cmd: &mut Command, child: process::Child) -> Output { - let out = child.wait_with_output() - .expect("command runs successfully"); - let stdout = String::from_utf8(out.stdout) - .expect("valid utf-8 (stdout)"); - let stderr = String::from_utf8(out.stderr) - .expect("valid utf-8 (stderr)"); + let out = child.wait_with_output().expect("command runs successfully"); + let stdout = + String::from_utf8(out.stdout).expect("valid utf-8 (stdout)"); + let stderr = + String::from_utf8(out.stderr).expect("valid utf-8 (stderr)"); Output { stdout: stdout, stderr: stderr, @@ -436,8 +438,12 @@ \n\nstdout: {}\ \n\nstderr: {}\ \n\n=====\n", - self.command, repo_dir().display(), - self.status, self.stdout, self.stderr); + self.command, + repo_dir().display(), + self.status, + self.stdout, + self.stderr + ); } &self.stdout } @@ -452,8 +458,12 @@ \n\nstdout: {}\ \n\nstderr: {}\ \n\n=====\n", - self.command, repo_dir().display(), - self.status, self.stdout, self.stderr); + self.command, + repo_dir().display(), + self.status, + self.stdout, + self.stderr + ); } &self.stdout } @@ -468,8 +478,12 @@ \n\nstdout: {}\ \n\nstderr: {}\ \n\n=====\n", - self.command, repo_dir().display(), - self.status, self.stdout, self.stderr); + self.command, + repo_dir().display(), + self.status, + self.stdout, + self.stderr + ); } &self.stderr }