criware_utf_core/
reader.rs1use std::{
2 collections::HashMap,
3 io::{Cursor, Read},
4};
5
6use crate::{Error, IOErrorHelper, Result, Value, ValueKind, value::sealed::Primitive};
7
8#[inline(always)]
9pub(crate) fn is_valid_value_flag(half: u8) -> bool {
10 half <= 8 || half == 0xa || half == 0xb
11}
12#[inline(always)]
13pub(crate) fn is_valid_storage_flag(half: u8) -> bool {
14 half == 0x10 || half == 0x30 || half == 0x50
15}
16
17macro_rules! handle_type_flag {
18 ($type_flag:path => $expected:path) => {
19 if $type_flag != $expected as u8 {
20 if is_valid_value_flag($type_flag) {
21 return Err(Error::WrongColumnType($type_flag, $expected as u8));
22 } else {
23 return Err(Error::InvalidColumnType($type_flag));
24 }
25 }
26 };
27}
28
29pub struct Reader {
32 column_buffer: Cursor<Vec<u8>>,
33 column_buffer_size: usize,
34 row_buffer: Cursor<Vec<u8>>,
35 row_buffer_size: usize,
36 strings: HashMap<u32, String>,
37 blobs: Vec<u8>,
38 table_name_index: u32,
39 field_count: u16,
40}
41
42impl Reader {
43 pub fn new(reader: &mut dyn Read) -> Result<Reader> {
57 let table_size = {
58 let mut header = [0u8; 8];
59 reader.read_exact(&mut header).io("@UTF header")?;
60 if &header[0..4] != b"@UTF" {
61 return Err(Error::MalformedHeader);
62 }
63 u32::from_be_bytes(header[4..8].try_into().unwrap())
64 };
65 if table_size < 24 {
66 return Err(Error::EOF("@UTF header".to_string()));
67 }
68 let mut header = [0u8; 24];
69 reader.read_exact(&mut header).io("@UTF header")?;
70 let row_offset = u32::from_be_bytes(header[0..4].try_into().unwrap());
71 let string_offset = u32::from_be_bytes(header[4..8].try_into().unwrap());
72 let blob_offset = u32::from_be_bytes(header[8..12].try_into().unwrap());
73 let table_name = u32::from_be_bytes(header[12..16].try_into().unwrap());
74 let field_count = u16::from_be_bytes(header[16..18].try_into().unwrap());
75 let row_size = u16::from_be_bytes(header[18..20].try_into().unwrap());
76 let row_count = u32::from_be_bytes(header[20..24].try_into().unwrap());
77 if 24 > row_offset
78 || row_offset > string_offset
79 || string_offset > blob_offset
80 || blob_offset > table_size
81 || (row_size as u32 * row_count) != string_offset - row_offset
82 {
83 return Err(Error::MalformedHeader);
84 }
85 let (column_buffer, column_buffer_size) = {
86 let mut buffer = vec![0u8; row_offset as usize - 24];
87 reader.read_exact(&mut buffer).io("UTF column data")?;
88 let len = buffer.len();
89 (Cursor::new(buffer), len)
90 };
91 let (row_buffer, row_buffer_size) = {
92 let mut buffer = vec![0u8; (string_offset - row_offset) as usize];
93 reader.read_exact(&mut buffer).io("UTF row data")?;
94 let len = buffer.len();
95 (Cursor::new(buffer), len)
96 };
97 let strings = {
98 let mut buffer = vec![0u8; (blob_offset - string_offset) as usize];
99 reader.read_exact(&mut buffer).io("UTF string data")?;
100 let mut strings = HashMap::new();
101 let mut start = 0;
102 let mut index = 0;
103 while index < buffer.len() {
104 if buffer[index] == 0 {
105 match std::str::from_utf8(&buffer[(start as usize)..index]) {
106 Ok(value) => strings.insert(start, value.to_owned()),
107 Err(error) => return Err(Error::StringMalformed(error)),
108 };
109 start = (index + 1) as u32;
110 }
111 index += 1;
112 }
113 strings
114 };
115 if !strings.contains_key(&table_name) {
116 return Err(Error::MalformedHeader);
117 }
118 let mut blobs = vec![0u8; (table_size - blob_offset) as usize];
119 reader.read_exact(&mut blobs).io("UTF blob data")?;
120 Ok(Reader {
121 column_buffer,
122 column_buffer_size,
123 row_buffer,
124 row_buffer_size,
125 strings,
126 blobs,
127 table_name_index: table_name,
128 field_count,
129 })
130 }
131
132 pub fn field_count(&self) -> u16 {
145 self.field_count
146 }
147
148 pub fn table_name<'a>(&'a self) -> &'a str {
161 self.strings.get(&self.table_name_index).unwrap().as_str()
162 }
163
164 pub fn more_column_data(&self) -> bool {
181 (self.column_buffer.position() as usize) < self.column_buffer_size
182 }
183
184 pub fn more_row_data(&self) -> bool {
201 (self.row_buffer.position() as usize) < self.row_buffer_size
202 }
203
204 fn read_constant_column_private<T: Value>(
205 &mut self,
206 name: &'static str,
207 optional: bool,
208 ) -> Result<Option<T>> {
209 let flag = self.read_primitive::<u8>(false)?;
210 let column_name = self.read_primitive::<str>(false)?;
211 if column_name != name {
212 return Err(Error::WrongColumnName(column_name, name));
213 }
214 let type_flag = flag & 0x0f;
215 let storage_flag = flag & 0xf0;
216 handle_type_flag!(type_flag => T::Primitive::TYPE_FLAG);
217 if storage_flag == 0x30 {
218 Ok(Some(self.read_value(false)?))
219 } else if optional && storage_flag == 0x10 {
220 Ok(None)
221 } else if is_valid_storage_flag(storage_flag) {
222 return Err(Error::WrongColumnStorage(storage_flag, "0x30"));
223 } else {
224 return Err(Error::InvalidColumnStorage(storage_flag));
225 }
226 }
227
228 pub fn read_constant_column<T: Value>(&mut self, name: &'static str) -> Result<T> {
245 Ok(self.read_constant_column_private(name, false)?.unwrap())
246 }
247
248 pub fn read_constant_column_opt<T: Value>(&mut self, name: &'static str) -> Result<Option<T>> {
267 self.read_constant_column_private(name, true)
268 }
269
270 fn read_rowed_column_private(
271 &mut self,
272 name: &'static str,
273 kind: ValueKind,
274 optional: bool,
275 ) -> Result<bool> {
276 let flag = self.read_primitive::<u8>(false)?;
277 let column_name = self.read_primitive::<str>(false)?;
278 if column_name != name {
279 return Err(Error::WrongColumnName(column_name, name));
280 }
281 let type_flag = flag & 0x0f;
282 let storage_flag = flag & 0xf0;
283 handle_type_flag!(type_flag => kind);
284 if storage_flag == 0x50 {
285 Ok(true)
286 } else if optional && storage_flag == 0x10 {
287 Ok(false)
288 } else if is_valid_storage_flag(storage_flag) {
289 return Err(Error::WrongColumnStorage(storage_flag, "0x50"));
290 } else {
291 return Err(Error::InvalidColumnStorage(storage_flag));
292 }
293 }
294
295 pub fn read_rowed_column<T: Value>(&mut self, name: &'static str) -> Result<()> {
311 self.read_rowed_column_private(name, T::Primitive::TYPE_FLAG, false)?;
312 Ok(())
313 }
314
315 pub fn read_rowed_column_opt<T: Value>(&mut self, name: &'static str) -> Result<bool> {
338 self.read_rowed_column_private(name, T::Primitive::TYPE_FLAG, true)
339 }
340
341 fn read_primitive<T: Primitive + ?Sized>(&mut self, row: bool) -> Result<T::Owned> {
342 let mut buffer: T::Buffer = Default::default();
343 let reader = if row {
344 &mut self.row_buffer
345 } else {
346 &mut self.column_buffer
347 };
348 match reader.read_exact(buffer.as_mut()) {
349 Ok(()) => (),
350 Err(error) => match error.kind() {
351 std::io::ErrorKind::UnexpectedEof => {
352 return Err(Error::EOF(format!(
353 "reading {} value",
354 std::any::type_name::<T>()
355 )));
356 }
357 _ => return Err(Error::IOError(error)),
358 },
359 };
360 match <T as Primitive>::parse(buffer, &self.strings, &self.blobs) {
361 Some(prim) => Ok(prim),
362 None => Err(Error::DataNotFound),
363 }
364 }
365
366 pub fn read_value<T: Value>(&mut self, row: bool) -> Result<T> {
383 T::from_primitive(self.read_primitive::<T::Primitive>(row)?).map_err(|error| {
384 Error::ValueConversion(
385 std::any::type_name::<T::Primitive>(),
386 std::any::type_name::<T>(),
387 error,
388 )
389 })
390 }
391}