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

facet-rs / facet / 14439337006

14 Apr 2025 06:53AM UTC coverage: 21.3% (-10.3%) from 31.623%
14439337006

push

github

web-flow
Rewrite facet-reflect for safety (#188)

* Rewrite facet-reflect for safety

* WIP invariants support

* WIP invariants

* WIP invariants

* Invariant validation works!

* Fix derive for enums

* Start documenting new reflect

* Comment out other workspace members for now.

* Get rid of warnings, tests pass again for now

* Update main readme

* Take care of Peek

* Yay no more errors in peek

* Most of Peek is back.

* PeekOption tests

* fix enum test

* Refactor enum field access methods

Replace field name-based access with index-based access and provide
a field_by_name helper. Remove redundant tuple_field method in favor
of a unified field access approach that works for both tuple and struct
variants.

* PeekList tests

* no clippy warnings

* Avoid clippy --all-features locally, which trashes target/

* Add map tests

* Some smart pointer tests

* Avoid cycles with delayed/fns

* Fix doc errors, rename impls to different file paths

* Option Debug

* f64 implements PartialCmp

* Replace as_ref with get in all unsafe blocks.

* When putting into a PokeValueUninit, require : 'mem

cf. #190 / https://github.com/facet-rs/facet/issues/190#issuecomment-2799860033

* Document facet-ansi

* Light ui test harness

* Make sure the facet-ansi tests can pass.

* Port facet-pretty over

* facet-pretty good except indentation, ofc

* Fix doc comment formatting

* Port libc sample test

* Uncomment scalar test

* Re-add smart pointer tests

* WIP HeapVal wrapper

* Wip HeapValue wrapper

* API design is hard okay

* Oh now poke tests are ANGRY

* Still HeapAlloc'ing

* More HeapVal

* whew 4

* Mhh slots are gonna be hard to get right

* well some things are failing BADLY

* no problems huh

* 2 failing

* mhmh

* mh

* I don't get it

* Test tree

* Try out a tree

* Cannot move out of huh, where have I heard that before

* Tree => builder

* New builder API coming along

* there we have it again — an invariant violation

* OMG IT WAS MEMCPY ALL ALONG

* Ah, ... (continued)

518 of 1109 new or added lines in 45 files covered. (46.71%)

642 existing lines in 17 files now uncovered.

1278 of 6000 relevant lines covered (21.3%)

12.01 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