1use dsntk_common::Jsonify;
4use std::fmt;
5
6#[derive(Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Clone)]
8pub struct Name(String);
9
10impl From<Vec<String>> for Name {
11 fn from(value: Vec<String>) -> Self {
13 Self::new(&value.iter().map(|string| string.as_str()).collect::<Vec<&str>>())
14 }
15}
16
17impl From<Vec<&str>> for Name {
18 fn from(value: Vec<&str>) -> Self {
20 Self::new(&value)
21 }
22}
23
24impl From<String> for Name {
25 fn from(value: String) -> Self {
27 Self(value.trim().to_string())
28 }
29}
30
31impl From<&String> for Name {
32 fn from(value: &String) -> Self {
34 Self(value.trim().to_string())
35 }
36}
37
38impl From<&str> for Name {
39 fn from(value: &str) -> Self {
41 Self(value.trim().to_string())
42 }
43}
44
45impl From<Name> for String {
46 fn from(value: Name) -> Self {
48 value.0
49 }
50}
51
52impl From<&Name> for String {
53 fn from(value: &Name) -> Self {
55 value.0.clone()
56 }
57}
58
59impl fmt::Display for Name {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 write!(f, "{}", self.0)
63 }
64}
65
66impl Jsonify for Name {
67 fn jsonify(&self) -> String {
69 self.0.clone()
70 }
71}
72
73impl Name {
74 pub fn new(parts: &[&str]) -> Self {
76 let mut result = String::with_capacity(80);
77 let mut current;
78 let mut prev = false;
79 for (index, part) in parts.iter().map(|s| s.trim()).enumerate() {
80 current = matches!(part, "." | "/" | "-" | "'" | "+" | "*");
81 if index > 0 && !prev && !current && !part.is_empty() {
82 result.push(' ');
83 }
84 result.push_str(part);
85 prev = current;
86 }
87 Self(result)
88 }
89
90 pub fn is_empty(&self) -> bool {
92 self.0.is_empty()
93 }
94}