Skip to content

Commit

Permalink
Improve input
Browse files Browse the repository at this point in the history
  • Loading branch information
ngtkana committed Mar 12, 2024
1 parent 489023d commit 0a929cd
Showing 1 changed file with 63 additions and 40 deletions.
103 changes: 63 additions & 40 deletions libs/input/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,76 @@
/// Provids utility on stdin.
//! Read input from stdin and parse it.
//!
//! # Example
//!
//! ```[no_run]
//! # use input::input;
//! let (a, b): (i32, i32) = input();
//! let a: Vec<i32> = input();
//! ```
//!
//! # Types that can be parsed
//! - primitive integer types ([`u8`], [`u16`], [`u32`], [`u64`], [`u128`], [`usize`], [`i8`], [`i16`], [`i32`], [`i64`], [`i128`], [`isize`])
//! - [`String`], [`char`]
//! - tuples (up to 10 elements)
//! - vectors
use std::cell::Cell;
/// Provids utility on stdin.
use std::convert::TryFrom;
/// Provids utility on stdin.
use std::io::stdin;
/// Provids utility on stdin.
use std::io::BufRead;
/// Provids utility on stdin.
use std::io::BufReader;
/// Provids utility on stdin.
use std::io::Lines;
/// Provids utility on stdin.
use std::io::Stdin;
/// Provids utility on stdin.
use std::str::FromStr;
/// Provids utility on stdin.
use std::sync::Mutex;
/// Provids utility on stdin.
use std::sync::Once;

type Server = Mutex<Lines<BufReader<Stdin>>>;
/// Read input from stdin and parse it.
pub fn input<T: ParseLine>() -> T {
ParseLine::parse_line(&line())
}

/// Trait for types that can be parsed.
pub trait ParseLine {
fn parse_line(s: &str) -> Self;
}

macro_rules! impl_parse_line {
($($t:ty),*) => {
$(impl ParseLine for $t {
fn parse_line(s: &str) -> Self {
s.parse().unwrap()
}
})*
};
}
impl_parse_line!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, String, char);
macro_rules! impl_parse_line_tuple {
($($t:ident),*) => {
impl<$($t: ParseLine),*> ParseLine for ($($t,)*) {
fn parse_line(s: &str) -> Self {
let mut s = s.split_whitespace();
($($t::parse_line(s.next().unwrap()),)*)
}
}
};
}
impl_parse_line_tuple!(T0, T1);
impl_parse_line_tuple!(T0, T1, T2);
impl_parse_line_tuple!(T0, T1, T2, T3);
impl_parse_line_tuple!(T0, T1, T2, T3, T4);
impl_parse_line_tuple!(T0, T1, T2, T3, T4, T5);
impl_parse_line_tuple!(T0, T1, T2, T3, T4, T5, T6);
impl_parse_line_tuple!(T0, T1, T2, T3, T4, T5, T6, T7);
impl_parse_line_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
impl_parse_line_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
impl<T: ParseLine> ParseLine for Vec<T> {
fn parse_line(s: &str) -> Self {
s.split_whitespace().map(T::parse_line).collect()
}
}

static ONCE: Once = Once::new();
pub struct Lazy(Cell<Option<Server>>);
type Server = Mutex<Lines<BufReader<Stdin>>>;
struct Lazy(Cell<Option<Server>>);
unsafe impl Sync for Lazy {}
fn line() -> String {
static SYNCER: Lazy = Lazy(Cell::new(None));
Expand All @@ -41,29 +90,3 @@ fn line() -> String {
.unwrap()
}
}
pub trait ForceFromStr: FromStr {
fn force_from_str(s: &str) -> Self;
}
impl<T, E> ForceFromStr for T
where
T: FromStr<Err = E>,
E: std::fmt::Debug,
{
fn force_from_str(s: &str) -> Self { s.parse().unwrap() }
}
/// Read a line from stdin and from_str to [T; N].
pub fn input_array<T: ForceFromStr, const N: usize>() -> [T; N]
where
T: std::fmt::Debug,
{
<[_; N]>::try_from(input_vec()).unwrap()
}
/// Read a line from stdin and from_str to [`Vec<T>`].
pub fn input_vec<T: ForceFromStr>() -> Vec<T> {
line()
.split_whitespace()
.map(T::force_from_str)
.collect::<Vec<_>>()
}
/// Read a line from stdin and from_str to T.
pub fn input<T: ForceFromStr>() -> T { T::force_from_str(&line()) }

0 comments on commit 0a929cd

Please sign in to comment.