1use std::io::{Cursor, Read};
2use byteorder::ReadBytesExt;
3use crate::common::{read_size, read_variable_sized_unsigned_number};
4use crate::TinyVgParseError;
5
6#[repr(u8)]
7#[derive(Debug)]
8pub enum ColorEncoding {
9 Rgba8888 = 0,
12
13 Rgb565 = 1,
19 RgbaF32 = 2,
24
25 Custom = 3
28}
29
30impl ColorEncoding {
31 fn from_u8(value: u8) -> ColorEncoding {
32 match value {
33 0 => ColorEncoding::Rgba8888,
34 1 => ColorEncoding::Rgb565,
35 2 => ColorEncoding::RgbaF32,
36 3 => ColorEncoding::Custom,
37 _ => unreachable!("ColorEncoding::from_u8 must be a 2-bit value.")
38 }
39 }
40}
41
42#[repr(u8)]
43#[derive(Debug)]
44pub enum CoordinateRange {
45 Default = 0,
47
48 Reduced = 1,
50
51 Enhanced = 2,
53}
54
55impl CoordinateRange {
56 fn from_u8(value: u8) -> CoordinateRange {
57 match value {
58 0 => CoordinateRange::Default,
59 1 => CoordinateRange::Reduced,
60 2 => CoordinateRange::Enhanced,
61 _ => unreachable!("CoordinateRange::from_u8 must be a 2-bit value.")
62 }
63 }
64}
65
66#[derive(Debug)]
67pub struct TinyVgHeader {
68 pub magic: [u8; 2],
70
71 pub version: u8,
73
74 pub scale: u8,
76
77 pub color_encoding: ColorEncoding,
79
80 pub coordinate_range: CoordinateRange,
83
84 pub width: u32,
88
89 pub height: u32,
93
94 pub color_count: u64,
96}
97
98impl TinyVgHeader {
99 pub(crate) fn parse(cursor: &mut Cursor<&[u8]>) -> Result<Self, TinyVgParseError> {
100 let mut magic = [0u8; 2];
101 cursor.read_exact(&mut magic).map_err(|_| TinyVgParseError::InvalidHeader)?;
102 let version = cursor.read_u8().map_err(|_| TinyVgParseError::InvalidHeader)?;
103
104 let scc = cursor.read_u8().map_err(|_| TinyVgParseError::InvalidHeader)?;
106
107 let scale: u8 = scc & 0x0F;
109
110 let color_encoding_raw = (scc & 0b00_11_00_00) >> 4;
112 let color_encoding = ColorEncoding::from_u8(color_encoding_raw);
113
114 let coordinate_range_raw = (scc & 0b11_00_00_00) >> 6;
116 let coordinate_range = CoordinateRange::from_u8(coordinate_range_raw);
117
118 let width: u32 = read_size(&coordinate_range, cursor)?;
119 let height: u32 = read_size(&coordinate_range, cursor)?;
120
121 let color_count = read_variable_sized_unsigned_number(cursor)?;
122
123 let header = TinyVgHeader {
124 magic,
125 version,
126 scale,
127 color_encoding,
128 coordinate_range,
129 width,
130 height,
131 color_count,
132 };
133
134 Ok(header)
135 }
136}