• 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/fn_ptr.rs
1
use std::iter;
2

3
// Generate implementations for function pointers up to the following arity
4
const MAX_ARITY: i32 = 6;
5
// Generate implementations for the following calling conventions
6
// (abi-string, abi-enum-variant-name)
7
#[rustfmt::skip]
8
const ABIS: &[(&str, &str)] = &[
9
    ("Rust", "Rust"),
10
    ("C", "C"),
11
];
12

13
/// Generate implementations for function pointers. It's highly repetitive and hard to get done with only
14
/// declarative macros. So that's why it's generated.
NEW
15
pub fn generate() -> String {
×
16
    use std::fmt::Write;
NEW
17
    let mut s = String::with_capacity(65536);
×
18

19
    macro_rules! w {
20
        ($($t:tt)*) => {
21
            write!(s, $($t)*).unwrap()
22
        };
23
    }
24

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

×
NEW
29
    w!("use core::{{alloc::Layout, fmt}};\n\n");
×
NEW
30
    w!("use crate::{{\n");
×
NEW
31
    w!("    value_vtable, ConstTypeId, Def, Facet, FunctionAbi,\n");
×
NEW
32
    w!("    FunctionPointerDef, Shape, TypeNameOpts, TypeParam\n");
×
NEW
33
    w!("}};
×
NEW
34
\n");
×
NEW
35

×
NEW
36
    // Helper functions
×
NEW
37
    w!("#[inline(always)]\n");
×
NEW
38
    w!("pub fn write_type_name_list(\n");
×
NEW
39
    w!("    f: &mut fmt::Formatter<'_>,\n");
×
NEW
40
    w!("    opts: TypeNameOpts,\n");
×
NEW
41
    w!("    abi: FunctionAbi,\n");
×
NEW
42
    w!("    params: &'static [&'static Shape],\n");
×
NEW
43
    w!("    ret_type: &'static Shape,\n");
×
NEW
44
    w!(") -> fmt::Result {{\n");
×
NEW
45
    w!("    if abi != FunctionAbi::Rust {{\n");
×
NEW
46
    w!("        f.pad(\"extern \\\"\")?;\n");
×
NEW
47
    w!("        if let Some(abi) = abi.as_abi_str() {{\n");
×
NEW
48
    w!("            f.pad(abi)?;\n");
×
NEW
49
    w!("        }}\n");
×
NEW
50
    w!("        f.pad(\"\\\" \")?;\n");
×
NEW
51
    w!("    }}\n");
×
NEW
52
    w!("    f.pad(\"fn\")?;\n");
×
NEW
53
    w!("    f.pad(\"(\")?;\n");
×
NEW
54
    w!("    if let Some(opts) = opts.for_children() {{\n");
×
NEW
55
    w!("        for (index, shape) in params.iter().enumerate() {{\n");
×
NEW
56
    w!("            if index > 0 {{\n");
×
NEW
57
    w!("                f.pad(\", \")?;\n");
×
NEW
58
    w!("            }}\n");
×
NEW
59
    w!("            shape.write_type_name(f, opts)?;\n");
×
NEW
60
    w!("        }}\n");
×
NEW
61
    w!("    }} else {{\n");
×
NEW
62
    w!("        write!(f, \"⋯\")?;\n");
×
NEW
63
    w!("    }}\n");
×
NEW
64
    w!("    f.pad(\") -> \")?;\n");
×
NEW
65
    w!("    ret_type.write_type_name(f, opts)?;\n");
×
NEW
66
    w!("    Ok(())\n");
×
NEW
67
    w!("}}\n\n");
×
68

NEW
69
    for &(abi_string, abi_name) in ABIS {
×
NEW
70
        for n in 0..=MAX_ARITY {
×
NEW
71
            let return_param = String::from("R");
×
NEW
72
            // Generate type parameters and where clauses
×
NEW
73
            let type_params = (0..n)
×
NEW
74
                .map(|i| format!("T{}", i))
×
NEW
75
                .collect::<Vec<_>>()
×
NEW
76
                .join(", ");
×
NEW
77
            let where_predicates = (0..n)
×
NEW
78
                .map(|i| format!("T{}: Facet", i))
×
NEW
79
                .chain(iter::once("R: Facet".to_owned()))
×
NEW
80
                .collect::<Vec<_>>()
×
NEW
81
                .join(",\n    ");
×
NEW
82
            let param_shape_list = (0..n)
×
NEW
83
                .map(|i| format!("T{}::SHAPE", i))
×
NEW
84
                .collect::<Vec<_>>()
×
NEW
85
                .join(", ");
×
NEW
86
            let param_shape_ctor = (0..n)
×
NEW
87
                .map(|i| format!("|| T{}::SHAPE", i))
×
NEW
88
                .collect::<Vec<_>>()
×
NEW
89
                .join(", ");
×
NEW
90

×
NEW
91
            let type_param_build = (0..n)
×
NEW
92
                .map(|i| format!("TypeParam {{ name: \"T{i}\", shape: || T{i}::SHAPE }}"))
×
NEW
93
                .collect::<Vec<_>>()
×
NEW
94
                .join(", ");
×
95

NEW
96
            let extern_abi = if abi_string == "Rust" {
×
NEW
97
                String::new()
×
98
            } else {
NEW
99
                format!("extern \"{abi_string}\" ")
×
100
            };
101

102
            // Start impl block
NEW
103
            w!(
×
NEW
104
                "unsafe impl<{return_param}, {type_params}> Facet for {extern_abi}fn({type_params}) -> {return_param}\n",
×
NEW
105
            );
×
NEW
106
            w!("where\n");
×
NEW
107
            w!("    {}\n", where_predicates);
×
NEW
108
            w!("{{\n");
×
NEW
109
            w!("    const SHAPE: &'static Shape = &const {{\n");
×
NEW
110

×
NEW
111
            // type_name function
×
NEW
112
            w!(
×
NEW
113
                "        fn type_name<{return_param}, {type_params}>(f: &mut fmt::Formatter, opts: TypeNameOpts) -> fmt::Result\n",
×
NEW
114
            );
×
NEW
115
            w!("        where\n");
×
NEW
116
            w!("            {}\n", where_predicates);
×
NEW
117
            w!("        {{\n");
×
NEW
118
            w!("            write_type_name_list(\n");
×
NEW
119
            w!("                f,\n");
×
NEW
120
            w!("                opts,\n");
×
NEW
121
            w!("                FunctionAbi::{abi_name},\n");
×
NEW
122
            w!("                &[\n");
×
NEW
123
            w!("                    {}\n", param_shape_list);
×
NEW
124
            w!("                ],\n");
×
NEW
125
            w!("                {return_param}::SHAPE,\n");
×
NEW
126
            w!("            )\n");
×
NEW
127
            w!("        }}\n\n");
×
NEW
128

×
NEW
129
            // Shape builder start
×
NEW
130
            w!("        Shape::builder()\n");
×
NEW
131
            w!("            .id(ConstTypeId::of::<Self>())\n");
×
NEW
132
            w!("            .layout(Layout::new::<Self>())\n");
×
NEW
133
            // FIXME: Dont use the macro here we can generate this
×
NEW
134
            // FIXME: type name
×
NEW
135
            w!(
×
NEW
136
                "            .vtable(value_vtable!(Self, type_name::<{return_param}, {type_params}>))\n"
×
NEW
137
            );
×
NEW
138
            w!("            .type_params(&[{type_param_build}])\n");
×
NEW
139
            w!("            .def(Def::FunctionPointer({{\n");
×
NEW
140
            w!("                FunctionPointerDef::builder()\n");
×
NEW
141
            w!("                    .parameter_types(&const {{ [{param_shape_ctor}] }})\n");
×
NEW
142
            w!("                    .return_type(|| R::SHAPE)\n");
×
NEW
143
            w!("                    .abi(FunctionAbi::{})\n", abi_name);
×
NEW
144
            w!("                    .build()\n");
×
NEW
145
            w!("            }}))\n");
×
NEW
146

×
NEW
147
            // Finish implementation
×
NEW
148
            w!("            .build()\n");
×
NEW
149
            w!("    }};\n");
×
NEW
150
            w!("}}\n");
×
151
        }
152
    }
NEW
153
    s
×
NEW
154
}
×
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