1use crate::entities::cli::use_case::ArgParseResult;
2use crate::entities::errors::CliArgError;
3use crate::proto::cli::IParamValidator;
4use std::any::{type_name, Any};
5use std::marker::PhantomData;
6use std::str::FromStr;
7
8pub struct EnumValidator {
9 variants: Vec<String>,
10 return_index: bool,
11}
12
13#[derive(Default)]
14pub struct BoolValidator {}
15#[derive(Default)]
16pub struct AsIsValidator {}
17#[derive(Default)]
18pub struct FromStrValidator<T> {
19 phantom: PhantomData<T>,
20}
21
22impl EnumValidator {
23 pub fn ret_values<T: ToString>(variants: &[T]) -> EnumValidator {
24 let variants = variants
25 .iter()
26 .map(|x| x.to_string())
27 .collect::<Vec<String>>();
28 EnumValidator {
29 variants,
30 return_index: false,
31 }
32 }
33
34 pub fn ret_indexes<T: ToString>(variants: &[T]) -> EnumValidator {
35 let mut validator = Self::ret_values(variants);
36 validator.return_index = true;
37 validator
38 }
39}
40
41impl IParamValidator for EnumValidator {
42 fn validate(&self, param: String) -> ArgParseResult {
43 for i in 0..self.variants.len() {
44 if self.variants[i] == param {
45 let dyn_val: Box<dyn Any> = if self.return_index {
46 Box::new(i)
47 } else {
48 Box::new(self.variants[i].clone())
49 };
50 return Ok(dyn_val);
51 }
52 }
53 Err(CliArgError::InvalidVariant(param))
54 }
55}
56
57impl IParamValidator for BoolValidator {
58 fn validate(&self, param: String) -> ArgParseResult {
59 const VARIANTS: &[(&str, bool)] = &[
60 ("1", true),
61 ("y", true),
62 ("t", true),
63 ("0", false),
64 ("n", false),
65 ("f", false),
66 ];
67 let param = param.to_lowercase();
68 for (var, val) in VARIANTS.iter() {
69 if *var == param {
70 return Ok(Box::new(*val));
71 }
72 }
73 Err(CliArgError::InvalidVariant(param))
74 }
75}
76
77impl IParamValidator for AsIsValidator {
78 fn validate(&self, param: String) -> ArgParseResult {
79 Ok(Box::new(param))
80 }
81}
82
83impl<T: FromStr + 'static> IParamValidator for FromStrValidator<T> {
84 fn validate(&self, param: String) -> ArgParseResult {
85 if let Ok(val) = T::from_str(¶m) {
86 return Ok(Box::new(val));
87 };
88 let msg = format!(
89 "invalid param: {}. Expected type: {}",
90 param,
91 type_name::<T>(),
92 );
93 Err(CliArgError::InvalidVariant(msg))
94 }
95}