1use crate::Pipe;
2use crate::case;
3
4pub struct Upper;
8
9impl Pipe for Upper {
10 type Input = String;
11 type Output = proc_macro2::Ident;
12
13 fn pipe(&self, input: String) -> proc_macro2::Ident {
14 proc_macro2::Ident::new(&input.to_uppercase(), proc_macro2::Span::call_site())
15 }
16}
17
18pub struct Lower;
22
23impl Pipe for Lower {
24 type Input = String;
25 type Output = proc_macro2::Ident;
26
27 fn pipe(&self, input: String) -> proc_macro2::Ident {
28 proc_macro2::Ident::new(&input.to_lowercase(), proc_macro2::Span::call_site())
29 }
30}
31
32pub struct Snake;
36
37impl Pipe for Snake {
38 type Input = String;
39 type Output = proc_macro2::Ident;
40
41 fn pipe(&self, input: String) -> proc_macro2::Ident {
42 proc_macro2::Ident::new(&case::to_snake(&input), proc_macro2::Span::call_site())
43 }
44}
45
46pub struct Camel;
50
51impl Pipe for Camel {
52 type Input = String;
53 type Output = proc_macro2::Ident;
54
55 fn pipe(&self, input: String) -> proc_macro2::Ident {
56 proc_macro2::Ident::new(&case::to_camel(&input), proc_macro2::Span::call_site())
57 }
58}
59
60pub struct Pascal;
64
65impl Pipe for Pascal {
66 type Input = String;
67 type Output = proc_macro2::Ident;
68
69 fn pipe(&self, input: String) -> proc_macro2::Ident {
70 proc_macro2::Ident::new(&case::to_pascal(&input), proc_macro2::Span::call_site())
71 }
72}
73
74pub struct Kebab;
81
82impl Pipe for Kebab {
83 type Input = String;
84 type Output = syn::LitStr;
85
86 fn pipe(&self, input: String) -> syn::LitStr {
87 syn::LitStr::new(&case::to_kebab(&input), proc_macro2::Span::call_site())
88 }
89}
90
91pub struct Screaming;
95
96impl Pipe for Screaming {
97 type Input = String;
98 type Output = proc_macro2::Ident;
99
100 fn pipe(&self, input: String) -> proc_macro2::Ident {
101 proc_macro2::Ident::new(&case::to_screaming(&input), proc_macro2::Span::call_site())
102 }
103}
104
105pub struct Ident(pub &'static str);
111
112impl Pipe for Ident {
113 type Input = String;
114 type Output = proc_macro2::Ident;
115
116 fn pipe(&self, input: String) -> proc_macro2::Ident {
117 let formatted = self.0.replace("{}", &input);
118 proc_macro2::Ident::new(&formatted, proc_macro2::Span::call_site())
119 }
120}
121
122pub struct Fmt(pub &'static str);
128
129impl Pipe for Fmt {
130 type Input = String;
131 type Output = syn::LitStr;
132
133 fn pipe(&self, input: String) -> syn::LitStr {
134 let formatted = self.0.replace("{}", &input);
135 syn::LitStr::new(&formatted, proc_macro2::Span::call_site())
136 }
137}
138
139pub struct Str;
143
144impl Pipe for Str {
145 type Input = String;
146 type Output = syn::LitStr;
147
148 fn pipe(&self, input: String) -> syn::LitStr {
149 syn::LitStr::new(&input, proc_macro2::Span::call_site())
150 }
151}
152
153pub struct Trim(pub &'static str, pub &'static str);
157
158impl Pipe for Trim {
159 type Input = String;
160 type Output = proc_macro2::Ident;
161
162 fn pipe(&self, input: String) -> proc_macro2::Ident {
163 let trimmed = input
164 .trim_start_matches(|c: char| self.0.contains(c))
165 .trim_end_matches(|c: char| self.1.contains(c));
166 proc_macro2::Ident::new(trimmed, proc_macro2::Span::call_site())
167 }
168}
169
170pub struct Plural;
174
175impl Pipe for Plural {
176 type Input = String;
177 type Output = proc_macro2::Ident;
178
179 fn pipe(&self, input: String) -> proc_macro2::Ident {
180 let result = if input.ends_with('y')
181 && input
182 .chars()
183 .rev()
184 .nth(1)
185 .is_some_and(|c| !"aeiou".contains(c))
186 {
187 format!("{}ies", &input[..input.len() - 1])
188 } else if input.ends_with('s')
189 || input.ends_with('x')
190 || input.ends_with('z')
191 || input.ends_with("ch")
192 || input.ends_with("sh")
193 {
194 format!("{}es", input)
195 } else {
196 format!("{}s", input)
197 };
198 proc_macro2::Ident::new(&result, proc_macro2::Span::call_site())
199 }
200}
201
202pub struct Singular;
206
207impl Pipe for Singular {
208 type Input = String;
209 type Output = proc_macro2::Ident;
210
211 fn pipe(&self, input: String) -> proc_macro2::Ident {
212 let result = if input.ends_with("ies") {
213 format!("{}y", &input[..input.len() - 3])
214 } else if input.ends_with("ses")
215 || input.ends_with("xes")
216 || input.ends_with("zes")
217 || input.ends_with("ches")
218 || input.ends_with("shes")
219 {
220 input[..input.len() - 2].to_string()
221 } else if input.ends_with('s') && !input.ends_with("ss") {
222 input[..input.len() - 1].to_string()
223 } else {
224 input
225 };
226 proc_macro2::Ident::new(&result, proc_macro2::Span::call_site())
227 }
228}