forked from simgine/bevy_replicon
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserialized_data.rs
More file actions
166 lines (143 loc) · 4.94 KB
/
Copy pathserialized_data.rs
File metadata and controls
166 lines (143 loc) · 4.94 KB
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
use core::ops::Range;
use bevy::{prelude::*, ptr::Ptr};
use crate::{
postcard_utils,
prelude::*,
shared::replication::registry::{FnsId, ctx::SerializeCtx, serde_fns::SerdeFns},
};
/// Single continuous buffer that stores serialized data for messages.
///
/// Values written into the buffer are referenced by byte ranges instead of being
/// copied into each message. This allows multiple messages to point to the same
/// serialized data.
///
/// See [`Updates`](super::updates::Updates) and
/// [`MutateMessage`](super::mutations::MutateMessage).
#[derive(Resource, Deref, DerefMut, Default)]
pub(crate) struct SerializedData(Vec<u8>);
impl SerializedData {
pub(crate) fn write_cached_mapping(
&mut self,
cached_range: &mut Option<Range<usize>>,
entity: Entity,
hash: u64,
) -> Result<Range<usize>> {
self.write_cached(cached_range, |serialized| {
serialized.write_mapping(entity, hash)
})
}
pub(crate) fn write_cached_component(
&mut self,
ctx: &mut SerializeCtx,
cached_range: &mut Option<Range<usize>>,
component: &mut ErasedComponent,
) -> Result<Range<usize>> {
self.write_cached(cached_range, |serialized| {
serialized.write_component(ctx, component)
})
}
pub(crate) fn write_cached_entity(
&mut self,
cached_range: &mut Option<Range<usize>>,
entity: Entity,
) -> Result<Range<usize>> {
self.write_cached(cached_range, |serialized| serialized.write_entity(entity))
}
pub(crate) fn write_cached_fns_id(
&mut self,
cached_range: &mut Option<Range<usize>>,
fns_id: FnsId,
) -> Result<Range<usize>> {
self.write_cached(cached_range, |serialized| serialized.write_fns_id(fns_id))
}
pub(crate) fn write_cached_tick(
&mut self,
cached_range: &mut Option<Range<usize>>,
tick: RepliconTick,
) -> Result<Range<usize>> {
self.write_cached(cached_range, |serialized| serialized.write_tick(tick))
}
/// Returns a previously written range, or writes the data and caches its range.
///
/// Used when several replication messages need to reference the same
/// serialized value.
fn write_cached(
&mut self,
cached_range: &mut Option<Range<usize>>,
write: impl FnOnce(&mut Self) -> Result<Range<usize>>,
) -> Result<Range<usize>> {
if let Some(range) = cached_range.clone() {
return Ok(range);
}
let range = write(self)?;
*cached_range = Some(range.clone());
Ok(range)
}
pub(crate) fn write_component(
&mut self,
ctx: &mut SerializeCtx,
component: &mut ErasedComponent,
) -> Result<Range<usize>> {
self.write_with(|bytes| {
postcard_utils::to_extend_mut(&component.fns_id, bytes)?;
// SAFETY: `fns` and `ptr` were created for the same component type.
unsafe {
component.fns.serialize(ctx, component.ptr, bytes)?;
}
Ok(())
})
}
fn write_mapping(&mut self, entity: Entity, hash: u64) -> Result<Range<usize>> {
self.write_with(|bytes| {
postcard_utils::entity_to_extend_mut(&entity, bytes)?;
bytes.extend(hash.to_le_bytes()); // Use fixint encoding because it's more efficient for hashes.
Ok(())
})
}
pub(crate) fn write_entity(&mut self, entity: Entity) -> Result<Range<usize>> {
self.write_with(|bytes| {
postcard_utils::entity_to_extend_mut(&entity, bytes)?;
Ok(())
})
}
pub(crate) fn write_fns_id(&mut self, fns_id: FnsId) -> Result<Range<usize>> {
self.write_with(|bytes| {
postcard_utils::to_extend_mut(&fns_id, bytes)?;
Ok(())
})
}
fn write_tick(&mut self, tick: RepliconTick) -> Result<Range<usize>> {
self.write_with(|bytes| {
postcard_utils::to_extend_mut(&tick, bytes)?;
Ok(())
})
}
/// Writes data for replication messages and returns a range that points to it.
fn write_with(
&mut self,
write: impl FnOnce(&mut Vec<u8>) -> Result<()>,
) -> Result<Range<usize>> {
let start = self.len();
write(&mut self.0)?;
let end = self.len();
Ok(start..end)
}
}
/// Wraps a component pointer and its associated functions.
///
/// Allows moving the unsafe precondition to construction.
pub(crate) struct ErasedComponent<'a> {
fns: SerdeFns<'a>,
ptr: Ptr<'a>,
fns_id: FnsId,
}
impl<'a> ErasedComponent<'a> {
/// Creates a new instance for component data that can be written into a replication message.
///
/// # Safety
///
/// The caller must ensure that `fns` and `ptr` was created for the same type.
pub(crate) unsafe fn new(fns: SerdeFns<'a>, ptr: Ptr<'a>, fns_id: FnsId) -> Self {
Self { fns, ptr, fns_id }
}
}