16fccd0a4Sopenharmony_ciuse std::fmt; 26fccd0a4Sopenharmony_ci 36fccd0a4Sopenharmony_ciuse crate::{lowercase, transform}; 46fccd0a4Sopenharmony_ci 56fccd0a4Sopenharmony_ci/// This trait defines a snake case conversion. 66fccd0a4Sopenharmony_ci/// 76fccd0a4Sopenharmony_ci/// In snake_case, word boundaries are indicated by underscores. 86fccd0a4Sopenharmony_ci/// 96fccd0a4Sopenharmony_ci/// ## Example: 106fccd0a4Sopenharmony_ci/// 116fccd0a4Sopenharmony_ci/// ```rust 126fccd0a4Sopenharmony_ci/// use heck::ToSnakeCase; 136fccd0a4Sopenharmony_ci/// 146fccd0a4Sopenharmony_ci/// let sentence = "We carry a new world here, in our hearts."; 156fccd0a4Sopenharmony_ci/// assert_eq!(sentence.to_snake_case(), "we_carry_a_new_world_here_in_our_hearts"); 166fccd0a4Sopenharmony_ci/// ``` 176fccd0a4Sopenharmony_cipub trait ToSnakeCase: ToOwned { 186fccd0a4Sopenharmony_ci /// Convert this type to snake case. 196fccd0a4Sopenharmony_ci fn to_snake_case(&self) -> Self::Owned; 206fccd0a4Sopenharmony_ci} 216fccd0a4Sopenharmony_ci 226fccd0a4Sopenharmony_ci/// Oh heck, SnekCase is an alias for ToSnakeCase. See ToSnakeCase for 236fccd0a4Sopenharmony_ci/// more documentation. 246fccd0a4Sopenharmony_cipub trait ToSnekCase: ToOwned { 256fccd0a4Sopenharmony_ci /// Convert this type to snek case. 266fccd0a4Sopenharmony_ci fn to_snek_case(&self) -> Self::Owned; 276fccd0a4Sopenharmony_ci} 286fccd0a4Sopenharmony_ci 296fccd0a4Sopenharmony_ciimpl<T: ?Sized + ToSnakeCase> ToSnekCase for T { 306fccd0a4Sopenharmony_ci fn to_snek_case(&self) -> Self::Owned { 316fccd0a4Sopenharmony_ci self.to_snake_case() 326fccd0a4Sopenharmony_ci } 336fccd0a4Sopenharmony_ci} 346fccd0a4Sopenharmony_ci 356fccd0a4Sopenharmony_ciimpl ToSnakeCase for str { 366fccd0a4Sopenharmony_ci fn to_snake_case(&self) -> String { 376fccd0a4Sopenharmony_ci AsSnakeCase(self).to_string() 386fccd0a4Sopenharmony_ci } 396fccd0a4Sopenharmony_ci} 406fccd0a4Sopenharmony_ci 416fccd0a4Sopenharmony_ci/// This wrapper performs a snake case conversion in [`fmt::Display`]. 426fccd0a4Sopenharmony_ci/// 436fccd0a4Sopenharmony_ci/// ## Example: 446fccd0a4Sopenharmony_ci/// 456fccd0a4Sopenharmony_ci/// ``` 466fccd0a4Sopenharmony_ci/// use heck::AsSnakeCase; 476fccd0a4Sopenharmony_ci/// 486fccd0a4Sopenharmony_ci/// let sentence = "We carry a new world here, in our hearts."; 496fccd0a4Sopenharmony_ci/// assert_eq!(format!("{}", AsSnakeCase(sentence)), "we_carry_a_new_world_here_in_our_hearts"); 506fccd0a4Sopenharmony_ci/// ``` 516fccd0a4Sopenharmony_cipub struct AsSnakeCase<T: AsRef<str>>(pub T); 526fccd0a4Sopenharmony_ci 536fccd0a4Sopenharmony_ciimpl<T: AsRef<str>> fmt::Display for AsSnakeCase<T> { 546fccd0a4Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 556fccd0a4Sopenharmony_ci transform(self.0.as_ref(), lowercase, |f| write!(f, "_"), f) 566fccd0a4Sopenharmony_ci } 576fccd0a4Sopenharmony_ci} 586fccd0a4Sopenharmony_ci 596fccd0a4Sopenharmony_ci#[cfg(test)] 606fccd0a4Sopenharmony_cimod tests { 616fccd0a4Sopenharmony_ci use super::ToSnakeCase; 626fccd0a4Sopenharmony_ci 636fccd0a4Sopenharmony_ci macro_rules! t { 646fccd0a4Sopenharmony_ci ($t:ident : $s1:expr => $s2:expr) => { 656fccd0a4Sopenharmony_ci #[test] 666fccd0a4Sopenharmony_ci fn $t() { 676fccd0a4Sopenharmony_ci assert_eq!($s1.to_snake_case(), $s2) 686fccd0a4Sopenharmony_ci } 696fccd0a4Sopenharmony_ci }; 706fccd0a4Sopenharmony_ci } 716fccd0a4Sopenharmony_ci 726fccd0a4Sopenharmony_ci t!(test1: "CamelCase" => "camel_case"); 736fccd0a4Sopenharmony_ci t!(test2: "This is Human case." => "this_is_human_case"); 746fccd0a4Sopenharmony_ci t!(test3: "MixedUP CamelCase, with some Spaces" => "mixed_up_camel_case_with_some_spaces"); 756fccd0a4Sopenharmony_ci t!(test4: "mixed_up_ snake_case with some _spaces" => "mixed_up_snake_case_with_some_spaces"); 766fccd0a4Sopenharmony_ci t!(test5: "kebab-case" => "kebab_case"); 776fccd0a4Sopenharmony_ci t!(test6: "SHOUTY_SNAKE_CASE" => "shouty_snake_case"); 786fccd0a4Sopenharmony_ci t!(test7: "snake_case" => "snake_case"); 796fccd0a4Sopenharmony_ci t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "this_contains_all_kinds_of_word_boundaries"); 806fccd0a4Sopenharmony_ci #[cfg(feature = "unicode")] 816fccd0a4Sopenharmony_ci t!(test9: "XΣXΣ baffle" => "xσxς_baffle"); 826fccd0a4Sopenharmony_ci t!(test10: "XMLHttpRequest" => "xml_http_request"); 836fccd0a4Sopenharmony_ci t!(test11: "FIELD_NAME11" => "field_name11"); 846fccd0a4Sopenharmony_ci t!(test12: "99BOTTLES" => "99bottles"); 856fccd0a4Sopenharmony_ci t!(test13: "FieldNamE11" => "field_nam_e11"); 866fccd0a4Sopenharmony_ci 876fccd0a4Sopenharmony_ci t!(test14: "abc123def456" => "abc123def456"); 886fccd0a4Sopenharmony_ci t!(test16: "abc123DEF456" => "abc123_def456"); 896fccd0a4Sopenharmony_ci t!(test17: "abc123Def456" => "abc123_def456"); 906fccd0a4Sopenharmony_ci t!(test18: "abc123DEf456" => "abc123_d_ef456"); 916fccd0a4Sopenharmony_ci t!(test19: "ABC123def456" => "abc123def456"); 926fccd0a4Sopenharmony_ci t!(test20: "ABC123DEF456" => "abc123def456"); 936fccd0a4Sopenharmony_ci t!(test21: "ABC123Def456" => "abc123_def456"); 946fccd0a4Sopenharmony_ci t!(test22: "ABC123DEf456" => "abc123d_ef456"); 956fccd0a4Sopenharmony_ci t!(test23: "ABC123dEEf456FOO" => "abc123d_e_ef456_foo"); 966fccd0a4Sopenharmony_ci t!(test24: "abcDEF" => "abc_def"); 976fccd0a4Sopenharmony_ci t!(test25: "ABcDE" => "a_bc_de"); 986fccd0a4Sopenharmony_ci} 99