Skip to main content

radiate_utils/
fmt.rs

1use crate::intern;
2
3#[inline]
4pub fn intern_kv_pair(name: &'static str, value: &'static str) -> &'static str {
5    crate::intern_str_cache!(name, value)
6}
7
8#[inline]
9pub fn short_type_name<T: ?Sized>() -> String {
10    // Walk the full type name and strip the module path of every segment, not
11    // just the head. Segments are delimited by `<`, `>`, `,`, or space; each
12    // segment becomes whatever follows its last `::`. So
13    // `module::Foo<other::Bar<u8>>` renders as `Foo<Bar<u8>>`.
14    let full = std::any::type_name::<T>();
15    let mut out = String::with_capacity(full.len());
16    let mut segment_start = 0usize;
17    for (i, c) in full.char_indices() {
18        if matches!(c, '<' | '>' | ',' | ' ') {
19            out.push_str(strip_path(&full[segment_start..i]));
20            out.push(c);
21            segment_start = i + c.len_utf8();
22        }
23    }
24
25    if segment_start < full.len() {
26        out.push_str(strip_path(&full[segment_start..]));
27    }
28
29    out
30}
31
32fn strip_path(segment: &str) -> &str {
33    match segment.rfind("::") {
34        Some(idx) => &segment[idx + 2..],
35        None => segment,
36    }
37}
38
39pub trait ToSnakeCase<O> {
40    fn to_snake_case(&self) -> O;
41}
42
43impl ToSnakeCase<String> for &'_ str {
44    fn to_snake_case(&self) -> String {
45        if self
46            .chars()
47            .all(|c| c.is_uppercase() || c.is_ascii_digit() || c == '_')
48        {
49            return self.to_string();
50        }
51
52        let mut snake_case = String::new();
53
54        for (i, c) in self.chars().enumerate() {
55            if c.is_uppercase() {
56                if i != 0 {
57                    snake_case.push('_');
58                }
59                for lower_c in c.to_lowercase() {
60                    snake_case.push(lower_c);
61                }
62            } else {
63                snake_case.push(c);
64            }
65        }
66        snake_case
67    }
68}
69
70impl ToSnakeCase<String> for String {
71    fn to_snake_case(&self) -> String {
72        if self
73            .chars()
74            .all(|c| c.is_uppercase() || c.is_ascii_digit() || c == '_')
75        {
76            return self.to_string();
77        }
78
79        let mut snake_case = String::new();
80
81        for (i, c) in self.chars().enumerate() {
82            if c.is_uppercase() {
83                if i != 0 {
84                    snake_case.push('_');
85                }
86                for lower_c in c.to_lowercase() {
87                    snake_case.push(lower_c);
88                }
89            } else {
90                snake_case.push(c);
91            }
92        }
93        snake_case
94    }
95}