sprite_sheet_file_type/
mapping.rs

1//! SpriteSheet Meta Data
2//! A structure representing the mappings between Sprite names and their Rect areas within an image.
3
4use serde::{Deserialize, Serialize};
5use serde_json;
6
7use std::collections::HashMap;
8
9use std::fs::File;
10use std::io::{BufReader, BufWriter, Cursor, Error, ErrorKind, Read, Result, Write};
11use std::path::Path;
12
13/// MetaData Format Version
14const MAPPING_VERSION_NUMBER: u8 = 0;
15
16/// Rectangle Area of Sprite
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct Rect {
19    pub x: u32,
20    pub y: u32,
21    pub w: u32,
22    pub h: u32,
23}
24
25/// MetaData of SpriteSheet File Type
26#[derive(Serialize, Deserialize, Clone)]
27pub struct SpriteSheetMetaData {
28    pub mapping: HashMap<String, Rect>,
29}
30impl SpriteSheetMetaData {
31    /// SpriteSheet Meta -> JSON File
32    pub fn save_json<P: AsRef<Path>>(&self, path: P) -> Result<()> {
33        let file = File::create(path)?;
34        let writer = BufWriter::new(file);
35        serde_json::to_writer(writer, self)?;
36
37        Ok(())
38    }
39
40    /// JSON File -> SpriteSheet Meta
41    pub fn load_json<P: AsRef<Path>>(path: P) -> Result<Self> {
42        let file = File::open(path)?;
43        let reader = BufReader::new(file);
44        Ok(serde_json::from_reader(reader)?)
45    }
46
47    /// SpriteSheet Meta -> File
48    pub fn save_raw<P: AsRef<Path>>(&self, path: P) -> Result<()> {
49        let file = File::create(path)?;
50        let mut writer = BufWriter::new(file);
51        self.to_writer(&mut writer)?;
52        writer.flush()?;
53        Ok(())
54    }
55
56    /// File -> SpriteSheet Meta
57    pub fn load_raw<P: AsRef<Path>>(path: P) -> Result<Self> {
58        let file = File::open(path)?;
59        let mut reader = BufReader::new(file);
60        Self::from_reader(&mut reader)
61    }
62
63    /// SpriteSheet Meta -> Bytes
64    pub fn to_bytes(&self) -> Vec<u8> {
65        let mut bytes = Vec::new();
66        self.to_writer(&mut bytes).unwrap();
67        bytes
68    }
69
70    /// Bytes -> SpriteSheet Meta
71    pub fn from_bytes(bytes: Vec<u8>) -> Result<Self> {
72        let mut reader = BufReader::new(Cursor::new(bytes));
73        Self::from_reader(&mut reader)
74    }
75
76    /// SpriteSheet Meta -> Writer
77    pub fn to_writer<W: Write>(&self, writer: &mut W) -> Result<()> {
78        /* Writing Header Data */
79        writer.write(&[MAPPING_VERSION_NUMBER])?;
80        writer.write(&(self.mapping.len() as u32).to_le_bytes())?;
81
82        /* Writing Mapping Data */
83        for (key, value) in self.mapping.iter() {
84            // Writing String Data
85            writer.write(&(key.bytes().len() as u32).to_le_bytes())?;
86            writer.write(key.as_bytes())?;
87
88            // Writing Rect Data
89            let mut rect_values = Vec::with_capacity(16);
90            rect_values.extend(value.x.to_le_bytes());
91            rect_values.extend(value.y.to_le_bytes());
92            rect_values.extend(value.w.to_le_bytes());
93            rect_values.extend(value.h.to_le_bytes());
94            writer.write(&rect_values)?;
95        }
96        writer.flush()?;
97
98        Ok(())
99    }
100
101    /// Reader -> SpriteSheet Meta
102    pub fn from_reader<R: Read>(reader: &mut R) -> Result<Self> {
103        /* Reading Header Data */
104        let mut buf = [0u8; 1];
105        reader.read_exact(&mut buf)?;
106        let version_number = u8::from_le_bytes(buf);
107
108        if version_number != MAPPING_VERSION_NUMBER {
109            return Err(Error::new(
110                ErrorKind::InvalidData,
111                "Unsupported file version",
112            ));
113        }
114
115        let mut buf = [0u8; 4];
116        reader.read_exact(&mut buf)?;
117        let entry_count = u32::from_le_bytes(buf);
118
119        /* Reading Mapping Data */
120        let mut mapping = HashMap::new();
121        for _ in 0..entry_count {
122            // Reading String Length
123            let mut buf = [0u8; 4];
124            reader.read_exact(&mut buf)?;
125            let string_length = u32::from_le_bytes(buf);
126
127            // Reading The String
128            let mut key_buf = vec![0u8; string_length as usize];
129            reader.read_exact(&mut key_buf)?;
130            let key = String::from_utf8(key_buf)
131                .map_err(|_| Error::new(ErrorKind::InvalidData, "Invalid UTF-8 string"))?;
132
133            // Reading Rect Data
134            let mut rect_buf = [0u8; 16]; // 4 bytes for each of x, y, w, h
135            reader.read_exact(&mut rect_buf)?;
136            let rect = Rect {
137                x: u32::from_le_bytes(rect_buf[0..4].try_into().unwrap()),
138                y: u32::from_le_bytes(rect_buf[4..8].try_into().unwrap()),
139                w: u32::from_le_bytes(rect_buf[8..12].try_into().unwrap()),
140                h: u32::from_le_bytes(rect_buf[12..16].try_into().unwrap()),
141            };
142
143            // Inserting
144            mapping.insert(key, rect);
145        }
146
147        Ok(Self { mapping })
148    }
149
150    pub fn empty() -> Self {
151        Self { mapping: HashMap::new() }
152    }
153
154    pub fn len(&self) -> usize {
155        self.mapping.len()
156    }
157}