1use super::DEFAULT_USERNAME_LABEL_SEPARATOR;
2use crate::context::Extensions;
3use crate::error::{BoxError, OpaqueError};
4use rama_utils::macros::all_the_tuples_no_last_special_case;
5use std::{convert::Infallible, fmt};
6
7#[inline]
10pub fn parse_username<P>(
11 ext: &mut Extensions,
12 parser: P,
13 username_ref: impl AsRef<str>,
14) -> Result<String, OpaqueError>
15where
16 P: UsernameLabelParser<Error: Into<BoxError>>,
17{
18 parse_username_with_separator(ext, parser, username_ref, DEFAULT_USERNAME_LABEL_SEPARATOR)
19}
20
21pub fn parse_username_with_separator<P>(
24 ext: &mut Extensions,
25 mut parser: P,
26 username_ref: impl AsRef<str>,
27 separator: char,
28) -> Result<String, OpaqueError>
29where
30 P: UsernameLabelParser<Error: Into<BoxError>>,
31{
32 let username_ref = username_ref.as_ref();
33 let mut label_it = username_ref.split(separator);
34
35 let username = match label_it.next() {
36 Some(username) => {
37 if username.is_empty() {
38 return Err(OpaqueError::from_display("empty username"));
39 } else {
40 username
41 }
42 }
43 None => return Err(OpaqueError::from_display("missing username")),
44 };
45
46 for (index, label) in label_it.enumerate() {
47 match parser.parse_label(label) {
48 UsernameLabelState::Used => (), UsernameLabelState::Ignored => {
50 return Err(OpaqueError::from_display(format!(
51 "ignored username label #{index}: {}",
52 label
53 )));
54 }
55 UsernameLabelState::Abort => {
56 return Err(OpaqueError::from_display(format!(
57 "invalid username label #{index}: {}",
58 label
59 )));
60 }
61 }
62 }
63
64 parser
65 .build(ext)
66 .map_err(|err| OpaqueError::from_boxed(err.into()))?;
67
68 Ok(username.to_owned())
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
76pub enum UsernameLabelState {
77 Used,
82
83 Ignored,
89
90 Abort,
93}
94
95pub trait UsernameLabelParser: Default + Send + Sync + 'static {
100 type Error: Into<BoxError>;
102
103 fn parse_label(&mut self, label: &str) -> UsernameLabelState;
107
108 fn build(self, ext: &mut Extensions) -> Result<(), Self::Error>;
110}
111
112pub struct ExclusiveUsernameParsers<P>(pub P);
115
116impl<P: Clone> Clone for ExclusiveUsernameParsers<P> {
117 fn clone(&self) -> Self {
118 Self(self.0.clone())
119 }
120}
121
122impl<P: Default> Default for ExclusiveUsernameParsers<P> {
123 fn default() -> Self {
124 Self(P::default())
125 }
126}
127
128impl<P: fmt::Debug> fmt::Debug for ExclusiveUsernameParsers<P> {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 f.debug_tuple("ExclusiveUsernameParsers")
131 .field(&self.0)
132 .finish()
133 }
134}
135
136macro_rules! username_label_parser_tuple_impl {
137 ($($T:ident),+ $(,)?) => {
138 #[allow(non_snake_case)]
139 impl<$($T,)+> UsernameLabelParser for ($($T,)+)
140 where
141 $(
142 $T: UsernameLabelParser<Error: Into<BoxError>>,
143 )+
144 {
145 type Error = OpaqueError;
146
147 fn parse_label(&mut self, label: &str) -> UsernameLabelState {
148 let ($($T,)+) = self;
149 let mut state = UsernameLabelState::Ignored;
150 $(
151 match $T.parse_label(label) {
152 UsernameLabelState::Ignored => (),
153 UsernameLabelState::Used => state = UsernameLabelState::Used,
154 UsernameLabelState::Abort => return UsernameLabelState::Abort,
155 }
156 )+
157 state
158 }
159
160 fn build(self, ext: &mut Extensions) -> Result<(), Self::Error> {
161 let ($($T,)+) = self;
162 $(
163 $T.build(ext).map_err(|err| OpaqueError::from_boxed(err.into()))?;
164 )+
165 Ok(())
166 }
167 }
168 };
169}
170
171all_the_tuples_no_last_special_case!(username_label_parser_tuple_impl);
172
173macro_rules! username_label_parser_tuple_exclusive_labels_impl {
174 ($($T:ident),+ $(,)?) => {
175 #[allow(non_snake_case)]
176 impl<$($T,)+> UsernameLabelParser for ExclusiveUsernameParsers<($($T,)+)>
177 where
178 $(
179 $T: UsernameLabelParser<Error: Into<BoxError>>,
180 )+
181 {
182 type Error = OpaqueError;
183
184 fn parse_label(&mut self, label: &str) -> UsernameLabelState {
185 let ($(ref mut $T,)+) = self.0;
186 $(
187 match $T.parse_label(label) {
188 UsernameLabelState::Ignored => (),
189 UsernameLabelState::Used => return UsernameLabelState::Used,
190 UsernameLabelState::Abort => return UsernameLabelState::Abort,
191 }
192 )+
193 UsernameLabelState::Ignored
194 }
195
196 fn build(self, ext: &mut Extensions) -> Result<(), Self::Error> {
197 let ($($T,)+) = self.0;
198 $(
199 $T.build(ext).map_err(|err| OpaqueError::from_boxed(err.into()))?;
200 )+
201 Ok(())
202 }
203 }
204 };
205}
206
207all_the_tuples_no_last_special_case!(username_label_parser_tuple_exclusive_labels_impl);
208
209impl UsernameLabelParser for () {
210 type Error = Infallible;
211
212 fn parse_label(&mut self, _label: &str) -> UsernameLabelState {
213 UsernameLabelState::Used
214 }
215
216 fn build(self, _ext: &mut Extensions) -> Result<(), Self::Error> {
217 Ok(())
218 }
219}
220
221#[derive(Debug, Clone, Default)]
222pub struct UsernameLabels(pub Vec<String>);
227
228impl<const SEPARATOR: char> super::UsernameLabelWriter<SEPARATOR> for UsernameLabels {
229 fn write_labels(
230 &self,
231 composer: &mut super::Composer<SEPARATOR>,
232 ) -> Result<(), super::ComposeError> {
233 self.0.write_labels(composer)
234 }
235}
236
237#[derive(Debug, Clone, Default)]
238pub struct UsernameOpaqueLabelParser {
241 labels: Vec<String>,
242}
243
244impl UsernameOpaqueLabelParser {
245 pub fn new() -> Self {
247 Self::default()
248 }
249}
250
251impl UsernameLabelParser for UsernameOpaqueLabelParser {
252 type Error = Infallible;
253
254 fn parse_label(&mut self, label: &str) -> UsernameLabelState {
255 self.labels.push(label.to_owned());
256 UsernameLabelState::Used
257 }
258
259 fn build(self, ext: &mut Extensions) -> Result<(), Self::Error> {
260 if !self.labels.is_empty() {
261 ext.insert(UsernameLabels(self.labels));
262 }
263 Ok(())
264 }
265}
266
267#[cfg(test)]
268mod test {
269 use super::*;
270
271 #[derive(Debug, Clone, Default)]
272 #[non_exhaustive]
273 struct UsernameNoLabelParser;
274
275 impl UsernameLabelParser for UsernameNoLabelParser {
276 type Error = Infallible;
277
278 fn parse_label(&mut self, _label: &str) -> UsernameLabelState {
279 UsernameLabelState::Ignored
280 }
281
282 fn build(self, _ext: &mut Extensions) -> Result<(), Self::Error> {
283 Ok(())
284 }
285 }
286
287 #[derive(Debug, Clone, Default)]
288 #[non_exhaustive]
289 struct UsernameNoLabelPanicParser;
290
291 impl UsernameLabelParser for UsernameNoLabelPanicParser {
292 type Error = Infallible;
293
294 fn parse_label(&mut self, _label: &str) -> UsernameLabelState {
295 unreachable!("this parser should not be called");
296 }
297
298 fn build(self, _ext: &mut Extensions) -> Result<(), Self::Error> {
299 Ok(())
300 }
301 }
302
303 #[derive(Debug, Clone, Default)]
304 #[non_exhaustive]
305 struct UsernameLabelAbortParser;
306
307 impl UsernameLabelParser for UsernameLabelAbortParser {
308 type Error = Infallible;
309
310 fn parse_label(&mut self, _label: &str) -> UsernameLabelState {
311 UsernameLabelState::Abort
312 }
313
314 fn build(self, _ext: &mut Extensions) -> Result<(), Self::Error> {
315 unreachable!("should not happen")
316 }
317 }
318
319 #[derive(Debug, Clone, Default)]
320 #[non_exhaustive]
321 struct MyLabelParser {
322 labels: Vec<String>,
323 }
324
325 #[derive(Debug, Clone, Default)]
326 struct MyLabels(Vec<String>);
327
328 impl UsernameLabelParser for MyLabelParser {
329 type Error = Infallible;
330
331 fn parse_label(&mut self, label: &str) -> UsernameLabelState {
332 self.labels.push(label.to_owned());
333 UsernameLabelState::Used
334 }
335
336 fn build(self, ext: &mut Extensions) -> Result<(), Self::Error> {
337 if !self.labels.is_empty() {
338 ext.insert(MyLabels(self.labels));
339 }
340 Ok(())
341 }
342 }
343
344 #[test]
345 fn test_parse_username_empty() {
346 let mut ext = Extensions::default();
347
348 assert!(parse_username(&mut ext, (), "",).is_err());
349 assert!(parse_username(&mut ext, (), "-",).is_err());
350 }
351
352 #[test]
353 fn test_parse_username_no_labels() {
354 let mut ext = Extensions::default();
355
356 assert_eq!(
357 parse_username(&mut ext, UsernameNoLabelParser, "username",).unwrap(),
358 "username"
359 );
360 }
361
362 #[test]
363 fn test_parse_username_label_collector() {
364 let mut ext = Extensions::default();
365 assert_eq!(
366 parse_username(
367 &mut ext,
368 UsernameOpaqueLabelParser::new(),
369 "username-label1-label2",
370 )
371 .unwrap(),
372 "username"
373 );
374
375 let labels = ext.get::<UsernameLabels>().unwrap();
376 assert_eq!(labels.0, vec!["label1".to_owned(), "label2".to_owned()]);
377 }
378
379 #[test]
380 fn test_username_labels_multi_parser() {
381 let mut ext = Extensions::default();
382
383 let parser = (
384 UsernameOpaqueLabelParser::new(),
385 UsernameNoLabelParser::default(),
386 );
387
388 assert_eq!(
389 parse_username(&mut ext, parser, "username-label1-label2",).unwrap(),
390 "username"
391 );
392
393 let labels = ext.get::<UsernameLabels>().unwrap();
394 assert_eq!(labels.0, vec!["label1".to_owned(), "label2".to_owned()]);
395 }
396
397 #[test]
398 fn test_username_labels_multi_consumer_parser() {
399 let mut ext = Extensions::default();
400
401 let parser = (
402 UsernameNoLabelParser::default(),
403 MyLabelParser::default(),
404 UsernameOpaqueLabelParser::new(),
405 );
406
407 assert_eq!(
408 parse_username(&mut ext, parser, "username-label1-label2",).unwrap(),
409 "username"
410 );
411
412 let labels = ext.get::<UsernameLabels>().unwrap();
413 assert_eq!(labels.0, vec!["label1".to_owned(), "label2".to_owned()]);
414
415 let labels = ext.get::<MyLabels>().unwrap();
416 assert_eq!(labels.0, vec!["label1".to_owned(), "label2".to_owned()]);
417 }
418
419 #[test]
420 fn test_username_labels_multi_consumer_exclusive_parsers() {
421 let mut ext = Extensions::default();
422
423 let parser = ExclusiveUsernameParsers((
424 UsernameOpaqueLabelParser::default(),
425 MyLabelParser::default(),
426 UsernameNoLabelPanicParser::default(),
427 ));
428
429 assert_eq!(
430 parse_username(&mut ext, parser, "username-label1-label2",).unwrap(),
431 "username"
432 );
433
434 let labels = ext.get::<UsernameLabels>().unwrap();
435 assert_eq!(labels.0, vec!["label1".to_owned(), "label2".to_owned()]);
436
437 assert!(ext.get::<MyLabels>().is_none());
438 }
439
440 #[test]
441 fn test_username_opaque_labels_none() {
442 let mut ext = Extensions::default();
443
444 let parser = UsernameOpaqueLabelParser::new();
445
446 assert_eq!(
447 parse_username(&mut ext, parser, "username",).unwrap(),
448 "username"
449 );
450
451 assert!(ext.get::<UsernameLabels>().is_none());
452 }
453
454 #[test]
455 fn test_username_label_parser_abort_tuple() {
456 let mut ext = Extensions::default();
457
458 let parser = (
459 UsernameLabelAbortParser::default(),
460 UsernameOpaqueLabelParser::default(),
461 );
462 assert!(parse_username(&mut ext, parser, "username-foo",).is_err());
463
464 let parser = (
465 UsernameOpaqueLabelParser::default(),
466 UsernameLabelAbortParser::default(),
467 );
468 assert!(parse_username(&mut ext, parser, "username-foo",).is_err());
469 }
470
471 #[test]
472 fn test_username_label_parser_abort_exclusive_tuple() {
473 let mut ext = Extensions::default();
474
475 let parser = ExclusiveUsernameParsers((
476 UsernameLabelAbortParser::default(),
477 UsernameOpaqueLabelParser::default(),
478 ));
479 assert!(parse_username(&mut ext, parser, "username-foo",).is_err());
480
481 let parser = (
482 UsernameOpaqueLabelParser::default(),
483 UsernameLabelAbortParser::default(),
484 );
485 assert!(parse_username(&mut ext, parser, "username-foo",).is_err());
486 }
487}