1mod tests;
2
3use std::any::TypeId;
4use std::fmt::Display;
5use std::io::stdin;
6use std::io::stdout;
7use std::io::BufRead;
8use std::io::Write;
9use std::str::FromStr;
10
11pub fn once<T>() -> Result<T, <T as FromStr>::Err>
25where
26 T: FromStr + 'static,
27{
28 let mut stdin = stdin().lock();
29 let mut buf: String = String::new();
30
31 while stdin.read_line(&mut buf).is_err() {
32 println!("Failed to read line. Please try again.");
33 }
34
35 if TypeId::of::<T>() != TypeId::of::<String>() {
36 buf = buf.trim().to_string();
37 }
38
39 buf.parse::<T>()
40}
41
42pub fn until_ok<T>() -> T
54where
55 T: FromStr + 'static,
56{
57 loop {
58 match once::<T>() {
59 Ok(value) => return value,
60 Err(_) => {
61 println!("Failed to parse. Please input a correct data type.");
62 continue;
63 }
64 }
65 }
66}
67
68pub fn prompt<T>(prompt: &(impl ToString + Display + ?Sized)) -> Result<T, <T as FromStr>::Err>
82where
83 T: FromStr + 'static,
84{
85 let mut stdout = stdout().lock();
86
87 print!("{}", prompt);
88 stdout.flush().expect("Failed to flush stdout");
89 once()
90}
91
92pub fn prompt_until_ok<T>(prompt: &(impl ToString + Display + ?Sized)) -> T
103where
104 T: FromStr + 'static,
105{
106 let mut stdout = stdout().lock();
107
108 loop {
109 print!("{}", prompt);
110 stdout.flush().expect("Failed to flush stdout");
111 match once::<T>() {
112 Ok(value) => return value,
113 Err(_) => {
114 println!("Failed to parse. Please input a correct data type.");
115 continue;
116 }
117 }
118 };
119}
120
121#[deprecated(since = "1.1.0", note = "Use `until_ok` instead.")]
123pub fn read_stdin_until_ok<T>() -> T
124where
125 T: FromStr + 'static,
126{
127 until_ok()
128}
129
130#[deprecated(since = "1.1.0", note = "Use `once` instead.")]
131pub fn read_stdin<T>() -> Result<T, <T as FromStr>::Err>
132where
133 T: FromStr + 'static,
134{
135 once()
136}