1use core::ops::Range;
6
7use arrayvec::{ArrayString, ArrayVec};
8
9use super::{
10 audio_clip::AudioClipAsset,
11 chunks::{ChunkDescriptor, SpriteChunkDescriptor},
12 sprite::{SpriteAsset, SpriteMipLevel, MAX_MIPS},
13 NamedAsset, ResourceDatabaseHeader, ASSET_NAME_LENGTH,
14};
15
16pub trait Serialize {
19 const SERIALIZED_SIZE: usize;
21 fn serialize(&self, dst: &mut [u8]);
24}
25
26impl Serialize for ChunkDescriptor {
27 const SERIALIZED_SIZE: usize = <Range<u64> as Serialize>::SERIALIZED_SIZE;
28 fn serialize(&self, dst: &mut [u8]) {
29 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
30 let mut cursor = 0;
31 let ChunkDescriptor { source_bytes } = self;
32 serialize::<Range<u64>>(source_bytes, dst, &mut cursor);
33 }
34}
35
36impl Serialize for SpriteChunkDescriptor {
37 const SERIALIZED_SIZE: usize =
38 u16::SERIALIZED_SIZE * 2 + <Range<u64> as Serialize>::SERIALIZED_SIZE;
39 fn serialize(&self, dst: &mut [u8]) {
40 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
41 let mut cursor = 0;
42 let SpriteChunkDescriptor {
43 region_width,
44 region_height,
45 source_bytes,
46 } = self;
47 serialize::<u16>(region_width, dst, &mut cursor);
48 serialize::<u16>(region_height, dst, &mut cursor);
49 serialize::<Range<u64>>(source_bytes, dst, &mut cursor);
50 }
51}
52
53impl Serialize for ResourceDatabaseHeader {
54 const SERIALIZED_SIZE: usize = 18 + u32::SERIALIZED_SIZE * 4;
55 fn serialize(&self, dst: &mut [u8]) {
56 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
57 let mut cursor = 0;
58
59 {
60 use super::*;
61 use platform::*;
62
63 serialize::<u32>(&RESOURCE_DB_MAGIC_NUMBER, dst, &mut cursor);
64 serialize::<u32>(&CHUNK_SIZE, dst, &mut cursor);
65 serialize::<u16>(&SPRITE_CHUNK_DIMENSIONS.0, dst, &mut cursor);
66 serialize::<u16>(&SPRITE_CHUNK_DIMENSIONS.1, dst, &mut cursor);
67 serialize::<u8>(&(SPRITE_CHUNK_FORMAT as u8), dst, &mut cursor);
68 serialize::<u32>(&AUDIO_SAMPLE_RATE, dst, &mut cursor);
69 serialize::<u8>(&(AUDIO_CHANNELS as u8), dst, &mut cursor);
70 }
71
72 let ResourceDatabaseHeader {
73 chunks,
74 sprite_chunks,
75 sprites,
76 audio_clips,
77 } = self;
78 serialize::<u32>(chunks, dst, &mut cursor);
79 serialize::<u32>(sprite_chunks, dst, &mut cursor);
80 serialize::<u32>(sprites, dst, &mut cursor);
81 serialize::<u32>(audio_clips, dst, &mut cursor);
82 }
83}
84
85impl<S: Serialize> Serialize for NamedAsset<S> {
86 const SERIALIZED_SIZE: usize =
87 <ArrayString<ASSET_NAME_LENGTH> as Serialize>::SERIALIZED_SIZE + S::SERIALIZED_SIZE;
88 fn serialize(&self, dst: &mut [u8]) {
89 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
90 let mut cursor = 0;
91 let NamedAsset { name, asset } = self;
92 serialize::<ArrayString<ASSET_NAME_LENGTH>>(name, dst, &mut cursor);
93 serialize::<S>(asset, dst, &mut cursor);
94 }
95}
96
97impl Serialize for AudioClipAsset {
98 const SERIALIZED_SIZE: usize =
99 u32::SERIALIZED_SIZE + <Range<u32> as Serialize>::SERIALIZED_SIZE;
100 fn serialize(&self, dst: &mut [u8]) {
101 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
102 let mut cursor = 0;
103 let AudioClipAsset { samples, chunks } = self;
104 serialize::<u32>(samples, dst, &mut cursor);
105 serialize::<Range<u32>>(chunks, dst, &mut cursor);
106 }
107}
108
109impl Serialize for SpriteAsset {
110 const SERIALIZED_SIZE: usize =
111 bool::SERIALIZED_SIZE + <ArrayVec<SpriteMipLevel, MAX_MIPS> as Serialize>::SERIALIZED_SIZE;
112 fn serialize(&self, dst: &mut [u8]) {
113 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
114 let mut cursor = 0;
115 let SpriteAsset {
116 transparent,
117 mip_chain,
118 } = self;
119 serialize::<bool>(transparent, dst, &mut cursor);
120 serialize::<ArrayVec<SpriteMipLevel, MAX_MIPS>>(mip_chain, dst, &mut cursor);
121 }
122}
123
124impl Serialize for SpriteMipLevel {
125 const SERIALIZED_SIZE: usize = bool::SERIALIZED_SIZE + 12;
128 fn serialize(&self, dst: &mut [u8]) {
129 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
130 let mut cursor = 0;
131 match self {
132 SpriteMipLevel::SingleChunkSprite {
133 offset,
134 size,
135 sprite_chunk,
136 } => {
137 serialize::<bool>(&false, dst, &mut cursor);
138 serialize::<(u16, u16)>(offset, dst, &mut cursor);
139 serialize::<(u16, u16)>(size, dst, &mut cursor);
140 serialize::<u32>(sprite_chunk, dst, &mut cursor);
141 }
142 SpriteMipLevel::MultiChunkSprite {
143 size,
144 sprite_chunks,
145 } => {
146 serialize::<bool>(&true, dst, &mut cursor);
147 serialize::<(u16, u16)>(size, dst, &mut cursor);
148 serialize::<Range<u32>>(sprite_chunks, dst, &mut cursor);
149 }
150 }
151 }
152}
153
154#[inline(always)]
160pub fn serialize<S: Serialize>(value: &S, dst: &mut [u8], cursor: &mut usize) {
161 value.serialize(&mut dst[*cursor..(*cursor + S::SERIALIZED_SIZE)]);
162 *cursor += S::SERIALIZED_SIZE;
163}
164
165impl<const LEN: usize> Serialize for ArrayString<LEN> {
166 const SERIALIZED_SIZE: usize = u8::SERIALIZED_SIZE + LEN;
167 fn serialize(&self, dst: &mut [u8]) {
168 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
169 assert!(
170 LEN < 0xFF,
171 "deserialization impl for ArrayString only supports string lengths up to 255",
172 );
173 (self.len() as u8).serialize(&mut dst[0..1]);
174 dst[1..1 + self.len()].copy_from_slice(self.as_bytes());
175 }
176}
177
178impl<T: Serialize, const LEN: usize> Serialize for ArrayVec<T, LEN> {
179 const SERIALIZED_SIZE: usize = u8::SERIALIZED_SIZE + T::SERIALIZED_SIZE * LEN;
180 fn serialize(&self, dst: &mut [u8]) {
181 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
182 assert!(
183 LEN < 0xFF,
184 "serialization impl for ArrayVec only supports lengths up to 255",
185 );
186 let mut cursor = 0;
187 serialize::<u8>(&(self.len() as u8), dst, &mut cursor);
188 for element in self {
189 serialize::<T>(element, dst, &mut cursor);
190 }
191 }
192}
193
194impl Serialize for Range<u64> {
195 const SERIALIZED_SIZE: usize = u64::SERIALIZED_SIZE * 2;
196 #[inline]
197 fn serialize(&self, dst: &mut [u8]) {
198 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
199 self.start.serialize(&mut dst[0..8]);
200 self.end.serialize(&mut dst[8..16]);
201 }
202}
203
204impl Serialize for Range<u32> {
205 const SERIALIZED_SIZE: usize = u32::SERIALIZED_SIZE * 2;
206 #[inline]
207 fn serialize(&self, dst: &mut [u8]) {
208 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
209 self.start.serialize(&mut dst[0..4]);
210 self.end.serialize(&mut dst[4..8]);
211 }
212}
213
214impl Serialize for (u16, u16) {
215 const SERIALIZED_SIZE: usize = u16::SERIALIZED_SIZE * 2;
216 #[inline]
217 fn serialize(&self, dst: &mut [u8]) {
218 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
219 self.0.serialize(&mut dst[0..2]);
220 self.1.serialize(&mut dst[2..4]);
221 }
222}
223
224impl Serialize for bool {
225 const SERIALIZED_SIZE: usize = 1;
226 #[inline]
227 fn serialize(&self, dst: &mut [u8]) {
228 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
229 let serialized_bool = if *self { 1 } else { 0 };
230 unsafe { *dst.get_unchecked_mut(0) = serialized_bool };
232 }
233}
234
235impl Serialize for u8 {
236 const SERIALIZED_SIZE: usize = 1;
237 #[inline]
238 fn serialize(&self, dst: &mut [u8]) {
239 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
240 unsafe { *dst.get_unchecked_mut(0) = *self };
242 }
243}
244
245impl Serialize for u16 {
246 const SERIALIZED_SIZE: usize = 2;
247 #[inline]
248 fn serialize(&self, dst: &mut [u8]) {
249 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
250 let [a, b] = self.to_le_bytes();
251 unsafe {
253 *dst.get_unchecked_mut(0) = a;
254 *dst.get_unchecked_mut(1) = b;
255 }
256 }
257}
258
259impl Serialize for u32 {
260 const SERIALIZED_SIZE: usize = 4;
261 #[inline]
262 fn serialize(&self, dst: &mut [u8]) {
263 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
264 let [a, b, c, d] = self.to_le_bytes();
265 unsafe {
267 *dst.get_unchecked_mut(0) = a;
268 *dst.get_unchecked_mut(1) = b;
269 *dst.get_unchecked_mut(2) = c;
270 *dst.get_unchecked_mut(3) = d;
271 }
272 }
273}
274
275impl Serialize for u64 {
276 const SERIALIZED_SIZE: usize = 8;
277 #[inline]
278 fn serialize(&self, dst: &mut [u8]) {
279 assert_eq!(Self::SERIALIZED_SIZE, dst.len());
280 let [a, b, c, d, e, f, g, h] = self.to_le_bytes();
281 unsafe {
283 *dst.get_unchecked_mut(0) = a;
284 *dst.get_unchecked_mut(1) = b;
285 *dst.get_unchecked_mut(2) = c;
286 *dst.get_unchecked_mut(3) = d;
287 *dst.get_unchecked_mut(4) = e;
288 *dst.get_unchecked_mut(5) = f;
289 *dst.get_unchecked_mut(6) = g;
290 *dst.get_unchecked_mut(7) = h;
291 }
292 }
293}