concise_scanf_like_input/lib.rs
1use std::io::{self, Read, Write};
2
3/// Reads a sample input into a buffer, separating the the lines from each other.
4/// On Unix, one needs to enter C-D to mark the end of input.
5///
6/// # Examples
7///
8/// ```
9/// use concise_scanf_like_input::read_input_lines;
10/// use std::io::{self, Read, Write};
11/// // you need to make the buffer mutable to allow the macro to fill it
12/// let mut buf = String::new();
13/// // the lines must be mutable to rewind themselves on every new line read
14/// let mut lines: &[&str] = read_input_lines!(buf);
15/// ```
16#[macro_export]
17macro_rules! read_input_lines {
18 ($buf:ident) => {
19 {
20 let mut stdin = io::stdin();
21 stdin.read_to_string(&mut $buf);
22 &$buf.lines().collect::<Vec<_>>()
23 }
24 }
25}
26
27
28/// Reads a sample line from the previously fetched vector of lines, then parses a
29/// heterogeneous sequence of variables and stores them in previously allocated
30/// memory.
31///
32/// # Examples
33///
34/// ```
35/// use concise_scanf_like_input::read_line_of_vars;
36/// let mut lines: &[&str] = &vec!["1", "2 3"];
37/// // you don't need to make a variable mutable
38/// let t: i32;
39/// read_line_of_vars!(i32, lines, t);
40/// for _ in 0..t {
41/// let (n, x): (i32, i32);
42/// read_line_of_vars!(i32, lines, n, x);
43/// }
44/// ```
45#[macro_export]
46macro_rules! read_line_of_vars {
47 ($type:ty, $lines:ident, $($var:ident),+) => {
48 {
49 let (line, rest) = $lines.split_first().unwrap();
50 $lines = rest;
51 let parsed = line.trim().split_whitespace().map(
52 |x| {
53 x.parse::<$type>().unwrap()
54 }
55 )
56 .collect::<Vec<$type>>();
57 let parsed = &parsed[..];
58 $(
59 match parsed.split_first() {
60 None => {
61 $var = parsed[0];
62 },
63 Some((value, parsed)) => {
64 $var = *value;
65 }
66 }
67 );+;
68 {(
69 $(
70 $var
71 ),+
72 )}
73 }
74 }
75}