Coverage Report

Created: 2025-08-29 06:57

/rust/registry/src/index.crates.io-6f17d22bba15001f/wyz-0.5.1/src/fmt.rs
Line
Count
Source (jump to first uncovered line)
1
/*! Format forwarding
2
3
This module provides wrapper types for each formatting trait other than `Debug`
4
which, when `Debug`-formatted, forward to the original trait instead of `Debug`.
5
6
Each wrapper type is a tuple struct so that it can be used as a named
7
constructor, such as in `.map(FmtDisplay)`. In addition, a blanket trait adds
8
extension methods `.fmt_<trait_name>>()` to provide the corresponding wrap.
9
10
Any modifiers in the format template string or struct modifier are passed
11
through to the desired trait implementation unchanged. The only effect of the
12
forwarding types in this module is to change the `?` template character to one
13
of the other trait signifiers.
14
!*/
15
16
use 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
/// Wraps any value with a format-forward to `Debug`.
37
#[cfg(not(tarpaulin_include))]
38
pub trait FmtForward: Sized {
39
  /// Causes `self` to use its `Binary` implementation when `Debug`-formatted.
40
  #[inline(always)]
41
  fn fmt_binary(self) -> FmtBinary<Self>
42
  where Self: Binary {
43
    FmtBinary(self)
44
  }
45
46
  /// Causes `self` to use its `Display` implementation when
47
  /// `Debug`-formatted.
48
  #[inline(always)]
49
  fn fmt_display(self) -> FmtDisplay<Self>
50
  where Self: Display {
51
    FmtDisplay(self)
52
  }
53
54
  /// Causes `self` to use its `LowerExp` implementation when
55
  /// `Debug`-formatted.
56
  #[inline(always)]
57
  fn fmt_lower_exp(self) -> FmtLowerExp<Self>
58
  where Self: LowerExp {
59
    FmtLowerExp(self)
60
  }
61
62
  /// Causes `self` to use its `LowerHex` implementation when
63
  /// `Debug`-formatted.
64
  #[inline(always)]
65
  fn fmt_lower_hex(self) -> FmtLowerHex<Self>
66
  where Self: LowerHex {
67
    FmtLowerHex(self)
68
  }
69
70
  /// Causes `self` to use its `Octal` implementation when `Debug`-formatted.
71
  #[inline(always)]
72
  fn fmt_octal(self) -> FmtOctal<Self>
73
  where Self: Octal {
74
    FmtOctal(self)
75
  }
76
77
  /// Causes `self` to use its `Pointer` implementation when
78
  /// `Debug`-formatted.
79
  #[inline(always)]
80
0
  fn fmt_pointer(self) -> FmtPointer<Self>
81
0
  where Self: Pointer {
82
0
    FmtPointer(self)
83
0
  }
84
85
  /// Causes `self` to use its `UpperExp` implementation when
86
  /// `Debug`-formatted.
87
  #[inline(always)]
88
  fn fmt_upper_exp(self) -> FmtUpperExp<Self>
89
  where Self: UpperExp {
90
    FmtUpperExp(self)
91
  }
92
93
  /// Causes `self` to use its `UpperHex` implementation when
94
  /// `Debug`-formatted.
95
  #[inline(always)]
96
  fn fmt_upper_hex(self) -> FmtUpperHex<Self>
97
  where Self: UpperHex {
98
    FmtUpperHex(self)
99
  }
100
101
  /// Formats each item in a sequence.
102
  ///
103
  /// This wrapper structure conditionally implements all of the formatting
104
  /// traits when `self` can be viewed as an iterator whose *items* implement
105
  /// them. It iterates over `&self` and prints each item according to the
106
  /// formatting specifier provided.
107
  #[inline(always)]
108
  fn fmt_list(self) -> FmtList<Self>
109
  where for<'a> &'a Self: IntoIterator {
110
    FmtList(self)
111
  }
112
}
113
114
impl<T: Sized> FmtForward for T {
115
}
116
117
/// Forwards a type’s `Binary` formatting implementation to `Debug`.
118
#[repr(transparent)]
119
pub struct FmtBinary<T: Binary>(pub T);
120
121
/// Forwards a type’s `Display` formatting implementation to `Debug`.
122
#[repr(transparent)]
123
pub struct FmtDisplay<T: Display>(pub T);
124
125
/// Renders each element of a stream into a list.
126
#[repr(transparent)]
127
pub struct FmtList<T>(pub T)
128
where for<'a> &'a T: IntoIterator;
129
130
/// Forwards a type’s `LowerExp` formatting implementation to `Debug`.
131
#[repr(transparent)]
132
pub struct FmtLowerExp<T: LowerExp>(pub T);
133
134
/// Forwards a type’s `LowerHex` formatting implementation to `Debug`.
135
#[repr(transparent)]
136
pub struct FmtLowerHex<T: LowerHex>(pub T);
137
138
/// Forwards a type’s `Octal` formatting implementation to `Debug`.
139
#[repr(transparent)]
140
pub struct FmtOctal<T: Octal>(pub T);
141
142
/// Forwards a type’s `Pointer` formatting implementation to `Debug`.
143
#[repr(transparent)]
144
pub struct FmtPointer<T: Pointer>(pub T);
145
146
/// Forwards a type’s `UpperExp` formatting implementation to `Debug`.
147
#[repr(transparent)]
148
pub struct FmtUpperExp<T: UpperExp>(pub T);
149
150
/// Forwards a type’s `UpperHex` formatting implementation to `Debug`.
151
#[repr(transparent)]
152
pub struct FmtUpperHex<T: UpperHex>(pub T);
153
154
macro_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
0
      fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
167
0
        <T as $t>::fmt(&self.0, fmt)
168
0
      }
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
263
fmt!(
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
274
impl<T> Binary for FmtList<T>
275
where
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
286
impl<T> Debug for FmtList<T>
287
where
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
296
impl<T> Display for FmtList<T>
297
where
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
308
impl<T> LowerExp for FmtList<T>
309
where
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
320
impl<T> LowerHex for FmtList<T>
321
where
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
332
impl<T> Octal for FmtList<T>
333
where
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
344
impl<T> UpperExp for FmtList<T>
345
where
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
356
impl<T> UpperHex for FmtList<T>
357
where
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))]
369
impl<T> Deref for FmtList<T>
370
where 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))]
381
impl<T> DerefMut for FmtList<T>
382
where 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))]
391
impl<T> AsRef<T> for FmtList<T>
392
where 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))]
401
impl<T> AsMut<T> for FmtList<T>
402
where 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"))]
411
mod 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
}