mbarc_map/
data_reference_generic.rs

1use std::{any::TypeId, marker::PhantomData, ptr::NonNull};
2
3use crate::{data_holder::DataHolder, DataReference};
4
5/// A Genericized version of [DataReference]\<T\>
6///
7/// This type can be safely passed around without knowing the inner `T` of a [DataReference].  [DataReferenceGeneric] will track ref count just as [DataReference], however the inner data `T` cannot be accessed without first converting back into [DataReference]\<T\>.
8///
9/// Implements [From<DataReference<`T`>>]
10pub struct DataReferenceGeneric {
11	ptr: NonNull<u8>,
12	type_id: TypeId,
13	inner_type_id: TypeId,
14	drop_fn: &'static dyn Fn(NonNull<u8>),
15}
16
17impl DataReferenceGeneric {
18	/// The [TypeId] of the associated [DataReference]\<T\>, literally `TypeId::of::<DataReference<T>>()`
19	pub fn type_id(&self) -> TypeId {
20		self.type_id
21	}
22	/// The [TypeId] of the inner type T of the associated [DataReference]\<T\>.  If this [DataReferenceGeneric] is associated with [DataReference]\<T\>, this would be the result of `TypeId::of::<T>()`
23	pub fn inner_type_id(&self) -> TypeId {
24		self.inner_type_id
25	}
26
27	/// For a given type T, create a [DataReference]\<T\> if and only if T matches the type that was used to create this [DataReferenceGeneric], otherwise None
28	///
29	/// This increments the ref count if Some is returned
30	pub fn to_typed<T: 'static>(&self) -> Option<DataReference<T>> {
31		if TypeId::of::<DataReference<T>>() == self.type_id {
32			let tmp = DataReference::<T> {
33				ptr: self.ptr.cast::<DataHolder<T>>(),
34				phantom: PhantomData,
35			};
36
37			tmp.increment_refcount();
38
39			Some(tmp)
40		} else {
41			None
42		}
43	}
44}
45
46unsafe impl Send for DataReferenceGeneric {}
47unsafe impl Sync for DataReferenceGeneric {}
48
49impl<T: 'static> From<DataReference<T>> for DataReferenceGeneric {
50	fn from(source: DataReference<T>) -> Self {
51		source.increment_refcount();
52
53		Self {
54			ptr: source.ptr.cast::<u8>(),
55			type_id: TypeId::of::<DataReference<T>>(),
56			inner_type_id: TypeId::of::<T>(),
57			drop_fn: &DataReference::<T>::drop_impl,
58		}
59	}
60}
61
62impl Drop for DataReferenceGeneric {
63	fn drop(&mut self) {
64		(self.drop_fn)(self.ptr.cast::<u8>());
65	}
66}