use std::io;
use std::io::Write;
use std::collections::HashSet;
pub fn h_input_data_single_f64(length: Option<u32>) -> Vec<f64> {
let mut count: u32 = 1;
let mut vec: Vec<f64> = Vec::new();
loop {
if length != None {
if (count - 1) == length.unwrap() && length.unwrap() > 0 {
return vec;
}
}
let mut input: String = String::new();
println!("data point {}: ", count);
if io::stdin()
.read_line(&mut input)
.is_err() {
println!("Failed to read line");
continue;
}
if input.trim() == ":q" {
return vec;
}
let num: f64 = match input.trim().parse() {
Ok(n) => n,
Err(_) => {
println!("Please enter a floating point number with 64 bits assigned to it");
continue;
}
};
vec.push(num);
count += 1;
}
}
pub fn h_input_data_single_i32(length: Option<u32>) -> Vec<i32> {
let mut count: u32 = 1;
let mut vec: Vec<i32> = vec![];
loop {
if length != None {
if (count - 1) == length.unwrap() && length.unwrap() > 0 {
return vec;
}
}
let mut input: String = String::new();
println!("data point {}: ", count);
if io::stdin()
.read_line(&mut input)
.is_err() {
println!("Failed to read line");
continue;
}
if input.trim() == ":q" {
return vec;
}
let num: i32 = match input.trim().parse() {
Ok(n) => n,
Err(_) => {
println!("Please enter an Integer NAX: 32 bits signed");
continue;
}
};
vec.push(num);
count += 1;
}
}
#[derive(PartialEq, Eq, Debug)]
pub enum InputType {
Lowercase,
Uppercase,
Letters, Integer,
}
pub trait ValidateInput {
fn h_validate_input(&self, input_requirements: InputType) -> Result<(), String>;
}
impl ValidateInput for String {
fn h_validate_input(&self, input_requirements: InputType) -> Result<(), String> {
if self.is_empty() {
return Err(String::from("The input is empty"));
}
if input_requirements == InputType::Lowercase {
if !self.chars().all(|c| c.is_ascii_lowercase()) {
let lowercase: HashSet<char> = ('a'..='z').collect();
let mut unexcpected: Vec<char> = vec![];
for c in self.chars() {
if !lowercase.contains(&c) {
unexcpected.push(c);
}
}
return Err(format!("Invalid input, lowercase letters only. Found: {:?}", unexcpected));
}
}
else if input_requirements == InputType::Uppercase {
if !self.chars().all(|c| c.is_ascii_uppercase()) {
let uppercase: HashSet<char> = ('A'..='Z').collect();
let mut unexcpected: Vec<char> = vec![];
for c in self.chars() {
if !uppercase.contains(&c) {
unexcpected.push(c);
}
}
return Err(format!("Invalid input, requirement: uppercase letters only. Found: {:?}", unexcpected));
}
}
else if input_requirements == InputType::Letters {
if !self.chars().all(|c: char| c.is_ascii_uppercase() || c.is_ascii_lowercase()) {
let characters: HashSet<char> = ('A'..='Z').chain('a'..='z').collect();
let mut unexcpected: Vec<char> = vec![];
for c in self.chars() {
if !characters.contains(&c) {
unexcpected.push(c);
}
}
return Err(format!("Invalid input, requirement: letters only. Found: {:?}", unexcpected));
}
}
else if input_requirements == InputType::Integer {
if self.parse::<i32>().is_err() {
let characters: HashSet<char> = ('0'..='9').collect();
let mut unexcpected: Vec<char> = vec![];
for c in self.chars() {
if !characters.contains(&c) {
unexcpected.push(c);
}
}
return Err(format!("Invalid input, requirement: whole Integer. Found: {:?}", unexcpected));
}
}
Ok(())
}
}
#[macro_export]
macro_rules! h_input {
($print:block, $in_type:ty, $stop_string:expr, $err_msg:expr) => {
{
let mut ret: Vec<$in_type> = Vec::new();
loop {
let mut input = String::new();
$print
io::stdout().flush().unwrap();
if io::stdin()
.read_line(&mut input)
.is_err() {
println!("Failed to read line");
continue;
}
if input.trim() == $stop_string {
break
}
let num: $in_type = match input.trim().parse() {
Ok(n) => n,
Err(_) => {
println!($err_msg);
continue;
}
};
ret.push(num);
}
ret
}
};
($print:block, $in_type:ty, $amount_of_inputs:expr, $err_msg:expr) => {
{
let mut ret: Vec<$in_type> = Vec::new();
let mut count: usize = 0;
loop {
if count >= $amount_of_inputs as usize {
break
}
let mut input = String::new();
$print
if io::stdin()
.read_line(&mut input)
.is_err() {
println!("Failed to read line");
continue;
}
let num: $in_type = match input.trim().parse() {
Ok(n) => n,
Err(_) => {
println!($err_msg);
continue;
}
};
count += 1;
ret.push(num);
}
ret
}
};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validate_input_lowercase_valid() {
let input = "hello".to_string();
assert!(input.h_validate_input(InputType::Lowercase).is_ok());
}
#[test]
fn test_validate_input_lowercase_invalid() {
let input = "Hello".to_string();
assert!(input.h_validate_input(InputType::Lowercase).is_err());
}
#[test]
fn test_validate_input_uppercase_valid() {
let input = "HELLO".to_string();
assert!(input.h_validate_input(InputType::Uppercase).is_ok());
}
#[test]
fn test_validate_input_uppercase_invalid() {
let input = "Hello".to_string();
assert!(input.h_validate_input(InputType::Uppercase).is_err());
}
#[test]
fn test_validate_input_letters_valid() {
let input = "HelloWorld".to_string();
assert!(input.h_validate_input(InputType::Letters).is_ok());
}
#[test]
fn test_validate_input_letters_invalid() {
let input = "Hello123".to_string();
assert!(input.h_validate_input(InputType::Letters).is_err());
}
#[test]
fn test_validate_input_integer_valid() {
let input = "123".to_string();
assert!(input.h_validate_input(InputType::Integer).is_ok());
}
#[test]
fn test_validate_input_integer_invalid() {
let input = "123a".to_string();
assert!(input.h_validate_input(InputType::Integer).is_err());
}
#[test]
fn test_validate_input_empty() {
let input = "".to_string();
assert!(input.h_validate_input(InputType::Lowercase).is_err());
}
}