engine/resources/
deserialize.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, str};
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 parsed from a constant-size byte
17/// slice.
18pub trait Deserialize {
19    /// The length of the buffer passed into [`Deserialize::deserialize`].
20    const SERIALIZED_SIZE: usize;
21    /// Deserializes the byte buffer into the struct. The length of `src` must
22    /// match the same type's [`Deserialize::SERIALIZED_SIZE`] constant.
23    fn deserialize(src: &[u8]) -> Self;
24}
25
26impl Deserialize for ChunkDescriptor {
27    const SERIALIZED_SIZE: usize = <Range<u64> as Deserialize>::SERIALIZED_SIZE;
28    fn deserialize(src: &[u8]) -> Self {
29        assert_eq!(Self::SERIALIZED_SIZE, src.len());
30        let mut cursor = 0;
31        Self {
32            source_bytes: deserialize::<Range<u64>>(src, &mut cursor),
33        }
34    }
35}
36
37impl Deserialize for SpriteChunkDescriptor {
38    const SERIALIZED_SIZE: usize =
39        u16::SERIALIZED_SIZE * 2 + <Range<u64> as Deserialize>::SERIALIZED_SIZE;
40    fn deserialize(src: &[u8]) -> Self {
41        assert_eq!(Self::SERIALIZED_SIZE, src.len());
42        let mut cursor = 0;
43        Self {
44            region_width: deserialize::<u16>(src, &mut cursor),
45            region_height: deserialize::<u16>(src, &mut cursor),
46            source_bytes: deserialize::<Range<u64>>(src, &mut cursor),
47        }
48    }
49}
50
51impl Deserialize for ResourceDatabaseHeader {
52    const SERIALIZED_SIZE: usize = 18 + u32::SERIALIZED_SIZE * 4;
53    fn deserialize(src: &[u8]) -> Self {
54        assert_eq!(Self::SERIALIZED_SIZE, src.len());
55        let mut cursor = 0;
56
57        {
58            use super::*;
59            use platform::*;
60
61            let magic = deserialize::<u32>(src, &mut cursor);
62            assert_eq!(RESOURCE_DB_MAGIC_NUMBER, magic);
63            let chunk_size = deserialize::<u32>(src, &mut cursor);
64            assert_eq!(CHUNK_SIZE, chunk_size);
65            let sprite_chunk_width = deserialize::<u16>(src, &mut cursor);
66            assert_eq!(SPRITE_CHUNK_DIMENSIONS.0, sprite_chunk_width);
67            let sprite_chunk_height = deserialize::<u16>(src, &mut cursor);
68            assert_eq!(SPRITE_CHUNK_DIMENSIONS.1, sprite_chunk_height);
69            let sprite_chunk_format = deserialize::<u8>(src, &mut cursor);
70            assert_eq!(SPRITE_CHUNK_FORMAT as u8, sprite_chunk_format);
71            let audio_sample_rate = deserialize::<u32>(src, &mut cursor);
72            assert_eq!(AUDIO_SAMPLE_RATE, audio_sample_rate);
73            let audio_channels = deserialize::<u8>(src, &mut cursor);
74            assert_eq!((AUDIO_CHANNELS as u8), audio_channels);
75        }
76
77        Self {
78            chunks: deserialize::<u32>(src, &mut cursor),
79            sprite_chunks: deserialize::<u32>(src, &mut cursor),
80            sprites: deserialize::<u32>(src, &mut cursor),
81            audio_clips: deserialize::<u32>(src, &mut cursor),
82        }
83    }
84}
85
86impl<D: Deserialize> Deserialize for NamedAsset<D> {
87    const SERIALIZED_SIZE: usize =
88        <ArrayString<ASSET_NAME_LENGTH> as Deserialize>::SERIALIZED_SIZE + D::SERIALIZED_SIZE;
89    fn deserialize(src: &[u8]) -> Self {
90        assert_eq!(Self::SERIALIZED_SIZE, src.len());
91        let mut cursor = 0;
92        Self {
93            name: deserialize::<ArrayString<ASSET_NAME_LENGTH>>(src, &mut cursor),
94            asset: deserialize::<D>(src, &mut cursor),
95        }
96    }
97}
98
99impl Deserialize for AudioClipAsset {
100    const SERIALIZED_SIZE: usize =
101        u32::SERIALIZED_SIZE + <Range<u32> as Deserialize>::SERIALIZED_SIZE;
102    fn deserialize(src: &[u8]) -> Self {
103        assert_eq!(Self::SERIALIZED_SIZE, src.len());
104        let mut cursor = 0;
105        Self {
106            samples: deserialize::<u32>(src, &mut cursor),
107            chunks: deserialize::<Range<u32>>(src, &mut cursor),
108        }
109    }
110}
111
112impl Deserialize for SpriteAsset {
113    const SERIALIZED_SIZE: usize = bool::SERIALIZED_SIZE
114        + <ArrayVec<SpriteMipLevel, MAX_MIPS> as Deserialize>::SERIALIZED_SIZE;
115    fn deserialize(src: &[u8]) -> Self {
116        assert_eq!(Self::SERIALIZED_SIZE, src.len());
117        let mut cursor = 0;
118        Self {
119            transparent: deserialize::<bool>(src, &mut cursor),
120            mip_chain: deserialize::<ArrayVec<SpriteMipLevel, MAX_MIPS>>(src, &mut cursor),
121        }
122    }
123}
124
125impl Deserialize for SpriteMipLevel {
126    // Sadly, `usize::max` is not const. One variant has 4x u16 and 1x u32, the
127    // other has 2x u16 and 2x u32, so the max of the two sizes is 12.
128    const SERIALIZED_SIZE: usize = bool::SERIALIZED_SIZE + 12;
129    fn deserialize(src: &[u8]) -> Self {
130        assert_eq!(Self::SERIALIZED_SIZE, src.len());
131        let mut cursor = 0;
132        let multi_chunk = deserialize::<bool>(src, &mut cursor);
133        if multi_chunk {
134            Self::MultiChunkSprite {
135                size: deserialize::<(u16, u16)>(src, &mut cursor),
136                sprite_chunks: deserialize::<Range<u32>>(src, &mut cursor),
137            }
138        } else {
139            Self::SingleChunkSprite {
140                offset: deserialize::<(u16, u16)>(src, &mut cursor),
141                size: deserialize::<(u16, u16)>(src, &mut cursor),
142                sprite_chunk: deserialize::<u32>(src, &mut cursor),
143            }
144        }
145    }
146}
147
148// Serialization helpers, at the bottom because they're very long, just so they
149// compile to something sane in debug builds.
150
151/// Deserializes the data from a byte slice into `D`, reading from the given
152/// cursor, and advancing it by the amount of bytes read.
153#[inline(always)]
154pub fn deserialize<D: Deserialize>(src: &[u8], cursor: &mut usize) -> D {
155    let value = D::deserialize(&src[*cursor..(*cursor + D::SERIALIZED_SIZE)]);
156    *cursor += D::SERIALIZED_SIZE;
157    value
158}
159
160impl<const LEN: usize> Deserialize for ArrayString<LEN> {
161    const SERIALIZED_SIZE: usize = u8::SERIALIZED_SIZE + LEN;
162    fn deserialize(src: &[u8]) -> Self {
163        assert_eq!(Self::SERIALIZED_SIZE, src.len());
164        assert!(
165            LEN < 0xFF,
166            "deserialization impl for ArrayString only supports string lengths up to 255",
167        );
168        let len = src[0] as usize;
169        assert!(len <= LEN, "serialized string cannot fit");
170        ArrayString::from(str::from_utf8(&src[1..1 + len]).unwrap()).unwrap()
171    }
172}
173
174impl<T: Deserialize, const LEN: usize> Deserialize for ArrayVec<T, LEN> {
175    const SERIALIZED_SIZE: usize = u8::SERIALIZED_SIZE + T::SERIALIZED_SIZE * LEN;
176    fn deserialize(src: &[u8]) -> Self {
177        assert_eq!(Self::SERIALIZED_SIZE, src.len());
178        assert!(
179            LEN < 0xFF,
180            "deserialization impl for ArrayVec only supports lengths up to 255",
181        );
182        let mut cursor = 0;
183        let len = deserialize::<u8>(src, &mut cursor) as usize;
184        assert!(len <= LEN, "serialized vec cannot fit");
185        let mut vec = ArrayVec::new();
186        for _ in 0..len {
187            vec.push(deserialize::<T>(src, &mut cursor));
188        }
189        vec
190    }
191}
192
193impl Deserialize for Range<u64> {
194    const SERIALIZED_SIZE: usize = u64::SERIALIZED_SIZE * 2;
195    #[inline]
196    fn deserialize(src: &[u8]) -> Self {
197        assert_eq!(Self::SERIALIZED_SIZE, src.len());
198        let start = u64::deserialize(&src[0..8]);
199        let end = u64::deserialize(&src[8..16]);
200        start..end
201    }
202}
203
204impl Deserialize for Range<u32> {
205    const SERIALIZED_SIZE: usize = u32::SERIALIZED_SIZE * 2;
206    #[inline]
207    fn deserialize(src: &[u8]) -> Self {
208        assert_eq!(Self::SERIALIZED_SIZE, src.len());
209        let start = u32::deserialize(&src[0..4]);
210        let end = u32::deserialize(&src[4..8]);
211        start..end
212    }
213}
214
215impl Deserialize for (u16, u16) {
216    const SERIALIZED_SIZE: usize = u16::SERIALIZED_SIZE * 2;
217    #[inline]
218    fn deserialize(src: &[u8]) -> Self {
219        assert_eq!(Self::SERIALIZED_SIZE, src.len());
220        let u0 = u16::deserialize(&src[0..2]);
221        let u1 = u16::deserialize(&src[2..4]);
222        (u0, u1)
223    }
224}
225
226impl Deserialize for bool {
227    const SERIALIZED_SIZE: usize = 1;
228    #[inline]
229    fn deserialize(src: &[u8]) -> Self {
230        assert_eq!(Self::SERIALIZED_SIZE, src.len());
231        // Safety: the the index is checked by the assert above.
232        unsafe { *src.get_unchecked(0) != 0 }
233    }
234}
235
236impl Deserialize for u8 {
237    const SERIALIZED_SIZE: usize = 1;
238    #[inline]
239    fn deserialize(src: &[u8]) -> Self {
240        assert_eq!(Self::SERIALIZED_SIZE, src.len());
241        // Safety: the the index is checked by the assert above.
242        unsafe { *src.get_unchecked(0) }
243    }
244}
245
246impl Deserialize for u16 {
247    const SERIALIZED_SIZE: usize = 2;
248    #[inline]
249    fn deserialize(src: &[u8]) -> Self {
250        assert_eq!(Self::SERIALIZED_SIZE, src.len());
251        // Safety: all the indexes are covered by the assert above.
252        let bytes = unsafe { [*src.get_unchecked(0), *src.get_unchecked(1)] };
253        u16::from_le_bytes(bytes)
254    }
255}
256
257impl Deserialize for u32 {
258    const SERIALIZED_SIZE: usize = 4;
259    #[inline]
260    fn deserialize(src: &[u8]) -> Self {
261        assert_eq!(Self::SERIALIZED_SIZE, src.len());
262        // Safety: all the indexes are covered by the assert above.
263        let bytes = unsafe {
264            [
265                *src.get_unchecked(0),
266                *src.get_unchecked(1),
267                *src.get_unchecked(2),
268                *src.get_unchecked(3),
269            ]
270        };
271        u32::from_le_bytes(bytes)
272    }
273}
274
275impl Deserialize for u64 {
276    const SERIALIZED_SIZE: usize = 8;
277    #[inline]
278    fn deserialize(src: &[u8]) -> Self {
279        assert_eq!(Self::SERIALIZED_SIZE, src.len());
280        // Safety: all the indexes are covered by the assert above.
281        let bytes = unsafe {
282            [
283                *src.get_unchecked(0),
284                *src.get_unchecked(1),
285                *src.get_unchecked(2),
286                *src.get_unchecked(3),
287                *src.get_unchecked(4),
288                *src.get_unchecked(5),
289                *src.get_unchecked(6),
290                *src.get_unchecked(7),
291            ]
292        };
293        u64::from_le_bytes(bytes)
294    }
295}