cetus_utils/
inquire_parser.rs

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