Import 'ident_case' crate

Request Document: go/android-rust-importing-crates
For CL Reviewers: go/android3p#cl-review
For Build Team: go/ab-third-party-imports
Bug: http://b/330678664
Test: m libident_case

Change-Id: Id219061fc44b910ee1897bf0d7b5a9df476e5af2
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..7d0b542
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+  "git": {
+    "sha1": "bf0d863e3006b40a0d923a81d7b2dd2db1136c2c"
+  }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4308d82
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+target/
+**/*.rs.bk
+Cargo.lock
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..6c60118
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,5 @@
+language: rust
+env:
+  - stable
+  - beta
+  - nightly
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..8903060
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,34 @@
+// This file is generated by cargo_embargo.
+// Do not modify this file as changes will be overridden on upgrade.
+
+// TODO: Add license.
+rust_test {
+    name: "ident_case_test_src_lib",
+    host_supported: true,
+    crate_name: "ident_case",
+    cargo_env_compat: true,
+    cargo_pkg_version: "1.0.1",
+    srcs: ["src/lib.rs"],
+    test_suites: ["general-tests"],
+    auto_gen_config: true,
+    test_options: {
+        unit_test: true,
+    },
+    edition: "2015",
+}
+
+rust_library {
+    name: "libident_case",
+    host_supported: true,
+    crate_name: "ident_case",
+    cargo_env_compat: true,
+    cargo_pkg_version: "1.0.1",
+    srcs: ["src/lib.rs"],
+    edition: "2015",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    product_available: true,
+    vendor_available: true,
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..4b89142
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,2 @@
+## v1.0.1 - March 18, 2019
+- Add `LICENSE` file (#3)[https://github.com/TedDriggs/ident_case/issues/3]
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..b5c457c
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,23 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# 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
+#
+# 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)
+
+[package]
+name = "ident_case"
+version = "1.0.1"
+authors = ["Ted Driggs <ted.driggs@outlook.com>"]
+description = "Utility for applying case rules to Rust identifiers."
+documentation = "https://docs.rs/ident_case/1.0.1"
+readme = "README.md"
+license = "MIT/Apache-2.0"
+repository = "https://github.com/TedDriggs/ident_case"
+[badges.travis-ci]
+repository = "TedDriggs/ident_case"
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..9cf1062
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..9f7434e
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,19 @@
+name: "ident_case"
+description: "Utility for applying case rules to Rust identifiers."
+third_party {
+  identifier {
+    type: "crates.io"
+    value: "https://crates.io/crates/ident_case"
+  }
+  identifier {
+    type: "Archive"
+    value: "https://static.crates.io/crates/ident_case/ident_case-1.0.1.crate"
+  }
+  version: "1.0.1"
+  license_type: NOTICE
+  last_upgrade_date {
+    year: 2024
+    month: 4
+    day: 9
+  }
+}
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..48bea6e
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 688011
+include platform/prebuilts/rust:main:/OWNERS
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..395f88a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+[![Build Status](https://travis-ci.org/TedDriggs/ident_case.svg?branch=master)](https://travis-ci.org/TedDriggs/ident_case)
+
+Crate for manipulating case of identifiers in Rust programs.
+
+# Features
+* Supports `snake_case`, `lowercase`, `camelCase`, 
+  `PascalCase`, `SCREAMING_SNAKE_CASE`, and `kebab-case`
+* Rename variants, and fields
+
+# Examples
+```rust
+assert_eq!("helloWorld", RenameRule::CamelCase.apply_to_field("hello_world"));
+
+assert_eq!("i_love_serde", RenameRule::SnakeCase.apply_to_variant("ILoveSerde"));
+```
\ No newline at end of file
diff --git a/cargo.metadata b/cargo.metadata
new file mode 100644
index 0000000..66ce839
--- /dev/null
+++ b/cargo.metadata
@@ -0,0 +1 @@
+{"packages":[{"name":"ident_case","version":"1.0.1","id":"ident_case 1.0.1 (path+file:///usr/local/google/home/mgeisler/src/aosp/external/rust/crates/ident_case-1.0.1)","license":"MIT/Apache-2.0","license_file":null,"description":"Utility for applying case rules to Rust identifiers.","source":null,"dependencies":[],"targets":[{"kind":["lib"],"crate_types":["lib"],"name":"ident_case","src_path":"/usr/local/google/home/mgeisler/src/aosp/external/rust/crates/ident_case-1.0.1/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true}],"features":{},"manifest_path":"/usr/local/google/home/mgeisler/src/aosp/external/rust/crates/ident_case-1.0.1/Cargo.toml","metadata":null,"publish":null,"authors":["Ted Driggs <ted.driggs@outlook.com>"],"categories":[],"keywords":[],"readme":"README.md","repository":"https://github.com/TedDriggs/ident_case","homepage":null,"documentation":"https://docs.rs/ident_case/1.0.1","edition":"2015","links":null,"default_run":null,"rust_version":null}],"workspace_members":["ident_case 1.0.1 (path+file:///usr/local/google/home/mgeisler/src/aosp/external/rust/crates/ident_case-1.0.1)"],"workspace_default_members":["ident_case 1.0.1 (path+file:///usr/local/google/home/mgeisler/src/aosp/external/rust/crates/ident_case-1.0.1)"],"resolve":{"nodes":[{"id":"ident_case 1.0.1 (path+file:///usr/local/google/home/mgeisler/src/aosp/external/rust/crates/ident_case-1.0.1)","dependencies":[],"deps":[],"features":[]}],"root":"ident_case 1.0.1 (path+file:///usr/local/google/home/mgeisler/src/aosp/external/rust/crates/ident_case-1.0.1)"},"target_directory":"/usr/local/google/home/mgeisler/src/aosp/external/rust/crates/ident_case-1.0.1/target","version":1,"workspace_root":"/usr/local/google/home/mgeisler/src/aosp/external/rust/crates/ident_case-1.0.1","metadata":null}
diff --git a/cargo_embargo.json b/cargo_embargo.json
new file mode 100644
index 0000000..c8842d1
--- /dev/null
+++ b/cargo_embargo.json
@@ -0,0 +1,4 @@
+{
+  "run_cargo": false,
+  "tests": true
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..d54d654
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,168 @@
+//! Crate for changing case of Rust identifiers.
+//!
+//! # Features
+//! * Supports `snake_case`, `lowercase`, `camelCase`, 
+//!   `PascalCase`, `SCREAMING_SNAKE_CASE`, and `kebab-case`
+//! * Rename variants, and fields
+//! 
+//! # Examples
+//! ```rust
+//! use ident_case::RenameRule;
+//!
+//! assert_eq!("helloWorld", RenameRule::CamelCase.apply_to_field("hello_world"));
+//!
+//! assert_eq!("i_love_serde", RenameRule::SnakeCase.apply_to_variant("ILoveSerde"));
+//! ```
+
+// Copyright 2017 Serde Developers
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::ascii::AsciiExt;
+use std::str::FromStr;
+
+use self::RenameRule::*;
+
+/// A casing rule for renaming Rust identifiers.
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub enum RenameRule {
+    /// No-op rename rule.
+    None,
+    /// Rename direct children to "lowercase" style.
+    LowerCase,
+    /// Rename direct children to "PascalCase" style, as typically used for enum variants.
+    PascalCase,
+    /// Rename direct children to "camelCase" style.
+    CamelCase,
+    /// Rename direct children to "snake_case" style, as commonly used for fields.
+    SnakeCase,
+    /// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly used for constants.
+    ScreamingSnakeCase,
+    /// Rename direct children to "kebab-case" style.
+    KebabCase,
+}
+
+impl RenameRule {
+    /// Change case of a `PascalCase` variant.
+    pub fn apply_to_variant<S: AsRef<str>>(&self, variant: S) -> String {
+        
+        let variant = variant.as_ref();
+        match *self {
+            None | PascalCase => variant.to_owned(),
+            LowerCase => variant.to_ascii_lowercase(),
+            CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
+            SnakeCase => {
+                let mut snake = String::new();
+                for (i, ch) in variant.char_indices() {
+                    if i > 0 && ch.is_uppercase() {
+                        snake.push('_');
+                    }
+                    snake.push(ch.to_ascii_lowercase());
+                }
+                snake
+            }
+            ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
+            KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
+        }
+    }
+
+    /// Change case of a `snake_case` field.
+    pub fn apply_to_field<S: AsRef<str>>(&self, field: S) -> String {
+        
+        let field = field.as_ref();
+        match *self {
+            None | LowerCase | SnakeCase => field.to_owned(),
+            PascalCase => {
+                let mut pascal = String::new();
+                let mut capitalize = true;
+                for ch in field.chars() {
+                    if ch == '_' {
+                        capitalize = true;
+                    } else if capitalize {
+                        pascal.push(ch.to_ascii_uppercase());
+                        capitalize = false;
+                    } else {
+                        pascal.push(ch);
+                    }
+                }
+                pascal
+            }
+            CamelCase => {
+                let pascal = PascalCase.apply_to_field(field);
+                pascal[..1].to_ascii_lowercase() + &pascal[1..]
+            }
+            ScreamingSnakeCase => field.to_ascii_uppercase(),
+            KebabCase => field.replace('_', "-"),
+        }
+    }
+}
+
+impl FromStr for RenameRule {
+    type Err = ();
+
+    fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
+        match rename_all_str {
+            "lowercase" => Ok(LowerCase),
+            "PascalCase" => Ok(PascalCase),
+            "camelCase" => Ok(CamelCase),
+            "snake_case" => Ok(SnakeCase),
+            "SCREAMING_SNAKE_CASE" => Ok(ScreamingSnakeCase),
+            "kebab-case" => Ok(KebabCase),
+            _ => Err(()),
+        }
+    }
+}
+
+impl Default for RenameRule {
+    fn default() -> Self {
+        RenameRule::None
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::RenameRule::*;
+
+    #[test]
+    fn rename_variants() {
+        for &(original, lower, camel, snake, screaming, kebab) in
+            &[
+                ("Outcome", "outcome", "outcome", "outcome", "OUTCOME", "outcome"),
+                ("VeryTasty", "verytasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty"),
+                ("A", "a", "a", "a", "A", "a"),
+                ("Z42", "z42", "z42", "z42", "Z42", "z42"),
+            ] {
+            assert_eq!(None.apply_to_variant(original), original);
+            assert_eq!(LowerCase.apply_to_variant(original), lower);
+            assert_eq!(PascalCase.apply_to_variant(original), original);
+            assert_eq!(CamelCase.apply_to_variant(original), camel);
+            assert_eq!(SnakeCase.apply_to_variant(original), snake);
+            assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
+            assert_eq!(KebabCase.apply_to_variant(original), kebab);
+        }
+    }
+
+    #[test]
+    fn rename_fields() {
+        for &(original, pascal, camel, screaming, kebab) in
+            &[
+                ("outcome", "Outcome", "outcome", "OUTCOME", "outcome"),
+                ("very_tasty", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty"),
+                ("_leading_under", "LeadingUnder", "leadingUnder", "_LEADING_UNDER", "-leading-under"),
+                ("double__under", "DoubleUnder", "doubleUnder", "DOUBLE__UNDER", "double--under"),
+                ("a", "A", "a", "A", "a"),
+                ("z42", "Z42", "z42", "Z42", "z42"),
+            ] {
+            assert_eq!(None.apply_to_field(original), original);
+            assert_eq!(PascalCase.apply_to_field(original), pascal);
+            assert_eq!(CamelCase.apply_to_field(original), camel);
+            assert_eq!(SnakeCase.apply_to_field(original), original);
+            assert_eq!(ScreamingSnakeCase.apply_to_field(original), screaming);
+            assert_eq!(KebabCase.apply_to_field(original), kebab);
+        }
+    }
+}
\ No newline at end of file