Repository: BurntSushi/rust-csv (language: rust)

Issue:
Attempt to add supprt for i128 and u128
Issue 149.

In the infer_deserialize functions I ended up adding try_positive_integer_64 and try_negative_integer_64, this was to keep a couple of existing unit tests happy, but I'm not 100% sure if that was a good idea, any feedback on that would be welcome.
Support for serializing/deserializing 128-bit integers
#### What version of the `csv` crate are you using?

1.0.5"

#### Briefly describe the question, bug or feature request.

I would like to serialise and deserialise 128-bit integers.

#### Include a complete program demonstrating a problem.

    #[test]
    fn integer_128() {
        let got = serialize(12345_u128);
        assert_eq!(got, "12345\n");
    }

#### What is the observed behavior of the code above?

`---- serializer::tests::integer_128 stdout ----
thread 'serializer::tests::integer_128' panicked at 'called `Result::unwrap()` on an `Err` value: Error(Serialize("u128 is not supported"))', src/libcore/result.rs:997:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.`

#### What is the expected or desired behavior of the code above?

The integer would be serialised.


Discussion / hints:

I attempted to add support for what I need here:

https://github.com/ian-hamlin/rust-csv

And I added a sample app here:

https://github.com/ian-hamlin/rust-csv-128

It all seems to work OK, when pointing at my branch, but I'm not really sure I covered all the bases.
@ian-hamlin Thanks! Do you want to submit a PR?

Fix patch:
diff --git a/.travis.yml b/.travis.yml
index a742395c..139472ef 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
 dist: trusty
 language: rust
 rust:
-  - 1.15.0
+  - 1.33.0
   - stable
   - beta
   - nightly
diff --git a/Cargo.toml b/Cargo.toml
index 05f2b257..a3df4264 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,6 +11,7 @@ keywords = ["csv", "comma", "parser", "delimited", "serde"]
 license = "Unlicense/MIT"
 categories = ["encoding", "parser-implementations"]
 exclude = ["/.travis.yml", "/appveyor.yml", "/ci/*", "/scripts/*"]
+edition = "2018"
 
 [badges]
 travis-ci = { repository = "BurntSushi/rust-csv" }
@@ -23,14 +24,14 @@ members = ["csv-core", "csv-index"]
 bench = false
 
 [dependencies]
+bstr = { version = "0.2.1", features = ["serde1"] }
 csv-core = { path = "csv-core", version = "0.1.4" }
 itoa = "0.4.3"
-ryu = "0.2.7"
+ryu = "1"
 serde = "1.0.55"
 
 [dev-dependencies]
-serde_derive = "1.0.55"
-serde_bytes = "0.10.4"
+serde = { version = "1.0.55", features = ["derive"] }
 
 [profile.release]
 debug = true
diff --git a/README.md b/README.md
index 74030c44..d66c55b5 100644
--- a/README.md
+++ b/README.md
@@ -24,13 +24,7 @@ Add this to your `Cargo.toml`:
 
 ```toml
 [dependencies]
-csv = "1"
-```
-
-and this to your crate root:
-
-```rust
-extern crate csv;
+csv = "1.1"
 ```
 
 ### Example
@@ -42,13 +36,11 @@ There are more examples in the
 [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<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     // 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 @@ By default, the member names of the struct are matched with the values in the
 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 @@ struct Record {
     population: Option<u64>,
 }
 
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     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 --git a/benches/bench.rs b/benches/bench.rs
index de1b2e78..2d742e75 100644
--- a/benches/bench.rs
+++ b/benches/bench.rs
@@ -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 @@ struct MBTARowBorrowed<'a> {
 
 #[derive(Default)]
 struct ByteCounter {
-    count: usize
+    count: usize,
 }
 impl io::Write for ByteCounter {
     fn write(&mut self, data: &[u8]) -> io::Result<usize> {
         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 @@ macro_rules! bench {
             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_trimmed {
     };
 }
 
-
 macro_rules! bench_serde {
     (no_headers,
      $name_de:ident, $name_ser:ident, $data:ident, $counter:ident, $type:ty, $result:expr) => {
@@ -166,9 +163,8 @@ macro_rules! bench_serde {
             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 @@ macro_rules! bench_serde {
             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 @@ macro_rules! bench_serde_borrowed_bytes {
                 count
             })
         }
-    }
+    };
 }
 
 macro_rules! bench_serde_borrowed_str {
@@ -279,21 +274,39 @@ macro_rules! bench_serde_borrowed_str {
                 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 @@ bench_serde!(
     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!(count_game_read_str, GAME, count_read_str, 600000);
 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!(count_pop_read_str, POP, count_read_str, 140007);
 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 @@ macro_rules! bench_write {
                 assert!(wtr.flush().is_ok());
             })
         }
-    }
+    };
 }
 
 macro_rules! bench_write_bytes {
@@ -392,14 +453,16 @@ macro_rules! bench_write_bytes {
                 assert!(wtr.flush().is_ok());
             })
         }
-    }
+    };
 }
 
 bench_write!(write_nfl_record, NFL);
 bench_write_bytes!(write_nfl_bytes, NFL);
 
 fn count_deserialize_owned_bytes<R, D>(rdr: &mut Reader<R>) -> 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_bytes<R, D>(rdr: &mut Reader<R>) -> u64
 }
 
 fn count_deserialize_owned_str<R, D>(rdr: &mut Reader<R>) -> u64
-    where R: io::Read, D: DeserializeOwned
+where
+    R: io::Read,
+    D: DeserializeOwned,
 {
     let mut count = 0;
     for rec in rdr.deserialize::<D>() {
@@ -456,10 +521,6 @@ fn count_read_str<R: io::Read>(rdr: &mut Reader<R>) -> u64 {
 }
 
 fn collect_records(data: &[u8]) -> Vec<ByteRecord> {
-    let mut rdr = ReaderBuilder::new()
-        .has_headers(false)
-        .from_reader(data);
-    rdr.byte_records()
-        .collect::<Result<Vec<_>, _>>()
-        .unwrap()
+    let mut rdr = ReaderBuilder::new().has_headers(false).from_reader(data);
+    rdr.byte_records().collect::<Result<Vec<_>, _>>().unwrap()
 }
diff --git a/ci/check-copy b/ci/check-copy
index 576ba0e9..be6263ea 100755
--- a/ci/check-copy
+++ b/ci/check-copy
@@ -19,6 +19,8 @@ errored() {
     exit 1
 }
 
+# Make sure the right rustfmt config is available.
+cp "$REPO/rustfmt.toml" "$TMPDIR/"
 "$SCRIPTS/copy-examples" \
   --rust-file "$REPO/src/$SOURCE.rs" \
   --example-dir "$TMPDIR"
diff --git a/ci/script.sh b/ci/script.sh
index d3c22fcf..17f851cd 100755
--- a/ci/script.sh
+++ b/ci/script.sh
@@ -2,13 +2,16 @@
 
 set -ex
 
-ci/check-copy cookbook
-ci/check-copy tutorial
 cargo build --verbose
 cargo doc --verbose
 cargo test --verbose
 cargo test --verbose --manifest-path csv-core/Cargo.toml
 cargo test --verbose --manifest-path csv-index/Cargo.toml
 if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
+  rustup component add rustfmt --toolchain nightly-x86_64-unknown-linux-gnu
+
+  cargo fmt -- --check
+  ci/check-copy cookbook
+  ci/check-copy tutorial
   cargo bench --verbose --no-run
 fi
diff --git a/csv-core/Cargo.toml b/csv-core/Cargo.toml
index f40f96f3..27ff5847 100644
--- a/csv-core/Cargo.toml
+++ b/csv-core/Cargo.toml
@@ -11,6 +11,7 @@ keywords = ["csv", "comma", "parser", "delimited", "no_std"]
 license = "Unlicense/MIT"
 categories = ["encoding", "no-std", "parser-implementations"]
 workspace = ".."
+edition = "2018"
 
 [badges]
 travis-ci = { repository = "BurntSushi/rust-csv" }
diff --git a/csv-core/README.md b/csv-core/README.md
index 6fad1531..d3efde3c 100644
--- a/csv-core/README.md
+++ b/csv-core/README.md
@@ -19,13 +19,7 @@ Add this to your `Cargo.toml`:
 
 ```toml
 [dependencies]
-csv-core = "0.1"
-```
-
-and this to your crate root:
-
-```rust
-extern crate csv_core;
+csv-core = "0.2"
 ```
 
 ### Build features
diff --git a/csv-core/benches/bench.rs b/csv-core/benches/bench.rs
index 3afceb73..2aa24a92 100644
--- a/csv-core/benches/bench.rs
+++ b/csv-core/benches/bench.rs
@@ -1,6 +1,5 @@
 #![feature(test)]
 
-extern crate csv_core;
 extern crate test;
 
 use test::Bencher;
@@ -9,8 +8,10 @@ use csv_core::{Reader, ReaderBuilder};
 
 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 = include_str!("../../examples/data/bench/gtfs-mbta-stop-times.csv");
+static POP: &'static str =
+    include_str!("../../examples/data/bench/worldcitiespop.csv");
+static MBTA: &'static str =
+    include_str!("../../examples/data/bench/gtfs-mbta-stop-times.csv");
 
 macro_rules! bench {
     ($name:ident, $data:ident, $counter:ident, $result:expr) => {
@@ -64,7 +65,9 @@ fn count_fields(rdr: &mut Reader, mut data: &[u8]) -> u64 {
         match res {
             InputEmpty => {}
             OutputFull => panic!("field too large"),
-            Field{..} => { count += 1; }
+            Field { .. } => {
+                count += 1;
+            }
             End => break,
         }
     }
diff --git a/csv-core/src/lib.rs b/csv-core/src/lib.rs
index 2f46213a..747e58d1 100644
--- a/csv-core/src/lib.rs
+++ b/csv-core/src/lib.rs
@@ -99,16 +99,13 @@ foo,\"bar,baz\"
 #![deny(missing_docs)]
 #![no_std]
 
-#[cfg(test)]
-extern crate arrayvec;
-extern crate memchr;
-
-pub use reader::{
-    Reader, ReaderBuilder,
-    ReadFieldResult, ReadFieldNoCopyResult,
-    ReadRecordResult, ReadRecordNoCopyResult,
+pub use crate::reader::{
+    ReadFieldNoCopyResult, ReadFieldResult, ReadRecordNoCopyResult,
+    ReadRecordResult, Reader, ReaderBuilder,
+};
+pub use crate::writer::{
+    is_non_numeric, quote, WriteResult, Writer, WriterBuilder,
 };
-pub use writer::{Writer, WriterBuilder, WriteResult, is_non_numeric, quote};
 
 mod reader;
 mod writer;
diff --git a/csv-core/src/reader.rs b/csv-core/src/reader.rs
index 3ac2c3ca..c148623c 100644
--- a/csv-core/src/reader.rs
+++ b/csv-core/src/reader.rs
@@ -1,6 +1,6 @@
 use core::fmt;
 
-use Terminator;
+use crate::Terminator;
 
 // BE ADVISED
 //
@@ -185,10 +185,7 @@ impl ReaderBuilder {
     /// A record terminator can be any single byte. The default is a special
     /// value, `Terminator::CRLF`, which treats any occurrence of `\r`, `\n`
     /// or `\r\n` as a single record terminator.
-    pub fn terminator(
-        &mut self,
-        term: Terminator,
-    ) -> &mut ReaderBuilder {
+    pub fn terminator(&mut self, term: Terminator) -> &mut ReaderBuilder {
         self.rdr.term = term;
         self
     }
@@ -470,9 +467,7 @@ impl NfaState {
     /// Returns true if this state indicates that a record has been parsed.
     fn is_record_final(&self) -> bool {
         match *self {
-            NfaState::End
-            | NfaState::EndRecord
-            | NfaState::CRLF => true,
+            NfaState::End | NfaState::EndRecord | NfaState::CRLF => true,
             _ => false,
         }
     }
@@ -616,9 +611,9 @@ impl Reader {
     /// buffered. Hopefully that won't happen very often.
     fn strip_utf8_bom<'a>(&self, input: &'a [u8]) -> (&'a [u8], usize) {
         let (input, nin) = if {
-            !self.has_read &&
-                input.len() >= 3 &&
-                &input[0..3] == b"\xef\xbb\xbf"
+            !self.has_read
+                && input.len() >= 3
+                && &input[0..3] == b"\xef\xbb\xbf"
         } {
             (&input[3..], 3)
         } else {
@@ -636,8 +631,8 @@ impl Reader {
     ) -> (ReadRecordResult, usize, usize, usize) {
         if input.is_empty() {
             let s = self.transition_final_dfa(self.dfa_state);
-            let res = self.dfa.new_read_record_result(
-                s, true, false, false, false);
+            let res =
+                self.dfa.new_read_record_result(s, true, false, false, false);
             // This part is a little tricky. When reading the final record,
             // the last result the caller will get is an InputEmpty, and while
             // they'll have everything they need in `output`, they'll be
@@ -686,15 +681,18 @@ impl Reader {
                 }
             }
             if state == self.dfa.in_field || state == self.dfa.in_quoted {
-                self.dfa.classes.scan_and_copy(
-                    input, &mut nin, output, &mut nout);
+                self.dfa
+                    .classes
+                    .scan_and_copy(input, &mut nin, output, &mut nout);
             }
         }
         let res = self.dfa.new_read_record_result(
-            state, false,
+            state,
+            false,
             nin >= input.len(),
             nout >= output.len(),
-            nend >= ends.len());
+            nend >= ends.len(),
+        );
         self.dfa_state = state;
         if res.is_record() {
             self.output_pos = 0;
@@ -713,7 +711,11 @@ impl Reader {
         if input.is_empty() {
             self.dfa_state = self.transition_final_dfa(self.dfa_state);
             let res = self.dfa.new_read_field_result(
-                self.dfa_state, true, false, false);
+                self.dfa_state,
+                true,
+                false,
+                false,
+            );
             return (res, 0, 0);
         }
         if output.is_empty() {
@@ -736,7 +738,11 @@ impl Reader {
             }
         }
         let res = self.dfa.new_read_field_result(
-            state, false, nin >= input.len(), nout >= output.len());
+            state,
+            false,
+            nin >= input.len(),
+            nout >= output.len(),
+        );
         self.dfa_state = state;
         (res, nin, nout)
     }
@@ -820,8 +826,7 @@ impl Reader {
             for c in (0..256).map(|c| c as u8) {
                 let mut nfa_result = (state, NfaInputAction::Epsilon);
                 // Consume NFA states until we hit a non-epsilon transition.
-                while
-                    nfa_result.0 != NfaState::End
+                while nfa_result.0 != NfaState::End
                     && nfa_result.1 == NfaInputAction::Epsilon
                 {
                     nfa_result = self.transition_nfa(nfa_result.0, c);
@@ -829,7 +834,11 @@ impl Reader {
                 let from = self.dfa.new_state(state);
                 let to = self.dfa.new_state(nfa_result.0);
                 self.dfa.set(
-                    from, c, to, nfa_result.1 == NfaInputAction::CopyToOutput);
+                    from,
+                    c,
+                    to,
+                    nfa_result.1 == NfaInputAction::CopyToOutput,
+                );
             }
         }
         self.dfa_state = self.dfa.new_state(NfaState::StartRecord);
@@ -882,10 +891,10 @@ impl Reader {
                     output[nout] = input[nin];
                     nout += 1;
                     nin += 1;
-                },
+                }
                 NfaInputAction::Discard => {
                     nin += 1;
-                },
+                }
                 NfaInputAction::Epsilon => {}
             }
             state = s;
@@ -901,7 +910,8 @@ impl Reader {
             state,
             nin >= input.len(),
             nout >= output.len(),
-            nend >= ends.len());
+            nend >= ends.len(),
+        );
         self.nfa_state = state;
         self.output_pos = if res.is_record() { 0 } else { nout };
         (res, nin, nout, nend)
@@ -932,11 +942,11 @@ impl Reader {
                     output[nout] = input[nin];
                     nout += 1;
                     nin += 1;
-                },
+                }
                 NfaInputAction::Discard => {
                     nin += 1;
-                },
-                NfaInputAction::Epsilon => ()
+                }
+                NfaInputAction::Epsilon => (),
             }
             state = s;
             if state.is_field_final() {
@@ -944,7 +954,10 @@ impl Reader {
             }
         }
         let res = ReadFieldResult::from_nfa(
-            state, nin >= input.len(), nout >= output.len());
+            state,
+            nin >= input.len(),
+            nout >= output.len(),
+        );
         self.nfa_state = state;
         (res, nin, nout)
     }
@@ -955,23 +968,13 @@ impl Reader {
     fn transition_final_nfa(&self, state: NfaState) -> NfaState {
         use self::NfaState::*;
         match state {
-            End
-            | StartRecord
-            | EndRecord
-            | InComment
-            | CRLF => End,
-            StartField
-            | EndFieldDelim
-            | EndFieldTerm
-            | InField
-            | InQuotedField
-            | InEscapedQuote
-            | InDoubleEscapedQuote
+            End | StartRecord | EndRecord | InComment | CRLF => End,
+            StartField | EndFieldDelim | EndFieldTerm | InField
+            | InQuotedField | InEscapedQuote | InDoubleEscapedQuote
             | InRecordTerm => EndRecord,
         }
     }
 
-
     /// Compute the next NFA state given the current NFA state and the current
     /// input byte.
     ///
@@ -996,9 +999,7 @@ impl Reader {
                     (StartField, NfaInputAction::Epsilon)
                 }
             }
-            EndRecord => {
-                (StartRecord, NfaInputAction::Epsilon)
-            }
+            EndRecord => (StartRecord, NfaInputAction::Epsilon),
             StartField => {
                 if self.quoting && self.quote == c {
                     (InQuotedField, NfaInputAction::Discard)
@@ -1010,12 +1011,8 @@ impl Reader {
                     (InField, NfaInputAction::CopyToOutput)
                 }
             }
-            EndFieldDelim => {
-                (StartField, NfaInputAction::Epsilon)
-            }
-            EndFieldTerm => {
-                (InRecordTerm, NfaInputAction::Epsilon)
-            }
+            EndFieldDelim => (StartField, NfaInputAction::Epsilon),
+            EndFieldTerm => (InRecordTerm, NfaInputAction::Epsilon),
             InField => {
                 if self.delimiter == c {
                     (EndFieldDelim, NfaInputAction::Discard)
@@ -1034,9 +1031,7 @@ impl Reader {
                     (InQuotedField, NfaInputAction::CopyToOutput)
                 }
             }
-            InEscapedQuote => {
-                (InQuotedField, NfaInputAction::CopyToOutput)
-            }
+            InEscapedQuote => (InQuotedField, NfaInputAction::CopyToOutput),
             InDoubleEscapedQuote => {
                 if self.quoting && self.double_quote && self.quote == c {
                     (InQuotedField, NfaInputAction::CopyToOutput)
@@ -1268,8 +1263,7 @@ impl DfaClasses {
         output: &mut [u8],
         nout: &mut usize,
     ) {
-        while
-            *nin < input.len()
+        while *nin < input.len()
             && *nout < output.len()
             && self.classes[input[*nin] as usize] == 0
         {
@@ -1310,7 +1304,8 @@ impl fmt::Debug for DfaClasses {
         write!(
             f,
             "DfaClasses {{ classes: N/A, next_class: {:?} }}",
-            self.next_class)
+            self.next_class
+        )
     }
 }
 
@@ -1336,16 +1331,16 @@ mod tests {
 
     use arrayvec::{ArrayString, ArrayVec};
 
-    use super::{
-        Reader, ReaderBuilder, ReadFieldResult, Terminator,
-    };
+    use super::{ReadFieldResult, Reader, ReaderBuilder, Terminator};
 
     type Csv = ArrayVec<[Row; 10]>;
     type Row = ArrayVec<[Field; 10]>;
     type Field = ArrayString<[u8; 10]>;
 
     // OMG I HATE BYTE STRING LITERALS SO MUCH.
-    fn b(s: &str) -> &[u8] { s.as_bytes() }
+    fn b(s: &str) -> &[u8] {
+        s.as_bytes()
+    }
 
     macro_rules! csv {
         ($([$($field:expr),*]),*) => {{
@@ -1440,7 +1435,7 @@ mod tests {
     }
 
     fn parse_by_record(rdr: &mut Reader, data: &str) -> Csv {
-        use ReadRecordResult::*;
+        use crate::ReadRecordResult::*;
 
         let mut data = data.as_bytes();
         let mut record = [0; 1024];
@@ -1450,7 +1445,10 @@ mod tests {
         let (mut outpos, mut endpos) = (0, 0);
         loop {
             let (res, nin, nout, nend) = rdr.read_record(
-                data, &mut record[outpos..], &mut ends[endpos..]);
+                data,
+                &mut record[outpos..],
+                &mut ends[endpos..],
+            );
             data = &data[nin..];
             outpos += nout;
             endpos += nend;
@@ -1496,78 +1494,111 @@ mod tests {
     parses_to!(many_rows_one_field, "a\nb", csv![["a"], ["b"]]);
     parses_to!(
         many_rows_many_fields,
-       "a,b,c\nx,y,z", csv![["a", "b", "c"], ["x", "y", "z"]]);
+        "a,b,c\nx,y,z",
+        csv![["a", "b", "c"], ["x", "y", "z"]]
+    );
     parses_to!(
         many_rows_trailing_comma,
-        "a,b,\nx,y,", csv![["a", "b", ""], ["x", "y", ""]]);
+        "a,b,\nx,y,",
+        csv![["a", "b", ""], ["x", "y", ""]]
+    );
     parses_to!(many_rows_one_field_lf, "a\nb\n", csv![["a"], ["b"]]);
     parses_to!(
         many_rows_many_fields_lf,
-        "a,b,c\nx,y,z\n", csv![["a", "b", "c"], ["x", "y", "z"]]);
+        "a,b,c\nx,y,z\n",
+        csv![["a", "b", "c"], ["x", "y", "z"]]
+    );
     parses_to!(
         many_rows_trailing_comma_lf,
-        "a,b,\nx,y,\n", csv![["a", "b", ""], ["x", "y", ""]]);
+        "a,b,\nx,y,\n",
+        csv![["a", "b", ""], ["x", "y", ""]]
+    );
     parses_to!(many_rows_one_field_crlf, "a\r\nb\r\n", csv![["a"], ["b"]]);
     parses_to!(
         many_rows_many_fields_crlf,
         "a,b,c\r\nx,y,z\r\n",
-        csv![["a", "b", "c"], ["x", "y", "z"]]);
-    parses_to!(many_rows_trailing_comma_crlf,
-               "a,b,\r\nx,y,\r\n", csv![["a", "b", ""], ["x", "y", ""]]);
+        csv![["a", "b", "c"], ["x", "y", "z"]]
+    );
+    parses_to!(
+        many_rows_trailing_comma_crlf,
+        "a,b,\r\nx,y,\r\n",
+        csv![["a", "b", ""], ["x", "y", ""]]
+    );
     parses_to!(many_rows_one_field_cr, "a\rb\r", csv![["a"], ["b"]]);
     parses_to!(
         many_rows_many_fields_cr,
-        "a,b,c\rx,y,z\r", csv![["a", "b", "c"], ["x", "y", "z"]]);
+        "a,b,c\rx,y,z\r",
+        csv![["a", "b", "c"], ["x", "y", "z"]]
+    );
     parses_to!(
         many_rows_trailing_comma_cr,
-        "a,b,\rx,y,\r", csv![["a", "b", ""], ["x", "y", ""]]);
+        "a,b,\rx,y,\r",
+        csv![["a", "b", ""], ["x", "y", ""]]
+    );
 
     parses_to!(
         trailing_lines_no_record,
         "\n\n\na,b,c\nx,y,z\n\n\n",
-        csv![["a", "b", "c"], ["x", "y", "z"]]);
+        csv![["a", "b", "c"], ["x", "y", "z"]]
+    );
     parses_to!(
         trailing_lines_no_record_cr,
         "\r\r\ra,b,c\rx,y,z\r\r\r",
-        csv![["a", "b", "c"], ["x", "y", "z"]]);
+        csv![["a", "b", "c"], ["x", "y", "z"]]
+    );
     parses_to!(
         trailing_lines_no_record_crlf,
         "\r\n\r\n\r\na,b,c\r\nx,y,z\r\n\r\n\r\n",
-        csv![["a", "b", "c"], ["x", "y", "z"]]);
+        csv![["a", "b", "c"], ["x", "y", "z"]]
+    );
 
     parses_to!(empty, "", csv![]);
     parses_to!(empty_lines, "\n\n\n\n", csv![]);
     parses_to!(
-        empty_lines_interspersed, "\n\na,b\n\n\nx,y\n\n\nm,n\n",
-        csv![["a", "b"], ["x", "y"], ["m", "n"]]);
+        empty_lines_interspersed,
+        "\n\na,b\n\n\nx,y\n\n\nm,n\n",
+        csv![["a", "b"], ["x", "y"], ["m", "n"]]
+    );
     parses_to!(empty_lines_crlf, "\r\n\r\n\r\n\r\n", csv![]);
     parses_to!(
         empty_lines_interspersed_crlf,
         "\r\n\r\na,b\r\n\r\n\r\nx,y\r\n\r\n\r\nm,n\r\n",
-        csv![["a", "b"], ["x", "y"], ["m", "n"]]);
+        csv![["a", "b"], ["x", "y"], ["m", "n"]]
+    );
     parses_to!(empty_lines_mixed, "\r\n\n\r\n\n", csv![]);
     parses_to!(
         empty_lines_interspersed_mixed,
         "\n\r\na,b\r\n\n\r\nx,y\r\n\n\r\nm,n\r\n",
-        csv![["a", "b"], ["x", "y"], ["m", "n"]]);
+        csv![["a", "b"], ["x", "y"], ["m", "n"]]
+    );
     parses_to!(empty_lines_cr, "\r\r\r\r", csv![]);
     parses_to!(
-        empty_lines_interspersed_cr, "\r\ra,b\r\r\rx,y\r\r\rm,n\r",
-        csv![["a", "b"], ["x", "y"], ["m", "n"]]);
+        empty_lines_interspersed_cr,
+        "\r\ra,b\r\r\rx,y\r\r\rm,n\r",
+        csv![["a", "b"], ["x", "y"], ["m", "n"]]
+    );
 
     parses_to!(
-        term_weird, "zza,bzc,dzz",
+        term_weird,
+        "zza,bzc,dzz",
         csv![["a", "b"], ["c", "d"]],
-        |b: &mut ReaderBuilder| { b.terminator(Terminator::Any(b'z')); });
+        |b: &mut ReaderBuilder| {
+            b.terminator(Terminator::Any(b'z'));
+        }
+    );
 
     parses_to!(
-        ascii_delimited, "a\x1fb\x1ec\x1fd",
+        ascii_delimited,
+        "a\x1fb\x1ec\x1fd",
         csv![["a", "b"], ["c", "d"]],
-        |b: &mut ReaderBuilder| { b.ascii(); });
+        |b: &mut ReaderBuilder| {
+            b.ascii();
+        }
+    );
 
     parses_to!(bom_at_start, "\u{feff}a", csv![["a"]]);
     parses_to!(bom_in_field, "a\u{feff}", csv![["a\u{feff}"]]);
-    parses_to!(bom_at_field_start, "a,\u{feff}b", csv![["a","\u{feff}b"]]);
+    parses_to!(bom_at_field_start, "a,\u{feff}b", csv![["a", "\u{feff}b"]]);
 
     parses_to!(quote_empty, "\"\"", csv![[""]]);
     parses_to!(quote_lf, "\"\"\n", csv![[""]]);
@@ -1575,21 +1606,46 @@ mod tests {
     parses_to!(quote_inner_space, "\" a \"", csv![[" a "]]);
     parses_to!(quote_outer_space, "  \"a\"  ", csv![["  \"a\"  "]]);
 
-    parses_to!(quote_change, "zaz", csv![["a"]],
-               |b: &mut ReaderBuilder| { b.quote(b'z'); });
+    parses_to!(quote_change, "zaz", csv![["a"]], |b: &mut ReaderBuilder| {
+        b.quote(b'z');
+    });
 
     // This one is pretty hokey.
     // I don't really know what the "right" behavior is.
-    parses_to!(quote_delimiter, ",a,,b", csv![["a,b"]],
-               |b: &mut ReaderBuilder| { b.quote(b','); });
+    parses_to!(
+        quote_delimiter,
+        ",a,,b",
+        csv![["a,b"]],
+        |b: &mut ReaderBuilder| {
+            b.quote(b',');
+        }
+    );
 
     parses_to!(quote_no_escapes, r#""a\"b""#, csv![[r#"a\b""#]]);
-    parses_to!(quote_escapes_no_double, r#""a""b""#, csv![[r#"a"b""#]],
-               |b: &mut ReaderBuilder| { b.double_quote(false); });
-    parses_to!(quote_escapes, r#""a\"b""#, csv![[r#"a"b"#]],
-               |b: &mut ReaderBuilder| { b.escape(Some(b'\\')); });
-    parses_to!(quote_escapes_change, r#""az"b""#, csv![[r#"a"b"#]],
-               |b: &mut ReaderBuilder| { b.escape(Some(b'z')); });
+    parses_to!(
+        quote_escapes_no_double,
+        r#""a""b""#,
+        csv![[r#"a"b""#]],
+        |b: &mut ReaderBuilder| {
+            b.double_quote(false);
+        }
+    );
+    parses_to!(
+        quote_escapes,
+        r#""a\"b""#,
+        csv![[r#"a"b"#]],
+        |b: &mut ReaderBuilder| {
+            b.escape(Some(b'\\'));
+        }
+    );
+    parses_to!(
+        quote_escapes_change,
+        r#""az"b""#,
+        csv![[r#"a"b"#]],
+        |b: &mut ReaderBuilder| {
+            b.escape(Some(b'z'));
+        }
+    );
 
     parses_to!(
         quote_escapes_with_comma,
@@ -1597,36 +1653,78 @@ mod tests {
         csv![[r#""A,B""#]],
         |b: &mut ReaderBuilder| {
             b.escape(Some(b'\\')).double_quote(false);
-        });
-
+        }
+    );
 
-    parses_to!(quoting_disabled, r#""abc,foo""#, csv![[r#""abc"#, r#"foo""#]],
-               |b: &mut ReaderBuilder| { b.quoting(false); });
+    parses_to!(
+        quoting_disabled,
+        r#""abc,foo""#,
+        csv![[r#""abc"#, r#"foo""#]],
+        |b: &mut ReaderBuilder| {
+            b.quoting(false);
+        }
+    );
 
-    parses_to!(delimiter_tabs, "a\tb", csv![["a", "b"]],
-               |b: &mut ReaderBuilder| { b.delimiter(b'\t'); });
-    parses_to!(delimiter_weird, "azb", csv![["a", "b"]],
-               |b: &mut ReaderBuilder| { b.delimiter(b'z'); });
+    parses_to!(
+        delimiter_tabs,
+        "a\tb",
+        csv![["a", "b"]],
+        |b: &mut ReaderBuilder| {
+            b.delimiter(b'\t');
+        }
+    );
+    parses_to!(
+        delimiter_weird,
+        "azb",
+        csv![["a", "b"]],
+        |b: &mut ReaderBuilder| {
+            b.delimiter(b'z');
+        }
+    );
 
     parses_to!(extra_record_crlf_1, "foo\n1\n", csv![["foo"], ["1"]]);
     parses_to!(extra_record_crlf_2, "foo\r\n1\r\n", csv![["foo"], ["1"]]);
 
-    parses_to!(comment_1, "foo\n# hi\nbar\n", csv![["foo"], ["bar"]],
-               |b: &mut ReaderBuilder| { b.comment(Some(b'#')); });
+    parses_to!(
+        comment_1,
+        "foo\n# hi\nbar\n",
+        csv![["foo"], ["bar"]],
+        |b: &mut ReaderBuilder| {
+            b.comment(Some(b'#'));
+        }
+    );
     parses_to!(
         comment_2,
         "foo\n # hi\nbar\n",
         csv![["foo"], [" # hi"], ["bar"]],
-        |b: &mut ReaderBuilder| { b.comment(Some(b'#')); });
+        |b: &mut ReaderBuilder| {
+            b.comment(Some(b'#'));
+        }
+    );
     parses_to!(
         comment_3,
         "foo\n# hi\nbar\n",
         csv![["foo"], ["# hi"], ["bar"]],
-        |b: &mut ReaderBuilder| { b.comment(Some(b'\n')); });
-    parses_to!(comment_4, "foo,b#ar,baz", csv![["foo", "b#ar", "baz"]],
-               |b: &mut ReaderBuilder| { b.comment(Some(b'#')); });
-    parses_to!(comment_5, "foo,#bar,baz", csv![["foo", "#bar", "baz"]],
-               |b: &mut ReaderBuilder| { b.comment(Some(b'#')); });
+        |b: &mut ReaderBuilder| {
+            b.comment(Some(b'\n'));
+        }
+    );
+    parses_to!(
+        comment_4,
+        "foo,b#ar,baz",
+        csv![["foo", "b#ar", "baz"]],
+        |b: &mut ReaderBuilder| {
+            b.comment(Some(b'#'));
+        }
+    );
+    parses_to!(
+        comment_5,
+        "foo,#bar,baz",
+        csv![["foo", "#bar", "baz"]],
+        |b: &mut ReaderBuilder| {
+            b.comment(Some(b'#'));
+        }
+    );
 
     macro_rules! assert_read {
         (
@@ -1644,7 +1742,7 @@ mod tests {
     // straight to End.
     #[test]
     fn stream_empty() {
-        use ReadFieldResult::*;
+        use crate::ReadFieldResult::*;
 
         let mut rdr = Reader::new();
         assert_read!(rdr, &[], &mut [], 0, 0, End);
@@ -1653,7 +1751,7 @@ mod tests {
     // Test that a single space is treated as a single field.
     #[test]
     fn stream_space() {
-        use ReadFieldResult::*;
+        use crate::ReadFieldResult::*;
 
         let mut rdr = Reader::new();
         assert_read!(rdr, b(" "), &mut [0], 1, 1, InputEmpty);
@@ -1664,7 +1762,7 @@ mod tests {
     // Test that a single comma ...
     #[test]
     fn stream_comma() {
-        use ReadFieldResult::*;
+        use crate::ReadFieldResult::*;
 
         let mut rdr = Reader::new();
         assert_read!(rdr, b(","), &mut [0], 1, 0, Field { record_end: false });
@@ -1676,7 +1774,7 @@ mod tests {
     // buffers.
     #[test]
     fn stream_output_chunks() {
-        use ReadFieldResult::*;
+        use crate::ReadFieldResult::*;
 
         let mut inp = b("fooquux");
         let out = &mut [0; 2];
@@ -1707,7 +1805,7 @@ mod tests {
     // buffers.
     #[test]
     fn stream_input_chunks() {
-        use ReadFieldResult::*;
+        use crate::ReadFieldResult::*;
 
         let out = &mut [0; 10];
         let mut rdr = Reader::new();
@@ -1731,7 +1829,7 @@ mod tests {
     // Test we can read doubled quotes correctly in a stream.
     #[test]
     fn stream_doubled_quotes() {
-        use ReadFieldResult::*;
+        use crate::ReadFieldResult::*;
 
         let out = &mut [0; 10];
         let mut rdr = Reader::new();
@@ -1749,7 +1847,7 @@ mod tests {
     // Test we can read escaped quotes correctly in a stream.
     #[test]
     fn stream_escaped_quotes() {
-        use ReadFieldResult::*;
+        use crate::ReadFieldResult::*;
 
         let out = &mut [0; 10];
         let mut builder = ReaderBuilder::new();
@@ -1768,13 +1866,19 @@ mod tests {
     // Test that empty output buffers don't wreak havoc.
     #[test]
     fn stream_empty_output() {
-        use ReadFieldResult::*;
+        use crate::ReadFieldResult::*;
 
         let out = &mut [0; 10];
         let mut rdr = Reader::new();
 
         assert_read!(
-            rdr, b("foo,bar"), out, 4, 3, Field { record_end: false });
+            rdr,
+            b("foo,bar"),
+            out,
+            4,
+            3,
+            Field { record_end: false }
+        );
         assert_eq!(&out[..3], b("foo"));
 
         assert_read!(rdr, b("bar"), &mut [], 0, 0, OutputFull);
@@ -1790,7 +1894,7 @@ mod tests {
     // the right thing.
     #[test]
     fn reset_works() {
-        use ReadFieldResult::*;
+        use crate::ReadFieldResult::*;
 
         let out = &mut [0; 10];
         let mut rdr = Reader::new();
@@ -1814,7 +1918,7 @@ mod tests {
     // Test the line number reporting is correct.
     #[test]
     fn line_numbers() {
-        use ReadFieldResult::*;
+        use crate::ReadFieldResult::*;
 
         let out = &mut [0; 10];
         let mut rdr = Reader::new();
@@ -1852,7 +1956,7 @@ mod tests {
     // Test that we can incrementally read a record.
     #[test]
     fn stream_record() {
-        use ReadRecordResult::*;
+        use crate::ReadRecordResult::*;
 
         let mut inp = b("foo,bar\nbaz");
         let out = &mut [0; 1024];
@@ -1877,7 +1981,7 @@ mod tests {
     // we get an appropriate state returned.
     #[test]
     fn stream_record_last_end_output_full() {
-        use ReadRecordResult::*;
+        use crate::ReadRecordResult::*;
 
         let mut inp = b("foo,bar\nbaz");
         let out = &mut [0; 1024];
diff --git a/csv-core/src/writer.rs b/csv-core/src/writer.rs
index 96b92202..d3ce1a19 100644
--- a/csv-core/src/writer.rs
+++ b/csv-core/src/writer.rs
@@ -3,7 +3,7 @@ use core::str;
 
 use memchr::memchr;
 
-use {QuoteStyle, Terminator};
+use crate::{QuoteStyle, Terminator};
 
 /// A builder for configuring a CSV writer.
 ///
@@ -32,7 +32,7 @@ impl WriterBuilder {
 
     /// Builder a CSV writer from this configuration.
     pub fn build(&self) -> Writer {
-        use Terminator::*;
+        use crate::Terminator::*;
 
         let mut wtr = self.wtr.clone();
         wtr.requires_quotes[self.wtr.delimiter as usize] = true;
@@ -296,14 +296,11 @@ impl Writer {
             }
             self.state.in_field = true;
         }
-        let (res, i, o) =
-            if self.state.quoting {
-                quote(
-                    input, output,
-                    self.quote, self.escape, self.double_quote)
-            } else {
-                write_optimistic(input, output)
-            };
+        let (res, i, o) = if self.state.quoting {
+            quote(input, output, self.quote, self.escape, self.double_quote)
+        } else {
+            write_optimistic(input, output)
+        };
         nin += i;
         nout += o;
         self.state.record_bytes += o as u64;
@@ -395,8 +392,7 @@ impl Writer {
     fn needs_quotes(&self, mut input: &[u8]) -> bool {
         let mut needs = false;
         while !needs && input.len() >= 8 {
-            needs =
-                self.requires_quotes[input[0] as usize]
+            needs = self.requires_quotes[input[0] as usize]
                 || self.requires_quotes[input[1] as usize]
                 || self.requires_quotes[input[2] as usize]
                 || self.requires_quotes[input[3] as usize]
@@ -487,11 +483,7 @@ impl Default for Writer {
 
 impl Default for WriterState {
     fn default() -> WriterState {
-        WriterState {
-            in_field: false,
-            quoting: false,
-            record_bytes: 0,
-        }
+        WriterState { in_field: false, quoting: false, record_bytes: 0 }
     }
 }
 
@@ -504,7 +496,7 @@ pub fn is_non_numeric(input: &[u8]) -> bool {
     // I suppose this could be faster if we wrote validators of numbers instead
     // of using the actual parser, but that's probably a lot of work for a bit
     // of a niche feature.
-    !s.parse::<f64>().is_ok() && !s.parse::<i64>().is_ok()
+    !s.parse::<f64>().is_ok() && !s.parse::<i128>().is_ok()
 }
 
 /// Escape quotes `input` and writes the result to `output`.
@@ -548,8 +540,8 @@ pub fn quote(
                 return (res, nin, nout);
             }
             Some(next_quote) => {
-                let (res, i, o) = write_optimistic(
-                    &input[..next_quote], output);
+                let (res, i, o) =
+                    write_optimistic(&input[..next_quote], output);
                 input = &input[i..];
                 output = &mut moving(output)[o..];
                 nin += i;
@@ -609,10 +601,7 @@ fn write_optimistic(
 /// `WriteResult::OutputFull` and copy nothing into `output`. Otherwise,
 /// return `WriteResult::InputEmpty` and the number of bytes copied into
 /// `output`.
-fn write_pessimistic(
-    input: &[u8],
-    output: &mut [u8],
-) -> (WriteResult, usize) {
+fn write_pessimistic(input: &[u8], output: &mut [u8]) -> (WriteResult, usize) {
     if input.len() > output.len() {
         (WriteResult::OutputFull, 0)
     } else {
@@ -623,16 +612,22 @@ fn write_pessimistic(
 
 /// This avoids reborrowing.
 /// See: https://bluss.github.io/rust/fun/2015/10/11/stuff-the-identity-function-does/
-fn moving<T>(x: T) -> T { x }
+fn moving<T>(x: T) -> T {
+    x
+}
 
 #[cfg(test)]
 mod tests {
-    use writer::{Writer, WriterBuilder, QuoteStyle, quote};
-    use writer::WriteResult::*;
+    use crate::writer::WriteResult::*;
+    use crate::writer::{quote, QuoteStyle, Writer, WriterBuilder};
 
     // OMG I HATE BYTE STRING LITERALS SO MUCH.
-    fn b(s: &str) -> &[u8] { s.as_bytes() }
-    fn s(b: &[u8]) -> &str { ::core::str::from_utf8(b).unwrap() }
+    fn b(s: &str) -> &[u8] {
+        s.as_bytes()
+    }
+    fn s(b: &[u8]) -> &str {
+        ::core::str::from_utf8(b).unwrap()
+    }
 
     macro_rules! assert_field {
         (
@@ -645,7 +640,7 @@ mod tests {
             assert_eq!($expect_in, i, "input");
             assert_eq!($expect_out, o, "output");
             assert_eq!($expect_data, s(&$out[..o]), "data");
-        }}
+        }};
     }
 
     macro_rules! assert_write {
@@ -657,7 +652,7 @@ mod tests {
             assert_eq!($expect_res, res, "result");
             assert_eq!($expect_out, o, "output");
             assert_eq!($expect_data, s(&$out[..o]), "data");
-        }}
+        }};
     }
 
     #[test]
@@ -721,7 +716,14 @@ mod tests {
         let mut n = 0;
 
         assert_field!(
-            wtr, b("a\"bc"), &mut out[n..], 4, 6, InputEmpty, "\"a\"\"bc");
+            wtr,
+            b("a\"bc"),
+            &mut out[n..],
+            4,
+            6,
+            InputEmpty,
+            "\"a\"\"bc"
+        );
         n += 6;
 
         assert_write!(wtr, finish, &mut out[n..], 1, InputEmpty, "\"");
@@ -748,7 +750,14 @@ mod tests {
         let mut n = 0;
 
         assert_field!(
-            wtr, b("abc\""), &mut out[n..], 4, 6, InputEmpty, "\"abc\"\"");
+            wtr,
+            b("abc\""),
+            &mut out[n..],
+            4,
+            6,
+            InputEmpty,
+            "\"abc\"\""
+        );
         n += 6;
         assert_field!(wtr, b("x"), &mut out[n..], 1, 1, InputEmpty, "x");
         n += 1;
@@ -787,9 +796,8 @@ mod tests {
 
     #[test]
     fn writer_two_fields_non_numeric() {
-        let mut wtr = WriterBuilder::new()
-            .quote_style(QuoteStyle::NonNumeric)
-            .build();
+        let mut wtr =
+            WriterBuilder::new().quote_style(QuoteStyle::NonNumeric).build();
         let out = &mut [0; 1024];
         let mut n = 0;
 
@@ -816,7 +824,14 @@ mod tests {
         let mut n = 0;
 
         assert_field!(
-            wtr, b("a,bc"), &mut out[n..], 4, 5, InputEmpty, "\"a,bc");
+            wtr,
+            b("a,bc"),
+            &mut out[n..],
+            4,
+            5,
+            InputEmpty,
+            "\"a,bc"
+        );
         n += 5;
         assert_write!(wtr, delimiter, &mut out[n..], 2, InputEmpty, "\",");
         n += 2;
@@ -862,7 +877,14 @@ mod tests {
         let mut n = 0;
 
         assert_field!(
-            wtr, b("a,bc"), &mut out[n..], 4, 5, InputEmpty, "\"a,bc");
+            wtr,
+            b("a,bc"),
+            &mut out[n..],
+            4,
+            5,
+            InputEmpty,
+            "\"a,bc"
+        );
         n += 5;
         assert_write!(wtr, delimiter, &mut out[n..], 2, InputEmpty, "\",");
         n += 2;
@@ -871,12 +893,26 @@ mod tests {
         assert_write!(wtr, terminator, &mut out[n..], 2, InputEmpty, "\"\n");
         n += 2;
         assert_field!(
-            wtr, b("f\"oo"), &mut out[n..], 4, 6, InputEmpty, "\"f\"\"oo");
+            wtr,
+            b("f\"oo"),
+            &mut out[n..],
+            4,
+            6,
+            InputEmpty,
+            "\"f\"\"oo"
+        );
         n += 6;
         assert_write!(wtr, delimiter, &mut out[n..], 2, InputEmpty, "\",");
         n += 2;
         assert_field!(
-            wtr, b("quux,"), &mut out[n..], 5, 6, InputEmpty, "\"quux,");
+            wtr,
+            b("quux,"),
+            &mut out[n..],
+            5,
+            6,
+            InputEmpty,
+            "\"quux,"
+        );
         n += 6;
 
         assert_write!(wtr, finish, &mut out[n..], 1, InputEmpty, "\"");
@@ -892,9 +928,14 @@ mod tests {
             $expect_res:expr, $expect_data:expr
         ) => {
             assert_quote!(
-                $inp, $out,
-                $expect_in, $expect_out, $expect_res, $expect_data,
-                true);
+                $inp,
+                $out,
+                $expect_in,
+                $expect_out,
+                $expect_res,
+                $expect_data,
+                true
+            );
         };
         (
             $inp:expr, $out:expr,
@@ -907,7 +948,7 @@ mod tests {
             assert_eq!($expect_in, i, "input");
             assert_eq!($expect_out, o, "output");
             assert_eq!(b($expect_data), &$out[..o], "data");
-        }}
+        }};
     }
 
     #[test]
@@ -964,8 +1005,13 @@ mod tests {
         let out = &mut [0; 1024];
 
         assert_quote!(
-            inp, out, 21, 25, InputEmpty,
-            r#"foo ""bar"" baz ""quux""?"#);
+            inp,
+            out,
+            21,
+            25,
+            InputEmpty,
+            r#"foo ""bar"" baz ""quux""?"#
+        );
     }
 
     #[test]
diff --git a/csv-index/Cargo.toml b/csv-index/Cargo.toml
index 18303fa4..ee34bc13 100644
--- a/csv-index/Cargo.toml
+++ b/csv-index/Cargo.toml
@@ -11,6 +11,7 @@ keywords = ["csv", "comma", "parser", "delimited", "index"]
 license = "Unlicense/MIT"
 categories = ["encoding", "parser-implementations"]
 workspace = ".."
+edition = "2018"
 
 [badges]
 travis-ci = { repository = "BurntSushi/rust-csv" }
diff --git a/csv-index/README.md b/csv-index/README.md
index 54328783..6c375185 100644
--- a/csv-index/README.md
+++ b/csv-index/README.md
@@ -19,13 +19,7 @@ Add this to your `Cargo.toml`:
 
 ```toml
 [dependencies]
-csv-index = "0.1"
-```
-
-and this to your crate root:
-
-```rust
-extern crate csv_index;
+csv-index = "0.2"
 ```
 
 ### Example: build a simple random access index
@@ -36,19 +30,17 @@ data. This example shows how to save this index to disk for a particular CSV
 file.
 
 ```rust
-extern crate csv;
-extern crate csv_index;
-
 use std::error::Error;
 use std::fs::File;
 use std::io::{self, Write};
+
 use csv_index::RandomAccessSimple;
 
 fn main() {
   example().unwrap();
 }
 
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     // Open a normal CSV reader.
     let mut rdr = csv::Reader::from_path("data.csv")?;
 
diff --git a/csv-index/src/lib.rs b/csv-index/src/lib.rs
index 5c7140d3..0840c8ea 100644
--- a/csv-index/src/lib.rs
+++ b/csv-index/src/lib.rs
@@ -10,13 +10,7 @@ and can be used by adding `csv-index` to your dependencies in your project's
 
 ```toml
 [dependencies]
-csv-index = "0.1"
-```
-
-and this to your crate root:
-
-```ignore
-extern crate csv_index;
+csv-index = "0.2"
 ```
 
 # Example: build a simple random access index
@@ -31,16 +25,13 @@ your CSV data has changed since the index was created, then the index will need
 to be regenerated.
 
 ```no_run
-extern crate csv;
-extern crate csv_index;
-
 use std::error::Error;
 use std::fs::File;
 use std::io::{self, Write};
 use csv_index::RandomAccessSimple;
 
 # fn main() { example().unwrap(); }
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     // Open a normal CSV reader.
     let mut rdr = csv::Reader::from_path("data.csv")?;
 
@@ -81,9 +72,6 @@ amenable to serializing to disk.)
 
 #![deny(missing_docs)]
 
-extern crate byteorder;
-extern crate csv;
-
-pub use simple::RandomAccessSimple;
+pub use crate::simple::RandomAccessSimple;
 
 mod simple;
diff --git a/csv-index/src/simple.rs b/csv-index/src/simple.rs
index 255d2458..c99a9c74 100644
--- a/csv-index/src/simple.rs
+++ b/csv-index/src/simple.rs
@@ -1,6 +1,6 @@
 use std::io;
 
-use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
+use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
 use csv;
 
 /// A simple index for random access to CSV records.
@@ -45,9 +45,6 @@ impl<W: io::Write> RandomAccessSimple<W> {
     /// and query the number of records in the index.
     ///
     /// ```
-    /// extern crate csv;
-    /// extern crate csv_index;
-    ///
     /// use std::io;
     /// use csv_index::RandomAccessSimple;
     ///
@@ -74,9 +71,6 @@ impl<W: io::Write> RandomAccessSimple<W> {
     /// in memory with `std::io::Cursor`, we write the index to a file.
     ///
     /// ```no_run
-    /// extern crate csv;
-    /// extern crate csv_index;
-    ///
     /// use std::fs::File;
     /// use std::io;
     /// use csv_index::RandomAccessSimple;
@@ -101,8 +95,7 @@ impl<W: io::Write> RandomAccessSimple<W> {
     pub fn create<R: io::Read>(
         rdr: &mut csv::Reader<R>,
         mut wtr: W,
-    ) -> csv::Result<()>
-    {
+    ) -> csv::Result<()> {
         // If the reader is configured to read a header, then read that
         // first. (The CSV reader otherwise won't yield the header record
         // when calling `read_byte_record`.)
@@ -138,9 +131,6 @@ impl<R: io::Read + io::Seek> RandomAccessSimple<R> {
     /// and query the number of records in the index.
     ///
     /// ```
-    /// extern crate csv;
-    /// extern crate csv_index;
-    ///
     /// use std::io;
     /// use csv_index::RandomAccessSimple;
     ///
@@ -163,10 +153,7 @@ impl<R: io::Read + io::Seek> RandomAccessSimple<R> {
     pub fn open(mut rdr: R) -> csv::Result<RandomAccessSimple<R>> {
         rdr.seek(io::SeekFrom::End(-8))?;
         let len = rdr.read_u64::<BigEndian>()?;
-        Ok(RandomAccessSimple {
-            rdr: rdr,
-            len: len,
-        })
+        Ok(RandomAccessSimple { rdr: rdr, len: len })
     }
 
     /// Get the position of the record at index `i`.
@@ -188,15 +175,12 @@ impl<R: io::Read + io::Seek> RandomAccessSimple<R> {
     /// and use it to seek a CSV reader to read an arbitrary record.
     ///
     /// ```
-    /// extern crate csv;
-    /// extern crate csv_index;
-    ///
     /// use std::error::Error;
     /// use std::io;
     /// use csv_index::RandomAccessSimple;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -228,7 +212,9 @@ impl<R: io::Read + io::Seek> RandomAccessSimple<R> {
     pub fn get(&mut self, i: u64) -> csv::Result<csv::Position> {
         if i >= self.len {
             let msg = format!(
-                "invalid record index {} (there are {} records)", i, self.len);
+                "invalid record index {} (there are {} records)",
+                i, self.len
+            );
             let err = io::Error::new(io::ErrorKind::Other, msg);
             return Err(csv::Error::from(err));
         }
@@ -302,12 +288,15 @@ mod tests {
 
     #[test]
     fn headers_many_fields() {
-        let mut idx = Indexed::new(true, "\
+        let mut idx = Indexed::new(
+            true,
+            "\
 h1,h2,h3
 a,b,c
 d,e,f
 g,h,i
-");
+",
+        );
         assert_eq!(idx.idx.len(), 4);
         assert_eq!(idx.read_at(0), vec!["h1", "h2", "h3"]);
         assert_eq!(idx.read_at(1), vec!["a", "b", "c"]);
@@ -327,12 +316,15 @@ g,h,i
 
     #[test]
     fn no_headers_many_fields() {
-        let mut idx = Indexed::new(false, "\
+        let mut idx = Indexed::new(
+            false,
+            "\
 h1,h2,h3
 a,b,c
 d,e,f
 g,h,i
-");
+",
+        );
         assert_eq!(idx.idx.len(), 4);
         assert_eq!(idx.read_at(0), vec!["h1", "h2", "h3"]);
         assert_eq!(idx.read_at(1), vec!["a", "b", "c"]);
@@ -342,7 +334,9 @@ g,h,i
 
     #[test]
     fn headers_one_field_newlines() {
-        let mut idx = Indexed::new(true, "
+        let mut idx = Indexed::new(
+            true,
+            "
 
 
 
@@ -366,7 +360,8 @@ c
 
 
 
-");
+",
+        );
         assert_eq!(idx.idx.len(), 4);
         assert_eq!(idx.read_at(0), vec!["h1"]);
         assert_eq!(idx.read_at(1), vec!["a"]);
diff --git a/examples/cookbook-read-basic.rs b/examples/cookbook-read-basic.rs
index 8ed6264f..a69b0e2d 100644
--- a/examples/cookbook-read-basic.rs
+++ b/examples/cookbook-read-basic.rs
@@ -1,10 +1,8 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     // Build the CSV reader and iterate over each record.
     let mut rdr = csv::Reader::from_reader(io::stdin());
     for result in rdr.records() {
diff --git a/examples/cookbook-read-colon.rs b/examples/cookbook-read-colon.rs
index 29f51b59..457cff3b 100644
--- a/examples/cookbook-read-colon.rs
+++ b/examples/cookbook-read-colon.rs
@@ -1,13 +1,10 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn example() -> Result<(), Box<Error>> {
-    let mut rdr = csv::ReaderBuilder::new()
-        .delimiter(b':')
-        .from_reader(io::stdin());
+fn example() -> Result<(), Box<dyn Error>> {
+    let mut rdr =
+        csv::ReaderBuilder::new().delimiter(b':').from_reader(io::stdin());
     for result in rdr.records() {
         let record = result?;
         println!("{:?}", record);
diff --git a/examples/cookbook-read-no-headers.rs b/examples/cookbook-read-no-headers.rs
index 8a289bfd..29812cb2 100644
--- a/examples/cookbook-read-no-headers.rs
+++ b/examples/cookbook-read-no-headers.rs
@@ -1,13 +1,10 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn example() -> Result<(), Box<Error>> {
-    let mut rdr = csv::ReaderBuilder::new()
-        .has_headers(false)
-        .from_reader(io::stdin());
+fn example() -> Result<(), Box<dyn Error>> {
+    let mut rdr =
+        csv::ReaderBuilder::new().has_headers(false).from_reader(io::stdin());
     for result in rdr.records() {
         let record = result?;
         println!("{:?}", record);
diff --git a/examples/cookbook-read-serde.rs b/examples/cookbook-read-serde.rs
index b5bc5ec4..420e0f7a 100644
--- a/examples/cookbook-read-serde.rs
+++ b/examples/cookbook-read-serde.rs
@@ -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 @@ struct Record {
     population: Option<u64>,
 }
 
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     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 --git a/examples/cookbook-write-basic.rs b/examples/cookbook-write-basic.rs
index 6f7ddbe0..199d94b1 100644
--- a/examples/cookbook-write-basic.rs
+++ b/examples/cookbook-write-basic.rs
@@ -1,10 +1,8 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     let mut wtr = csv::Writer::from_writer(io::stdout());
 
     // When writing records without Serde, the header record is written just
diff --git a/examples/cookbook-write-serde.rs b/examples/cookbook-write-serde.rs
index 28954463..54e85a5c 100644
--- a/examples/cookbook-write-serde.rs
+++ b/examples/cookbook-write-serde.rs
@@ -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 @@ struct Record {
     population: Option<u64>,
 }
 
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     let mut wtr = csv::Writer::from_writer(io::stdout());
 
     // When writing records with Serde using structs, the header row is written
diff --git a/examples/tutorial-error-01.rs b/examples/tutorial-error-01.rs
index 5e56af5f..ac2a1ce8 100644
--- a/examples/tutorial-error-01.rs
+++ b/examples/tutorial-error-01.rs
@@ -1,5 +1,3 @@
-extern crate csv;
-
 use std::io;
 
 fn main() {
diff --git a/examples/tutorial-error-02.rs b/examples/tutorial-error-02.rs
index b9a22ecf..e2b5dfe5 100644
--- a/examples/tutorial-error-02.rs
+++ b/examples/tutorial-error-02.rs
@@ -1,5 +1,3 @@
-extern crate csv;
-
 use std::io;
 use std::process;
 
diff --git a/examples/tutorial-error-03.rs b/examples/tutorial-error-03.rs
index e810f72e..6bfcc7a5 100644
--- a/examples/tutorial-error-03.rs
+++ b/examples/tutorial-error-03.rs
@@ -1,5 +1,3 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
@@ -11,16 +9,16 @@ fn main() {
     }
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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<Error> and return it.
+        // Otherwise, convert our error to a Box<dyn Error> and return it.
         match result {
             Err(err) => return Err(From::from(err)),
             Ok(record) => {
-              println!("{:?}", record);
+                println!("{:?}", record);
             }
         }
     }
diff --git a/examples/tutorial-error-04.rs b/examples/tutorial-error-04.rs
index ca91cabc..67eb4f26 100644
--- a/examples/tutorial-error-04.rs
+++ b/examples/tutorial-error-04.rs
@@ -1,5 +1,3 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
@@ -11,7 +9,7 @@ fn main() {
     }
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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 --git a/examples/tutorial-perf-alloc-01.rs b/examples/tutorial-perf-alloc-01.rs
index f7ab107e..d3020cc6 100644
--- a/examples/tutorial-perf-alloc-01.rs
+++ b/examples/tutorial-perf-alloc-01.rs
@@ -1,10 +1,8 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<u64, Box<Error>> {
+fn run() -> Result<u64, Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
 
     let mut count = 0;
diff --git a/examples/tutorial-perf-alloc-02.rs b/examples/tutorial-perf-alloc-02.rs
index aca0f5fd..a3099a1d 100644
--- a/examples/tutorial-perf-alloc-02.rs
+++ b/examples/tutorial-perf-alloc-02.rs
@@ -1,10 +1,8 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<u64, Box<Error>> {
+fn run() -> Result<u64, Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
 
     let mut count = 0;
@@ -18,13 +16,13 @@ fn run() -> Result<u64, Box<Error>> {
 }
 
 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 --git a/examples/tutorial-perf-alloc-03.rs b/examples/tutorial-perf-alloc-03.rs
index 21c2a478..08edf5a1 100644
--- a/examples/tutorial-perf-alloc-03.rs
+++ b/examples/tutorial-perf-alloc-03.rs
@@ -1,10 +1,8 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<u64, Box<Error>> {
+fn run() -> Result<u64, Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
     let mut record = csv::ByteRecord::new();
 
@@ -18,13 +16,13 @@ fn run() -> Result<u64, Box<Error>> {
 }
 
 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 --git a/examples/tutorial-perf-core-01.rs b/examples/tutorial-perf-core-01.rs
index 5dee7f71..220918c3 100644
--- a/examples/tutorial-perf-core-01.rs
+++ b/examples/tutorial-perf-core-01.rs
@@ -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<u64> {
     let mut rdr = Reader::new();
diff --git a/examples/tutorial-perf-serde-01.rs b/examples/tutorial-perf-serde-01.rs
index d0fed0a4..c64538b4 100644
--- a/examples/tutorial-perf-serde-01.rs
+++ b/examples/tutorial-perf-serde-01.rs
@@ -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 @@ struct Record {
     longitude: f64,
 }
 
-fn run() -> Result<u64, Box<Error>> {
+fn run() -> Result<u64, Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
 
     let mut count = 0;
diff --git a/examples/tutorial-perf-serde-02.rs b/examples/tutorial-perf-serde-02.rs
index ace04f8c..44202f8a 100644
--- a/examples/tutorial-perf-serde-02.rs
+++ b/examples/tutorial-perf-serde-02.rs
@@ -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 @@ struct Record<'a> {
     longitude: f64,
 }
 
-fn run() -> Result<u64, Box<Error>> {
+fn run() -> Result<u64, Box<dyn Error>> {
     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 run() -> Result<u64, Box<Error>> {
 }
 
 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 --git a/examples/tutorial-perf-serde-03.rs b/examples/tutorial-perf-serde-03.rs
index 3af7328d..8c8b5f23 100644
--- a/examples/tutorial-perf-serde-03.rs
+++ b/examples/tutorial-perf-serde-03.rs
@@ -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 @@ struct Record<'a> {
     longitude: f64,
 }
 
-fn run() -> Result<u64, Box<Error>> {
+fn run() -> Result<u64, Box<dyn Error>> {
     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 run() -> Result<u64, Box<Error>> {
 }
 
 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 --git a/examples/tutorial-pipeline-pop-01.rs b/examples/tutorial-pipeline-pop-01.rs
index 7a9e9f87..f10cd43b 100644
--- a/examples/tutorial-pipeline-pop-01.rs
+++ b/examples/tutorial-pipeline-pop-01.rs
@@ -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 @@ struct Record {
     longitude: f64,
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     // 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 --git a/examples/tutorial-pipeline-search-01.rs b/examples/tutorial-pipeline-search-01.rs
index 4004c0fd..3bfb8ea5 100644
--- a/examples/tutorial-pipeline-search-01.rs
+++ b/examples/tutorial-pipeline-search-01.rs
@@ -1,11 +1,9 @@
-extern crate csv;
-
 use std::env;
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     // Get the query from the positional arguments.
     // If one doesn't exist, return an error.
     let query = match env::args().nth(1) {
diff --git a/examples/tutorial-pipeline-search-02.rs b/examples/tutorial-pipeline-search-02.rs
index 9da9c6ae..ab033854 100644
--- a/examples/tutorial-pipeline-search-02.rs
+++ b/examples/tutorial-pipeline-search-02.rs
@@ -1,11 +1,9 @@
-extern crate csv;
-
 use std::env;
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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 run() -> Result<(), Box<Error>> {
 }
 
 fn main() {
-if let Err(err) = run() {
-println!("{}", err);
-process::exit(1);
-}
+    if let Err(err) = run() {
+        println!("{}", err);
+        process::exit(1);
+    }
 }
diff --git a/examples/tutorial-read-01.rs b/examples/tutorial-read-01.rs
index a7549afc..9fc92939 100644
--- a/examples/tutorial-read-01.rs
+++ b/examples/tutorial-read-01.rs
@@ -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<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let file_path = get_first_arg()?;
     let file = File::open(file_path)?;
     let mut rdr = csv::Reader::from_reader(file);
@@ -19,7 +17,7 @@ fn run() -> Result<(), Box<Error>> {
 
 /// 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<OsString, Box<Error>> {
+fn get_first_arg() -> Result<OsString, Box<dyn Error>> {
     match env::args_os().nth(1) {
         None => Err(From::from("expected 1 argument, but got none")),
         Some(file_path) => Ok(file_path),
diff --git a/examples/tutorial-read-delimiter-01.rs b/examples/tutorial-read-delimiter-01.rs
index 38baa55a..10a93e1a 100644
--- a/examples/tutorial-read-delimiter-01.rs
+++ b/examples/tutorial-read-delimiter-01.rs
@@ -1,10 +1,8 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::ReaderBuilder::new()
         .has_headers(false)
         .delimiter(b';')
@@ -21,8 +19,8 @@ fn run() -> Result<(), Box<Error>> {
 }
 
 fn main() {
-if let Err(err) = run() {
-println!("{}", err);
-process::exit(1);
-}
+    if let Err(err) = run() {
+        println!("{}", err);
+        process::exit(1);
+    }
 }
diff --git a/examples/tutorial-read-headers-01.rs b/examples/tutorial-read-headers-01.rs
index b25b5caf..d5b1c7b7 100644
--- a/examples/tutorial-read-headers-01.rs
+++ b/examples/tutorial-read-headers-01.rs
@@ -1,13 +1,10 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<(), Box<Error>> {
-    let mut rdr = csv::ReaderBuilder::new()
-        .has_headers(false)
-        .from_reader(io::stdin());
+fn run() -> Result<(), Box<dyn Error>> {
+    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 run() -> Result<(), Box<Error>> {
 }
 
 fn main() {
-if let Err(err) = run() {
-println!("{}", err);
-process::exit(1);
-}
+    if let Err(err) = run() {
+        println!("{}", err);
+        process::exit(1);
+    }
 }
diff --git a/examples/tutorial-read-headers-02.rs b/examples/tutorial-read-headers-02.rs
index 0c9c9ae5..ddaa7569 100644
--- a/examples/tutorial-read-headers-02.rs
+++ b/examples/tutorial-read-headers-02.rs
@@ -1,10 +1,8 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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 run() -> Result<(), Box<Error>> {
 }
 
 fn main() {
-if let Err(err) = run() {
-println!("{}", err);
-process::exit(1);
-}
+    if let Err(err) = run() {
+        println!("{}", err);
+        process::exit(1);
+    }
 }
diff --git a/examples/tutorial-read-serde-01.rs b/examples/tutorial-read-serde-01.rs
index 6dcd24a3..a073157f 100644
--- a/examples/tutorial-read-serde-01.rs
+++ b/examples/tutorial-read-serde-01.rs
@@ -1,10 +1,8 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
     for result in rdr.records() {
         let record = result?;
@@ -23,14 +21,15 @@ fn run() -> Result<(), Box<Error>> {
         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 --git a/examples/tutorial-read-serde-02.rs b/examples/tutorial-read-serde-02.rs
index fce3131d..d9114fb8 100644
--- a/examples/tutorial-read-serde-02.rs
+++ b/examples/tutorial-read-serde-02.rs
@@ -1,5 +1,3 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
@@ -8,7 +6,7 @@ use std::process;
 // record type.
 type Record = (String, String, Option<u64>, f64, f64);
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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 run() -> Result<(), Box<Error>> {
 }
 
 fn main() {
-if let Err(err) = run() {
-println!("{}", err);
-process::exit(1);
-}
+    if let Err(err) = run() {
+        println!("{}", err);
+        process::exit(1);
+    }
 }
diff --git a/examples/tutorial-read-serde-03.rs b/examples/tutorial-read-serde-03.rs
index 752f42e7..a4c31f07 100644
--- a/examples/tutorial-read-serde-03.rs
+++ b/examples/tutorial-read-serde-03.rs
@@ -1,5 +1,3 @@
-extern crate csv;
-
 use std::collections::HashMap;
 use std::error::Error;
 use std::io;
@@ -9,7 +7,7 @@ use std::process;
 // record type.
 type Record = HashMap<String, String>;
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
     for result in rdr.deserialize() {
         let record: Record = result?;
@@ -19,8 +17,8 @@ fn run() -> Result<(), Box<Error>> {
 }
 
 fn main() {
-if let Err(err) = run() {
-println!("{}", err);
-process::exit(1);
-}
+    if let Err(err) = run() {
+        println!("{}", err);
+        process::exit(1);
+    }
 }
diff --git a/examples/tutorial-read-serde-04.rs b/examples/tutorial-read-serde-04.rs
index e4e5a6ca..e01d355f 100644
--- a/examples/tutorial-read-serde-04.rs
+++ b/examples/tutorial-read-serde-04.rs
@@ -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 @@ struct Record {
     state: String,
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
     for result in rdr.deserialize() {
         let record: Record = result?;
diff --git a/examples/tutorial-read-serde-invalid-01.rs b/examples/tutorial-read-serde-invalid-01.rs
index 9e79a4e3..604b3840 100644
--- a/examples/tutorial-read-serde-invalid-01.rs
+++ b/examples/tutorial-read-serde-invalid-01.rs
@@ -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 @@ struct Record {
     state: String,
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
     for result in rdr.deserialize() {
         let record: Record = result?;
@@ -26,8 +24,8 @@ fn run() -> Result<(), Box<Error>> {
 }
 
 fn main() {
-if let Err(err) = run() {
-println!("{}", err);
-process::exit(1);
-}
+    if let Err(err) = run() {
+        println!("{}", err);
+        process::exit(1);
+    }
 }
diff --git a/examples/tutorial-read-serde-invalid-02.rs b/examples/tutorial-read-serde-invalid-02.rs
index cff5e4c1..3723496e 100644
--- a/examples/tutorial-read-serde-invalid-02.rs
+++ b/examples/tutorial-read-serde-invalid-02.rs
@@ -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 @@ struct Record {
     state: String,
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
     for result in rdr.deserialize() {
         let record: Record = result?;
@@ -27,8 +24,8 @@ fn run() -> Result<(), Box<Error>> {
 }
 
 fn main() {
-if let Err(err) = run() {
-println!("{}", err);
-process::exit(1);
-}
+    if let Err(err) = run() {
+        println!("{}", err);
+        process::exit(1);
+    }
 }
diff --git a/examples/tutorial-setup-01.rs b/examples/tutorial-setup-01.rs
index e882c152..536dab3e 100644
--- a/examples/tutorial-setup-01.rs
+++ b/examples/tutorial-setup-01.rs
@@ -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 --git a/examples/tutorial-write-01.rs b/examples/tutorial-write-01.rs
index 66a01523..229470d4 100644
--- a/examples/tutorial-write-01.rs
+++ b/examples/tutorial-write-01.rs
@@ -1,16 +1,26 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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 --git a/examples/tutorial-write-02.rs b/examples/tutorial-write-02.rs
index 1fef5287..76b5755f 100644
--- a/examples/tutorial-write-02.rs
+++ b/examples/tutorial-write-02.rs
@@ -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<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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 @@ fn run() -> Result<(), Box<Error>> {
 
 /// 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<OsString, Box<Error>> {
+fn get_first_arg() -> Result<OsString, Box<dyn Error>> {
     match env::args_os().nth(1) {
         None => Err(From::from("expected 1 argument, but got none")),
         Some(file_path) => Ok(file_path),
diff --git a/examples/tutorial-write-delimiter-01.rs b/examples/tutorial-write-delimiter-01.rs
index 50c52520..795fd0a0 100644
--- a/examples/tutorial-write-delimiter-01.rs
+++ b/examples/tutorial-write-delimiter-01.rs
@@ -1,17 +1,27 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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 run() -> Result<(), Box<Error>> {
 }
 
 fn main() {
-if let Err(err) = run() {
-println!("{}", err);
-process::exit(1);
-}
+    if let Err(err) = run() {
+        println!("{}", err);
+        process::exit(1);
+    }
 }
diff --git a/examples/tutorial-write-serde-01.rs b/examples/tutorial-write-serde-01.rs
index 0fdd7e79..595b31fc 100644
--- a/examples/tutorial-write-serde-01.rs
+++ b/examples/tutorial-write-serde-01.rs
@@ -1,14 +1,18 @@
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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 @@ fn run() -> Result<(), Box<Error>> {
     // 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<T>` but
     // `None::<u64>` has type `Option<u64>`.
-    wtr.serialize(("Davidsons Landing", "AK", None::<u64>, 65.2419444, -165.2716667))?;
+    wtr.serialize((
+        "Davidsons Landing",
+        "AK",
+        None::<u64>,
+        65.2419444,
+        -165.2716667,
+    ))?;
     wtr.serialize(("Kenai", "AK", Some(7610), 60.5544444, -151.2583333))?;
     wtr.serialize(("Oakman", "AL", None::<u64>, 33.7133333, -87.3886111))?;
 
@@ -25,8 +35,8 @@ fn run() -> Result<(), Box<Error>> {
 }
 
 fn main() {
-if let Err(err) = run() {
-println!("{}", err);
-process::exit(1);
-}
+    if let Err(err) = run() {
+        println!("{}", err);
+        process::exit(1);
+    }
 }
diff --git a/examples/tutorial-write-serde-02.rs b/examples/tutorial-write-serde-02.rs
index 6b101fe7..455de3a1 100644
--- a/examples/tutorial-write-serde-02.rs
+++ b/examples/tutorial-write-serde-02.rs
@@ -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 @@ struct Record<'a> {
     longitude: f64,
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut wtr = csv::Writer::from_writer(io::stdout());
 
     wtr.serialize(Record {
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 00000000..aa37a218
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1,2 @@
+max_width = 79
+use_small_heuristics = "max"
diff --git a/scripts/copy-examples b/scripts/copy-examples
index 100b080d..6fb91ff3 100755
--- a/scripts/copy-examples
+++ b/scripts/copy-examples
@@ -5,6 +5,7 @@ import argparse
 import codecs
 import os.path
 import re
+import subprocess
 
 RE_EACH_CODE_BLOCK = re.compile(r'(?s)```[^\n]*\n(.*?)```')
 RE_MARKER = re.compile(r'^(?:# )?//(.+)$')
@@ -29,3 +30,4 @@ if __name__ == '__main__':
         fpath = os.path.join(args.example_dir, m.group(1))
         with codecs.open(fpath, mode='w+', encoding='utf-8') as f:
             print(code, file=f)
+        subprocess.check_output(['rustfmt', fpath])
diff --git a/src/byte_record.rs b/src/byte_record.rs
index f0ae296e..42edb0d9 100644
--- a/src/byte_record.rs
+++ b/src/byte_record.rs
@@ -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<u8>, &mut Vec<usize>) {
-    // 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<I, T>(record: &ByteRecord, other: I) -> bool
-    where I: IntoIterator<Item=T>, 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 {
 
 impl<T: AsRef<[u8]>> PartialEq<Vec<T>> for ByteRecord {
     fn eq(&self, other: &Vec<T>) -> bool {
-        eq(self, other)
+        self.iter_eq(other)
     }
 }
 
 impl<'a, T: AsRef<[u8]>> PartialEq<Vec<T>> for &'a ByteRecord {
     fn eq(&self, other: &Vec<T>) -> bool {
-        eq(self, other)
+        self.iter_eq(other)
     }
 }
 
 impl<T: AsRef<[u8]>> 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 @@ impl fmt::Debug for ByteRecord {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let mut fields = vec![];
         for field in self {
-            let escaped: Vec<u8> = 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 @@ impl ByteRecord {
     /// 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 @@ impl ByteRecord {
     /// }
     ///
     /// # fn main() { example().unwrap() }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let record = ByteRecord::from(vec![
     ///         "Boston", "United States", "4628910",
     ///     ]);
@@ -276,12 +196,10 @@ impl ByteRecord {
     /// 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 @@ impl ByteRecord {
     /// }
     ///
     /// # fn main() { example().unwrap() }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     // 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 @@ impl ByteRecord {
     /// 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<R>(&self, range: R) -> usize
-    where R: Iterator<Item=usize>
-    {
-        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 @@ impl ByteRecord {
     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 @@ impl ByteRecord {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
+    ///
     /// use csv::{ByteRecord, ReaderBuilder};
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut record = ByteRecord::new();
     ///     let mut rdr = ReaderBuilder::new()
     ///         .has_headers(false)
@@ -600,6 +496,72 @@ impl ByteRecord {
     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<u8>, &mut Vec<usize>) {
+        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<I, T>(&self, other: I) -> bool
+    where
+        I: IntoIterator<Item = T>,
+        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 @@ impl Position {
     }
 
     /// 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 Bounds {
 impl ops::Index<usize> 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<StringRecord> for ByteRecord {
     #[inline]
-    fn from(record: StringRecord) -> ByteRecord { record.into_byte_record() }
+    fn from(record: StringRecord) -> ByteRecord {
+        record.into_byte_record()
+    }
 }
 
 impl<T: AsRef<[u8]>> From<Vec<T>> for ByteRecord {
@@ -766,7 +741,7 @@ impl<'a, T: AsRef<[u8]>> From<&'a [T]> for ByteRecord {
 
 impl<T: AsRef<[u8]>> FromIterator<T> for ByteRecord {
     #[inline]
-    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> ByteRecord {
+    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> ByteRecord {
         let mut record = ByteRecord::new();
         record.extend(iter);
         record
@@ -775,7 +750,7 @@ impl<T: AsRef<[u8]>> FromIterator<T> for ByteRecord {
 
 impl<T: AsRef<[u8]>> Extend<T> for ByteRecord {
     #[inline]
-    fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
+    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
         for x in iter {
             self.push_field(x.as_ref());
         }
@@ -852,7 +827,8 @@ impl<'r> DoubleEndedIterator for ByteRecordIter<'r> {
             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 @@ impl<'r> DoubleEndedIterator for ByteRecordIter<'r> {
 
 #[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 @@ mod tests {
     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 @@ mod tests {
     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 @@ mod tests {
     // 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 @@ mod tests {
     // 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 --git a/src/cookbook.rs b/src/cookbook.rs
index 904a1990..a28dc723 100644
--- a/src/cookbook.rs
+++ b/src/cookbook.rs
@@ -31,13 +31,11 @@ stdout.
 
 ```no_run
 # //cookbook-read-basic.rs
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     // 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 @@ method.
 
 ```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 @@ struct Record {
     population: Option<u64>,
 }
 
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     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 @@ by `:` instead of `,`.
 
 ```no_run
 # //cookbook-read-colon.rs
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::ReaderBuilder::new()
         .delimiter(b':')
         .from_reader(io::stdin());
@@ -170,13 +164,11 @@ first record is not skipped. This example shows how to disable that setting.
 
 ```no_run
 # //cookbook-read-no-headers.rs
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::ReaderBuilder::new()
         .has_headers(false)
         .from_reader(io::stdin());
@@ -209,13 +201,11 @@ This example shows how to write CSV data to stdout.
 
 ```no_run
 # //cookbook-write-basic.rs
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     let mut wtr = csv::Writer::from_writer(io::stdout());
 
     // When writing records without Serde, the header record is written just
@@ -251,14 +241,12 @@ headers are written automatically.
 
 ```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 @@ struct Record {
     population: Option<u64>,
 }
 
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     let mut wtr = csv::Writer::from_writer(io::stdout());
 
     // When writing records with Serde using structs, the header row is written
diff --git a/src/deserializer.rs b/src/deserializer.rs
index 9d1d980f..df4e4b9e 100644
--- a/src/deserializer.rs
+++ b/src/deserializer.rs
@@ -1,19 +1,19 @@
-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 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 +27,7 @@ pub fn deserialize_string_record<'de, D: Deserialize<'de>>(
         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 +44,7 @@ pub fn deserialize_byte_record<'de, D: Deserialize<'de>>(
         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 +181,7 @@ impl<'r> DeRecord<'r> for DeStringRecord<'r> {
             None => Err(DeserializeError {
                 field: None,
                 kind: DEK::UnexpectedEndOfRow,
-            })
+            }),
         }
     }
 
@@ -211,10 +211,14 @@ impl<'r> DeRecord<'r> for DeStringRecord<'r> {
             visitor.visit_bool(true)
         } else if x == "false" {
             visitor.visit_bool(false)
-        } else if let Some(n) = try_positive_integer(x) {
+        } else if let Some(n) = try_positive_integer_64(x) {
             visitor.visit_u64(n)
-        } else if let Some(n) = try_negative_integer(x) {
+        } else if let Some(n) = try_negative_integer_64(x) {
             visitor.visit_i64(n)
+        } else if let Some(n) = try_positive_integer(x) {
+            visitor.visit_u128(n)
+        } else if let Some(n) = try_negative_integer(x) {
+            visitor.visit_i128(n)
         } else if let Some(n) = try_float(x) {
             visitor.visit_f64(n)
         } else {
@@ -238,9 +242,10 @@ impl<'r> DeRecord<'r> for DeByteRecord<'r> {
     #[inline]
     fn next_header(&mut self) -> Result<Option<&'r str>, 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 +261,8 @@ impl<'r> DeRecord<'r> for DeByteRecord<'r> {
     #[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 +276,7 @@ impl<'r> DeRecord<'r> for DeByteRecord<'r> {
             None => Err(DeserializeError {
                 field: None,
                 kind: DEK::UnexpectedEndOfRow,
-            })
+            }),
         }
     }
 
@@ -297,10 +301,14 @@ impl<'r> DeRecord<'r> for DeByteRecord<'r> {
             visitor.visit_bool(true)
         } else if x == b"false" {
             visitor.visit_bool(false)
-        } else if let Some(n) = try_positive_integer_bytes(x) {
+        } else if let Some(n) = try_positive_integer_bytes_64(x) {
             visitor.visit_u64(n)
-        } else if let Some(n) = try_negative_integer_bytes(x) {
+        } else if let Some(n) = try_negative_integer_bytes_64(x) {
             visitor.visit_i64(n)
+        } else if let Some(n) = try_positive_integer_bytes(x) {
+            visitor.visit_u128(n)
+        } else if let Some(n) = try_negative_integer_bytes(x) {
+            visitor.visit_i128(n)
         } else if let Some(n) = try_float_bytes(x) {
             visitor.visit_f64(n)
         } else if let Ok(s) = str::from_utf8(x) {
@@ -317,8 +325,8 @@ macro_rules! deserialize_int {
             self,
             visitor: V,
         ) -> Result<V::Value, Self::Error> {
-            let field = self.next_field()?; 
-            let num = 
+            let field = self.next_field()?;
+            let num =
                 if field.starts_with("0x") {
                     <$inttype>::from_str_radix(&field[2..], 16)
                 } else {
@@ -347,17 +355,21 @@ impl<'a, 'de: 'a, T: DeRecord<'de>> Deserializer<'de>
     ) -> Result<V::Value, Self::Error> {
         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);
+    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);
+    deserialize_int!(deserialize_i128, visit_i128, i128);
 
     fn deserialize_f32<V: Visitor<'de>>(
         self,
@@ -365,7 +377,9 @@ impl<'a, 'de: 'a, T: DeRecord<'de>> Deserializer<'de>
     ) -> Result<V::Value, Self::Error> {
         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<V: Visitor<'de>>(
@@ -374,7 +388,9 @@ impl<'a, 'de: 'a, T: DeRecord<'de>> Deserializer<'de>
     ) -> Result<V::Value, Self::Error> {
         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<V: Visitor<'de>>(
@@ -386,7 +402,8 @@ impl<'a, 'de: 'a, T: DeRecord<'de>> Deserializer<'de>
         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())
     }
@@ -409,9 +426,7 @@ impl<'a, 'de: 'a, T: DeRecord<'de>> Deserializer<'de>
         self,
         visitor: V,
     ) -> Result<V::Value, Self::Error> {
-        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<V: Visitor<'de>>(
@@ -550,8 +565,8 @@ impl<'a, 'de: 'a, T: DeRecord<'de>> EnumAccess<'de>
     }
 }
 
-impl<'a, 'de: 'a, T: DeRecord<'de>>
-    VariantAccess<'de> for &'a mut DeRecordWrap<T>
+impl<'a, 'de: 'a, T: DeRecord<'de>> VariantAccess<'de>
+    for &'a mut DeRecordWrap<T>
 {
     type Error = DeserializeError;
 
@@ -586,8 +601,8 @@ impl<'a, 'de: 'a, T: DeRecord<'de>>
     }
 }
 
-impl<'a, 'de: 'a, T: DeRecord<'de>>
-    SeqAccess<'de> for &'a mut DeRecordWrap<T>
+impl<'a, 'de: 'a, T: DeRecord<'de>> SeqAccess<'de>
+    for &'a mut DeRecordWrap<T>
 {
     type Error = DeserializeError;
 
@@ -603,8 +618,8 @@ impl<'a, 'de: 'a, T: DeRecord<'de>>
     }
 }
 
-impl<'a, 'de: 'a, T: DeRecord<'de>>
-    MapAccess<'de> for &'a mut DeRecordWrap<T>
+impl<'a, 'de: 'a, T: DeRecord<'de>> MapAccess<'de>
+    for &'a mut DeRecordWrap<T>
 {
     type Error = DeserializeError;
 
@@ -659,10 +674,7 @@ pub enum DeserializeErrorKind {
 
 impl SerdeError for DeserializeError {
     fn custom<T: fmt::Display>(msg: T) -> DeserializeError {
-        DeserializeError {
-            field: None,
-            kind: DEK::Message(msg.to_string()),
-        }
+        DeserializeError { field: None, kind: DEK::Message(msg.to_string()) }
     }
 }
 
@@ -728,11 +740,19 @@ impl DeserializeErrorKind {
     }
 }
 
-fn try_positive_integer(s: &str) -> Option<u64> {
+fn try_positive_integer(s: &str) -> Option<u128> {
+    s.parse().ok()
+}
+
+fn try_negative_integer(s: &str) -> Option<i128> {
     s.parse().ok()
 }
 
-fn try_negative_integer(s: &str) -> Option<i64> {
+fn try_positive_integer_64(s: &str) -> Option<u64> {
+    s.parse().ok()
+}
+
+fn try_negative_integer_64(s: &str) -> Option<i64> {
     s.parse().ok()
 }
 
@@ -740,11 +760,19 @@ fn try_float(s: &str) -> Option<f64> {
     s.parse().ok()
 }
 
-fn try_positive_integer_bytes(s: &[u8]) -> Option<u64> {
+fn try_positive_integer_bytes_64(s: &[u8]) -> Option<u64> {
+    str::from_utf8(s).ok().and_then(|s| s.parse().ok())
+}
+
+fn try_negative_integer_bytes_64(s: &[u8]) -> Option<i64> {
+    str::from_utf8(s).ok().and_then(|s| s.parse().ok())
+}
+
+fn try_positive_integer_bytes(s: &[u8]) -> Option<u128> {
     str::from_utf8(s).ok().and_then(|s| s.parse().ok())
 }
 
-fn try_negative_integer_bytes(s: &[u8]) -> Option<i64> {
+fn try_negative_integer_bytes(s: &[u8]) -> Option<i128> {
     str::from_utf8(s).ok().and_then(|s| s.parse().ok())
 }
 
@@ -756,17 +784,15 @@ fn try_float_bytes(s: &[u8]) -> Option<f64> {
 mod tests {
     use std::collections::HashMap;
 
-    use serde::de::DeserializeOwned;
-    use serde_bytes::{self, ByteBuf};
+    use bstr::BString;
+    use serde::{de::DeserializeOwned, 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<D: DeserializeOwned>(
-        fields: &[&str],
-    ) -> Result<D, Error> {
+    fn de<D: DeserializeOwned>(fields: &[&str]) -> Result<D, Error> {
         let record = StringRecord::from(fields);
         deserialize_string_record(&record, None)
     }
@@ -793,10 +819,8 @@ mod tests {
             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 });
     }
 
@@ -812,7 +836,8 @@ mod tests {
         assert!(de_headers::<Foo>(
             &["a", "x", "y", "z"],
             &["foo", "hi", "42", "1.3"],
-        ).is_err());
+        )
+        .is_err());
     }
 
     #[test]
@@ -823,10 +848,7 @@ mod tests {
             y: i32,
             x: String,
         }
-        assert!(de_headers::<Foo>(
-            &["y", "z"],
-            &["42", "1.3"],
-        ).is_err());
+        assert!(de_headers::<Foo>(&["y", "z"], &["42", "1.3"],).is_err());
     }
 
     #[test]
@@ -838,10 +860,7 @@ mod tests {
             x: Option<String>,
         }
 
-        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 });
     }
 
@@ -883,7 +902,7 @@ mod tests {
         assert_eq!(got.unwrap(), Foo);
 
         let got = de_headers::<Bar>(&[], &[]);
-        assert_eq!(got.unwrap(), Bar{});
+        assert_eq!(got.unwrap(), Bar {});
 
         let got = de_headers::<()>(&[], &[]);
         assert_eq!(got.unwrap(), ());
@@ -913,6 +932,12 @@ mod tests {
         assert_eq!(got, 42);
     }
 
+    #[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();
@@ -1014,7 +1039,7 @@ mod tests {
 
     #[test]
     fn bytes() {
-        let got: Vec<u8> = de::<ByteBuf>(&["foobar"]).unwrap().into();
+        let got: Vec<u8> = de::<BString>(&["foobar"]).unwrap().into();
         assert_eq!(got, b"foobar".to_vec());
     }
 
@@ -1062,15 +1087,16 @@ mod tests {
             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]
@@ -1082,10 +1108,8 @@ mod tests {
             c: Option<i32>,
         }
 
-        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) });
     }
 
@@ -1093,18 +1117,16 @@ mod tests {
     fn option_invalid_field() {
         #[derive(Deserialize, Debug, PartialEq)]
         struct Foo {
-            #[serde(deserialize_with = "::invalid_option")]
+            #[serde(deserialize_with = "crate::invalid_option")]
             a: Option<i32>,
-            #[serde(deserialize_with = "::invalid_option")]
+            #[serde(deserialize_with = "crate::invalid_option")]
             b: Option<i32>,
-            #[serde(deserialize_with = "::invalid_option")]
+            #[serde(deserialize_with = "crate::invalid_option")]
             c: Option<i32>,
         }
 
-        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) });
     }
 
@@ -1119,8 +1141,8 @@ mod tests {
 
         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" });
     }
 
@@ -1130,13 +1152,11 @@ mod tests {
 
         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);
     }
 
@@ -1146,13 +1166,11 @@ mod tests {
 
         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);
     }
 
@@ -1181,10 +1199,13 @@ mod tests {
         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]
@@ -1192,22 +1213,22 @@ mod tests {
         #[derive(Debug, Deserialize, PartialEq)]
         struct Row {
             h1: String,
-            #[serde(with = "serde_bytes")]
-            h2: Vec<u8>,
+            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 --git a/src/error.rs b/src/error.rs
index 6a912616..793ad3e9 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -2,16 +2,9 @@ use std::error::Error as StdError;
 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<T, csv::Error>`.
 pub type Result<T> = result::Result<T, Error>;
@@ -28,6 +21,11 @@ pub type Result<T> = result::Result<T, Error>;
 pub struct Error(Box<ErrorKind>);
 
 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 @@ impl Error {
             _ => 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 @@ pub enum ErrorKind {
     __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<io::Error> for Error {
     fn from(err: io::Error) -> Error {
-        new_error(ErrorKind::Io(err))
+        Error::new(ErrorKind::Io(err))
     }
 }
 
@@ -114,25 +135,11 @@ impl From<Error> for io::Error {
 }
 
 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),
@@ -148,47 +155,61 @@ impl fmt::Display for Error {
             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!(),
         }
     }
@@ -204,12 +225,12 @@ pub struct FromUtf8Error {
     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
@@ -228,8 +249,9 @@ impl fmt::Display for FromUtf8Error {
 }
 
 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.
@@ -254,22 +276,24 @@ pub fn new_utf8_error(field: usize, valid_up_to: usize) -> Utf8Error {
 
 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
+        )
     }
 }
 
@@ -285,15 +309,15 @@ pub struct IntoInnerError<W> {
     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<W>(wtr: W, err: io::Error) -> IntoInnerError<W> {
-    IntoInnerError { wtr: wtr, err: err }
-}
-
 impl<W> IntoInnerError<W> {
+    /// 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<W> {
+        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.
@@ -310,14 +334,9 @@ impl<W> IntoInnerError<W> {
     }
 }
 
-impl<W: ::std::any::Any> StdError for IntoInnerError<W> {
-    fn description(&self) -> &str {
-        self.err.description()
-    }
-
-    #[allow(deprecated)]
-    fn cause(&self) -> Option<&StdError> {
-        self.err.cause()
+impl<W: std::any::Any> StdError for IntoInnerError<W> {
+    fn source(&self) -> Option<&(dyn StdError + 'static)> {
+        self.err.source()
     }
 }
 
diff --git a/src/lib.rs b/src/lib.rs
index 1d7b3fc5..3c771c95 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -46,13 +46,7 @@ Add this to your `Cargo.toml`:
 
 ```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 @@ then add this to your `[dependencies]` section of `Cargo.toml`:
 
 ```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 @@ stdout.
 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<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     // 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 @@ By default, the member names of the struct are matched with the values in the
 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 @@ struct Record {
     population: Option<u64>,
 }
 
-fn example() -> Result<(), Box<Error>> {
+fn example() -> Result<(), Box<dyn Error>> {
     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,38 +149,27 @@ $ cargo run --example cookbook-read-serde < examples/data/smallpop.csv
 
 #![deny(missing_docs)]
 
-extern crate csv_core;
-extern crate itoa;
-extern crate ryu;
-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;
@@ -349,12 +319,10 @@ impl Default for Trim {
 /// 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 {
@@ -367,7 +335,7 @@ impl Default for Trim {
 /// }
 ///
 /// # fn main() { example().unwrap(); }
-/// fn example() -> Result<(), Box<Error>> {
+/// fn example() -> Result<(), Box<dyn Error>> {
 ///     let data = "\
 /// a,b,c
 /// 5,\"\",xyz
@@ -383,7 +351,9 @@ impl Default for Trim {
 /// }
 /// ```
 pub fn invalid_option<'de, D, T>(de: D) -> result::Result<Option<T>, D::Error>
-    where D: Deserializer<'de>, Option<T>: Deserialize<'de>
+where
+    D: Deserializer<'de>,
+    Option<T>: Deserialize<'de>,
 {
     Option::<T>::deserialize(de).or_else(|_| Ok(None))
 }
diff --git a/src/reader.rs b/src/reader.rs
index 55cb1db6..dce47b43 100644
--- a/src/reader.rs
+++ b/src/reader.rs
@@ -4,15 +4,13 @@ use std::marker::PhantomData;
 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 @@ pub struct ReaderBuilder {
 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 @@ impl ReaderBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::{ReaderBuilder, StringRecord};
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -91,13 +87,11 @@ impl ReaderBuilder {
     /// # Example
     ///
     /// ```no_run
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::ReaderBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut rdr = ReaderBuilder::new().from_path("foo.csv")?;
     ///     for result in rdr.records() {
     ///         let record = result?;
@@ -118,13 +112,11 @@ impl ReaderBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::ReaderBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -149,13 +141,11 @@ impl ReaderBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::ReaderBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city;country;pop
     /// Boston;United States;4628910
@@ -194,13 +184,11 @@ impl ReaderBuilder {
     /// 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<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -246,13 +234,11 @@ impl ReaderBuilder {
     /// # Example: flexible records enabled
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::ReaderBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     // Notice that the first row is missing the population count.
     ///     let data = "\
     /// city,country,pop
@@ -279,13 +265,11 @@ impl ReaderBuilder {
     /// default).
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::{ErrorKind, ReaderBuilder};
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     // Notice that the first row is missing the population count.
     ///     let data = "\
     /// city,country,pop
@@ -343,13 +327,11 @@ impl ReaderBuilder {
     /// 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<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city ,   country ,  pop
     /// Boston,\"
@@ -383,13 +365,11 @@ impl ReaderBuilder {
     /// # Example: `$` as a record terminator
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::{ReaderBuilder, Terminator};
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "city,country,pop$Boston,United States,4628910";
     ///     let mut rdr = ReaderBuilder::new()
     ///         .terminator(Terminator::Any(b'$'))
@@ -404,10 +384,7 @@ impl ReaderBuilder {
     ///     }
     /// }
     /// ```
-    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 @@ impl ReaderBuilder {
     /// # 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<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,'United States',4628910
@@ -458,13 +433,11 @@ impl ReaderBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::ReaderBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,\"The \\\"United\\\" States\",4628910
@@ -497,13 +470,11 @@ impl ReaderBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::ReaderBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,\"The \"\"United\"\" States\",4628910
@@ -536,13 +507,11 @@ impl ReaderBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::ReaderBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,\"The United States,4628910
@@ -577,13 +546,11 @@ impl ReaderBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::ReaderBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// #Concord,United States,42695
@@ -616,13 +583,11 @@ impl ReaderBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::ReaderBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city\x1Fcountry\x1Fpop\x1EBoston\x1FUnited States\x1F4628910";
     ///     let mut rdr = ReaderBuilder::new()
@@ -679,13 +644,11 @@ impl ReaderBuilder {
 /// 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<Error>> {
+/// fn example() -> Result<(), Box<dyn Error>> {
 ///     let data = "\
 /// city;country;pop
 /// Boston;United States;4628910
@@ -801,13 +764,11 @@ impl Reader<Reader<File>> {
     /// # Example
     ///
     /// ```no_run
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::Reader;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut rdr = Reader::from_path("foo.csv")?;
     ///     for result in rdr.records() {
     ///         let record = result?;
@@ -850,13 +811,11 @@ impl<R: io::Read> Reader<R> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::Reader;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -893,12 +852,10 @@ impl<R: io::Read> Reader<R> {
     /// 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 @@ impl<R: io::Read> Reader<R> {
     /// }
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,popcount
     /// Boston,United States,4628910
@@ -952,12 +909,10 @@ impl<R: io::Read> Reader<R> {
     /// 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 @@ impl<R: io::Read> Reader<R> {
     /// }
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "foo,1,2,3";
     ///     let mut rdr = ReaderBuilder::new()
     ///         .has_headers(false)
@@ -1001,12 +956,10 @@ impl<R: io::Read> Reader<R> {
     /// 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 @@ impl<R: io::Read> Reader<R> {
     /// }
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// label,value
     /// celsius,22.2222
@@ -1065,7 +1018,8 @@ impl<R: io::Read> Reader<R> {
     /// }
     /// ```
     pub fn deserialize<D>(&mut self) -> DeserializeRecordsIter<R, D>
-            where D: DeserializeOwned
+    where
+        D: DeserializeOwned,
     {
         DeserializeRecordsIter::new(self)
     }
@@ -1091,12 +1045,10 @@ impl<R: io::Read> Reader<R> {
     /// # 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 @@ impl<R: io::Read> Reader<R> {
     /// }
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,popcount
     /// Boston,United States,4628910
@@ -1129,7 +1081,8 @@ impl<R: io::Read> Reader<R> {
     /// }
     /// ```
     pub fn into_deserialize<D>(self) -> DeserializeRecordsIntoIter<R, D>
-            where D: DeserializeOwned
+    where
+        D: DeserializeOwned,
     {
         DeserializeRecordsIntoIter::new(self)
     }
@@ -1146,13 +1099,11 @@ impl<R: io::Read> Reader<R> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::Reader;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -1188,13 +1139,11 @@ impl<R: io::Read> Reader<R> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::Reader;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -1227,13 +1176,11 @@ impl<R: io::Read> Reader<R> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::Reader;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -1269,13 +1216,11 @@ impl<R: io::Read> Reader<R> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::Reader;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -1316,13 +1261,11 @@ impl<R: io::Read> Reader<R> {
     /// 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<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -1361,7 +1304,7 @@ impl<R: io::Read> Reader<R> {
         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 @@ impl<R: io::Read> Reader<R> {
     /// 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<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -1441,13 +1382,11 @@ impl<R: io::Read> Reader<R> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::{Reader, StringRecord};
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -1474,13 +1413,11 @@ impl<R: io::Read> Reader<R> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::{Reader, ByteRecord};
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -1545,13 +1482,11 @@ impl<R: io::Read> Reader<R> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::{Reader, StringRecord};
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -1568,7 +1503,7 @@ impl<R: io::Read> Reader<R> {
     /// }
     /// ```
     pub fn read_record(&mut self, record: &mut StringRecord) -> Result<bool> {
-        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 @@ impl<R: io::Read> Reader<R> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::{ByteRecord, Reader};
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,pop
     /// Boston,United States,4628910
@@ -1672,13 +1605,17 @@ impl<R: io::Read> Reader<R> {
         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 @@ impl<R: io::Read> Reader<R> {
             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 @@ impl<R: io::Read> Reader<R> {
     /// # 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<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,popcount
     /// Boston,United States,4628910
@@ -1760,14 +1695,12 @@ impl<R: io::Read> Reader<R> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use std::io;
     /// use csv::{Reader, Position};
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,popcount
     /// Boston,United States,4628910
@@ -1838,14 +1771,12 @@ impl<R: io::Read + io::Seek> Reader<R> {
     /// # 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<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let data = "\
     /// city,country,popcount
     /// Boston,United States,4628910
@@ -1929,7 +1860,7 @@ impl ReaderState {
                 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 @@ pub struct DeserializeRecordsIntoIter<R, D> {
 
 impl<R: io::Read, D: DeserializeOwned> DeserializeRecordsIntoIter<R, D> {
     fn new(mut rdr: Reader<R>) -> DeserializeRecordsIntoIter<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)
+        };
         DeserializeRecordsIntoIter {
             rdr: rdr,
             rec: StringRecord::new(),
@@ -1985,8 +1915,8 @@ impl<R: io::Read, D: DeserializeOwned> DeserializeRecordsIntoIter<R, D> {
     }
 }
 
-impl<R: io::Read, D: DeserializeOwned>
-    Iterator for DeserializeRecordsIntoIter<R, D>
+impl<R: io::Read, D: DeserializeOwned> Iterator
+    for DeserializeRecordsIntoIter<R, D>
 {
     type Item = Result<D>;
 
@@ -2014,12 +1944,11 @@ pub struct DeserializeRecordsIter<'r, R: 'r, D> {
 
 impl<'r, R: io::Read, D: DeserializeOwned> DeserializeRecordsIter<'r, R, D> {
     fn new(rdr: &'r mut Reader<R>) -> 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> DeserializeRecordsIter<'r, R, D> {
     }
 }
 
-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<D>;
 
@@ -2209,14 +2138,18 @@ impl<'r, R: io::Read> Iterator for ByteRecordsIter<'r, R> {
 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 @@ mod tests {
     #[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());
@@ -2347,9 +2279,8 @@ mod tests {
     #[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());
@@ -2357,18 +2288,16 @@ mod tests {
         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),
         }
     }
@@ -2399,9 +2328,8 @@ mod tests {
     #[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());
@@ -2409,18 +2337,16 @@ mod tests {
         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),
         }
 
@@ -2501,9 +2427,8 @@ mod tests {
     #[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();
 
         {
@@ -2532,9 +2457,8 @@ mod tests {
     #[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());
@@ -2561,8 +2485,7 @@ mod tests {
     #[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();
@@ -2587,8 +2510,7 @@ mod tests {
     #[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"]);
     }
@@ -2598,8 +2520,7 @@ mod tests {
     #[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());
@@ -2611,8 +2532,7 @@ mod tests {
     #[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]);
     }
@@ -2661,9 +2581,8 @@ mod tests {
     // 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);
     }
 
@@ -2671,9 +2590,8 @@ mod tests {
     // 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 --git a/src/serializer.rs b/src/serializer.rs
index 8f9366c7..1585625d 100644
--- a/src/serializer.rs
+++ b/src/serializer.rs
@@ -5,15 +5,13 @@ 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 error::{Error, ErrorKind, new_error};
-use writer::Writer;
+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.
@@ -67,6 +65,10 @@ impl<'a, 'w, W: io::Write> Serializer for &'a mut SeRecord<'w, W> {
         self.wtr.write_field(buffer.format(v))
     }
 
+    fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
+        self.collect_str(&v)
+    }
+
     fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
         let mut buffer = itoa::Buffer::new();
         self.wtr.write_field(buffer.format(v))
@@ -87,6 +89,10 @@ impl<'a, 'w, W: io::Write> Serializer for &'a mut SeRecord<'w, W> {
         self.wtr.write_field(buffer.format(v))
     }
 
+    fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
+        self.collect_str(&v)
+    }
+
     fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
         let mut buffer = ryu::Buffer::new();
         self.wtr.write_field(buffer.format(v))
@@ -198,7 +204,8 @@ impl<'a, 'w, W: io::Write> Serializer for &'a mut SeRecord<'w, W> {
         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(
@@ -343,7 +350,7 @@ impl<'a, 'w, W: io::Write> SerializeStructVariant for &'a mut SeRecord<'w, W> {
 
 impl SerdeError for Error {
     fn custom<T: fmt::Display>(msg: T) -> Error {
-        new_error(ErrorKind::Serialize(msg.to_string()))
+        Error::new(ErrorKind::Serialize(msg.to_string()))
     }
 }
 
@@ -440,10 +447,7 @@ struct SeHeader<'w, W: 'w + io::Write> {
 
 impl<'w, W: io::Write> SeHeader<'w, W> {
     fn new(wtr: &'w mut Writer<W>) -> Self {
-        SeHeader {
-            wtr: wtr,
-            state: HeaderState::Write,
-        }
+        SeHeader { wtr: wtr, state: HeaderState::Write }
     }
 
     fn wrote_header(&self) -> bool {
@@ -513,6 +517,10 @@ impl<'a, 'w, W: io::Write> Serializer for &'a mut SeHeader<'w, W> {
         self.handle_scalar(v)
     }
 
+    fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
+        self.handle_scalar(v)
+    }
+
     fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
         self.handle_scalar(v)
     }
@@ -529,6 +537,10 @@ impl<'a, 'w, W: io::Write> Serializer for &'a mut SeHeader<'w, W> {
         self.handle_scalar(v)
     }
 
+    fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
+        self.handle_scalar(v)
+    }
+
     fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
         self.handle_scalar(v)
     }
@@ -627,9 +639,7 @@ impl<'a, 'w, W: io::Write> Serializer for &'a mut SeHeader<'w, W> {
         _variant: &'static str,
         _len: usize,
     ) -> Result<Self::SerializeTupleVariant, Self::Error> {
-        Err(Error::custom(
-            "serializing enum tuple variants is not supported",
-        ))
+        Err(Error::custom("serializing enum tuple variants is not supported"))
     }
 
     fn serialize_map(
@@ -659,9 +669,7 @@ impl<'a, 'w, W: io::Write> Serializer for &'a mut SeHeader<'w, W> {
         _variant: &'static str,
         _len: usize,
     ) -> Result<Self::SerializeStructVariant, Self::Error> {
-        Err(Error::custom(
-            "serializing enum struct variants is not supported",
-        ))
+        Err(Error::custom("serializing enum struct variants is not supported"))
     }
 }
 
@@ -762,10 +770,8 @@ impl<'a, 'w, W: io::Write> SerializeStruct for &'a mut SeHeader<'w, W> {
         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);
         }
@@ -803,11 +809,11 @@ impl<'a, 'w, W: io::Write> SerializeStructVariant for &'a mut SeHeader<'w, W> {
 
 #[cfg(test)]
 mod tests {
+    use bstr::ByteSlice;
     use serde::Serialize;
-    use serde_bytes::Bytes;
 
-    use error::{Error, ErrorKind};
-    use writer::Writer;
+    use crate::error::{Error, ErrorKind};
+    use crate::writer::Writer;
 
     use super::{SeHeader, SeRecord};
 
@@ -858,6 +864,24 @@ mod tests {
         assert_eq!(got, "");
     }
 
+    #[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);
@@ -867,6 +891,15 @@ mod tests {
         assert_eq!(got, "");
     }
 
+    #[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('☃');
@@ -887,7 +920,7 @@ mod tests {
 
     #[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);
@@ -951,7 +984,11 @@ mod tests {
     #[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");
@@ -975,7 +1012,11 @@ mod tests {
     #[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");
@@ -1088,6 +1129,23 @@ mod tests {
         assert_eq!(got, "true,5,hi\n");
     }
 
+    #[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)]
@@ -1120,10 +1178,7 @@ mod tests {
 
         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());
@@ -1169,19 +1224,9 @@ mod tests {
             empty: (),
         }
         let row = (
-            Foo {
-                label: "hi".to_string(),
-                num: 5.0,
-            },
-            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());
@@ -1199,13 +1244,7 @@ mod tests {
             label: String,
             num: f64,
         }
-        let row = (
-            3.14,
-            Foo {
-                label: "hi".to_string(),
-                num: 5.0,
-            },
-        );
+        let row = (3.14, Foo { label: "hi".to_string(), num: 5.0 });
 
         let got = serialize(row.clone());
         assert_eq!(got, "3.14,hi,5.0\n");
@@ -1224,13 +1263,7 @@ mod tests {
             label: String,
             num: f64,
         }
-        let row = (
-            Foo {
-                label: "hi".to_string(),
-                num: 5.0,
-            },
-            3.14,
-        );
+        let row = (Foo { label: "hi".to_string(), num: 5.0 }, 3.14);
 
         let got = serialize(row.clone());
         assert_eq!(got, "hi,5.0,3.14\n");
@@ -1250,14 +1283,8 @@ mod tests {
             num: f64,
         }
         let row = vec![
-            Foo {
-                label: "hi".to_string(),
-                num: 5.0,
-            },
-            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());
@@ -1285,22 +1312,10 @@ mod tests {
         struct Baz(bool);
         let row = (
             (
-                Foo {
-                    label: "hi".to_string(),
-                    num: 5.0,
-                },
-                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());
diff --git a/src/string_record.rs b/src/string_record.rs
index cbd3307c..4b680b62 100644
--- a/src/string_record.rs
+++ b/src/string_record.rs
@@ -7,47 +7,10 @@ use std::str;
 
 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<R: io::Read>(
-    rdr: &mut Reader<R>,
-    record: &mut StringRecord,
-) -> Result<bool> {
-    // 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 @@ pub struct StringRecord(ByteRecord);
 
 impl PartialEq for StringRecord {
     fn eq(&self, other: &StringRecord) -> bool {
-        byte_record::eq(&self.0, &other.0)
+        self.0.iter_eq(&other.0)
     }
 }
 
 impl<T: AsRef<[u8]>> PartialEq<Vec<T>> for StringRecord {
     fn eq(&self, other: &Vec<T>) -> bool {
-        byte_record::eq(&self.0, other)
+        self.0.iter_eq(other)
     }
 }
 
 impl<'a, T: AsRef<[u8]>> PartialEq<Vec<T>> for &'a StringRecord {
     fn eq(&self, other: &Vec<T>) -> bool {
-        byte_record::eq(&self.0, other)
+        self.0.iter_eq(other)
     }
 }
 
 impl<T: AsRef<[u8]>> 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 @@ impl StringRecord {
     /// # Example: valid UTF-8
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::{ByteRecord, StringRecord};
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     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 @@ impl StringRecord {
     pub fn from_byte_record(
         record: ByteRecord,
     ) -> result::Result<StringRecord, FromUtf8Error> {
-        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 @@ impl StringRecord {
     #[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 @@ impl StringRecord {
     /// 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 @@ impl StringRecord {
     /// }
     ///
     /// # fn main() { example().unwrap() }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let record = StringRecord::from(vec![
     ///         "Boston", "United States", "4628910",
     ///     ]);
@@ -300,12 +259,10 @@ impl StringRecord {
     /// 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 @@ impl StringRecord {
     /// }
     ///
     /// # fn main() { example().unwrap() }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     // Notice that the fields are not in the same order
     ///     // as the fields in the struct!
     ///     let header = StringRecord::from(vec![
@@ -473,8 +430,9 @@ impl StringRecord {
             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());
+        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());
         }
@@ -502,13 +460,11 @@ impl StringRecord {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::{StringRecord, ReaderBuilder};
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut record = StringRecord::new();
     ///     let mut rdr = ReaderBuilder::new()
     ///         .has_headers(false)
@@ -651,12 +607,49 @@ impl StringRecord {
     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<R: io::Read>(
+        &mut self,
+        rdr: &mut Reader<R>,
+    ) -> Result<bool> {
+        // 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<usize> 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<T: AsRef<str>> From<Vec<T>> for StringRecord {
@@ -675,7 +668,7 @@ impl<'a, T: AsRef<str>> From<&'a [T]> for StringRecord {
 
 impl<T: AsRef<str>> FromIterator<T> for StringRecord {
     #[inline]
-    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> StringRecord {
+    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> StringRecord {
         let mut record = StringRecord::new();
         record.extend(iter);
         record
@@ -684,7 +677,7 @@ impl<T: AsRef<str>> FromIterator<T> for StringRecord {
 
 impl<T: AsRef<str>> Extend<T> for StringRecord {
     #[inline]
-    fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
+    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
         for x in iter {
             self.push_field(x.as_ref());
         }
@@ -741,7 +734,7 @@ impl<'r> DoubleEndedIterator for StringRecordIter<'r> {
 
 #[cfg(test)]
 mod tests {
-    use string_record::StringRecord;
+    use crate::string_record::StringRecord;
 
     #[test]
     fn trim_front() {
@@ -815,8 +808,8 @@ mod tests {
     // 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 @@ mod tests {
     // 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 --git a/src/tutorial.rs b/src/tutorial.rs
index c9c91b12..3ec8c2a6 100644
--- a/src/tutorial.rs
+++ b/src/tutorial.rs
@@ -53,7 +53,7 @@ $ cd csvtutor
 ```
 
 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 @@ version = "0.1.0"
 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 @@ this:
 
 ```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 @@ its error handling.
 
 ```no_run
 //tutorial-error-01.rs
-extern crate csv;
-
 use std::io;
 
 fn main() {
@@ -286,8 +281,6 @@ let's get rid of the panic and print an error message manually:
 
 ```no_run
 //tutorial-error-02.rs
-extern crate csv;
-
 use std::io;
 use std::process;
 
@@ -327,8 +320,6 @@ error, which our `main` function can then inspect and decide what to do with.
 
 ```no_run
 //tutorial-error-03.rs
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
@@ -340,12 +331,12 @@ fn main() {
     }
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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<Error> and return it.
+        // Otherwise, convert our error to a Box<dyn Error> and return it.
         match result {
             Err(err) => return Err(From::from(err)),
             Ok(record) => {
@@ -357,10 +348,10 @@ fn run() -> Result<(), Box<Error>> {
 }
 ```
 
-Our new function, `run`, has a return type of `Result<(), Box<Error>>`. In
+Our new function, `run`, has a return type of `Result<(), Box<dyn Error>>`. In
 simple terms, this says that `run` either returns nothing when successful, or
-if an error occurred, it returns a `Box<Error>`, which stands for "any kind of
-error." A `Box<Error>` is hard to inspect if we cared about the specific error
+if an error occurred, it returns a `Box<dyn Error>`, which stands for "any kind of
+error." A `Box<dyn Error>` 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 @@ special Rust language feature: the question mark.
 
 ```no_run
 //tutorial-error-04.rs
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
@@ -382,7 +371,7 @@ fn main() {
     }
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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 @@ ourselves. We will use the `?` heavily throughout this tutorial, and it's
 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<Error>` as our error
+We'll end this section with a word of caution: using `Box<dyn Error>` 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 @@ path argument instead of stdin.
 
 ```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<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let file_path = get_first_arg()?;
     let file = File::open(file_path)?;
     let mut rdr = csv::Reader::from_reader(file);
@@ -448,7 +435,7 @@ fn run() -> Result<(), Box<Error>> {
 
 /// 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<OsString, Box<Error>> {
+fn get_first_arg() -> Result<OsString, Box<dyn Error>> {
     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 @@ produces terser examples.)
 
 ```no_run
 //tutorial-read-headers-01.rs
-# extern crate csv;
-#
 # use std::error::Error;
 # use std::io;
 # use std::process;
 #
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::ReaderBuilder::new()
         .has_headers(false)
         .from_reader(io::stdin());
@@ -580,13 +565,11 @@ method like so:
 
 ```no_run
 //tutorial-read-headers-02.rs
-# extern crate csv;
-#
 # use std::error::Error;
 # use std::io;
 # use std::process;
 #
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
     {
         // We nest this call in its own scope because of lifetimes.
@@ -663,13 +646,11 @@ as seen in the following example:
 
 ```no_run
 //tutorial-read-delimiter-01.rs
-# extern crate csv;
-#
 # use std::error::Error;
 # use std::io;
 # use std::process;
 #
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::ReaderBuilder::new()
         .has_headers(false)
         .delimiter(b';')
@@ -753,13 +734,11 @@ a lot of manual work. This next example shows how.
 
 ```no_run
 //tutorial-read-serde-01.rs
-# extern crate csv;
-#
 # use std::error::Error;
 # use std::io;
 # use std::process;
 #
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
     for result in rdr.records() {
         let record = result?;
@@ -798,8 +777,6 @@ type: `(String, String, Option<u64>, f64, f64)`.
 
 ```no_run
 //tutorial-read-serde-02.rs
-# extern crate csv;
-#
 # use std::error::Error;
 # use std::io;
 # use std::process;
@@ -808,7 +785,7 @@ type: `(String, String, Option<u64>, f64, f64)`.
 // record type.
 type Record = (String, String, Option<u64>, f64, f64);
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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 @@ a new `use` statement that imports `HashMap` from the standard library:
 
 ```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 @@ use std::collections::HashMap;
 // record type.
 type Record = HashMap<String, String>;
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
     for result in rdr.deserialize() {
         let record: Record = result?;
@@ -894,37 +869,33 @@ $ ./target/debug/csvtutor < uspop.csv
 
 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<u64>, 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<u64>, 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 @@ struct Record {
     state: String,
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
     for result in rdr.deserialize() {
         let record: Record = result?;
@@ -972,14 +943,13 @@ Record { latitude: 33.7133333, longitude: -87.3886111, population: None, city: "
 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 @@ Let's start by running our program from the previous section:
 
 ```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 @@ struct Record {
     state: String,
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
     for result in rdr.deserialize() {
         let record: Record = result?;
@@ -1128,14 +1096,11 @@ to a `None` value, as shown in this next example:
 
 ```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 @@ struct Record {
     state: String,
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
     for result in rdr.deserialize() {
         let record: Record = result?;
@@ -1199,13 +1164,11 @@ Let's start with the most basic example: writing a few CSV records to `stdout`.
 
 ```no_run
 //tutorial-write-01.rs
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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 @@ of `stdout`:
 
 ```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<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let file_path = get_first_arg()?;
     let mut wtr = csv::Writer::from_path(file_path)?;
 
@@ -1332,7 +1293,7 @@ fn run() -> Result<(), Box<Error>> {
 
 /// 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<OsString, Box<Error>> {
+fn get_first_arg() -> Result<OsString, Box<dyn Error>> {
     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 @@ Here's an example:
 
 ```no_run
 //tutorial-write-delimiter-01.rs
-# extern crate csv;
-#
 # use std::error::Error;
 # use std::io;
 # use std::process;
 #
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut wtr = csv::WriterBuilder::new()
         .delimiter(b'\t')
         .quote_style(csv::QuoteStyle::NonNumeric)
@@ -1431,13 +1390,11 @@ As with reading, let's start by seeing how we can serialize a Rust tuple.
 
 ```no_run
 //tutorial-write-serde-01.rs
-# extern crate csv;
-#
 # use std::error::Error;
 # use std::io;
 # use std::process;
 #
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut wtr = csv::Writer::from_writer(io::stdout());
 
     // We still need to write headers manually.
@@ -1488,31 +1445,27 @@ As with reading, we can also serialize custom structs as CSV records. As a
 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 @@ struct Record<'a> {
     longitude: f64,
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     let mut wtr = csv::Writer::from_writer(io::stdout());
 
     wtr.serialize(Record {
@@ -1636,14 +1589,12 @@ rows with a field that matches the query.
 
 ```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<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     // 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 @@ change:
 
 ```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<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     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 @@ dependencies to your `Cargo.toml` in your `[dependencies]` section if they
 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 @@ struct Record {
     longitude: f64,
 }
 
-fn run() -> Result<(), Box<Error>> {
+fn run() -> Result<(), Box<dyn Error>> {
     // 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 @@ adapting a previous example to count the number of records in
 
 ```no_run
 //tutorial-perf-alloc-01.rs
-extern crate csv;
-
 use std::error::Error;
 use std::io;
 use std::process;
 
-fn run() -> Result<u64, Box<Error>> {
+fn run() -> Result<u64, Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
 
     let mut count = 0;
@@ -2029,13 +1972,11 @@ shown in the next example:
 
 ```no_run
 //tutorial-perf-alloc-02.rs
-# extern crate csv;
-#
 # use std::error::Error;
 # use std::io;
 # use std::process;
 #
-fn run() -> Result<u64, Box<Error>> {
+fn run() -> Result<u64, Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
 
     let mut count = 0;
@@ -2114,13 +2055,11 @@ method.
 
 ```no_run
 //tutorial-perf-alloc-03.rs
-# extern crate csv;
-#
 # use std::error::Error;
 # use std::io;
 # use std::process;
 #
-fn run() -> Result<u64, Box<Error>> {
+fn run() -> Result<u64, Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
     let mut record = csv::ByteRecord::new();
 
@@ -2197,15 +2136,12 @@ example using Serde in a previous section:
 
 ```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 @@ struct Record {
     longitude: f64,
 }
 
-fn run() -> Result<u64, Box<Error>> {
+fn run() -> Result<u64, Box<dyn Error>> {
     let mut rdr = csv::Reader::from_reader(io::stdin());
 
     let mut count = 0;
@@ -2269,15 +2205,12 @@ like:
 
 ```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 @@ struct Record<'a> {
     longitude: f64,
 }
 
-fn run() -> Result<u64, Box<Error>> {
+fn run() -> Result<u64, Box<dyn Error>> {
     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 @@ of `StringRecord`:
 
 ```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 @@ struct Record<'a> {
     longitude: f64,
 }
 
-fn run() -> Result<u64, Box<Error>> {
+fn run() -> Result<u64, Box<dyn Error>> {
     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 @@ access to I/O, which would be harder without the standard library.)
 
 ```no_run
 //tutorial-perf-core-01.rs
-extern crate csv_core;
-
 use std::io::{self, Read};
 use std::process;
 
diff --git a/src/writer.rs b/src/writer.rs
index f02bee92..2d7d097b 100644
--- a/src/writer.rs
+++ b/src/writer.rs
@@ -4,20 +4,15 @@ 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.
 ///
@@ -36,7 +31,7 @@ impl Default for WriterBuilder {
     fn default() -> WriterBuilder {
         WriterBuilder {
             builder: CoreWriterBuilder::default(),
-            capacity: 8 * (1<<10),
+            capacity: 8 * (1 << 10),
             flexible: false,
             has_headers: true,
         }
@@ -52,13 +47,11 @@ impl WriterBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::WriterBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new().from_writer(vec![]);
     ///     wtr.write_record(&["a", "b", "c"])?;
     ///     wtr.write_record(&["x", "y", "z"])?;
@@ -81,13 +74,11 @@ impl WriterBuilder {
     /// # Example
     ///
     /// ```no_run
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::WriterBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new().from_path("foo.csv")?;
     ///     wtr.write_record(&["a", "b", "c"])?;
     ///     wtr.write_record(&["x", "y", "z"])?;
@@ -107,13 +98,11 @@ impl WriterBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::WriterBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new().from_writer(vec![]);
     ///     wtr.write_record(&["a", "b", "c"])?;
     ///     wtr.write_record(&["x", "y", "z"])?;
@@ -134,13 +123,11 @@ impl WriterBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::WriterBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new()
     ///         .delimiter(b';')
     ///         .from_writer(vec![]);
@@ -176,12 +163,10 @@ impl WriterBuilder {
     /// 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> {
@@ -194,7 +179,7 @@ impl WriterBuilder {
     /// }
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new().from_writer(vec![]);
     ///     wtr.serialize(Row {
     ///         city: "Boston",
@@ -225,13 +210,11 @@ impl WriterBuilder {
     /// 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<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new().from_writer(vec![]);
     ///     wtr.serialize(("Boston", "United States", 4628910))?;
     ///     wtr.serialize(("Concord", "United States", 42695))?;
@@ -260,13 +243,11 @@ impl WriterBuilder {
     /// # Example: writing flexible records
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::WriterBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new()
     ///         .flexible(true)
     ///         .from_writer(vec![]);
@@ -282,13 +263,11 @@ impl WriterBuilder {
     /// # Example: error when `flexible` is disabled
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::WriterBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new()
     ///         .flexible(false)
     ///         .from_writer(vec![]);
@@ -323,13 +302,11 @@ impl WriterBuilder {
     /// 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<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new()
     ///         .terminator(Terminator::CRLF)
     ///         .from_writer(vec![]);
@@ -341,10 +318,7 @@ impl WriterBuilder {
     ///     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
     }
@@ -362,13 +336,11 @@ impl WriterBuilder {
     /// 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<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new()
     ///         .quote_style(QuoteStyle::NonNumeric)
     ///         .from_writer(vec![]);
@@ -387,13 +359,11 @@ impl WriterBuilder {
     /// 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<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new()
     ///         .quote_style(QuoteStyle::Never)
     ///         .from_writer(vec![]);
@@ -417,13 +387,11 @@ impl WriterBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::WriterBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new()
     ///         .quote(b'\'')
     ///         .from_writer(vec![]);
@@ -448,13 +416,11 @@ impl WriterBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::WriterBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new()
     ///         .double_quote(false)
     ///         .from_writer(vec![]);
@@ -482,13 +448,11 @@ impl WriterBuilder {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::WriterBuilder;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new()
     ///         .double_quote(false)
     ///         .escape(b'$')
@@ -612,13 +576,11 @@ impl Writer<File> {
     /// # Example
     ///
     /// ```no_run
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::Writer;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = Writer::from_path("foo.csv")?;
     ///     wtr.write_record(&["a", "b", "c"])?;
     ///     wtr.write_record(&["x", "y", "z"])?;
@@ -633,19 +595,15 @@ impl Writer<File> {
 
 impl<W: io::Write> Writer<W> {
     fn new(builder: &WriterBuilder, wtr: W) -> Writer<W> {
-        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,
@@ -665,13 +623,11 @@ impl<W: io::Write> Writer<W> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::Writer;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = Writer::from_writer(vec![]);
     ///     wtr.write_record(&["a", "b", "c"])?;
     ///     wtr.write_record(&["x", "y", "z"])?;
@@ -696,12 +652,10 @@ impl<W: io::Write> Writer<W> {
     /// 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> {
@@ -714,7 +668,7 @@ impl<W: io::Write> Writer<W> {
     /// }
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = Writer::from_writer(vec![]);
     ///     wtr.serialize(Row {
     ///         city: "Boston",
@@ -763,7 +717,7 @@ impl<W: io::Write> Writer<W> {
     /// | 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` |
@@ -781,12 +735,10 @@ impl<W: io::Write> Writer<W> {
     /// this:
     ///
     /// ```
-    /// extern crate csv;
-    /// #[macro_use]
-    /// extern crate serde_derive;
-    ///
     /// use std::error::Error;
+    ///
     /// use csv::Writer;
+    /// use serde::Serialize;
     ///
     /// #[derive(Serialize)]
     /// struct Row {
@@ -801,7 +753,7 @@ impl<W: io::Write> Writer<W> {
     /// }
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = Writer::from_writer(vec![]);
     ///     wtr.serialize(Row {
     ///         label: "foo".to_string(),
@@ -849,12 +801,10 @@ impl<W: io::Write> Writer<W> {
     /// 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 {
@@ -863,7 +813,7 @@ impl<W: io::Write> Writer<W> {
     /// }
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = WriterBuilder::new()
     ///         .has_headers(false)
     ///         .from_writer(vec![]);
@@ -926,13 +876,11 @@ impl<W: io::Write> Writer<W> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::Writer;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = Writer::from_writer(vec![]);
     ///     wtr.write_record(&["a", "b", "c"])?;
     ///     wtr.write_record(&["x", "y", "z"])?;
@@ -943,7 +891,9 @@ impl<W: io::Write> Writer<W> {
     /// }
     /// ```
     pub fn write_record<I, T>(&mut self, record: I) -> Result<()>
-        where I: IntoIterator<Item=T>, T: AsRef<[u8]>
+    where
+        I: IntoIterator<Item = T>,
+        T: AsRef<[u8]>,
     {
         for field in record.into_iter() {
             self.write_field_impl(field)?;
@@ -967,13 +917,11 @@ impl<W: io::Write> Writer<W> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::{ByteRecord, Writer};
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     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"][..]))?;
@@ -1027,7 +975,8 @@ impl<W: io::Write> Writer<W> {
                     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);
@@ -1051,13 +1000,11 @@ impl<W: io::Write> Writer<W> {
     /// # Example
     ///
     /// ```
-    /// extern crate csv;
-    ///
     /// use std::error::Error;
     /// use csv::Writer;
     ///
     /// # fn main() { example().unwrap(); }
-    /// fn example() -> Result<(), Box<Error>> {
+    /// fn example() -> Result<(), Box<dyn Error>> {
     ///     let mut wtr = Writer::from_writer(vec![]);
     ///     wtr.write_field("a")?;
     ///     wtr.write_field("b")?;
@@ -1124,7 +1071,7 @@ impl<W: io::Write> Writer<W> {
     ) -> result::Result<W, IntoInnerError<Writer<W>>> {
         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)),
         }
     }
 
@@ -1185,7 +1132,7 @@ impl<W: io::Write> Writer<W> {
                         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,
@@ -1230,9 +1177,11 @@ impl Buffer {
 
 #[cfg(test)]
 mod tests {
-    use byte_record::ByteRecord;
-    use error::ErrorKind;
-    use string_record::StringRecord;
+    use serde::Serialize;
+
+    use crate::byte_record::ByteRecord;
+    use crate::error::ErrorKind;
+    use crate::string_record::StringRecord;
 
     use super::{Writer, WriterBuilder};
 
@@ -1327,8 +1276,8 @@ mod tests {
     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());
@@ -1380,13 +1329,31 @@ mod tests {
             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");
     }
 
+    #[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,
+        });
+        assert_eq!(wtr_as_string(wtr), "9223372036854775808,42.5,true\n");
+    }
+
     #[test]
     fn serialize_tuple() {
         let mut wtr = WriterBuilder::new().from_writer(vec![]);


Test patch:
diff --git a/tests/tests.rs b/tests/tests.rs
index 1d2386f4..c1416481 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -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 @@ use std::process::{self, Command};
 
 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 @@ impl Output {
     ///
     /// 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 @@ impl Output {
                  \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 @@ impl Output {
                  \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 @@ impl Output {
                  \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
     }