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

facet-rs / facet / 16482855623

23 Jul 2025 10:08PM UTC coverage: 58.447% (-0.2%) from 58.68%
16482855623

Pull #855

github

web-flow
Merge dca4c2302 into 5e8e214d1
Pull Request #855: wip: Remove 'shape lifetime

400 of 572 new or added lines in 70 files covered. (69.93%)

3 existing lines in 3 files now uncovered.

11939 of 20427 relevant lines covered (58.45%)

120.58 hits per line

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

1.65
/facet-core/src/types/def/pointer.rs
1
use bitflags::bitflags;
2

3
use crate::{GenericPtr, PtrConst, PtrMut, PtrUninit};
4

5
use super::Shape;
6

7
/// Describes a pointer — including a vtable to query and alter its state,
8
/// and the inner shape (the pointee type in the pointer).
9
#[derive(Clone, Copy, Debug)]
10
#[repr(C)]
11
pub struct PointerDef {
12
    /// vtable for interacting with the pointer
13
    pub vtable: &'static PointerVTable,
14

15
    /// shape of the inner type of the pointer, if not opaque
16
    pub pointee: Option<fn() -> &'static Shape>,
17

18
    /// shape of the corresponding strong pointer, if this pointer is weak
19
    pub weak: Option<fn() -> &'static Shape>,
20

21
    /// shape of the corresponding weak pointer, if this pointer is strong
22
    pub strong: Option<fn() -> &'static Shape>,
23

24
    /// Flags representing various characteristics of the pointer
25
    pub flags: PointerFlags,
26

27
    /// An optional field to identify the kind of pointer
28
    pub known: Option<KnownPointer>,
29
}
30

31
impl PointerDef {
32
    /// Creates a new `PointerDefBuilder` with all fields set to `None`.
33
    #[must_use]
NEW
34
    pub const fn builder() -> PointerDefBuilder {
×
35
        PointerDefBuilder {
×
36
            vtable: None,
×
37
            pointee: None,
×
38
            flags: None,
×
39
            known: None,
×
40
            weak: None,
×
41
            strong: None,
×
42
        }
×
43
    }
×
44

45
    /// Returns shape of the inner type of the pointer, if not opaque
46
    pub fn pointee(&self) -> Option<&'static Shape> {
112✔
47
        self.pointee.map(|v| v())
112✔
48
    }
112✔
49

50
    /// Returns shape of the corresponding strong pointer, if this pointer is weak
NEW
51
    pub fn weak(&self) -> Option<&'static Shape> {
×
52
        self.weak.map(|v| v())
×
53
    }
×
54

55
    /// Returns shape of the corresponding weak pointer, if this pointer is strong
NEW
56
    pub fn strong(&self) -> Option<&'static Shape> {
×
57
        self.strong.map(|v| v())
×
58
    }
×
59
}
60

61
/// Builder for creating a `PointerDef`.
62
#[derive(Debug)]
63
pub struct PointerDefBuilder {
64
    vtable: Option<&'static PointerVTable>,
65
    pointee: Option<fn() -> &'static Shape>,
66
    flags: Option<PointerFlags>,
67
    known: Option<KnownPointer>,
68
    weak: Option<fn() -> &'static Shape>,
69
    strong: Option<fn() -> &'static Shape>,
70
}
71

72
impl PointerDefBuilder {
73
    /// Creates a new `PointerDefBuilder` with all fields set to `None`.
74
    #[must_use]
75
    #[expect(clippy::new_without_default)]
76
    pub const fn new() -> Self {
×
77
        Self {
×
78
            vtable: None,
×
79
            pointee: None,
×
80
            flags: None,
×
81
            known: None,
×
82
            weak: None,
×
83
            strong: None,
×
84
        }
×
85
    }
×
86

87
    /// Sets the vtable for the pointer.
88
    #[must_use]
NEW
89
    pub const fn vtable(mut self, vtable: &'static PointerVTable) -> Self {
×
90
        self.vtable = Some(vtable);
×
91
        self
×
92
    }
×
93

94
    /// Sets the shape of the inner type of the pointer.
95
    #[must_use]
NEW
96
    pub const fn pointee(mut self, pointee: fn() -> &'static Shape) -> Self {
×
97
        self.pointee = Some(pointee);
×
98
        self
×
99
    }
×
100

101
    /// Sets the flags for the pointer.
102
    #[must_use]
103
    pub const fn flags(mut self, flags: PointerFlags) -> Self {
×
104
        self.flags = Some(flags);
×
105
        self
×
106
    }
×
107

108
    /// Sets the known pointer type.
109
    #[must_use]
110
    pub const fn known(mut self, known: KnownPointer) -> Self {
×
111
        self.known = Some(known);
×
112
        self
×
113
    }
×
114

115
    /// Sets the shape of the corresponding weak pointer, if this pointer is strong.
116
    #[must_use]
NEW
117
    pub const fn weak(mut self, weak: fn() -> &'static Shape) -> Self {
×
118
        self.weak = Some(weak);
×
119
        self
×
120
    }
×
121

122
    /// Sets the shape of the corresponding strong pointer, if this pointer is weak
123
    #[must_use]
NEW
124
    pub const fn strong(mut self, strong: fn() -> &'static Shape) -> Self {
×
125
        self.strong = Some(strong);
×
126
        self
×
127
    }
×
128

129
    /// Builds a `PointerDef` from the provided configuration.
130
    ///
131
    /// # Panics
132
    ///
133
    /// Panics if any required field (vtable, flags) is not set.
134
    #[must_use]
NEW
135
    pub const fn build(self) -> PointerDef {
×
136
        PointerDef {
×
137
            vtable: self.vtable.unwrap(),
×
138
            pointee: self.pointee,
×
139
            weak: self.weak,
×
140
            strong: self.strong,
×
141
            flags: self.flags.unwrap(),
×
142
            known: self.known,
×
143
        }
×
144
    }
×
145
}
146

147
bitflags! {
148
    /// Flags to represent various characteristics of pointers
149
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
150
    pub struct PointerFlags: u8 {
151
        /// An empty set of flags
152
        const EMPTY = 0;
153

154
        /// Whether the pointer is weak (like [`std::sync::Weak`])
155
        const WEAK = 1 << 0;
156
        /// Whether the pointer is atomic (like [`std::sync::Arc`])
157
        const ATOMIC = 1 << 1;
158
        /// Whether the pointer is a lock (like [`std::sync::Mutex`])
159
        const LOCK = 1 << 2;
160
    }
161
}
162

163
/// Tries to upgrade the weak pointer to a strong one.
164
///
165
/// If the upgrade succeeds, initializes the pointer into the given `strong`, and returns a
166
/// copy of `strong`, which has been guaranteed to be initialized. If the upgrade fails, `None` is
167
/// returned and `strong` is not initialized.
168
///
169
/// `weak` is not moved out of.
170
///
171
/// # Safety
172
///
173
/// `weak` must be a valid weak pointer (like [`std::sync::Weak`] or [`std::rc::Weak`]).
174
///
175
/// `strong` must be allocated, and of the right layout for the corresponding pointer.
176
///
177
/// `strong` must not have been initialized yet.
178
pub type UpgradeIntoFn =
179
    for<'ptr> unsafe fn(weak: PtrMut<'ptr>, strong: PtrUninit<'ptr>) -> Option<PtrMut<'ptr>>;
180

181
/// Downgrades a strong pointer to a weak one.
182
///
183
/// Initializes the pointer into the given `weak`, and returns a copy of `weak`, which has
184
/// been guaranteed to be initialized.
185
///
186
/// Only strong pointers can be downgraded (like [`std::sync::Arc`] or [`std::rc::Rc`]).
187
///
188
/// # Safety
189
///
190
/// `strong` must be a valid strong pointer (like [`std::sync::Arc`] or [`std::rc::Rc`]).
191
///
192
/// `weak` must be allocated, and of the right layout for the corresponding weak pointer.
193
///
194
/// `weak` must not have been initialized yet.
195
pub type DowngradeIntoFn =
196
    for<'ptr> unsafe fn(strong: PtrMut<'ptr>, weak: PtrUninit<'ptr>) -> PtrMut<'ptr>;
197

198
/// Tries to obtain a reference to the inner value of the pointer.
199
///
200
/// This can only be used with strong pointers (like [`std::sync::Arc`] or [`std::rc::Rc`]).
201
///
202
/// # Safety
203
///
204
/// `this` must be a valid strong pointer (like [`std::sync::Arc`] or [`std::rc::Rc`]).
205
pub type BorrowFn = for<'ptr> unsafe fn(this: PtrConst<'ptr>) -> GenericPtr<'ptr>;
206

207
/// Creates a new pointer wrapping the given value.
208
///
209
/// Initializes the pointer into the given `this`, and returns a copy of `this`, which has
210
/// been guaranteed to be initialized.
211
///
212
/// This can only be used with strong pointers (like [`std::sync::Arc`] or [`std::rc::Rc`]).
213
///
214
/// # Safety
215
///
216
/// `this` must be allocated, and of the right layout for the corresponding pointer.
217
///
218
/// `this` must not have been initialized yet.
219
///
220
/// `ptr` must point to a value of type `T`.
221
///
222
/// `ptr` is moved out of (with [`core::ptr::read`]) — it should be deallocated afterwards (e.g.
223
/// with [`core::mem::forget`]) but NOT dropped).
224
pub type NewIntoFn = for<'ptr> unsafe fn(this: PtrUninit<'ptr>, ptr: PtrMut<'ptr>) -> PtrMut<'ptr>;
225

226
/// Type-erased result of locking a mutex-like pointer
227
pub struct LockResult<'ptr> {
228
    /// The data that was locked
229
    data: PtrMut<'ptr>,
230
    /// The guard that protects the data
231
    guard: PtrConst<'ptr>,
232
    /// The vtable for the guard
233
    guard_vtable: &'static LockGuardVTable,
234
}
235

236
impl<'ptr> LockResult<'ptr> {
237
    /// Returns a reference to the locked data
238
    #[must_use]
239
    pub fn data(&self) -> &PtrMut<'ptr> {
×
240
        &self.data
×
241
    }
×
242
}
243

244
impl Drop for LockResult<'_> {
245
    fn drop(&mut self) {
×
246
        unsafe {
×
247
            (self.guard_vtable.drop_in_place)(self.guard);
×
248
        }
×
249
    }
×
250
}
251

252
/// Functions for manipulating a guard
253
pub struct LockGuardVTable {
254
    /// Drops the guard in place
255
    pub drop_in_place: for<'ptr> unsafe fn(guard: PtrConst<'ptr>),
256
}
257

258
/// Acquires a lock on a mutex-like pointer
259
pub type LockFn = for<'ptr> unsafe fn(opaque: PtrConst<'ptr>) -> Result<LockResult<'ptr>, ()>;
260

261
/// Acquires a read lock on a reader-writer lock-like pointer
262
pub type ReadFn = for<'ptr> unsafe fn(opaque: PtrConst<'ptr>) -> Result<LockResult<'ptr>, ()>;
263

264
/// Acquires a write lock on a reader-writer lock-like pointer
265
pub type WriteFn = for<'ptr> unsafe fn(opaque: PtrConst<'ptr>) -> Result<LockResult<'ptr>, ()>;
266

267
/// Creates a new slice builder for a pointer: ie. for `Arc<[u8]>`, it builds a
268
/// `Vec<u8>` internally, to which you can push, and then turn into an `Arc<[u8]>` at
269
/// the last stage.
270
///
271
/// This works for any `U` in `Arc<[U]>` because those have separate concrete implementations, and
272
/// thus, separate concrete vtables.
273
pub type SliceBuilderNewFn = fn() -> PtrMut<'static>;
274

275
/// Pushes a value into a slice builder.
276
///
277
/// # Safety
278
///
279
/// Item must point to a valid value of type `U` and must be initialized.
280
/// Function is infallible as it uses the global allocator.
281
pub type SliceBuilderPushFn = unsafe fn(builder: PtrMut, item: PtrMut);
282

283
/// Converts a slice builder into a pointer. This takes ownership of the builder
284
/// and frees the backing storage.
285
///
286
/// # Safety
287
///
288
/// The builder must be valid and must not be used after this function is called.
289
/// Function is infallible as it uses the global allocator.
290
pub type SliceBuilderConvertFn = unsafe fn(builder: PtrMut<'static>) -> PtrConst<'static>;
291

292
/// Frees a slice builder without converting it into a pointer
293
///
294
/// # Safety
295
///
296
/// The builder must be valid and must not be used after this function is called.
297
pub type SliceBuilderFreeFn = unsafe fn(builder: PtrMut<'static>);
298

299
/// Functions for creating and manipulating slice builders.
300
#[derive(Debug, Clone, Copy)]
301
pub struct SliceBuilderVTable {
302
    /// See [`SliceBuilderNewFn`]
303
    pub new_fn: SliceBuilderNewFn,
304
    /// See [`SliceBuilderPushFn`]
305
    pub push_fn: SliceBuilderPushFn,
306
    /// See [`SliceBuilderConvertFn`]
307
    pub convert_fn: SliceBuilderConvertFn,
308
    /// See [`SliceBuilderFreeFn`]
309
    pub free_fn: SliceBuilderFreeFn,
310
}
311

312
impl SliceBuilderVTable {
313
    /// Creates a new `SliceBuilderVTableBuilder` with all fields set to `None`.
314
    #[must_use]
315
    pub const fn builder() -> SliceBuilderVTableBuilder {
×
316
        SliceBuilderVTableBuilder {
×
317
            new_fn: None,
×
318
            push_fn: None,
×
319
            convert_fn: None,
×
320
            free_fn: None,
×
321
        }
×
322
    }
×
323
}
324

325
/// Builder for creating a `SliceBuilderVTable`.
326
#[derive(Debug)]
327
pub struct SliceBuilderVTableBuilder {
328
    new_fn: Option<SliceBuilderNewFn>,
329
    push_fn: Option<SliceBuilderPushFn>,
330
    convert_fn: Option<SliceBuilderConvertFn>,
331
    free_fn: Option<SliceBuilderFreeFn>,
332
}
333

334
impl SliceBuilderVTableBuilder {
335
    /// Creates a new `SliceBuilderVTableBuilder` with all fields set to `None`.
336
    #[must_use]
337
    #[expect(clippy::new_without_default)]
338
    pub const fn new() -> Self {
×
339
        Self {
×
340
            new_fn: None,
×
341
            push_fn: None,
×
342
            convert_fn: None,
×
343
            free_fn: None,
×
344
        }
×
345
    }
×
346

347
    /// Sets the `new` function for the slice builder.
348
    #[must_use]
349
    pub const fn new_fn(mut self, new_fn: SliceBuilderNewFn) -> Self {
×
350
        self.new_fn = Some(new_fn);
×
351
        self
×
352
    }
×
353

354
    /// Sets the `push` function for the slice builder.
355
    #[must_use]
356
    pub const fn push_fn(mut self, push_fn: SliceBuilderPushFn) -> Self {
×
357
        self.push_fn = Some(push_fn);
×
358
        self
×
359
    }
×
360

361
    /// Sets the `convert` function for the slice builder.
362
    #[must_use]
363
    pub const fn convert_fn(mut self, convert_fn: SliceBuilderConvertFn) -> Self {
×
364
        self.convert_fn = Some(convert_fn);
×
365
        self
×
366
    }
×
367

368
    /// Sets the `free` function for the slice builder.
369
    #[must_use]
370
    pub const fn free_fn(mut self, free_fn: SliceBuilderFreeFn) -> Self {
×
371
        self.free_fn = Some(free_fn);
×
372
        self
×
373
    }
×
374

375
    /// Builds a `SliceBuilderVTable` from the provided configuration.
376
    #[must_use]
377
    pub const fn build(self) -> SliceBuilderVTable {
×
378
        SliceBuilderVTable {
×
379
            new_fn: self.new_fn.expect("new_fn must be set"),
×
380
            push_fn: self.push_fn.expect("push_fn must be set"),
×
381
            convert_fn: self.convert_fn.expect("convert_fn must be set"),
×
382
            free_fn: self.free_fn.expect("free_fn must be set"),
×
383
        }
×
384
    }
×
385
}
386

387
/// Functions for interacting with a pointer
388
#[derive(Debug, Clone, Copy)]
389
pub struct PointerVTable {
390
    /// See [`UpgradeIntoFn`]
391
    pub upgrade_into_fn: Option<UpgradeIntoFn>,
392

393
    /// See [`DowngradeIntoFn`]
394
    pub downgrade_into_fn: Option<DowngradeIntoFn>,
395

396
    /// See [`BorrowFn`]
397
    pub borrow_fn: Option<BorrowFn>,
398

399
    /// See [`NewIntoFn`]
400
    pub new_into_fn: Option<NewIntoFn>,
401

402
    /// See [`LockFn`]
403
    pub lock_fn: Option<LockFn>,
404

405
    /// See [`ReadFn`]
406
    pub read_fn: Option<ReadFn>,
407

408
    /// See [`WriteFn`]
409
    pub write_fn: Option<WriteFn>,
410

411
    /// See [`SliceBuilderVTable`]
412
    pub slice_builder_vtable: Option<&'static SliceBuilderVTable>,
413
}
414

415
impl PointerVTable {
416
    /// Creates a new `PointerVTableBuilder` with all fields set to `None`.
417
    #[must_use]
NEW
418
    pub const fn builder() -> PointerVTableBuilder {
×
419
        PointerVTableBuilder {
×
420
            upgrade_into_fn: None,
×
421
            downgrade_into_fn: None,
×
422
            borrow_fn: None,
×
423
            new_into_fn: None,
×
424
            lock_fn: None,
×
425
            read_fn: None,
×
426
            write_fn: None,
×
427
            slice_builder_vtable: None,
×
428
        }
×
429
    }
×
430
}
431

432
/// Builder for creating a `PointerVTable`.
433
#[derive(Debug)]
434
pub struct PointerVTableBuilder {
435
    upgrade_into_fn: Option<UpgradeIntoFn>,
436
    downgrade_into_fn: Option<DowngradeIntoFn>,
437
    borrow_fn: Option<BorrowFn>,
438
    new_into_fn: Option<NewIntoFn>,
439
    lock_fn: Option<LockFn>,
440
    read_fn: Option<ReadFn>,
441
    write_fn: Option<WriteFn>,
442
    slice_builder_vtable: Option<&'static SliceBuilderVTable>,
443
}
444

445
impl PointerVTableBuilder {
446
    /// Creates a new `PointerVTableBuilder` with all fields set to `None`.
447
    #[must_use]
448
    #[expect(clippy::new_without_default)]
449
    pub const fn new() -> Self {
×
450
        Self {
×
451
            upgrade_into_fn: None,
×
452
            downgrade_into_fn: None,
×
453
            borrow_fn: None,
×
454
            new_into_fn: None,
×
455
            lock_fn: None,
×
456
            read_fn: None,
×
457
            write_fn: None,
×
458
            slice_builder_vtable: None,
×
459
        }
×
460
    }
×
461

462
    /// Sets the `try_upgrade` function.
463
    #[must_use]
464
    pub const fn upgrade_into_fn(mut self, upgrade_into_fn: UpgradeIntoFn) -> Self {
×
465
        self.upgrade_into_fn = Some(upgrade_into_fn);
×
466
        self
×
467
    }
×
468

469
    /// Sets the `downgrade` function.
470
    #[must_use]
471
    pub const fn downgrade_into_fn(mut self, downgrade_into_fn: DowngradeIntoFn) -> Self {
×
472
        self.downgrade_into_fn = Some(downgrade_into_fn);
×
473
        self
×
474
    }
×
475

476
    /// Sets the `borrow` function.
477
    #[must_use]
478
    pub const fn borrow_fn(mut self, borrow_fn: BorrowFn) -> Self {
×
479
        self.borrow_fn = Some(borrow_fn);
×
480
        self
×
481
    }
×
482

483
    /// Sets the `new_into` function.
484
    #[must_use]
485
    pub const fn new_into_fn(mut self, new_into_fn: NewIntoFn) -> Self {
×
486
        self.new_into_fn = Some(new_into_fn);
×
487
        self
×
488
    }
×
489

490
    /// Sets the `lock` function.
491
    #[must_use]
492
    pub const fn lock_fn(mut self, lock_fn: LockFn) -> Self {
×
493
        self.lock_fn = Some(lock_fn);
×
494
        self
×
495
    }
×
496

497
    /// Sets the `read` function.
498
    #[must_use]
499
    pub const fn read_fn(mut self, read_fn: ReadFn) -> Self {
×
500
        self.read_fn = Some(read_fn);
×
501
        self
×
502
    }
×
503

504
    /// Sets the `write` function.
505
    #[must_use]
506
    pub const fn write_fn(mut self, write_fn: WriteFn) -> Self {
×
507
        self.write_fn = Some(write_fn);
×
508
        self
×
509
    }
×
510

511
    /// Sets the `slice_builder_vtable` function.
512
    #[must_use]
513
    pub const fn slice_builder_vtable(
×
514
        mut self,
×
NEW
515
        slice_builder_vtable: &'static SliceBuilderVTable,
×
516
    ) -> Self {
×
517
        self.slice_builder_vtable = Some(slice_builder_vtable);
×
518
        self
×
519
    }
×
520

521
    /// Builds a `PointerVTable` from the provided configuration.
522
    #[must_use]
NEW
523
    pub const fn build(self) -> PointerVTable {
×
524
        PointerVTable {
×
525
            upgrade_into_fn: self.upgrade_into_fn,
×
526
            downgrade_into_fn: self.downgrade_into_fn,
×
527
            borrow_fn: self.borrow_fn,
×
528
            new_into_fn: self.new_into_fn,
×
529
            lock_fn: self.lock_fn,
×
530
            read_fn: self.read_fn,
×
531
            write_fn: self.write_fn,
×
532
            slice_builder_vtable: self.slice_builder_vtable,
×
533
        }
×
534
    }
×
535
}
536

537
/// Represents common standard library pointer kinds
538
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
539
pub enum KnownPointer {
540
    /// [`Box<T>`](std::boxed::Box), heap-allocated values with single ownership
541
    Box,
542
    /// [`Rc<T>`](std::rc::Rc), reference-counted values with multiple ownership
543
    Rc,
544
    /// [`Weak<T>`](std::rc::Weak), a weak reference to an `Rc`-managed value
545
    RcWeak,
546
    /// [`Arc<T>`](std::sync::Arc), thread-safe reference-counted values with multiple ownership
547
    Arc,
548
    /// [`Weak<T>`](std::sync::Weak), a weak reference to an `Arc`-managed value
549
    ArcWeak,
550
    /// [`Cow<'a, T>`](std::borrow::Cow), a clone-on-write smart pointer
551
    Cow,
552
    /// [`Pin<P>`](std::pin::Pin), a type that pins values behind a pointer
553
    Pin,
554
    /// [`Cell<T>`](std::cell::Cell), a mutable memory location with interior mutability
555
    Cell,
556
    /// [`RefCell<T>`](std::cell::RefCell), a mutable memory location with dynamic borrowing rules
557
    RefCell,
558
    /// [`OnceCell<T>`](std::cell::OnceCell), a cell that can be written to only once
559
    OnceCell,
560
    /// [`Mutex<T>`](std::sync::Mutex), a mutual exclusion primitive
561
    Mutex,
562
    /// [`RwLock<T>`](std::sync::RwLock), a reader-writer lock
563
    RwLock,
564
    /// [`NonNull<T>`](core::ptr::NonNull), a wrapper around a raw pointer that is not null
565
    NonNull,
566
    /// `&T`
567
    SharedReference,
568
    /// `&mut T`
569
    ExclusiveReference,
570
}
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