1use crate::fmt_display;
2use core::fmt::{self, Debug, Display, Formatter};
3
4pub struct FmtDebugList<F>
6where
7 F: ?Sized,
8{
9 values_fn: F,
10}
11
12impl<F> FmtDebugList<F> {
13 const fn new(values_fn: F) -> Self {
14 Self { values_fn }
15 }
16}
17
18impl<F, I> Debug for FmtDebugList<F>
19where
20 F: Fn() -> I + ?Sized,
21 I: IntoIterator,
22 I::Item: Debug,
23{
24 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
25 let entries = (self.values_fn)();
26
27 f.debug_list().entries(entries).finish()
28 }
29}
30
31impl<F, I> Display for FmtDebugList<F>
33where
34 F: Fn() -> I + ?Sized,
35 I: IntoIterator,
36 I::Item: Debug,
37{
38 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
39 Debug::fmt(self, f)
40 }
41}
42
43pub struct FmtDisplayList<F>
45where
46 F: ?Sized,
47{
48 values_fn: F,
49}
50
51impl<F> FmtDisplayList<F> {
52 const fn new(values_fn: F) -> Self {
53 Self { values_fn }
54 }
55}
56
57impl<F, I> Debug for FmtDisplayList<F>
58where
59 F: Fn() -> I + ?Sized,
60 I: IntoIterator,
61 I::Item: Display,
62{
63 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
64 let entries = (self.values_fn)().into_iter().map(fmt_display);
65
66 f.debug_list().entries(entries).finish()
67 }
68}
69
70impl<F, I> Display for FmtDisplayList<F>
71where
72 F: Fn() -> I + ?Sized,
73 I: IntoIterator,
74 I::Item: Display,
75{
76 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
77 Debug::fmt(self, f)
78 }
79}
80
81pub const fn fmt_debug_list<F, I>(values_fn: F) -> FmtDebugList<F>
92where
93 F: Fn() -> I,
94 I: IntoIterator,
95 I::Item: Debug,
96{
97 FmtDebugList::new(values_fn)
98}
99
100pub const fn fmt_display_list<F, I>(values_fn: F) -> FmtDisplayList<F>
111where
112 F: Fn() -> I,
113 I: IntoIterator,
114 I::Item: Display,
115{
116 FmtDisplayList::new(values_fn)
117}
118
119#[cfg(test)]
120mod tests {
121 use super::{FmtDebugList, FmtDisplayList};
122 use core::fmt::{self, Display, Formatter};
123
124 #[test]
125 fn test_debug_fmt_list() {
126 #[derive(Debug)]
127 struct Foo;
128
129 #[allow(trivial_casts)]
130 let test_cases = [
131 (&[] as &[Foo], "[]"),
132 (&[Foo], "[Foo]"),
133 (&[Foo, Foo], "[Foo, Foo]"),
134 (&[Foo, Foo, Foo], "[Foo, Foo, Foo]"),
135 ];
136
137 for (values, expected) in test_cases {
138 let fmt = super::fmt_debug_list(|| values);
139 let unsized_fmt: &FmtDebugList<dyn Fn() -> &'static [Foo]> = &fmt;
140
141 assert_eq!(std::format!("{fmt:?}"), expected);
142 assert_eq!(std::format!("{fmt}"), expected);
143 assert_eq!(std::format!("{unsized_fmt:?}"), expected);
144 assert_eq!(std::format!("{unsized_fmt}"), expected);
145 }
146 }
147
148 #[test]
149 fn test_display_fmt_list() {
150 struct Foo;
151
152 impl Display for Foo {
153 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
154 f.write_str("item")
155 }
156 }
157
158 #[allow(trivial_casts)]
159 let test_cases = [
160 (&[] as &[Foo], "[]"),
161 (&[Foo], "[item]"),
162 (&[Foo, Foo], "[item, item]"),
163 (&[Foo, Foo, Foo], "[item, item, item]"),
164 ];
165
166 for (values, expected) in test_cases {
167 let fmt = super::fmt_display_list(|| values);
168 let unsized_fmt: &FmtDisplayList<dyn Fn() -> &'static [Foo]> = &fmt;
169
170 assert_eq!(std::format!("{fmt:?}"), expected);
171 assert_eq!(std::format!("{fmt}"), expected);
172 assert_eq!(std::format!("{unsized_fmt:?}"), expected);
173 assert_eq!(std::format!("{unsized_fmt}"), expected);
174 }
175 }
176}