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

facet-rs / facet / 14459841398

15 Apr 2025 02:20AM UTC coverage: 30.835% (+0.7%) from 30.122%
14459841398

push

github

web-flow
Rename opaque to ptr, closes #221 (#222)

47 of 344 new or added lines in 20 files covered. (13.66%)

1 existing line in 1 file now uncovered.

2032 of 6590 relevant lines covered (30.83%)

25.82 hits per line

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

0.0
/facet-core/src/types/smartptr.rs
1
use bitflags::bitflags;
2

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

5
use super::Shape;
6

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

16
    /// shape of the inner type of the smart pointer, if not opaque
17
    pub pointee: Option<&'static Shape>,
18

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

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

25
    /// Flags representing various characteristics of the smart pointer
26
    pub flags: SmartPointerFlags,
27

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

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

47
/// Builder for creating a `SmartPointerDef`.
48
#[derive(Debug)]
49
#[allow(clippy::new_without_default)]
50
pub struct SmartPointerDefBuilder {
51
    vtable: Option<&'static SmartPointerVTable>,
52
    pointee: Option<&'static Shape>,
53
    flags: Option<SmartPointerFlags>,
54
    known: Option<KnownSmartPointer>,
55
    weak: Option<fn() -> &'static Shape>,
56
    strong: Option<fn() -> &'static Shape>,
57
}
58

59
impl SmartPointerDefBuilder {
60
    /// Creates a new `SmartPointerDefBuilder` with all fields set to `None`.
61
    #[must_use]
62
    #[allow(clippy::new_without_default)]
63
    pub const fn new() -> Self {
×
64
        Self {
65
            vtable: None,
66
            pointee: None,
67
            flags: None,
68
            known: None,
69
            weak: None,
70
            strong: None,
71
        }
72
    }
73

74
    /// Sets the vtable for the smart pointer.
75
    #[must_use]
76
    pub const fn vtable(mut self, vtable: &'static SmartPointerVTable) -> Self {
×
77
        self.vtable = Some(vtable);
×
78
        self
×
79
    }
80

81
    /// Sets the shape of the inner type of the smart pointer.
82
    #[must_use]
83
    pub const fn pointee(mut self, pointee: &'static Shape) -> Self {
×
84
        self.pointee = Some(pointee);
×
85
        self
×
86
    }
87

88
    /// Sets the flags for the smart pointer.
89
    #[must_use]
90
    pub const fn flags(mut self, flags: SmartPointerFlags) -> Self {
×
91
        self.flags = Some(flags);
×
92
        self
×
93
    }
94

95
    /// Sets the known smart pointer type.
96
    #[must_use]
97
    pub const fn known(mut self, known: KnownSmartPointer) -> Self {
×
98
        self.known = Some(known);
×
99
        self
×
100
    }
101

102
    /// Sets the shape of the corresponding strong pointer, if this pointer is weak.
103
    #[must_use]
104
    pub const fn weak(mut self, weak: fn() -> &'static Shape) -> Self {
×
105
        self.weak = Some(weak);
×
106
        self
×
107
    }
108

109
    /// Sets the shape of the corresponding non-atomic pointer, if this pointer is atomic.
110
    #[must_use]
111
    pub const fn strong(mut self, strong: fn() -> &'static Shape) -> Self {
×
112
        self.strong = Some(strong);
×
113
        self
×
114
    }
115

116
    /// Builds a `SmartPointerDef` from the provided configuration.
117
    ///
118
    /// # Panics
119
    ///
120
    /// Panics if any required field (vtable, pointee, flags) is not set.
121
    #[must_use]
122
    pub const fn build(self) -> SmartPointerDef {
×
123
        SmartPointerDef {
124
            vtable: self.vtable.unwrap(),
×
125
            pointee: self.pointee,
×
126
            weak: self.weak,
×
127
            strong: self.strong,
×
128
            flags: self.flags.unwrap(),
×
129
            known: self.known,
×
130
        }
131
    }
132
}
133

134
bitflags! {
135
    /// Flags to represent various characteristics of smart pointers
136
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
137
    pub struct SmartPointerFlags: u8 {
138
        /// An empty set of flags
139
        const EMPTY = 0;
140

141
        /// Whether the smart pointer is weak (like [`std::sync::Weak`])
142
        const WEAK = 1 << 0;
143
        /// Whether the smart pointer is atomic (like [`std::sync::Arc`])
144
        const ATOMIC = 1 << 1;
145
        /// Whether the pointer is a lock (like [`std::sync::Mutex`])
146
        const LOCK = 1 << 2;
147
    }
148
}
149

150
/// Tries to upgrade the weak pointer to a strong one.
151
///
152
/// # Safety
153
///
154
/// `weak` must be a valid weak smart pointer (like [`std::sync::Weak`] or [`std::rc::Weak`]).
155
/// `strong` must be allocated, and of the right layout for the corresponding smart pointer.
156
/// `strong` must not have been initialized yet.
157
///
158
/// `weak` is not moved out of — `Weak::upgrade(&self)` takes self by reference.
159
/// If this fails, `strong` is not initialized.
160
///
161
/// `strong.assume_init()` is returned as part of the Option if the upgrade succeeds.
162
/// `None` is returned if this is not a type of smart pointer that supports upgrades.
163
pub type UpgradeIntoFn =
164
    for<'ptr> unsafe fn(weak: PtrMut<'ptr>, strong: PtrUninit<'ptr>) -> Option<PtrMut<'ptr>>;
165

166
/// Downgrades a strong pointer to a weak one.
167
///
168
/// Only strong pointers can be downgraded (like [`std::sync::Arc`] or [`std::rc::Rc`]).
169
///
170
/// # Safety
171
///
172
/// `strong` must be a valid strong smart pointer (like [`std::sync::Arc`] or [`std::rc::Rc`]).
173
/// `weak` must be allocated, and of the right layout for the corresponding weak pointer.
174
/// `weak` must not have been initialized yet.
175
///
176
/// `weak.assume_init()` is returned if the downgrade succeeds.
177
pub type DowngradeIntoFn =
178
    for<'ptr> unsafe fn(strong: PtrMut<'ptr>, weak: PtrUninit<'ptr>) -> PtrMut<'ptr>;
179

180
/// Tries to obtain a reference to the inner value of the smart pointer.
181
///
182
/// Weak pointers don't even have that function in their vtable.
183
pub type BorrowFn = for<'ptr> unsafe fn(opaque: PtrConst<'ptr>) -> PtrConst<'ptr>;
184

185
/// Creates a new smart pointer wrapping the given value. Writes the smart pointer
186
/// into the given `this`.
187
///
188
/// Weak pointers don't even have that function in their vtable.
189
///
190
/// # Safety
191
///
192
/// `this` must have the correct layout.
193
///
194
/// `ptr` must point to a value of type `T`.
195
///
196
/// After calling this, `ptr` has been moved out of, and must be
197
/// deallocated (but not dropped).
198
pub type NewIntoFn =
199
    for<'ptr> unsafe fn(this: PtrUninit<'ptr>, ptr: PtrConst<'ptr>) -> PtrMut<'ptr>;
200

201
/// Type-erased result of locking a mutex-like smart pointer
202
pub struct LockResult<'ptr> {
203
    /// The data that was locked
204
    data: PtrMut<'ptr>,
205
    /// The guard that protects the data
206
    guard: PtrConst<'ptr>,
207
    /// The vtable for the guard
208
    guard_vtable: &'static LockGuardVTable,
209
}
210

211
impl<'ptr> LockResult<'ptr> {
212
    /// Returns a reference to the locked data
NEW
213
    pub fn data(&self) -> &PtrMut<'ptr> {
×
214
        &self.data
×
215
    }
216
}
217

218
impl Drop for LockResult<'_> {
219
    fn drop(&mut self) {
×
220
        unsafe {
221
            (self.guard_vtable.drop_in_place)(self.guard);
×
222
        }
223
    }
224
}
225

226
/// Functions for manipulating a guard
227
pub struct LockGuardVTable {
228
    /// Drops the guard in place
229
    pub drop_in_place: for<'ptr> unsafe fn(guard: PtrConst<'ptr>),
230
}
231

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

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

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

241
/// Functions for interacting with a smart pointer
242
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
243
pub struct SmartPointerVTable {
244
    /// See [`UpgradeIntoFn`]
245
    pub upgrade_into_fn: Option<UpgradeIntoFn>,
246

247
    /// See [`DowngradeIntoFn`]
248
    pub downgrade_into_fn: Option<DowngradeIntoFn>,
249

250
    /// See [`BorrowFn`]
251
    pub borrow_fn: Option<BorrowFn>,
252

253
    /// See [`NewIntoFn`]
254
    pub new_into_fn: Option<NewIntoFn>,
255

256
    /// See [`LockFn`]
257
    pub lock_fn: Option<LockFn>,
258

259
    /// See [`ReadFn`]
260
    pub read_fn: Option<ReadFn>,
261

262
    /// See [`WriteFn`]
263
    pub write_fn: Option<WriteFn>,
264
}
265

266
impl SmartPointerVTable {
267
    /// Creates a new `SmartPointerVTableBuilder` with all fields set to `None`.
268
    #[must_use]
269
    pub const fn builder() -> SmartPointerVTableBuilder {
×
270
        SmartPointerVTableBuilder {
271
            upgrade_into_fn: None,
272
            downgrade_into_fn: None,
273
            borrow_fn: None,
274
            new_fn: None,
275
            lock_fn: None,
276
            read_fn: None,
277
            write_fn: None,
278
        }
279
    }
280
}
281

282
/// Builder for creating a `SmartPointerVTable`.
283
#[derive(Debug)]
284
pub struct SmartPointerVTableBuilder {
285
    upgrade_into_fn: Option<UpgradeIntoFn>,
286
    downgrade_into_fn: Option<DowngradeIntoFn>,
287
    borrow_fn: Option<BorrowFn>,
288
    new_fn: Option<NewIntoFn>,
289
    lock_fn: Option<LockFn>,
290
    read_fn: Option<ReadFn>,
291
    write_fn: Option<WriteFn>,
292
}
293

294
impl SmartPointerVTableBuilder {
295
    /// Creates a new `SmartPointerVTableBuilder` with all fields set to `None`.
296
    #[must_use]
297
    #[allow(clippy::new_without_default)]
298
    pub const fn new() -> Self {
×
299
        Self {
300
            upgrade_into_fn: None,
301
            downgrade_into_fn: None,
302
            borrow_fn: None,
303
            new_fn: None,
304
            lock_fn: None,
305
            read_fn: None,
306
            write_fn: None,
307
        }
308
    }
309

310
    /// Sets the try_upgrade function.
311
    #[must_use]
312
    pub const fn upgrade_into_fn(mut self, upgrade_into_fn: UpgradeIntoFn) -> Self {
×
313
        self.upgrade_into_fn = Some(upgrade_into_fn);
×
314
        self
×
315
    }
316

317
    /// Sets the downgrade function.
318
    #[must_use]
319
    pub const fn downgrade_fn(mut self, downgrade_into_fn: DowngradeIntoFn) -> Self {
×
320
        self.downgrade_into_fn = Some(downgrade_into_fn);
×
321
        self
×
322
    }
323

324
    /// Sets the borrow function.
325
    #[must_use]
326
    pub const fn borrow_fn(mut self, borrow_fn: BorrowFn) -> Self {
×
327
        self.borrow_fn = Some(borrow_fn);
×
328
        self
×
329
    }
330

331
    /// Sets the new function.
332
    #[must_use]
333
    pub const fn new_into_fn(mut self, new_fn: NewIntoFn) -> Self {
×
334
        self.new_fn = Some(new_fn);
×
335
        self
×
336
    }
337

338
    /// Sets the lock function.
339
    #[must_use]
340
    pub const fn lock_fn(mut self, lock_fn: LockFn) -> Self {
×
341
        self.lock_fn = Some(lock_fn);
×
342
        self
×
343
    }
344

345
    /// Sets the read function.
346
    #[must_use]
347
    pub const fn read_fn(mut self, read_fn: ReadFn) -> Self {
×
348
        self.read_fn = Some(read_fn);
×
349
        self
×
350
    }
351

352
    /// Sets the write function.
353
    #[must_use]
354
    pub const fn write_fn(mut self, write_fn: WriteFn) -> Self {
×
355
        self.write_fn = Some(write_fn);
×
356
        self
×
357
    }
358

359
    /// Builds a `SmartPointerVTable` from the provided configuration.
360
    #[must_use]
361
    pub const fn build(self) -> SmartPointerVTable {
×
362
        SmartPointerVTable {
363
            upgrade_into_fn: self.upgrade_into_fn,
×
364
            downgrade_into_fn: self.downgrade_into_fn,
×
365
            borrow_fn: self.borrow_fn,
×
366
            new_into_fn: self.new_fn,
×
367
            lock_fn: self.lock_fn,
×
368
            read_fn: self.read_fn,
×
369
            write_fn: self.write_fn,
×
370
        }
371
    }
372
}
373

374
/// Represents common standard library smart pointer kinds
375
#[non_exhaustive]
376
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
377
pub enum KnownSmartPointer {
378
    /// [`Box<T>`](std::boxed::Box), heap-allocated values with single ownership
379
    Box,
380
    /// [`Rc<T>`](std::rc::Rc), reference-counted values with multiple ownership
381
    Rc,
382
    /// [`Weak<T>`](std::rc::Weak), a weak reference to an `Rc`-managed value
383
    RcWeak,
384
    /// [`Arc<T>`](std::sync::Arc), thread-safe reference-counted values with multiple ownership
385
    Arc,
386
    /// [`Weak<T>`](std::sync::Weak), a weak reference to an `Arc`-managed value
387
    ArcWeak,
388
    /// [`Cow<'a, T>`](std::borrow::Cow), a clone-on-write smart pointer
389
    Cow,
390
    /// [`Pin<P>`](std::pin::Pin), a type that pins values behind a pointer
391
    Pin,
392
    /// [`Cell<T>`](std::cell::Cell), a mutable memory location with interior mutability
393
    Cell,
394
    /// [`RefCell<T>`](std::cell::RefCell), a mutable memory location with dynamic borrowing rules
395
    RefCell,
396
    /// [`OnceCell<T>`](std::cell::OnceCell), a cell that can be written to only once
397
    OnceCell,
398
    /// [`Mutex<T>`](std::sync::Mutex), a mutual exclusion primitive
399
    Mutex,
400
    /// [`RwLock<T>`](std::sync::RwLock), a reader-writer lock
401
    RwLock,
402
    /// [`NonNull<T>`](core::ptr::NonNull), a wrapper around a raw pointer that is not null
403
    NonNull,
404
}
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