use crate::{read_string, ReadData, ReadLine};
pub struct BoolInput;
impl ReadLine for BoolInput {
type Output = bool;
fn try_read_line(&self, mut read_data: ReadData<Self::Output>) -> crate::BoxResult<Self::Output> {
let mut prompt = read_data.prompt.unwrap_or(String::from("Enter a bool: "));
if let Some(default) = read_data.default.as_ref() {
prompt += &format!("(default: {default}) ");
}
loop {
print!("{prompt}");
let input = read_string(&mut read_data.input)?.to_lowercase();
match (&*input, read_data.default) {
("", Some(default)) => return Ok(default),
("true", _) | ("t", _) => return Ok(true),
("false", _) | ("f", _) => return Ok(false),
(_, _) => println!("Invalid input."),
}
}
}
}
pub struct YesNoInput;
impl ReadLine for YesNoInput {
type Output = bool;
fn try_read_line(&self, mut read_data: ReadData<Self::Output>) -> crate::BoxResult<Self::Output> {
let mut prompt = read_data.prompt.unwrap_or(String::from("Enter 'Yes' or 'No': "));
if let Some(default) = read_data.default.as_ref() {
prompt += &format!("(default: {}) ", if *default {"Yes"} else {"No"});
}
loop {
print!("{prompt}");
let input = read_string(&mut read_data.input)?.to_lowercase();
match (&*input, read_data.default) {
("", Some(default)) => return Ok(default),
("yes", _) | ("y", _) => return Ok(true),
("no", _) | ("n", _) => return Ok(false),
(_, _) => println!("Invalid input."),
}
}
}
}
macro_rules! implement_number_input {
($type_name:tt, $type_base:ty, $default_prompt:expr) => {
impl ReadLine for $type_name {
type Output = $type_base;
fn try_read_line(&self, mut read_data: ReadData<Self::Output>) -> crate::BoxResult<Self::Output> {
let mut prompt = read_data.prompt.unwrap_or(String::from($default_prompt));
if let Some(default) = read_data.default.as_ref() {
prompt += &format!("(default: {default}) ");
}
loop {
print!("{prompt}");
let input_string = read_string(&mut read_data.input)?.to_lowercase();
if input_string.is_empty() && let Some(default) = read_data.default {
return Ok(default);
}
let Ok(input) = input_string.parse::<$type_base>() else {
println!("Could not parse input.");
continue;
};
return Ok(input);
}
}
}
};
}
pub struct CharInput;
implement_number_input!(CharInput, char, "Enter a character: ");
pub struct UsizeInput;
implement_number_input!(UsizeInput, usize, "Enter an unsigned int: ");
pub struct IsizeInput;
implement_number_input!(IsizeInput, isize, "Enter an int: ");
pub struct U8Input;
implement_number_input!(U8Input, u8, "Enter an int (u8): ");
pub struct I8Input;
implement_number_input!(I8Input, i8, "Enter an int (i8): ");
pub struct U16Input;
implement_number_input!(U16Input, u16, "Enter an int (u16): ");
pub struct I16Input;
implement_number_input!(I16Input, i16, "Enter an int (i16): ");
pub struct U32Input;
implement_number_input!(U32Input, u32, "Enter an int (u32): ");
pub struct I32Input;
implement_number_input!(I32Input, i32, "Enter an int (i32): ");
pub struct U64Input;
implement_number_input!(U64Input, u64, "Enter an int (u64): ");
pub struct I64Input;
implement_number_input!(I64Input, i64, "Enter an int (i64): ");
pub struct U128Input;
implement_number_input!(U128Input, u128, "Enter an int (u128): ");
pub struct I128Input;
implement_number_input!(I128Input, i128, "Enter an int (i128): ");
pub struct F32Input;
implement_number_input!(F32Input, f32, "Enter a number: ");
pub struct F64Input;
implement_number_input!(F64Input, f64, "Enter a number: ");