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}