hermes_tdata/qdatastream/
reader.rs1use byteorder::{BigEndian, ReadBytesExt};
4use std::io::{Cursor, Read, Seek, SeekFrom};
5
6use crate::{Error, Result};
7
8use super::constants::{EXTENDED_LENGTH_MARKER, NULL_MARKER, QT_VERSION_5_1};
9
10pub struct QDataStream<'a> {
12 pub(super) cursor: Cursor<&'a [u8]>,
13 pub(super) version: u32,
14}
15
16impl std::fmt::Debug for QDataStream<'_> {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 f.debug_struct("QDataStream")
19 .field("position", &self.cursor.position())
20 .field("version", &self.version)
21 .finish()
22 }
23}
24
25impl<'a> QDataStream<'a> {
26 #[must_use]
28 pub const fn new(data: &'a [u8]) -> Self {
29 Self { cursor: Cursor::new(data), version: QT_VERSION_5_1 }
30 }
31
32 #[must_use]
34 pub const fn with_version(data: &'a [u8], version: u32) -> Self {
35 Self { cursor: Cursor::new(data), version }
36 }
37
38 #[must_use]
40 pub const fn version(&self) -> u32 {
41 self.version
42 }
43
44 #[must_use]
46 pub const fn position(&self) -> u64 {
47 self.cursor.position()
48 }
49
50 #[must_use]
52 pub const fn at_end(&self) -> bool {
53 self.cursor.position() >= self.cursor.get_ref().len() as u64
54 }
55
56 #[must_use]
58 pub const fn remaining(&self) -> usize {
59 let pos = self.cursor.position() as usize;
60 let len = self.cursor.get_ref().len();
61 len.saturating_sub(pos)
62 }
63
64 pub fn skip(&mut self, n: usize) -> Result<()> {
66 let _ = self
67 .cursor
68 .seek(SeekFrom::Current(n as i64))
69 .map_err(|_| Error::UnexpectedEof { offset: self.position() })?;
70 Ok(())
71 }
72
73 pub fn read_u8(&mut self) -> Result<u8> {
75 self.cursor.read_u8().map_err(|_| Error::UnexpectedEof { offset: self.position() })
76 }
77
78 pub fn read_i8(&mut self) -> Result<i8> {
80 self.cursor.read_i8().map_err(|_| Error::UnexpectedEof { offset: self.position() })
81 }
82
83 pub fn read_u16(&mut self) -> Result<u16> {
85 self.cursor
86 .read_u16::<BigEndian>()
87 .map_err(|_| Error::UnexpectedEof { offset: self.position() })
88 }
89
90 pub fn read_i16(&mut self) -> Result<i16> {
92 self.cursor
93 .read_i16::<BigEndian>()
94 .map_err(|_| Error::UnexpectedEof { offset: self.position() })
95 }
96
97 pub fn read_u32(&mut self) -> Result<u32> {
99 self.cursor
100 .read_u32::<BigEndian>()
101 .map_err(|_| Error::UnexpectedEof { offset: self.position() })
102 }
103
104 pub fn read_i32(&mut self) -> Result<i32> {
106 self.cursor
107 .read_i32::<BigEndian>()
108 .map_err(|_| Error::UnexpectedEof { offset: self.position() })
109 }
110
111 pub fn read_u64(&mut self) -> Result<u64> {
113 self.cursor
114 .read_u64::<BigEndian>()
115 .map_err(|_| Error::UnexpectedEof { offset: self.position() })
116 }
117
118 pub fn read_i64(&mut self) -> Result<i64> {
120 self.cursor
121 .read_i64::<BigEndian>()
122 .map_err(|_| Error::UnexpectedEof { offset: self.position() })
123 }
124
125 pub fn read_bool(&mut self) -> Result<bool> {
127 Ok(self.read_u8()? != 0)
128 }
129
130 pub fn read_f32(&mut self) -> Result<f32> {
132 self.cursor
133 .read_f32::<BigEndian>()
134 .map_err(|_| Error::UnexpectedEof { offset: self.position() })
135 }
136
137 pub fn read_f64(&mut self) -> Result<f64> {
139 self.cursor
140 .read_f64::<BigEndian>()
141 .map_err(|_| Error::UnexpectedEof { offset: self.position() })
142 }
143
144 pub fn read_raw(&mut self, len: usize) -> Result<Vec<u8>> {
146 if self.remaining() < len {
147 return Err(Error::UnexpectedEof { offset: self.position() });
148 }
149
150 let mut buf = vec![0u8; len];
151 self.cursor
152 .read_exact(&mut buf)
153 .map_err(|_| Error::UnexpectedEof { offset: self.position() })?;
154 Ok(buf)
155 }
156
157 pub fn read_qbytearray(&mut self) -> Result<Vec<u8>> {
165 let len = self.read_u32()?;
166
167 match len {
168 NULL_MARKER => Ok(Vec::new()),
169 EXTENDED_LENGTH_MARKER => {
170 let real_len = self.read_u64()? as usize;
172 self.read_raw(real_len)
173 },
174 _ => self.read_raw(len as usize),
175 }
176 }
177
178 pub fn read_qstring(&mut self) -> Result<String> {
185 let byte_len = self.read_u32()?;
186
187 if byte_len == NULL_MARKER {
188 return Ok(String::new());
189 }
190
191 if byte_len % 2 != 0 {
192 return Err(Error::qdatastream("QString byte length is not even"));
193 }
194
195 let char_count = (byte_len / 2) as usize;
196 let mut utf16: Vec<u16> = Vec::with_capacity(char_count);
197
198 for _ in 0..char_count {
199 utf16.push(self.read_u16()?);
200 }
201
202 String::from_utf16(&utf16).map_err(|_| Error::InvalidUtf16)
203 }
204
205 pub fn read_cstring(&mut self) -> Result<String> {
211 let data = self.read_qbytearray()?;
212
213 let data = if data.last() == Some(&0) { &data[..data.len() - 1] } else { &*data };
215
216 String::from_utf8(data.to_vec())
217 .map_err(|_| Error::qdatastream("invalid UTF-8 in C string"))
218 }
219}