clidi/cli/
validators.rs

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(&param) {
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}