toasty_core/schema/name.rs
1use heck::{ToLowerCamelCase, ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase};
2
3/// A multi-part identifier that can be rendered in various casing conventions.
4///
5/// `Name` stores the identifier as individual lowercase words (parts). It is
6/// created from a string in any common casing style (snake_case, camelCase,
7/// PascalCase) and can be converted back to any of those forms.
8///
9/// # Examples
10///
11/// ```
12/// use toasty_core::schema::Name;
13///
14/// let name = Name::new("UserProfile");
15/// assert_eq!(name.snake_case(), "user_profile");
16/// assert_eq!(name.upper_camel_case(), "UserProfile");
17/// assert_eq!(name.camel_case(), "userProfile");
18/// assert_eq!(name.upper_snake_case(), "USER_PROFILE");
19/// ```
20#[derive(Debug, Clone, Eq, PartialEq, Hash)]
21pub struct Name {
22 /// The individual lowercase word parts of this name.
23 pub parts: Vec<String>,
24}
25
26impl Name {
27 /// Creates a new `Name` by splitting `src` into word parts.
28 ///
29 /// The input is first converted to snake_case, then split on underscores.
30 ///
31 /// # Examples
32 ///
33 /// ```
34 /// use toasty_core::schema::Name;
35 ///
36 /// let name = Name::new("myField");
37 /// assert_eq!(name.parts, vec!["my", "field"]);
38 /// ```
39 pub fn new(src: &str) -> Self {
40 // TODO: make better
41 let snake = src.to_snake_case();
42 let parts = snake.split("_").map(String::from).collect();
43 Self { parts }
44 }
45
46 /// Returns this name in `camelCase`.
47 ///
48 /// # Examples
49 ///
50 /// ```
51 /// use toasty_core::schema::Name;
52 ///
53 /// assert_eq!(Name::new("user_id").camel_case(), "userId");
54 /// ```
55 pub fn camel_case(&self) -> String {
56 self.snake_case().to_lower_camel_case()
57 }
58
59 /// Returns this name in `UpperCamelCase` (PascalCase).
60 ///
61 /// # Examples
62 ///
63 /// ```
64 /// use toasty_core::schema::Name;
65 ///
66 /// assert_eq!(Name::new("user_id").upper_camel_case(), "UserId");
67 /// ```
68 pub fn upper_camel_case(&self) -> String {
69 self.snake_case().to_upper_camel_case()
70 }
71
72 /// Returns this name in `snake_case`.
73 ///
74 /// # Examples
75 ///
76 /// ```
77 /// use toasty_core::schema::Name;
78 ///
79 /// assert_eq!(Name::new("UserProfile").snake_case(), "user_profile");
80 /// ```
81 pub fn snake_case(&self) -> String {
82 self.parts.join("_")
83 }
84
85 /// Returns this name in `UPPER_SNAKE_CASE`.
86 ///
87 /// # Examples
88 ///
89 /// ```
90 /// use toasty_core::schema::Name;
91 ///
92 /// assert_eq!(Name::new("user_id").upper_snake_case(), "USER_ID");
93 /// ```
94 pub fn upper_snake_case(&self) -> String {
95 self.snake_case().to_shouty_snake_case()
96 }
97}
98
99impl core::fmt::Display for Name {
100 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
101 f.write_str(&self.upper_camel_case())
102 }
103}