maikor_vm_file/
atlas_file.rs

1use crate::file_utils::ReaderExt;
2use crate::read_write_impl::{Readable, Writeable};
3use crate::GameFileError;
4use crate::GameFileError::InvalidAtlas;
5use maikor_platform::constants::{ATLAS_TILE_HEIGHT, ATLAS_TILE_WIDTH};
6
7const ATLAS_SPRITE_SIZE: usize = ATLAS_TILE_HEIGHT * ATLAS_TILE_WIDTH;
8
9pub struct AtlasFile {
10    images: Vec<[u8; ATLAS_SPRITE_SIZE]>,
11}
12
13impl AtlasFile {
14    pub fn validate(&self) -> Result<(), Vec<String>> {
15        let mut error = vec![];
16        if self.images.len() > ATLAS_SPRITE_SIZE {
17            error.push(String::from("Atlas has too many images"));
18        }
19        if error.is_empty() {
20            Ok(())
21        } else {
22            Err(error)
23        }
24    }
25}
26
27impl Writeable for AtlasFile {
28    fn as_bytes(&self) -> Result<Vec<u8>, GameFileError> {
29        let mut output = vec![];
30        for image in &self.images {
31            output.extend_from_slice(image);
32        }
33        Ok(output)
34    }
35}
36
37impl Readable for AtlasFile {
38    fn from_reader<R: ReaderExt>(reader: &mut R) -> Result<Self, GameFileError>
39    where
40        Self: Sized,
41    {
42        let mut bytes = vec![];
43        let read_count = reader
44            .read_to_end(&mut bytes)
45            .map_err(|e| InvalidAtlas(e.to_string()))?;
46        if read_count as f64 % ATLAS_SPRITE_SIZE as f64 != 0.0 {
47            return Err(InvalidAtlas(format!(
48                "Content must be multiple of {}",
49                ATLAS_SPRITE_SIZE
50            )));
51        }
52        let mut images = vec![];
53        for chunk in bytes.chunks_exact_mut(ATLAS_SPRITE_SIZE) {
54            let mut image = [0; ATLAS_SPRITE_SIZE];
55            unsafe {
56                std::ptr::copy_nonoverlapping(
57                    chunk.as_mut_ptr(),
58                    image.as_mut_ptr(),
59                    ATLAS_SPRITE_SIZE,
60                );
61            }
62            images.push(image);
63        }
64        Ok(AtlasFile { images })
65    }
66}
67
68#[cfg(test)]
69mod test {
70    use crate::atlas_file::AtlasFile;
71    use crate::read_write_impl::{Readable, Writeable};
72    use std::io::BufReader;
73
74    #[test]
75    fn basic_read_write() {
76        let image = [
77            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
78            24, 25, 26, 27, 28, 29, 30, 31,
79        ];
80        let atlas = AtlasFile {
81            images: vec![image],
82        };
83        let output = atlas.as_bytes().unwrap();
84        assert_eq!(image.to_vec(), output);
85        let parsed_atlas = AtlasFile::from_reader(&mut BufReader::new(&*image.to_vec())).unwrap();
86        assert_eq!(parsed_atlas.images.len(), 1);
87        let mut bytes = image.to_vec();
88        bytes.extend_from_slice(&image);
89        let parsed_atlas = AtlasFile::from_reader(&mut BufReader::new(&*bytes)).unwrap();
90        assert_eq!(parsed_atlas.images.len(), 2);
91        assert_eq!(parsed_atlas.images[1], image);
92    }
93}