1use std::marker::PhantomData;
4
5use hecs::{Component, EntityBuilder, EntityRef};
6use nbt::CompoundTag;
7
8
9pub trait EntityCodec: Send + Sync {
18
19 fn encode(&self, src: &EntityRef, dst: &mut CompoundTag) -> Result<(), String>;
22
23 fn decode(&self, src: &CompoundTag, dst: &mut EntityBuilder) -> Result<(), String>;
25
26 fn default(&self, dst: &mut EntityBuilder);
28
29}
30
31
32pub trait SingleEntityCodec {
39
40 type Comp: Default + Component;
42
43 fn encode(&self, src: &Self::Comp, dst: &mut CompoundTag);
44 fn decode(&self, src: &CompoundTag) -> Self::Comp;
45
46}
47
48impl<C, D> EntityCodec for C
49where
50 C: Send + Sync,
51 C: SingleEntityCodec<Comp=D>,
52 D: Default + Component
53{
54
55 fn encode(&self, src: &EntityRef, dst: &mut CompoundTag) -> Result<(), String> {
56 if let Some(comp) = src.get::<D>() {
57 <Self as SingleEntityCodec>::encode(self, &*comp, dst);
58 }
59 Ok(())
60 }
61
62 fn decode(&self, src: &CompoundTag, dst: &mut EntityBuilder) -> Result<(), String> {
63 dst.add(<Self as SingleEntityCodec>::decode(self, src));
64 Ok(())
65 }
66
67 fn default(&self, dst: &mut EntityBuilder) {
68 dst.add(D::default());
69 }
70
71}
72
73
74pub struct DefaultEntityCodec<T>(PhantomData<*const T>);
79unsafe impl<T> Send for DefaultEntityCodec<T> {}
80unsafe impl<T> Sync for DefaultEntityCodec<T> {}
81
82impl<T> DefaultEntityCodec<T> {
83 pub const fn new() -> Self {
84 Self(PhantomData)
85 }
86}
87
88#[allow(unused_variables)]
89impl<T> EntityCodec for DefaultEntityCodec<T>
90where
91 T: Default + Component
92{
93
94 fn encode(&self, src: &EntityRef, dst: &mut CompoundTag) -> Result<(), String> {
95 Ok(())
96 }
97
98 fn decode(&self, src: &CompoundTag, dst: &mut EntityBuilder) -> Result<(), String> {
99 Ok(())
100 }
101
102 fn default(&self, dst: &mut EntityBuilder) {
103 dst.add(<T as Default>::default());
104 }
105
106}
107
108
109pub struct NullEntityCodec;
111
112#[allow(unused_variables)]
113impl EntityCodec for NullEntityCodec {
114
115 fn encode(&self, src: &EntityRef, dst: &mut CompoundTag) -> Result<(), String> {
116 Ok(())
117 }
118
119 fn decode(&self, src: &CompoundTag, dst: &mut EntityBuilder) -> Result<(), String> {
120 Ok(())
121 }
122
123 fn default(&self, dst: &mut EntityBuilder) { }
124
125}