Snap for 10453563 from d608568a4d220cc73ce87193ba5b6b7afd22bbdb to mainline-permission-release

Change-Id: Ib4c35d91c01e6f661876c9c8e5ff550216463387
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 0eb4358..b891109 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "837538c549f3458f157ee154ae76e3e2b9e27118"
-  }
-}
+    "sha1": "359bc90a4f07224f79cc79c45dc873d44bcd6f14"
+  },
+  "path_in_vcs": "idna"
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 1838279..c80099f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -42,11 +42,10 @@
     host_supported: true,
     crate_name: "idna",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.2.3",
+    cargo_pkg_version: "0.3.0",
     srcs: ["src/lib.rs"],
     edition: "2018",
     rustlibs: [
-        "libmatches",
         "libunicode_bidi",
         "libunicode_normalization",
     ],
@@ -54,5 +53,7 @@
         "//apex_available:platform",
         "com.android.resolv",
     ],
+    product_available: true,
+    vendor_available: true,
     min_sdk_version: "29",
 }
diff --git a/Cargo.toml b/Cargo.toml
index 138a271..fa2ed42 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,21 +3,21 @@
 # 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 = "idna"
-version = "0.2.3"
+version = "0.3.0"
 authors = ["The rust-url developers"]
 autotests = false
 description = "IDNA (Internationalizing Domain Names in Applications) and Punycode."
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
 repository = "https://github.com/servo/rust-url/"
 
 [lib]
@@ -33,22 +33,21 @@
 [[bench]]
 name = "all"
 harness = false
-[dependencies.matches]
-version = "0.1"
 
 [dependencies.unicode-bidi]
 version = "0.3"
 
 [dependencies.unicode-normalization]
 version = "0.1.17"
+
 [dev-dependencies.assert_matches]
 version = "1.3"
 
 [dev-dependencies.bencher]
 version = "0.1"
 
-[dev-dependencies.rustc-test]
-version = "0.3"
-
 [dev-dependencies.serde_json]
 version = "1.0"
+
+[dev-dependencies.tester]
+version = "0.9"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 6b3750b..942f122 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,12 +1,13 @@
 [package]
 name = "idna"
-version = "0.2.3"
+version = "0.3.0"
 authors = ["The rust-url developers"]
 description = "IDNA (Internationalizing Domain Names in Applications) and Punycode."
 repository = "https://github.com/servo/rust-url/"
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
 autotests = false
 edition = "2018"
+rust-version = "1.51"
 
 [lib]
 doctest = false
@@ -21,13 +22,12 @@
 [dev-dependencies]
 assert_matches = "1.3"
 bencher = "0.1"
-rustc-test = "0.3"
+tester = "0.9"
 serde_json = "1.0"
 
 [dependencies]
 unicode-bidi = "0.3"
 unicode-normalization = "0.1.17"
-matches = "0.1"
 
 [[bench]]
 name = "all"
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 265ca62..bb93743 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/idna
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "idna"
 description: "IDNA (Internationalizing Domain Names in Applications) and Punycode."
 third_party {
@@ -7,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/idna/idna-0.2.3.crate"
+    value: "https://static.crates.io/crates/idna/idna-0.3.0.crate"
   }
-  version: "0.2.3"
+  version: "0.3.0"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 5
-    day: 19
+    year: 2022
+    month: 12
+    day: 12
   }
 }
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 407ec5c..b2d8ebc 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -6,16 +6,9 @@
     },
     {
       "path": "external/rust/crates/url"
-    }
-  ],
-  "presubmit": [
+    },
     {
-      "name": "doh_unit_test"
-    }
-  ],
-  "presubmit-rust": [
-    {
-      "name": "doh_unit_test"
+      "path": "packages/modules/DnsResolver"
     }
   ]
 }
diff --git a/src/lib.rs b/src/lib.rs
index b87d4a1..37d6387 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -32,8 +32,9 @@
 //! > that minimizes the impact of this transition for client software,
 //! > allowing client software to access domains that are valid under either system.
 
+#[cfg(test)]
 #[macro_use]
-extern crate matches;
+extern crate assert_matches;
 
 pub mod punycode;
 mod uts46;
diff --git a/src/uts46.rs b/src/uts46.rs
index ad79805..ec2fd0b 100644
--- a/src/uts46.rs
+++ b/src/uts46.rs
@@ -156,7 +156,7 @@
         // LTR label
         BidiClass::L => {
             // Rule 5
-            while let Some(c) = chars.next() {
+            for c in chars.by_ref() {
                 if !matches!(
                     bidi_class(c),
                     BidiClass::L
@@ -318,51 +318,48 @@
     // V8: Bidi rules are checked inside `processing()`
 }
 
-/// http://www.unicode.org/reports/tr46/#Processing
-#[allow(clippy::manual_strip)] // introduced in 1.45, MSRV is 1.36
-fn processing(
-    domain: &str,
-    config: Config,
-    normalized: &mut String,
-    output: &mut String,
-) -> Errors {
-    // Weed out the simple cases: only allow all lowercase ASCII characters and digits where none
-    // of the labels start with PUNYCODE_PREFIX and labels don't start or end with hyphen.
-    let (mut prev, mut simple, mut puny_prefix) = ('?', !domain.is_empty(), 0);
+// Detect simple cases: all lowercase ASCII characters and digits where none
+// of the labels start with PUNYCODE_PREFIX and labels don't start or end with hyphen.
+fn is_simple(domain: &str) -> bool {
+    if domain.is_empty() {
+        return false;
+    }
+    let (mut prev, mut puny_prefix) = ('?', 0);
     for c in domain.chars() {
         if c == '.' {
             if prev == '-' {
-                simple = false;
-                break;
+                return false;
             }
             puny_prefix = 0;
             continue;
         } else if puny_prefix == 0 && c == '-' {
-            simple = false;
-            break;
+            return false;
         } else if puny_prefix < 5 {
             if c == ['x', 'n', '-', '-'][puny_prefix] {
                 puny_prefix += 1;
                 if puny_prefix == 4 {
-                    simple = false;
-                    break;
+                    return false;
                 }
             } else {
                 puny_prefix = 5;
             }
         }
         if !c.is_ascii_lowercase() && !c.is_ascii_digit() {
-            simple = false;
-            break;
+            return false;
         }
         prev = c;
     }
 
-    if simple {
-        output.push_str(domain);
-        return Errors::default();
-    }
+    true
+}
 
+/// http://www.unicode.org/reports/tr46/#Processing
+fn processing(
+    domain: &str,
+    config: Config,
+    normalized: &mut String,
+    output: &mut String,
+) -> Errors {
     normalized.clear();
     let mut errors = Errors::default();
     let offset = output.len();
@@ -384,8 +381,8 @@
             output.push('.');
         }
         first = false;
-        if label.starts_with(PUNYCODE_PREFIX) {
-            match decoder.decode(&label[PUNYCODE_PREFIX.len()..]) {
+        if let Some(remainder) = label.strip_prefix(PUNYCODE_PREFIX) {
+            match decoder.decode(remainder) {
                 Ok(decode) => {
                     let start = output.len();
                     output.extend(decode);
@@ -396,7 +393,7 @@
                     }
 
                     if !errors.is_err() {
-                        if !is_nfc(&decoded_label) {
+                        if !is_nfc(decoded_label) {
                             errors.nfc = true;
                         } else {
                             check_validity(decoded_label, non_transitional, &mut errors);
@@ -448,11 +445,13 @@
         }
     }
 
-    /// http://www.unicode.org/reports/tr46/#ToASCII
-    #[allow(clippy::wrong_self_convention)]
-    pub fn to_ascii<'a>(&'a mut self, domain: &str, out: &mut String) -> Result<(), Errors> {
-        let mut errors = processing(domain, self.config, &mut self.normalized, &mut self.output);
-
+    pub fn to_ascii_inner(&mut self, domain: &str, out: &mut String) -> Errors {
+        if is_simple(domain) {
+            out.push_str(domain);
+            return Errors::default();
+        }
+        let mut errors = processing(domain, self.config, &mut self.normalized, out);
+        self.output = std::mem::replace(out, String::with_capacity(out.len()));
         let mut first = true;
         for label in self.output.split('.') {
             if !first {
@@ -471,6 +470,13 @@
                 }
             }
         }
+        errors
+    }
+
+    /// http://www.unicode.org/reports/tr46/#ToASCII
+    #[allow(clippy::wrong_self_convention)]
+    pub fn to_ascii<'a>(&'a mut self, domain: &str, out: &mut String) -> Result<(), Errors> {
+        let mut errors = self.to_ascii_inner(domain, out);
 
         if self.config.verify_dns_length {
             let domain = if out.ends_with('.') {
@@ -492,6 +498,10 @@
     /// http://www.unicode.org/reports/tr46/#ToUnicode
     #[allow(clippy::wrong_self_convention)]
     pub fn to_unicode<'a>(&'a mut self, domain: &str, out: &mut String) -> Result<(), Errors> {
+        if is_simple(domain) {
+            out.push_str(domain);
+            return Errors::default().into();
+        }
         processing(domain, self.config, &mut self.normalized, out).into()
     }
 }
@@ -555,7 +565,7 @@
 
     /// http://www.unicode.org/reports/tr46/#ToASCII
     pub fn to_ascii(self, domain: &str) -> Result<String, Errors> {
-        let mut result = String::new();
+        let mut result = String::with_capacity(domain.len());
         let mut codec = Idna::new(self);
         codec.to_ascii(domain, &mut result).map(|()| result)
     }
diff --git a/tests/punycode.rs b/tests/punycode.rs
index c0123c6..1a51cbc 100644
--- a/tests/punycode.rs
+++ b/tests/punycode.rs
@@ -63,9 +63,9 @@
                         };
                         add_test(
                             test_name,
-                            TestFn::dyn_test_fn(move || {
+                            TestFn::DynTestFn(Box::new(move || {
                                 one_test(get_string(&o, "decoded"), get_string(&o, "encoded"))
-                            }),
+                            })),
                         )
                     }
                     _ => panic!(),
diff --git a/tests/tests.rs b/tests/tests.rs
index 5f0f8cd..0704c81 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -1,4 +1,4 @@
-use rustc_test as test;
+use tester as test;
 
 mod punycode;
 mod uts46;
@@ -8,12 +8,18 @@
     {
         let mut add_test = |name, run| {
             tests.push(test::TestDescAndFn {
-                desc: test::TestDesc::new(test::DynTestName(name)),
+                desc: test::TestDesc {
+                    name: test::DynTestName(name),
+                    ignore: false,
+                    should_panic: test::ShouldPanic::No,
+                    allow_fail: false,
+                    test_type: test::TestType::Unknown,
+                },
                 testfn: run,
             })
         };
         punycode::collect_tests(&mut add_test);
         uts46::collect_tests(&mut add_test);
     }
-    test::test_main(&std::env::args().collect::<Vec<_>>(), tests)
+    test::test_main(&std::env::args().collect::<Vec<_>>(), tests, None)
 }
diff --git a/tests/uts46.rs b/tests/uts46.rs
index 72b5bce..bd402ce 100644
--- a/tests/uts46.rs
+++ b/tests/uts46.rs
@@ -8,6 +8,7 @@
 
 use crate::test::TestFn;
 use std::char;
+use std::fmt::Write;
 
 use idna::Errors;
 
@@ -25,10 +26,10 @@
         };
 
         let mut pieces = line.split(';').map(|x| x.trim()).collect::<Vec<&str>>();
-        let source = unescape(&pieces.remove(0));
+        let source = unescape(pieces.remove(0));
 
         // ToUnicode
-        let mut to_unicode = unescape(&pieces.remove(0));
+        let mut to_unicode = unescape(pieces.remove(0));
         if to_unicode.is_empty() {
             to_unicode = source.clone();
         }
@@ -65,7 +66,7 @@
         let test_name = format!("UTS #46 line {}", i + 1);
         add_test(
             test_name,
-            TestFn::dyn_test_fn(move || {
+            TestFn::DynTestFn(Box::new(move || {
                 let config = idna::Config::default()
                     .use_std3_ascii_rules(true)
                     .verify_dns_length(true)
@@ -109,7 +110,7 @@
                     to_ascii_t_result,
                     |e| e.starts_with('C') || e == "V2",
                 );
-            }),
+            })),
         )
     }
 }
@@ -160,8 +161,8 @@
                             match char::from_u32(((c1 * 16 + c2) * 16 + c3) * 16 + c4) {
                                 Some(c) => output.push(c),
                                 None => {
-                                    output
-                                        .push_str(&format!("\\u{:X}{:X}{:X}{:X}", c1, c2, c3, c4));
+                                    write!(&mut output, "\\u{:X}{:X}{:X}{:X}", c1, c2, c3, c4)
+                                        .expect("Could not write to output");
                                 }
                             };
                         }