1use std::io::Cursor;
2use byteorder::{LittleEndian, ReadBytesExt};
3use crate::{CoordinateRange, TinyVgParseError};
4
5#[derive(Debug, Copy, Clone)]
6pub struct Unit(pub f64);
7
8pub(crate) fn read_size(coordinate_range: &CoordinateRange, cursor: &mut Cursor<&[u8]>) -> Result<u32, TinyVgParseError> {
10 let res = match coordinate_range {
11 CoordinateRange::Reduced => cursor.read_u8().map_err(|_| TinyVgParseError::InvalidHeader)? as u32,
12 CoordinateRange::Default => cursor.read_u16::<LittleEndian>().map_err(|_| TinyVgParseError::InvalidHeader)? as u32,
13 CoordinateRange::Enhanced => cursor.read_u32::<LittleEndian>().map_err(|_| TinyVgParseError::InvalidHeader)?
14 };
15 Ok(res)
16}
17
18pub(crate) fn read_variable_sized_unsigned_number(cursor: &mut Cursor<&[u8]>) -> Result<u64, TinyVgParseError> {
23 let mut count = 0u64;
24 let mut result = 0u64;
25 loop {
26 let byte = cursor.read_u8().map_err(|_| TinyVgParseError::InvalidHeader)?;
27 let val: u64 = (byte as u64 & 0x7F) << (7 * count);
28 result |= val;
29 if (byte & 0x80) == 0 {
30 break;
31 }
32 count += 1;
33 }
34
35 Ok(result)
36}
37
38
39pub(crate) fn read_unit(scale: u8, cursor: &mut Cursor<&[u8]>, coordinate_range: &CoordinateRange) -> Result<Unit, TinyVgParseError> {
40 let raw: i64;
41
42 match coordinate_range {
43 CoordinateRange::Default => raw = cursor.read_i16::<LittleEndian>().map_err(|_| TinyVgParseError::InvalidCommand)? as i64,
44 CoordinateRange::Reduced => raw = cursor.read_i8().map_err(|_| TinyVgParseError::InvalidCommand)? as i64,
45 CoordinateRange::Enhanced => raw = cursor.read_i32::<LittleEndian>().map_err(|_| TinyVgParseError::InvalidCommand)? as i64,
46 }
47
48 let units_in_css_px: f64 = raw as f64 / (1 << scale) as f64;
49
50 Ok(Unit(units_in_css_px))
51}