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

facet-rs / facet / 14434945618

14 Apr 2025 12:35AM UTC coverage: 19.561% (-12.1%) from 31.623%
14434945618

Pull #188

github

web-flow
Merge 8230131c0 into 046ca7ecc
Pull Request #188: Rewrite facet-reflect for safety

421 of 969 new or added lines in 44 files covered. (43.45%)

679 existing lines in 19 files now uncovered.

1149 of 5874 relevant lines covered (19.56%)

8.61 hits per line

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

0.0
/facet-derive/src/process_struct.rs
1
use super::*;
2

3
/// Processes a regular struct to implement Facet
4
///
5
/// Example input:
6
/// ```rust
7
/// struct Blah {
8
///     foo: u32,
9
///     bar: String,
10
/// }
11
/// ```
12
pub(crate) fn process_struct(parsed: Struct) -> proc_macro::TokenStream {
×
13
    let struct_name = parsed.name.to_string();
×
14

15
    // Generate field definitions
16
    let (generics_def, generics_use) = generics_split_for_impl(parsed.generics.as_ref());
×
17
    let kind;
18
    let where_clauses;
19

20
    let fields = match &parsed.kind {
×
21
        StructKind::Struct { clauses, fields } => {
×
22
            kind = "::facet::StructKind::Struct";
×
23
            where_clauses = clauses.as_ref();
×
24
            fields
×
25
                .content
×
26
                .0
×
27
                .iter()
28
                .map(|field| {
×
29
                    let field_name = field.value.name.to_string();
×
30
                    gen_struct_field(
×
31
                        &field_name,
×
32
                        &struct_name,
×
33
                        &generics_use,
×
34
                        &field.value.attributes,
×
35
                    )
36
                })
37
                .collect::<Vec<String>>()
38
        }
39
        StructKind::TupleStruct {
40
            fields,
×
41
            clauses,
×
42
            semi: _,
×
43
        } => {
×
44
            kind = "::facet::StructKind::TupleStruct";
×
45
            where_clauses = clauses.as_ref();
×
46
            fields
×
47
                .content
×
48
                .0
×
49
                .iter()
50
                .enumerate()
51
                .map(|(index, field)| {
×
52
                    let field_name = format!("{index}");
×
53
                    gen_struct_field(
×
54
                        &field_name,
×
55
                        &struct_name,
×
56
                        &generics_use,
×
57
                        &field.value.attributes,
×
58
                    )
59
                })
60
                .collect::<Vec<String>>()
61
        }
62
        StructKind::UnitStruct { clauses, semi: _ } => {
×
63
            kind = "::facet::StructKind::Unit";
×
64
            where_clauses = clauses.as_ref();
×
65
            vec![]
×
66
        }
67
    }
68
    .join(", ");
69

70
    let static_decl = if parsed.generics.is_none() {
×
71
        generate_static_decl(&struct_name)
×
72
    } else {
73
        String::new()
×
74
    };
75
    let maybe_container_doc = build_maybe_doc(&parsed.attributes);
×
76
    let where_clauses = where_clauses.map_or(String::new(), ToString::to_string);
×
77

NEW
78
    let mut invariant_maybe = "".to_string();
×
NEW
79
    let invariant_attrs = parsed
×
NEW
80
        .attributes
×
81
        .iter()
NEW
82
        .filter_map(|attr| match &attr.body.content {
×
NEW
83
            AttributeInner::Facet(facet_attr) => match &facet_attr.inner.content {
×
NEW
84
                FacetInner::Invariants(invariant_inner) => Some(invariant_inner),
×
NEW
85
                _ => None,
×
86
            },
NEW
87
            _ => None,
×
88
        })
89
        .collect::<Vec<_>>();
90

NEW
91
    if !invariant_attrs.is_empty() {
×
NEW
92
        let tests = invariant_attrs
×
93
            .iter()
NEW
94
            .map(|invariant| {
×
NEW
95
                let invariant_name = invariant.value.as_str();
×
NEW
96
                format!(
×
NEW
97
                    r#"
×
NEW
98
                    if !value.{invariant_name}() {{
×
NEW
99
                        return false;
×
100
                    }}
NEW
101
                    "#
×
102
                )
103
            })
104
            .collect::<Vec<_>>()
105
            .join("\n");
106

NEW
107
        let invariant_fn = format!(
×
108
            r#"
109
            unsafe fn invariants<'mem>(value: ::facet::OpaqueConst<'mem>) -> bool {{
110
                let value = value.get::<{struct_name}<{generics_use}>>();
111
                {tests}
112
                true
113
            }}
114
            "#
115
        );
116

NEW
117
        invariant_maybe = format!(
×
NEW
118
            r#"
×
NEW
119
            {invariant_fn}
×
120

NEW
121
            vtable.invariants = Some(invariants);
×
NEW
122
            "#
×
123
        );
124
    }
125

126
    // Generate the impl
127
    let output = format!(
×
128
        r#"
129
{static_decl}
130

131
#[automatically_derived]
132
unsafe impl<{generics_def}> ::facet::Facet for {struct_name}<{generics_use}> {where_clauses} {{
133
    const SHAPE: &'static ::facet::Shape = &const {{
134
        let fields: &'static [::facet::Field] = &const {{[{fields}]}};
135

136
        let vtable = &const {{
137
            let mut vtable = ::facet::value_vtable_inner!(
138
                Self,
139
                |f, _opts| ::core::fmt::Write::write_str(f, "{struct_name}")
140
            );
141
            {invariant_maybe}
142
            vtable
143
        }};
144

145
        ::facet::Shape::builder()
146
            .id(::facet::ConstTypeId::of::<Self>())
147
            .layout(::core::alloc::Layout::new::<Self>())
148
            .vtable(vtable)
149
            .def(::facet::Def::Struct(::facet::Struct::builder()
150
                .kind({kind})
151
                .fields(fields)
152
                .build()))
153
            {maybe_container_doc}
154
            .build()
155
    }};
156
}}
157
        "#
158
    );
159

160
    output.into_token_stream().into()
×
161
}
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