#![forbid(unsafe_code)]
#![forbid(missing_docs)]
use thiserror::Error;
#[derive(Debug, Error)]
#[error(transparent)]
pub enum Error<E> {
Fetch(std::io::Error),
Parse(E),
}
pub type Result<T, E> = std::result::Result<T, Error<E>>;
pub const FETCH_ERROR: &str = "I/O error occured while fetching input";
#[macro_export]
macro_rules! tiny_input {
(as $type: ty $(, $($token: tt)+)?) => {
$crate::raw_input!($($($token)+)?).expect($crate::FETCH_ERROR).parse::<$type>()
};
($($token: tt)*) => {
$crate::raw_input!($($token)*).expect($crate::FETCH_ERROR).parse()
};
}
#[macro_export]
macro_rules! input {
(as $type: ty $(, $($token: tt)+)?) => {
$crate::raw_input!($($($token)+)?)
.map_err($crate::Error::Fetch)
.and_then(|string| string.parse::<$type>().map_err($crate::Error::Parse))
};
($($token: tt)*) => {
$crate::raw_input!($($token)*)
.map_err($crate::Error::Fetch)
.and_then(|string| string.parse().map_err($crate::Error::Parse))
};
}
#[macro_export]
macro_rules! raw_input {
($($token: tt)+) => {{
use ::std::io::Write;
let mut stdout = ::std::io::stdout().lock();
match write!(stdout, $($token)+) {
Ok(_) => match stdout.flush() {
Ok(_) => $crate::raw_input!(),
Err(error) => Err(error),
},
Err(error) => Err(error),
}
}};
() => {{
use ::std::io::BufRead;
let mut string = ::std::string::String::new();
match ::std::io::stdin().lock().read_line(&mut string) {
Ok(_) => {
string.pop();
Ok(string)
},
Err(error) => Err(error),
}
}};
}