1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use crate::private::ArchetypeMetadata;
use std::any::{Any, TypeId};
use std::mem::MaybeUninit;
use std::{mem, ptr};
pub trait ArchetypeState: Send + Sync + 'static {
fn ty(&self) -> TypeId;
fn as_ptr(&self) -> *const u8;
fn forget(self);
fn metadata(&self) -> fn() -> ArchetypeMetadata;
}
pub trait StaticArchetype: ArchetypeState {
const N_COMPONENTS: usize;
fn into_any(self) -> AnyState
where
Self: Sized + 'static,
{
let ty = self.type_id();
let size = mem::size_of::<Self>();
let metadata = self.metadata();
let mut data = Vec::<u8>::with_capacity(size);
unsafe {
ptr::write(data.as_mut_ptr() as *mut Self, self);
data.set_len(size);
}
AnyState { ty, data, metadata }
}
}
pub struct AnyState {
pub(crate) ty: TypeId,
pub(crate) data: Vec<u8>,
pub(crate) metadata: fn() -> ArchetypeMetadata,
}
impl AnyState {
pub fn into_static<S: StaticArchetype>(mut self) -> Option<S> {
if TypeId::of::<S>() != self.ty {
return None;
}
let mut result = MaybeUninit::<S>::uninit();
unsafe {
let src_ptr = self.data.as_ptr() as *const S;
src_ptr.copy_to_nonoverlapping(result.as_mut_ptr(), mem::size_of::<S>());
(&mut self.data as *mut Vec<_>).drop_in_place();
mem::forget(self);
Some(result.assume_init())
}
}
}
impl ArchetypeState for AnyState {
fn ty(&self) -> TypeId {
self.ty
}
fn as_ptr(&self) -> *const u8 {
self.data.as_ptr()
}
fn forget(mut self) {
unsafe { (&mut self.data as *mut Vec<_>).drop_in_place() };
mem::forget(self);
}
fn metadata(&self) -> fn() -> ArchetypeMetadata {
self.metadata
}
}
impl<T: StaticArchetype> From<T> for AnyState {
fn from(state: T) -> Self {
state.into_any()
}
}
impl Clone for AnyState {
fn clone(&self) -> Self {
let data = (self.metadata()().clone_func)(self.data.as_ptr());
Self {
ty: self.ty,
data,
metadata: self.metadata,
}
}
}
impl Drop for AnyState {
fn drop(&mut self) {
(self.metadata()().drop_func)(self.data.as_mut_ptr());
}
}