1use super::error::Error;
4use crate::Cursor;
5use types::Fixed;
6
7#[inline]
8pub(crate) fn parse_int(cursor: &mut Cursor, b0: u8) -> Result<i32, Error> {
9 Ok(match b0 {
18 32..=246 => b0 as i32 - 139,
19 247..=250 => (b0 as i32 - 247) * 256 + cursor.read::<u8>()? as i32 + 108,
20 251..=254 => -(b0 as i32 - 251) * 256 - cursor.read::<u8>()? as i32 - 108,
21 28 => cursor.read::<i16>()? as i32,
22 29 => cursor.read::<i32>()?,
23 _ => {
24 return Err(Error::InvalidNumber);
25 }
26 })
27}
28
29const BCD_OVERFLOW: Fixed = Fixed::from_bits(0x7FFFFFFF);
34const BCD_UNDERFLOW: Fixed = Fixed::ZERO;
36const BCD_NUMBER_LIMIT: i32 = 0xCCCCCCC;
39const BCD_INTEGER_LIMIT: i32 = 0x7FFF;
41
42pub(crate) const BCD_POWER_TENS: [i32; 10] = [
44 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,
45];
46
47#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
50pub struct BcdComponents {
51 error: Option<Fixed>,
55 number: i32,
56 sign: i32,
57 exponent: i32,
58 exponent_add: i32,
59 integer_len: i32,
60 fraction_len: i32,
61}
62
63impl BcdComponents {
64 pub(crate) fn parse(cursor: &mut Cursor) -> Result<Self, Error> {
67 enum Phase {
68 Integer,
69 Fraction,
70 Exponent,
71 }
72 let mut phase = Phase::Integer;
73 let mut sign = 1i32;
74 let mut exponent_sign = 1i32;
75 let mut number = 0i32;
76 let mut exponent = 0i32;
77 let mut exponent_add = 0i32;
78 let mut integer_len = 0;
79 let mut fraction_len = 0;
80 'outer: loop {
91 let b = cursor.read::<u8>()?;
92 for nibble in [(b >> 4) & 0xF, b & 0xF] {
93 match phase {
94 Phase::Integer => match nibble {
95 0x0..=0x9 => {
96 if number >= BCD_NUMBER_LIMIT {
97 exponent_add += 1;
98 } else if nibble != 0 || number != 0 {
99 number = number * 10 + nibble as i32;
100 integer_len += 1;
101 }
102 }
103 0xE => sign = -1,
104 0xA => {
105 phase = Phase::Fraction;
106 }
107 0xB => {
108 phase = Phase::Exponent;
109 }
110 0xC => {
111 phase = Phase::Exponent;
112 exponent_sign = -1;
113 }
114 _ => break 'outer,
115 },
116 Phase::Fraction => match nibble {
117 0x0..=0x9 => {
118 if nibble == 0 && number == 0 {
119 exponent_add -= 1;
120 } else if number < BCD_NUMBER_LIMIT && fraction_len < 9 {
121 number = number * 10 + nibble as i32;
122 fraction_len += 1;
123 }
124 }
125 0xB => {
126 phase = Phase::Exponent;
127 }
128 0xC => {
129 phase = Phase::Exponent;
130 exponent_sign = -1;
131 }
132 _ => break 'outer,
133 },
134 Phase::Exponent => {
135 match nibble {
136 0x0..=0x9 => {
137 if exponent > 1000 {
139 return if exponent_sign == -1 {
140 Ok(BCD_UNDERFLOW.into())
141 } else {
142 Ok(BCD_OVERFLOW.into())
143 };
144 } else {
145 exponent = exponent * 10 + nibble as i32;
146 }
147 }
148 _ => break 'outer,
149 }
150 }
151 }
152 }
153 }
154 exponent *= exponent_sign;
155 Ok(Self {
156 error: None,
157 number,
158 sign,
159 exponent,
160 exponent_add,
161 integer_len,
162 fraction_len,
163 })
164 }
165
166 pub fn value(&self, scale_by_1000: bool) -> Fixed {
170 if let Some(error) = self.error {
171 return error;
172 }
173 let mut number = self.number;
174 if number == 0 {
175 return Fixed::ZERO;
176 }
177 let mut exponent = self.exponent;
178 let mut integer_len = self.integer_len;
179 let mut fraction_len = self.fraction_len;
180 if scale_by_1000 {
181 exponent += 3 + self.exponent_add;
182 } else {
183 exponent += self.exponent_add;
184 }
185 integer_len += exponent;
186 fraction_len -= exponent;
187 if integer_len > 5 {
188 return BCD_OVERFLOW;
189 }
190 if integer_len < -5 {
191 return BCD_UNDERFLOW;
192 }
193 if integer_len < 0 {
195 number /= BCD_POWER_TENS[(-integer_len) as usize];
196 fraction_len += integer_len;
197 }
198 if fraction_len == 10 {
200 number /= 10;
201 fraction_len -= 1;
202 }
203 let mut result = if fraction_len > 0 {
205 let b = BCD_POWER_TENS[fraction_len as usize];
206 if number / b > BCD_INTEGER_LIMIT {
207 0
208 } else {
209 (Fixed::from_bits(number) / Fixed::from_bits(b)).to_bits()
210 }
211 } else {
212 number = number.wrapping_mul(BCD_POWER_TENS[-fraction_len as usize]);
213 if number > BCD_INTEGER_LIMIT {
214 return BCD_OVERFLOW;
215 } else {
216 number << 16
217 }
218 };
219 if scale_by_1000 {
220 result = (Fixed::from_bits(result) / Fixed::from_i32(1000)).to_bits();
224 }
225 Fixed::from_bits(result * self.sign)
226 }
227
228 pub(crate) fn dynamically_scaled_value(&self) -> (Fixed, i32) {
235 if let Some(error) = self.error {
236 return (error, 0);
237 }
238 let mut number = self.number;
239 if number == 0 {
240 return (Fixed::ZERO, 0);
241 }
242 let mut exponent = self.exponent;
243 let integer_len = self.integer_len;
244 let mut fraction_len = self.fraction_len;
245 exponent += self.exponent_add;
246 fraction_len += integer_len;
247 exponent += integer_len;
248 let result;
249 let scaling;
250 if fraction_len <= 5 {
251 if number > BCD_INTEGER_LIMIT {
252 result = Fixed::from_bits(number) / Fixed::from_bits(10);
253 scaling = exponent - fraction_len + 1;
254 } else {
255 if exponent > 0 {
256 let new_fraction_len = exponent.min(5);
258 let shift = new_fraction_len - fraction_len;
259 if shift > 0 {
260 exponent -= new_fraction_len;
261 number *= BCD_POWER_TENS[shift as usize];
262 if number > BCD_INTEGER_LIMIT {
263 number /= 10;
264 exponent += 1;
265 }
266 } else {
267 exponent -= fraction_len;
268 }
269 } else {
270 exponent -= fraction_len;
271 }
272 result = Fixed::from_bits(number << 16);
273 scaling = exponent;
274 }
275 } else if (number / BCD_POWER_TENS[fraction_len as usize - 5]) > BCD_INTEGER_LIMIT {
276 result = Fixed::from_bits(number)
277 / Fixed::from_bits(BCD_POWER_TENS[fraction_len as usize - 4]);
278 scaling = exponent - 4;
279 } else {
280 result = Fixed::from_bits(number)
281 / Fixed::from_bits(BCD_POWER_TENS[fraction_len as usize - 5]);
282 scaling = exponent - 5;
283 }
284 (Fixed::from_bits(result.to_bits() * self.sign), scaling)
285 }
286}
287
288impl From<Fixed> for BcdComponents {
289 fn from(value: Fixed) -> Self {
290 Self {
291 error: Some(value),
292 ..Default::default()
293 }
294 }
295}
296
297pub(crate) fn parse_fixed_dynamic(cursor: &mut Cursor) -> Result<(Fixed, i32), Error> {
301 let b0 = cursor.read::<u8>()?;
302 match b0 {
303 30 => Ok(BcdComponents::parse(cursor)?.dynamically_scaled_value()),
304 28 | 29 | 32..=254 => {
305 let num = parse_int(cursor, b0)?;
306 let mut int_len = 10;
307 if num > BCD_INTEGER_LIMIT {
308 for (i, power_ten) in BCD_POWER_TENS.iter().enumerate().skip(5) {
309 if num < *power_ten {
310 int_len = i;
311 break;
312 }
313 }
314 let scaling = if (num - BCD_POWER_TENS[int_len - 5]) > BCD_INTEGER_LIMIT {
315 int_len - 4
316 } else {
317 int_len - 5
318 };
319 Ok((
320 Fixed::from_bits(num) / Fixed::from_bits(BCD_POWER_TENS[scaling]),
321 scaling as i32,
322 ))
323 } else {
324 Ok((Fixed::from_bits(num << 16), 0))
325 }
326 }
327 _ => Err(Error::InvalidNumber),
328 }
329}
330
331#[cfg(test)]
332mod tests {
333 use super::*;
334 use crate::FontData;
335
336 #[test]
337 fn int_operands() {
338 let empty = FontData::new(&[]);
340 let min_byte = FontData::new(&[0]);
341 let max_byte = FontData::new(&[255]);
342 assert_eq!(parse_int(&mut empty.cursor(), 32).unwrap(), -107);
344 assert_eq!(parse_int(&mut empty.cursor(), 246).unwrap(), 107);
345 assert_eq!(parse_int(&mut min_byte.cursor(), 247).unwrap(), 108);
347 assert_eq!(parse_int(&mut max_byte.cursor(), 250).unwrap(), 1131);
348 assert_eq!(parse_int(&mut min_byte.cursor(), 251).unwrap(), -108);
350 assert_eq!(parse_int(&mut max_byte.cursor(), 254).unwrap(), -1131);
351 }
352
353 #[test]
354 fn binary_coded_decimal_operands() {
355 let bytes = FontData::new(&[0xe2, 0xa2, 0x5f]);
364 assert_eq!(
365 BcdComponents::parse(&mut bytes.cursor())
366 .unwrap()
367 .value(false),
368 Fixed::from_f64(-2.25)
369 );
370 let bytes = FontData::new(&[0x0a, 0x14, 0x05, 0x41, 0xc3, 0xff]);
371 assert_eq!(
372 BcdComponents::parse(&mut bytes.cursor())
373 .unwrap()
374 .value(false),
375 Fixed::from_f64(0.140541E-3)
376 );
377 let bytes = FontData::new(&[0x37, 0x5c, 0x4f]);
381 assert_eq!(
382 BcdComponents::parse(&mut bytes.cursor())
383 .unwrap()
384 .value(false),
385 Fixed::from_f64(0.0370025634765625)
386 );
387 }
388
389 #[test]
390 fn scaled_binary_coded_decimal_operands() {
391 let bytes = FontData::new(&[0xA, 0x06, 0x25, 0xf]);
394 assert_eq!(
395 BcdComponents::parse(&mut bytes.cursor())
396 .unwrap()
397 .value(true),
398 Fixed::from_f64(0.0625)
399 );
400 let bytes = FontData::new(&[0x37, 0x5c, 0x4f]);
403 assert_eq!(
404 BcdComponents::parse(&mut bytes.cursor())
405 .unwrap()
406 .value(true),
407 Fixed::from_f64(0.037506103515625)
408 );
409 }
410
411 #[test]
412 fn dynamically_scaled_binary_coded_decimal_operands() {
413 let bytes = FontData::new(&[0xA, 0x06, 0x25, 0xf]);
415 assert_eq!(
416 BcdComponents::parse(&mut bytes.cursor())
417 .unwrap()
418 .dynamically_scaled_value(),
419 (Fixed::from_f64(6250.0), -5)
420 );
421 let bytes = FontData::new(&[0x37, 0x5c, 0x4f]);
423 assert_eq!(
424 BcdComponents::parse(&mut bytes.cursor())
425 .unwrap()
426 .dynamically_scaled_value(),
427 (Fixed::from_f64(375.0), -4)
428 );
429 let bytes = FontData::new(&[0xa0, 0x1, 0x95, 0x31, 0x25, 0xff]);
431 assert_eq!(
432 BcdComponents::parse(&mut bytes.cursor())
433 .unwrap()
434 .dynamically_scaled_value(),
435 (Fixed::from_bits(1280000000), -7)
436 );
437 }
438
439 #[test]
441 fn blue_scale_fraction_length_of_0() {
442 let bytes = FontData::new(&[0x37, 0xC3, 0xFF]);
444 assert_eq!(
445 BcdComponents::parse(&mut bytes.cursor())
446 .unwrap()
447 .value(true),
448 Fixed::from_f64(0.0370025634765625)
449 );
450 }
451}