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}