inflector/
lib.rs

1#![deny(warnings, unused_variables, missing_docs, unsafe_code, unused_extern_crates)]
2#![cfg_attr(feature = "unstable", feature(test))]
3
4//! Adds String based inflections for Rust. Snake, kebab, train, camel,
5//! word, sentence, class, and title cases as well as ordinalize,
6//! deordinalize, demodulize, deconstantize, and foreign key are supported as
7//! both traits and pure functions acting on String types.
8//! ```rust
9//! use inflector::Inflector;
10//! let camel_case_string: String = "some_string".to_camel_case();
11//! let is_camel_cased: bool= camel_case_string.is_camel_case();
12//! assert!(is_camel_cased == true);
13//! ```
14
15#[cfg(feature = "heavyweight")]
16extern crate regex;
17
18#[cfg(feature = "heavyweight")]
19#[macro_use] extern crate lazy_static;
20
21/// Provides case inflections
22/// - Camel case
23/// - Class case
24/// - Kebab case
25/// - Train case
26/// - Screaming snake case
27/// - Table case
28/// - Word case
29/// - Sentence case
30/// - Snake case
31/// - Pascal case
32pub mod cases;
33/// Provides number inflections
34/// - Ordinalize
35/// - Deordinalize
36pub mod numbers;
37/// Provides suffix inflections
38/// - Foreign key
39pub mod suffix;
40/// Provides string inflections
41/// - Deconstantize
42/// - Demodulize
43/// - Pluralize
44/// - Singularize
45/// - Articlize
46/// - Dearticlize
47#[cfg(feature = "heavyweight")]
48pub mod string;
49
50
51#[cfg(feature = "heavyweight")]
52use cases::classcase::to_class_case;
53#[cfg(feature = "heavyweight")]
54use cases::classcase::is_class_case;
55
56use cases::camelcase::to_camel_case;
57use cases::camelcase::is_camel_case;
58
59use cases::pascalcase::to_pascal_case;
60use cases::pascalcase::is_pascal_case;
61
62use cases::snakecase::to_snake_case;
63use cases::snakecase::is_snake_case;
64
65use cases::screamingsnakecase::to_screaming_snake_case;
66use cases::screamingsnakecase::is_screaming_snake_case;
67
68use cases::kebabcase::to_kebab_case;
69use cases::kebabcase::is_kebab_case;
70
71use cases::traincase::to_train_case;
72use cases::traincase::is_train_case;
73
74use cases::wordcase::to_word_case;
75use cases::wordcase::is_word_case;
76
77use cases::sentencecase::to_sentence_case;
78use cases::sentencecase::is_sentence_case;
79
80use cases::titlecase::to_title_case;
81use cases::titlecase::is_title_case;
82
83#[cfg(feature = "heavyweight")]
84use cases::tablecase::to_table_case;
85#[cfg(feature = "heavyweight")]
86use cases::tablecase::is_table_case;
87
88use numbers::ordinalize::ordinalize;
89use numbers::deordinalize::deordinalize;
90
91use suffix::foreignkey::to_foreign_key;
92use suffix::foreignkey::is_foreign_key;
93
94#[cfg(feature = "heavyweight")]
95use string::demodulize::demodulize;
96#[cfg(feature = "heavyweight")]
97use string::deconstantize::deconstantize;
98
99#[cfg(feature = "heavyweight")]
100use string::pluralize::to_plural;
101#[cfg(feature = "heavyweight")]
102use string::singularize::to_singular;
103
104#[cfg(feature = "heavyweight")]
105use string::articlize::articlize;
106#[cfg(feature = "heavyweight")]
107use string::dearticlize::dearticlize;
108
109#[allow(missing_docs)]
110pub trait Inflector {
111
112    fn to_camel_case(&self) -> String;
113    fn is_camel_case(&self) -> bool;
114
115    fn to_pascal_case(&self) -> String;
116    fn is_pascal_case(&self) -> bool;
117
118    fn to_snake_case(&self) -> String;
119    fn is_snake_case(&self) -> bool;
120
121    fn to_screaming_snake_case(&self) -> String;
122    fn is_screaming_snake_case(&self) -> bool;
123
124    fn to_kebab_case(&self) -> String;
125    fn is_kebab_case(&self) -> bool;
126
127    fn to_train_case(&self) -> String;
128    fn is_train_case(&self) -> bool;
129
130    fn to_word_case(&self) -> String;
131    fn is_word_case(&self) -> bool;
132
133    fn to_sentence_case(&self) -> String;
134    fn is_sentence_case(&self) -> bool;
135
136    fn to_title_case(&self) -> String;
137    fn is_title_case(&self) -> bool;
138
139    fn ordinalize(&self) -> String;
140    fn deordinalize(&self) -> String;
141
142    fn to_foreign_key(&self) -> String;
143    fn is_foreign_key(&self) -> bool;
144
145    #[cfg(feature = "heavyweight")]
146    fn demodulize(&self) -> String;
147    #[cfg(feature = "heavyweight")]
148    fn deconstantize(&self) -> String;
149
150    #[cfg(feature = "heavyweight")]
151    fn to_class_case(&self) -> String;
152    #[cfg(feature = "heavyweight")]
153    fn is_class_case(&self) -> bool;
154
155    #[cfg(feature = "heavyweight")]
156    fn to_table_case(&self) -> String;
157    #[cfg(feature = "heavyweight")]
158    fn is_table_case(&self) -> bool;
159    #[cfg(feature = "heavyweight")]
160    fn to_plural(&self) -> String;
161    #[cfg(feature = "heavyweight")]
162    fn to_singular(&self) -> String;
163
164    #[cfg(feature = "heavyweight")]
165    fn articlize(&self) -> String;
166    #[cfg(feature = "heavyweight")]
167    fn dearticlize(&self) -> String;
168}
169
170
171#[allow(missing_docs)]
172pub trait InflectorNumbers {
173    fn ordinalize(&self) -> String;
174}
175
176
177macro_rules! define_implementations {
178    ( $slf:ident; $($imp_trait:ident => $typ:ident), *) => {
179        $(
180            #[inline]
181            fn $imp_trait(&$slf) -> $typ {
182                $imp_trait($slf)
183            }
184        )*
185    }
186}
187
188macro_rules! define_number_implementations {
189    ( $slf:ident; $($imp_trait:ident => $typ:ident), *) => {
190        $(
191            #[inline]
192            fn $imp_trait(&$slf) -> $typ {
193                $imp_trait(&$slf.to_string())
194            }
195        )*
196    }
197}
198
199macro_rules! define_gated_implementations {
200    ( $slf:ident; $($imp_trait:ident => $typ:ident), *) => {
201        $(
202            #[inline]
203            #[cfg(feature = "heavyweight")]
204            fn $imp_trait(&$slf) -> $typ {
205                $imp_trait($slf)
206            }
207        )*
208    }
209}
210
211macro_rules! implement_string_for {
212    ( $trt:ident; $($typ:ident), *) => {
213        $(
214            impl $trt for $typ {
215                define_implementations![self;
216                    to_camel_case => String,
217                    is_camel_case => bool,
218                    to_pascal_case => String,
219                    is_pascal_case => bool,
220                    to_screaming_snake_case => String,
221                    is_screaming_snake_case => bool,
222                    to_snake_case => String,
223                    is_snake_case => bool,
224                    to_kebab_case => String,
225                    is_kebab_case => bool,
226                    to_train_case => String,
227                    is_train_case => bool,
228                    to_word_case => String,
229                    is_word_case => bool,
230                    to_sentence_case => String,
231                    is_sentence_case => bool,
232                    to_title_case => String,
233                    is_title_case => bool,
234                    to_foreign_key => String,
235                    is_foreign_key => bool,
236                    ordinalize => String,
237                    deordinalize => String
238                ];
239                define_gated_implementations![self;
240                    to_class_case => String,
241                    is_class_case => bool,
242                    to_table_case => String,
243                    is_table_case => bool,
244                    to_plural => String,
245                    to_singular => String,
246                    demodulize => String,
247                    deconstantize => String,
248                    articlize => String,
249                    dearticlize => String
250                ];
251            }
252        )*
253    }
254}
255
256macro_rules! implement_number_for {
257    ( $trt:ident; $($typ:ident), *) => {
258        $(
259            impl $trt for $typ {
260                define_number_implementations![self;
261                    ordinalize => String
262                ];
263            }
264        )*
265    }
266}
267
268implement_string_for![
269    Inflector;
270    String, str
271];
272
273implement_number_for![
274    InflectorNumbers;
275    i8, i16, i32, i64, u8, u16, u32, u64, isize, usize, f32, f64
276];
277
278#[cfg(all(feature = "unstable", test))]
279mod benchmarks {
280    extern crate test;
281    use self::test::Bencher;
282    use ::Inflector;
283
284    macro_rules! benchmarks {
285        ( $($test_name:ident => $imp_trait:ident => $to_cast:expr), *) => {
286            $(
287                #[bench]
288                fn $test_name(b: &mut Bencher) {
289                    b.iter(|| {
290                        $to_cast.$imp_trait()
291                    });
292                }
293            )*
294        }
295    }
296
297    benchmarks![
298        benchmark_str_to_camel => to_camel_case => "foo_bar",
299        benchmark_str_is_camel => is_camel_case => "fooBar",
300        benchmark_str_to_screaming_snake => to_screaming_snake_case => "fooBar",
301        benchmark_str_is_screaming_snake => is_screaming_snake_case => "FOO_BAR",
302        benchmark_str_to_snake => to_snake_case => "fooBar",
303        benchmark_str_is_snake => is_snake_case => "foo_bar",
304        benchmark_str_to_kebab => to_kebab_case => "fooBar",
305        benchmark_str_is_kebab => is_kebab_case => "foo-bar",
306        benchmark_str_to_train => to_train_case => "fooBar",
307        benchmark_str_is_train => is_train_case => "Foo-Bar",
308        benchmark_str_to_word => to_word_case => "fooBar",
309        benchmark_str_is_word => is_word_case => "foo bar",
310        benchmark_str_to_sentence => to_sentence_case => "fooBar",
311        benchmark_str_is_sentence => is_sentence_case => "Foo bar",
312        benchmark_str_to_title => to_title_case => "fooBar",
313        benchmark_str_is_title => is_title_case => "Foo Bar",
314        benchmark_str_ordinalize  => ordinalize => "1",
315        benchmark_str_deordinalize  => deordinalize => "1st",
316        benchmark_str_to_foreign_key => to_foreign_key => "Foo::Bar",
317        benchmark_str_is_foreign_key => is_foreign_key => "bar_id",
318        benchmark_string_to_camel => to_camel_case => "foo_bar".to_string(),
319        benchmark_string_is_camel => is_camel_case => "fooBar".to_string(),
320        benchmark_string_to_screaming_snake => to_screaming_snake_case => "fooBar".to_string(),
321        benchmark_string_is_screaming_snake => is_screaming_snake_case => "FOO_BAR".to_string(),
322        benchmark_string_to_snake => to_snake_case => "fooBar".to_string(),
323        benchmark_string_is_snake => is_snake_case => "foo_bar".to_string(),
324        benchmark_string_to_kebab => to_kebab_case => "fooBar".to_string(),
325        benchmark_string_is_kebab => is_kebab_case => "foo-bar".to_string(),
326        benchmark_string_to_train => to_train_case => "fooBar".to_string(),
327        benchmark_string_is_train => is_train_case => "Foo-Bar".to_string(),
328        benchmark_string_to_sentence => to_sentence_case => "fooBar".to_string(),
329        benchmark_string_is_sentence => is_sentence_case => "Foo bar".to_string(),
330        benchmark_string_to_title => to_title_case => "fooBar".to_string(),
331        benchmark_string_is_title => is_title_case => "Foo Bar".to_string(),
332        benchmark_string_ordinalize  => ordinalize => "1".to_string(),
333        benchmark_string_deordinalize  => deordinalize => "1st".to_string(),
334        benchmark_string_to_foreign_key => to_foreign_key => "Foo::Bar".to_string(),
335        benchmark_string_is_foreign_key => is_foreign_key => "bar_id".to_string()
336    ];
337
338    #[cfg(feature = "heavyweight")]
339    benchmarks![
340        benchmark_str_to_class => to_class_case => "foo",
341        benchmark_str_is_class => is_class_case => "Foo",
342        benchmark_str_to_table => to_table_case => "fooBar",
343        benchmark_str_is_table => is_table_case => "foo_bars",
344        benchmark_str_pluralize => to_plural => "crate",
345        benchmark_str_singular => to_singular => "crates",
346        benchmark_string_to_class => to_class_case => "foo".to_string(),
347        benchmark_string_is_class => is_class_case => "Foo".to_string(),
348        benchmark_string_to_table => to_table_case => "fooBar".to_string(),
349        benchmark_string_is_table => is_table_case => "foo_bars".to_string(),
350        benchmark_string_pluralize => to_plural => "crate".to_string(),
351        benchmark_string_singular => to_singular => "crates".to_string(),
352        benchmark_string_demodulize => demodulize => "Foo::Bar".to_string(),
353        benchmark_string_deconstantize => deconstantize => "Foo::Bar".to_string(),
354        benchmark_str_demodulize => demodulize => "Foo::Bar",
355        benchmark_str_deconstantize => deconstantize => "Foo::Bar",
356        benchmark_str_articlize => articlize => "crate",
357        benchmark_str_dearticlize => dearticlize => "a crate"
358    ];
359}