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    /// Get the hash of the type.
95    ///
96    /// # Safety
97    ///
98    /// The pointer must be aligned, readable, and be a pointer to the type that this Hash function
99    /// was created for.
100    unsafe fn raw_eq(a: *const c_void, b: *const c_void) -> bool;
101
102    /// Get a callback suitable for [`SchemaData`].
103    fn raw_eq_cb(
104    ) -> Unsafe<&'static (dyn Fn(*const c_void, *const c_void) -> bool + Sync + Send + 'static)>
105    {
106        unsafe { Unsafe::new(Box::leak(Box::new(|a, b| Self::raw_eq(a, b)))) }
107    }
108}
109impl<T: Eq> RawEq for T {
110    unsafe fn raw_eq(a: *const c_void, b: *const c_void) -> bool {
111        let a = unsafe { &*(a as *const Self) };
112        let b = unsafe { &*(b as *const Self) };
113        a.eq(b)
114    }
115}
116
117/// Trait implemented automatically for types that implement [`Default`] and can be used to write
118/// the default value of the type to a pointer.
119pub trait RawDefault {
120    /// Write the default value of the type to the pointer.
121    ///
122    /// # Safety
123    ///
124    /// The pointer must be aligned, writable, and have the same layout that this function is
125    /// assocated to.
126    unsafe fn raw_default(dst: *mut c_void);
127
128    /// Get a callback suitable for [`SchemaData`].
129    fn raw_default_cb() -> Unsafe<&'static (dyn Fn(*mut c_void) + Sync + Send + 'static)> {
130        unsafe { Unsafe::new(Box::leak(Box::new(|a| Self::raw_default(a)))) }
131    }
132}
133impl<T: Default> RawDefault for T {
134    unsafe fn raw_default(dst: *mut c_void) {
135        let d = T::default();
136        (dst as *mut T).write(d)
137    }
138}