iof/read/macros.rs
1/// Read a single data item, a [Vec] or a [Mat] from input using [ReadInto].
2///
3/// The intended grammar is:
4///
5/// ```rust,ignore
6/// $($dims:expr),* $(,)? $(; src = $src:expr)? $(; fmt = $fmt:expr)?
7/// ```
8///
9/// - `read!()` reads a single data item from input.
10/// - `read!(n)` reads `n` data items from input and stores them in a [Vec].
11/// - `read!(m, n)` reads `m * n` data items from input and stores them in a [Mat],
12///
13/// which consists of `m` [Vec]s, each containing `n` data items.
14///
15/// And the reader will always respect your size hint, and if you pass a size larger that the actual data in current line, it will go on to the next line and read as many as the size hint.
16///
17/// [Mat]: crate::Mat
18/// [ReadInto]: crate::ReadInto
19///
20/// # Example
21///
22/// ```rust,no_run
23/// use iof::read;
24/// let a: usize = read!();
25/// let b: Vec<usize> = read!(3);
26/// let c: Vec<Vec<usize>> = read!(2, 3);
27/// ```
28///
29/// # Notes
30///
31/// This macro accepts even higher dimensions, such as `read!(m, n, o, p)`,
32/// but as this creates a nested [Vec], this may cause performance concerns.
33///
34/// What's more, you can pass a dynamic value to `read!` like `read!(m, f())`,
35/// which can create a nested [Vec] with a non-uniform length.
36///
37/// Given the input:
38///
39/// ```txt
40#[doc = include_str!("../../examples/doc_macro_read.txt")]
41/// ```
42///
43/// ```rust,no_run
44#[doc = include_str!("../../examples/doc_macro_read.rs")]
45/// ```
46///
47/// Also, you can specify the source (as long as it implements [BufReadExt]) via `src =` and format (as long as it implements [Format]) via `fmt =` for reading, and you can also specify the characters to skip via `skip =`, which is a shorthand for `fmt = iof::fmt::skip($skip)`.
48///
49/// [BufReadExt]: crate::BufReadExt
50/// [Format]: crate::fmt::Format
51///
52/// ```rust
53/// use iof::{fmt::csv, read, InputStream, Mat};
54///
55/// let a: usize = read!(; src = InputStream::new(b"42".as_slice()));
56/// assert_eq!(a, 42);
57///
58/// let b: Vec<usize> = read!(3; src = InputStream::new(b"1 2 3".as_slice()));
59/// assert_eq!(b, [1, 2, 3]);
60///
61/// let b: Vec<usize> = read!(3; src = InputStream::new(b"1, 2, 3".as_slice()); fmt = csv());
62/// assert_eq!(b, [1, 2, 3]);
63///
64/// let s = b"010\n101";
65///
66/// let b: Mat<char> = read!(2, 3; src = InputStream::new(s.as_slice()); skip = [' ', ',', ';', '\n', '\r']);
67/// assert_eq!(b, [['0', '1', '0'], ['1', '0', '1']]);
68///
69/// let s = b"1,2,3;4,5,6\r\n";
70///
71/// let b: Mat<usize> = read!(2, 3; src = InputStream::new(s.as_slice()); skip = [' ', ',', ';', '\r', '\n']);
72/// assert_eq!(b, [[1, 2, 3], [4, 5, 6]]);
73///
74/// let b: Mat<usize> = read!(2, 3; src = InputStream::new(s.as_slice()); skip = " \t,;\r\n".chars());
75/// assert_eq!(b, [[1, 2, 3], [4, 5, 6]]);
76/// ```
77#[macro_export]
78macro_rules! read {
79 (@ $(,)?; src = $src:expr; fmt = $fmt:expr) => {
80 $crate::unwrap!($crate::ReadFrom::try_read_from($src, $fmt))
81 };
82 (@ $dim0:expr $(, $dims:expr)* $(,)?; src = $src:expr; fmt = $fmt:expr) => {{
83 let range = 0usize..$dim0;
84 ::std::vec::Vec::<_>::from_iter(range.map(|_| $crate::read!(@ $($dims, )* ; src = $src ; fmt = $fmt)))
85 }};
86 ($(,)? $(; src = $src:expr)? $(; fmt = $fmt:expr)?) => {{
87 let src = $crate::argument_or_default!($(&mut $src)?, &mut *$crate::stdin());
88 let fmt = $crate::argument_or_default!($(&$fmt)?, &$crate::fmt::Default::new());
89 $crate::unwrap!($crate::ReadFrom::try_read_from(src, fmt))
90 }};
91 ($dim0:expr $(, $dims:expr)* $(,)? $(; src = $src:expr)? $(; fmt = $fmt:expr)?) => {{
92 let range = 0usize..$dim0;
93 let src = $crate::argument_or_default!($(&mut $src)?, &mut *$crate::stdin());
94 let fmt = $crate::argument_or_default!($(&$fmt)?, &$crate::fmt::Default::new());
95 ::std::vec::Vec::<_>::from_iter(range.map(|_| $crate::read!(@ $($dims, )*; src = src; fmt = fmt)))
96 }};
97 ($(,)? $(; src = $src:expr)? ; skip = $skip:expr) => {{
98 let src = $crate::argument_or_default!($(&mut $src)?, &mut *$crate::stdin());
99 let fmt = &$crate::fmt::skip($skip);
100 $crate::unwrap!($crate::ReadFrom::try_read_from(src, fmt))
101 }};
102 ($dim0:expr $(, $dims:expr)* $(,)? $(; src = $src:expr)? ; skip = $skip:expr) => {{
103 let range = 0usize..$dim0;
104 let src = $crate::argument_or_default!($(&mut $src)?, &mut *$crate::stdin());
105 let fmt = &$crate::fmt::skip($skip);
106 ::std::vec::Vec::<_>::from_iter(range.map(|_| $crate::read!(@ $($dims, )*; src = src; fmt = fmt)))
107 }};
108}
109
110/// Implement [ReadOneFrom] for given types that already implement [std::str::FromStr].
111///
112/// The intended grammar is:
113///
114/// ```rust,ignore
115/// $($ty:ty $(=> $accept:pat)?)*
116/// ```
117///
118/// Note that all types that are [ReadOneFrom] will also implement [ReadInto] automatically.
119///
120/// [ReadOneFrom]: crate::ReadOneFrom
121/// [ReadInto]: crate::ReadInto
122#[macro_export]
123macro_rules! impl_read_one_from_for_from_str {
124 ($($ty:ty)+) => {
125 $(
126 impl $crate::ReadOneFrom for $ty {
127 type ParseError = <Self as ::core::str::FromStr>::Err;
128
129 #[inline]
130 fn parse(s: &::core::primitive::str) -> Result<Self, $crate::ReadOneFromError<Self>> {
131 s.parse().map_err(|err| $crate::ReadError::FromStrError(err, s.to_owned(), ::core::any::type_name::<Self>()))
132 }
133 }
134 )*
135 };
136 ($($ty:ty)+ => $accept:expr) => {
137 $(
138 impl $crate::ReadOneFrom for $ty {
139 type ParseError = <Self as ::core::str::FromStr>::Err;
140
141 #[inline]
142 fn accept() -> impl $crate::ext::Pattern<Item = ::core::primitive::char> {
143 $accept
144 }
145
146 #[inline]
147 fn parse(s: &::core::primitive::str) -> Result<Self, $crate::ReadOneFromError<Self>> {
148 s.parse().map_err(|err| $crate::ReadError::FromStrError(err, s.to_owned(), ::core::any::type_name::<Self>()))
149 }
150 }
151 )*
152 };
153}