iof/write/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use crate::{stdout, unwrap, Mat, SepBy};
use std::io::{self, Write};

mod impls;
mod macros;
pub(super) mod writer;

type Result<T = ()> = io::Result<T>;

/// Write an element into a stream.
///
/// Most types that implement [Display] also implement this.
///
/// [Display]: std::fmt::Display
pub trait WriteOneInto {
    /// Separator between items.
    const SEP_ITEM: &'static str = " ";
    /// Separator between lines.
    const SEP_LINE: &'static str = "\n";
    /// Write into a stream.
    fn try_write_one_into<S: Write + ?Sized>(&self, s: &mut S) -> Result;
    /// Unwrapping version of [WriteOneInto::try_write_one_into].
    #[track_caller]
    #[inline]
    fn write_one_into<S: Write + ?Sized>(&self, s: &mut S) {
        unwrap!(self.try_write_one_into(s))
    }
}

impl<T: WriteOneInto + ?Sized> WriteOneInto for &T {
    fn try_write_one_into<S: Write + ?Sized>(&self, s: &mut S) -> Result {
        (*self).try_write_one_into(s)
    }
}

/// Write into a stream.
///
/// - Most types that implement [std::fmt::Display] also implement this.
/// - [Vec] and `[T]` where `T` implements [std::fmt::Display] also implements this.
///   They write each item separated by a space.
/// - [Mat] where `T` implements [std::fmt::Display] also implements this.
///   They write each row separated by a newline, and each item in a row separated by a space.
///
/// [Mat]: crate::Mat
pub trait WriteInto {
    /// Write into a stream.
    fn try_write_into<S: Write + ?Sized>(&self, s: &mut S) -> Result;
    /// Unwrapping version of [WriteInto::try_write_into].
    #[track_caller]
    #[inline]
    fn write_into<S: Write + ?Sized>(&self, s: &mut S) {
        unwrap!(self.try_write_into(s))
    }
    /// Write into a string.
    fn try_write_into_string(&self) -> Result<String> {
        let mut s = Vec::new();
        self.try_write_into(&mut s)?;
        // What if the string is not valid UTF-8?
        String::from_utf8(s).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
    }
    /// Unwrapping version of [WriteInto::try_write_into_string].
    #[track_caller]
    #[inline]
    fn write_into_string(&self) -> String {
        unwrap!(self.try_write_into_string())
    }
    /// Write into [std::io::Stdout].
    fn try_write(&self) -> Result {
        self.try_write_into(&mut stdout())
    }
    /// Unwrapping version of [WriteInto::try_write].
    #[track_caller]
    #[inline]
    fn write(&self) {
        unwrap!(self.try_write())
    }
}

impl<T: WriteOneInto> WriteInto for T {
    fn try_write_into<S: Write + ?Sized>(&self, s: &mut S) -> Result<()> {
        self.try_write_one_into(s)
    }
}

impl<T: WriteOneInto> WriteInto for Vec<T> {
    fn try_write_into<S: Write + ?Sized>(&self, s: &mut S) -> Result<()> {
        self.as_slice().try_write_into(s)
    }
}

impl<T: WriteOneInto, const N: usize> WriteInto for [T; N] {
    fn try_write_into<S: Write + ?Sized>(&self, s: &mut S) -> Result<()> {
        self.as_slice().try_write_into(s)
    }
}
impl<T: WriteOneInto> WriteInto for [T] {
    fn try_write_into<S: Write + ?Sized>(&self, s: &mut S) -> Result<()> {
        WriteInto::try_write_into(&self.sep_by(T::SEP_ITEM), s)
    }
}

impl<T: WriteOneInto> WriteInto for Mat<T> {
    fn try_write_into<S: Write + ?Sized>(&self, s: &mut S) -> Result<()> {
        self.iter()
            .map(|row| row.iter().sep_by(T::SEP_ITEM))
            .sep_by(T::SEP_LINE)
            .try_write_into(s)
    }
}

impl<T: WriteOneInto, const M: usize, const N: usize> WriteInto for [[T; N]; M] {
    fn try_write_into<S: Write + ?Sized>(&self, s: &mut S) -> Result<()> {
        self.iter()
            .map(|row| row.iter().sep_by(T::SEP_ITEM))
            .sep_by(T::SEP_LINE)
            .try_write_into(s)
    }
}