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

facet-rs / facet / 20134750802

11 Dec 2025 01:29PM UTC coverage: 57.796% (-0.1%) from 57.906%
20134750802

push

github

fasterthanlime
feat: Add concept of truthiness

The easiest way to tell if something should be serialized or not!

61 of 197 new or added lines in 14 files covered. (30.96%)

1 existing line in 1 file now uncovered.

28969 of 50123 relevant lines covered (57.8%)

6281.89 hits per line

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

47.66
/facet-core/src/impls/core/pointer.rs
1
//! Facet implementation for raw pointers (*const T, *mut T)
2

3
use core::cmp::Ordering;
4
use core::hash::Hash;
5

6
use crate::{
7
    Def, Facet, HashProxy, OxPtrConst, OxPtrMut, PointerType, Shape, ShapeBuilder, Type,
8
    TypeOpsIndirect, TypeParam, VTableIndirect, ValuePointerType, Variance,
9
};
10

11
// For raw pointers, we use indirect vtable since they're generic over T
12
// However, they're scalars so the implementations are simple
13

14
/// Debug for *const T
15
unsafe fn const_ptr_debug<T: ?Sized>(
59✔
16
    ox: OxPtrConst,
59✔
17
    f: &mut core::fmt::Formatter<'_>,
59✔
18
) -> Option<core::fmt::Result> {
59✔
19
    let p = unsafe { ox.ptr().get::<*const T>() };
59✔
20
    Some(core::fmt::Debug::fmt(&p, f))
59✔
21
}
59✔
22

23
/// Hash for *const T
24
unsafe fn const_ptr_hash<T: ?Sized>(ox: OxPtrConst, hasher: &mut HashProxy<'_>) -> Option<()> {
×
25
    let p = unsafe { ox.ptr().get::<*const T>() };
×
26
    p.hash(hasher);
×
27
    Some(())
×
28
}
×
29

30
/// PartialEq for *const T
31
#[allow(ambiguous_wide_pointer_comparisons)]
32
unsafe fn const_ptr_partial_eq<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<bool> {
12✔
33
    let a_val = unsafe { a.ptr().get::<*const T>() };
12✔
34
    let b_val = unsafe { b.ptr().get::<*const T>() };
12✔
35
    Some(*a_val == *b_val)
12✔
36
}
12✔
37

38
/// PartialOrd for *const T
39
#[allow(ambiguous_wide_pointer_comparisons)]
40
unsafe fn const_ptr_partial_cmp<T: ?Sized>(
12✔
41
    a: OxPtrConst,
12✔
42
    b: OxPtrConst,
12✔
43
) -> Option<Option<Ordering>> {
12✔
44
    let a_val = unsafe { a.ptr().get::<*const T>() };
12✔
45
    let b_val = unsafe { b.ptr().get::<*const T>() };
12✔
46
    Some(a_val.partial_cmp(b_val))
12✔
47
}
12✔
48

49
/// Ord for *const T
50
#[allow(ambiguous_wide_pointer_comparisons)]
51
unsafe fn const_ptr_cmp<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<Ordering> {
12✔
52
    let a_val = unsafe { a.ptr().get::<*const T>() };
12✔
53
    let b_val = unsafe { b.ptr().get::<*const T>() };
12✔
54
    Some(a_val.cmp(b_val))
12✔
55
}
12✔
56

57
/// Drop for *const T (no-op, pointers don't need dropping)
58
unsafe fn const_ptr_drop<T: ?Sized>(_ptr: OxPtrMut) {
8✔
59
    // Pointers don't need dropping
60
}
8✔
61

62
/// Clone for *const T (Copy types can be cloned by copying)
63
unsafe fn const_ptr_clone<T: ?Sized>(src: OxPtrConst, dst: OxPtrMut) {
8✔
64
    let src_val = unsafe { src.ptr().get::<*const T>() };
8✔
65
    let dst_ptr = unsafe { dst.ptr().as_mut::<*const T>() };
8✔
66
    *dst_ptr = *src_val;
8✔
67
}
8✔
68

69
/// Debug for *mut T
70
unsafe fn mut_ptr_debug<T: ?Sized>(
40✔
71
    ox: OxPtrConst,
40✔
72
    f: &mut core::fmt::Formatter<'_>,
40✔
73
) -> Option<core::fmt::Result> {
40✔
74
    let p = unsafe { ox.ptr().get::<*mut T>() };
40✔
75
    Some(core::fmt::Debug::fmt(&p, f))
40✔
76
}
40✔
77

78
/// Hash for *mut T
79
unsafe fn mut_ptr_hash<T: ?Sized>(ox: OxPtrConst, hasher: &mut HashProxy<'_>) -> Option<()> {
×
80
    let p = unsafe { ox.ptr().get::<*mut T>() };
×
81
    p.hash(hasher);
×
82
    Some(())
×
83
}
×
84

85
/// PartialEq for *mut T
86
#[allow(ambiguous_wide_pointer_comparisons)]
87
unsafe fn mut_ptr_partial_eq<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<bool> {
8✔
88
    let a_val = unsafe { a.ptr().get::<*mut T>() };
8✔
89
    let b_val = unsafe { b.ptr().get::<*mut T>() };
8✔
90
    Some(*a_val == *b_val)
8✔
91
}
8✔
92

93
/// PartialOrd for *mut T
94
#[allow(ambiguous_wide_pointer_comparisons)]
95
unsafe fn mut_ptr_partial_cmp<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<Option<Ordering>> {
8✔
96
    let a_val = unsafe { a.ptr().get::<*mut T>() };
8✔
97
    let b_val = unsafe { b.ptr().get::<*mut T>() };
8✔
98
    Some(a_val.partial_cmp(b_val))
8✔
99
}
8✔
100

101
/// Ord for *mut T
102
#[allow(ambiguous_wide_pointer_comparisons)]
103
unsafe fn mut_ptr_cmp<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<Ordering> {
8✔
104
    let a_val = unsafe { a.ptr().get::<*mut T>() };
8✔
105
    let b_val = unsafe { b.ptr().get::<*mut T>() };
8✔
106
    Some(a_val.cmp(b_val))
8✔
107
}
8✔
108

109
/// Drop for *mut T (no-op, pointers don't need dropping)
110
unsafe fn mut_ptr_drop<T: ?Sized>(_ptr: OxPtrMut) {
8✔
111
    // Pointers don't need dropping
112
}
8✔
113

114
/// Clone for *mut T (Copy types can be cloned by copying)
115
unsafe fn mut_ptr_clone<T: ?Sized>(src: OxPtrConst, dst: OxPtrMut) {
8✔
116
    let src_val = unsafe { src.ptr().get::<*mut T>() };
8✔
117
    let dst_ptr = unsafe { dst.ptr().as_mut::<*mut T>() };
8✔
118
    *dst_ptr = *src_val;
8✔
119
}
8✔
120

121
// *const pointers
122
unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for *const T {
123
    const SHAPE: &'static Shape = &const {
124
        const fn build_const_ptr_vtable<'a, T: Facet<'a> + ?Sized>() -> VTableIndirect {
×
125
            VTableIndirect {
×
126
                display: None,
×
127
                debug: Some(const_ptr_debug::<T>),
×
128
                hash: Some(const_ptr_hash::<T>),
×
129
                invariants: None,
×
130
                parse: None,
×
131
                try_from: None,
×
132
                try_into_inner: None,
×
133
                try_borrow_inner: None,
×
134
                partial_eq: Some(const_ptr_partial_eq::<T>),
×
135
                partial_cmp: Some(const_ptr_partial_cmp::<T>),
×
136
                cmp: Some(const_ptr_cmp::<T>),
×
137
            }
×
138
        }
×
139

140
        const fn build_const_ptr_type_ops<T: ?Sized>() -> TypeOpsIndirect {
×
141
            TypeOpsIndirect {
×
142
                drop_in_place: const_ptr_drop::<T>,
×
143
                default_in_place: None,
×
144
                clone_into: Some(const_ptr_clone::<T>),
×
NEW
145
                is_truthy: None,
×
146
            }
×
147
        }
×
148

149
        ShapeBuilder::for_sized::<*const T>("*const T")
150
            .ty({
151
                let is_wide = ::core::mem::size_of::<Self>() != ::core::mem::size_of::<*const ()>();
152
                let vpt = ValuePointerType {
153
                    mutable: false,
154
                    wide: is_wide,
155
                    target: T::SHAPE,
156
                };
157
                Type::Pointer(PointerType::Raw(vpt))
158
            })
159
            .def(Def::Scalar)
160
            .type_params(&[TypeParam {
161
                name: "T",
162
                shape: T::SHAPE,
163
            }])
164
            .inner(T::SHAPE)
165
            .vtable_indirect(&const { build_const_ptr_vtable::<T>() })
166
            .type_ops_indirect(&const { build_const_ptr_type_ops::<T>() })
167
            .eq()
168
            .copy()
169
            .build()
170
    };
171
}
172

173
// *mut pointers
174
unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for *mut T {
175
    const SHAPE: &'static Shape = &const {
176
        const fn build_mut_ptr_vtable<'a, T: Facet<'a> + ?Sized>() -> VTableIndirect {
×
177
            VTableIndirect {
×
178
                display: None,
×
179
                debug: Some(mut_ptr_debug::<T>),
×
180
                hash: Some(mut_ptr_hash::<T>),
×
181
                invariants: None,
×
182
                parse: None,
×
183
                try_from: None,
×
184
                try_into_inner: None,
×
185
                try_borrow_inner: None,
×
186
                partial_eq: Some(mut_ptr_partial_eq::<T>),
×
187
                partial_cmp: Some(mut_ptr_partial_cmp::<T>),
×
188
                cmp: Some(mut_ptr_cmp::<T>),
×
189
            }
×
190
        }
×
191

192
        const fn build_mut_ptr_type_ops<T: ?Sized>() -> TypeOpsIndirect {
×
193
            TypeOpsIndirect {
×
194
                drop_in_place: mut_ptr_drop::<T>,
×
195
                default_in_place: None,
×
196
                clone_into: Some(mut_ptr_clone::<T>),
×
NEW
197
                is_truthy: None,
×
198
            }
×
199
        }
×
200

201
        ShapeBuilder::for_sized::<*mut T>("*mut T")
202
            .ty({
203
                let is_wide = ::core::mem::size_of::<Self>() != ::core::mem::size_of::<*const ()>();
204
                let vpt = ValuePointerType {
205
                    mutable: true,
206
                    wide: is_wide,
207
                    target: T::SHAPE,
208
                };
209
                Type::Pointer(PointerType::Raw(vpt))
210
            })
211
            .def(Def::Scalar)
212
            .type_params(&[TypeParam {
213
                name: "T",
214
                shape: T::SHAPE,
215
            }])
216
            .inner(T::SHAPE)
217
            .vtable_indirect(&const { build_mut_ptr_vtable::<T>() })
218
            .type_ops_indirect(&const { build_mut_ptr_type_ops::<T>() })
219
            // *mut T is invariant in T
220
            .variance(Variance::INVARIANT)
221
            .eq()
222
            .copy()
223
            .build()
224
    };
225
}
226

227
#[cfg(test)]
228
mod test {
229
    use core::panic::{RefUnwindSafe, UnwindSafe};
230

231
    #[cfg(feature = "auto-traits")]
232
    use impls::impls;
233

234
    #[allow(unused)]
235
    const fn assert_impls_unwind_safe<T: UnwindSafe>() {}
×
236
    #[allow(unused)]
237
    const fn assert_impls_ref_unwind_safe<T: RefUnwindSafe>() {}
×
238

239
    #[allow(unused)]
240
    const fn ref_unwind_safe<T: RefUnwindSafe>() {
×
241
        assert_impls_unwind_safe::<&T>();
×
242
        assert_impls_ref_unwind_safe::<&T>();
×
243

244
        assert_impls_ref_unwind_safe::<&mut T>();
×
245

246
        assert_impls_unwind_safe::<*const T>();
×
247
        assert_impls_ref_unwind_safe::<*const T>();
×
248

249
        assert_impls_unwind_safe::<*mut T>();
×
250
        assert_impls_ref_unwind_safe::<*mut T>();
×
251
    }
×
252

253
    #[test]
254
    #[cfg(feature = "auto-traits")]
255
    fn mut_ref_not_unwind_safe() {
256
        assert!(impls!(&mut (): !UnwindSafe));
257
    }
258
}
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