bones_schema/
raw_fns.rs

1//! Traits implementing raw function calls for cloning, dropping, and creating default values for
2//! Rust types.
3
4use std::{
5    ffi::c_void,
6    hash::{Hash, Hasher},
7};
8
9use fxhash::FxHasher;
10
11use crate::Unsafe;
12
13#[cfg(doc)]
14use crate::SchemaData;
15
16/// Trait implemented automatically for types that implement [`Clone`] and can be used to clone the
17/// type through raw pointers.
18pub trait RawClone {
19    /// Write the default value of the type to the pointer.
20    ///
21    /// # Safety
22    ///
23    /// The `dst` pointer must be aligned, writable, and have the same layout that this function is
24    /// assocated to, and the `src` pointer must be readable and point to a valid instance of the
25    /// type that this function is associated with.
26    unsafe fn raw_clone(src: *const c_void, dst: *mut c_void);
27
28    /// Get a callback suitable for [`SchemaData`].
29    fn raw_clone_cb(
30    ) -> Unsafe<&'static (dyn Fn(*const c_void, *mut c_void) + Sync + Send + 'static)> {
31        unsafe { Unsafe::new(Box::leak(Box::new(|a, b| Self::raw_clone(a, b)))) }
32    }
33}
34impl<T: Clone> RawClone for T {
35    unsafe fn raw_clone(src: *const c_void, dst: *mut c_void) {
36        let t = &*(src as *const T);
37        let t = t.clone();
38        (dst as *mut T).write(t)
39    }
40}
41
42/// Trait implemented automatically for types that implement [`Drop`] and can be used to drop the
43/// type through a raw pointer.
44pub trait RawDrop {
45    /// Write the default value of the type to the pointer.
46    ///
47    /// # Safety
48    ///
49    /// The pointer must be aligned, writable, and have the same layout that this function is
50    /// assocated to.
51    unsafe fn raw_drop(ptr: *mut c_void);
52
53    /// Get a callback suitable for [`SchemaData`].
54    fn raw_drop_cb() -> Unsafe<&'static (dyn Fn(*mut c_void) + Sync + Send + 'static)> {
55        unsafe { Unsafe::new(Box::leak(Box::new(|a| Self::raw_drop(a)))) }
56    }
57}
58impl<T> RawDrop for T {
59    unsafe fn raw_drop(ptr: *mut c_void) {
60        if std::mem::needs_drop::<T>() {
61            (ptr as *mut T).drop_in_place()
62        }
63    }
64}
65
66/// Trait implemented automatically for types that implement [`Hash`] and can be used compute a
67/// [`u64`] hash for a type using a pointer to it.
68pub trait RawHash {
69    /// Get the hash of the type.
70    ///
71    /// # Safety
72    ///
73    /// The pointer must be aligned, readable, and be a pointer to the type that this Hash function
74    /// was created for.
75    unsafe fn raw_hash(ptr: *const c_void) -> u64;
76
77    /// Get a callback suitable for [`SchemaData`].
78    fn raw_hash_cb() -> Unsafe<&'static (dyn Fn(*const c_void) -> u64 + Sync + Send + 'static)> {
79        unsafe { Unsafe::new(Box::leak(Box::new(|a| Self::raw_hash(a)))) }
80    }
81}
82impl<T: Hash> RawHash for T {
83    unsafe fn raw_hash(ptr: *const c_void) -> u64 {
84        let this = unsafe { &*(ptr as *const Self) };
85        let mut hasher = FxHasher::default();
86        this.hash(&mut hasher);
87        hasher.finish()
88    }
89}
90
91/// Trait implemented automatically for types that implement [`Eq`] that can compare two values
92/// through their pointers.
93pub trait RawEq {
94    // TODO: correctly document this function ( it thinks it is `raw_hash` )
95    /// Get the hash of the type.
96    ///
97    /// # Safety
98    ///
99    /// The pointer must be aligned, readable, and be a pointer to the type that this Hash function
100    /// was created for.
101    unsafe fn raw_eq(a: *const c_void, b: *const c_void) -> bool;
102
103    /// Get a callback suitable for [`SchemaData`].
104    fn raw_eq_cb(
105    ) -> Unsafe<&'static (dyn Fn(*const c_void, *const c_void) -> bool + Sync + Send + 'static)>
106    {
107        unsafe { Unsafe::new(Box::leak(Box::new(|a, b| Self::raw_eq(a, b)))) }
108    }
109}
110impl<T: Eq> RawEq for T {
111    unsafe fn raw_eq(a: *const c_void, b: *const c_void) -> bool {
112        let a = unsafe { &*(a as *const Self) };
113        let b = unsafe { &*(b as *const Self) };
114        a.eq(b)
115    }
116}
117
118/// Trait implemented automatically for types that implement [`Default`] and can be used to write
119/// the default value of the type to a pointer.
120pub trait RawDefault {
121    /// Write the default value of the type to the pointer.
122    ///
123    /// # Safety
124    ///
125    /// The pointer must be aligned, writable, and have the same layout that this function is
126    /// assocated to.
127    unsafe fn raw_default(dst: *mut c_void);
128
129    /// Get a callback suitable for [`SchemaData`].
130    fn raw_default_cb() -> Unsafe<&'static (dyn Fn(*mut c_void) + Sync + Send + 'static)> {
131        unsafe { Unsafe::new(Box::leak(Box::new(|a| Self::raw_default(a)))) }
132    }
133}
134impl<T: Default> RawDefault for T {
135    unsafe fn raw_default(dst: *mut c_void) {
136        let d = T::default();
137        (dst as *mut T).write(d)
138    }
139}