hyper_scripter/util/
writable.rs

1pub 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}