Skip to main content

icydb_utils/case/
mod.rs

1mod constant;
2mod snake;
3mod title;
4
5use convert_case as cc;
6use std::fmt::{self, Display};
7
8pub use snake::to_snake_case;
9
10///
11/// Case
12///
13/// Supported case conversion targets shared across schema, derive, and runtime
14/// surfaces.
15///
16
17#[derive(Clone, Copy, Debug)]
18pub enum Case {
19    Camel,
20    Constant,
21    Kebab,
22    Lower,
23    Sentence,
24    Snake,
25    Title,
26    Upper,
27    UpperCamel,
28    UpperSnake,
29    UpperKebab,
30}
31
32impl Display for Case {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        let label = match self {
35            Self::Camel => "Camel",
36            Self::Constant => "Constant",
37            Self::Kebab => "Kebab",
38            Self::Lower => "Lower",
39            Self::Sentence => "Sentence",
40            Self::Snake => "Snake",
41            Self::Title => "Title",
42            Self::Upper => "Upper",
43            Self::UpperCamel => "UpperCamel",
44            Self::UpperSnake => "UpperSnake",
45            Self::UpperKebab => "UpperKebab",
46        };
47
48        f.write_str(label)
49    }
50}
51
52///
53/// Casing
54///
55/// Shared string case conversion surface retained locally so workspace crates
56/// do not depend on `canic-utils` for text casing.
57///
58
59pub trait Casing<T: std::fmt::Display> {
60    /// Convert the receiver into the requested case form.
61    fn to_case(&self, case: Case) -> String;
62
63    /// Return whether the receiver is already in the requested case form.
64    fn is_case(&self, case: Case) -> bool;
65}
66
67impl<T: std::fmt::Display> Casing<T> for T
68where
69    String: PartialEq<T>,
70{
71    fn to_case(&self, case: Case) -> String {
72        let s = &self.to_string();
73
74        match case {
75            Case::Lower => s.to_lowercase(),
76            Case::Upper => s.to_uppercase(),
77            Case::Title => title::to_title_case(s),
78            Case::Snake => snake::to_snake_case(s),
79            Case::UpperSnake => snake::to_snake_case(s).to_uppercase(),
80            Case::Constant => constant::to_constant_case(s).to_uppercase(),
81            Case::Camel => cc::Casing::to_case(s, cc::Case::Camel),
82            Case::Kebab => cc::Casing::to_case(s, cc::Case::Kebab),
83            Case::Sentence => cc::Casing::to_case(s, cc::Case::Sentence),
84            Case::UpperCamel => cc::Casing::to_case(s, cc::Case::UpperCamel),
85            Case::UpperKebab => cc::Casing::to_case(s, cc::Case::Kebab).to_uppercase(),
86        }
87    }
88
89    fn is_case(&self, case: Case) -> bool {
90        &self.to_case(case) == self
91    }
92}