Coverage Report

Created: 2024-05-21 06:19

/rust/registry/src/index.crates.io-6f17d22bba15001f/debug-helper-0.3.13/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
/*!
2
# Debug Helper
3
4
This crate provides declarative macros to help you implement the `Debug` trait manually.
5
6
Instead of this crate, in most cases, you can use the [`educe`](https://crates.io/crates/educe) crate to implement the `Debug` trait.
7
8
## Examples
9
10
For structs,
11
12
```rust
13
use std::fmt::{self, Formatter, Debug};
14
15
pub struct A {
16
    pub f1: u8,
17
    pub f2: i16,
18
    pub f3: f64,
19
}
20
21
impl Debug for A {
22
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
23
        debug_helper::impl_debug_for_struct!(A, f, self, .f1, (.f3, "{:.3}", self.f3));
24
    }
25
}
26
27
let a = A {
28
    f1: 1,
29
    f2: 2,
30
    f3: std::f64::consts::PI,
31
};
32
33
println!("{:#?}", a);
34
35
/*
36
    A {
37
        f1: 1,
38
        f3: 3.142,
39
    }
40
*/
41
```
42
43
For tuple structs,
44
45
```rust
46
use std::fmt::{self, Formatter, Debug};
47
48
pub struct A(pub u8, pub i16, pub f64);
49
50
impl Debug for A {
51
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
52
        debug_helper::impl_debug_for_tuple_struct!(A, f, self, .0, (.2, "{:.3}", self.2));
53
    }
54
}
55
56
let a = A(1, 2, std::f64::consts::PI);
57
58
println!("{:#?}", a);
59
60
/*
61
    A(
62
        1,
63
        3.142,
64
    )
65
*/
66
```
67
68
For enums (without the enum name),
69
70
```rust
71
use std::fmt::{self, Formatter, Debug};
72
73
pub enum A {
74
    V1,
75
    V2(u8, i16, f64),
76
    V3 {
77
        f1: u8,
78
        f2: i16,
79
        f3: f64,
80
    },
81
}
82
83
impl Debug for A {
84
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
85
        debug_helper::impl_debug_for_enum!(A::{V1, (V2(f1, _, f3): (.f1, (.f3, "{:.3}", f3))), {V3{f1, f2: _, f3}: (.f1, (.f3, "{:.3}", f3))}}, f, self);
86
    }
87
}
88
89
let a = A::V1;
90
let b = A::V2(1, 2, std::f64::consts::PI);
91
let c = A::V3{
92
    f1: 1,
93
    f2: 2,
94
    f3: std::f64::consts::PI,
95
};
96
97
println!("{:#?}", a);
98
println!("{:#?}", b);
99
println!("{:#?}", c);
100
101
/*
102
    V1
103
    V2(
104
        1,
105
        3.142,
106
    )
107
    V3 {
108
        f1: 1,
109
        f3: 3.142,
110
    }
111
*/
112
```
113
114
For enums (with the enum name),
115
116
```rust
117
use std::fmt::{self, Formatter, Debug};
118
119
pub enum A {
120
    V1,
121
    V2(u8, i16, f64),
122
    V3 {
123
        f1: u8,
124
        f2: i16,
125
        f3: f64,
126
    },
127
}
128
129
impl Debug for A {
130
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
131
        debug_helper::impl_debug_for_enum!({A::V1, (V2(f1, _, f3): (.f1, (.f3, "{:.3}", f3))), {V3{f1, f2: _, f3}: (.f1, (.f3, "{:.3}", f3))}}, f, self);
132
    }
133
}
134
135
let a = A::V1;
136
let b = A::V2(1, 2, std::f64::consts::PI);
137
let c = A::V3{
138
    f1: 1,
139
    f2: 2,
140
    f3: std::f64::consts::PI,
141
};
142
143
println!("{:#?}", a);
144
println!("{:#?}", b);
145
println!("{:#?}", c);
146
147
/*
148
    A::V1
149
    A::V2(
150
        1,
151
        3.142,
152
    )
153
    A::V3 {
154
        f1: 1,
155
        f3: 3.142,
156
    }
157
*/
158
```
159
160
161
162
Ghost fields,
163
164
```rust
165
use std::fmt::{self, Formatter, Debug};
166
167
pub struct A {
168
    pub f1: u8,
169
    pub f2: i16,
170
    pub f3: f64,
171
}
172
173
impl Debug for A {
174
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
175
        debug_helper::impl_debug_for_struct!(A, f, self, .f1, (.f3, "{:.3}", self.f3), (.sum, "{:.3}", self.f1 as f64 + self.f2 as f64 + self.f3));
176
    }
177
}
178
179
let a = A {
180
    f1: 1,
181
    f2: 2,
182
    f3: std::f64::consts::PI,
183
};
184
185
println!("{:#?}", a);
186
187
/*
188
    A {
189
        f1: 1,
190
        f3: 3.142,
191
        sum: 6.142,
192
    }
193
*/
194
```
195
196
```rust
197
use std::fmt::{self, Formatter, Debug};
198
199
pub struct A(pub u8, pub i16, pub f64);
200
201
impl Debug for A {
202
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
203
        debug_helper::impl_debug_for_tuple_struct!(A, f, self, .0, (.2, "{:.3}", self.2), (.3, "{:.3}", self.0 as f64 + self.1 as f64 + self.2));
204
    }
205
}
206
207
let a = A(1, 2, std::f64::consts::PI);
208
209
println!("{:#?}", a);
210
211
/*
212
    A(
213
        1,
214
        3.142,
215
        6.142,
216
    )
217
*/
218
```
219
220
Fake structs,
221
222
```rust
223
use std::fmt::{self, Formatter, Debug};
224
225
pub struct A(pub u8, pub i16, pub f64);
226
227
impl Debug for A {
228
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
229
        debug_helper::impl_debug_for_struct!(A, f, self, let .f1 = self.0, let .f2 = self.1, let .f3 = self.2);
230
    }
231
}
232
233
let a = A(1, 2, std::f64::consts::PI);
234
235
println!("{:#?}", a);
236
237
/*
238
    A {
239
        f1: 1,
240
        f2: 2,
241
        f3: 3.141592653589793,
242
    }
243
*/
244
```
245
246
Fake tuple structs,
247
248
```rust
249
use std::fmt::{self, Formatter, Debug};
250
251
pub struct A {
252
    pub f1: u8,
253
    pub f2: i16,
254
    pub f3: f64,
255
}
256
257
impl Debug for A {
258
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
259
        debug_helper::impl_debug_for_tuple_struct!(A, f, self, let .0 = self.f1, let .1 = self.f2, let .2 = self.f3);
260
    }
261
}
262
263
let a = A {
264
    f1: 1,
265
    f2: 2,
266
    f3: std::f64::consts::PI,
267
};
268
269
println!("{:#?}", a);
270
271
/*
272
    A(
273
        1,
274
        2,
275
        3.141592653589793,
276
    )
277
*/
278
```
279
280
## TODO
281
282
1. Fake enum struct variants and tuple variants.
283
1. Enum variants can be renamed.
284
285
*/
286
287
#![no_std]
288
289
extern crate alloc;
290
291
use alloc::fmt::{Debug, Formatter, Result as FormatResult};
292
use alloc::string::String;
293
294
#[doc(hidden)]
295
pub struct RawString(pub String);
296
297
impl Debug for RawString {
298
0
    fn fmt(&self, f: &mut Formatter<'_>) -> FormatResult {
299
0
        if f.alternate() {
300
0
            f.write_str(self.0.replace('\n', "\n    ").as_str())
301
        } else {
302
0
            f.write_str(self.0.as_str())
303
        }
304
0
    }
305
}
306
307
#[macro_export]
308
macro_rules! impl_debug_for_struct {
309
    // TODO unit struct
310
    ($struct_name:ident, $formatter:expr $(, $self:expr)? $(,)*) => {
311
        return $formatter.write_str(stringify!($struct_name));
312
    };
313
    // TODO struct
314
    ($struct_name:ident, $formatter:expr, $self:expr, $( $(.$field:ident)? $((.$field_2:ident, $($field_2_fmt:tt)+))? $(let .$field_3:ident = $field_3_value:expr)? ),* $(,)*) => {
315
        {
316
            let mut builder = $formatter.debug_struct(stringify!($struct_name));
317
318
            $(
319
                $(
320
                    builder.field(stringify!($field), &$self.$field);
321
                )?
322
323
                $(
324
                    builder.field(stringify!($field_2), &$crate::RawString(format!($($field_2_fmt)*)));
325
                )?
326
327
                $(
328
                    builder.field(stringify!($field_3), &$field_3_value);
329
                )?
330
            )*
331
332
            return builder.finish();
333
        }
334
    };
335
}
336
337
#[macro_export]
338
macro_rules! impl_debug_for_tuple_struct {
339
    // TODO unit tuple struct
340
    ($struct_name:ident, $formatter:expr $(, $self:expr)? $(,)*) => {
341
        return $formatter.write_str(stringify!($struct_name));
342
    };
343
    // TODO tuple struct
344
    ($struct_name:ident, $formatter:expr, $self:expr, $( $(.$field:tt)? $((.$field_2:tt, $($field_2_fmt:tt)+))? $(let .$field_3:tt = $field_3_value:expr)? ),* $(,)*) => {
345
        {
346
            let mut builder = $formatter.debug_tuple(stringify!($struct_name));
347
348
            $(
349
                $(
350
                    builder.field(&$self.$field);
351
                )?
352
353
                $(
354
                    builder.field(&$crate::RawString(format!($($field_2_fmt)*)));
355
                )?
356
357
                $(
358
                    builder.field(&$field_3_value);
359
                )?
360
            )*
361
362
            return builder.finish();
363
        }
364
    }
365
}
366
367
#[macro_export]
368
macro_rules! impl_debug_for_enum {
369
    // TODO enum
370
    ($enum_name:ident::{$( $($variant_unit:ident)? $(($variant_tuple:ident ($($tuple:tt)*) $(:($( $(.$t_field:tt)? $((.$t_field_2:tt, $($t_field_2_fmt:tt)+))? $(let .$t_field_3:tt = $t_field_3_value:expr)? ),* $(,)*))? ) )? $({$variant_struct:ident {$($struct:tt)*} $(:($( $(.$s_field:tt)? $((.$s_field_2:tt, $($s_field_2_fmt:tt)+))? $(let .$s_field_3:ident = $s_field_3_value:expr)? ),* $(,)*))? })? ),+ $(,)*}, $formatter:expr, $self:expr $(,)*) => {
371
        {
372
            match $self {
373
                $(
374
                    $(
375
                        Self::$variant_unit => {
376
                            return $formatter.write_str(stringify!($variant_unit));
377
                        }
378
                    )?
379
                    $(
380
                        Self::$variant_tuple ($($tuple)*)=> {
381
                            let mut builder = $formatter.debug_tuple(stringify!($variant_tuple));
382
383
                            $(
384
                                $(
385
                                    $(
386
                                        builder.field(&$t_field);
387
                                    )?
388
389
                                    $(
390
                                        builder.field(&$crate::RawString(format!($($t_field_2_fmt)*)));
391
                                    )?
392
393
                                    $(
394
                                        builder.field(&$t_field_3_value);
395
                                    )?
396
                                )*
397
                            )?
398
399
                            return builder.finish();
400
                        }
401
                    )?
402
                    $(
403
                        Self::$variant_struct {$($struct)*}=> {
404
                            let mut builder = $formatter.debug_struct(stringify!($variant_struct));
405
406
                            $(
407
                                $(
408
                                    $(
409
                                        builder.field(stringify!($s_field), &$s_field);
410
                                    )?
411
412
                                    $(
413
                                        builder.field(stringify!($s_field_2), &$crate::RawString(format!($($s_field_2_fmt)*)));
414
                                    )?
415
416
                                    $(
417
                                        builder.field(stringify!($s_field_3), &$s_field_3_value);
418
                                    )?
419
                                )*
420
                            )?
421
422
                            return builder.finish();
423
                        }
424
                    )?
425
                )+
426
            }
427
        }
428
    };
429
    // TODO enum full path
430
    ({$enum_name:ident::$( $($variant_unit:ident)? $(($variant_tuple:ident ($($tuple:tt)*) $(:($( $(.$t_field:tt)? $((.$t_field_2:tt, $($t_field_2_fmt:tt)+))? $(let .$t_field_3:tt = $t_field_3_value:expr)? ),* $(,)*))? ) )? $({$variant_struct:ident {$($struct:tt)*} $(:($( $(.$s_field:tt)? $((.$s_field_2:tt, $($s_field_2_fmt:tt)+))? $(let .$s_field_3:ident = $s_field_3_value:expr)? ),* $(,)*))? })? ),+ $(,)*}, $formatter:expr, $self:expr $(,)*) => {
431
        {
432
            match $self {
433
                $(
434
                    $(
435
                        Self::$variant_unit => {
436
                            $formatter.write_str(stringify!($enum_name))?;
437
                            $formatter.write_str("::")?;
438
                            return $formatter.write_str(stringify!($variant_unit));
439
                        }
440
                    )?
441
                    $(
442
                        Self::$variant_tuple ($($tuple)*)=> {
443
                            let mut builder = $formatter.debug_tuple(&format!("{}::{}", stringify!($enum_name), stringify!($variant_tuple)));
444
445
                            $(
446
                                $(
447
                                    $(
448
                                        builder.field(&$t_field);
449
                                    )?
450
451
                                    $(
452
                                        builder.field(&$crate::RawString(format!($($t_field_2_fmt)*)));
453
                                    )?
454
455
                                    $(
456
                                        builder.field(&$t_field_3_value);
457
                                    )?
458
                                )*
459
                            )?
460
461
                            return builder.finish();
462
                        }
463
                    )?
464
                    $(
465
                        Self::$variant_struct {$($struct)*}=> {
466
                            let mut builder = $formatter.debug_struct(&format!("{}::{}", stringify!($enum_name), stringify!($variant_struct)));
467
468
                            $(
469
                                $(
470
                                    $(
471
                                        builder.field(stringify!($s_field), &$s_field);
472
                                    )?
473
474
                                    $(
475
                                        builder.field(stringify!($s_field_2), &$crate::RawString(format!($($s_field_2_fmt)*)));
476
                                    )?
477
478
                                    $(
479
                                        builder.field(stringify!($s_field_3), &$s_field_3_value);
480
                                    )?
481
                                )*
482
                            )?
483
484
                            return builder.finish();
485
                        }
486
                    )?
487
                )+
488
            }
489
        }
490
    };
491
}