engine/resources/
serialize.rs

1// SPDX-FileCopyrightText: 2024 Jens Pitkänen <jens.pitkanen@helsinki.fi>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5use 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
16/// Trait for describing how a type can be serialized into a constant-size byte
17/// slice.
18pub trait Serialize {
19    /// The length of the buffer passed into [`Serialize::serialize`].
20    const SERIALIZED_SIZE: usize;
21    /// Serializes the struct into the byte buffer. The length of `dst` must
22    /// match the same type's [`Serialize::SERIALIZED_SIZE`] constant.
23    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    // Sadly, `usize::max` is not const. One variant has 4x u16 and 1x u32, the
126    // other has 2x u16 and 2x u32, so the max of the two sizes is 12.
127    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// Serialization helpers, at the bottom because they're very long, just so they
155// compile to something sane in debug builds.
156
157/// Serializes the data into a byte slice, with the write starting from the
158/// cursor, and advances the cursor by the amount of bytes written.
159#[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        // Safety: all the indexes are covered by the assert above.
231        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        // Safety: all the indexes are covered by the assert above.
241        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        // Safety: all the indexes are covered by the assert above.
252        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        // Safety: all the indexes are covered by the assert above.
266        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        // Safety: all the indexes are covered by the assert above.
282        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}