Snap for 8254899 from d3e09fe0f87a172176a5d25fcb396f283997b2bf to tm-release

Change-Id: Ie2888b16d77612970eb16c5f5646824e6b9214c1
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 3a72e82..492a5e3 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "c6a423b4da80da8e80f757f94d2e718187302e40"
-  }
-}
+    "sha1": "e9c65bdb6d982cb7a8593408dca81cca2932bdc6"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 27b486a..d97e86f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,7 +5,7 @@
 
 matrix:
   include:
-    - rust: 1.34.0
+    - rust: 1.46.0 # MSRV
     - rust: stable
     - rust: beta
     - rust: nightly
@@ -37,7 +37,6 @@
     then
         rustup target add $CROSS_CHECK
         cargo check --target $CROSS_CHECK
-        cargo check --tests --target $CROSS_CHECK
         cargo check --target $CROSS_CHECK --no-default-features
     elif [[ "$CROSS_TEST" ]]
     then
diff --git a/Android.bp b/Android.bp
index 027e256..616fb7b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -42,7 +42,7 @@
     host_supported: true,
     crate_name: "crc32fast",
     cargo_env_compat: true,
-    cargo_pkg_version: "1.2.1",
+    cargo_pkg_version: "1.3.2",
     srcs: ["src/lib.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
@@ -68,7 +68,7 @@
     host_supported: true,
     crate_name: "crc32fast",
     cargo_env_compat: true,
-    cargo_pkg_version: "1.2.1",
+    cargo_pkg_version: "1.3.2",
     srcs: ["src/lib.rs"],
     edition: "2015",
     features: [
diff --git a/Cargo.toml b/Cargo.toml
index d211f29..79c0b04 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,16 +3,15 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
 name = "crc32fast"
-version = "1.2.1"
+version = "1.3.2"
 authors = ["Sam Rijs <srijs@airpost.net>", "Alex Crichton <alex@alexcrichton.com>"]
 description = "Fast, SIMD-accelerated CRC32 (IEEE) checksum computation"
 readme = "README.md"
@@ -29,11 +28,11 @@
 version = "0.1"
 
 [dev-dependencies.quickcheck]
-version = "0.9"
+version = "1.0"
 default-features = false
 
 [dev-dependencies.rand]
-version = "0.7"
+version = "0.8"
 
 [features]
 default = ["std"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 6da29ea..83804b3 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "crc32fast"
-version = "1.2.1"
+version = "1.3.2"
 license = "MIT OR Apache-2.0"
 authors = [
   "Sam Rijs <srijs@airpost.net>",
@@ -16,8 +16,8 @@
 
 [dev-dependencies]
 bencher = "0.1"
-quickcheck = { version = "0.9", default-features = false }
-rand = "0.7"
+quickcheck = { version = "1.0", default-features = false }
+rand = "0.8"
 
 [features]
 default = ["std"]
diff --git a/METADATA b/METADATA
index 5a1ae28..a92dca4 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/crc32fast/crc32fast-1.2.1.crate"
+    value: "https://static.crates.io/crates/crc32fast/crc32fast-1.3.2.crate"
   }
-  version: "1.2.1"
+  version: "1.3.2"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 2
-    day: 6
+    year: 2022
+    month: 3
+    day: 1
   }
 }
diff --git a/README.md b/README.md
index 0f1f78b..b0a4827 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,31 @@
 # crc32fast [![Build Status][travis-img]][travis] [![Crates.io][crates-img]][crates] [![Documentation][docs-img]][docs]
 
-[travis-img]:   https://travis-ci.com/srijs/rust-crc32fast.svg?branch=master
-[travis]:       https://travis-ci.com/srijs/rust-crc32fast
-[crates-img]:   https://img.shields.io/crates/v/crc32fast.svg
-[crates]:       https://crates.io/crates/crc32fast
-[docs-img]:     https://docs.rs/crc32fast/badge.svg
-[docs]:         https://docs.rs/crc32fast
+[travis-img]: https://travis-ci.com/srijs/rust-crc32fast.svg?branch=master
+[travis]: https://travis-ci.com/srijs/rust-crc32fast
+[crates-img]: https://img.shields.io/crates/v/crc32fast.svg
+[crates]: https://crates.io/crates/crc32fast
+[docs-img]: https://docs.rs/crc32fast/badge.svg
+[docs]: https://docs.rs/crc32fast
 
 _Fast, SIMD-accelerated CRC32 (IEEE) checksum computation_
 
 ## Usage
 
-```rust
-extern crate crc32fast;
+### Simple usage
 
+For simple use-cases, you can call the `hash` convenience function to
+directly compute the CRC32 checksum for a given byte slice:
+
+```rust
+let checksum = crc32fast::hash(b"foo bar baz");
+```
+
+### Advanced usage
+
+For use-cases that require more flexibility or performance, for example when
+processing large amounts of data, you can create and manipulate a `Hasher`:
+
+```rust
 use crc32fast::Hasher;
 
 let mut hasher = Hasher::new();
@@ -33,10 +45,10 @@
 optimal implementation for the current CPU feature set.
 
 | crate                               | version | variant   | ns/iter | MB/s |
-|-------------------------------------|---------|-----------|---------|------|
-| [crc](https://crates.io/crates/crc) | 1.8.1   | n/a       |   4,926 |  207 |
-| crc32fast (this crate)              | 1.0.0   | baseline  |     683 | 1499 |
-| crc32fast (this crate)              | 1.0.0   | pclmulqdq |     140 | 7314 |
+| ----------------------------------- | ------- | --------- | ------- | ---- |
+| [crc](https://crates.io/crates/crc) | 1.8.1   | n/a       | 4,926   | 207  |
+| crc32fast (this crate)              | 1.0.0   | baseline  | 683     | 1499 |
+| crc32fast (this crate)              | 1.0.0   | pclmulqdq | 140     | 7314 |
 
 ## Memory Safety
 
@@ -67,10 +79,10 @@
 
 This project is licensed under either of
 
- * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
-   http://www.apache.org/licenses/LICENSE-2.0)
- * MIT license ([LICENSE-MIT](LICENSE-MIT) or
-   http://opensource.org/licenses/MIT)
+- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
+  http://www.apache.org/licenses/LICENSE-2.0)
+- MIT license ([LICENSE-MIT](LICENSE-MIT) or
+  http://opensource.org/licenses/MIT)
 
 at your option.
 
diff --git a/benches/bench.rs b/benches/bench.rs
index d702df0..53b3d83 100644
--- a/benches/bench.rs
+++ b/benches/bench.rs
@@ -21,19 +21,23 @@
 }
 
 fn bench_kilobyte_baseline(b: &mut Bencher) {
-    bench(b, 1024, Hasher::internal_new_baseline(0))
+    bench(b, 1024, Hasher::internal_new_baseline(0, 0))
 }
 
 fn bench_kilobyte_specialized(b: &mut Bencher) {
-    bench(b, 1024, Hasher::internal_new_specialized(0).unwrap())
+    bench(b, 1024, Hasher::internal_new_specialized(0, 0).unwrap())
 }
 
 fn bench_megabyte_baseline(b: &mut Bencher) {
-    bench(b, 1024 * 1024, Hasher::internal_new_baseline(0))
+    bench(b, 1024 * 1024, Hasher::internal_new_baseline(0, 0))
 }
 
 fn bench_megabyte_specialized(b: &mut Bencher) {
-    bench(b, 1024 * 1024, Hasher::internal_new_specialized(0).unwrap())
+    bench(
+        b,
+        1024 * 1024,
+        Hasher::internal_new_specialized(0, 0).unwrap(),
+    )
 }
 
 benchmark_group!(
diff --git a/src/lib.rs b/src/lib.rs
index f147286..8c4f9a9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,20 @@
-//! ## Example
+//! Fast, SIMD-accelerated CRC32 (IEEE) checksum computation.
+//!
+//! ## Usage
+//!
+//! ### Simple usage
+//!
+//! For simple use-cases, you can call the [`hash()`] convenience function to
+//! directly compute the CRC32 checksum for a given byte slice:
+//!
+//! ```rust
+//! let checksum = crc32fast::hash(b"foo bar baz");
+//! ```
+//!
+//! ### Advanced usage
+//!
+//! For use-cases that require more flexibility or performance, for example when
+//! processing large amounts of data, you can create and manipulate a [`Hasher`]:
 //!
 //! ```rust
 //! use crc32fast::Hasher;
@@ -15,7 +31,7 @@
 //! - A fast baseline implementation which processes up to 16 bytes per iteration
 //! - An optimized implementation for modern `x86` using `sse` and `pclmulqdq` instructions
 //!
-//! Calling the `Hasher::new` constructor at runtime will perform a feature detection to select the most
+//! Calling the [`Hasher::new`] constructor at runtime will perform a feature detection to select the most
 //! optimal implementation for the current CPU feature set.
 
 #![cfg_attr(not(feature = "std"), no_std)]
@@ -43,6 +59,15 @@
 mod specialized;
 mod table;
 
+/// Computes the CRC32 hash of a byte slice.
+///
+/// Check out [`Hasher`] for more advanced use-cases.
+pub fn hash(buf: &[u8]) -> u32 {
+    let mut h = Hasher::new();
+    h.update(buf);
+    h.finalize()
+}
+
 #[derive(Clone)]
 enum State {
     Baseline(baseline::State),
@@ -72,25 +97,35 @@
     /// This works just like `Hasher::new`, except that it allows for an initial
     /// CRC32 state to be passed in.
     pub fn new_with_initial(init: u32) -> Self {
-        Self::internal_new_specialized(init).unwrap_or_else(|| Self::internal_new_baseline(init))
+        Self::new_with_initial_len(init, 0)
+    }
+
+    /// Create a new `Hasher` with an initial CRC32 state.
+    ///
+    /// As `new_with_initial`, but also accepts a length (in bytes). The
+    /// resulting object can then be used with `combine` to compute `crc(a ||
+    /// b)` from `crc(a)`, `crc(b)`, and `len(b)`.
+    pub fn new_with_initial_len(init: u32, amount: u64) -> Self {
+        Self::internal_new_specialized(init, amount)
+            .unwrap_or_else(|| Self::internal_new_baseline(init, amount))
     }
 
     #[doc(hidden)]
     // Internal-only API. Don't use.
-    pub fn internal_new_baseline(init: u32) -> Self {
+    pub fn internal_new_baseline(init: u32, amount: u64) -> Self {
         Hasher {
-            amount: 0,
+            amount,
             state: State::Baseline(baseline::State::new(init)),
         }
     }
 
     #[doc(hidden)]
     // Internal-only API. Don't use.
-    pub fn internal_new_specialized(init: u32) -> Option<Self> {
+    pub fn internal_new_specialized(init: u32, amount: u64) -> Option<Self> {
         {
             if let Some(state) = specialized::State::new(init) {
                 return Some(Hasher {
-                    amount: 0,
+                    amount,
                     state: State::Specialized(state),
                 });
             }
@@ -174,5 +209,27 @@
 
             hash_a.finalize() == hash_c.finalize()
         }
+
+        fn combine_from_len(bytes_1: Vec<u8>, bytes_2: Vec<u8>) -> bool {
+            let mut hash_a = Hasher::new();
+            hash_a.update(&bytes_1);
+            let a = hash_a.finalize();
+
+            let mut hash_b = Hasher::new();
+            hash_b.update(&bytes_2);
+            let b = hash_b.finalize();
+
+            let mut hash_ab = Hasher::new();
+            hash_ab.update(&bytes_1);
+            hash_ab.update(&bytes_2);
+            let ab = hash_ab.finalize();
+
+            let mut reconstructed = Hasher::new_with_initial_len(a, bytes_1.len() as u64);
+            let hash_b_reconstructed = Hasher::new_with_initial_len(b, bytes_2.len() as u64);
+
+            reconstructed.combine(&hash_b_reconstructed);
+
+            reconstructed.finalize() == ab
+        }
     }
 }
diff --git a/src/specialized/aarch64.rs b/src/specialized/aarch64.rs
index ce05261..49de6b0 100644
--- a/src/specialized/aarch64.rs
+++ b/src/specialized/aarch64.rs
@@ -7,7 +7,7 @@
 
 impl State {
     pub fn new(state: u32) -> Option<Self> {
-        if is_aarch64_feature_detected!("crc") {
+        if std::arch::is_aarch64_feature_detected!("crc") {
             // SAFETY: The conditions above ensure that all
             //         required instructions are supported by the CPU.
             Some(Self { state })
diff --git a/src/specialized/mod.rs b/src/specialized/mod.rs
index d4b0b8d..525a42c 100644
--- a/src/specialized/mod.rs
+++ b/src/specialized/mod.rs
@@ -1,6 +1,7 @@
 cfg_if! {
     if #[cfg(all(
         crc32fast_stdarchx86,
+        target_feature = "sse2",
         any(target_arch = "x86", target_arch = "x86_64")
     ))] {
         mod pclmulqdq;
diff --git a/src/specialized/pclmulqdq.rs b/src/specialized/pclmulqdq.rs
index 6abb08b..84a60ca 100644
--- a/src/specialized/pclmulqdq.rs
+++ b/src/specialized/pclmulqdq.rs
@@ -89,7 +89,7 @@
 }
 
 #[target_feature(enable = "pclmulqdq", enable = "sse2", enable = "sse4.1")]
-pub unsafe fn calculate(crc: u32, mut data: &[u8]) -> u32 {
+unsafe fn calculate(crc: u32, mut data: &[u8]) -> u32 {
     // In theory we can accelerate smaller chunks too, but for now just rely on
     // the fallback implementation as it's too much hassle and doesn't seem too
     // beneficial.
diff --git a/src/table.rs b/src/table.rs
index 9354601..78b89c3 100644
--- a/src/table.rs
+++ b/src/table.rs
@@ -1,4 +1,7 @@
-pub const CRC32_TABLE: [[u32; 256]; 16] = [
+// NOTE: This is static instead of const to ensure that indexing into this table
+//       doesn't result in large memmoves when in debug mode, which can significantly
+//       impact performance.
+pub static CRC32_TABLE: [[u32; 256]; 16] = [
     [
         0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535,
         0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,