mod helpers;
use std::any::TypeId;
use std::fs::File;
use std::io::{self, Read, Stdin};
use std::str::FromStr;
pub trait Import {
fn import<T: FromStr + 'static>(&self) -> io::Result<T>;
}
impl Import for Stdin {
fn import<T: FromStr + 'static>(&self) -> io::Result<T> {
let mut data = String::new();
let _ = self.read_line(&mut data)?;
data.trim().parse::<T>().map_err(|_| helpers::parse_error())
}
}
impl Import for File {
fn import<T: FromStr + 'static>(&self) -> io::Result<T> {
let mut data = Vec::<u8>::new();
let mut buf = [0_u8; 1];
loop {
let mut u_cell = std::cell::UnsafeCell::new(self);
let mut_self = u_cell.get_mut();
match mut_self.read_exact(&mut buf) {
Ok(_) => {
if TypeId::of::<T>() == TypeId::of::<String>() {
if buf[0] == b'\n' {
break;
};
} else {
if buf[0] == b' ' || buf[0] == b'\t' || buf[0] == b'\n' {
break;
};
}
data.push(buf[0]);
}
Err(e) => {
if e.kind() == io::ErrorKind::UnexpectedEof {
break;
} else {
return Err(e);
}
}
}
}
let data = String::from_utf8(data).map_err(|e| helpers::utf8_error(e))?;
data.trim().parse::<T>().map_err(|_| helpers::parse_error())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_import_numbers() {
let f = File::open("tests/numbers.txt").unwrap();
{
let num = f.import::<i32>();
assert_eq!(num.unwrap_or_default(), 123);
}
{
let num = f.import::<u32>();
assert_eq!(num.unwrap_or_default(), 12);
}
{
let num = f.import::<i32>();
assert_eq!(num.unwrap_or_default(), -9);
}
{
let num = f.import::<f32>();
assert_eq!(num.unwrap_or_default(), 12.098);
}
{
let num = f.import::<f64>();
assert_eq!(num.unwrap_or_default(), -0.000001);
}
{
let num = f.import::<u64>();
assert_eq!(num.unwrap_or_default(), 0);
}
{
let num = f.import::<f64>();
assert_eq!(num.unwrap_or_default(), -0.);
}
{
let num = f.import::<f64>();
assert_eq!(num.unwrap_or_default(), 0.);
}
{
let num = f.import::<f32>();
assert_eq!(num.unwrap_or_default(), 1e-5);
}
}
#[test]
fn test_import_strings() {
let f = File::open("tests/strings.txt").unwrap();
{
let s = f.import::<String>();
assert_eq!(s.unwrap_or_default(), "aaa bbb");
}
{
let s = f.import::<String>();
assert_eq!(s.unwrap_or("*".to_owned()), "");
}
{
let s = f.import::<String>();
assert_eq!(s.unwrap_or_default(), "ccc");
}
let _ = f.import::<String>();
{
let s = f.import::<String>();
assert_eq!(s.unwrap_or_default(), "Привет !");
}
let _ = f.import::<String>();
{
let s = f.import::<String>();
assert_eq!(s.unwrap_or_default(), "小 休");
}
}
#[test]
fn test_import_other() {
let f = File::open("tests/other.txt").unwrap();
{
let b = f.import::<bool>();
assert_eq!(b.unwrap_or_default(), true);
}
{
let b = f.import::<bool>();
assert_eq!(b.unwrap_or_default(), false);
}
{
let mut chars = Vec::<char>::new();
chars.push(f.import::<char>().unwrap());
chars.push(f.import::<char>().unwrap());
chars.push(f.import::<char>().unwrap());
assert_eq!(chars, vec!['a','m','d']);
}
{
let ch = f.import::<char>();
assert_eq!(ch.unwrap_or_default(), 'ё');
}
}
}