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