1use crate::Pipe;
35use crate::case;
36
37pub struct Upper;
41
42impl Pipe for Upper {
43 type Input = String;
44 type Output = proc_macro2::Ident;
45
46 fn pipe(&self, input: String) -> proc_macro2::Ident {
47 proc_macro2::Ident::new(&input.to_uppercase(), proc_macro2::Span::call_site())
48 }
49}
50
51pub struct Lower;
55
56impl Pipe for Lower {
57 type Input = String;
58 type Output = proc_macro2::Ident;
59
60 fn pipe(&self, input: String) -> proc_macro2::Ident {
61 proc_macro2::Ident::new(&input.to_lowercase(), proc_macro2::Span::call_site())
62 }
63}
64
65pub struct Snake;
69
70impl Pipe for Snake {
71 type Input = String;
72 type Output = proc_macro2::Ident;
73
74 fn pipe(&self, input: String) -> proc_macro2::Ident {
75 proc_macro2::Ident::new(&case::to_snake(&input), proc_macro2::Span::call_site())
76 }
77}
78
79pub struct Camel;
83
84impl Pipe for Camel {
85 type Input = String;
86 type Output = proc_macro2::Ident;
87
88 fn pipe(&self, input: String) -> proc_macro2::Ident {
89 proc_macro2::Ident::new(&case::to_camel(&input), proc_macro2::Span::call_site())
90 }
91}
92
93pub struct Pascal;
97
98impl Pipe for Pascal {
99 type Input = String;
100 type Output = proc_macro2::Ident;
101
102 fn pipe(&self, input: String) -> proc_macro2::Ident {
103 proc_macro2::Ident::new(&case::to_pascal(&input), proc_macro2::Span::call_site())
104 }
105}
106
107pub struct Kebab;
114
115impl Pipe for Kebab {
116 type Input = String;
117 type Output = syn::LitStr;
118
119 fn pipe(&self, input: String) -> syn::LitStr {
120 syn::LitStr::new(&case::to_kebab(&input), proc_macro2::Span::call_site())
121 }
122}
123
124pub struct Screaming;
128
129impl Pipe for Screaming {
130 type Input = String;
131 type Output = proc_macro2::Ident;
132
133 fn pipe(&self, input: String) -> proc_macro2::Ident {
134 proc_macro2::Ident::new(&case::to_screaming(&input), proc_macro2::Span::call_site())
135 }
136}
137
138pub struct Ident(pub &'static str);
144
145impl Pipe for Ident {
146 type Input = String;
147 type Output = proc_macro2::Ident;
148
149 fn pipe(&self, input: String) -> proc_macro2::Ident {
150 let formatted = self.0.replace("{}", &input);
151 proc_macro2::Ident::new(&formatted, proc_macro2::Span::call_site())
152 }
153}
154
155pub struct Fmt(pub &'static str);
161
162impl Pipe for Fmt {
163 type Input = String;
164 type Output = syn::LitStr;
165
166 fn pipe(&self, input: String) -> syn::LitStr {
167 let formatted = self.0.replace("{}", &input);
168 syn::LitStr::new(&formatted, proc_macro2::Span::call_site())
169 }
170}
171
172pub struct Str;
176
177impl Pipe for Str {
178 type Input = String;
179 type Output = syn::LitStr;
180
181 fn pipe(&self, input: String) -> syn::LitStr {
182 syn::LitStr::new(&input, proc_macro2::Span::call_site())
183 }
184}
185
186pub struct Trim(pub &'static str, pub &'static str);
190
191impl Pipe for Trim {
192 type Input = String;
193 type Output = proc_macro2::Ident;
194
195 fn pipe(&self, input: String) -> proc_macro2::Ident {
196 let trimmed = input
197 .trim_start_matches(|c: char| self.0.contains(c))
198 .trim_end_matches(|c: char| self.1.contains(c));
199 proc_macro2::Ident::new(trimmed, proc_macro2::Span::call_site())
200 }
201}
202
203pub struct Plural;
207
208impl Pipe for Plural {
209 type Input = String;
210 type Output = proc_macro2::Ident;
211
212 fn pipe(&self, input: String) -> proc_macro2::Ident {
213 let result = if input.ends_with('y')
214 && input
215 .chars()
216 .rev()
217 .nth(1)
218 .is_some_and(|c| !"aeiou".contains(c))
219 {
220 format!("{}ies", &input[..input.len() - 1])
221 } else if input.ends_with('s')
222 || input.ends_with('x')
223 || input.ends_with('z')
224 || input.ends_with("ch")
225 || input.ends_with("sh")
226 {
227 format!("{}es", input)
228 } else {
229 format!("{}s", input)
230 };
231 proc_macro2::Ident::new(&result, proc_macro2::Span::call_site())
232 }
233}
234
235pub struct Singular;
239
240impl Pipe for Singular {
241 type Input = String;
242 type Output = proc_macro2::Ident;
243
244 fn pipe(&self, input: String) -> proc_macro2::Ident {
245 let result = if input.ends_with("ies") {
246 format!("{}y", &input[..input.len() - 3])
247 } else if input.ends_with("ses")
248 || input.ends_with("xes")
249 || input.ends_with("zes")
250 || input.ends_with("ches")
251 || input.ends_with("shes")
252 {
253 input[..input.len() - 2].to_string()
254 } else if input.ends_with('s') && !input.ends_with("ss") {
255 input[..input.len() - 1].to_string()
256 } else {
257 input
258 };
259 proc_macro2::Ident::new(&result, proc_macro2::Span::call_site())
260 }
261}