facet_core/types/def/smartptr.rs
1use bitflags::bitflags;
2
3use crate::{GenericPtr, PtrConst, PtrMut, PtrUninit};
4
5use 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, Debug)]
10#[repr(C)]
11pub struct SmartPointerDef<'shape> {
12 /// vtable for interacting with the smart pointer
13 pub vtable: &'shape SmartPointerVTable<'shape>,
14
15 /// shape of the inner type of the smart pointer, if not opaque
16 pub pointee: Option<fn() -> &'shape Shape<'shape>>,
17
18 /// shape of the corresponding strong pointer, if this pointer is weak
19 pub weak: Option<fn() -> &'shape Shape<'shape>>,
20
21 /// shape of the corresponding weak pointer, if this pointer is strong
22 pub strong: Option<fn() -> &'shape Shape<'shape>>,
23
24 /// Flags representing various characteristics of the smart pointer
25 pub flags: SmartPointerFlags,
26
27 /// An optional field to identify the kind of smart pointer
28 pub known: Option<KnownSmartPointer>,
29}
30
31impl<'shape> SmartPointerDef<'shape> {
32 /// Creates a new `SmartPointerDefBuilder` with all fields set to `None`.
33 #[must_use]
34 pub const fn builder() -> SmartPointerDefBuilder<'shape> {
35 SmartPointerDefBuilder {
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 smart pointer, if not opaque
46 pub fn pointee(&self) -> Option<&'shape Shape<'shape>> {
47 self.pointee.map(|v| v())
48 }
49
50 /// Returns shape of the corresponding strong pointer, if this pointer is weak
51 pub fn weak(&self) -> Option<&'shape Shape<'shape>> {
52 self.weak.map(|v| v())
53 }
54
55 /// Returns shape of the corresponding weak pointer, if this pointer is strong
56 pub fn strong(&self) -> Option<&'shape Shape<'shape>> {
57 self.strong.map(|v| v())
58 }
59}
60
61/// Builder for creating a `SmartPointerDef`.
62#[derive(Debug)]
63pub struct SmartPointerDefBuilder<'shape> {
64 vtable: Option<&'shape SmartPointerVTable<'shape>>,
65 pointee: Option<fn() -> &'shape Shape<'shape>>,
66 flags: Option<SmartPointerFlags>,
67 known: Option<KnownSmartPointer>,
68 weak: Option<fn() -> &'shape Shape<'shape>>,
69 strong: Option<fn() -> &'shape Shape<'shape>>,
70}
71
72impl<'shape> SmartPointerDefBuilder<'shape> {
73 /// Creates a new `SmartPointerDefBuilder` 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 smart pointer.
88 #[must_use]
89 pub const fn vtable(mut self, vtable: &'shape SmartPointerVTable) -> Self {
90 self.vtable = Some(vtable);
91 self
92 }
93
94 /// Sets the shape of the inner type of the smart pointer.
95 #[must_use]
96 pub const fn pointee(mut self, pointee: fn() -> &'shape Shape<'shape>) -> Self {
97 self.pointee = Some(pointee);
98 self
99 }
100
101 /// Sets the flags for the smart pointer.
102 #[must_use]
103 pub const fn flags(mut self, flags: SmartPointerFlags) -> Self {
104 self.flags = Some(flags);
105 self
106 }
107
108 /// Sets the known smart pointer type.
109 #[must_use]
110 pub const fn known(mut self, known: KnownSmartPointer) -> 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]
117 pub const fn weak(mut self, weak: fn() -> &'shape Shape<'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]
124 pub const fn strong(mut self, strong: fn() -> &'shape Shape<'shape>) -> Self {
125 self.strong = Some(strong);
126 self
127 }
128
129 /// Builds a `SmartPointerDef` from the provided configuration.
130 ///
131 /// # Panics
132 ///
133 /// Panics if any required field (vtable, flags) is not set.
134 #[must_use]
135 pub const fn build(self) -> SmartPointerDef<'shape> {
136 SmartPointerDef {
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
147bitflags! {
148 /// Flags to represent various characteristics of smart pointers
149 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
150 pub struct SmartPointerFlags: u8 {
151 /// An empty set of flags
152 const EMPTY = 0;
153
154 /// Whether the smart pointer is weak (like [`std::sync::Weak`])
155 const WEAK = 1 << 0;
156 /// Whether the smart 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 smart 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 smart pointer (like [`std::sync::Weak`] or [`std::rc::Weak`]).
174///
175/// `strong` must be allocated, and of the right layout for the corresponding smart pointer.
176///
177/// `strong` must not have been initialized yet.
178pub 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 smart 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 smart 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.
195pub 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 smart 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 smart pointer (like [`std::sync::Arc`] or [`std::rc::Rc`]).
205pub type BorrowFn = for<'ptr> unsafe fn(this: PtrConst<'ptr>) -> GenericPtr<'ptr>;
206
207/// Creates a new smart pointer wrapping the given value.
208///
209/// Initializes the smart 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 smart 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).
224pub type NewIntoFn = for<'ptr> unsafe fn(this: PtrUninit<'ptr>, ptr: PtrMut<'ptr>) -> PtrMut<'ptr>;
225
226/// Type-erased result of locking a mutex-like smart pointer
227pub 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
236impl<'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
244impl 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
253pub 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 smart pointer
259pub type LockFn = for<'ptr> unsafe fn(opaque: PtrConst<'ptr>) -> Result<LockResult<'ptr>, ()>;
260
261/// Acquires a read lock on a reader-writer lock-like smart pointer
262pub type ReadFn = for<'ptr> unsafe fn(opaque: PtrConst<'ptr>) -> Result<LockResult<'ptr>, ()>;
263
264/// Acquires a write lock on a reader-writer lock-like smart pointer
265pub type WriteFn = for<'ptr> unsafe fn(opaque: PtrConst<'ptr>) -> Result<LockResult<'ptr>, ()>;
266
267/// Creates a new slice builder for a smart 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.
273pub 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.
281pub type SliceBuilderPushFn = unsafe fn(builder: PtrMut, item: PtrMut);
282
283/// Converts a slice builder into a smart 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.
290pub type SliceBuilderConvertFn = unsafe fn(builder: PtrMut<'static>) -> PtrConst<'static>;
291
292/// Frees a slice builder without converting it into a smart pointer
293///
294/// # Safety
295///
296/// The builder must be valid and must not be used after this function is called.
297pub type SliceBuilderFreeFn = unsafe fn(builder: PtrMut<'static>);
298
299/// Functions for creating and manipulating slice builders.
300#[derive(Debug, Clone, Copy)]
301pub 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
312impl 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)]
327pub struct SliceBuilderVTableBuilder {
328 new_fn: Option<SliceBuilderNewFn>,
329 push_fn: Option<SliceBuilderPushFn>,
330 convert_fn: Option<SliceBuilderConvertFn>,
331 free_fn: Option<SliceBuilderFreeFn>,
332}
333
334impl 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 smart pointer
388#[derive(Debug, Clone, Copy)]
389pub struct SmartPointerVTable<'shape> {
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<&'shape SliceBuilderVTable>,
413}
414
415impl<'shape> SmartPointerVTable<'shape> {
416 /// Creates a new `SmartPointerVTableBuilder` with all fields set to `None`.
417 #[must_use]
418 pub const fn builder() -> SmartPointerVTableBuilder<'shape> {
419 SmartPointerVTableBuilder {
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 `SmartPointerVTable`.
433#[derive(Debug)]
434pub struct SmartPointerVTableBuilder<'shape> {
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<&'shape SliceBuilderVTable>,
443}
444
445impl<'shape> SmartPointerVTableBuilder<'shape> {
446 /// Creates a new `SmartPointerVTableBuilder` 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,
515 slice_builder_vtable: &'shape SliceBuilderVTable,
516 ) -> Self {
517 self.slice_builder_vtable = Some(slice_builder_vtable);
518 self
519 }
520
521 /// Builds a `SmartPointerVTable` from the provided configuration.
522 #[must_use]
523 pub const fn build(self) -> SmartPointerVTable<'shape> {
524 SmartPointerVTable {
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 smart pointer kinds
538#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
539pub enum KnownSmartPointer {
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}