use core::str;
use lazy_static::lazy_static;
use std::io::{self, BufRead};
pub mod basic_constraints;
pub mod constraints;
pub mod error;
pub mod prelude;
use constraints::*;
use error::{Error, ErrorKind, Result};
lazy_static! {
static ref IO_IN: io::Stdin = io::stdin();
}
pub fn input<T>() -> Result<T>
where
T: std::str::FromStr,
<T as str::FromStr>::Err: std::fmt::Display,
{
read_stream(IO_IN.lock())
}
pub fn cinput<T, C>(constraint: C) -> Result<T>
where
T: std::str::FromStr,
<T as str::FromStr>::Err: std::fmt::Display,
C: Constraint<T>,
{
let value = input()?;
constraint.validate(&value)?;
Ok(value)
}
pub fn string_input<T>(string: &String) -> Result<T>
where
T: std::str::FromStr,
<T as str::FromStr>::Err: std::fmt::Display,
{
string.parse::<T>().map_err(|err| Error {
kind: ErrorKind::ValidationError,
message: err.to_string(),
})
}
pub fn cstring_input<T, C>(string: &String, constraint: &C) -> Result<T>
where
T: std::str::FromStr,
<T as str::FromStr>::Err: std::fmt::Display,
C: Constraint<T>,
{
let value: T = string_input(string)?;
constraint.validate(&value)?;
Ok(value)
}
pub fn read_stream<R, T>(mut reader: R) -> Result<T>
where
R: BufRead,
T: std::str::FromStr,
<T as str::FromStr>::Err: std::fmt::Display,
{
let mut buf = String::new();
reader.read_line(&mut buf).map_err(|err| Error {
kind: ErrorKind::IOError,
message: err.to_string(),
})?;
string_input(&buf.trim().to_string())
}
pub fn cread_stream<R, T, C>(mut reader: R, constraint: &C) -> Result<T>
where
R: BufRead,
T: std::str::FromStr,
<T as str::FromStr>::Err: std::fmt::Display,
C: Constraint<T>,
{
let mut buf = String::new();
reader.read_line(&mut buf).map_err(|err| Error {
kind: ErrorKind::IOError,
message: err.to_string(),
})?;
cstring_input(&buf, constraint)
}