emote_psb\types/
number.rs

1/*
2 * Created on Fri Dec 25 2020
3 *
4 * Copyright (c) storycraft. Licensed under the MIT Licence.
5 */
6
7use std::io::{Read, Write};
8
9use crate::{PsbError, PsbErrorKind};
10
11use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
12
13use super::{PSB_TYPE_DOUBLE, PSB_TYPE_FLOAT, PSB_TYPE_INTEGER_N, PSB_TYPE_FLOAT0};
14
15#[cfg(feature = "serde")]
16use serde::{Serialize, Deserialize};
17
18#[derive(Debug, Clone, PartialEq)]
19#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
20#[cfg_attr(feature = "serde", serde(untagged))]
21pub enum PsbNumber {
22
23    Integer(i64),
24    Double(f64),
25    Float(f32)
26
27}
28
29impl PsbNumber {
30
31    pub fn from_bytes(number_type: u8, stream: &mut impl Read) -> Result<(u64, Self), PsbError> {
32        match number_type {
33
34            PSB_TYPE_DOUBLE => {
35                Ok((8, Self::Double(stream.read_f64::<LittleEndian>()?)))
36            },
37
38            PSB_TYPE_FLOAT => {
39                Ok((4, Self::Float(stream.read_f32::<LittleEndian>()?)))
40            },
41
42            PSB_TYPE_FLOAT0 => {
43                Ok((0, Self::Float(0_f32)))
44            },
45
46            _ if number_type >= PSB_TYPE_INTEGER_N && number_type <= PSB_TYPE_INTEGER_N + 8 => {
47                let number_size = number_type - PSB_TYPE_INTEGER_N;
48
49                let (read, val) = Self::read_integer(number_size, stream)?;
50
51                Ok((read, Self::Integer(val)))
52            }
53
54            _ => {
55                Err(PsbError::new(PsbErrorKind::InvalidPSBValue, None))
56            }
57
58        }
59    }
60
61    /// Read uint with given size.
62    pub fn read_uint(number_size: u8, stream: &mut impl Read) -> Result<(u64, u64), PsbError> {
63        if number_size == 0 {
64            Ok((1, 0))
65        } else if number_size <= 8 {
66            let mut buf = [0_u8; 8];
67
68            stream.read_exact(&mut buf[..number_size as usize])?;
69
70            Ok((number_size as u64, u64::from_le_bytes(buf)))
71        } else {
72            Err(PsbError::new(PsbErrorKind::InvalidPSBValue, None))
73        }
74    }
75
76    pub fn read_integer(number_size: u8, stream: &mut impl Read) -> Result<(u64, i64), PsbError> {
77        if number_size == 0 {
78            Ok((1, 0))
79        } else if number_size <= 8 {
80            let (read, unsigned) = Self::read_uint(number_size, stream)?;
81
82            let max = 1_u64 << (number_size * 8);
83            let number = if unsigned >= (max >> 1) {
84                -((max - unsigned) as i64)
85            } else {
86                unsigned as i64
87            };
88
89            Ok((read, number))
90        } else {
91            Err(PsbError::new(PsbErrorKind::InvalidPSBValue, None))
92        }
93    }
94
95    pub fn get_n(mut number: i64) -> u8 {
96        if number < 0 {
97            number = -number;
98        }
99        
100        if number <= 0x7f {
101            1
102        } else if number <= 0x7fff {
103            2
104        } else if number <= 0x7fffff {
105            3
106        } else if number <= 0x7fffffff {
107            4
108        } else if number <= 0x7fffffffff {
109            5
110        } else if number <= 0x7fffffffffff {
111            6
112        } else if number <= 0x7fffffffffffff {
113            7
114        } else {
115            8
116        }
117    }
118
119    pub fn get_uint_n(number: u64) -> u8 {
120        if number <= 0xff {
121            1
122        } else if number <= 0xffff {
123            2
124        } else if number <= 0xffffff {
125            3
126        } else if number <= 0xffffffff {
127            4
128        } else if number <= 0xffffffffff {
129            5
130        } else if number <= 0xffffffffffff {
131            6
132        } else if number <= 0xffffffffffffff {
133            7
134        } else {
135            8
136        }
137    }
138
139    pub fn write_bytes(&self, stream: &mut impl Write) -> Result<u64, PsbError> {
140        match self {
141            PsbNumber::Integer(val) => {
142                if *val == 0 {
143                    return Ok(0);
144                }
145                
146                let n = Self::get_n(*val);
147                
148                Self::write_integer(n, *val, stream)?;
149                Ok(n as u64)
150            },
151
152            PsbNumber::Double(val) => {
153                stream.write_f64::<LittleEndian>(*val)?;
154                Ok(8)
155            },
156
157            PsbNumber::Float(val) => {
158                if *val == 0f32 {
159                    Ok(0)
160                } else {
161                    stream.write_f32::<LittleEndian>(*val)?;
162
163                    Ok(4)
164                }
165            }
166
167        }
168    }
169
170    pub fn write_uint(n: u8, number: u64, stream: &mut impl Write) -> Result<u8, PsbError> {
171        if n > 0 {
172            stream.write_all(&number.to_le_bytes()[..n as usize])?;
173
174            Ok(n)
175        } else {
176            Ok(0)
177        }
178    }
179
180    pub fn write_integer(n: u8, number: i64, stream: &mut impl Write) -> Result<u8, PsbError> {
181        Self::write_uint(n, number as u64, stream)
182    }
183
184}
185
186impl From<i8> for PsbNumber {
187    fn from(number: i8) -> Self {
188        PsbNumber::Integer(number as i64)
189    }
190}
191
192impl From<i16> for PsbNumber {
193    fn from(number: i16) -> Self {
194        PsbNumber::Integer(number as i64)
195    }
196}
197
198impl From<i32> for PsbNumber {
199    fn from(number: i32) -> Self {
200        PsbNumber::Integer(number as i64)
201    }
202}
203
204impl From<i64> for PsbNumber {
205    fn from(number: i64) -> Self {
206        PsbNumber::Integer(number)
207    }
208}
209
210impl From<f32> for PsbNumber {
211    fn from(number: f32) -> Self {
212        PsbNumber::Float(number)
213    }
214}
215
216impl From<f64> for PsbNumber {
217    fn from(number: f64) -> Self {
218        PsbNumber::Double(number)
219    }
220}