1use std::io::Write;
2
3macro_rules! macro_map {
4 ($mcr:ident, $($e:ty),*) => {
5 $(
6 $mcr!($e);
7 )*
8 };
9}
10
11#[macro_export]
12macro_rules! echo {
13 ($($e:expr),*) => {
14 ($($e),*).echo(&mut std::io::stdout()).unwrap();
15 println!();
16 };
17}
18
19pub trait Echo {
20 fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error>;
21}
22
23impl<T: Echo> Echo for Vec<T> {
24 fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
25 for (i, value) in self.iter().enumerate() {
26 if i > 0 {
27 write!(w, " ")?;
28 }
29 value.echo(w)?;
30 }
31 Ok(())
32 }
33}
34
35pub struct Mat<T>(pub Vec<Vec<T>>);
36
37impl<T: Echo> Echo for Mat<T> {
38 fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
39 for i in 0..self.0.len() {
40 if i > 0 {
41 writeln!(w)?;
42 }
43 self.0[i].echo(w)?;
44 }
45 Ok(())
46 }
47}
48
49pub struct MatS(pub Vec<Vec<char>>);
50
51impl Echo for MatS {
52 fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
53 for i in 0..self.0.len() {
54 if i > 0 {
55 writeln!(w)?;
56 }
57 for j in 0..self.0[i].len() {
58 write!(w, "{}", self.0[i][j])?;
59 }
60 }
61 Ok(())
62 }
63}
64
65macro_rules! impl_tuple_for_echo {
66 ($v0:ident: $t0:ident $(, $v:ident: $t:ident)*) => {
67 impl< $t0 : Echo $(, $t : Echo)* > Echo for ($t0, $($t),*) {
68 fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
69 let (v0, $($v),*) = self;
70 v0.echo(w)?;
71 $(
72 write!(w, " ")?;
73 $v.echo(w)?;
74 )*
75 Ok(())
76 }
77 }
78 };
79}
80
81macro_rules! tuple_echo_impls {
82 ($v0:ident: $t0:ident $(, $v:ident: $t:ident)*) => {
83 tuple_echo_impls!($($v: $t),*);
84 impl_tuple_for_echo!($v0: $t0 $(, $v: $t)*);
85 };
86 () => {};
87}
88
89tuple_echo_impls!(
90 t7: T7,
91 t6: T6,
92 t5: T5,
93 t4: T4,
94 t3: T3,
95 t2: T2,
96 t1: T1,
97 t0: T0
98);
99
100macro_rules! impl_echo {
101 ($t:ty) => {
102 impl Echo for $t {
103 fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
104 write!(w, "{}", self)
105 }
106 }
107 };
108}
109
110macro_rules! impl_echo_float {
111 ($t:ty) => {
112 impl Echo for $t {
113 fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
114 write!(w, "{:.12}", self)
115 }
116 }
117 };
118}
119
120macro_map!(impl_echo, i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
121macro_map!(impl_echo, char, &str, String);
122macro_map!(impl_echo_float, f32, f64);
123
124#[cfg(test)]
125mod test {
126 use super::*;
127 #[allow(clippy::approx_constant)]
128 #[test]
129 fn test_echo() {
130 fn echo_str(v: impl Echo) -> String {
131 let mut buf = vec![];
132 v.echo(&mut buf).unwrap();
133 String::from_utf8(buf).unwrap()
134 }
135
136 assert_eq!(echo_str(1_i32), "1");
137 assert_eq!(echo_str((1, 2, 3)), "1 2 3");
138 assert_eq!(echo_str((1, 3.14, "hello")), "1 3.140000000000 hello");
139 assert_eq!(echo_str(vec![1, 2, 3]), "1 2 3");
140
141 let m = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
142 assert_eq!(echo_str(Mat(m)), "1 2 3\n4 5 6\n7 8 9");
143
144 let m = vec![
145 vec!['a', 'b', 'c'],
146 vec!['d', 'e', 'f'],
147 vec!['g', 'h', 'i'],
148 ];
149 assert_eq!(echo_str(MatS(m)), "abc\ndef\nghi");
150 }
151}