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
119
120
//! 形式つき出力。

/// 形式つき出力(スペース区切り)。
///
/// # Examples
/// ```
/// use nekolib::utils::{SpaceSep, StrSep, PerLine};
///
/// let a = vec![13, 5, 30, 27, 6];
/// let b = vec!['a', 'b', 'c'];
///
/// assert_eq!(format!("{}", SpaceSep(&a)), "13 5 30 27 6");
/// assert_eq!(format!("{:02}", SpaceSep(&a)), "13 05 30 27 06");
/// assert_eq!(format!("{:#04x}", SpaceSep(&a[..3])), "0x0d 0x05 0x1e");
/// assert_eq!(format!("{:?}", SpaceSep(&b)), "'a' 'b' 'c'");
/// assert_eq!(format!("{}", PerLine(&b)), "a\nb\nc");
/// assert_eq!(format!("{:2}", StrSep(&a, ", ")), "13,  5, 30, 27,  6");
/// ```
pub struct SpaceSep<'a, D: ?Sized>(pub &'a D);

/// 形式つき出力(改行区切り)。
///
/// # Examples
/// ```
/// use nekolib::utils::{SpaceSep, StrSep, PerLine};
///
/// let a = vec![13, 5, 30, 27, 6];
/// let b = vec!['a', 'b', 'c'];
///
/// assert_eq!(format!("{}", SpaceSep(&a)), "13 5 30 27 6");
/// assert_eq!(format!("{:02}", SpaceSep(&a)), "13 05 30 27 06");
/// assert_eq!(format!("{:#04x}", SpaceSep(&a[..3])), "0x0d 0x05 0x1e");
/// assert_eq!(format!("{:?}", SpaceSep(&b)), "'a' 'b' 'c'");
/// assert_eq!(format!("{}", PerLine(&b)), "a\nb\nc");
/// assert_eq!(format!("{:2}", StrSep(&a, ", ")), "13,  5, 30, 27,  6");
/// ```
pub struct PerLine<'a, D: ?Sized>(pub &'a D);

/// 形式つき出力(任意文字列区切り)。
///
/// # Examples
/// ```
/// use nekolib::utils::{SpaceSep, StrSep, PerLine};
///
/// let a = vec![13, 5, 30, 27, 6];
/// let b = vec!['a', 'b', 'c'];
///
/// assert_eq!(format!("{}", SpaceSep(&a)), "13 5 30 27 6");
/// assert_eq!(format!("{:02}", SpaceSep(&a)), "13 05 30 27 06");
/// assert_eq!(format!("{:#04x}", SpaceSep(&a[..3])), "0x0d 0x05 0x1e");
/// assert_eq!(format!("{:?}", SpaceSep(&b)), "'a' 'b' 'c'");
/// assert_eq!(format!("{}", PerLine(&b)), "a\nb\nc");
/// assert_eq!(format!("{:2}", StrSep(&a, ", ")), "13,  5, 30, 27,  6");
/// ```
pub struct StrSep<'a, D: ?Sized>(pub &'a D, pub &'a str);

use std::fmt;

macro_rules! impl_fmt {
    ( $( ($fmt:ident, $fn:ident), )* ) => { $(
        fn $fn<I>(it: I, sep: &str, f: &mut fmt::Formatter) -> fmt::Result
        where
            I: IntoIterator,
            <I as IntoIterator>::Item: fmt::$fmt,
        {
            for (i, x) in it.into_iter().enumerate() {
                if i > 0 {
                    write!(f, "{}", sep)?;
                }
                fmt::$fmt::fmt(&x, f)?;
            }
            Ok(())
        }

        impl<'a, D: 'a> fmt::$fmt for SpaceSep<'a, D>
        where
            D: ?Sized,
            &'a D: IntoIterator,
            <&'a D as IntoIterator>::Item: fmt::$fmt,
        {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                $fn(self.0, " ", f)
            }
        }

        impl<'a, D: 'a> fmt::$fmt for PerLine<'a, D>
        where
            D: ?Sized,
            &'a D: IntoIterator,
            <&'a D as IntoIterator>::Item: fmt::$fmt,
        {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                $fn(self.0, "\n", f)
            }
        }

        impl<'a, D: 'a> fmt::$fmt for StrSep<'a, D>
        where
            D: ?Sized,
            &'a D: IntoIterator,
            <&'a D as IntoIterator>::Item: fmt::$fmt,
        {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                $fn(self.0, self.1, f)
            }
        }
)* };
}

impl_fmt! {
    (Display, join_display),
    (Debug, join_debug),
    (Octal, join_octal),
    (LowerHex, join_lower_hex),
    (UpperHex, join_upper_hex),
    (Pointer, join_pointer),
    (Binary, join_binary),
    (LowerExp, join_lower_exp),
    (UpperExp, join_upper_exp),
}