emote_psb\types/
mod.rs

1/*
2 * Created on Fri Dec 25 2020
3 *
4 * Copyright (c) storycraft. Licensed under the MIT Licence.
5 */
6
7pub mod collection;
8pub mod number;
9pub mod reference;
10pub mod binary_tree;
11pub mod string;
12
13use std::io::{Read, Seek, Write};
14
15use collection::{PsbUintArray, PsbList, PsbObject};
16use number::PsbNumber;
17use reference::PsbExtraRef;
18
19use crate::{PsbError, PsbErrorKind, PsbRefs};
20use byteorder::{ReadBytesExt, WriteBytesExt};
21
22use self::{reference::PsbResourceRef, string::PsbString};
23
24#[cfg(feature = "serde")]
25use serde::{Serialize, Deserialize};
26
27pub const PSB_TYPE_NONE: u8 = 0x00;
28
29pub const PSB_TYPE_NULL: u8 = 0x01;
30
31pub const PSB_TYPE_FALSE: u8 = 0x02;
32pub const PSB_TYPE_TRUE: u8 = 0x03;
33
34/// 0 <= N <= 8
35pub const PSB_TYPE_INTEGER_N: u8 = 0x04;
36pub const PSB_TYPE_FLOAT0: u8 = 0x1d;
37pub const PSB_TYPE_FLOAT: u8 = 0x1e;
38pub const PSB_TYPE_DOUBLE: u8 = 0x1f;
39
40/// 1 <= N <= 8
41pub const PSB_TYPE_INTEGER_ARRAY_N: u8 = 0x0C;
42
43/// 1 <= N <= 4
44pub const PSB_TYPE_STRING_N: u8 = 0x14;
45
46/// 1 <= N <= 4
47pub const PSB_TYPE_RESOURCE_N: u8 = 0x18;
48
49pub const PSB_TYPE_LIST: u8 = 0x20;
50pub const PSB_TYPE_OBJECT: u8 = 0x21;
51
52/// 1 <= N <= 8
53pub const PSB_TYPE_EXTRA_N: u8 = 0x21;
54
55pub const PSB_COMPILER_INTEGER: u8 = 0x80;
56pub const PSB_COMPILER_STRING: u8 = 0x81;
57pub const PSB_COMPILER_RESOURCE: u8 = 0x82;
58pub const PSB_COMPILER_DECIMAL: u8 = 0x83;
59pub const PSB_COMPILER_ARRAY: u8 = 0x84;
60pub const PSB_COMPILER_BOOL: u8 = 0x85;
61pub const PSB_COMPILER_BINARY_TREE: u8 = 0x86;
62
63#[derive(Debug, PartialEq)]
64#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
65#[cfg_attr(feature = "serde", serde(untagged))]
66pub enum PsbValue {
67
68    None, Null,
69    Bool(bool),
70    Number(PsbNumber),
71    IntArray(PsbUintArray),
72
73    String(PsbString),
74
75    List(PsbList),
76    Object(PsbObject),
77
78    Resource(PsbResourceRef),
79    ExtraResource(PsbExtraRef),
80
81    CompilerNumber,
82    CompilerString,
83    CompilerResource,
84    CompilerDecimal,
85    CompilerArray,
86    CompilerBool,
87    CompilerBinaryTree
88
89}
90
91impl PsbValue {
92
93    fn from_bytes_type<T: Read + Seek>(value_type: u8, stream: &mut T) -> Result<(u64, PsbValue), PsbError> {
94        match value_type {
95            PSB_TYPE_NONE => Ok((1, PsbValue::None)),
96            PSB_TYPE_NULL => Ok((1, PsbValue::Null)),
97
98            PSB_TYPE_FALSE => Ok((1, PsbValue::Bool(false))),
99            PSB_TYPE_TRUE => Ok((1, PsbValue::Bool(true))),
100            
101            PSB_TYPE_DOUBLE => {
102                let (read, val) = PsbNumber::from_bytes(value_type, stream)?;
103                Ok((read + 1, PsbValue::Number(val)))
104            },
105
106            PSB_TYPE_FLOAT0 => {
107                let (read, val) = PsbNumber::from_bytes(value_type, stream)?;
108                Ok((read + 1, PsbValue::Number(val)))
109            },
110
111            PSB_TYPE_FLOAT => {
112                let (read, val) = PsbNumber::from_bytes(value_type, stream)?;
113                Ok((read + 1, PsbValue::Number(val)))
114            },
115
116            _ if value_type >= PSB_TYPE_INTEGER_N && value_type <= PSB_TYPE_INTEGER_N + 8 => {
117                let (read, number) = PsbNumber::from_bytes(value_type, stream)?;
118                Ok((read + 1, PsbValue::Number(number)))
119            },
120
121            _ if value_type > PSB_TYPE_INTEGER_ARRAY_N && value_type <= PSB_TYPE_INTEGER_ARRAY_N + 8 => {
122                let (read, array) = PsbUintArray::from_bytes(value_type - PSB_TYPE_INTEGER_ARRAY_N, stream)?;
123                Ok((read + 1, PsbValue::IntArray(array)))
124            },
125
126            _ if value_type > PSB_TYPE_RESOURCE_N && value_type <= PSB_TYPE_RESOURCE_N + 4 => {
127                let (read, map) = PsbResourceRef::from_bytes(value_type - PSB_TYPE_RESOURCE_N, stream)?;
128
129                Ok((read + 1, PsbValue::Resource(map)))
130            },
131
132            _ if value_type > PSB_TYPE_EXTRA_N && value_type <= PSB_TYPE_EXTRA_N + 4 => {
133                let (read, map) = PsbExtraRef::from_bytes(value_type - PSB_TYPE_EXTRA_N, stream)?;
134
135                Ok((read + 1, PsbValue::ExtraResource(map)))
136            },
137
138            PSB_COMPILER_INTEGER => Ok((1, PsbValue::CompilerNumber)),
139            PSB_COMPILER_STRING => Ok((1, PsbValue::CompilerString)),
140            PSB_COMPILER_RESOURCE => Ok((1, PsbValue::CompilerResource)),
141            PSB_COMPILER_ARRAY => Ok((1, PsbValue::CompilerArray)),
142            PSB_COMPILER_BOOL => Ok((1, PsbValue::CompilerBool)),
143            PSB_COMPILER_BINARY_TREE => Ok((1, PsbValue::CompilerBinaryTree)),
144
145            _ => {
146                Err(PsbError::new(PsbErrorKind::InvalidPSBValue, None))
147            }
148        }
149    }
150
151    pub fn from_bytes<T: Read + Seek>(stream: &mut T) -> Result<(u64, PsbValue), PsbError> {
152        Self::from_bytes_type(stream.read_u8()?, stream)
153    }
154
155    pub fn from_bytes_refs<T: Read + Seek>(stream: &mut T, table: &PsbRefs) -> Result<(u64, PsbValue), PsbError> {
156        let value_type = stream.read_u8()?;
157
158        match value_type {
159
160            PSB_TYPE_LIST => {
161                let (read, list) = PsbList::from_bytes(stream, table)?;
162
163                Ok((read + 1, PsbValue::List(list)))
164            },
165
166            PSB_TYPE_OBJECT => {
167                let (read, map) = PsbObject::from_bytes(stream, table)?;
168
169                Ok((read + 1, PsbValue::Object(map)))
170            },
171
172            _ if value_type > PSB_TYPE_STRING_N && value_type <= PSB_TYPE_STRING_N + 4 => {
173                let (read, string) = PsbString::from_bytes(value_type - PSB_TYPE_STRING_N, stream, table)?;
174
175                Ok((read + 1, PsbValue::String(string)))
176            },
177
178            _ => {
179                Self::from_bytes_type(value_type, stream)
180            }
181
182        }
183    }
184
185    pub fn write_bytes(&self, stream: &mut impl Write) -> Result<u64, PsbError> {
186        match self {
187            PsbValue::None => {
188                stream.write_u8(PSB_TYPE_NONE)?;
189                Ok(1)
190            },
191            PsbValue::Null => {
192                stream.write_u8(PSB_TYPE_NULL)?;
193                Ok(1)
194            },
195            PsbValue::Bool(value) => {
196                if *value {
197                    stream.write_u8(PSB_TYPE_TRUE)?;
198                } else {
199                    stream.write_u8(PSB_TYPE_FALSE)?;
200                }
201
202                Ok(1)
203            },
204            PsbValue::Number(number) => {
205                match number {
206                    PsbNumber::Integer(integer) => {
207                        let n = if *integer == 0 {
208                            0
209                        } else {
210                            PsbNumber::get_n(*integer)
211                        };
212
213                        stream.write_u8(PSB_TYPE_INTEGER_N + n)?;
214                    },
215
216                    PsbNumber::Double(_) => {
217                        stream.write_u8(PSB_TYPE_DOUBLE)?;
218                    },
219
220                    PsbNumber::Float(float) => {
221                        if *float == 0_f32 {
222                            stream.write_u8(PSB_TYPE_FLOAT0)?;
223                        } else {
224                            stream.write_u8(PSB_TYPE_FLOAT)?;
225                        }
226                    }
227                }
228
229                Ok(1 + number.write_bytes(stream)?)
230            },
231
232            PsbValue::IntArray(array) => {
233                stream.write_u8(PSB_TYPE_INTEGER_ARRAY_N + array.get_n())?;
234
235                Ok(1 + array.write_bytes(stream)?)
236            },
237
238            PsbValue::Resource(res) => {
239                stream.write_u8(PSB_TYPE_RESOURCE_N + res.get_n())?;
240
241                Ok(1 + res.write_bytes(stream)?)
242            },
243            PsbValue::ExtraResource(res) => {
244                stream.write_u8(PSB_TYPE_EXTRA_N + res.get_n())?;
245
246                Ok(1 + res.write_bytes(stream)?)
247            },
248
249            PsbValue::CompilerNumber => {
250                stream.write_u8(PSB_COMPILER_INTEGER)?;
251                Ok(1)
252            },
253            PsbValue::CompilerString => {
254                stream.write_u8(PSB_COMPILER_STRING)?;
255                Ok(1)
256            },
257            PsbValue::CompilerResource => {
258                stream.write_u8(PSB_COMPILER_RESOURCE)?;
259                Ok(1)
260            },
261            PsbValue::CompilerDecimal => {
262                stream.write_u8(PSB_COMPILER_DECIMAL)?;
263                Ok(1)
264            },
265            PsbValue::CompilerArray => {
266                stream.write_u8(PSB_COMPILER_ARRAY)?;
267                Ok(1)
268            },
269            PsbValue::CompilerBool => {
270                stream.write_u8(PSB_COMPILER_BOOL)?;
271                Ok(1)
272            },
273            PsbValue::CompilerBinaryTree => {
274                stream.write_u8(PSB_COMPILER_BINARY_TREE)?;
275                Ok(1)
276            },
277
278            _ => {
279                Err(PsbError::new(PsbErrorKind::InvalidPSBValue, None))
280            }
281        }
282    }
283
284    pub fn write_bytes_refs(&self, stream: &mut impl Write, table: &PsbRefs) -> Result<u64, PsbError> {
285        match &self {
286
287            PsbValue::String(string) => {
288                let n = PsbNumber::get_uint_n(match table.find_string_index(string.string()) {
289
290                    Some(ref_index) => {
291                        Ok(ref_index)
292                    },
293        
294                    None => Err(PsbError::new(PsbErrorKind::InvalidOffsetTable, None))
295                }?);
296                
297                stream.write_u8(PSB_TYPE_STRING_N + n)?;
298
299                Ok(1 + string.write_bytes(stream, table)?)
300            },
301
302            PsbValue::List(list) => {
303                stream.write_u8(PSB_TYPE_LIST)?;
304
305                Ok(1 + list.write_bytes(stream, table)?)
306            },
307
308            PsbValue::Object(object) => {
309                stream.write_u8(PSB_TYPE_OBJECT)?;
310
311                Ok(1 + object.write_bytes(stream, table)?)
312            },
313
314            _ => self.write_bytes(stream)
315
316        }
317    }
318
319}