Skip to main content

facet_core/impls/core/
nonnull.rs

1use core::ptr::NonNull;
2
3use crate::{
4    Def, Facet, HashProxy, KnownPointer, OxPtrConst, PointerDef, PointerFlags, PointerVTable,
5    PtrConst, PtrMut, PtrUninit, Shape, ShapeBuilder, Type, TypeParam, UserType, VTableIndirect,
6};
7
8// Debug for NonNull<T> - just prints the pointer value
9unsafe fn nonnull_debug(
10    ox: OxPtrConst,
11    f: &mut core::fmt::Formatter<'_>,
12) -> Option<core::fmt::Result> {
13    let ptr = ox.ptr();
14    // Read the NonNull<T> which is just a pointer
15    let inner_ptr = unsafe { *(ptr.as_byte_ptr() as *const *const u8) };
16    Some(write!(f, "{inner_ptr:p}"))
17}
18
19// Hash for NonNull<T> - hash the pointer value
20unsafe fn nonnull_hash(ox: OxPtrConst, hasher: &mut HashProxy<'_>) -> Option<()> {
21    use core::hash::Hasher;
22    let ptr = ox.ptr();
23    let inner_ptr = unsafe { *(ptr.as_byte_ptr() as *const *const u8) };
24    hasher.write_usize(inner_ptr as usize);
25    Some(())
26}
27
28// PartialEq for NonNull<T> - compare pointer values
29unsafe fn nonnull_partial_eq(a: OxPtrConst, b: OxPtrConst) -> Option<bool> {
30    let a_ptr = a.ptr();
31    let b_ptr = b.ptr();
32    let a_inner = unsafe { *(a_ptr.as_byte_ptr() as *const *const u8) };
33    let b_inner = unsafe { *(b_ptr.as_byte_ptr() as *const *const u8) };
34    Some(a_inner == b_inner)
35}
36
37// PartialOrd for NonNull<T> - compare pointer values
38unsafe fn nonnull_partial_cmp(a: OxPtrConst, b: OxPtrConst) -> Option<Option<core::cmp::Ordering>> {
39    let a_ptr = a.ptr();
40    let b_ptr = b.ptr();
41    let a_inner = unsafe { *(a_ptr.as_byte_ptr() as *const *const u8) };
42    let b_inner = unsafe { *(b_ptr.as_byte_ptr() as *const *const u8) };
43    Some(a_inner.partial_cmp(&b_inner))
44}
45
46// Ord for NonNull<T> - compare pointer values
47unsafe fn nonnull_cmp(a: OxPtrConst, b: OxPtrConst) -> Option<core::cmp::Ordering> {
48    let a_ptr = a.ptr();
49    let b_ptr = b.ptr();
50    let a_inner = unsafe { *(a_ptr.as_byte_ptr() as *const *const u8) };
51    let b_inner = unsafe { *(b_ptr.as_byte_ptr() as *const *const u8) };
52    Some(a_inner.cmp(&b_inner))
53}
54
55// Shared vtable for all NonNull<T>
56const NONNULL_VTABLE: VTableIndirect = VTableIndirect {
57    display: None,
58    debug: Some(nonnull_debug),
59    hash: Some(nonnull_hash),
60    invariants: None,
61    parse: None,
62    parse_bytes: None,
63    try_from: None,
64    try_into_inner: None,
65    try_borrow_inner: None,
66    partial_eq: Some(nonnull_partial_eq),
67    partial_cmp: Some(nonnull_partial_cmp),
68    cmp: Some(nonnull_cmp),
69};
70
71// Named function for borrow_fn
72unsafe fn borrow_fn<'a, T: Facet<'a>>(this: PtrConst) -> PtrConst {
73    unsafe {
74        let ptr = this.get::<NonNull<T>>();
75        PtrConst::new(ptr.as_ptr())
76    }
77}
78
79// Named function for new_into_fn
80unsafe fn new_into_fn<'a, 'ptr, T: Facet<'a>>(this: PtrUninit, ptr: PtrMut) -> PtrMut {
81    unsafe {
82        let raw_ptr = ptr.read::<*mut T>();
83        let non_null = core::ptr::NonNull::new_unchecked(raw_ptr);
84        this.put(non_null)
85    }
86}
87
88unsafe impl<'a, T: Facet<'a>> Facet<'a> for core::ptr::NonNull<T> {
89    const SHAPE: &'static Shape = &const {
90        ShapeBuilder::for_sized::<Self>("NonNull")
91            .module_path("core::ptr")
92            .ty(Type::User(UserType::Opaque))
93            .def(Def::Pointer(PointerDef {
94                vtable: &const {
95                    PointerVTable {
96                        borrow_fn: Some(borrow_fn::<T>),
97                        new_into_fn: Some(new_into_fn::<T>),
98                        ..PointerVTable::new()
99                    }
100                },
101                pointee: Some(T::SHAPE),
102                weak: None,
103                strong: None,
104                flags: PointerFlags::EMPTY,
105                known: Some(KnownPointer::NonNull),
106            }))
107            .type_params(&[TypeParam {
108                name: "T",
109                shape: T::SHAPE,
110            }])
111            .vtable_indirect(&NONNULL_VTABLE)
112            .eq()
113            .copy()
114            .build()
115    };
116}