• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

facet-rs / facet / 14570645698

21 Apr 2025 08:57AM UTC coverage: 46.087% (-1.7%) from 47.789%
14570645698

push

github

Veykril
Implement `Facet` for (subset of) function pointers

42 of 551 new or added lines in 6 files covered. (7.62%)

1 existing line in 1 file now uncovered.

5848 of 12689 relevant lines covered (46.09%)

55.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/facet-dev/src/tuples.rs
1
/// Generate implementations for tuples. It's highly repetitive and hard to get done with only
2
/// declarative macros. So that's why it's generated.
3
pub fn generate() -> String {
×
4
    use std::fmt::Write;
5
    let mut s = String::with_capacity(65536);
×
6

7
    macro_rules! w {
8
        ($($t:tt)*) => {
9
            write!(s, $($t)*).unwrap()
10
        };
11
    }
12

13
    // Header
NEW
14
    w!("//! GENERATED: DO NOT EDIT — this file is generated by the `facet-dev` crate.\n");
×
NEW
15
    w!("//! Run `just gen` to regenerate.\n\n");
×
16

×
17
    w!("use core::{{alloc::Layout, fmt}};\n\n");
×
18
    w!("use crate::{{\n");
×
19
    w!("    Characteristic, ConstTypeId, Def, Facet, Field, FieldFlags, PtrConst, Shape,\n");
×
20
    w!("    Struct, TypeNameOpts, ValueVTable,\n");
×
21
    w!("}};
×
22
\n");
×
23

×
24
    // Helper functions
×
25
    w!("#[inline(always)]\n");
×
26
    w!("pub fn write_type_name_list(\n");
×
27
    w!("    f: &mut fmt::Formatter<'_>,\n");
×
28
    w!("    opts: TypeNameOpts,\n");
×
29
    w!("    open: &'static str,\n");
×
30
    w!("    delimiter: &'static str,\n");
×
31
    w!("    close: &'static str,\n");
×
32
    w!("    shapes: &'static [&'static Shape],\n");
×
33
    w!(") -> fmt::Result {{\n");
×
34
    w!("    f.pad(open)?;\n");
×
35
    w!("    if let Some(opts) = opts.for_children() {{\n");
×
36
    w!("        for (index, shape) in shapes.iter().enumerate() {{\n");
×
37
    w!("            if index > 0 {{\n");
×
38
    w!("                f.pad(delimiter)?;\n");
×
39
    w!("            }}\n");
×
40
    w!("            shape.write_type_name(f, opts)?;\n");
×
41
    w!("        }}\n");
×
42
    w!("    }} else {{\n");
×
43
    w!("        write!(f, \"⋯\")?;\n");
×
44
    w!("    }}\n");
×
45
    w!("    f.pad(close)?;\n");
×
46
    w!("    Ok(())\n");
×
47
    w!("}}\n\n");
×
48

×
49
    w!("macro_rules! field {{\n");
×
50
    w!("    ($idx:tt, $ty:ty,) => {{\n");
×
51
    w!("        Field::builder()\n");
×
52
    w!("            .name(stringify!($idx))\n");
×
53
    w!("            .shape(|| $crate::shape_of(&|t: &$ty| &t.$idx))\n");
×
54
    w!("            .offset(core::mem::offset_of!($ty, $idx))\n");
×
55
    w!("            .flags(FieldFlags::EMPTY)\n");
×
56
    w!("            .build()\n");
×
57
    w!("    }};\n");
×
58
    w!("}}\n\n");
×
59

×
60
    // Generate implementations for tuples of different sizes
×
61
    let max_tuple_size = 12;
×
62

63
    for n in 1..=max_tuple_size {
×
64
        // Generate type parameters and where clauses
65
        let type_params = (0..n)
×
66
            .map(|i| format!("T{}", i))
×
67
            .collect::<Vec<_>>()
×
68
            .join(", ");
×
69
        let where_predicates = (0..n)
×
70
            .map(|i| format!("T{}: Facet", i))
×
71
            .collect::<Vec<_>>()
×
72
            .join(",\n    ");
×
73
        let shape_list = (0..n)
×
74
            .map(|i| format!("T{}::SHAPE", i))
×
75
            .collect::<Vec<_>>()
×
76
            .join(", ");
×
77

×
78
        // Start impl block
×
79
        w!(
×
80
            "unsafe impl<{}> Facet for {}
×
81
",
×
82
            type_params,
×
83
            // Handle formatting of tuple types correctly
×
84
            if n == 1 {
×
85
                "(T0,)".to_string()
×
86
            } else {
87
                format!("({})", type_params)
×
88
            },
89
        );
90
        w!("where\n");
×
91
        w!("    {}\n", where_predicates);
×
92
        w!("{{\n");
×
93
        w!("    const SHAPE: &'static Shape = &const {{\n");
×
94

×
95
        // type_name function
×
96
        w!(
×
97
            "        fn type_name<{}>(f: &mut fmt::Formatter, opts: TypeNameOpts) -> fmt::Result\n",
×
98
            type_params
×
99
        );
×
100
        w!("        where\n");
×
101
        w!("            {}\n", where_predicates);
×
102
        w!("        {{\n");
×
103
        if n <= 3 {
×
104
            w!(
×
105
                "            write_type_name_list(f, opts, \"(\", \", \", \")\", &[{}])\n",
×
106
                shape_list
×
107
            );
×
108
        } else {
×
109
            w!("            write_type_name_list(\n");
×
110
            w!("                f,\n");
×
111
            w!("                opts,\n");
×
112
            w!("                \"(\",\n");
×
113
            w!("                \", \",\n");
×
114
            w!("                \")\",\n");
×
115
            w!("                &[\n");
×
116
            w!("                    {},\n", shape_list);
×
117
            w!("                ],\n");
×
118
            w!("            )\n");
×
119
        }
×
120
        w!("        }}\n\n");
×
121

×
122
        // Shape builder start
×
123
        w!("        Shape::builder()\n");
×
124
        w!("            .id(ConstTypeId::of::<");
×
125
        if n == 1 {
×
126
            w!("(T0,)")
×
127
        } else {
128
            w!("({})", type_params)
×
129
        }
130
        w!(">())\n");
×
131
        w!("            .layout(Layout::new::<");
×
132
        if n == 1 {
×
133
            w!("(T0,)")
×
134
        } else {
135
            w!("({})", type_params)
×
136
        }
137
        w!(">())\n");
×
138
        w!("            .vtable(\n");
×
139
        w!("                &const {{\n");
×
140
        w!("                    let mut builder = ValueVTable::builder()\n");
×
141
        w!(
×
142
            "                        .type_name(type_name::<{}>)\n",
×
143
            type_params
×
144
        );
×
145
        w!("                        .marker_traits(");
×
146
        if n == 1 {
×
147
            w!("T0::SHAPE.vtable.marker_traits);\n\n")
×
148
        } else {
149
            w!("                        {{\n");
×
150
            w!("                            T0::SHAPE.vtable.marker_traits\n");
×
151
            for i in 1..n {
×
152
                w!(
×
153
                    "                                .intersection(T{i}::SHAPE.vtable.marker_traits)\n"
×
154
                );
×
155
            }
×
156
            w!("                    }});\n\n");
×
157
        }
158

159
        // Conditional debug and eq implementations
160
        w!("                    if Characteristic::Eq.all(&[");
×
161
        if n <= 5 {
×
162
            w!("{}", shape_list);
×
163
        } else {
×
164
            w!("\n");
×
165
            w!("                        {},\n", shape_list);
×
166
            w!("                    ");
×
167
        }
×
168
        w!("]) {{\n");
×
169

×
170
        // debug implementation
×
171
        w!("                        builder = builder.debug(|value, f| {{\n");
×
172
        if n == 1 {
×
173
            w!("                            let value = unsafe {{ value.get::<(T0,)>() }};\n");
×
174
        } else {
×
175
            w!(
×
176
                "                            let value = unsafe {{ value.get::<({})>() }};\n",
×
177
                type_params
×
178
            );
×
179
        }
×
180
        w!("                            write!(f, \"(\")?;\n");
×
181

182
        for i in 0..n {
×
183
            if i > 0 {
×
184
                w!("                            write!(f, \", \")?;\n");
×
185
            }
×
186
            w!("                            unsafe {{\n");
×
187
            w!(
×
188
                "                                let ptr = &value.{0} as *const T{0};\n",
×
189
                i
×
190
            );
×
191
            w!(
×
192
                "                                (T{0}::SHAPE.vtable.debug.unwrap_unchecked())(\n",
×
193
                i
×
194
            );
×
195
            w!("                                    PtrConst::new(ptr),\n");
×
196
            w!("                                    f,\n");
×
197
            w!("                                )\n");
×
198
            w!("                            }}?;\n");
×
199
        }
200

201
        w!("                            write!(f, \")\")\n");
×
202
        w!("                        }});\n\n");
×
203

×
204
        // eq implementation
×
205
        w!("                        builder = builder.eq(|a, b| {{\n");
×
206
        if n == 1 {
×
207
            w!("                            let a = unsafe {{ a.get::<(T0,)>() }};\n");
×
208
            w!("                            let b = unsafe {{ b.get::<(T0,)>() }};\n\n");
×
209
        } else {
×
210
            w!(
×
211
                "                            let a = unsafe {{ a.get::<({})>() }};\n",
×
212
                type_params
×
213
            );
×
214
            w!(
×
215
                "                            let b = unsafe {{ b.get::<({})>() }};\n\n",
×
216
                type_params
×
217
            );
×
218
        }
×
219

220
        // Compare elements except the last one
221
        for i in 0..n - 1 {
×
222
            w!("                            // Compare element {}\n", i);
×
223
            w!("                            unsafe {{\n");
×
224
            w!(
×
225
                "                                let a_ptr = &a.{0} as *const T{0};\n",
×
226
                i
×
227
            );
×
228
            w!(
×
229
                "                                let b_ptr = &b.{0} as *const T{0};\n",
×
230
                i
×
231
            );
×
232
            w!(
×
233
                "                                if !(T{0}::SHAPE.vtable.eq.unwrap_unchecked())(\n",
×
234
                i
×
235
            );
×
236
            w!("                                    PtrConst::new(a_ptr),\n");
×
237
            w!("                                    PtrConst::new(b_ptr),\n");
×
238
            w!("                                ) {{\n");
×
239
            w!("                                    return false;\n");
×
240
            w!("                                }}\n");
×
241
            w!("                            }}\n\n");
×
242
        }
×
243

244
        // Special case for the last element
245
        let last = n - 1;
×
246
        w!("                            // Compare last element\n");
×
247
        w!("                            unsafe {{\n");
×
248
        w!(
×
249
            "                                (T{0}::SHAPE.vtable.eq.unwrap_unchecked())(\n",
×
250
            last
×
251
        );
×
252
        w!(
×
253
            "                                    PtrConst::new(&a.{0} as *const T{0}),\n",
×
254
            last
×
255
        );
×
256
        w!(
×
257
            "                                    PtrConst::new(&b.{0} as *const T{0}),\n",
×
258
            last
×
259
        );
×
260
        w!("                                )\n");
×
261
        w!("                            }}\n");
×
262
        w!("                        }});\n");
×
263
        w!("                    }}\n\n");
×
264

×
265
        // Finish vtable builder
×
266
        w!("                    builder.build()\n");
×
267
        w!("                }},\n");
×
268
        w!("            )\n");
×
269
        w!("            .def(Def::Struct({{\n");
×
270
        w!("                Struct::builder()\n");
×
271
        w!("                    .tuple()\n");
×
272
        w!("                    .fields(\n");
×
273

×
274
        // Generate field array
×
275
        if n <= 3 {
×
276
            w!("                        &const {{ [");
×
277
            for i in 0..n {
×
278
                if i > 0 {
×
279
                    w!(",\n                        ");
×
280
                }
×
281
                if n == 1 {
×
282
                    w!("field!({}, (T0,),)", i);
×
283
                } else {
×
284
                    let field_tuple = format!("({},)", type_params);
×
285
                    w!("field!({}, {},)", i, field_tuple);
×
286
                }
×
287
            }
288
            w!("] }}\n");
×
289
        } else {
290
            w!("                        &const {{\n");
×
291
            w!("                            [\n");
×
292
            for i in 0..n {
×
293
                if n == 1 {
×
294
                    w!("                                field!({}, (T0,),)", i);
×
295
                } else {
×
296
                    let field_tuple = format!("({},)", type_params);
×
297
                    w!(
×
298
                        "                                field!({}, {},)",
×
299
                        i,
×
300
                        field_tuple
×
301
                    );
×
302
                }
×
303
                if i < n - 1 {
×
304
                    w!(",\n");
×
305
                } else {
×
306
                    w!("\n");
×
307
                }
×
308
            }
309
            w!("                            ]\n");
×
310
            w!("                        }},\n");
×
311
        }
312

313
        // Finish implementation
314
        w!("                    )\n");
×
315
        w!("                    .build()\n");
×
316
        w!("            }}))\n");
×
317
        w!("            .build()\n");
×
318
        w!("    }};\n");
×
319
        w!("}}\n");
×
320
    }
321

322
    s
×
323
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc