/
debug-print.rs
134 lines (113 loc) · 2.93 KB
/
debug-print.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#![allow(incomplete_features)]
#![feature(adt_const_params)]
use constduck::{
ConstDuck, ConstDuckGeneric, Field, FieldList, FieldListCons, FieldListNil, Struct,
};
use std::fmt;
// Some boring formatting stuff
#[derive(Copy, Clone)]
struct Indent {
n: usize,
}
impl Indent {
pub fn next(&self) -> Indent {
Indent { n: self.n + 1 }
}
pub fn new() -> Indent {
Indent { n: 0 }
}
}
impl fmt::Display for Indent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for _ in 0..self.n {
write!(f, " ")?;
}
Ok(())
}
}
// The trait we're going to implement.
// MyPrint will simply print all the fields of a struct to stdout, recursively.
trait MyPrint {
fn print(&self, indent: Indent);
}
// Implementations for some basic types
impl MyPrint for &'static str {
fn print(&self, indent: Indent) {
println!("{}&'static str = {:?}", indent, self);
}
}
impl MyPrint for u32 {
fn print(&self, indent: Indent) {
println!("{}u32 = {}", indent, self);
}
}
// Implementation guard to make sure nobody else can implement conflicting implementations.
struct ImplGuard;
// Helper trait for printing fields in a field list
trait PrintHelper<O> {
fn print(obj: &O, indent: Indent);
}
impl<O> PrintHelper<O> for FieldListNil {
fn print(_: &O, _: Indent) {}
}
// `MyPrint` implementation for a struct
impl<O, L: FieldList + PrintHelper<O>> PrintHelper<O> for Struct<L> {
fn print(obj: &O, indent: Indent) {
L::print(obj, indent);
}
}
impl<O, const NAME: &'static str, T: FieldList> PrintHelper<O> for FieldListCons<NAME, T>
where
O: Field<NAME>,
O::Ty: MyPrint,
T: PrintHelper<O>,
{
fn print(obj: &O, indent: Indent) {
println!("{}Field `{}`", indent, NAME);
obj.get().print(indent.next());
T::print(obj, indent);
}
}
// `MyPrint` implementation for all types that derive `ConstDuck`.
impl<T: ConstDuckGeneric<ImplGuard>> MyPrint for T
where
<T as ConstDuckGeneric<ImplGuard>>::Reflect: PrintHelper<T>,
{
fn print(&self, indent: Indent) {
println!("{}struct `{}`:", indent, T::NAME);
<T::Reflect as PrintHelper<T>>::print(&self, indent.next())
}
}
fn main() {
// Derive ConstDuck for some types
#[derive(ConstDuck)]
struct Foo {
bar: Bar,
baz: Baz,
}
#[derive(ConstDuck)]
struct Bar {
life: u32,
is_like: &'static str,
a: u32,
}
#[derive(ConstDuck)]
struct Baz {
hurricane: &'static str,
}
// Use MyPrint for a simple type
let baz = Baz { hurricane: "Hello" };
baz.print(Indent::new());
// Use MyPrint for a more complex type
let foo = Foo {
bar: Bar {
life: 16,
is_like: "Hello, world!",
a: 100_234,
},
baz: Baz {
hurricane: "Hello, world!",
},
};
foo.print(Indent::new());
}