elicitation/primitives/
unit_structs.rs1use crate::{ElicitClient, ElicitResult, Elicitation, Generator, Prompt};
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
56pub struct Validator;
57
58impl Validator {
59 pub fn is_utf8(&self, bytes: &[u8]) -> bool {
61 std::str::from_utf8(bytes).is_ok()
62 }
63
64 pub fn is_non_empty(&self, s: &str) -> bool {
66 !s.is_empty()
67 }
68
69 pub fn is_in_range<T: PartialOrd>(&self, value: T, min: T, max: T) -> bool {
71 value >= min && value <= max
72 }
73}
74
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
77pub struct Formatter;
78
79impl Formatter {
80 pub fn uppercase(&self, s: &str) -> String {
82 s.to_uppercase()
83 }
84
85 pub fn lowercase(&self, s: &str) -> String {
87 s.to_lowercase()
88 }
89
90 pub fn trim(&self, s: &str) -> String {
92 s.trim().to_string()
93 }
94}
95
96#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
98pub struct Parser;
99
100impl Parser {
101 pub fn parse_int(&self, s: &str) -> Result<i64, std::num::ParseIntError> {
103 s.parse()
104 }
105
106 pub fn parse_float(&self, s: &str) -> Result<f64, std::num::ParseFloatError> {
108 s.parse()
109 }
110
111 pub fn parse_bool(&self, s: &str) -> Result<bool, std::str::ParseBoolError> {
113 s.parse()
114 }
115}
116
117impl Generator for Validator {
125 type Target = Self;
126
127 fn generate(&self) -> Self::Target {
128 Validator
129 }
130}
131
132impl Generator for Formatter {
133 type Target = Self;
134
135 fn generate(&self) -> Self::Target {
136 Formatter
137 }
138}
139
140impl Generator for Parser {
141 type Target = Self;
142
143 fn generate(&self) -> Self::Target {
144 Parser
145 }
146}
147
148crate::default_style!(Validator => ValidatorStyle);
157crate::default_style!(Formatter => FormatterStyle);
158crate::default_style!(Parser => ParserStyle);
159
160impl Prompt for Validator {
161 fn prompt() -> Option<&'static str> {
162 Some("Create a Validator instance (unit struct - only one value)")
163 }
164}
165
166impl Elicitation for Validator {
167 type Style = ValidatorStyle;
168
169 async fn elicit(_client: &ElicitClient) -> ElicitResult<Self> {
170 tracing::debug!("Eliciting Validator (unit struct)");
171
172 Ok(Validator)
175 }
176}
177
178impl Prompt for Formatter {
179 fn prompt() -> Option<&'static str> {
180 Some("Create a Formatter instance (unit struct - only one value)")
181 }
182}
183
184impl Elicitation for Formatter {
185 type Style = FormatterStyle;
186
187 async fn elicit(_client: &ElicitClient) -> ElicitResult<Self> {
188 tracing::debug!("Eliciting Formatter (unit struct)");
189 Ok(Formatter)
190 }
191}
192
193impl Prompt for Parser {
194 fn prompt() -> Option<&'static str> {
195 Some("Create a Parser instance (unit struct - only one value)")
196 }
197}
198
199impl Elicitation for Parser {
200 type Style = ParserStyle;
201
202 async fn elicit(_client: &ElicitClient) -> ElicitResult<Self> {
203 tracing::debug!("Eliciting Parser (unit struct)");
204 Ok(Parser)
205 }
206}
207
208#[cfg(test)]
209mod tests {
210 use super::*;
211
212 #[test]
213 fn test_validator_methods() {
214 let v = Validator;
215 assert!(v.is_utf8(b"hello"));
216 assert!(!v.is_utf8(b"\xFF\xFE"));
217 assert!(v.is_non_empty("test"));
218 assert!(!v.is_non_empty(""));
219 assert!(v.is_in_range(5, 0, 10));
220 assert!(!v.is_in_range(15, 0, 10));
221 }
222
223 #[test]
224 fn test_formatter_methods() {
225 let f = Formatter;
226 assert_eq!(f.uppercase("hello"), "HELLO");
227 assert_eq!(f.lowercase("WORLD"), "world");
228 assert_eq!(f.trim(" test "), "test");
229 }
230
231 #[test]
232 fn test_parser_methods() {
233 let p = Parser;
234 assert_eq!(p.parse_int("42").unwrap(), 42);
235 let result = p.parse_float("2.5").unwrap();
236 assert!((result - 2.5_f64).abs() < 0.001);
237 assert!(p.parse_bool("true").unwrap());
238 }
239
240 #[test]
241 fn test_generator_trivial() {
242 let v = Validator;
243 assert_eq!(v.generate(), Validator);
244
245 let f = Formatter;
246 assert_eq!(f.generate(), Formatter);
247
248 let p = Parser;
249 assert_eq!(p.generate(), Parser);
250 }
251}