crm_cli_utils/
parser.rs

1use inquire::validator::{ErrorMessage, Validation};
2use inquire::{Confirm, Text};
3use rust_decimal::Decimal;
4use solana_sdk::pubkey::Pubkey;
5use std::fs::File;
6use std::str::FromStr;
7
8pub trait Parser {
9    fn to_pubkey(self) -> Result<Pubkey, Box<dyn std::error::Error>>;
10    fn to_u128(self) -> Result<u128, Box<dyn std::error::Error>>;
11    fn to_u64(self) -> Result<u64, Box<dyn std::error::Error>>;
12    fn to_u16(self) -> Result<u16, Box<dyn std::error::Error>>;
13    fn to_f64(self) -> Result<f64, Box<dyn std::error::Error>>;
14    fn to_file(self) -> Result<String, Box<dyn std::error::Error>>;
15    fn to_string(self) -> Result<String, Box<dyn std::error::Error>>;
16    fn to_decimal(self) -> Result<Decimal, Box<dyn std::error::Error>>;
17    fn confirm() -> Result<(), Box<dyn std::error::Error>>;
18}
19
20impl Parser for Text<'_> {
21    fn to_pubkey(self) -> Result<Pubkey, Box<dyn std::error::Error>> {
22        let s = self
23            .with_validator(|s: &str| match Pubkey::from_str(s).is_err() {
24                true => Ok(Validation::Invalid(ErrorMessage::Custom(
25                    "wrong address".to_string(),
26                ))),
27                false => Ok(Validation::Valid),
28            })
29            .prompt()?;
30        Ok(Pubkey::from_str(s.as_str()).unwrap())
31    }
32
33    fn to_u128(self) -> Result<u128, Box<dyn std::error::Error>> {
34        let s = self
35            .with_validator(|s: &str| match s.parse::<u128>().is_err() {
36                true => Ok(Validation::Invalid(ErrorMessage::Custom(
37                    "wrong number with u128".to_string(),
38                ))),
39                false => Ok(Validation::Valid),
40            })
41            .prompt()?;
42        Ok(s.parse::<u128>().unwrap())
43    }
44
45    fn to_u64(self) -> Result<u64, Box<dyn std::error::Error>> {
46        let s = self
47            .with_validator(|s: &str| match s.parse::<u64>().is_err() {
48                true => Ok(Validation::Invalid(ErrorMessage::Custom(
49                    "wrong number with u64".to_string(),
50                ))),
51                false => Ok(Validation::Valid),
52            })
53            .prompt()?;
54        Ok(s.parse::<u64>().unwrap())
55    }
56
57    fn to_u16(self) -> Result<u16, Box<dyn std::error::Error>> {
58        let s = self
59            .with_validator(|s: &str| match s.parse::<u16>().is_err() {
60                true => Ok(Validation::Invalid(ErrorMessage::Custom(
61                    "wrong number with u16".to_string(),
62                ))),
63                false => Ok(Validation::Valid),
64            })
65            .prompt()?;
66        Ok(s.parse::<u16>().unwrap())
67    }
68
69    fn to_f64(self) -> Result<f64, Box<dyn std::error::Error>> {
70        let s = self
71            .with_validator(|s: &str| match s.parse::<f64>().is_err() {
72                true => Ok(Validation::Invalid(ErrorMessage::Custom(
73                    "wrong number with f64".to_string(),
74                ))),
75                false => Ok(Validation::Valid),
76            })
77            .prompt()?;
78        Ok(s.parse::<f64>().unwrap())
79    }
80
81    fn to_file(self) -> Result<String, Box<dyn std::error::Error>> {
82        let s = self
83            .with_validator(|s: &str| match File::open(s).is_err() {
84                true => Ok(Validation::Invalid(ErrorMessage::Custom(
85                    "wrong file path".to_string(),
86                ))),
87                false => Ok(Validation::Valid),
88            })
89            .prompt()?;
90        Ok(s)
91    }
92
93    fn to_string(self) -> Result<String, Box<dyn std::error::Error>> {
94        Ok(self.prompt()?)
95    }
96
97    fn to_decimal(self) -> Result<Decimal, Box<dyn std::error::Error>> {
98        let s = self
99            .with_validator(|s: &str| match Decimal::from_str(s).is_err() {
100                true => Ok(Validation::Invalid(ErrorMessage::Custom(
101                    "wrong decimal".to_string(),
102                ))),
103                false => Ok(Validation::Valid),
104            })
105            .prompt()?;
106        Ok(Decimal::from_str(s.as_str()).unwrap())
107    }
108
109    fn confirm() -> Result<(), Box<dyn std::error::Error>> {
110        let res = Confirm::new("Confirm this operation?")
111            .with_default(false)
112            .prompt();
113        match res {
114            Ok(true) => Ok(()),
115            Ok(false) => Err(Box::<dyn std::error::Error>::from("Cancel the operation")),
116            Err(_) => Err(Box::new(res.err().unwrap())),
117        }
118    }
119}