hyper_scripter/util/
writable.rs1pub struct FmtWrite<W: std::fmt::Write>(pub W);
2pub struct IoWrite<W: std::io::Write>(pub W);
3pub trait Writable {
4 type Fmt: std::fmt::Write;
5 type IO: std::io::Write;
6 fn as_fmt(&mut self) -> Option<&mut Self::Fmt>;
7 fn as_io(&mut self) -> Option<&mut Self::IO>;
8}
9
10impl<W: std::fmt::Write> Writable for FmtWrite<W> {
11 type Fmt = W;
12 type IO = std::io::Stdout;
13 fn as_fmt(&mut self) -> Option<&mut Self::Fmt> {
14 Some(&mut self.0)
15 }
16 fn as_io(&mut self) -> Option<&mut Self::IO> {
17 None
18 }
19}
20
21impl<W: std::io::Write> Writable for IoWrite<W> {
22 type Fmt = String;
23 type IO = W;
24 fn as_fmt(&mut self) -> Option<&mut Self::Fmt> {
25 None
26 }
27 fn as_io(&mut self) -> Option<&mut Self::IO> {
28 Some(&mut self.0)
29 }
30}
31
32macro_rules! write_writable {
33 ($dst:expr, $($arg:tt)*) => {{
34 use $crate::error::Error;
35 use std::io::Write as IOWrite;
36 use std::fmt::Write as FmtWrite;
37 if let Some(w) = $dst.as_fmt() {
38 write!(w, $($arg)*).map_err(|e| Into::<Error>::into(e))
39 } else if let Some(w) = $dst.as_io() {
40 write!(w, $($arg)*).map_err(|e| Into::<Error>::into(e))
41 } else {
42 panic!()
43 }
44 }};
45}
46pub(crate) use write_writable;
47
48#[cfg(test)]
49mod test {
50 use super::*;
51 #[test]
52 fn test_writable() {
53 let mut s = String::new();
54 let mut w = FmtWrite(&mut s);
55 write_writable!(w, "{}", 123).unwrap();
56 assert_eq!("123", s);
57
58 let mut stdout = std::io::stdout().lock();
59 let mut w = IoWrite(&mut stdout);
60 write_writable!(w, "{}", 123).unwrap();
61 }
62}