1use core::{
17 fmt::{
18 self,
19 Binary,
20 Debug,
21 Display,
22 Formatter,
23 LowerExp,
24 LowerHex,
25 Octal,
26 Pointer,
27 UpperExp,
28 UpperHex,
29 },
30 ops::{
31 Deref,
32 DerefMut,
33 },
34};
35
36#[cfg(not(tarpaulin_include))]
38pub trait FmtForward: Sized {
39 #[inline(always)]
41 fn fmt_binary(self) -> FmtBinary<Self>
42 where Self: Binary {
43 FmtBinary(self)
44 }
45
46 #[inline(always)]
49 fn fmt_display(self) -> FmtDisplay<Self>
50 where Self: Display {
51 FmtDisplay(self)
52 }
53
54 #[inline(always)]
57 fn fmt_lower_exp(self) -> FmtLowerExp<Self>
58 where Self: LowerExp {
59 FmtLowerExp(self)
60 }
61
62 #[inline(always)]
65 fn fmt_lower_hex(self) -> FmtLowerHex<Self>
66 where Self: LowerHex {
67 FmtLowerHex(self)
68 }
69
70 #[inline(always)]
72 fn fmt_octal(self) -> FmtOctal<Self>
73 where Self: Octal {
74 FmtOctal(self)
75 }
76
77 #[inline(always)]
80 fn fmt_pointer(self) -> FmtPointer<Self>
81 where Self: Pointer {
82 FmtPointer(self)
83 }
84
85 #[inline(always)]
88 fn fmt_upper_exp(self) -> FmtUpperExp<Self>
89 where Self: UpperExp {
90 FmtUpperExp(self)
91 }
92
93 #[inline(always)]
96 fn fmt_upper_hex(self) -> FmtUpperHex<Self>
97 where Self: UpperHex {
98 FmtUpperHex(self)
99 }
100
101 #[inline(always)]
108 fn fmt_list(self) -> FmtList<Self>
109 where for<'a> &'a Self: IntoIterator {
110 FmtList(self)
111 }
112}
113
114impl<T: Sized> FmtForward for T {
115}
116
117#[repr(transparent)]
119pub struct FmtBinary<T: Binary>(pub T);
120
121#[repr(transparent)]
123pub struct FmtDisplay<T: Display>(pub T);
124
125#[repr(transparent)]
127pub struct FmtList<T>(pub T)
128where for<'a> &'a T: IntoIterator;
129
130#[repr(transparent)]
132pub struct FmtLowerExp<T: LowerExp>(pub T);
133
134#[repr(transparent)]
136pub struct FmtLowerHex<T: LowerHex>(pub T);
137
138#[repr(transparent)]
140pub struct FmtOctal<T: Octal>(pub T);
141
142#[repr(transparent)]
144pub struct FmtPointer<T: Pointer>(pub T);
145
146#[repr(transparent)]
148pub struct FmtUpperExp<T: UpperExp>(pub T);
149
150#[repr(transparent)]
152pub struct FmtUpperHex<T: UpperHex>(pub T);
153
154macro_rules! fmt {
155 ($($w:ty => $t:ident),* $(,)?) => { $(
156 #[cfg(not(tarpaulin_include))]
157 impl<T: $t + Binary> Binary for $w {
158 #[inline(always)]
159 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
160 Binary::fmt(&self.0, fmt)
161 }
162 }
163
164 impl<T: $t> Debug for $w {
165 #[inline(always)]
166 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
167 <T as $t>::fmt(&self.0, fmt)
168 }
169 }
170
171 #[cfg(not(tarpaulin_include))]
172 impl<T: $t + Display> Display for $w {
173 #[inline(always)]
174 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
175 Display::fmt(&self.0, fmt)
176 }
177 }
178
179 #[cfg(not(tarpaulin_include))]
180 impl<T: $t + LowerExp> LowerExp for $w {
181 #[inline(always)]
182 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
183 LowerExp::fmt(&self.0, fmt)
184 }
185 }
186
187 #[cfg(not(tarpaulin_include))]
188 impl<T: $t + LowerHex> LowerHex for $w {
189 #[inline(always)]
190 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
191 LowerHex::fmt(&self.0, fmt)
192 }
193 }
194
195 #[cfg(not(tarpaulin_include))]
196 impl<T: $t + Octal> Octal for $w {
197 #[inline(always)]
198 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
199 Octal::fmt(&self.0, fmt)
200 }
201 }
202
203 #[cfg(not(tarpaulin_include))]
204 impl<T: $t + Pointer> Pointer for $w {
205 #[inline(always)]
206 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
207 Pointer::fmt(&self.0, fmt)
208 }
209 }
210
211 #[cfg(not(tarpaulin_include))]
212 impl<T: $t + UpperExp> UpperExp for $w {
213 #[inline(always)]
214 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
215 UpperExp::fmt(&self.0, fmt)
216 }
217 }
218
219 #[cfg(not(tarpaulin_include))]
220 impl<T: $t + UpperHex> UpperHex for $w {
221 #[inline(always)]
222 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
223 UpperHex::fmt(&self.0, fmt)
224 }
225 }
226
227 #[cfg(not(tarpaulin_include))]
228 impl<T: $t> Deref for $w {
229 type Target = T;
230
231 #[inline(always)]
232 fn deref(&self) -> &Self::Target {
233 &self.0
234 }
235 }
236
237 #[cfg(not(tarpaulin_include))]
238 impl<T: $t> DerefMut for $w {
239 #[inline(always)]
240 fn deref_mut(&mut self) -> &mut Self::Target {
241 &mut self.0
242 }
243 }
244
245 #[cfg(not(tarpaulin_include))]
246 impl<T: $t> AsRef<T> for $w {
247 #[inline(always)]
248 fn as_ref(&self) -> &T {
249 &self.0
250 }
251 }
252
253 #[cfg(not(tarpaulin_include))]
254 impl<T: $t> AsMut<T> for $w {
255 #[inline(always)]
256 fn as_mut(&mut self) -> &mut T {
257 &mut self.0
258 }
259 }
260 )* };
261}
262
263fmt!(
264 FmtBinary<T> => Binary,
265 FmtDisplay<T> => Display,
266 FmtLowerExp<T> => LowerExp,
267 FmtLowerHex<T> => LowerHex,
268 FmtOctal<T> => Octal,
269 FmtPointer<T> => Pointer,
270 FmtUpperExp<T> => UpperExp,
271 FmtUpperHex<T> => UpperHex,
272);
273
274impl<T> Binary for FmtList<T>
275where
276 for<'a> &'a T: IntoIterator,
277 for<'a> <&'a T as IntoIterator>::Item: Binary,
278{
279 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
280 fmt.debug_list()
281 .entries((&self.0).into_iter().map(FmtBinary))
282 .finish()
283 }
284}
285
286impl<T> Debug for FmtList<T>
287where
288 for<'a> &'a T: IntoIterator,
289 for<'a> <&'a T as IntoIterator>::Item: Debug,
290{
291 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
292 fmt.debug_list().entries((&self.0).into_iter()).finish()
293 }
294}
295
296impl<T> Display for FmtList<T>
297where
298 for<'a> &'a T: IntoIterator,
299 for<'a> <&'a T as IntoIterator>::Item: Display,
300{
301 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
302 fmt.debug_list()
303 .entries((&self.0).into_iter().map(FmtDisplay))
304 .finish()
305 }
306}
307
308impl<T> LowerExp for FmtList<T>
309where
310 for<'a> &'a T: IntoIterator,
311 for<'a> <&'a T as IntoIterator>::Item: LowerExp,
312{
313 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
314 fmt.debug_list()
315 .entries((&self.0).into_iter().map(FmtLowerExp))
316 .finish()
317 }
318}
319
320impl<T> LowerHex for FmtList<T>
321where
322 for<'a> &'a T: IntoIterator,
323 for<'a> <&'a T as IntoIterator>::Item: LowerHex,
324{
325 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
326 fmt.debug_list()
327 .entries((&self.0).into_iter().map(FmtLowerHex))
328 .finish()
329 }
330}
331
332impl<T> Octal for FmtList<T>
333where
334 for<'a> &'a T: IntoIterator,
335 for<'a> <&'a T as IntoIterator>::Item: Octal,
336{
337 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
338 fmt.debug_list()
339 .entries((&self.0).into_iter().map(FmtOctal))
340 .finish()
341 }
342}
343
344impl<T> UpperExp for FmtList<T>
345where
346 for<'a> &'a T: IntoIterator,
347 for<'a> <&'a T as IntoIterator>::Item: UpperExp,
348{
349 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
350 fmt.debug_list()
351 .entries((&self.0).into_iter().map(FmtUpperExp))
352 .finish()
353 }
354}
355
356impl<T> UpperHex for FmtList<T>
357where
358 for<'a> &'a T: IntoIterator,
359 for<'a> <&'a T as IntoIterator>::Item: UpperHex,
360{
361 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
362 fmt.debug_list()
363 .entries((&self.0).into_iter().map(FmtUpperHex))
364 .finish()
365 }
366}
367
368#[cfg(not(tarpaulin_include))]
369impl<T> Deref for FmtList<T>
370where for<'a> &'a T: IntoIterator
371{
372 type Target = T;
373
374 #[inline(always)]
375 fn deref(&self) -> &Self::Target {
376 &self.0
377 }
378}
379
380#[cfg(not(tarpaulin_include))]
381impl<T> DerefMut for FmtList<T>
382where for<'a> &'a T: IntoIterator
383{
384 #[inline(always)]
385 fn deref_mut(&mut self) -> &mut Self::Target {
386 &mut self.0
387 }
388}
389
390#[cfg(not(tarpaulin_include))]
391impl<T> AsRef<T> for FmtList<T>
392where for<'a> &'a T: IntoIterator
393{
394 #[inline(always)]
395 fn as_ref(&self) -> &T {
396 &self.0
397 }
398}
399
400#[cfg(not(tarpaulin_include))]
401impl<T> AsMut<T> for FmtList<T>
402where for<'a> &'a T: IntoIterator
403{
404 #[inline(always)]
405 fn as_mut(&mut self) -> &mut T {
406 &mut self.0
407 }
408}
409
410#[cfg(all(test, feature = "alloc"))]
411mod tests {
412 #[cfg(not(feature = "std"))]
413 use alloc::format;
414
415 #[cfg(feature = "std")]
416 use std::format;
417
418 use super::*;
419
420 #[test]
421 fn render_item() {
422 let num = 29;
423
424 assert_eq!(format!("{:?}", num.fmt_binary()), "11101");
425 assert_eq!(format!("{:?}", num.fmt_display()), "29");
426 assert_eq!(format!("{:?}", num.fmt_upper_hex()), "1D");
427 assert_eq!(format!("{:?}", num.fmt_octal()), "35");
428 assert_eq!(format!("{:?}", num.fmt_lower_hex()), "1d");
429
430 let num = 53.7;
431 assert_eq!(format!("{:?}", num.fmt_lower_exp()), "5.37e1");
432 assert_eq!(format!("{:?}", num.fmt_upper_exp()), "5.37E1");
433 }
434
435 #[test]
436 fn render_list() {
437 let list = [0, 1, 2, 3];
438 assert_eq!(format!("{:02b}", list.fmt_list()), "[00, 01, 10, 11]");
439 assert_eq!(format!("{:01?}", list.fmt_list()), "[0, 1, 2, 3]");
440 assert_eq!(format!("{:01}", list.fmt_list()), "[0, 1, 2, 3]");
441
442 let list = [-51.0, -1.2, 1.3, 54.0];
443 assert_eq!(
444 format!("{:e}", list.fmt_list()),
445 "[-5.1e1, -1.2e0, 1.3e0, 5.4e1]"
446 );
447 assert_eq!(
448 format!("{:E}", list.fmt_list()),
449 "[-5.1E1, -1.2E0, 1.3E0, 5.4E1]"
450 );
451
452 let list = [0, 10, 20, 30];
453 assert_eq!(format!("{:02x}", list.fmt_list()), "[00, 0a, 14, 1e]");
454 assert_eq!(format!("{:02o}", list.fmt_list()), "[00, 12, 24, 36]");
455 assert_eq!(format!("{:02X}", list.fmt_list()), "[00, 0A, 14, 1E]");
456 }
457}