summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurice Lam <yukl@google.com>2023-02-14 20:00:52 +0000
committerMaurice Lam <yukl@google.com>2023-02-14 20:05:04 +0000
commit548a0c8be03c50e4ed569f05a6d9082a448a678b (patch)
tree9c8ddf1676d5e8bde86fa4b5bf4ad06aa857bdb1
parent8c0ab8ecf605f4d3b47d7dc33e6a5dce31f2308a (diff)
downloadinflector-548a0c8be03c50e4ed569f05a6d9082a448a678b.tar.gz
Import inflector crate
Bug: 267375624 Test: None, no build files added yet Change-Id: I8fc770f1522a5ac650e1364ae8d8bb60a60cd569
-rw-r--r--.cargo_vcs_info.json5
-rw-r--r--Cargo.toml42
-rw-r--r--Cargo.toml.orig34
l---------LICENSE1
-rw-r--r--LICENSE.md22
-rw-r--r--METADATA19
-rw-r--r--MODULE_LICENSE_BSD_LIKE0
-rw-r--r--OWNERS1
-rw-r--r--README.android13
-rw-r--r--README.md136
-rw-r--r--src/cases/camelcase/mod.rs370
-rw-r--r--src/cases/case/mod.rs303
-rw-r--r--src/cases/classcase/mod.rs393
-rw-r--r--src/cases/kebabcase/mod.rs262
-rw-r--r--src/cases/mod.rs52
-rw-r--r--src/cases/pascalcase/mod.rs360
-rw-r--r--src/cases/screamingsnakecase/mod.rs253
-rw-r--r--src/cases/sentencecase/mod.rs313
-rw-r--r--src/cases/snakecase/mod.rs334
-rw-r--r--src/cases/tablecase/mod.rs271
-rw-r--r--src/cases/titlecase/mod.rs308
-rw-r--r--src/cases/traincase/mod.rs320
-rw-r--r--src/lib.rs332
-rw-r--r--src/numbers/deordinalize/mod.rs117
-rw-r--r--src/numbers/mod.rs9
-rw-r--r--src/numbers/ordinalize/mod.rs147
-rw-r--r--src/string/constants/mod.rs225
-rw-r--r--src/string/deconstantize/mod.rs50
-rw-r--r--src/string/demodulize/mod.rs46
-rw-r--r--src/string/mod.rs23
-rw-r--r--src/string/pluralize/mod.rs194
-rw-r--r--src/string/singularize/mod.rs189
-rw-r--r--src/suffix/foreignkey/mod.rs139
-rw-r--r--src/suffix/mod.rs5
-rw-r--r--tests/lib.rs162
35 files changed, 5450 insertions, 0 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..e73255e
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+ "git": {
+ "sha1": "a4a95eac75043f4bffb127c7c8ec886b5b106053"
+ }
+}
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..553f00f
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,42 @@
+# 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 = "Inflector"
+version = "0.11.4"
+authors = ["Josh Teeter<joshteeter@gmail.com>"]
+include = ["**/*.rs", "Cargo.toml", "README.md"]
+description = "Adds String based inflections for Rust. Snake, kebab, camel, sentence, class, title and table cases as well as ordinalize, deordinalize, demodulize, foreign key, and pluralize/singularize are supported as both traits and pure functions acting on String types.\n"
+homepage = "https://github.com/whatisinternet/inflector"
+documentation = "https://docs.rs/Inflector"
+readme = "README.md"
+keywords = ["pluralize", "Inflector", "camel", "snake", "inflection"]
+categories = ["text-processing", "value-formatting"]
+license = "BSD-2-Clause"
+repository = "https://github.com/whatisinternet/inflector"
+
+[lib]
+name = "inflector"
+[dependencies.lazy_static]
+version = "1.2.0"
+optional = true
+
+[dependencies.regex]
+version = "1.1"
+optional = true
+
+[features]
+default = ["heavyweight"]
+heavyweight = ["regex", "lazy_static"]
+unstable = []
+[badges.travis-ci]
+repository = "whatisinternet/Inflector"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..9458157
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,34 @@
+[package]
+name = "Inflector"
+version = "0.11.4"
+authors = ["Josh Teeter<joshteeter@gmail.com>"]
+include = [
+ "**/*.rs",
+ "Cargo.toml",
+ "README.md"
+]
+readme = "README.md"
+repository = "https://github.com/whatisinternet/inflector"
+documentation = "https://docs.rs/Inflector"
+homepage = "https://github.com/whatisinternet/inflector"
+license="BSD-2-Clause"
+description = """
+Adds String based inflections for Rust. Snake, kebab, camel, sentence, class, title and table cases as well as ordinalize, deordinalize, demodulize, foreign key, and pluralize/singularize are supported as both traits and pure functions acting on String types.
+"""
+keywords = ["pluralize", "Inflector", "camel", "snake", "inflection"]
+categories = ["text-processing", "value-formatting"]
+
+[badges]
+travis-ci = { repository = "whatisinternet/Inflector" }
+
+[features]
+default = ['heavyweight']
+unstable = []
+heavyweight = ['regex', 'lazy_static']
+
+[lib]
+name = "inflector"
+
+[dependencies]
+regex = {version = "1.1", optional = true}
+lazy_static = {version = "1.2.0", optional = true}
diff --git a/LICENSE b/LICENSE
new file mode 120000
index 0000000..f0c4298
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1 @@
+LICENSE.md \ No newline at end of file
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..937b1bd
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,22 @@
+Copyright 2017 Josh Teeter
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..9cf6c81
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,19 @@
+name: "Inflector"
+description: "Adds String based inflections for Rust. Snake, kebab, camel, sentence, class, title and table cases as well as ordinalize, deordinalize, demodulize, foreign key, and pluralize/singularize are supported as both traits and pure functions acting on String types."
+third_party {
+ url {
+ type: HOMEPAGE
+ value: "https://crates.io/crates/Inflector"
+ }
+ url {
+ type: ARCHIVE
+ value: "https://static.crates.io/crates/Inflector/Inflector-0.11.4.crate"
+ }
+ version: "0.11.4"
+ license_type: NOTICE
+ last_upgrade_date {
+ year: 2023
+ month: 2
+ day: 14
+ }
+}
diff --git a/MODULE_LICENSE_BSD_LIKE b/MODULE_LICENSE_BSD_LIKE
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_BSD_LIKE
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..45dc4dd
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1 @@
+include platform/prebuilts/rust:master:/OWNERS
diff --git a/README.android b/README.android
new file mode 100644
index 0000000..366abc2
--- /dev/null
+++ b/README.android
@@ -0,0 +1,13 @@
+Steps taken to download this crate:
+
+1. `get_rust_pkg.py -add3prf Inflector`. This results in an error about missing license.
+
+ ```
+ FileNotFoundError: No license file has been found.
+ ```
+
+2. Because LICENSE.md is not uploaded to the sources for crates.io, we download it from the
+ corresponding GitHub repository: `cd Inflector-VERSION && wget https://raw.githubusercontent.com/whatisinternet/Inflector/master/LICENSE.md`
+3. Run `add3prf.py`
+4. Continue with the import review process.
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..db8de09
--- /dev/null
+++ b/README.md
@@ -0,0 +1,136 @@
+# Rust Inflector
+
+
+[![Build Status](https://travis-ci.org/whatisinternet/Inflector.svg?branch=master)](https://travis-ci.org/whatisinternet/Inflector) [![Crates.io](https://img.shields.io/crates/v/Inflector.svg)](https://crates.io/crates/inflector)[![Crate downloads](https://img.shields.io/crates/d/Inflector.svg)](https://crates.io/crates/inflector)
+
+
+Adds String based inflections for Rust. Snake, kebab, train, camel,
+sentence, class, and title cases as well as ordinalize,
+deordinalize, demodulize, deconstantize, foreign key, table case, and pluralize/singularize are supported as both traits and pure functions
+acting on &str and String types.
+
+-----
+## Documentation:
+
+Documentation can be found here at the README or via rust docs below.
+
+[Rust docs with examples](https://docs.rs/Inflector)
+
+-----
+
+## Installation:
+
+### As a [crate](http://crates.io)
+
+```toml
+[dependencies]
+Inflector = "*"
+```
+
+### Compile yourself:
+
+1. Install [Rust and cargo](http://doc.crates.io/)
+2. git clone https://github.com/whatisinternet/Inflector
+3. Library: cd inflector && cargo build --release --lib
+4. You can find the library in target/release
+
+## Usage / Example:
+
+```rust
+...
+// to use methods like String.to_lower_case();
+extern crate inflector;
+use inflector::Inflector;
+...
+fn main() {
+...
+ let camel_case_string: String = "some_string".to_camel_case();
+...
+}
+
+```
+
+Or
+
+```rust
+...
+// to use methods like to_snake_case(&str);
+extern crate inflector;
+
+// use inflector::cases::classcase::to_class_case;
+// use inflector::cases::classcase::is_class_case;
+
+// use inflector::cases::camelcase::to_camel_case;
+// use inflector::cases::camelcase::is_camel_case;
+
+// use inflector::cases::pascalcase::to_pascal_case;
+// use inflector::cases::pascalcase::is_pascal_case;
+
+// use inflector::cases::screamingsnakecase::to_screamingsnake_case;
+// use inflector::cases::screamingsnakecase::is_screamingsnake_case;
+
+// use inflector::cases::snakecase::to_snake_case;
+// use inflector::cases::snakecase::is_snake_case;
+
+// use inflector::cases::kebabcase::to_kebab_case;
+// use inflector::cases::kebabcase::is_kebab_case;
+
+// use inflector::cases::traincase::to_train_case;
+// use inflector::cases::traincase::is_train_case;
+
+// use inflector::cases::sentencecase::to_sentence_case;
+// use inflector::cases::sentencecase::is_sentence_case;
+
+// use inflector::cases::titlecase::to_title_case;
+// use inflector::cases::titlecase::is_title_case;
+
+// use inflector::cases::tablecase::to_table_case;
+// use inflector::cases::tablecase::is_table_case;
+
+// use inflector::numbers::ordinalize::ordinalize;
+// use inflector::numbers::deordinalize::deordinalize;
+
+// use inflector::suffix::foreignkey::to_foreign_key;
+// use inflector::suffix::foreignkey::is_foreign_key;
+
+// use inflector::string::demodulize::demodulize;
+// use inflector::string::deconstantize::deconstantize;
+
+// use inflector::string::pluralize::to_plural;
+// use inflector::string::singularize::to_singular;
+...
+fn main() {
+...
+ let camel_case_string: String = to_camel_case("some_string");
+...
+}
+
+```
+
+## Advanced installation and usage:
+
+If the project doesn't require singularize, pluralize, class, table, demodulize,
+deconstantize. Then in your `cargo.toml` you may wish to specify:
+
+```toml
+[dependencies.Inflector]
+version = "*"
+default-features = false
+```
+
+Or
+
+```toml
+Inflector = {version="*", default-features=false}
+
+```
+
+To test this crate locally with features off try:
+
+```shell
+cargo test --no-default-features
+```
+
+## [Contributing](CONTRIBUTING.md)
+
+This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
diff --git a/src/cases/camelcase/mod.rs b/src/cases/camelcase/mod.rs
new file mode 100644
index 0000000..b09ddc6
--- /dev/null
+++ b/src/cases/camelcase/mod.rs
@@ -0,0 +1,370 @@
+#![deny(warnings)]
+use cases::case::*;
+
+/// Converts a `&str` to camelCase `String`
+///
+/// ```
+/// use inflector::cases::camelcase::to_camel_case;
+/// let mock_string: &str = "fooBar";
+/// let expected_string: String = "fooBar".to_string();
+/// let asserted_string: String = to_camel_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::to_camel_case;
+/// let mock_string: &str = "FOO_BAR";
+/// let expected_string: String = "fooBar".to_string();
+/// let asserted_string: String = to_camel_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::to_camel_case;
+/// let mock_string: &str = "Foo Bar";
+/// let expected_string: String = "fooBar".to_string();
+/// let asserted_string: String = to_camel_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::to_camel_case;
+/// let mock_string: &str = "foo_bar";
+/// let expected_string: String = "fooBar".to_string();
+/// let asserted_string: String = to_camel_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::to_camel_case;
+/// let mock_string: &str = "Foo bar";
+/// let expected_string: String = "fooBar".to_string();
+/// let asserted_string: String = to_camel_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::to_camel_case;
+/// let mock_string: &str = "foo-bar";
+/// let expected_string: String = "fooBar".to_string();
+/// let asserted_string: String = to_camel_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::to_camel_case;
+/// let mock_string: &str = "FooBar";
+/// let expected_string: String = "fooBar".to_string();
+/// let asserted_string: String = to_camel_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::to_camel_case;
+/// let mock_string: &str = "FooBar3";
+/// let expected_string: String = "fooBar3".to_string();
+/// let asserted_string: String = to_camel_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::to_camel_case;
+/// let mock_string: &str = "Foo-Bar";
+/// let expected_string: String = "fooBar".to_string();
+/// let asserted_string: String = to_camel_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_camel_case(non_camelized_string: &str) -> String {
+ let options = CamelOptions {
+ new_word: false,
+ last_char: ' ',
+ first_word: false,
+ injectable_char: ' ',
+ has_seperator: false,
+ inverted: false,
+ };
+ to_case_camel_like(&non_camelized_string, options)
+}
+
+/// Determines if a `&str` is camelCase bool``
+///
+/// ```
+/// use inflector::cases::camelcase::is_camel_case;
+/// let mock_string: &str = "Foo";
+/// let asserted_bool: bool = is_camel_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::is_camel_case;
+/// let mock_string: &str = "foo";
+/// let asserted_bool: bool = is_camel_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::is_camel_case;
+/// let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+/// let asserted_bool: bool = is_camel_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::is_camel_case;
+/// let mock_string: &str = "FooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_camel_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::is_camel_case;
+/// let mock_string: &str = "fooBarIsAReallyReally3LongString";
+/// let asserted_bool: bool = is_camel_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::is_camel_case;
+/// let mock_string: &str = "fooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_camel_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::is_camel_case;
+/// let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+/// let asserted_bool: bool = is_camel_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::is_camel_case;
+/// let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+/// let asserted_bool: bool = is_camel_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::is_camel_case;
+/// let mock_string: &str = "Foo bar string that is really really long";
+/// let asserted_bool: bool = is_camel_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::camelcase::is_camel_case;
+/// let mock_string: &str = "Foo Bar Is A Really Really Long String";
+/// let asserted_bool: bool = is_camel_case(mock_string);
+/// assert!(asserted_bool == false);
+/// ```
+pub fn is_camel_case(test_string: &str) -> bool {
+ to_camel_case(&test_string.clone()) == test_string
+}
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+ extern crate test;
+ use self::test::Bencher;
+
+ #[bench]
+ fn bench_camel0(b: &mut Bencher) {
+ b.iter(|| {
+ let test_string = "Foo bar";
+ super::to_camel_case(test_string)
+ });
+ }
+
+ #[bench]
+ fn bench_camel1(b: &mut Bencher) {
+ b.iter(|| {
+ let test_string = "foo_bar";
+ super::to_camel_case(test_string)
+ });
+ }
+
+ #[bench]
+ fn bench_camel2(b: &mut Bencher) {
+ b.iter(|| {
+ let test_string = "fooBar";
+ super::to_camel_case(test_string)
+ });
+ }
+
+ #[bench]
+ fn bench_is_camel(b: &mut Bencher) {
+ b.iter(|| {
+ let test_string: &str = "Foo bar";
+ super::is_camel_case(test_string)
+ });
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use ::to_camel_case;
+ use ::is_camel_case;
+
+ #[test]
+ fn from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ let expected: String = "fooBar".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ let expected: String = "fooBar".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ let expected: String = "fooBar".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ let expected: String = "fooBar".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ let expected: String = "fooBar".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ let expected: String = "fooBar".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ let expected: String = "fooBar".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ let expected: String = "fooBar".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_case_with_loads_of_space() {
+ let convertable_string: String = "foo bar".to_owned();
+ let expected: String = "fooBar".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn a_name_with_a_dot() {
+ let convertable_string: String = "Robert C. Martin".to_owned();
+ let expected: String = "robertCMartin".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn random_text_with_bad_chars() {
+ let convertable_string: String = "Random text with *(bad) chars".to_owned();
+ let expected: String = "randomTextWithBadChars".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn trailing_bad_chars() {
+ let convertable_string: String = "trailing bad_chars*(()())".to_owned();
+ let expected: String = "trailingBadChars".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn leading_bad_chars() {
+ let convertable_string: String = "-!#$%leading bad chars".to_owned();
+ let expected: String = "leadingBadChars".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn wrapped_in_bad_chars() {
+ let convertable_string: String = "-!#$%wrapped in bad chars&*^*&(&*^&(<><?>><?><>))".to_owned();
+ let expected: String = "wrappedInBadChars".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn has_a_sign() {
+ let convertable_string: String = "has a + sign".to_owned();
+ let expected: String = "hasASign".to_owned();
+ assert_eq!(to_camel_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn is_correct_from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ assert_eq!(is_camel_case(&convertable_string), true)
+ }
+
+ #[test]
+ fn is_correct_from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ assert_eq!(is_camel_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ assert_eq!(is_camel_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ assert_eq!(is_camel_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ assert_eq!(is_camel_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ assert_eq!(is_camel_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ assert_eq!(is_camel_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ assert_eq!(is_camel_case(&convertable_string), false)
+ }
+}
+
diff --git a/src/cases/case/mod.rs b/src/cases/case/mod.rs
new file mode 100644
index 0000000..bb4c3d2
--- /dev/null
+++ b/src/cases/case/mod.rs
@@ -0,0 +1,303 @@
+#![deny(warnings)]
+#[allow(unknown_lints)]
+#[allow(unused_imports)]
+use std::ascii::*;
+
+pub struct CamelOptions {
+ pub new_word: bool,
+ pub last_char: char,
+ pub first_word: bool,
+ pub injectable_char: char,
+ pub has_seperator: bool,
+ pub inverted: bool,
+}
+
+pub fn to_case_snake_like(convertable_string: &str, replace_with: &str, case: &str) -> String {
+ let mut first_character: bool = true;
+ let mut result: String = String::with_capacity(convertable_string.len() * 2);
+ for char_with_index in trim_right(convertable_string).char_indices() {
+ if char_is_seperator(&char_with_index.1) {
+ if !first_character {
+ first_character = true;
+ result.push(replace_with.chars().nth(0).unwrap_or('_'));
+ }
+ } else if requires_seperator(char_with_index, first_character, &convertable_string) {
+ first_character = false;
+ result = snake_like_with_seperator(result, replace_with, &char_with_index.1, case)
+ } else {
+ first_character = false;
+ result = snake_like_no_seperator(result, &char_with_index.1, case)
+ }
+ }
+ result
+}
+
+pub fn to_case_camel_like(convertable_string: &str, camel_options: CamelOptions) -> String {
+ let mut new_word: bool = camel_options.new_word;
+ let mut first_word: bool = camel_options.first_word;
+ let mut last_char: char = camel_options.last_char;
+ let mut found_real_char: bool = false;
+ let mut result: String = String::with_capacity(convertable_string.len() * 2);
+ for character in trim_right(convertable_string).chars() {
+ if char_is_seperator(&character) && found_real_char {
+ new_word = true;
+ } else if !found_real_char && is_not_alphanumeric(character) {
+ continue;
+ } else if character.is_numeric() {
+ found_real_char = true;
+ new_word = true;
+ result.push(character);
+ } else if last_char_lower_current_is_upper_or_new_word(new_word, last_char, character) {
+ found_real_char = true;
+ new_word = false;
+ result = append_on_new_word(result, first_word, character, &camel_options);
+ first_word = false;
+ } else {
+ found_real_char = true;
+ last_char = character;
+ result.push(character.to_ascii_lowercase());
+ }
+ }
+ result
+}
+
+#[inline]
+fn append_on_new_word(mut result: String, first_word: bool, character: char, camel_options: &CamelOptions) -> String {
+ if not_first_word_and_has_seperator(first_word, camel_options.has_seperator) {
+ result.push(camel_options.injectable_char);
+ }
+ if first_word_or_not_inverted(first_word, camel_options.inverted) {
+ result.push(character.to_ascii_uppercase());
+ } else {
+ result.push(character.to_ascii_lowercase());
+ }
+ result
+}
+
+fn not_first_word_and_has_seperator(first_word: bool, has_seperator: bool) -> bool {
+ has_seperator && !first_word
+}
+
+fn first_word_or_not_inverted(first_word: bool, inverted: bool) -> bool {
+ !inverted || first_word
+}
+
+
+fn last_char_lower_current_is_upper_or_new_word(new_word: bool, last_char: char, character: char) -> bool{
+ new_word ||
+ ((last_char.is_lowercase() && character.is_uppercase()) &&
+ (last_char != ' '))
+}
+
+fn char_is_seperator(character: &char) -> bool {
+ is_not_alphanumeric(*character)
+}
+
+fn trim_right(convertable_string: &str) -> &str {
+ convertable_string.trim_end_matches(is_not_alphanumeric)
+}
+
+fn is_not_alphanumeric(character: char) -> bool {
+ !character.is_alphanumeric()
+}
+
+#[inline]
+fn requires_seperator(char_with_index: (usize, char), first_character: bool, convertable_string: &str) -> bool {
+ !first_character &&
+ char_is_uppercase(char_with_index.1) &&
+ next_or_previous_char_is_lowercase(convertable_string, char_with_index.0)
+}
+
+#[inline]
+fn snake_like_no_seperator(mut accumlator: String, current_char: &char, case: &str) -> String {
+ if case == "lower" {
+ accumlator.push(current_char.to_ascii_lowercase());
+ accumlator
+ } else {
+ accumlator.push(current_char.to_ascii_uppercase());
+ accumlator
+ }
+}
+
+#[inline]
+fn snake_like_with_seperator(mut accumlator: String, replace_with: &str, current_char: &char, case: &str) -> String {
+ if case == "lower" {
+ accumlator.push(replace_with.chars().nth(0).unwrap_or('_'));
+ accumlator.push(current_char.to_ascii_lowercase());
+ accumlator
+ } else {
+ accumlator.push(replace_with.chars().nth(0).unwrap_or('_'));
+ accumlator.push(current_char.to_ascii_uppercase());
+ accumlator
+ }
+}
+
+fn next_or_previous_char_is_lowercase(convertable_string: &str, char_with_index: usize) -> bool {
+ convertable_string.chars().nth(char_with_index + 1).unwrap_or('A').is_lowercase() ||
+ convertable_string.chars().nth(char_with_index - 1).unwrap_or('A').is_lowercase()
+}
+
+fn char_is_uppercase(test_char: char) -> bool {
+ test_char == test_char.to_ascii_uppercase()
+}
+
+#[test]
+fn test_trim_bad_chars() {
+ assert_eq!("abc", trim_right("abc----^"))
+}
+
+#[test]
+fn test_trim_bad_chars_when_none_are_bad() {
+ assert_eq!("abc", trim_right("abc"))
+}
+
+#[test]
+fn test_is_not_alphanumeric_on_is_alphanumeric() {
+ assert!(!is_not_alphanumeric('a'))
+}
+
+#[test]
+fn test_is_not_alphanumeric_on_is_not_alphanumeric() {
+ assert!(is_not_alphanumeric('_'))
+}
+
+
+#[test]
+fn test_char_is_uppercase_when_it_is() {
+ assert_eq!(char_is_uppercase('A'), true)
+}
+
+#[test]
+fn test_char_is_uppercase_when_it_is_not() {
+ assert_eq!(char_is_uppercase('a'), false)
+}
+
+#[test]
+fn test_next_or_previous_char_is_lowercase_true() {
+ assert_eq!(next_or_previous_char_is_lowercase("TestWWW", 3), true)
+}
+
+#[test]
+fn test_next_or_previous_char_is_lowercase_false() {
+ assert_eq!(next_or_previous_char_is_lowercase("TestWWW", 5), false)
+}
+
+#[test]
+fn snake_like_with_seperator_lowers() {
+ assert_eq!(snake_like_with_seperator("".to_owned(), "^", &'c', "lower"), "^c".to_string())
+}
+
+#[test]
+fn snake_like_with_seperator_upper() {
+ assert_eq!(snake_like_with_seperator("".to_owned(), "^", &'c', "upper"), "^C".to_string())
+}
+
+#[test]
+fn snake_like_no_seperator_lower() {
+ assert_eq!(snake_like_no_seperator("".to_owned(), &'C', "lower"), "c".to_string())
+}
+
+#[test]
+fn snake_like_no_seperator_upper() {
+ assert_eq!(snake_like_no_seperator("".to_owned(), &'c', "upper"), "C".to_string())
+}
+
+#[test]
+fn requires_seperator_upper_not_first_wrap_is_safe_current_upper() {
+ assert_eq!(requires_seperator((2, 'C'), false, "test"), true)
+}
+
+#[test]
+fn requires_seperator_upper_not_first_wrap_is_safe_current_lower() {
+ assert_eq!(requires_seperator((2, 'c'), false, "test"), false)
+}
+
+#[test]
+fn requires_seperator_upper_first_wrap_is_safe_current_upper() {
+ assert_eq!(requires_seperator((0, 'T'), true, "Test"), false)
+}
+
+#[test]
+fn requires_seperator_upper_first_wrap_is_safe_current_lower() {
+ assert_eq!(requires_seperator((0, 't'), true, "Test"), false)
+}
+
+#[test]
+fn requires_seperator_upper_first_wrap_is_safe_current_lower_next_is_too() {
+ assert_eq!(requires_seperator((0, 't'), true, "test"), false)
+}
+
+#[test]
+fn test_char_is_seperator_dash() {
+ assert_eq!(char_is_seperator(&'-'), true)
+}
+
+#[test]
+fn test_char_is_seperator_underscore() {
+ assert_eq!(char_is_seperator(&'_'), true)
+}
+
+#[test]
+fn test_char_is_seperator_space() {
+ assert_eq!(char_is_seperator(&' '), true)
+}
+
+#[test]
+fn test_char_is_seperator_when_not() {
+ assert_eq!(char_is_seperator(&'A'), false)
+}
+
+#[test]
+fn test_last_char_lower_current_is_upper_or_new_word_with_new_word() {
+ assert_eq!(last_char_lower_current_is_upper_or_new_word(true, ' ', '-'), true)
+}
+
+#[test]
+fn test_last_char_lower_current_is_upper_or_new_word_last_char_space() {
+ assert_eq!(last_char_lower_current_is_upper_or_new_word(false, ' ', '-'), false)
+}
+
+#[test]
+fn test_last_char_lower_current_is_upper_or_new_word_last_char_lower_current_upper() {
+ assert_eq!(last_char_lower_current_is_upper_or_new_word(false, 'a', 'A'), true)
+}
+
+#[test]
+fn test_last_char_lower_current_is_upper_or_new_word_last_char_upper_current_upper() {
+ assert_eq!(last_char_lower_current_is_upper_or_new_word(false, 'A', 'A'), false)
+}
+
+#[test]
+fn test_last_char_lower_current_is_upper_or_new_word_last_char_upper_current_lower() {
+ assert_eq!(last_char_lower_current_is_upper_or_new_word(false, 'A', 'a'), false)
+}
+
+#[test]
+fn test_first_word_or_not_inverted_with_first_word() {
+ assert_eq!(first_word_or_not_inverted(true, false), true)
+}
+
+#[test]
+fn test_first_word_or_not_inverted_not_first_word_not_inverted() {
+ assert_eq!(first_word_or_not_inverted(false, false), true)
+}
+
+#[test]
+fn test_first_word_or_not_inverted_not_first_word_is_inverted() {
+ assert_eq!(first_word_or_not_inverted(false, true), false)
+}
+
+#[test]
+fn test_not_first_word_and_has_seperator_is_first_and_not_seperator() {
+ assert_eq!(not_first_word_and_has_seperator(true, false), false)
+}
+
+#[test]
+fn test_not_first_word_and_has_seperator_not_first_and_not_seperator() {
+ assert_eq!(not_first_word_and_has_seperator(false, false), false)
+}
+
+#[test]
+fn test_not_first_word_and_has_seperator_not_first_and_has_seperator() {
+ assert_eq!(not_first_word_and_has_seperator(false, true), true)
+}
diff --git a/src/cases/classcase/mod.rs b/src/cases/classcase/mod.rs
new file mode 100644
index 0000000..e0b6ef6
--- /dev/null
+++ b/src/cases/classcase/mod.rs
@@ -0,0 +1,393 @@
+#![deny(warnings)]
+use cases::case::*;
+#[cfg(feature = "heavyweight")]
+use string::singularize::to_singular;
+#[cfg(feature = "heavyweight")]
+/// Converts a `&str` to `ClassCase` `String`
+///
+/// ```
+/// use inflector::cases::classcase::to_class_case;
+/// let mock_string: &str = "FooBar";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_class_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::to_class_case;
+/// let mock_string: &str = "FooBars";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_class_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::to_class_case;
+/// let mock_string: &str = "Foo Bar";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_class_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::to_class_case;
+/// let mock_string: &str = "foo-bar";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_class_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::to_class_case;
+/// let mock_string: &str = "fooBar";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_class_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::to_class_case;
+/// let mock_string: &str = "FOO_BAR";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_class_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::to_class_case;
+/// let mock_string: &str = "foo_bar";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_class_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::to_class_case;
+/// let mock_string: &str = "foo_bars";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_class_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::to_class_case;
+/// let mock_string: &str = "Foo bar";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_class_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_class_case(non_class_case_string: &str) -> String {
+ let options = CamelOptions {
+ new_word: true,
+ last_char: ' ',
+ first_word: false,
+ injectable_char: ' ',
+ has_seperator: false,
+ inverted: false,
+ };
+ let class_plural = to_case_camel_like(non_class_case_string, options);
+ let split: (&str, &str) =
+ class_plural.split_at(class_plural.rfind(char::is_uppercase).unwrap_or(0));
+ format!("{}{}", split.0, to_singular(split.1))
+}
+
+#[cfg(feature = "heavyweight")]
+/// Determines if a `&str` is `ClassCase` `bool`
+///
+/// ```
+/// use inflector::cases::classcase::is_class_case;
+/// let mock_string: &str = "Foo";
+/// let asserted_bool: bool = is_class_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::is_class_case;
+/// let mock_string: &str = "foo";
+/// let asserted_bool: bool = is_class_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::is_class_case;
+/// let mock_string: &str = "FooBarIsAReallyReallyLongStrings";
+/// let asserted_bool: bool = is_class_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+///
+/// ```
+/// use inflector::cases::classcase::is_class_case;
+/// let mock_string: &str = "FooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_class_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::is_class_case;
+/// let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+/// let asserted_bool: bool = is_class_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::is_class_case;
+/// let mock_string: &str = "foo_bar_is_a_really_really_long_strings";
+/// let asserted_bool: bool = is_class_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+///
+/// ```
+/// use inflector::cases::classcase::is_class_case;
+/// let mock_string: &str = "fooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_class_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::is_class_case;
+/// let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+/// let asserted_bool: bool = is_class_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::is_class_case;
+/// let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+/// let asserted_bool: bool = is_class_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::is_class_case;
+/// let mock_string: &str = "Foo bar string that is really really long";
+/// let asserted_bool: bool = is_class_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::classcase::is_class_case;
+/// let mock_string: &str = "Foo Bar Is A Really Really Long String";
+/// let asserted_bool: bool = is_class_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+pub fn is_class_case(test_string: &str) -> bool {
+ to_class_case(&test_string.clone()) == test_string
+}
+
+#[cfg(all(feature = "unstable", test))]
+#[cfg(feature = "heavyweight")]
+mod benchmarks {
+ extern crate test;
+ use self::test::Bencher;
+
+ #[bench]
+ fn bench_class_case(b: &mut Bencher) {
+ b.iter(|| super::to_class_case("Foo bar"));
+ }
+
+ #[bench]
+ fn bench_is_class(b: &mut Bencher) {
+ b.iter(|| super::is_class_case("Foo bar"));
+ }
+
+ #[bench]
+ fn bench_class_from_snake(b: &mut Bencher) {
+ b.iter(|| super::to_class_case("foo_bar"));
+ }
+}
+
+#[cfg(test)]
+#[cfg(feature = "heavyweight")]
+mod tests {
+ use ::to_class_case;
+ use ::is_class_case;
+
+ #[test]
+ fn from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_screaming_class_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_table_case() {
+ let convertable_string: String = "foo_bars".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_case_with_loads_of_space() {
+ let convertable_string: String = "foo bar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn a_name_with_a_dot() {
+ let convertable_string: String = "Robert C. Martin".to_owned();
+ let expected: String = "RobertCMartin".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn random_text_with_bad_chars() {
+ let convertable_string: String = "Random text with *(bad) chars".to_owned();
+ let expected: String = "RandomTextWithBadChar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn trailing_bad_chars() {
+ let convertable_string: String = "trailing bad_chars*(()())".to_owned();
+ let expected: String = "TrailingBadChar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn leading_bad_chars() {
+ let convertable_string: String = "-!#$%leading bad chars".to_owned();
+ let expected: String = "LeadingBadChar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn wrapped_in_bad_chars() {
+ let convertable_string: String = "-!#$%wrapped in bad chars&*^*&(&*^&(<><?>><?><>))".to_owned();
+ let expected: String = "WrappedInBadChar".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn has_a_sign() {
+ let convertable_string: String = "has a + sign".to_owned();
+ let expected: String = "HasASign".to_owned();
+ assert_eq!(to_class_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn is_correct_from_class_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ assert_eq!(is_class_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ assert_eq!(is_class_case(&convertable_string), true)
+ }
+
+ #[test]
+ fn is_correct_from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ assert_eq!(is_class_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ assert_eq!(is_class_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ assert_eq!(is_class_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ assert_eq!(is_class_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ assert_eq!(is_class_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ assert_eq!(is_class_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_table_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ assert_eq!(is_class_case(&convertable_string), true)
+ }
+}
+
diff --git a/src/cases/kebabcase/mod.rs b/src/cases/kebabcase/mod.rs
new file mode 100644
index 0000000..d79f273
--- /dev/null
+++ b/src/cases/kebabcase/mod.rs
@@ -0,0 +1,262 @@
+#![deny(warnings)]
+use cases::case::*;
+/// Determines if a `&str` is `kebab-case`
+///
+/// ```
+/// use inflector::cases::kebabcase::is_kebab_case;
+/// let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+/// let asserted_bool: bool = is_kebab_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::kebabcase::is_kebab_case;
+/// let mock_string: &str = "FooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_kebab_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::kebabcase::is_kebab_case;
+/// let mock_string: &str = "fooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_kebab_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::kebabcase::is_kebab_case;
+/// let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+/// let asserted_bool: bool = is_kebab_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::kebabcase::is_kebab_case;
+/// let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+/// let asserted_bool: bool = is_kebab_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::kebabcase::is_kebab_case;
+/// let mock_string: &str = "Foo bar string that is really really long";
+/// let asserted_bool: bool = is_kebab_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::kebabcase::is_kebab_case;
+/// let mock_string: &str = "Foo Bar Is A Really Really Long String";
+/// let asserted_bool: bool = is_kebab_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+pub fn is_kebab_case(test_string: &str) -> bool {
+ test_string == to_kebab_case(test_string.clone())
+}
+
+/// Converts a `&str` to `kebab-case` `String`
+///
+/// ```
+/// use inflector::cases::kebabcase::to_kebab_case;
+/// let mock_string: &str = "foo-bar";
+/// let expected_string: String = "foo-bar".to_string();
+/// let asserted_string: String = to_kebab_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::kebabcase::to_kebab_case;
+/// let mock_string: &str = "FOO_BAR";
+/// let expected_string: String = "foo-bar".to_string();
+/// let asserted_string: String = to_kebab_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::kebabcase::to_kebab_case;
+/// let mock_string: &str = "foo_bar";
+/// let expected_string: String = "foo-bar".to_string();
+/// let asserted_string: String = to_kebab_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::kebabcase::to_kebab_case;
+/// let mock_string: &str = "Foo Bar";
+/// let expected_string: String = "foo-bar".to_string();
+/// let asserted_string: String = to_kebab_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::kebabcase::to_kebab_case;
+/// let mock_string: &str = "Foo bar";
+/// let expected_string: String = "foo-bar".to_string();
+/// let asserted_string: String = to_kebab_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::kebabcase::to_kebab_case;
+/// let mock_string: &str = "FooBar";
+/// let expected_string: String = "foo-bar".to_string();
+/// let asserted_string: String = to_kebab_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::kebabcase::to_kebab_case;
+/// let mock_string: &str = "fooBar";
+/// let expected_string: String = "foo-bar".to_string();
+/// let asserted_string: String = to_kebab_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_kebab_case(non_kebab_case_string: &str) -> String {
+ to_case_snake_like(non_kebab_case_string, "-", "lower")
+}
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+ extern crate test;
+ use self::test::Bencher;
+
+ #[bench]
+ fn bench_kebab(b: &mut Bencher) {
+ b.iter(|| super::to_kebab_case("Foo bar"));
+ }
+
+ #[bench]
+ fn bench_is_kebab(b: &mut Bencher) {
+ b.iter(|| super::is_kebab_case("Foo bar"));
+ }
+
+ #[bench]
+ fn bench_kebab_from_snake(b: &mut Bencher) {
+ b.iter(|| super::to_kebab_case("test_test_test"));
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use ::to_kebab_case;
+ use ::is_kebab_case;
+
+ #[test]
+ fn from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ let expected: String = "foo-bar".to_owned();
+ assert_eq!(to_kebab_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ let expected: String = "foo-bar".to_owned();
+ assert_eq!(to_kebab_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ let expected: String = "foo-bar".to_owned();
+ assert_eq!(to_kebab_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ let expected: String = "foo-bar".to_owned();
+ assert_eq!(to_kebab_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ let expected: String = "foo-bar".to_owned();
+ assert_eq!(to_kebab_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ let expected: String = "foo-bar".to_owned();
+ assert_eq!(to_kebab_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ let expected: String = "foo-bar".to_owned();
+ assert_eq!(to_kebab_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ let expected: String = "foo-bar".to_owned();
+ assert_eq!(to_kebab_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn is_correct_from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ assert_eq!(is_kebab_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ assert_eq!(is_kebab_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ assert_eq!(is_kebab_case(&convertable_string), true)
+ }
+
+ #[test]
+ fn is_correct_from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ assert_eq!(is_kebab_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ assert_eq!(is_kebab_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ assert_eq!(is_kebab_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ assert_eq!(is_kebab_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ assert_eq!(is_kebab_case(&convertable_string), false)
+ }
+}
+
diff --git a/src/cases/mod.rs b/src/cases/mod.rs
new file mode 100644
index 0000000..dfa772e
--- /dev/null
+++ b/src/cases/mod.rs
@@ -0,0 +1,52 @@
+mod case;
+/// Provides conversion to and detection of class case strings.
+///
+/// This version singularizes strings.
+///
+/// Example string `ClassCase`
+pub mod classcase;
+
+/// Provides conversion to and detection of camel case strings.
+///
+/// Example string `camelCase`
+pub mod camelcase;
+
+/// Provides conversion to and detection of snake case strings.
+///
+/// Example string `snake_case`
+pub mod snakecase;
+
+/// Provides conversion to and detection of screaming snake case strings.
+///
+/// Example string `SCREAMING_SNAKE_CASE`
+pub mod screamingsnakecase;
+
+/// Provides conversion to and detection of kebab case strings.
+///
+/// Example string `kebab-case`
+pub mod kebabcase;
+
+/// Provides conversion to and detection of train case strings.
+///
+/// Example string `Train-Case`
+pub mod traincase;
+
+/// Provides conversion to and detection of sentence case strings.
+///
+/// Example string `Sentence case`
+pub mod sentencecase;
+
+/// Provides conversion to and detection of title case strings.
+///
+/// Example string `Title Case`
+pub mod titlecase;
+
+/// Provides conversion to and detection of table case strings.
+///
+/// Example string `table_cases`
+pub mod tablecase;
+
+/// Provides conversion to pascal case strings.
+///
+/// Example string `PascalCase`
+pub mod pascalcase;
diff --git a/src/cases/pascalcase/mod.rs b/src/cases/pascalcase/mod.rs
new file mode 100644
index 0000000..248f91a
--- /dev/null
+++ b/src/cases/pascalcase/mod.rs
@@ -0,0 +1,360 @@
+#![deny(warnings)]
+use cases::case::*;
+/// Converts a `&str` to pascalCase `String`
+///
+/// ```
+/// use inflector::cases::pascalcase::to_pascal_case;
+/// let mock_string: &str = "fooBar";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_pascal_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::to_pascal_case;
+/// let mock_string: &str = "FOO_BAR";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_pascal_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::to_pascal_case;
+/// let mock_string: &str = "Foo Bar";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_pascal_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::to_pascal_case;
+/// let mock_string: &str = "foo_bar";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_pascal_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::to_pascal_case;
+/// let mock_string: &str = "Foo bar";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_pascal_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::to_pascal_case;
+/// let mock_string: &str = "foo-bar";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_pascal_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::to_pascal_case;
+/// let mock_string: &str = "FooBar";
+/// let expected_string: String = "FooBar".to_string();
+/// let asserted_string: String = to_pascal_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::to_pascal_case;
+/// let mock_string: &str = "FooBar3";
+/// let expected_string: String = "FooBar3".to_string();
+/// let asserted_string: String = to_pascal_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_pascal_case(non_pascalized_string: &str) -> String {
+ let options = CamelOptions {
+ new_word: true,
+ last_char: ' ',
+ first_word: false,
+ injectable_char: ' ',
+ has_seperator: false,
+ inverted: false,
+ };
+ to_case_camel_like(non_pascalized_string, options)
+}
+
+/// Determines if a `&str` is pascalCase bool``
+///
+/// ```
+/// use inflector::cases::pascalcase::is_pascal_case;
+/// let mock_string: &str = "Foo";
+/// let asserted_bool: bool = is_pascal_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::is_pascal_case;
+/// let mock_string: &str = "foo";
+/// let asserted_bool: bool = is_pascal_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::is_pascal_case;
+/// let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+/// let asserted_bool: bool = is_pascal_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::is_pascal_case;
+/// let mock_string: &str = "FooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_pascal_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::is_pascal_case;
+/// let mock_string: &str = "FooBarIsAReallyReally3LongString";
+/// let asserted_bool: bool = is_pascal_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::is_pascal_case;
+/// let mock_string: &str = "FooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_pascal_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::is_pascal_case;
+/// let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+/// let asserted_bool: bool = is_pascal_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::is_pascal_case;
+/// let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+/// let asserted_bool: bool = is_pascal_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::is_pascal_case;
+/// let mock_string: &str = "Foo bar string that is really really long";
+/// let asserted_bool: bool = is_pascal_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+/// use inflector::cases::pascalcase::is_pascal_case;
+/// let mock_string: &str = "Foo Bar Is A Really Really Long String";
+/// let asserted_bool: bool = is_pascal_case(mock_string);
+/// assert!(asserted_bool == false);
+/// ```
+pub fn is_pascal_case(test_string: &str) -> bool {
+ to_pascal_case(test_string.clone()) == test_string
+}
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+ extern crate test;
+ use self::test::Bencher;
+
+ #[bench]
+ fn bench_pascal0(b: &mut Bencher) {
+ b.iter(|| {
+ let test_string = "Foo bar";
+ super::to_pascal_case(test_string)
+ });
+ }
+
+ #[bench]
+ fn bench_pascal1(b: &mut Bencher) {
+ b.iter(|| {
+ let test_string = "foo_bar";
+ super::to_pascal_case(test_string)
+ });
+ }
+
+ #[bench]
+ fn bench_pascal2(b: &mut Bencher) {
+ b.iter(|| {
+ let test_string = "fooBar";
+ super::to_pascal_case(test_string)
+ });
+ }
+
+ #[bench]
+ fn bench_is_pascal(b: &mut Bencher) {
+ b.iter(|| {
+ let test_string: &str = "Foo bar";
+ super::is_pascal_case(test_string)
+ });
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use ::to_pascal_case;
+ use ::is_pascal_case;
+
+ #[test]
+ fn from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_case_with_loads_of_space() {
+ let convertable_string: String = "foo bar".to_owned();
+ let expected: String = "FooBar".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn a_name_with_a_dot() {
+ let convertable_string: String = "Robert C. Martin".to_owned();
+ let expected: String = "RobertCMartin".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn random_text_with_bad_chars() {
+ let convertable_string: String = "Random text with *(bad) chars".to_owned();
+ let expected: String = "RandomTextWithBadChars".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn trailing_bad_chars() {
+ let convertable_string: String = "trailing bad_chars*(()())".to_owned();
+ let expected: String = "TrailingBadChars".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn leading_bad_chars() {
+ let convertable_string: String = "-!#$%leading bad chars".to_owned();
+ let expected: String = "LeadingBadChars".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn wrapped_in_bad_chars() {
+ let convertable_string: String = "-!#$%wrapped in bad chars&*^*&(&*^&(<><?>><?><>))".to_owned();
+ let expected: String = "WrappedInBadChars".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn has_a_sign() {
+ let convertable_string: String = "has a + sign".to_owned();
+ let expected: String = "HasASign".to_owned();
+ assert_eq!(to_pascal_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn is_correct_from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ assert_eq!(is_pascal_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ assert_eq!(is_pascal_case(&convertable_string), true)
+ }
+
+ #[test]
+ fn is_correct_from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ assert_eq!(is_pascal_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ assert_eq!(is_pascal_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ assert_eq!(is_pascal_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ assert_eq!(is_pascal_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ assert_eq!(is_pascal_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ assert_eq!(is_pascal_case(&convertable_string), false)
+ }
+}
diff --git a/src/cases/screamingsnakecase/mod.rs b/src/cases/screamingsnakecase/mod.rs
new file mode 100644
index 0000000..9bec7a5
--- /dev/null
+++ b/src/cases/screamingsnakecase/mod.rs
@@ -0,0 +1,253 @@
+#![deny(warnings)]
+use cases::case::*;
+/// Converts a `&str` to `SCREAMING_SNAKE_CASE` `String`
+///
+/// ```
+/// use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+/// let mock_string: &str = "foo_bar";
+/// let expected_string: String = "FOO_BAR".to_string();
+/// let asserted_string: String = to_screaming_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+/// let mock_string: &str = "HTTP Foo bar";
+/// let expected_string: String = "HTTP_FOO_BAR".to_string();
+/// let asserted_string: String = to_screaming_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+/// let mock_string: &str = "Foo bar";
+/// let expected_string: String = "FOO_BAR".to_string();
+/// let asserted_string: String = to_screaming_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+/// let mock_string: &str = "Foo Bar";
+/// let expected_string: String = "FOO_BAR".to_string();
+/// let asserted_string: String = to_screaming_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+/// let mock_string: &str = "FooBar";
+/// let expected_string: String = "FOO_BAR".to_string();
+/// let asserted_string: String = to_screaming_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+/// let mock_string: &str = "fooBar";
+/// let expected_string: String = "FOO_BAR".to_string();
+/// let asserted_string: String = to_screaming_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+/// let mock_string: &str = "fooBar3";
+/// let expected_string: String = "FOO_BAR_3".to_string();
+/// let asserted_string: String = to_screaming_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_screaming_snake_case(non_snake_case_string: &str) -> String {
+ to_case_snake_like(non_snake_case_string, "_", "upper")
+}
+
+/// Determines of a `&str` is `SCREAMING_SNAKE_CASE`
+///
+/// ```
+/// use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+/// let mock_string: &str = "Foo bar string that is really really long";
+/// let asserted_bool: bool = is_screaming_snake_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+/// let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+/// let asserted_bool: bool = is_screaming_snake_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+/// let mock_string: &str = "FooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_screaming_snake_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+/// let mock_string: &str = "Foo Bar Is A Really Really Long String";
+/// let asserted_bool: bool = is_screaming_snake_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+/// let mock_string: &str = "fooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_screaming_snake_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+/// let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+/// let asserted_bool: bool = is_screaming_snake_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+/// ```
+/// ```
+/// use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+/// let mock_string: &str = "FOO_BAR1_STRING_THAT_IS_REALLY_REALLY_LONG";
+/// let asserted_bool: bool = is_screaming_snake_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+/// ```
+/// ```
+/// use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+/// let mock_string: &str = "FOO_BAR_1_STRING_THAT_IS_REALLY_REALLY_LONG";
+/// let asserted_bool: bool = is_screaming_snake_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+/// ```
+pub fn is_screaming_snake_case(test_string: &str) -> bool {
+ test_string == to_screaming_snake_case(test_string.clone())
+}
+
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+ extern crate test;
+ use self::test::Bencher;
+
+ #[bench]
+ fn bench_screaming_snake(b: &mut Bencher) {
+ b.iter(|| super::to_screaming_snake_case("Foo bar"));
+ }
+
+ #[bench]
+ fn bench_is_screaming_snake(b: &mut Bencher) {
+ b.iter(|| super::is_screaming_snake_case("Foo bar"));
+ }
+
+}
+
+#[cfg(test)]
+mod tests {
+ use ::to_screaming_snake_case;
+ use ::is_screaming_snake_case;
+
+ #[test]
+ fn from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ let expected: String = "FOO_BAR".to_owned();
+ assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ let expected: String = "FOO_BAR".to_owned();
+ assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ let expected: String = "FOO_BAR".to_owned();
+ assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ let expected: String = "FOO_BAR".to_owned();
+ assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ let expected: String = "FOO_BAR".to_owned();
+ assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ let expected: String = "FOO_BAR".to_owned();
+ assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_screaming_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ let expected: String = "FOO_BAR".to_owned();
+ assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ let expected: String = "FOO_BAR".to_owned();
+ assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn is_correct_from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ assert_eq!(is_screaming_snake_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ assert_eq!(is_screaming_snake_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ assert_eq!(is_screaming_snake_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ assert_eq!(is_screaming_snake_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ assert_eq!(is_screaming_snake_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ assert_eq!(is_screaming_snake_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_screaming_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ assert_eq!(is_screaming_snake_case(&convertable_string), true)
+ }
+
+ #[test]
+ fn is_correct_from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ assert_eq!(is_screaming_snake_case(&convertable_string), false)
+ }
+}
diff --git a/src/cases/sentencecase/mod.rs b/src/cases/sentencecase/mod.rs
new file mode 100644
index 0000000..5a99d21
--- /dev/null
+++ b/src/cases/sentencecase/mod.rs
@@ -0,0 +1,313 @@
+#![deny(warnings)]
+use cases::case::*;
+/// Converts a `&str` to `Sentence case` `String`
+///
+/// ```
+/// use inflector::cases::sentencecase::to_sentence_case;
+/// let mock_string: &str = "Foo bar";
+/// let expected_string: String = "Foo bar".to_string();
+/// let asserted_string: String = to_sentence_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::sentencecase::to_sentence_case;
+/// let mock_string: &str = "FooBar";
+/// let expected_string: String = "Foo bar".to_string();
+/// let asserted_string: String = to_sentence_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::sentencecase::to_sentence_case;
+/// let mock_string: &str = "fooBar";
+/// let expected_string: String = "Foo bar".to_string();
+/// let asserted_string: String = to_sentence_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::sentencecase::to_sentence_case;
+/// let mock_string: &str = "FOO_BAR";
+/// let expected_string: String = "Foo bar".to_string();
+/// let asserted_string: String = to_sentence_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::sentencecase::to_sentence_case;
+/// let mock_string: &str = "foo_bar";
+/// let expected_string: String = "Foo bar".to_string();
+/// let asserted_string: String = to_sentence_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::sentencecase::to_sentence_case;
+/// let mock_string: &str = "foo-bar";
+/// let expected_string: String = "Foo bar".to_string();
+/// let asserted_string: String = to_sentence_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_sentence_case(non_sentence_case_string: &str) -> String {
+ let options = CamelOptions {
+ new_word: true,
+ last_char: ' ',
+ first_word: true,
+ injectable_char: ' ',
+ has_seperator: true,
+ inverted: true,
+ };
+ to_case_camel_like(non_sentence_case_string, options)
+}
+/// Determines of a `&str` is `Sentence case`
+///
+/// ```
+/// use inflector::cases::sentencecase::is_sentence_case;
+/// let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+/// let asserted_bool: bool = is_sentence_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::sentencecase::is_sentence_case;
+/// let mock_string: &str = "FooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_sentence_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::sentencecase::is_sentence_case;
+/// let mock_string: &str = "fooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_sentence_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::sentencecase::is_sentence_case;
+/// let mock_string: &str = "Foo Bar Is A Really Really Long String";
+/// let asserted_bool: bool = is_sentence_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::sentencecase::is_sentence_case;
+/// let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+/// let asserted_bool: bool = is_sentence_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::sentencecase::is_sentence_case;
+/// let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+/// let asserted_bool: bool = is_sentence_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::sentencecase::is_sentence_case;
+/// let mock_string: &str = "Foo";
+/// let asserted_bool: bool = is_sentence_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+/// ```
+/// ```
+/// use inflector::cases::sentencecase::is_sentence_case;
+/// let mock_string: &str = "foo";
+/// let asserted_bool: bool = is_sentence_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::sentencecase::is_sentence_case;
+/// let mock_string: &str = "Foo bar string that is really really long";
+/// let asserted_bool: bool = is_sentence_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+/// ```
+pub fn is_sentence_case(test_string: &str) -> bool {
+ test_string == to_sentence_case(test_string.clone())
+}
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+ extern crate test;
+ use self::test::Bencher;
+
+ #[bench]
+ fn bench_sentence(b: &mut Bencher) {
+ b.iter(|| super::to_sentence_case("Foo BAR"));
+ }
+
+ #[bench]
+ fn bench_is_sentence(b: &mut Bencher) {
+ b.iter(|| super::is_sentence_case("Foo bar"));
+ }
+
+ #[bench]
+ fn bench_sentence_from_snake(b: &mut Bencher) {
+ b.iter(|| super::to_sentence_case("foo_bar"));
+ }
+
+}
+
+#[cfg(test)]
+mod tests {
+ use ::to_sentence_case;
+ use ::is_sentence_case;
+
+ #[test]
+ fn from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ let expected: String = "Foo bar".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ let expected: String = "Foo bar".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ let expected: String = "Foo bar".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ let expected: String = "Foo bar".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ let expected: String = "Foo bar".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ let expected: String = "Foo bar".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ let expected: String = "Foo bar".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ let expected: String = "Foo bar".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_case_with_loads_of_space() {
+ let convertable_string: String = "foo bar".to_owned();
+ let expected: String = "Foo bar".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn a_name_with_a_dot() {
+ let convertable_string: String = "Robert C. Martin".to_owned();
+ let expected: String = "Robert c martin".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn random_text_with_bad_chars() {
+ let convertable_string: String = "Random text with *(bad) chars".to_owned();
+ let expected: String = "Random text with bad chars".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn trailing_bad_chars() {
+ let convertable_string: String = "trailing bad_chars*(()())".to_owned();
+ let expected: String = "Trailing bad chars".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn leading_bad_chars() {
+ let convertable_string: String = "-!#$%leading bad chars".to_owned();
+ let expected: String = "Leading bad chars".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn wrapped_in_bad_chars() {
+ let convertable_string: String = "-!#$%wrapped in bad chars&*^*&(&*^&(<><?>><?><>))".to_owned();
+ let expected: String = "Wrapped in bad chars".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn has_a_sign() {
+ let convertable_string: String = "has a + sign".to_owned();
+ let expected: String = "Has a sign".to_owned();
+ assert_eq!(to_sentence_case(&convertable_string), expected)
+ }
+
+
+ #[test]
+ fn is_correct_from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ assert_eq!(is_sentence_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ assert_eq!(is_sentence_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ assert_eq!(is_sentence_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ assert_eq!(is_sentence_case(&convertable_string), true)
+ }
+
+ #[test]
+ fn is_correct_from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ assert_eq!(is_sentence_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ assert_eq!(is_sentence_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ assert_eq!(is_sentence_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ assert_eq!(is_sentence_case(&convertable_string), false)
+ }
+}
diff --git a/src/cases/snakecase/mod.rs b/src/cases/snakecase/mod.rs
new file mode 100644
index 0000000..a56894b
--- /dev/null
+++ b/src/cases/snakecase/mod.rs
@@ -0,0 +1,334 @@
+#![deny(warnings)]
+use cases::case::*;
+/// Converts a `&str` to `snake_case` `String`
+///
+/// ```
+/// use inflector::cases::snakecase::to_snake_case;
+/// let mock_string: &str = "foo_bar";
+/// let expected_string: String = "foo_bar".to_string();
+/// let asserted_string: String = to_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::to_snake_case;
+/// let mock_string: &str = "HTTP Foo bar";
+/// let expected_string: String = "http_foo_bar".to_string();
+/// let asserted_string: String = to_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::to_snake_case;
+/// let mock_string: &str = "HTTPFooBar";
+/// let expected_string: String = "http_foo_bar".to_string();
+/// let asserted_string: String = to_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::to_snake_case;
+/// let mock_string: &str = "Foo bar";
+/// let expected_string: String = "foo_bar".to_string();
+/// let asserted_string: String = to_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::to_snake_case;
+/// let mock_string: &str = "Foo Bar";
+/// let expected_string: String = "foo_bar".to_string();
+/// let asserted_string: String = to_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::to_snake_case;
+/// let mock_string: &str = "FooBar";
+/// let expected_string: String = "foo_bar".to_string();
+/// let asserted_string: String = to_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::to_snake_case;
+/// let mock_string: &str = "FOO_BAR";
+/// let expected_string: String = "foo_bar".to_string();
+/// let asserted_string: String = to_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::to_snake_case;
+/// let mock_string: &str = "fooBar";
+/// let expected_string: String = "foo_bar".to_string();
+/// let asserted_string: String = to_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::to_snake_case;
+/// let mock_string: &str = "fooBar3";
+/// let expected_string: String = "foo_bar_3".to_string();
+/// let asserted_string: String = to_snake_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_snake_case(non_snake_case_string: &str) -> String {
+ to_case_snake_like(non_snake_case_string, "_", "lower")
+}
+
+/// Determines of a `&str` is `snake_case`
+///
+/// ```
+/// use inflector::cases::snakecase::is_snake_case;
+/// let mock_string: &str = "Foo bar string that is really really long";
+/// let asserted_bool: bool = is_snake_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::is_snake_case;
+/// let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+/// let asserted_bool: bool = is_snake_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::is_snake_case;
+/// let mock_string: &str = "FooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_snake_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::is_snake_case;
+/// let mock_string: &str = "Foo Bar Is A Really Really Long String";
+/// let asserted_bool: bool = is_snake_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::is_snake_case;
+/// let mock_string: &str = "FOO_BAR_IS_A_REALLY_REALLY_LONG_STRING";
+/// let asserted_bool: bool = is_snake_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::is_snake_case;
+/// let mock_string: &str = "fooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_snake_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::is_snake_case;
+/// let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+/// let asserted_bool: bool = is_snake_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::is_snake_case;
+/// let mock_string: &str = "foo_bar1_string_that_is_really_really_long";
+/// let asserted_bool: bool = is_snake_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::snakecase::is_snake_case;
+/// let mock_string: &str = "foo_bar_1_string_that_is_really_really_long";
+/// let asserted_bool: bool = is_snake_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+/// ```
+pub fn is_snake_case(test_string: &str) -> bool {
+ test_string == to_snake_case(test_string.clone())
+}
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+ extern crate test;
+ use self::test::Bencher;
+
+ #[bench]
+ fn bench_snake_from_title(b: &mut Bencher) {
+ b.iter(|| super::to_snake_case("Foo bar"));
+ }
+
+ #[bench]
+ fn bench_snake_from_camel(b: &mut Bencher) {
+ b.iter(|| super::to_snake_case("fooBar"));
+ }
+
+ #[bench]
+ fn bench_snake_from_snake(b: &mut Bencher) {
+ b.iter(|| super::to_snake_case("foo_bar_bar_bar"));
+ }
+
+ #[bench]
+ fn bench_is_snake(b: &mut Bencher) {
+ b.iter(|| super::is_snake_case("Foo bar"));
+ }
+
+}
+
+#[cfg(test)]
+mod tests {
+ use ::to_snake_case;
+ use ::is_snake_case;
+
+ #[test]
+ fn from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ let expected: String = "foo_bar".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ let expected: String = "foo_bar".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ let expected: String = "foo_bar".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ let expected: String = "foo_bar".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ let expected: String = "foo_bar".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ let expected: String = "foo_bar".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ let expected: String = "foo_bar".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ let expected: String = "foo_bar".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_case_with_loads_of_space() {
+ let convertable_string: String = "foo bar".to_owned();
+ let expected: String = "foo_bar".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn a_name_with_a_dot() {
+ let convertable_string: String = "Robert C. Martin".to_owned();
+ let expected: String = "robert_c_martin".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn random_text_with_bad_chars() {
+ let convertable_string: String = "Random text with *(bad) chars".to_owned();
+ let expected: String = "random_text_with_bad_chars".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn trailing_bad_chars() {
+ let convertable_string: String = "trailing bad_chars*(()())".to_owned();
+ let expected: String = "trailing_bad_chars".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn leading_bad_chars() {
+ let convertable_string: String = "-!#$%leading bad chars".to_owned();
+ let expected: String = "leading_bad_chars".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn wrapped_in_bad_chars() {
+ let convertable_string: String = "-!#$%wrapped in bad chars&*^*&(&*^&(<><?>><?><>))".to_owned();
+ let expected: String = "wrapped_in_bad_chars".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn has_a_sign() {
+ let convertable_string: String = "has a + sign".to_owned();
+ let expected: String = "has_a_sign".to_owned();
+ assert_eq!(to_snake_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn is_correct_from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ assert_eq!(is_snake_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ assert_eq!(is_snake_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ assert_eq!(is_snake_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ assert_eq!(is_snake_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ assert_eq!(is_snake_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ assert_eq!(is_snake_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ assert_eq!(is_snake_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ assert_eq!(is_snake_case(&convertable_string), true)
+ }
+}
diff --git a/src/cases/tablecase/mod.rs b/src/cases/tablecase/mod.rs
new file mode 100644
index 0000000..7224cc4
--- /dev/null
+++ b/src/cases/tablecase/mod.rs
@@ -0,0 +1,271 @@
+#![deny(warnings)]
+#[cfg(feature = "heavyweight")]
+use string::pluralize::to_plural;
+#[cfg(feature = "heavyweight")]
+use cases::case::*;
+#[cfg(feature = "heavyweight")]
+/// Converts a `&str` to `table-case` `String`
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "foo-bar";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "FOO_BAR";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "foo_bar";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "Foo Bar";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "Foo bar";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "FooBar";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "fooBar";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+pub fn to_table_case(non_table_case_string: &str) -> String {
+ let snaked: String = to_case_snake_like(non_table_case_string, "_", "lower");
+ let split: (&str, &str) = snaked.split_at(snaked.rfind('_').unwrap_or(0));
+ format!("{}{}", split.0, to_plural(split.1))
+}
+
+#[cfg(feature = "heavyweight")]
+/// Determines if a `&str` is `table-case`
+///
+/// ```
+/// use inflector::cases::tablecase::is_table_case;
+/// let mock_string: &str = "foo_bar_strings";
+/// let asserted_bool: bool = is_table_case(mock_string);
+/// assert!(asserted_bool == true);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::is_table_case;
+/// let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+/// let asserted_bool: bool = is_table_case(mock_string);
+/// assert!(asserted_bool == false);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::is_table_case;
+/// let mock_string: &str = "FooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_table_case(mock_string);
+/// assert!(asserted_bool == false);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::is_table_case;
+/// let mock_string: &str = "fooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_table_case(mock_string);
+/// assert!(asserted_bool == false);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::is_table_case;
+/// let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+/// let asserted_bool: bool = is_table_case(mock_string);
+/// assert!(asserted_bool == false);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::is_table_case;
+/// let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+/// let asserted_bool: bool = is_table_case(mock_string);
+/// assert!(asserted_bool == false);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::is_table_case;
+/// let mock_string: &str = "Foo bar string that is really really long";
+/// let asserted_bool: bool = is_table_case(mock_string);
+/// assert!(asserted_bool == false);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::is_table_case;
+/// let mock_string: &str = "Foo Bar Is A Really Really Long String";
+/// let asserted_bool: bool = is_table_case(mock_string);
+/// assert!(asserted_bool == false);
+/// ```
+pub fn is_table_case(test_string: &str) -> bool {
+ to_table_case(&test_string.clone()) == test_string
+}
+
+#[cfg(all(feature = "unstable", test))]
+#[cfg(feature = "heavyweight")]
+mod benchmarks {
+ extern crate test;
+ use self::test::Bencher;
+
+ #[bench]
+ fn bench_table_case(b: &mut Bencher) {
+ b.iter(|| super::to_table_case("Foo bar"));
+ }
+
+ #[bench]
+ fn bench_is_table_case(b: &mut Bencher) {
+ b.iter(|| super::is_table_case("Foo bar"));
+ }
+}
+
+#[cfg(test)]
+#[cfg(feature = "heavyweight")]
+mod tests {
+ use ::to_table_case;
+ use ::is_table_case;
+
+ #[test]
+ fn from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ let expected: String = "foo_bars".to_owned();
+ assert_eq!(to_table_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ let expected: String = "foo_bars".to_owned();
+ assert_eq!(to_table_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ let expected: String = "foo_bars".to_owned();
+ assert_eq!(to_table_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ let expected: String = "foo_bars".to_owned();
+ assert_eq!(to_table_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ let expected: String = "foo_bars".to_owned();
+ assert_eq!(to_table_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ let expected: String = "foo_bars".to_owned();
+ assert_eq!(to_table_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ let expected: String = "foo_bars".to_owned();
+ assert_eq!(to_table_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ let expected: String = "foo_bars".to_owned();
+ assert_eq!(to_table_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_table_case() {
+ let convertable_string: String = "foo_bars".to_owned();
+ let expected: String = "foo_bars".to_owned();
+ assert_eq!(to_table_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn is_correct_from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ assert_eq!(is_table_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ assert_eq!(is_table_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ assert_eq!(is_table_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ assert_eq!(is_table_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ assert_eq!(is_table_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ assert_eq!(is_table_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ assert_eq!(is_table_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ assert_eq!(is_table_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_table_case() {
+ let convertable_string: String = "foo_bars".to_owned();
+ assert_eq!(is_table_case(&convertable_string), true)
+ }
+}
diff --git a/src/cases/titlecase/mod.rs b/src/cases/titlecase/mod.rs
new file mode 100644
index 0000000..eb0de25
--- /dev/null
+++ b/src/cases/titlecase/mod.rs
@@ -0,0 +1,308 @@
+#![deny(warnings)]
+use cases::case::*;
+/// Converts a `&str` to `Title Case` `String`
+///
+/// ```
+/// use inflector::cases::titlecase::to_title_case;
+/// let mock_string: &str = "Foo bar";
+/// let expected_string: String = "Foo Bar".to_string();
+/// let asserted_string: String = to_title_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::titlecase::to_title_case;
+/// let mock_string: &str = "FooBar";
+/// let expected_string: String = "Foo Bar".to_string();
+/// let asserted_string: String = to_title_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::titlecase::to_title_case;
+/// let mock_string: &str = "fooBar";
+/// let expected_string: String = "Foo Bar".to_string();
+/// let asserted_string: String = to_title_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::titlecase::to_title_case;
+/// let mock_string: &str = "FOO_BAR";
+/// let expected_string: String = "Foo Bar".to_string();
+/// let asserted_string: String = to_title_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::titlecase::to_title_case;
+/// let mock_string: &str = "foo_bar";
+/// let expected_string: String = "Foo Bar".to_string();
+/// let asserted_string: String = to_title_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::cases::titlecase::to_title_case;
+/// let mock_string: &str = "foo-bar";
+/// let expected_string: String = "Foo Bar".to_string();
+/// let asserted_string: String = to_title_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_title_case(non_title_case_string: &str) -> String {
+ let options = CamelOptions {
+ new_word: true,
+ last_char: ' ',
+ first_word: true,
+ injectable_char: ' ',
+ has_seperator: true,
+ inverted: false,
+ };
+ to_case_camel_like(non_title_case_string, options)
+}
+
+/// Determines if a `&str` is `Title Case`
+///
+/// ```
+/// use inflector::cases::titlecase::is_title_case;
+/// let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+/// let asserted_bool: bool = is_title_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::titlecase::is_title_case;
+/// let mock_string: &str = "FooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_title_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::titlecase::is_title_case;
+/// let mock_string: &str = "fooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_title_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::titlecase::is_title_case;
+/// let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+/// let asserted_bool: bool = is_title_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::titlecase::is_title_case;
+/// let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+/// let asserted_bool: bool = is_title_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::titlecase::is_title_case;
+/// let mock_string: &str = "Foo bar string that is really really long";
+/// let asserted_bool: bool = is_title_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::titlecase::is_title_case;
+/// let mock_string: &str = "foo";
+/// let asserted_bool: bool = is_title_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::cases::titlecase::is_title_case;
+/// let mock_string: &str = "Foo Bar String That Is Really Really Long";
+/// let asserted_bool: bool = is_title_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+/// ```
+pub fn is_title_case(test_string: &str) -> bool {
+ test_string == to_title_case(test_string.clone())
+}
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+ extern crate test;
+ use self::test::Bencher;
+
+ #[bench]
+ fn bench_title(b: &mut Bencher) {
+ b.iter(|| super::to_title_case("Foo BAR"));
+ }
+
+ #[bench]
+ fn bench_is_title(b: &mut Bencher) {
+ b.iter(|| super::is_title_case("Foo bar"));
+ }
+
+ #[bench]
+ fn bench_title_from_snake(b: &mut Bencher) {
+ b.iter(|| super::to_title_case("foo_bar"));
+ }
+
+}
+
+
+#[cfg(test)]
+mod tests {
+ use ::to_title_case;
+ use ::is_title_case;
+
+ #[test]
+ fn from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ let expected: String = "Foo Bar".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ let expected: String = "Foo Bar".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ let expected: String = "Foo Bar".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ let expected: String = "Foo Bar".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ let expected: String = "Foo Bar".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ let expected: String = "Foo Bar".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ let expected: String = "Foo Bar".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ let expected: String = "Foo Bar".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_case_with_loads_of_space() {
+ let convertable_string: String = "foo bar".to_owned();
+ let expected: String = "Foo Bar".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn a_name_with_a_dot() {
+ let convertable_string: String = "Robert C. Martin".to_owned();
+ let expected: String = "Robert C Martin".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn random_text_with_bad_chars() {
+ let convertable_string: String = "Random text with *(bad) chars".to_owned();
+ let expected: String = "Random Text With Bad Chars".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn trailing_bad_chars() {
+ let convertable_string: String = "trailing bad_chars*(()())".to_owned();
+ let expected: String = "Trailing Bad Chars".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn leading_bad_chars() {
+ let convertable_string: String = "-!#$%leading bad chars".to_owned();
+ let expected: String = "Leading Bad Chars".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn wrapped_in_bad_chars() {
+ let convertable_string: String = "-!#$%wrapped in bad chars&*^*&(&*^&(<><?>><?><>))".to_owned();
+ let expected: String = "Wrapped In Bad Chars".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn has_a_sign() {
+ let convertable_string: String = "has a + sign".to_owned();
+ let expected: String = "Has A Sign".to_owned();
+ assert_eq!(to_title_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn is_correct_from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ assert_eq!(is_title_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ assert_eq!(is_title_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ assert_eq!(is_title_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ assert_eq!(is_title_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ assert_eq!(is_title_case(&convertable_string), true)
+ }
+
+ #[test]
+ fn is_correct_from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ assert_eq!(is_title_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ assert_eq!(is_title_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ assert_eq!(is_title_case(&convertable_string), false)
+ }
+}
+
diff --git a/src/cases/traincase/mod.rs b/src/cases/traincase/mod.rs
new file mode 100644
index 0000000..cb2e882
--- /dev/null
+++ b/src/cases/traincase/mod.rs
@@ -0,0 +1,320 @@
+#![deny(warnings)]
+use cases::case::*;
+/// Determines if a `&str` is `Train-Case`
+///
+/// ```
+/// use inflector::cases::traincase::is_train_case;
+/// let mock_string: &str = "Foo-Bar-String-That-Is-Really-Really-Long";
+/// let asserted_bool: bool = is_train_case(mock_string);
+/// assert!(asserted_bool == true);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::traincase::is_train_case;
+/// let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+/// let asserted_bool: bool = is_train_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::traincase::is_train_case;
+/// let mock_string: &str = "FooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_train_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::traincase::is_train_case;
+/// let mock_string: &str = "fooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_train_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::traincase::is_train_case;
+/// let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+/// let asserted_bool: bool = is_train_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::traincase::is_train_case;
+/// let mock_string: &str = "Foo bar string that is really really long";
+/// let asserted_bool: bool = is_train_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::traincase::is_train_case;
+/// let mock_string: &str = "Foo Bar Is A Really Really Long String";
+/// let asserted_bool: bool = is_train_case(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+pub fn is_train_case(test_string: &str) -> bool {
+ test_string == to_train_case(test_string.clone())
+}
+
+
+/// Converts a `&str` to `Train-Case` `String`
+///
+/// ```
+/// use inflector::cases::traincase::to_train_case;
+/// let mock_string: &str = "foo-bar";
+/// let expected_string: String = "Foo-Bar".to_string();
+/// let asserted_string: String = to_train_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::traincase::to_train_case;
+/// let mock_string: &str = "FOO_BAR";
+/// let expected_string: String = "Foo-Bar".to_string();
+/// let asserted_string: String = to_train_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::traincase::to_train_case;
+/// let mock_string: &str = "foo_bar";
+/// let expected_string: String = "Foo-Bar".to_string();
+/// let asserted_string: String = to_train_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::traincase::to_train_case;
+/// let mock_string: &str = "Foo Bar";
+/// let expected_string: String = "Foo-Bar".to_string();
+/// let asserted_string: String = to_train_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::traincase::to_train_case;
+/// let mock_string: &str = "Foo bar";
+/// let expected_string: String = "Foo-Bar".to_string();
+/// let asserted_string: String = to_train_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::traincase::to_train_case;
+/// let mock_string: &str = "FooBar";
+/// let expected_string: String = "Foo-Bar".to_string();
+/// let asserted_string: String = to_train_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+/// use inflector::cases::traincase::to_train_case;
+/// let mock_string: &str = "fooBar";
+/// let expected_string: String = "Foo-Bar".to_string();
+/// let asserted_string: String = to_train_case(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_train_case(non_train_case_string: &str) -> String {
+ let options = CamelOptions {
+ new_word: true,
+ last_char: ' ',
+ first_word: true,
+ injectable_char: '-',
+ has_seperator: true,
+ inverted: false,
+ };
+ to_case_camel_like(non_train_case_string, options)
+}
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+ extern crate test;
+ use self::test::Bencher;
+
+ #[bench]
+ fn bench_train(b: &mut Bencher) {
+ b.iter(|| super::to_train_case("Foo bar"));
+ }
+
+ #[bench]
+ fn bench_is_train(b: &mut Bencher) {
+ b.iter(|| super::is_train_case("Foo bar"));
+ }
+
+ #[bench]
+ fn bench_train_from_snake(b: &mut Bencher) {
+ b.iter(|| super::to_train_case("test_test_test"));
+ }
+
+}
+
+#[cfg(test)]
+mod tests {
+ use ::to_train_case;
+ use ::is_train_case;
+
+ #[test]
+ fn from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ let expected: String = "Foo-Bar".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ let expected: String = "Foo-Bar".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ let expected: String = "Foo-Bar".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ let expected: String = "Foo-Bar".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ let expected: String = "Foo-Bar".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ let expected: String = "Foo-Bar".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ let expected: String = "Foo-Bar".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ let expected: String = "Foo-Bar".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn from_case_with_loads_of_space() {
+ let convertable_string: String = "foo bar".to_owned();
+ let expected: String = "Foo-Bar".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn a_name_with_a_dot() {
+ let convertable_string: String = "Robert C. Martin".to_owned();
+ let expected: String = "Robert-C-Martin".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn random_text_with_bad_chars() {
+ let convertable_string: String = "Random text with *(bad) chars".to_owned();
+ let expected: String = "Random-Text-With-Bad-Chars".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn trailing_bad_chars() {
+ let convertable_string: String = "trailing bad_chars*(()())".to_owned();
+ let expected: String = "Trailing-Bad-Chars".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn leading_bad_chars() {
+ let convertable_string: String = "-!#$%leading bad chars".to_owned();
+ let expected: String = "Leading-Bad-Chars".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn wrapped_in_bad_chars() {
+ let convertable_string: String = "-!#$%wrapped in bad chars&*^*&(&*^&(<><?>><?><>))".to_owned();
+ let expected: String = "Wrapped-In-Bad-Chars".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn has_a_sign() {
+ let convertable_string: String = "has a + sign".to_owned();
+ let expected: String = "Has-A-Sign".to_owned();
+ assert_eq!(to_train_case(&convertable_string), expected)
+ }
+
+ #[test]
+ fn is_correct_from_camel_case() {
+ let convertable_string: String = "fooBar".to_owned();
+ assert_eq!(is_train_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_pascal_case() {
+ let convertable_string: String = "FooBar".to_owned();
+ assert_eq!(is_train_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_kebab_case() {
+ let convertable_string: String = "foo-bar".to_owned();
+ assert_eq!(is_train_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_sentence_case() {
+ let convertable_string: String = "Foo bar".to_owned();
+ assert_eq!(is_train_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_title_case() {
+ let convertable_string: String = "Foo Bar".to_owned();
+ assert_eq!(is_train_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_train_case() {
+ let convertable_string: String = "Foo-Bar".to_owned();
+ assert_eq!(is_train_case(&convertable_string), true)
+ }
+
+ #[test]
+ fn is_correct_from_screaming_snake_case() {
+ let convertable_string: String = "FOO_BAR".to_owned();
+ assert_eq!(is_train_case(&convertable_string), false)
+ }
+
+ #[test]
+ fn is_correct_from_snake_case() {
+ let convertable_string: String = "foo_bar".to_owned();
+ assert_eq!(is_train_case(&convertable_string), false)
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..f52ea29
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,332 @@
+#![deny(warnings, unused_variables, missing_docs, unsafe_code, unused_extern_crates)]
+#![cfg_attr(feature = "unstable", feature(test))]
+
+//! Adds String based inflections for Rust. Snake, kebab, train, camel,
+//! sentence, class, and title cases as well as ordinalize,
+//! deordinalize, demodulize, deconstantize, and foreign key are supported as
+//! both traits and pure functions acting on String types.
+//! ```rust
+//! use inflector::Inflector;
+//! let camel_case_string: String = "some_string".to_camel_case();
+//! let is_camel_cased: bool= camel_case_string.is_camel_case();
+//! assert!(is_camel_cased == true);
+//! ```
+
+#[cfg(feature = "heavyweight")]
+extern crate regex;
+
+#[cfg(feature = "heavyweight")]
+#[macro_use] extern crate lazy_static;
+
+/// Provides case inflections
+/// - Camel case
+/// - Class case
+/// - Kebab case
+/// - Train case
+/// - Screaming snake case
+/// - Table case
+/// - Sentence case
+/// - Snake case
+/// - Pascal case
+pub mod cases;
+/// Provides number inflections
+/// - Ordinalize
+/// - Deordinalize
+pub mod numbers;
+/// Provides suffix inflections
+/// - Foreign key
+pub mod suffix;
+/// Provides string inflections
+/// - Deconstantize
+/// - Demodulize
+/// - Pluralize
+/// - Singularize
+#[cfg(feature = "heavyweight")]
+pub mod string;
+
+
+#[cfg(feature = "heavyweight")]
+use cases::classcase::to_class_case;
+#[cfg(feature = "heavyweight")]
+use cases::classcase::is_class_case;
+
+use cases::camelcase::to_camel_case;
+use cases::camelcase::is_camel_case;
+
+use cases::pascalcase::to_pascal_case;
+use cases::pascalcase::is_pascal_case;
+
+use cases::snakecase::to_snake_case;
+use cases::snakecase::is_snake_case;
+
+use cases::screamingsnakecase::to_screaming_snake_case;
+use cases::screamingsnakecase::is_screaming_snake_case;
+
+use cases::kebabcase::to_kebab_case;
+use cases::kebabcase::is_kebab_case;
+
+use cases::traincase::to_train_case;
+use cases::traincase::is_train_case;
+
+use cases::sentencecase::to_sentence_case;
+use cases::sentencecase::is_sentence_case;
+
+use cases::titlecase::to_title_case;
+use cases::titlecase::is_title_case;
+
+#[cfg(feature = "heavyweight")]
+use cases::tablecase::to_table_case;
+#[cfg(feature = "heavyweight")]
+use cases::tablecase::is_table_case;
+
+use numbers::ordinalize::ordinalize;
+use numbers::deordinalize::deordinalize;
+
+use suffix::foreignkey::to_foreign_key;
+use suffix::foreignkey::is_foreign_key;
+
+#[cfg(feature = "heavyweight")]
+use string::demodulize::demodulize;
+#[cfg(feature = "heavyweight")]
+use string::deconstantize::deconstantize;
+
+#[cfg(feature = "heavyweight")]
+use string::pluralize::to_plural;
+#[cfg(feature = "heavyweight")]
+use string::singularize::to_singular;
+
+#[allow(missing_docs)]
+pub trait Inflector {
+
+ fn to_camel_case(&self) -> String;
+ fn is_camel_case(&self) -> bool;
+
+ fn to_pascal_case(&self) -> String;
+ fn is_pascal_case(&self) -> bool;
+
+ fn to_snake_case(&self) -> String;
+ fn is_snake_case(&self) -> bool;
+
+ fn to_screaming_snake_case(&self) -> String;
+ fn is_screaming_snake_case(&self) -> bool;
+
+ fn to_kebab_case(&self) -> String;
+ fn is_kebab_case(&self) -> bool;
+
+ fn to_train_case(&self) -> String;
+ fn is_train_case(&self) -> bool;
+
+ fn to_sentence_case(&self) -> String;
+ fn is_sentence_case(&self) -> bool;
+
+ fn to_title_case(&self) -> String;
+ fn is_title_case(&self) -> bool;
+
+ fn ordinalize(&self) -> String;
+ fn deordinalize(&self) -> String;
+
+ fn to_foreign_key(&self) -> String;
+ fn is_foreign_key(&self) -> bool;
+
+ #[cfg(feature = "heavyweight")]
+ fn demodulize(&self) -> String;
+ #[cfg(feature = "heavyweight")]
+ fn deconstantize(&self) -> String;
+
+ #[cfg(feature = "heavyweight")]
+ fn to_class_case(&self) -> String;
+ #[cfg(feature = "heavyweight")]
+ fn is_class_case(&self) -> bool;
+
+ #[cfg(feature = "heavyweight")]
+ fn to_table_case(&self) -> String;
+ #[cfg(feature = "heavyweight")]
+ fn is_table_case(&self) -> bool;
+ #[cfg(feature = "heavyweight")]
+ fn to_plural(&self) -> String;
+ #[cfg(feature = "heavyweight")]
+ fn to_singular(&self) -> String;
+}
+
+
+#[allow(missing_docs)]
+pub trait InflectorNumbers {
+ fn ordinalize(&self) -> String;
+}
+
+
+macro_rules! define_implementations {
+ ( $slf:ident; $($imp_trait:ident => $typ:ident), *) => {
+ $(
+ #[inline]
+ fn $imp_trait(&$slf) -> $typ {
+ $imp_trait($slf)
+ }
+ )*
+ }
+}
+
+macro_rules! define_number_implementations {
+ ( $slf:ident; $($imp_trait:ident => $typ:ident), *) => {
+ $(
+ #[inline]
+ fn $imp_trait(&$slf) -> $typ {
+ $imp_trait(&$slf.to_string())
+ }
+ )*
+ }
+}
+
+macro_rules! define_gated_implementations {
+ ( $slf:ident; $($imp_trait:ident => $typ:ident), *) => {
+ $(
+ #[inline]
+ #[cfg(feature = "heavyweight")]
+ fn $imp_trait(&$slf) -> $typ {
+ $imp_trait($slf)
+ }
+ )*
+ }
+}
+
+macro_rules! implement_string_for {
+ ( $trt:ident; $($typ:ident), *) => {
+ $(
+ impl $trt for $typ {
+ define_implementations![self;
+ to_camel_case => String,
+ is_camel_case => bool,
+ to_pascal_case => String,
+ is_pascal_case => bool,
+ to_screaming_snake_case => String,
+ is_screaming_snake_case => bool,
+ to_snake_case => String,
+ is_snake_case => bool,
+ to_kebab_case => String,
+ is_kebab_case => bool,
+ to_train_case => String,
+ is_train_case => bool,
+ to_sentence_case => String,
+ is_sentence_case => bool,
+ to_title_case => String,
+ is_title_case => bool,
+ to_foreign_key => String,
+ is_foreign_key => bool,
+ ordinalize => String,
+ deordinalize => String
+ ];
+ define_gated_implementations![self;
+ to_class_case => String,
+ is_class_case => bool,
+ to_table_case => String,
+ is_table_case => bool,
+ to_plural => String,
+ to_singular => String,
+ demodulize => String,
+ deconstantize => String
+ ];
+ }
+ )*
+ }
+}
+
+macro_rules! implement_number_for {
+ ( $trt:ident; $($typ:ident), *) => {
+ $(
+ impl $trt for $typ {
+ define_number_implementations![self;
+ ordinalize => String
+ ];
+ }
+ )*
+ }
+}
+
+implement_string_for![
+ Inflector;
+ String, str
+];
+
+implement_number_for![
+ InflectorNumbers;
+ i8, i16, i32, i64, u8, u16, u32, u64, isize, usize, f32, f64
+];
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+ extern crate test;
+ use self::test::Bencher;
+ use ::Inflector;
+
+ macro_rules! benchmarks {
+ ( $($test_name:ident => $imp_trait:ident => $to_cast:expr), *) => {
+ $(
+ #[bench]
+ fn $test_name(b: &mut Bencher) {
+ b.iter(|| {
+ $to_cast.$imp_trait()
+ });
+ }
+ )*
+ }
+ }
+
+ benchmarks![
+ benchmark_str_to_camel => to_camel_case => "foo_bar",
+ benchmark_str_is_camel => is_camel_case => "fooBar",
+ benchmark_str_to_screaming_snake => to_screaming_snake_case => "fooBar",
+ benchmark_str_is_screaming_snake => is_screaming_snake_case => "FOO_BAR",
+ benchmark_str_to_snake => to_snake_case => "fooBar",
+ benchmark_str_is_snake => is_snake_case => "foo_bar",
+ benchmark_str_to_kebab => to_kebab_case => "fooBar",
+ benchmark_str_is_kebab => is_kebab_case => "foo-bar",
+ benchmark_str_to_train => to_train_case => "fooBar",
+ benchmark_str_is_train => is_train_case => "Foo-Bar",
+ benchmark_str_to_sentence => to_sentence_case => "fooBar",
+ benchmark_str_is_sentence => is_sentence_case => "Foo bar",
+ benchmark_str_to_title => to_title_case => "fooBar",
+ benchmark_str_is_title => is_title_case => "Foo Bar",
+ benchmark_str_ordinalize => ordinalize => "1",
+ benchmark_str_deordinalize => deordinalize => "1st",
+ benchmark_str_to_foreign_key => to_foreign_key => "Foo::Bar",
+ benchmark_str_is_foreign_key => is_foreign_key => "bar_id",
+ benchmark_string_to_camel => to_camel_case => "foo_bar".to_string(),
+ benchmark_string_is_camel => is_camel_case => "fooBar".to_string(),
+ benchmark_string_to_screaming_snake => to_screaming_snake_case => "fooBar".to_string(),
+ benchmark_string_is_screaming_snake => is_screaming_snake_case => "FOO_BAR".to_string(),
+ benchmark_string_to_snake => to_snake_case => "fooBar".to_string(),
+ benchmark_string_is_snake => is_snake_case => "foo_bar".to_string(),
+ benchmark_string_to_kebab => to_kebab_case => "fooBar".to_string(),
+ benchmark_string_is_kebab => is_kebab_case => "foo-bar".to_string(),
+ benchmark_string_to_train => to_train_case => "fooBar".to_string(),
+ benchmark_string_is_train => is_train_case => "Foo-Bar".to_string(),
+ benchmark_string_to_sentence => to_sentence_case => "fooBar".to_string(),
+ benchmark_string_is_sentence => is_sentence_case => "Foo bar".to_string(),
+ benchmark_string_to_title => to_title_case => "fooBar".to_string(),
+ benchmark_string_is_title => is_title_case => "Foo Bar".to_string(),
+ benchmark_string_ordinalize => ordinalize => "1".to_string(),
+ benchmark_string_deordinalize => deordinalize => "1st".to_string(),
+ benchmark_string_to_foreign_key => to_foreign_key => "Foo::Bar".to_string(),
+ benchmark_string_is_foreign_key => is_foreign_key => "bar_id".to_string()
+ ];
+
+ #[cfg(feature = "heavyweight")]
+ benchmarks![
+ benchmark_str_to_class => to_class_case => "foo",
+ benchmark_str_is_class => is_class_case => "Foo",
+ benchmark_str_to_table => to_table_case => "fooBar",
+ benchmark_str_is_table => is_table_case => "foo_bars",
+ benchmark_str_pluralize => to_plural => "crate",
+ benchmark_str_singular => to_singular => "crates",
+ benchmark_string_to_class => to_class_case => "foo".to_string(),
+ benchmark_string_is_class => is_class_case => "Foo".to_string(),
+ benchmark_string_to_table => to_table_case => "fooBar".to_string(),
+ benchmark_string_is_table => is_table_case => "foo_bars".to_string(),
+ benchmark_string_pluralize => to_plural => "crate".to_string(),
+ benchmark_string_singular => to_singular => "crates".to_string(),
+ benchmark_string_demodulize => demodulize => "Foo::Bar".to_string(),
+ benchmark_string_deconstantize => deconstantize => "Foo::Bar".to_string(),
+ benchmark_str_demodulize => demodulize => "Foo::Bar",
+ benchmark_str_deconstantize => deconstantize => "Foo::Bar"
+ ];
+}
diff --git a/src/numbers/deordinalize/mod.rs b/src/numbers/deordinalize/mod.rs
new file mode 100644
index 0000000..f64cce1
--- /dev/null
+++ b/src/numbers/deordinalize/mod.rs
@@ -0,0 +1,117 @@
+/// Deorginalizes a `&str`
+///
+/// ```
+/// use inflector::numbers::deordinalize::deordinalize;
+/// let mock_string: &str = "0.1";
+/// let expected_string: String = "0.1".to_owned();
+/// let asserted_string: String = deordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::deordinalize::deordinalize;
+/// let mock_string: &str = "-1st";
+/// let expected_string: String = "-1".to_owned();
+/// let asserted_string: String = deordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::deordinalize::deordinalize;
+/// let mock_string: &str = "0th";
+/// let expected_string: String = "0".to_owned();
+/// let asserted_string: String = deordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::deordinalize::deordinalize;
+/// let mock_string: &str = "1st";
+/// let expected_string: String = "1".to_owned();
+/// let asserted_string: String = deordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::deordinalize::deordinalize;
+/// let mock_string: &str = "2nd";
+/// let expected_string: String = "2".to_owned();
+/// let asserted_string: String = deordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::deordinalize::deordinalize;
+/// let mock_string: &str = "3rd";
+/// let expected_string: String = "3".to_owned();
+/// let asserted_string: String = deordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::deordinalize::deordinalize;
+/// let mock_string: &str = "9th";
+/// let expected_string: String = "9".to_owned();
+/// let asserted_string: String = deordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::deordinalize::deordinalize;
+/// let mock_string: &str = "12th";
+/// let expected_string: String = "12".to_owned();
+/// let asserted_string: String = deordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::deordinalize::deordinalize;
+/// let mock_string: &str = "12000th";
+/// let expected_string: String = "12000".to_owned();
+/// let asserted_string: String = deordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::deordinalize::deordinalize;
+/// let mock_string: &str = "12001th";
+/// let expected_string: String = "12001".to_owned();
+/// let asserted_string: String = deordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::deordinalize::deordinalize;
+/// let mock_string: &str = "12002nd";
+/// let expected_string: String = "12002".to_owned();
+/// let asserted_string: String = deordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::deordinalize::deordinalize;
+/// let mock_string: &str = "12003rd";
+/// let expected_string: String = "12003".to_owned();
+/// let asserted_string: String = deordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::deordinalize::deordinalize;
+/// let mock_string: &str = "12004th";
+/// let expected_string: String = "12004".to_owned();
+/// let asserted_string: String = deordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn deordinalize(non_ordinalized_string: &str) -> String {
+ if non_ordinalized_string.contains('.') {
+ non_ordinalized_string.to_owned()
+ } else {
+ non_ordinalized_string.trim_end_matches("st")
+ .trim_end_matches("nd")
+ .trim_end_matches("rd")
+ .trim_end_matches("th")
+ .to_owned()
+ }
+}
diff --git a/src/numbers/mod.rs b/src/numbers/mod.rs
new file mode 100644
index 0000000..f28704f
--- /dev/null
+++ b/src/numbers/mod.rs
@@ -0,0 +1,9 @@
+#![deny(warnings)]
+/// Provides ordinalization of a string.
+///
+/// Example string "1" becomes "1st"
+pub mod ordinalize;
+/// Provides deordinalization of a string.
+///
+/// Example string "1st" becomes "1"
+pub mod deordinalize;
diff --git a/src/numbers/ordinalize/mod.rs b/src/numbers/ordinalize/mod.rs
new file mode 100644
index 0000000..82b0d2d
--- /dev/null
+++ b/src/numbers/ordinalize/mod.rs
@@ -0,0 +1,147 @@
+/// Orginalizes a `&str`
+///
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "a";
+/// let expected_string: String = "a".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "0.1";
+/// let expected_string: String = "0.1".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "-1";
+/// let expected_string: String = "-1st".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "0";
+/// let expected_string: String = "0th".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "1";
+/// let expected_string: String = "1st".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "2";
+/// let expected_string: String = "2nd".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "3";
+/// let expected_string: String = "3rd".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "9";
+/// let expected_string: String = "9th".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "12";
+/// let expected_string: String = "12th".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "12000";
+/// let expected_string: String = "12000th".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "12001";
+/// let expected_string: String = "12001st".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "12002";
+/// let expected_string: String = "12002nd".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "12003";
+/// let expected_string: String = "12003rd".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::numbers::ordinalize::ordinalize;
+/// let mock_string: &str = "12004";
+/// let expected_string: String = "12004th".to_owned();
+/// let asserted_string: String = ordinalize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn ordinalize(non_ordinalized_string: &str) -> String {
+ let chars: Vec<char> = non_ordinalized_string.clone().chars().collect();
+ let last_number: char = chars[chars.len() - 1];
+ if is_ordinalizable(last_number) {
+ return non_ordinalized_string.to_owned();
+ }
+ if chars.len() > 1 {
+ if second_last_number_is_one(chars) {
+ return format!("{}{}", non_ordinalized_string, "th");
+ } else if string_contains_decimal(non_ordinalized_string.to_owned()) {
+ return non_ordinalized_string.to_owned();
+ }
+ }
+ match last_number {
+ '1' => format!("{}{}", non_ordinalized_string, "st"),
+ '2' => format!("{}{}", non_ordinalized_string, "nd"),
+ '3' => format!("{}{}", non_ordinalized_string, "rd"),
+ _ => format!("{}{}", non_ordinalized_string, "th"),
+ }
+}
+
+fn is_ordinalizable(last_number: char) -> bool {
+ !last_number.is_numeric()
+}
+
+fn second_last_number_is_one(chars: Vec<char>) -> bool {
+ let second_last_number: char = chars[chars.len() - 2];
+ second_last_number == '1'
+}
+
+fn string_contains_decimal(non_ordinalized_string: String) -> bool {
+ non_ordinalized_string.contains('.')
+}
diff --git a/src/string/constants/mod.rs b/src/string/constants/mod.rs
new file mode 100644
index 0000000..0ba4e42
--- /dev/null
+++ b/src/string/constants/mod.rs
@@ -0,0 +1,225 @@
+pub const UNACCONTABLE_WORDS: [&'static str; 202] = ["accommodation",
+ "adulthood",
+ "advertising",
+ "advice",
+ "aggression",
+ "aid",
+ "air",
+ "aircraft",
+ "alcohol",
+ "anger",
+ "applause",
+ "arithmetic",
+ "assistance",
+ "athletics",
+
+ "bacon",
+ "baggage",
+ "beef",
+ "biology",
+ "blood",
+ "botany",
+ "bread",
+ "butter",
+
+ "carbon",
+ "cardboard",
+ "cash",
+ "chalk",
+ "chaos",
+ "chess",
+ "crossroads",
+ "countryside",
+
+ "dancing",
+ "deer",
+ "dignity",
+ "dirt",
+ "dust",
+
+ "economics",
+ "education",
+ "electricity",
+ "engineering",
+ "enjoyment",
+ "envy",
+ "equipment",
+ "ethics",
+ "evidence",
+ "evolution",
+
+ "fame",
+ "fiction",
+ "flour",
+ "flu",
+ "food",
+ "fuel",
+ "fun",
+ "furniture",
+
+ "gallows",
+ "garbage",
+ "garlic",
+ "genetics",
+ "gold",
+ "golf",
+ "gossip",
+ "grammar",
+ "gratitude",
+ "grief",
+ "guilt",
+ "gymnastics",
+
+ "happiness",
+ "hardware",
+ "harm",
+ "hate",
+ "hatred",
+ "health",
+ "heat",
+ "help",
+ "homework",
+ "honesty",
+ "honey",
+ "hospitality",
+ "housework",
+ "humour",
+ "hunger",
+ "hydrogen",
+
+ "ice",
+ "importance",
+ "inflation",
+ "information",
+ "innocence",
+ "iron",
+ "irony",
+
+ "jam",
+ "jewelry",
+ "judo",
+
+ "karate",
+ "knowledge",
+
+ "lack",
+ "laughter",
+ "lava",
+ "leather",
+ "leisure",
+ "lightning",
+ "linguine",
+ "linguini",
+ "linguistics",
+ "literature",
+ "litter",
+ "livestock",
+ "logic",
+ "loneliness",
+ "luck",
+ "luggage",
+
+ "macaroni",
+ "machinery",
+ "magic",
+ "management",
+ "mankind",
+ "marble",
+ "mathematics",
+ "mayonnaise",
+ "measles",
+ "methane",
+ "milk",
+ "money",
+ "mud",
+ "music",
+ "mumps",
+
+ "nature",
+ "news",
+ "nitrogen",
+ "nonsense",
+ "nurture",
+ "nutrition",
+
+ "obedience",
+ "obesity",
+ "oxygen",
+
+ "pasta",
+ "patience",
+ "physics",
+ "poetry",
+ "pollution",
+ "poverty",
+ "pride",
+ "psychology",
+ "publicity",
+ "punctuation",
+
+ "quartz",
+
+ "racism",
+ "relaxation",
+ "reliability",
+ "research",
+ "respect",
+ "revenge",
+ "rice",
+ "rubbish",
+ "rum",
+
+ "safety",
+ "scenery",
+ "seafood",
+ "seaside",
+ "series",
+ "shame",
+ "sheep",
+ "shopping",
+ "sleep",
+ "smoke",
+ "smoking",
+ "snow",
+ "soap",
+ "software",
+ "soil",
+ "spaghetti",
+ "species",
+ "steam",
+ "stuff",
+ "stupidity",
+ "sunshine",
+ "symmetry",
+
+ "tennis",
+ "thirst",
+ "thunder",
+ "timber",
+ "traffic",
+ "transportation",
+ "trust",
+
+ "underwear",
+ "unemployment",
+ "unity",
+
+ "validity",
+ "veal",
+ "vegetation",
+ "vegetarianism",
+ "vengeance",
+ "violence",
+ "vitality",
+
+ "warmth",
+ "wealth",
+ "weather",
+ "welfare",
+ "wheat",
+ "wildlife",
+ "wisdom",
+ "yoga",
+
+ "zinc",
+ "zoology"];
diff --git a/src/string/deconstantize/mod.rs b/src/string/deconstantize/mod.rs
new file mode 100644
index 0000000..5b106e5
--- /dev/null
+++ b/src/string/deconstantize/mod.rs
@@ -0,0 +1,50 @@
+#[cfg(feature = "heavyweight")]
+use cases::classcase::to_class_case;
+
+#[cfg(feature = "heavyweight")]
+/// Deconstantizes a `&str`
+///
+/// ```
+/// use inflector::string::deconstantize::deconstantize;
+/// let mock_string: &str = "Bar";
+/// let expected_string: String = "".to_owned();
+/// let asserted_string: String = deconstantize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::deconstantize::deconstantize;
+/// let mock_string: &str = "::Bar";
+/// let expected_string: String = "".to_owned();
+/// let asserted_string: String = deconstantize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::deconstantize::deconstantize;
+/// let mock_string: &str = "Foo::Bar";
+/// let expected_string: String = "Foo".to_owned();
+/// let asserted_string: String = deconstantize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::deconstantize::deconstantize;
+/// let mock_string: &str = "Test::Foo::Bar";
+/// let expected_string: String = "Foo".to_owned();
+/// let asserted_string: String = deconstantize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn deconstantize(non_deconstantized_string: &str) -> String {
+ if non_deconstantized_string.contains("::") {
+ let split_string: Vec<&str> = non_deconstantized_string.split("::").collect();
+ if split_string.len() > 1 {
+ to_class_case(split_string[split_string.len() - 2])
+ } else {
+ "".to_owned()
+ }
+ } else {
+ "".to_owned()
+ }
+}
diff --git a/src/string/demodulize/mod.rs b/src/string/demodulize/mod.rs
new file mode 100644
index 0000000..5d4bd77
--- /dev/null
+++ b/src/string/demodulize/mod.rs
@@ -0,0 +1,46 @@
+#[cfg(feature = "heavyweight")]
+use cases::classcase::to_class_case;
+
+#[cfg(feature = "heavyweight")]
+/// Demodulize a `&str`
+///
+/// ```
+/// use inflector::string::demodulize::demodulize;
+/// let mock_string: &str = "Bar";
+/// let expected_string: String = "Bar".to_owned();
+/// let asserted_string: String = demodulize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::demodulize::demodulize;
+/// let mock_string: &str = "::Bar";
+/// let expected_string: String = "Bar".to_owned();
+/// let asserted_string: String = demodulize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::demodulize::demodulize;
+/// let mock_string: &str = "Foo::Bar";
+/// let expected_string: String = "Bar".to_owned();
+/// let asserted_string: String = demodulize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::demodulize::demodulize;
+/// let mock_string: &str = "Test::Foo::Bar";
+/// let expected_string: String = "Bar".to_owned();
+/// let asserted_string: String = demodulize(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn demodulize(non_demodulize_string: &str) -> String {
+ if non_demodulize_string.contains("::") {
+ let split_string: Vec<&str> = non_demodulize_string.split("::").collect();
+ to_class_case(split_string[split_string.len() - 1])
+ } else {
+ non_demodulize_string.to_owned()
+ }
+}
diff --git a/src/string/mod.rs b/src/string/mod.rs
new file mode 100644
index 0000000..7270288
--- /dev/null
+++ b/src/string/mod.rs
@@ -0,0 +1,23 @@
+#![deny(warnings)]
+/// Provides demodulize a string.
+///
+/// Example string `Foo::Bar` becomes `Bar`
+#[cfg(feature = "heavyweight")]
+pub mod demodulize;
+/// Provides deconstantizea string.
+///
+/// Example string `Foo::Bar` becomes `Foo`
+#[cfg(feature = "heavyweight")]
+pub mod deconstantize;
+/// Provides conversion to plural strings.
+///
+/// Example string `FooBar` -> `FooBars`
+#[cfg(feature = "heavyweight")]
+pub mod pluralize;
+/// Provides conversion to singular strings.
+///
+/// Example string `FooBars` -> `FooBar`
+#[cfg(feature = "heavyweight")]
+pub mod singularize;
+
+mod constants;
diff --git a/src/string/pluralize/mod.rs b/src/string/pluralize/mod.rs
new file mode 100644
index 0000000..1caeea5
--- /dev/null
+++ b/src/string/pluralize/mod.rs
@@ -0,0 +1,194 @@
+#![deny(warnings)]
+use regex::Regex;
+use string::constants::UNACCONTABLE_WORDS;
+
+macro_rules! add_rule{
+ ($r:ident, $rule:expr => $replace:expr) => {
+ $r.push((Regex::new($rule).unwrap(), $replace));
+ }
+}
+
+macro_rules! rules{
+ ($r:ident; $($rule:expr => $replace:expr), *) => {
+ $(
+ add_rule!{$r, $rule => $replace}
+ )*
+ }
+}
+
+
+lazy_static!{
+ static ref RULES: Vec<(Regex, &'static str)> = {
+ let mut r = Vec::with_capacity(24);
+ rules![r;
+ r"(\w*)s$" => "s",
+ r"(\w*([^aeiou]ese))$" => "",
+ r"(\w*(ax|test))is$" => "es",
+ r"(\w*(alias|[^aou]us|tlas|gas|ris))$" => "es",
+ r"(\w*(e[mn]u))s?$" => "s",
+ r"(\w*([^l]ias|[aeiou]las|[emjzr]as|[iu]am))$" => "",
+ r"(\w*(alumn|syllab|octop|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat))(?:us|i)$" => "i",
+ r"(\w*(alumn|alg|vertebr))(?:a|ae)$" => "ae",
+ r"(\w*(seraph|cherub))(?:im)?$" => "im",
+ r"(\w*(her|at|gr))o$" => "oes",
+ r"(\w*(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor))(?:a|um)$" => "a",
+ r"(\w*(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat))(?:a|on)$" => "a",
+ r"(\w*)sis$" => "ses",
+ r"(\w*(kni|wi|li))fe$" => "ves",
+ r"(\w*(ar|l|ea|eo|oa|hoo))f$" => "ves",
+ r"(\w*([^aeiouy]|qu))y$" => "ies",
+ r"(\w*([^ch][ieo][ln]))ey$" => "ies",
+ r"(\w*(x|ch|ss|sh|zz)es)$" => "",
+ r"(\w*(x|ch|ss|sh|zz))$" => "es",
+ r"(\w*(matr|cod|mur|sil|vert|ind|append))(?:ix|ex)$" => "ices",
+ r"(\w*(m|l)(?:ice|ouse))$" => "ice",
+ r"(\w*(pe)(?:rson|ople))$" => "ople",
+ r"(\w*(child))(?:ren)?$" => "ren",
+ r"(\w*eaux)$" => ""
+ ];
+ r
+ };
+}
+
+macro_rules! special_cases{
+ ($s:ident, $($singular: expr => $plural:expr), *) => {
+ match &$s[..] {
+ $(
+ $singular => {
+ return $plural.to_owned();
+ },
+ )*
+ _ => ()
+ }
+ }
+}
+
+
+/// Converts a `&str` to pluralized `String`
+///
+/// ```
+/// use inflector::string::pluralize::to_plural;
+/// let mock_string: &str = "foo_bar";
+/// let expected_string: String = "foo_bars".to_owned();
+/// let asserted_string: String = to_plural(mock_string);
+/// assert_eq!(asserted_string, expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::pluralize::to_plural;
+/// let mock_string: &str = "ox";
+/// let expected_string: String = "oxen".to_owned();
+/// let asserted_string: String = to_plural(mock_string);
+/// assert_eq!(asserted_string, expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::pluralize::to_plural;
+/// let mock_string: &str = "crate";
+/// let expected_string: String = "crates".to_owned();
+/// let asserted_string: String = to_plural(mock_string);
+/// assert_eq!(asserted_string, expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::pluralize::to_plural;
+/// let mock_string: &str = "boxes";
+/// let expected_string: String = "boxes".to_owned();
+/// let asserted_string: String = to_plural(mock_string);
+/// assert_eq!(asserted_string, expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::pluralize::to_plural;
+/// let mock_string: &str = "vengeance";
+/// let expected_string: String = "vengeance".to_owned();
+/// let asserted_string: String = to_plural(mock_string);
+/// assert_eq!(asserted_string, expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::pluralize::to_plural;
+/// let mock_string: &str = "yoga";
+/// let expected_string: String = "yoga".to_owned();
+/// let asserted_string: String = to_plural(mock_string);
+/// assert_eq!(asserted_string, expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::pluralize::to_plural;
+/// let mock_string: &str = "geometry";
+/// let expected_string: String = "geometries".to_owned();
+/// let asserted_string: String = to_plural(mock_string);
+/// assert_eq!(asserted_string, expected_string);
+///
+/// ```
+///
+pub fn to_plural(non_plural_string: &str) -> String {
+ if UNACCONTABLE_WORDS.contains(&non_plural_string.as_ref()) {
+ non_plural_string.to_owned()
+ } else {
+ special_cases![non_plural_string,
+ "ox" => "oxen",
+ "man" => "men",
+ "woman" => "women",
+ "die" => "dice",
+ "yes" => "yeses",
+ "foot" => "feet",
+ "eave" => "eaves",
+ "goose" => "geese",
+ "tooth" => "teeth",
+ "quiz" => "quizzes"
+ ];
+ for &(ref rule, replace) in RULES.iter().rev() {
+ if let Some(c) = rule.captures(&non_plural_string) {
+ if let Some(c) = c.get(1) {
+ return format!("{}{}", c.as_str(), replace);
+ }
+ }
+ }
+
+ format!("{}s", non_plural_string)
+ }
+}
+
+
+#[cfg(test)]
+mod tests {
+
+ macro_rules! as_item {
+ ($i:item) => { $i };
+ }
+
+ macro_rules! make_tests{
+ ($($singular:ident => $plural:ident); *) =>{
+ $(
+ as_item! {
+ #[test]
+ fn $singular(){
+ assert_eq!(
+ stringify!($plural),
+ super::to_plural(stringify!($singular))
+ );
+ }
+ }
+ )*
+ }
+ }
+
+ #[test]
+ fn boxes() {
+ assert_eq!("boxes", super::to_plural("box"));
+ }
+
+ make_tests!{
+ geometry => geometries;
+ ox => oxen;
+ woman => women;
+ test => tests;
+ axis => axes;
+ knife => knives;
+ agendum => agenda;
+ elf => elves;
+ zoology => zoology
+ }
+}
diff --git a/src/string/singularize/mod.rs b/src/string/singularize/mod.rs
new file mode 100644
index 0000000..60e0b51
--- /dev/null
+++ b/src/string/singularize/mod.rs
@@ -0,0 +1,189 @@
+use regex::Regex;
+use string::constants::UNACCONTABLE_WORDS;
+
+macro_rules! special_cases{
+ ($s:ident, $($singular: expr => $plural:expr), *) => {
+ match &$s[..] {
+ $(
+ $singular => {
+ return $plural.to_owned();
+ },
+ )*
+ _ => ()
+ }
+ }
+}
+
+
+/// Converts a `&str` to singularized `String`
+///
+/// ```
+/// use inflector::string::singularize::to_singular;
+/// let mock_string: &str = "foo_bars";
+/// let expected_string: String = "foo_bar".to_owned();
+/// let asserted_string: String = to_singular(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::singularize::to_singular;
+/// let mock_string: &str = "oxen";
+/// let expected_string: String = "ox".to_owned();
+/// let asserted_string: String = to_singular(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::singularize::to_singular;
+/// let mock_string: &str = "crates";
+/// let expected_string: String = "crate".to_owned();
+/// let asserted_string: String = to_singular(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::singularize::to_singular;
+/// let mock_string: &str = "oxen";
+/// let expected_string: String = "ox".to_owned();
+/// let asserted_string: String = to_singular(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::singularize::to_singular;
+/// let mock_string: &str = "boxes";
+/// let expected_string: String = "box".to_owned();
+/// let asserted_string: String = to_singular(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::singularize::to_singular;
+/// let mock_string: &str = "vengeance";
+/// let expected_string: String = "vengeance".to_owned();
+/// let asserted_string: String = to_singular(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::string::singularize::to_singular;
+/// let mock_string: &str = "yoga";
+/// let expected_string: String = "yoga".to_owned();
+/// let asserted_string: String = to_singular(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+///
+pub fn to_singular(non_singular_string: &str) -> String {
+ if UNACCONTABLE_WORDS.contains(&non_singular_string.as_ref()) {
+ non_singular_string.to_owned()
+ } else {
+ special_cases![non_singular_string,
+ "oxen" => "ox",
+ "boxes" => "box",
+ "men" => "man",
+ "women" => "woman",
+ "dice" => "die",
+ "yeses" => "yes",
+ "feet" => "foot",
+ "eaves" => "eave",
+ "geese" => "goose",
+ "teeth" => "tooth",
+ "quizzes" => "quiz"
+ ];
+ for &(ref rule, replace) in RULES.iter().rev() {
+ if let Some(captures) = rule.captures(&non_singular_string) {
+ if let Some(c) = captures.get(1) {
+ let mut buf = String::new();
+ captures.expand(&format!("{}{}", c.as_str(), replace), &mut buf);
+ return buf;
+ }
+ }
+ }
+
+ format!("{}", non_singular_string)
+ }
+}
+
+macro_rules! add_rule{
+ ($r:ident, $rule:expr => $replace:expr) => {
+ $r.push((Regex::new($rule).unwrap(), $replace));
+ }
+}
+
+macro_rules! rules{
+ ($r:ident; $($rule:expr => $replace:expr), *) => {
+ $(
+ add_rule!{$r, $rule => $replace}
+ )*
+ }
+}
+
+
+lazy_static!{
+ static ref RULES: Vec<(Regex, &'static str)> = {
+ let mut r = Vec::with_capacity(27);
+ rules![r;
+ r"(\w*)s$" => "",
+ r"(\w*)(ss)$" => "$2",
+ r"(n)ews$" => "ews",
+ r"(\w*)(o)es$" => "",
+ r"(\w*)([ti])a$" => "um",
+ r"((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$" => "sis",
+ r"(^analy)(sis|ses)$" => "sis",
+ r"(\w*)([^f])ves$" => "fe",
+ r"(\w*)(hive)s$" => "",
+ r"(\w*)(tive)s$" => "",
+ r"(\w*)([lr])ves$" => "f",
+ r"(\w*([^aeiouy]|qu))ies$" => "y",
+ r"(s)eries$" => "eries",
+ r"(m)ovies$" => "ovie",
+ r"(\w*)(x|ch|ss|sh)es$" => "$2",
+ r"(m|l)ice$" => "ouse",
+ r"(bus)(es)?$" => "",
+ r"(shoe)s$" => "",
+ r"(cris|test)(is|es)$" => "is",
+ r"^(a)x[ie]s$" => "xis",
+ r"(octop|vir)(us|i)$" => "us",
+ r"(alias|status)(es)?$" => "",
+ r"^(ox)en" => "",
+ r"(vert|ind)ices$" => "ex",
+ r"(matr)ices$" => "ix",
+ r"(quiz)zes$" => "",
+ r"(database)s$" => ""
+ ];
+ r
+ };
+}
+
+#[test]
+fn singularize_ies_suffix() {
+ assert_eq!("reply", to_singular("replies"));
+ assert_eq!("lady", to_singular("ladies"));
+ assert_eq!("soliloquy", to_singular("soliloquies"));
+}
+
+#[test]
+fn singularize_ss_suffix() {
+ assert_eq!("glass", to_singular("glass"));
+ assert_eq!("access", to_singular("access"));
+ assert_eq!("glass", to_singular("glasses"));
+ assert_eq!("witch", to_singular("witches"));
+ assert_eq!("dish", to_singular("dishes"));
+}
+
+#[test]
+fn singularize_string_if_a_regex_will_match() {
+ let expected_string: String = "ox".to_owned();
+ let asserted_string: String = to_singular("oxen");
+ assert!(expected_string == asserted_string);
+
+}
+
+#[test]
+fn singularize_string_returns_none_option_if_no_match() {
+ let expected_string: String = "bacon".to_owned();
+ let asserted_string: String = to_singular("bacon");
+
+ assert!(expected_string == asserted_string);
+}
diff --git a/src/suffix/foreignkey/mod.rs b/src/suffix/foreignkey/mod.rs
new file mode 100644
index 0000000..e46696d
--- /dev/null
+++ b/src/suffix/foreignkey/mod.rs
@@ -0,0 +1,139 @@
+use cases::snakecase::to_snake_case;
+
+/// Converts a `&str` to a `foreign_key`
+///
+/// ```
+/// use inflector::suffix::foreignkey::to_foreign_key;
+/// let mock_string: &str = "foo_bar";
+/// let expected_string: String = "foo_bar_id".to_owned();
+/// let asserted_string: String = to_foreign_key(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::suffix::foreignkey::to_foreign_key;
+/// let mock_string: &str = "Foo bar";
+/// let expected_string: String = "foo_bar_id".to_owned();
+/// let asserted_string: String = to_foreign_key(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::suffix::foreignkey::to_foreign_key;
+/// let mock_string: &str = "Foo Bar";
+/// let expected_string: String = "foo_bar_id".to_owned();
+/// let asserted_string: String = to_foreign_key(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::suffix::foreignkey::to_foreign_key;
+/// let mock_string: &str = "Foo::Bar";
+/// let expected_string: String = "bar_id".to_owned();
+/// let asserted_string: String = to_foreign_key(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::suffix::foreignkey::to_foreign_key;
+/// let mock_string: &str = "Test::Foo::Bar";
+/// let expected_string: String = "bar_id".to_owned();
+/// let asserted_string: String = to_foreign_key(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::suffix::foreignkey::to_foreign_key;
+/// let mock_string: &str = "FooBar";
+/// let expected_string: String = "foo_bar_id".to_owned();
+/// let asserted_string: String = to_foreign_key(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::suffix::foreignkey::to_foreign_key;
+/// let mock_string: &str = "fooBar";
+/// let expected_string: String = "foo_bar_id".to_owned();
+/// let asserted_string: String = to_foreign_key(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+/// use inflector::suffix::foreignkey::to_foreign_key;
+/// let mock_string: &str = "fooBar3";
+/// let expected_string: String = "foo_bar_3_id".to_owned();
+/// let asserted_string: String = to_foreign_key(mock_string);
+/// assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_foreign_key(non_foreign_key_string: &str) -> String {
+ if non_foreign_key_string.contains("::") {
+ let split_string: Vec<&str> = non_foreign_key_string.split("::").collect();
+ safe_convert(split_string[split_string.len() - 1])
+ } else {
+ safe_convert(non_foreign_key_string)
+ }
+}
+fn safe_convert(safe_string: &str) -> String {
+ let snake_cased: String = to_snake_case(safe_string);
+ if snake_cased.ends_with("_id") {
+ snake_cased
+ } else {
+ format!("{}{}", snake_cased, "_id")
+ }
+}
+
+/// Determines if a `&str` is a `foreign_key`
+///
+/// ```
+/// use inflector::suffix::foreignkey::is_foreign_key;
+/// let mock_string: &str = "Foo bar string that is really really long";
+/// let asserted_bool: bool = is_foreign_key(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::suffix::foreignkey::is_foreign_key;
+/// let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+/// let asserted_bool: bool = is_foreign_key(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::suffix::foreignkey::is_foreign_key;
+/// let mock_string: &str = "FooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_foreign_key(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::suffix::foreignkey::is_foreign_key;
+/// let mock_string: &str = "Foo Bar Is A Really Really Long String";
+/// let asserted_bool: bool = is_foreign_key(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::suffix::foreignkey::is_foreign_key;
+/// let mock_string: &str = "fooBarIsAReallyReallyLongString";
+/// let asserted_bool: bool = is_foreign_key(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::suffix::foreignkey::is_foreign_key;
+/// let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+/// let asserted_bool: bool = is_foreign_key(mock_string);
+/// assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+/// use inflector::suffix::foreignkey::is_foreign_key;
+/// let mock_string: &str = "foo_bar_string_that_is_really_really_long_id";
+/// let asserted_bool: bool = is_foreign_key(mock_string);
+/// assert!(asserted_bool == true);
+///
+/// ```
+pub fn is_foreign_key(test_string: &str) -> bool {
+ to_foreign_key(test_string.clone()) == test_string
+}
diff --git a/src/suffix/mod.rs b/src/suffix/mod.rs
new file mode 100644
index 0000000..2083cd5
--- /dev/null
+++ b/src/suffix/mod.rs
@@ -0,0 +1,5 @@
+#![deny(warnings)]
+/// Provides foreign key conversion for String.
+///
+/// Example string `foo` becomes `foo_id`
+pub mod foreignkey;
diff --git a/tests/lib.rs b/tests/lib.rs
new file mode 100644
index 0000000..62d77f4
--- /dev/null
+++ b/tests/lib.rs
@@ -0,0 +1,162 @@
+#![deny(warnings)]
+extern crate inflector;
+
+use inflector::Inflector;
+use inflector::InflectorNumbers;
+
+macro_rules! str_tests {
+ ( $($test_name:ident => $imp_trait:ident => $to_cast:expr => $casted:expr), *) => {
+ $(
+ #[test]
+ fn $test_name() {
+ assert_eq!($to_cast.$imp_trait(), $casted)
+ }
+ )*
+ }
+}
+
+macro_rules! string_tests {
+ ( $($test_name:ident => $imp_trait:ident => $to_cast:expr => $casted:expr), *) => {
+ $(
+ #[test]
+ fn $test_name() {
+ assert_eq!($to_cast.to_string().$imp_trait(), $casted)
+ }
+ )*
+ }
+}
+
+macro_rules! number_tests {
+ ( $($test_name:ident => $imp_trait:ident => $typ:ident => $to_cast:expr => $casted:expr), *) => {
+ $(
+ #[test]
+ fn $test_name() {
+ let to_cast: $typ = $to_cast;
+ assert_eq!(to_cast.$imp_trait(), $casted)
+ }
+ )*
+ }
+}
+
+macro_rules! gated_str_tests {
+ ( $($test_name:ident => $imp_trait:ident => $to_cast:expr => $casted:expr), *) => {
+ $(
+ #[test]
+ #[cfg(feature = "heavyweight")]
+ fn $test_name() {
+ assert_eq!($to_cast.$imp_trait(), $casted)
+ }
+ )*
+ }
+}
+
+macro_rules! gated_string_tests {
+ ( $($test_name:ident => $imp_trait:ident => $to_cast:expr => $casted:expr), *) => {
+ $(
+ #[test]
+ #[cfg(feature = "heavyweight")]
+ fn $test_name() {
+ assert_eq!($to_cast.to_string().$imp_trait(), $casted)
+ }
+ )*
+ }
+}
+
+str_tests![
+ str_to_camel => to_camel_case => "foo_bar" => "fooBar".to_string(),
+ str_is_camel => is_camel_case => "fooBar" => true,
+ str_is_not_camel => is_camel_case => "foo_bar" => false,
+ str_to_screaming_snake => to_screaming_snake_case => "fooBar" => "FOO_BAR".to_string(),
+ str_is_screaming_snake => is_screaming_snake_case => "FOO_BAR" => true,
+ str_is_not_screaming_snake => is_screaming_snake_case => "foo_bar" => false,
+ str_to_snake => to_snake_case => "fooBar" => "foo_bar".to_string(),
+ str_is_snake => is_snake_case => "foo_bar" => true,
+ str_is_not_snake => is_snake_case => "fooBar" => false,
+ str_to_kebab => to_kebab_case => "fooBar" => "foo-bar".to_string(),
+ str_is_kebab => is_kebab_case => "foo-bar" => true,
+ str_is_not_kebab => is_kebab_case => "fooBar" => false,
+ str_to_train => to_train_case => "fooBar" => "Foo-Bar".to_string(),
+ str_is_train => is_train_case => "Foo-Bar" => true,
+ str_is_not_train => is_train_case => "FOO-Bar" => false,
+ str_to_sentence => to_sentence_case => "fooBar" => "Foo bar".to_string(),
+ str_is_sentence => is_sentence_case => "Foo bar" => true,
+ str_is_not_sentence => is_sentence_case => "foo_bar" => false,
+ str_to_title => to_title_case => "fooBar" => "Foo Bar".to_string(),
+ str_is_title => is_title_case => "Foo Bar" => true,
+ str_is_not_title => is_title_case => "Foo_Bar" => false,
+ str_ordinalize => ordinalize => "1" => "1st".to_string(),
+ str_deordinalize => deordinalize => "1st" => "1".to_string(),
+ str_to_foreign_key => to_foreign_key => "Foo::Bar" => "bar_id".to_string(),
+ str_is_foreign_key => is_foreign_key => "bar_id" => true,
+ str_is_not_foreign_key => is_foreign_key => "bar" => false
+];
+
+gated_str_tests![
+ str_to_class_case => to_class_case => "foo" => "Foo".to_string(),
+ str_is_class_case => is_class_case => "Foo" => true,
+ str_is_not_class_case => is_class_case => "foo" => false,
+ str_to_table => to_table_case => "fooBar" => "foo_bars".to_string(),
+ str_is_table => is_table_case => "foo_bars" => true,
+ str_is_not_table => is_table_case => "fooBars" => false,
+ str_pluralize => to_plural => "crate" => "crates".to_string(),
+ str_singular => to_singular => "crates" => "crate".to_string(),
+ str_demodulize => demodulize => "Foo::Bar" => "Bar".to_string(),
+ str_deconstantize => deconstantize => "Foo::Bar" => "Foo".to_string()
+];
+
+string_tests![
+ string_to_camel => to_camel_case => "foo_bar".to_string() => "fooBar".to_string(),
+ string_is_camel => is_camel_case => "fooBar".to_string() => true,
+ string_is_not_camel => is_camel_case => "foo_bar".to_string() => false,
+ string_to_screaming_snake => to_screaming_snake_case => "fooBar".to_string() => "FOO_BAR".to_string(),
+ string_is_screaming_snake => is_screaming_snake_case => "FOO_BAR".to_string() => true,
+ string_is_not_screaming_snake => is_screaming_snake_case => "foo_bar".to_string() => false,
+ string_to_snake => to_snake_case => "fooBar".to_string() => "foo_bar".to_string(),
+ string_is_snake => is_snake_case => "foo_bar".to_string() => true,
+ string_is_not_snake => is_snake_case => "fooBar".to_string() => false,
+ string_to_kebab => to_kebab_case => "fooBar".to_string() => "foo-bar".to_string(),
+ string_is_kebab => is_kebab_case => "foo-bar".to_string() => true,
+ string_is_not_kebab => is_kebab_case => "fooBar".to_string() => false,
+ string_to_train => to_train_case => "fooBar".to_string() => "Foo-Bar".to_string(),
+ string_is_train => is_train_case => "Foo-Bar".to_string() => true,
+ string_is_not_train => is_train_case => "foo-Bar".to_string() => false,
+ string_to_sentence => to_sentence_case => "fooBar".to_string() => "Foo bar".to_string(),
+ string_is_sentence => is_sentence_case => "Foo bar".to_string() => true,
+ string_is_not_sentence => is_sentence_case => "fooBar".to_string() => false,
+ string_to_title => to_title_case => "fooBar".to_string() => "Foo Bar".to_string(),
+ string_is_title => is_title_case => "Foo Bar".to_string() => true,
+ string_is_not_title => is_title_case => "fooBar".to_string() => false,
+ string_ordinalize => ordinalize => "1".to_string() => "1st".to_string(),
+ string_deordinalize => deordinalize => "1st".to_string() => "1".to_string(),
+ string_to_foreign_key => to_foreign_key => "Foo::Bar".to_string() => "bar_id".to_string(),
+ string_is_foreign_key => is_foreign_key => "bar_id".to_string() => true,
+ string_is_not_foreign_key => is_foreign_key => "bar".to_string() => false
+];
+
+gated_string_tests![
+ string_to_class_case => to_class_case => "foo".to_string() => "Foo".to_string(),
+ string_is_class_case => is_class_case => "Foo".to_string() => true,
+ string_is_not_class_case => is_class_case => "ooBar".to_string() => false,
+ string_to_table => to_table_case => "fooBar".to_string() => "foo_bars".to_string(),
+ string_is_table => is_table_case => "foo_bars".to_string() => true,
+ string_is_not_table => is_table_case => "fooBar".to_string() => false,
+ string_pluralize => to_plural => "crate".to_string() => "crates".to_string(),
+ string_singular => to_singular => "crates".to_string() => "crate".to_string(),
+ string_demodulize => demodulize => "Foo::Bar".to_string() => "Bar".to_string(),
+ string_deconstantize => deconstantize => "Foo::Bar".to_string() => "Foo".to_string()
+];
+
+number_tests![
+ i8_ordinalize => ordinalize => i8 => 1 => "1st".to_string(),
+ i16_ordinalize => ordinalize => i16 => 1 => "1st".to_string(),
+ i32_ordinalize => ordinalize => i32 => 1 => "1st".to_string(),
+ i64_ordinalize => ordinalize => i64 => 1 => "1st".to_string(),
+ u8_ordinalize => ordinalize => u8 => 1 => "1st".to_string(),
+ u16_ordinalize => ordinalize => u16 => 1 => "1st".to_string(),
+ u32_ordinalize => ordinalize => u32 => 1 => "1st".to_string(),
+ u64_ordinalize => ordinalize => u64 => 1 => "1st".to_string(),
+ isize_ordinalize => ordinalize => isize => 1 => "1st".to_string(),
+ usize_ordinalize => ordinalize => usize => 1 => "1st".to_string(),
+ f32_ordinalize => ordinalize => f32 => 1.0 => "1st".to_string(),
+ f64_ordinalize => ordinalize => f64 => 1.0 => "1st".to_string()
+];