Upgrade percent-encoding to 2.2.0

This project was upgraded with external_updater.
Usage: tools/external_updater/updater.sh update rust/crates/percent-encoding
For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md

Test: TreeHugger
Change-Id: Ib2f98a35a2d7f1bfd74708aafa80bd825326fb1b
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 9e89b5d..a163a23 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "0e874ddcd6fc68a19dc2b6d91bbde2928bac2d0f"
-  }
-}
+    "sha1": "359bc90a4f07224f79cc79c45dc873d44bcd6f14"
+  },
+  "path_in_vcs": "percent_encoding"
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 58d499f..55cce55 100644
--- a/Android.bp
+++ b/Android.bp
@@ -45,9 +45,13 @@
     host_supported: true,
     crate_name: "percent_encoding",
     cargo_env_compat: true,
-    cargo_pkg_version: "2.1.0",
-    srcs: ["lib.rs"],
-    edition: "2015",
+    cargo_pkg_version: "2.2.0",
+    srcs: ["src/lib.rs"],
+    edition: "2018",
+    features: [
+        "alloc",
+        "default",
+    ],
     apex_available: [
         "//apex_available:platform",
         "com.android.resolv",
diff --git a/Cargo.toml b/Cargo.toml
index b51d1d4..53d0b63 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,21 +3,22 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
+edition = "2018"
+rust-version = "1.51"
 name = "percent-encoding"
-version = "2.1.0"
+version = "2.2.0"
 authors = ["The rust-url developers"]
 description = "Percent encoding and decoding"
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
 repository = "https://github.com/servo/rust-url/"
 
-[lib]
-path = "lib.rs"
-test = false
+[features]
+alloc = []
+default = ["alloc"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index e5ff212..cbd8220 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,11 +1,13 @@
 [package]
 name = "percent-encoding"
-version = "2.1.0"
+version = "2.2.0"
 authors = ["The rust-url developers"]
 description = "Percent encoding and decoding"
 repository = "https://github.com/servo/rust-url/"
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
+edition = "2018"
+rust-version = "1.51"
 
-[lib]
-test = false
-path = "lib.rs"
+[features]
+default = ["alloc"]
+alloc = []
diff --git a/LICENSE-MIT b/LICENSE-MIT
index 24de6b4..51d5dc7 100644
--- a/LICENSE-MIT
+++ b/LICENSE-MIT
@@ -1,4 +1,4 @@
-Copyright (c) 2013-2016 The rust-url developers
+Copyright (c) 2013-2022 The rust-url developers
 
 Permission is hereby granted, free of charge, to any
 person obtaining a copy of this software and associated
diff --git a/METADATA b/METADATA
index ac7180b..b0a2425 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/percent-encoding
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "percent-encoding"
 description: "Percent encoding and decoding"
 third_party {
@@ -7,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/percent-encoding/percent-encoding-2.1.0.crate"
+    value: "https://static.crates.io/crates/percent-encoding/percent-encoding-2.2.0.crate"
   }
-  version: "2.1.0"
+  version: "2.2.0"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2020
+    year: 2022
     month: 12
-    day: 15
+    day: 13
   }
 }
diff --git a/lib.rs b/src/lib.rs
similarity index 83%
rename from lib.rs
rename to src/lib.rs
index 27eaf67..46a5d74 100644
--- a/lib.rs
+++ b/src/lib.rs
@@ -6,7 +6,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! URLs use special chacters to indicate the parts of the request.
+//! URLs use special characters to indicate the parts of the request.
 //! For example, a `?` question mark marks the end of a path and the start of a query string.
 //! In order for that character to exist inside a path, it needs to be encoded differently.
 //!
@@ -21,9 +21,9 @@
 //! The [`AsciiSet`] parameter of [`percent_encode`] and [`utf8_percent_encode`]
 //! lets callers configure this.
 //!
-//! This crate delibarately does not provide many different sets.
+//! This crate deliberately does not provide many different sets.
 //! Users should consider in what context the encoded string will be used,
-//! real relevant specifications, and define their own set.
+//! read relevant specifications, and define their own set.
 //! This is done by using the `add` method of an existing set.
 //!
 //! # Examples
@@ -37,15 +37,22 @@
 //! assert_eq!(utf8_percent_encode("foo <bar>", FRAGMENT).to_string(), "foo%20%3Cbar%3E");
 //! ```
 
-use std::borrow::Cow;
-use std::fmt;
-use std::slice;
-use std::str;
+#![no_std]
+#[cfg(feature = "alloc")]
+extern crate alloc;
+
+#[cfg(feature = "alloc")]
+use alloc::{
+    borrow::{Cow, ToOwned},
+    string::String,
+    vec::Vec,
+};
+use core::{fmt, mem, slice, str};
 
 /// Represents a set of characters or bytes in the ASCII range.
 ///
-/// This used in [`percent_encode`] and [`utf8_percent_encode`].
-/// This is simlar to [percent-encode sets](https://url.spec.whatwg.org/#percent-encoded-bytes).
+/// This is used in [`percent_encode`] and [`utf8_percent_encode`].
+/// This is similar to [percent-encode sets](https://url.spec.whatwg.org/#percent-encoded-bytes).
 ///
 /// Use the `add` method of an existing set to define a new set. For example:
 ///
@@ -63,7 +70,7 @@
 
 const ASCII_RANGE_LEN: usize = 0x80;
 
-const BITS_PER_CHUNK: usize = 8 * std::mem::size_of::<Chunk>();
+const BITS_PER_CHUNK: usize = 8 * mem::size_of::<Chunk>();
 
 impl AsciiSet {
     /// Called with UTF-8 bytes rather than code points.
@@ -109,7 +116,7 @@
     ($( $bool: expr, )+) => {
         fn _static_assert() {
             $(
-                let _ = std::mem::transmute::<[u8; $bool as usize], u8>;
+                let _ = mem::transmute::<[u8; $bool as usize], u8>;
             )+
         }
     }
@@ -252,6 +259,8 @@
                 self.bytes = remaining;
                 Some(percent_encode_byte(first_byte))
             } else {
+                // The unsafe blocks here are appropriate because the bytes are
+                // confirmed as a subset of UTF-8 in should_percent_encode.
                 for (i, &byte) in remaining.iter().enumerate() {
                     if self.ascii_set.should_percent_encode(byte) {
                         // 1 for first_byte + i for previous iterations of this loop
@@ -279,7 +288,7 @@
 }
 
 impl<'a> fmt::Display for PercentEncode<'a> {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         for c in (*self).clone() {
             formatter.write_str(c)?
         }
@@ -287,6 +296,7 @@
     }
 }
 
+#[cfg(feature = "alloc")]
 impl<'a> From<PercentEncode<'a>> for Cow<'a, str> {
     fn from(mut iter: PercentEncode<'a>) -> Self {
         match iter.next() {
@@ -310,7 +320,7 @@
 ///
 /// See [`percent_decode`] regarding the return type.
 #[inline]
-pub fn percent_decode_str(input: &str) -> PercentDecode {
+pub fn percent_decode_str(input: &str) -> PercentDecode<'_> {
     percent_decode(input.as_bytes())
 }
 
@@ -333,7 +343,7 @@
 /// assert_eq!(percent_decode(b"foo%20bar%3f").decode_utf8().unwrap(), "foo bar?");
 /// ```
 #[inline]
-pub fn percent_decode(input: &[u8]) -> PercentDecode {
+pub fn percent_decode(input: &[u8]) -> PercentDecode<'_> {
     PercentDecode {
         bytes: input.iter(),
     }
@@ -345,7 +355,7 @@
     bytes: slice::Iter<'a, u8>,
 }
 
-fn after_percent_sign(iter: &mut slice::Iter<u8>) -> Option<u8> {
+fn after_percent_sign(iter: &mut slice::Iter<'_, u8>) -> Option<u8> {
     let mut cloned_iter = iter.clone();
     let h = char::from(*cloned_iter.next()?).to_digit(16)?;
     let l = char::from(*cloned_iter.next()?).to_digit(16)?;
@@ -368,10 +378,11 @@
 
     fn size_hint(&self) -> (usize, Option<usize>) {
         let bytes = self.bytes.len();
-        (bytes / 3, Some(bytes))
+        ((bytes + 2) / 3, Some(bytes))
     }
 }
 
+#[cfg(feature = "alloc")]
 impl<'a> From<PercentDecode<'a>> for Cow<'a, [u8]> {
     fn from(iter: PercentDecode<'a>) -> Self {
         match iter.if_any() {
@@ -383,6 +394,7 @@
 
 impl<'a> PercentDecode<'a> {
     /// If the percent-decoding is different from the input, return it as a new bytes vector.
+    #[cfg(feature = "alloc")]
     fn if_any(&self) -> Option<Vec<u8>> {
         let mut bytes_iter = self.bytes.clone();
         while bytes_iter.any(|&b| b == b'%') {
@@ -402,6 +414,7 @@
     /// Decode the result of percent-decoding as UTF-8.
     ///
     /// This is return `Err` when the percent-decoded bytes are not well-formed in UTF-8.
+    #[cfg(feature = "alloc")]
     pub fn decode_utf8(self) -> Result<Cow<'a, str>, str::Utf8Error> {
         match self.clone().into() {
             Cow::Borrowed(bytes) => match str::from_utf8(bytes) {
@@ -419,24 +432,37 @@
     ///
     /// Invalid UTF-8 percent-encoded byte sequences will be replaced � U+FFFD,
     /// the replacement character.
+    #[cfg(feature = "alloc")]
     pub fn decode_utf8_lossy(self) -> Cow<'a, str> {
         decode_utf8_lossy(self.clone().into())
     }
 }
 
-fn decode_utf8_lossy(input: Cow<[u8]>) -> Cow<str> {
+#[cfg(feature = "alloc")]
+fn decode_utf8_lossy(input: Cow<'_, [u8]>) -> Cow<'_, str> {
+    // Note: This function is duplicated in `form_urlencoded/src/query_encoding.rs`.
     match input {
         Cow::Borrowed(bytes) => String::from_utf8_lossy(bytes),
         Cow::Owned(bytes) => {
-            let raw_utf8: *const [u8];
             match String::from_utf8_lossy(&bytes) {
-                Cow::Borrowed(utf8) => raw_utf8 = utf8.as_bytes(),
-                Cow::Owned(s) => return s.into(),
+                Cow::Borrowed(utf8) => {
+                    // If from_utf8_lossy returns a Cow::Borrowed, then we can
+                    // be sure our original bytes were valid UTF-8. This is because
+                    // if the bytes were invalid UTF-8 from_utf8_lossy would have
+                    // to allocate a new owned string to back the Cow so it could
+                    // replace invalid bytes with a placeholder.
+
+                    // First we do a debug_assert to confirm our description above.
+                    let raw_utf8: *const [u8] = utf8.as_bytes();
+                    debug_assert!(raw_utf8 == &*bytes as *const [u8]);
+
+                    // Given we know the original input bytes are valid UTF-8,
+                    // and we have ownership of those bytes, we re-use them and
+                    // return a Cow::Owned here.
+                    Cow::Owned(unsafe { String::from_utf8_unchecked(bytes) })
+                }
+                Cow::Owned(s) => Cow::Owned(s),
             }
-            // from_utf8_lossy returned a borrow of `bytes` unchanged.
-            debug_assert!(raw_utf8 == &*bytes as *const [u8]);
-            // Reuse the existing `Vec` allocation.
-            unsafe { String::from_utf8_unchecked(bytes) }.into()
         }
     }
 }