Vendor dependencies

This commit is contained in:
2026-08-01 16:11:49 +03:00
parent 7f139a0241
commit 6b5e7f0f8b
29706 changed files with 9575646 additions and 0 deletions
@@ -0,0 +1 @@
{"$comment":"This file only protects against accidental modifications. It is not a security mechanism and does not protect against malicious changes.","files":{".cargo_vcs_info.json":"178a22cd4fe71f3f07c5ac9b0bbcb80541bdccf67f7bc7e55371acc3100cfd96","Cargo.toml":"92a6679b87874dbfc18e7f7ec5b9119daed13f9422df90a8b4d006ca910d581c","Cargo.toml.orig":"5d2764930c6bf687a6c29ff03afe61089546e1c88c38ffbca390ee4ffcc7a58f","README.md":"0bce520e9948d0642ff25ac9de00e71d9d3487b65a86289ff7655a0629e4e631","src/case/camel.rs":"acb8f5e64712cb73b4f359d60b97053b5b8b9b8df3544f291ab98747ded72f54","src/case/class.rs":"5ef4d492b65c987e0d58d44f020fe8d0db6b726aaedfa7f79607523574632645","src/case/kebab.rs":"493bbcf7e64b3776b0e4dd04da84372ee025210f76f7a8a803b2e5253f87bebd","src/case/mod.rs":"ec26a8c7511a9ca07d93b4d5c0d537648b89e829d4ec30938983ed8ea7967010","src/case/pascal.rs":"c74d5193c6ee611e171282254a993a7bb5badbf980998574404068835f454dc4","src/case/screaming_snake.rs":"969677462e85893e4ce2a603c499bbb621ac29681a7581d74bedc3448e2a7058","src/case/sentence.rs":"71a57e8e5f68f3d32b7e3f621fd007644f78c540b1cfd94d16737a4f0a733609","src/case/snake.rs":"270f72b71b769695510b3f9e4202d0cb13575a4792ed7666f013b60dbdf370ea","src/case/table.rs":"c1a43d58d0b81fa2e171ab49211441eac89708795f094401e7d25e864704a444","src/case/title.rs":"605607e316d312b4b9d12ea40ee98a6697be2251f28bad15f87df629a3f116f8","src/case/train.rs":"57283b15d1633a33c6cc49c5b2e55f64251155ce9f192c0314afdeb2962a2834","src/lib.rs":"6410fef0ae40752c9494c236b064f3693dda93758284521a32d723e3dfd59177","src/number/deordinalize.rs":"fff272936cb1d36844cf85d8d26c96b3073180290d19077c9a2496d26f5c145e","src/number/mod.rs":"6535d3742ab764896ca0136a2397e6f2b42705362e459bf2bb032b0feba9be12","src/number/ordinalize.rs":"333323100866628e2d845226676026097f05d5145697bf0d3024df2637364b2d","src/string/constants.rs":"273421d29309f87dd772c5ab239b0cdd63ed8dd845626fd4f1bf9ee5efa3df47","src/string/deconstantize.rs":"f65250cc272666f7da8863a421621ce20cb0973e2502ae0e2fc9289331e97c94","src/string/demodulize.rs":"aef9a66730809698f5656c8787fb73120b87a8b9dbb31556c62fd6fb70ffb116","src/string/mod.rs":"c4cc124ff3d26bb3b97d33c4916c5ccde74a6033311a0933a91e70d44793cfd7","src/string/pluralize.rs":"ccc9972c529d7545e1ae0b20140f5a4128f8d836797a0c9724a914123792bee6","src/string/singularize.rs":"539a9de1986d61a718ed97b8a8ae6b702ac89707275d15809b917ab2e32204df","src/suffix/foreign_key.rs":"ad634e86cfd603f7242f5908337506e2f8f8f42f72ead01e37847b5eacf932d7","src/suffix/mod.rs":"767e062a39dfb7ba462a1f9bfc607a2e974f9b2e237153f30f897e0f57bea323","tests/lib.rs":"7916ea523c3dfc860d7faa1cdf0b79d884af79e21f6d8e7a56f3bccdef9232d1"},"package":"113a9e83d8f614be76de8df1f25bf9d0ea6e85ea573710a3d3f3abe1438ae49c"}
@@ -0,0 +1,6 @@
{
"git": {
"sha1": "c7fe28f04693912cfcaa564bcec4fe0ef8ef5d79"
},
"path_in_vcs": ""
}
+55
View File
@@ -0,0 +1,55 @@
# 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 are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
name = "cruet"
version = "0.13.3"
authors = [
"Josh Teeter<joshteeter@gmail.com>",
"Chrislearn Young<chris@kenorld.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.
"""
homepage = "https://github.com/chrislearn/cruet"
documentation = "https://docs.rs/cruet"
readme = "README.md"
keywords = [
"pluralize",
"camel",
"snake",
"Inflector",
"inflection",
]
categories = [
"text-processing",
"value-formatting",
]
license = "BSD-2-Clause"
repository = "https://github.com/chrislearn/cruet"
[lib]
name = "cruet"
[dependencies.once_cell]
version = "1"
[dependencies.regex]
version = "1"
[badges.travis-ci]
repository = "chrislearn/cruet"
+26
View File
@@ -0,0 +1,26 @@
[package]
name = "cruet"
version = "0.13.3"
authors = ["Josh Teeter<joshteeter@gmail.com>", "Chrislearn Young<chris@kenorld.com>"]
edition = "2021"
include = ["**/*.rs", "Cargo.toml", "README.md"]
readme = "README.md"
repository = "https://github.com/chrislearn/cruet"
documentation = "https://docs.rs/cruet"
homepage = "https://github.com/chrislearn/cruet"
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", "camel", "snake", "Inflector", "inflection"]
categories = ["text-processing", "value-formatting"]
[badges]
travis-ci = { repository = "chrislearn/cruet" }
[lib]
name = "cruet"
[dependencies]
regex = { version = "1" }
once_cell = { version = "1" }
+103
View File
@@ -0,0 +1,103 @@
# Rust Inflector
This project is forked from https://github.com/whatisinternet/Inflector. The original author doesn't maintain this anymore.
[![Build Status](https://travis-ci.org/chrislearn/cruet.svg?branch=master)](https://travis-ci.org/chrislearn/cruet) [![Crates.io](https://img.shields.io/crates/v/cruet.svg)](https://crates.io/crates/cruet)[![Crate downloads](https://img.shields.io/crates/d/cruet.svg)](https://crates.io/crates/cruet)
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/cruet)
-----
## Installation:
### As a [crate](http://crates.io)
```toml
[dependencies]
cruet = "*"
```
### Compile yourself:
1. Install [Rust and cargo](http://doc.crates.io/)
2. git clone https://github.com/chrislearn/cruet
3. Library: cd cruet && cargo build --release --lib
4. You can find the library in target/release
## Usage / Example:
```rust
// to use methods like String.to_lower_case();
use cruet::Inflector;
fn main() {
let camel_case_string: String = "some_string".to_camel_case();
}
```
Or
```rust
// to use methods like to_snake_case(&str);
use cruet;
// use cruet::to_class_case;
// use cruet::is_class_case;
// use cruet::to_camel_case;
// use cruet::is_camel_case;
// use cruet::to_pascal_case;
// use cruet::is_pascal_case;
// use cruet::to_screamingsnake_case;
// use cruet::is_screamingsnake_case;
// use cruet::to_snake_case;
// use cruet::is_snake_case;
// use cruet::to_kebab_case;
// use cruet::is_kebab_case;
// use cruet::to_train_case;
// use cruet::is_train_case;
// use cruet::to_sentence_case;
// use cruet::is_sentence_case;
// use cruet::to_title_case;
// use cruet::is_title_case;
// use cruet::to_table_case;
// use cruet::is_table_case;
// use cruet::ordinalize;
// use cruet::deordinalize;
// use cruet::to_foreign_key;
// use cruet::is_foreign_key;
// use cruet::demodulize;
// use cruet::deconstantize;
// use cruet::to_plural;
// use cruet::to_singular;
fn main() {
let camel_case_string: String = to_camel_case("some_string");
}
```
## [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.
+247
View File
@@ -0,0 +1,247 @@
use crate::case::*;
/// Converts a `&str` to camelCase `String`
///
/// ```
/// use cruet::case::to_camel_case;
///
/// assert_eq!(to_camel_case("fooBar"), "fooBar");
/// assert_eq!(to_camel_case("FOO_BAR"), "fooBar");
/// assert_eq!(to_camel_case("Foo Bar"), "fooBar");
/// assert_eq!(to_camel_case("foo_bar"), "fooBar");
/// assert_eq!(to_camel_case("Foo bar"), "fooBar");
/// assert_eq!(to_camel_case("foo-bar"), "fooBar");
/// assert_eq!(to_camel_case("FooBar"), "fooBar");
/// assert_eq!(to_camel_case("FooBar3"), "fooBar3");
/// assert_eq!(to_camel_case("Foo-Bar"), "fooBar");
/// ```
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 cruet::case::is_camel_case;
///
/// assert!(is_camel_case("foo"));
/// assert!(is_camel_case("fooBarIsAReallyReally3LongString"));
/// assert!(is_camel_case("fooBarIsAReallyReallyLongString"));
///
/// assert!(!is_camel_case("Foo"));
/// assert!(!is_camel_case("foo-bar-string-that-is-really-really-long"));
/// assert!(!is_camel_case("FooBarIsAReallyReallyLongString"));
/// assert!(!is_camel_case("FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG"));
/// assert!(!is_camel_case("foo_bar_string_that_is_really_really_long"));
/// assert!(!is_camel_case("Foo bar string that is really really long"));
/// assert!(!is_camel_case("Foo Bar Is A Really Really Long String"));
/// ```
pub fn is_camel_case(test_string: &str) -> bool {
to_camel_case(test_string) == 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 super::is_camel_case;
use super::to_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)
}
}
+226
View File
@@ -0,0 +1,226 @@
use crate::case::*;
use crate::string::singularize::to_singular;
/// Converts a `&str` to `ClassCase` `String`
///
/// ```
/// use cruet::case::to_class_case;
///
/// assert_eq!(to_class_case("FooBar"), "FooBar");
/// assert_eq!(to_class_case("FooBars"), "FooBar");
/// assert_eq!(to_class_case("Foo Bar"), "FooBar");
/// assert_eq!(to_class_case("foo-bar"), "FooBar");
/// assert_eq!(to_class_case("fooBar"), "FooBar");
/// assert_eq!(to_class_case("FOO_BAR"), "FooBar");
/// assert_eq!(to_class_case("foo_bars"), "FooBar");
/// assert_eq!(to_class_case("Foo bar"), "FooBar");
/// ```
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))
}
/// Determines if a `&str` is `ClassCase` `bool`
///
/// ```
/// use cruet::case::is_class_case;
///
/// assert!(is_class_case("Foo"));
/// assert!(is_class_case("FooBarIsAReallyReallyLongString"));
///
/// assert!(!is_class_case("foo"));
/// assert!(!is_class_case("FooBarIsAReallyReallyLongStrings"));
/// assert!(!is_class_case("foo-bar-string-that-is-really-really-long"));
/// assert!(!is_class_case("foo_bar_is_a_really_really_long_strings"));
/// assert!(!is_class_case("fooBarIsAReallyReallyLongString"));
/// assert!(!is_class_case("FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG"));
/// assert!(!is_class_case("foo_bar_string_that_is_really_really_long"));
/// assert!(!is_class_case("Foo bar string that is really really long"));
/// assert!(!is_class_case("Foo Bar Is A Really Really Long String"));
/// ```
pub fn is_class_case(test_string: &str) -> bool {
to_class_case(test_string) == test_string
}
#[cfg(test)]
mod tests {
use super::is_class_case;
use super::to_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)
}
}
+165
View File
@@ -0,0 +1,165 @@
use crate::case::*;
/// Determines if a `&str` is `kebab-case`
///
/// ```
/// use cruet::case::is_kebab_case;
///
/// assert!(is_kebab_case("foo-bar-string-that-is-really-really-long"));
/// assert!(!is_kebab_case("FooBarIsAReallyReallyLongString"));
/// assert!(!is_kebab_case("fooBarIsAReallyReallyLongString"));
/// assert!(!is_kebab_case("FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG"));
/// assert!(!is_kebab_case("foo_bar_string_that_is_really_really_long"));
/// assert!(!is_kebab_case("Foo bar string that is really really long"));
/// assert!(!is_kebab_case("Foo Bar Is A Really Really Long String"));
/// ```
pub fn is_kebab_case(test_string: &str) -> bool {
test_string == to_kebab_case(test_string)
}
/// Converts a `&str` to `kebab-case` `String`
///
/// ```
/// use cruet::case::to_kebab_case;
///
/// assert_eq!(to_kebab_case("foo-bar"), "foo-bar");
/// assert_eq!(to_kebab_case("FOO_BAR"), "foo-bar");
/// assert_eq!(to_kebab_case("foo_bar"), "foo-bar");
/// assert_eq!(to_kebab_case("Foo Bar"),"foo-bar");
/// assert_eq!(to_kebab_case("Foo bar"), "foo-bar");
/// assert_eq!(to_kebab_case("FooBar"), "foo-bar");
/// assert_eq!(to_kebab_case("fooBar"), "foo-bar");
/// ```
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 super::is_kebab_case;
use super::to_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)
}
}
+422
View File
@@ -0,0 +1,422 @@
/// Provides conversion to and detection of class case strings.
///
/// This version singularizes strings.
///
/// Example string `ClassCase`
pub mod class;
pub use class::is_class_case;
pub use class::to_class_case;
/// Provides conversion to and detection of camel case strings.
///
/// Example string `camelCase`
pub mod camel;
pub use camel::is_camel_case;
pub use camel::to_camel_case;
/// Provides conversion to and detection of snake case strings.
///
/// Example string `snake_case`
pub mod snake;
pub use snake::is_snake_case;
pub use snake::to_snake_case;
/// Provides conversion to and detection of screaming snake case strings.
///
/// Example string `SCREAMING_SNAKE_CASE`
pub mod screaming_snake;
pub use screaming_snake::is_screaming_snake_case;
pub use screaming_snake::to_screaming_snake_case;
/// Provides conversion to and detection of kebab case strings.
///
/// Example string `kebab-case`
pub mod kebab;
pub use kebab::is_kebab_case;
pub use kebab::to_kebab_case;
/// Provides conversion to and detection of train case strings.
///
/// Example string `Train-Case`
pub mod train;
pub use train::is_train_case;
pub use train::to_train_case;
/// Provides conversion to and detection of sentence case strings.
///
/// Example string `Sentence case`
pub mod sentence;
pub use sentence::is_sentence_case;
pub use sentence::to_sentence_case;
/// Provides conversion to and detection of title case strings.
///
/// Example string `Title Case`
pub mod title;
pub use title::is_title_case;
pub use title::to_title_case;
/// Provides conversion to and detection of table case strings.
///
/// Example string `table_cases`
pub mod table;
pub use table::is_table_case;
pub use table::to_table_case;
/// Provides conversion to pascal case strings.
///
/// Example string `PascalCase`
pub mod pascal;
pub use pascal::is_pascal_case;
pub use pascal::to_pascal_case;
#[doc(hidden)]
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,
}
#[doc(hidden)]
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().next().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
}
#[doc(hidden)]
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().next().unwrap_or('_'));
accumlator.push(current_char.to_ascii_lowercase());
accumlator
} else {
accumlator.push(replace_with.chars().next().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)
}
+245
View File
@@ -0,0 +1,245 @@
use crate::case::*;
/// Converts a `&str` to pascalCase `String`
///
/// ```
/// use cruet::case::to_pascal_case;
///
/// assert_eq!(to_pascal_case("fooBar"), "FooBar");
/// assert_eq!(to_pascal_case("FOO_BAR"), "FooBar");
/// assert_eq!(to_pascal_case("Foo Bar"), "FooBar");
/// assert_eq!(to_pascal_case("foo_bar"), "FooBar");
/// assert_eq!(to_pascal_case("Foo bar"), "FooBar");
/// assert_eq!(to_pascal_case("foo-bar"), "FooBar");
/// assert_eq!(to_pascal_case("FooBar"), "FooBar");
/// assert_eq!(to_pascal_case("FooBar3"), "FooBar3");
/// ```
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 cruet::case::is_pascal_case;
///
/// assert!(is_pascal_case("Foo"));
/// assert!(is_pascal_case("FooBarIsAReallyReallyLongString"));
/// assert!(is_pascal_case("FooBarIsAReallyReally3LongString"));
/// assert!(is_pascal_case("FooBarIsAReallyReallyLongString"));
///
/// assert!(!is_pascal_case("foo"));
/// assert!(!is_pascal_case("foo-bar-string-that-is-really-really-long"));
/// assert!(!is_pascal_case("FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG"));
/// assert!(!is_pascal_case("foo_bar_string_that_is_really_really_long"));
/// assert!(!is_pascal_case("Foo bar string that is really really long"));
/// assert!(!is_pascal_case("Foo Bar Is A Really Really Long String"));
/// ```
pub fn is_pascal_case(test_string: &str) -> bool {
to_pascal_case(test_string) == 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 super::is_pascal_case;
use super::to_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)
}
}
@@ -0,0 +1,162 @@
use crate::case::*;
/// Converts a `&str` to `SCREAMING_SNAKE_CASE` `String`
///
/// ```
/// use cruet::case::to_screaming_snake_case;
///
/// assert_eq!(to_screaming_snake_case("foo_bar"), "FOO_BAR");
/// assert_eq!(to_screaming_snake_case("HTTP Foo bar"), "HTTP_FOO_BAR");
/// assert_eq!(to_screaming_snake_case("Foo bar"), "FOO_BAR");
/// assert_eq!(to_screaming_snake_case("Foo Bar"), "FOO_BAR");
/// assert_eq!(to_screaming_snake_case("FooBar"), "FOO_BAR");
/// assert_eq!(to_screaming_snake_case("fooBar"), "FOO_BAR");
/// assert_eq!(to_screaming_snake_case("fooBar3"), "FOO_BAR_3");
/// ```
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 cruet::case::is_screaming_snake_case;
///
/// assert!(is_screaming_snake_case("FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG"));
/// assert!(is_screaming_snake_case("FOO_BAR1_STRING_THAT_IS_REALLY_REALLY_LONG"));
/// assert!(is_screaming_snake_case("FOO_BAR_1_STRING_THAT_IS_REALLY_REALLY_LONG"));
///
/// assert!(!is_screaming_snake_case("Foo bar string that is really really long"));
/// assert!(!is_screaming_snake_case("foo-bar-string-that-is-really-really-long"));
/// assert!(!is_screaming_snake_case("FooBarIsAReallyReallyLongString"));
/// assert!(!is_screaming_snake_case("Foo Bar Is A Really Really Long String"));
/// assert!(!is_screaming_snake_case("fooBarIsAReallyReallyLongString"));
/// ```
pub fn is_screaming_snake_case(test_string: &str) -> bool {
test_string == to_screaming_snake_case(test_string)
}
#[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 super::is_screaming_snake_case;
use super::to_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)
}
}
+224
View File
@@ -0,0 +1,224 @@
use crate::case::*;
/// Converts a `&str` to `Sentence case` `String`
///
/// ```
/// use cruet::case::to_sentence_case;
///
/// assert_eq!(to_sentence_case("Foo bar"), "Foo bar");
/// assert_eq!(to_sentence_case("FooBar"), "Foo bar");
/// assert_eq!(to_sentence_case("fooBar"), "Foo bar");
/// assert_eq!(to_sentence_case("FOO_BAR"), "Foo bar");
/// assert_eq!(to_sentence_case("foo_bar"), "Foo bar");
/// assert_eq!(to_sentence_case("foo-bar"), "Foo bar");
/// ```
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 cruet::case::is_sentence_case;
///
/// assert!(is_sentence_case("Foo"));
/// assert!(is_sentence_case("Foo bar string that is really really long"));
///
/// assert!(!is_sentence_case("foo-bar-string-that-is-really-really-long"));
/// assert!(!is_sentence_case("FooBarIsAReallyReallyLongString"));
/// assert!(!is_sentence_case("fooBarIsAReallyReallyLongString"));
/// assert!(!is_sentence_case("Foo Bar Is A Really Really Long String"));
/// assert!(!is_sentence_case("FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG"));
/// assert!(!is_sentence_case("foo_bar_string_that_is_really_really_long"));
/// assert!(!is_sentence_case("foo"));
/// ```
pub fn is_sentence_case(test_string: &str) -> bool {
test_string == to_sentence_case(test_string)
}
#[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 super::is_sentence_case;
use super::to_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)
}
}
+225
View File
@@ -0,0 +1,225 @@
use crate::case::*;
/// Converts a `&str` to `snake_case` `String`
///
/// ```
/// use cruet::case::to_snake_case;
///
/// assert_eq!(to_snake_case("foo_bar"), "foo_bar");
/// assert_eq!(to_snake_case("HTTP Foo bar"), "http_foo_bar");
/// assert_eq!(to_snake_case("HTTPFooBar"), "http_foo_bar");
/// assert_eq!(to_snake_case("Foo bar"), "foo_bar");
/// assert_eq!(to_snake_case("Foo Bar"), "foo_bar");
/// assert_eq!(to_snake_case("FooBar"), "foo_bar");
/// assert_eq!(to_snake_case("FOO_BAR"), "foo_bar");
/// assert_eq!(to_snake_case("fooBar"), "foo_bar");
/// assert_eq!(to_snake_case("fooBar3"), "foo_bar_3");
/// ```
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 cruet::case::is_snake_case;
///
/// assert!(is_snake_case("foo_bar_string_that_is_really_really_long"));
/// assert!(is_snake_case("foo_bar_1_string_that_is_really_really_long"));
///
/// assert!(!is_snake_case("foo_bar1_string_that_is_really_really_long"));
/// assert!(!is_snake_case("Foo bar string that is really really long"));
/// assert!(!is_snake_case("foo-bar-string-that-is-really-really-long"));
/// assert!(!is_snake_case("FooBarIsAReallyReallyLongString"));
/// assert!(!is_snake_case("Foo Bar Is A Really Really Long String"));
/// assert!(!is_snake_case("FOO_BAR_IS_A_REALLY_REALLY_LONG_STRING"));
/// assert!(!is_snake_case("fooBarIsAReallyReallyLongString"));
/// ```
pub fn is_snake_case(test_string: &str) -> bool {
test_string == to_snake_case(test_string)
}
#[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 super::is_snake_case;
use super::to_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)
}
}
+180
View File
@@ -0,0 +1,180 @@
use crate::case::*;
use crate::string::pluralize::to_plural;
/// Converts a `&str` to `table-case` `String`
///
/// ```
/// use cruet::case::table::to_table_case;
///
/// assert_eq!(to_table_case("foo-bar"), "foo_bars");
/// assert_eq!(to_table_case("FOO_BAR"), "foo_bars");
/// assert_eq!(to_table_case("foo_bar"), "foo_bars");
/// assert_eq!(to_table_case("Foo Bar"), "foo_bars");
/// assert_eq!(to_table_case("Foo bar"), "foo_bars");
/// assert_eq!(to_table_case("FooBar"), "foo_bars");
/// assert_eq!(to_table_case("fooBar"), "foo_bars");
/// ```
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))
}
/// Determines if a `&str` is `table-case`
///
/// ```
/// use cruet::case::table::is_table_case;
/// assert!(is_table_case("foo_bar_strings"));
/// assert!(!is_table_case("foo-bar-string-that-is-really-really-long"));
/// assert!(!is_table_case("FooBarIsAReallyReallyLongString"));
/// assert!(!is_table_case("fooBarIsAReallyReallyLongString"));
/// assert!(!is_table_case("FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG"));
/// assert!(!is_table_case("foo_bar_string_that_is_really_really_long"));
/// assert!(!is_table_case("Foo bar string that is really really long"));
/// assert!(!is_table_case("Foo Bar Is A Really Really Long String"));
/// ```
pub fn is_table_case(test_string: &str) -> bool {
to_table_case(test_string) == test_string
}
#[cfg(all(feature = "unstable", test))]
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)]
mod tests {
use super::is_table_case;
use super::to_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)
}
}
+223
View File
@@ -0,0 +1,223 @@
use crate::case::*;
/// Converts a `&str` to `Title Case` `String`
///
/// ```
/// use cruet::case::title::to_title_case;
///
/// assert!(to_title_case("Foo bar") == "Foo Bar");
/// assert!(to_title_case("FooBar") == "Foo Bar");
/// assert!(to_title_case("fooBar") == "Foo Bar");
/// assert!(to_title_case("FOO_BAR") == "Foo Bar");
/// assert!(to_title_case("foo_bar") == "Foo Bar");
/// assert!(to_title_case("foo-bar") == "Foo Bar");
/// ```
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 cruet::case::title::is_title_case;
///
/// assert!(is_title_case("Foo Bar String That Is Really Really Long"));
/// assert!(!is_title_case("foo-bar-string-that-is-really-really-long"));
/// assert!(!is_title_case("FooBarIsAReallyReallyLongString"));
/// assert!(!is_title_case("fooBarIsAReallyReallyLongString"));
/// assert!(!is_title_case("FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG"));
/// assert!(!is_title_case("foo_bar_string_that_is_really_really_long"));
/// assert!(!is_title_case("Foo bar string that is really really long"));
/// assert!(!is_title_case("foo"));
/// ```
pub fn is_title_case(test_string: &str) -> bool {
test_string == to_title_case(test_string)
}
#[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 super::is_title_case;
use super::to_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)
}
}
+223
View File
@@ -0,0 +1,223 @@
use crate::case::*;
/// Determines if a `&str` is `Train-Case`
///
/// ```
/// use cruet::case::train::is_train_case;
///
/// assert!(is_train_case("Foo-Bar-String-That-Is-Really-Really-Long"));
/// assert!(!is_train_case("foo-bar-string-that-is-really-really-long"));
/// assert!(!is_train_case("FooBarIsAReallyReallyLongString"));
/// assert!(!is_train_case("fooBarIsAReallyReallyLongString"));
/// assert!(!is_train_case("foo_bar_string_that_is_really_really_long"));
/// assert!(!is_train_case("Foo bar string that is really really long"));
/// assert!(!is_train_case("Foo Bar Is A Really Really Long String"));
/// ```
pub fn is_train_case(test_string: &str) -> bool {
test_string == to_train_case(test_string)
}
/// Converts a `&str` to `Train-Case` `String`
///
/// ```
/// use cruet::case::train::to_train_case;
///
/// assert!(to_train_case("foo-bar") == "Foo-Bar");
/// assert!(to_train_case("FOO_BAR") == "Foo-Bar");
/// assert!(to_train_case("foo_bar") == "Foo-Bar");
/// assert!(to_train_case("Foo Bar") == "Foo-Bar");
/// assert!(to_train_case("Foo-Bar") == "Foo-Bar");
/// assert!(to_train_case("FooBar") == "Foo-Bar");
/// assert!(to_train_case("fooBar") == "Foo-Bar");
/// ```
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 super::is_train_case;
use super::to_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)
}
}
+314
View File
@@ -0,0 +1,314 @@
#![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 cruet::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);
//! ```
/// Provides case inflections
/// - Camel case
/// - Class case
/// - Kebab case
/// - Train case
/// - Screaming snake case
/// - Table case
/// - Sentence case
/// - Snake case
/// - Pascal case
pub mod case;
/// Provides number inflections
/// - Ordinalize
/// - Deordinalize
pub mod number;
/// Provides string inflections
/// - Deconstantize
/// - Demodulize
/// - Pluralize
/// - Singularize
pub mod string;
/// Provides suffix inflections
/// - Foreign key
pub mod suffix;
pub use case::class::is_class_case;
pub use case::class::to_class_case;
pub use case::camel::is_camel_case;
pub use case::camel::to_camel_case;
pub use case::pascal::is_pascal_case;
pub use case::pascal::to_pascal_case;
pub use case::snake::is_snake_case;
pub use case::snake::to_snake_case;
pub use case::screaming_snake::is_screaming_snake_case;
pub use case::screaming_snake::to_screaming_snake_case;
pub use case::kebab::is_kebab_case;
pub use case::kebab::to_kebab_case;
pub use case::train::is_train_case;
pub use case::train::to_train_case;
pub use case::sentence::is_sentence_case;
pub use case::sentence::to_sentence_case;
pub use case::title::is_title_case;
pub use case::title::to_title_case;
pub use case::table::is_table_case;
pub use case::table::to_table_case;
pub use number::deordinalize::deordinalize;
pub use number::ordinalize::ordinalize;
pub use suffix::foreign_key::is_foreign_key;
pub use suffix::foreign_key::to_foreign_key;
pub use string::deconstantize::deconstantize;
pub use string::demodulize::demodulize;
pub use string::pluralize::to_plural;
pub 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;
fn demodulize(&self) -> String;
fn deconstantize(&self) -> String;
fn to_class_case(&self) -> String;
fn is_class_case(&self) -> bool;
fn to_table_case(&self) -> String;
fn is_table_case(&self) -> bool;
fn to_plural(&self) -> String;
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]
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()
];
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"
];
}
@@ -0,0 +1,33 @@
/// Deorginalizes a `&str`
///
/// ```
/// use cruet::number::deordinalize::deordinalize;
///
/// assert!(deordinalize("0.1") == "0.1");
/// assert!(deordinalize("-1st") == "-1");
/// assert!(deordinalize("0th") == "0");
/// assert!(deordinalize("1st") == "1");
/// assert!(deordinalize("2nd") == "2");
/// assert!(deordinalize("3rd") == "3");
/// assert!(deordinalize("9th") == "9");
/// assert!(deordinalize("12th") == "12");
/// assert!(deordinalize("12000th") == "12000");
/// assert!(deordinalize("12001th") == "12001");
/// assert!(deordinalize("12002nd") == "12002");
/// assert!(deordinalize("12003rd") == "12003");
/// assert!(deordinalize("12004th") == "12004");
/// assert!(deordinalize("3rd") == "3");
/// assert!(deordinalize("3rd") == "3");
/// ```
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()
}
}
+11
View File
@@ -0,0 +1,11 @@
/// Provides deordinalization of a string.
///
/// Example string "1st" becomes "1"
pub mod deordinalize;
pub use deordinalize::deordinalize;
/// Provides ordinalization of a string.
///
/// Example string "1" becomes "1st"
pub mod ordinalize;
pub use ordinalize::ordinalize;
@@ -0,0 +1,147 @@
/// Orginalizes a `&str`
///
/// ```
/// use cruet::number::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 cruet::number::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 cruet::number::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 cruet::number::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 cruet::number::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 cruet::number::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 cruet::number::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 cruet::number::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 cruet::number::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 cruet::number::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 cruet::number::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 cruet::number::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 cruet::number::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 cruet::number::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.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('.')
}
@@ -0,0 +1,204 @@
pub const UNACCONTABLE_WORDS: [&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",
];
@@ -0,0 +1,48 @@
use crate::case::class::to_class_case;
/// Deconstantizes a `&str`
///
/// ```
/// use cruet::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 cruet::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 cruet::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 cruet::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()
}
}
@@ -0,0 +1,44 @@
use crate::case::class::to_class_case;
/// Demodulize a `&str`
///
/// ```
/// use cruet::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 cruet::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 cruet::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 cruet::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()
}
}
+25
View File
@@ -0,0 +1,25 @@
/// Provides deconstantizea string.
///
/// Example string `Foo::Bar` becomes `Foo`
pub mod deconstantize;
pub use deconstantize::deconstantize;
/// Provides demodulize a string.
///
/// Example string `Foo::Bar` becomes `Bar`
pub mod demodulize;
pub use demodulize::demodulize;
/// Provides conversion to plural strings.
///
/// Example string `FooBar` -> `FooBars`
pub mod pluralize;
pub use pluralize::to_plural;
/// Provides conversion to singular strings.
///
/// Example string `FooBars` -> `FooBar`
pub mod singularize;
pub use singularize::to_singular;
mod constants;
@@ -0,0 +1,175 @@
use crate::string::constants::UNACCONTABLE_WORDS;
use once_cell::sync::Lazy;
use regex::Regex;
static RULES: Lazy<Vec<(Regex, &'static str)>> = Lazy::new(|| {
vec![(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)$", "")].into_iter().map(|(rule, replace)| {(Regex::new(rule).unwrap(), replace)}).collect()
});
macro_rules! special_cases{
($s:ident, $($singular: expr => $plural:expr), *) => {
match &$s[..] {
$(
$singular => {
return $plural.to_owned();
},
)*
_ => ()
}
}
}
/// Converts a `&str` to pluralized `String`
///
/// ```
/// use cruet::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 cruet::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 cruet::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 cruet::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 cruet::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 cruet::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 cruet::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) {
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;
mice => mice;
people => people
}
}
@@ -0,0 +1,210 @@
use once_cell::sync::Lazy;
use regex::Regex;
use crate::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 cruet::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 cruet::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 cruet::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 cruet::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 cruet::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 cruet::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 cruet::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) {
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;
}
}
}
non_singular_string.to_owned()
}
}
static RULES: Lazy<Vec<(Regex, &'static str)>> = Lazy::new(|| {
vec![
(r"(\w*)s$", ""),
(r"(\w*(ss))$", ""),
(r"(\w*(n))ews$", "ews"),
(r"(\w*(o))es$", ""),
(r"(\w*([ti]))a$", "um"),
(
r"(\w*((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"(\w*(s))eries$", "eries"),
(r"(\w*(m))ovies$", "ovie"),
(r"(\w*(x|ch|ss|sh))es$", ""),
(r"(\w*(m|l))ice$", "ouse"),
(r"(\w*(bus))(es)?$", ""),
(r"(\w*(shoe))s$", ""),
(r"(\w*(cris|test))(is|es)$", "is"),
(r"^(a)x[ie]s$", "xis"),
(r"(\w*(octop|vir))(us|i)$", "us"),
(r"(\w*(alias|status))(es)?$", ""),
(r"^(ox)en", ""),
(r"(\w*(vert|ind))ices$", "ex"),
(r"(\w*(matr))ices$", "ix"),
(r"(\w*(quiz))zes$", ""),
(r"(\w*(database))s$", ""),
]
.into_iter()
.map(|(rule, replace)| (Regex::new(rule).unwrap(), replace))
.collect()
});
#[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() {
assert_eq!("news", to_singular("news"));
assert_eq!("goodnews", to_singular("goodnews"));
assert_eq!("potato", to_singular("potatoes"));
assert_eq!("datum", to_singular("data"));
assert_eq!("analysis", to_singular("analyses"));
assert_eq!("codebasis", to_singular("codebases"));
assert_eq!("diagnosis", to_singular("diagnoses"));
assert_eq!("parenthesis", to_singular("parentheses"));
assert_eq!("prognosis", to_singular("prognoses"));
assert_eq!("synopsis", to_singular("synopses"));
assert_eq!("thesis", to_singular("theses"));
assert_eq!("knife", to_singular("knives"));
assert_eq!("archive", to_singular("archives"));
assert_eq!("motive", to_singular("motives"));
assert_eq!("half", to_singular("halves"));
assert_eq!("wolf", to_singular("wolves"));
assert_eq!("calf", to_singular("calves"));
assert_eq!("shelf", to_singular("shelves"));
assert_eq!("series", to_singular("series"));
assert_eq!("movie", to_singular("movies"));
assert_eq!("bus", to_singular("buses"));
assert_eq!("wish", to_singular("wishes"));
assert_eq!("pitch", to_singular("pitches"));
assert_eq!("box", to_singular("boxes"));
assert_eq!("mouse", to_singular("mice"));
assert_eq!("minibus", to_singular("minibuses"));
assert_eq!("snowshoe", to_singular("snowshoes"));
assert_eq!("crisis", to_singular("crises"));
assert_eq!("ovotestis", to_singular("ovotestes"));
assert_eq!("axis", to_singular("axes"));
assert_eq!("octopus", to_singular("octopi"));
assert_eq!("alias", to_singular("aliases"));
assert_eq!("ox", to_singular("oxen"));
assert_eq!("index", to_singular("indices"));
assert_eq!("matrix", to_singular("matrices"));
assert_eq!("quiz", to_singular("quizzes"));
assert_eq!("database", to_singular("databases"));
}
#[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);
}
@@ -0,0 +1,49 @@
use crate::case::snake::to_snake_case;
/// Converts a `&str` to a `foreign_key`
///
/// ```
/// use cruet::suffix::foreign_key::to_foreign_key;
///
/// assert!(to_foreign_key("foo_bar") == "foo_bar_id");
/// assert!(to_foreign_key("Foo bar") == "foo_bar_id");
/// assert!(to_foreign_key("Foo Bar") == "foo_bar_id");
/// assert!(to_foreign_key("Foo::Bar") == "bar_id");
/// assert!(to_foreign_key("Test::Foo::Bar") == "bar_id");
/// assert!(to_foreign_key("FooBar") == "foo_bar_id");
/// assert!(to_foreign_key("fooBar") == "foo_bar_id");
/// assert!(to_foreign_key("fooBar3") == "foo_bar_3_id");
/// ```
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 cruet::suffix::foreign_key::is_foreign_key;
///
/// assert!(!is_foreign_key("Foo bar string that is really really long"));
/// assert!(!is_foreign_key("foo-bar-string-that-is-really-really-long"));
/// assert!(!is_foreign_key("FooBarIsAReallyReallyLongString"));
/// assert!(!is_foreign_key("Foo Bar Is A Really Really Long String"));
/// assert!(!is_foreign_key("fooBarIsAReallyReallyLongString"));
/// assert!(!is_foreign_key("foo_bar_string_that_is_really_really_long"));
/// assert!(is_foreign_key("foo_bar_string_that_is_really_really_long_id"));
/// ```
pub fn is_foreign_key(test_string: &str) -> bool {
to_foreign_key(test_string) == test_string
}
+6
View File
@@ -0,0 +1,6 @@
/// Provides foreign key conversion for String.
///
/// Example string `foo` becomes `foo_id`
pub mod foreign_key;
pub use foreign_key::is_foreign_key;
pub use foreign_key::to_foreign_key;
+161
View File
@@ -0,0 +1,161 @@
extern crate cruet;
use cruet::Inflector;
use cruet::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]
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]
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()
];