Upgrade rust/crates/rand_chacha to 0.3.0

Test: make
Change-Id: I327b9a5812630e9622633e0cba33b1b1e535c1c8
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 0739f24..0db4f9b 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
 {
   "git": {
-    "sha1": "e2112c4404c61d3850c0e91f48114db5daf06569"
+    "sha1": "98e220c30234370fb04ba928799ebd9727fc049a"
   }
 }
diff --git a/Android.bp b/Android.bp
index af926c4..18535ef 100644
--- a/Android.bp
+++ b/Android.bp
@@ -8,7 +8,6 @@
     edition: "2018",
     features: [
         "default",
-        "simd",
         "std",
     ],
     rustlibs: [
@@ -18,5 +17,5 @@
 }
 
 // dependent_library ["feature_list"]
-//   ppv-lite86-0.2.8 "simd,std"
-//   rand_core-0.5.1
+//   ppv-lite86-0.2.10 "simd,std"
+//   rand_core-0.6.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1273895..8a07390 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,14 @@
 The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [0.3.0] - 2020-12-08
+- Bump `rand_core` version to 0.6.0
+- Bump MSRV to 1.36 (#1011)
+- Remove usage of deprecated feature "simd" of `ppv-lite86` (#979), then revert
+  this change (#1023) since SIMD is only enabled by default from `ppv-lite86 v0.2.10`
+- impl PartialEq+Eq for ChaChaXRng and ChaChaXCore (#979)
+- Fix panic on block counter wrap that was occurring in debug builds (#980)
+
 ## [0.2.2] - 2020-03-09
 - Integrate `c2-chacha`, reducing dependency count (#931)
 - Add CryptoRng to ChaChaXCore (#944)
diff --git a/Cargo.toml b/Cargo.toml
index dea94e9..0f371b3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "rand_chacha"
-version = "0.2.2"
+version = "0.3.0"
 authors = ["The Rand Project Developers", "The Rust Project Developers", "The CryptoCorrosion Contributors"]
 description = "ChaCha random number generator\n"
 homepage = "https://crates.io/crates/rand_chacha"
@@ -24,19 +24,14 @@
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-random/rand"
 [dependencies.ppv-lite86]
-version = "0.2.6"
+version = "0.2.8"
 features = ["simd"]
 default-features = false
 
 [dependencies.rand_core]
-version = "0.5"
+version = "0.6.0"
 
 [features]
-default = ["std", "simd"]
+default = ["std"]
 simd = []
 std = ["ppv-lite86/std"]
-[badges.appveyor]
-repository = "rust-random/rand"
-
-[badges.travis-ci]
-repository = "rust-random/rand"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 601fef9..8d7dcd7 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "rand_chacha"
-version = "0.2.2"
+version = "0.3.0"
 authors = ["The Rand Project Developers", "The Rust Project Developers", "The CryptoCorrosion Contributors"]
 license = "MIT OR Apache-2.0"
 readme = "README.md"
@@ -14,15 +14,11 @@
 categories = ["algorithms", "no-std"]
 edition = "2018"
 
-[badges]
-travis-ci = { repository = "rust-random/rand" }
-appveyor = { repository = "rust-random/rand" }
-
 [dependencies]
-rand_core = { path = "../rand_core", version = "0.5" }
-ppv-lite86 = { version = "0.2.6", default-features = false, features = ["simd"] }
+rand_core = { path = "../rand_core", version = "0.6.0" }
+ppv-lite86 = { version = "0.2.8", default-features = false, features = ["simd"] }
 
 [features]
-default = ["std", "simd"]
+default = ["std"]
 std = ["ppv-lite86/std"]
 simd = [] # deprecated
diff --git a/METADATA b/METADATA
index 7898235..ba8e6ec 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/rand_chacha/rand_chacha-0.2.2.crate"
+    value: "https://static.crates.io/crates/rand_chacha/rand_chacha-0.3.0.crate"
   }
-  version: "0.2.2"
+  version: "0.3.0"
   license_type: NOTICE
   last_upgrade_date {
     year: 2020
-    month: 6
-    day: 18
+    month: 12
+    day: 15
   }
 }
diff --git a/README.md b/README.md
index 69a0ce7..edd754d 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,11 @@
 # rand_chacha
 
-[![Build Status](https://travis-ci.org/rust-random/rand.svg)](https://travis-ci.org/rust-random/rand)
-[![Build Status](https://ci.appveyor.com/api/projects/status/github/rust-random/rand?svg=true)](https://ci.appveyor.com/project/rust-random/rand)
+[![Test Status](https://github.com/rust-random/rand/workflows/Tests/badge.svg?event=push)](https://github.com/rust-random/rand/actions)
 [![Latest version](https://img.shields.io/crates/v/rand_chacha.svg)](https://crates.io/crates/rand_chacha)
 [![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/)
 [![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_chacha)
 [![API](https://docs.rs/rand_chacha/badge.svg)](https://docs.rs/rand_chacha)
-[![Minimum rustc version](https://img.shields.io/badge/rustc-1.32+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)
+[![Minimum rustc version](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)
 
 A cryptographically secure random number generator that uses the ChaCha
 algorithm.
diff --git a/src/chacha.rs b/src/chacha.rs
index cf68c52..17bcc55 100644
--- a/src/chacha.rs
+++ b/src/chacha.rs
@@ -19,6 +19,11 @@
 const STREAM_PARAM_NONCE: u32 = 1;
 const STREAM_PARAM_BLOCK: u32 = 0;
 
+// NB. this must remain consistent with some currently hard-coded numbers in this module
+const BUF_BLOCKS: u8 = 4;
+// number of 32-bit words per ChaCha block (fixed by algorithm definition)
+const BLOCK_WORDS: u8 = 16;
+
 pub struct Array64<T>([T; 64]);
 impl<T> Default for Array64<T>
 where T: Default
@@ -65,7 +70,7 @@
 macro_rules! chacha_impl {
     ($ChaChaXCore:ident, $ChaChaXRng:ident, $rounds:expr, $doc:expr) => {
         #[doc=$doc]
-        #[derive(Clone)]
+        #[derive(Clone, PartialEq, Eq)]
         pub struct $ChaChaXCore {
             state: ChaCha,
         }
@@ -187,10 +192,19 @@
             /// byte-offset.
             #[inline]
             pub fn get_word_pos(&self) -> u128 {
-                let mut block = u128::from(self.rng.core.state.get_stream_param(STREAM_PARAM_BLOCK));
-                // counter is incremented *after* filling buffer
-                block -= 4;
-                (block << 4) + self.rng.index() as u128
+                let buf_start_block = {
+                    let buf_end_block = self.rng.core.state.get_stream_param(STREAM_PARAM_BLOCK);
+                    u64::wrapping_sub(buf_end_block, BUF_BLOCKS.into())
+                };
+                let (buf_offset_blocks, block_offset_words) = {
+                    let buf_offset_words = self.rng.index() as u64;
+                    let blocks_part = buf_offset_words / u64::from(BLOCK_WORDS);
+                    let words_part = buf_offset_words % u64::from(BLOCK_WORDS);
+                    (blocks_part, words_part)
+                };
+                let pos_block = u64::wrapping_add(buf_start_block, buf_offset_blocks);
+                let pos_block_words = u128::from(pos_block) * u128::from(BLOCK_WORDS);
+                pos_block_words + u128::from(block_offset_words)
             }
 
             /// Set the offset from the start of the stream, in 32-bit words.
@@ -200,12 +214,12 @@
             /// 60 bits.
             #[inline]
             pub fn set_word_pos(&mut self, word_offset: u128) {
-                let block = (word_offset >> 4) as u64;
+                let block = (word_offset / u128::from(BLOCK_WORDS)) as u64;
                 self.rng
                     .core
                     .state
                     .set_stream_param(STREAM_PARAM_BLOCK, block);
-                self.rng.generate_and_set((word_offset & 15) as usize);
+                self.rng.generate_and_set((word_offset % u128::from(BLOCK_WORDS)) as usize);
             }
 
             /// Set the stream number.
@@ -241,6 +255,14 @@
                 }
             }
         }
+
+        impl PartialEq<$ChaChaXRng> for $ChaChaXRng {
+            fn eq(&self, rhs: &$ChaChaXRng) -> bool {
+                self.rng.core.state.stream64_eq(&rhs.rng.core.state)
+                    && self.get_word_pos() == rhs.get_word_pos()
+            }
+        }
+        impl Eq for $ChaChaXRng {}
     }
 }
 
@@ -456,4 +478,32 @@
             assert_eq!(rng.next_u32(), clone.next_u32());
         }
     }
+
+    #[test]
+    fn test_chacha_word_pos_wrap_exact() {
+        use super::{BUF_BLOCKS, BLOCK_WORDS};
+        let mut rng = ChaChaRng::from_seed(Default::default());
+        // refilling the buffer in set_word_pos will wrap the block counter to 0
+        let last_block = (1 << 68) - u128::from(BUF_BLOCKS * BLOCK_WORDS);
+        rng.set_word_pos(last_block);
+        assert_eq!(rng.get_word_pos(), last_block);
+    }
+
+    #[test]
+    fn test_chacha_word_pos_wrap_excess() {
+        use super::BLOCK_WORDS;
+        let mut rng = ChaChaRng::from_seed(Default::default());
+        // refilling the buffer in set_word_pos will wrap the block counter past 0
+        let last_block = (1 << 68) - u128::from(BLOCK_WORDS);
+        rng.set_word_pos(last_block);
+        assert_eq!(rng.get_word_pos(), last_block);
+    }
+
+    #[test]
+    fn test_chacha_word_pos_zero() {
+        let mut rng = ChaChaRng::from_seed(Default::default());
+        assert_eq!(rng.get_word_pos(), 0);
+        rng.set_word_pos(0);
+        assert_eq!(rng.get_word_pos(), 0);
+    }
 }
diff --git a/src/guts.rs b/src/guts.rs
index 7561c1b..27ff957 100644
--- a/src/guts.rs
+++ b/src/guts.rs
@@ -21,7 +21,7 @@
 pub(crate) const BUFSZ64: u64 = BLOCK64 * BUFBLOCKS;
 pub(crate) const BUFSZ: usize = BUFSZ64 as usize;
 
-#[derive(Clone)]
+#[derive(Clone, PartialEq, Eq)]
 pub struct ChaCha {
     pub(crate) b: vec128_storage,
     pub(crate) c: vec128_storage,
@@ -91,8 +91,17 @@
     pub fn get_stream_param(&self, param: u32) -> u64 {
         get_stream_param(self, param)
     }
+
+    /// Return whether rhs is equal in all parameters except current 64-bit position.
+    #[inline]
+    pub fn stream64_eq(&self, rhs: &Self) -> bool {
+        let self_d: [u32; 4] = self.d.into();
+        let rhs_d: [u32; 4] = rhs.d.into();
+        self.b == rhs.b && self.c == rhs.c && self_d[3] == rhs_d[3] && self_d[2] == rhs_d[2]
+    }
 }
 
+#[allow(clippy::many_single_char_names)]
 #[inline(always)]
 fn refill_wide_impl<Mach: Machine>(
     m: Mach, state: &mut ChaCha, drounds: u32, out: &mut [u8; BUFSZ],
@@ -100,11 +109,11 @@
     let k = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]);
     let mut pos = state.pos64(m);
     let d0: Mach::u32x4 = m.unpack(state.d);
-    pos += 1;
+    pos = pos.wrapping_add(1);
     let d1 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
-    pos += 1;
+    pos = pos.wrapping_add(1);
     let d2 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
-    pos += 1;
+    pos = pos.wrapping_add(1);
     let d3 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
 
     let b = m.unpack(state.b);
@@ -121,13 +130,13 @@
     }
     let mut pos = state.pos64(m);
     let d0: Mach::u32x4 = m.unpack(state.d);
-    pos += 1;
+    pos = pos.wrapping_add(1);
     let d1 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
-    pos += 1;
+    pos = pos.wrapping_add(1);
     let d2 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
-    pos += 1;
+    pos = pos.wrapping_add(1);
     let d3 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
-    pos += 1;
+    pos = pos.wrapping_add(1);
     let d4 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
 
     let (a, b, c, d) = (