Skip to main content

steamkit/base/
msg_base.rs

1//! The payload buffer of a client message, plus a small slice reader.
2//!
3//! * [`MsgBase`] owns its bytes and has a read/write cursor.
4//! * [`Reader`] is a borrowing cursor over a slice. The generated
5//!   [`SteamSerializable`](crate::base::generated::steam_language_internal::SteamSerializable)
6//!   types read through it.
7
8use crate::error::SteamError;
9
10/// The reference point for [`MsgBase::seek_from`].
11#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
12pub enum SeekOrigin {
13    /// The beginning of the stream.
14    Begin,
15    /// The current position of the stream.
16    Current,
17    /// The end of the stream.
18    End,
19}
20
21/// A forward-only reader over a byte slice. Integers are little endian.
22#[derive(Clone, Debug)]
23pub struct Reader<'a> {
24    data: &'a [u8],
25    position: usize,
26}
27
28impl<'a> Reader<'a> {
29    /// Creates a reader positioned at the start of `data`.
30    pub fn new(data: &'a [u8]) -> Self {
31        Self { data, position: 0 }
32    }
33
34    /// The number of bytes consumed so far.
35    pub fn position(&self) -> usize {
36        self.position
37    }
38
39    /// The number of bytes left to read.
40    pub fn remaining(&self) -> usize {
41        self.data.len() - self.position
42    }
43
44    /// Whether the reader has consumed the whole slice.
45    pub fn is_empty(&self) -> bool {
46        self.remaining() == 0
47    }
48
49    /// Reads exactly `count` bytes and advances the cursor.
50    pub fn read_bytes(&mut self, count: usize) -> Result<Vec<u8>, SteamError> {
51        let end = self.position.checked_add(count).ok_or_else(|| {
52            SteamError::Malformed(format!("read length overflow at offset {}", self.position))
53        })?;
54        if end > self.data.len() {
55            return Err(SteamError::Malformed(format!(
56                "attempted to read {count} bytes at offset {}, but only {} remain",
57                self.position,
58                self.remaining()
59            )));
60        }
61        let slice = self.data[self.position..end].to_vec();
62        self.position = end;
63        Ok(slice)
64    }
65
66    /// Reads up to `count` bytes and advances the cursor. Returns fewer bytes
67    /// if the data runs out instead of failing.
68    pub fn read_up_to(&mut self, count: usize) -> Vec<u8> {
69        let start = self.position.min(self.data.len());
70        let end = start.saturating_add(count).min(self.data.len());
71        self.position = end;
72        self.data[start..end].to_vec()
73    }
74
75    /// Reads a single unsigned byte.
76    pub fn read_u8(&mut self) -> Result<u8, SteamError> {
77        Ok(self.read_bytes(1)?[0])
78    }
79
80    /// Reads a single signed byte.
81    pub fn read_i8(&mut self) -> Result<i8, SteamError> {
82        Ok(self.read_u8()? as i8)
83    }
84
85    /// Reads a single unsigned 16 bit short.
86    pub fn read_u16(&mut self) -> Result<u16, SteamError> {
87        let bytes = self.read_bytes(2)?;
88        Ok(u16::from_le_bytes([bytes[0], bytes[1]]))
89    }
90
91    /// Reads a single signed 16 bit short.
92    pub fn read_i16(&mut self) -> Result<i16, SteamError> {
93        Ok(self.read_u16()? as i16)
94    }
95
96    /// Reads a single unsigned 32 bit integer.
97    pub fn read_u32(&mut self) -> Result<u32, SteamError> {
98        let bytes = self.read_bytes(4)?;
99        Ok(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
100    }
101
102    /// Reads a single signed 32 bit integer.
103    pub fn read_i32(&mut self) -> Result<i32, SteamError> {
104        Ok(self.read_u32()? as i32)
105    }
106
107    /// Reads a single unsigned 64 bit integer.
108    pub fn read_u64(&mut self) -> Result<u64, SteamError> {
109        let bytes = self.read_bytes(8)?;
110        Ok(u64::from_le_bytes([
111            bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
112        ]))
113    }
114
115    /// Reads a single signed 64 bit integer.
116    pub fn read_i64(&mut self) -> Result<i64, SteamError> {
117        Ok(self.read_u64()? as i64)
118    }
119
120    /// Reads a single 32 bit float.
121    pub fn read_f32(&mut self) -> Result<f32, SteamError> {
122        Ok(f32::from_bits(self.read_u32()?))
123    }
124
125    /// Reads a single 64 bit double.
126    pub fn read_f64(&mut self) -> Result<f64, SteamError> {
127        Ok(f64::from_bits(self.read_u64()?))
128    }
129
130    /// Reads a null-terminated UTF-8 string and consumes the terminator. If
131    /// there's no terminator, reads to the end of the data.
132    pub fn read_null_term_string(&mut self) -> Result<String, SteamError> {
133        let start = self.position;
134        while self.position < self.data.len() && self.data[self.position] != 0 {
135            self.position += 1;
136        }
137        let bytes = &self.data[start..self.position];
138        if self.position < self.data.len() {
139            // consume the null terminator
140            self.position += 1;
141        }
142        Ok(String::from_utf8_lossy(bytes).into_owned())
143    }
144}
145
146/// The payload of a client message: a byte buffer with a cursor.
147#[derive(Clone, Debug, Default)]
148pub struct MsgBase {
149    /// The raw bytes of the message payload.
150    pub payload: Vec<u8>,
151    /// The read/write cursor into [`MsgBase::payload`].
152    pub position: u64,
153}
154
155impl MsgBase {
156    /// Creates an empty payload with the given initial capacity.
157    pub fn new(payload_reserve: usize) -> Self {
158        Self {
159            payload: Vec::with_capacity(payload_reserve),
160            position: 0,
161        }
162    }
163
164    /// Creates a payload pre-filled with `data`, positioned at the start.
165    pub fn from_bytes(data: &[u8]) -> Self {
166        Self {
167            payload: data.to_vec(),
168            position: 0,
169        }
170    }
171
172    /// Seeks to `offset` from the beginning of the payload.
173    ///
174    /// Returns the new position.
175    pub fn seek(&mut self, offset: u64) -> u64 {
176        self.position = offset;
177        self.position
178    }
179
180    /// Seeks to `offset` relative to `origin` and returns the new position.
181    pub fn seek_from(&mut self, offset: u64, origin: SeekOrigin) -> u64 {
182        let base = match origin {
183            SeekOrigin::Begin => 0u64,
184            SeekOrigin::Current => self.position,
185            SeekOrigin::End => self.payload.len() as u64,
186        };
187        self.position = base.saturating_add(offset);
188        self.position
189    }
190
191    /// The number of bytes held in the payload.
192    pub fn len(&self) -> usize {
193        self.payload.len()
194    }
195
196    /// Whether the payload holds no bytes.
197    pub fn is_empty(&self) -> bool {
198        self.payload.is_empty()
199    }
200
201    /// A copy of the whole payload, not just the part after the cursor.
202    pub fn to_bytes(&self) -> Vec<u8> {
203        self.payload.clone()
204    }
205
206    /// A borrowing reader over the part of the payload after the cursor.
207    pub fn reader(&self) -> Reader<'_> {
208        let start = (self.position as usize).min(self.payload.len());
209        Reader::new(&self.payload[start..])
210    }
211
212    /// Writes a single unsigned byte.
213    pub fn write_u8(&mut self, v: u8) {
214        self.write_bytes(&[v]);
215    }
216
217    /// Writes a single signed byte.
218    pub fn write_i8(&mut self, v: i8) {
219        self.write_bytes(&[v as u8]);
220    }
221
222    /// Writes a single unsigned 16 bit short.
223    pub fn write_u16(&mut self, v: u16) {
224        self.write_bytes(&v.to_le_bytes());
225    }
226
227    /// Writes a single signed 16 bit short.
228    pub fn write_i16(&mut self, v: i16) {
229        self.write_bytes(&v.to_le_bytes());
230    }
231
232    /// Writes a single unsigned 32 bit integer.
233    pub fn write_u32(&mut self, v: u32) {
234        self.write_bytes(&v.to_le_bytes());
235    }
236
237    /// Writes a single signed 32 bit integer.
238    pub fn write_i32(&mut self, v: i32) {
239        self.write_bytes(&v.to_le_bytes());
240    }
241
242    /// Writes a single unsigned 64 bit integer.
243    pub fn write_u64(&mut self, v: u64) {
244        self.write_bytes(&v.to_le_bytes());
245    }
246
247    /// Writes a single signed 64 bit integer.
248    pub fn write_i64(&mut self, v: i64) {
249        self.write_bytes(&v.to_le_bytes());
250    }
251
252    /// Writes a single 32 bit float.
253    pub fn write_f32(&mut self, v: f32) {
254        self.write_bytes(&v.to_le_bytes());
255    }
256
257    /// Writes a single 64 bit double.
258    pub fn write_f64(&mut self, v: f64) {
259        self.write_bytes(&v.to_le_bytes());
260    }
261
262    /// Writes `v` at the cursor and advances it. Writing past the end
263    /// zero-fills the gap.
264    pub fn write_bytes(&mut self, v: &[u8]) {
265        let start = self.position as usize;
266        let end = start.saturating_add(v.len());
267        if end > self.payload.len() {
268            self.payload.resize(end, 0);
269        }
270        self.payload[start..end].copy_from_slice(v);
271        self.position = end as u64;
272    }
273
274    /// Writes the UTF-8 bytes of `v`, without a terminator.
275    pub fn write_string(&mut self, v: &str) {
276        self.write_bytes(v.as_bytes());
277    }
278
279    /// Writes the UTF-8 bytes of `v` followed by a null terminator.
280    pub fn write_null_term_string(&mut self, v: &str) {
281        self.write_bytes(v.as_bytes());
282        self.write_u8(0);
283    }
284
285    /// Reads exactly `count` bytes and advances the cursor.
286    pub fn read_exact(&mut self, count: usize) -> Result<Vec<u8>, SteamError> {
287        let start = self.position as usize;
288        let end = start.checked_add(count).ok_or_else(|| {
289            SteamError::Malformed(format!("read length overflow at offset {}", start))
290        })?;
291        if end > self.payload.len() {
292            return Err(SteamError::Malformed(format!(
293                "attempted to read {count} bytes at offset {start}, but only {} remain",
294                self.payload.len().saturating_sub(start)
295            )));
296        }
297        self.position = end as u64;
298        Ok(self.payload[start..end].to_vec())
299    }
300
301    /// Reads up to `count` bytes and advances the cursor. Returns fewer bytes
302    /// if the payload runs out instead of failing.
303    pub fn read_bytes(&mut self, count: usize) -> Vec<u8> {
304        let start = (self.position as usize).min(self.payload.len());
305        let end = start.saturating_add(count).min(self.payload.len());
306        self.position = end as u64;
307        self.payload[start..end].to_vec()
308    }
309
310    /// Reads a single unsigned byte.
311    pub fn read_u8(&mut self) -> Result<u8, SteamError> {
312        Ok(self.read_exact(1)?[0])
313    }
314
315    /// Reads a single signed byte.
316    pub fn read_i8(&mut self) -> Result<i8, SteamError> {
317        Ok(self.read_u8()? as i8)
318    }
319
320    /// Reads a single unsigned 16 bit short.
321    pub fn read_u16(&mut self) -> Result<u16, SteamError> {
322        let bytes = self.read_exact(2)?;
323        Ok(u16::from_le_bytes([bytes[0], bytes[1]]))
324    }
325
326    /// Reads a single signed 16 bit short.
327    pub fn read_i16(&mut self) -> Result<i16, SteamError> {
328        Ok(self.read_u16()? as i16)
329    }
330
331    /// Reads a single unsigned 32 bit integer.
332    pub fn read_u32(&mut self) -> Result<u32, SteamError> {
333        let bytes = self.read_exact(4)?;
334        Ok(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
335    }
336
337    /// Reads a single signed 32 bit integer.
338    pub fn read_i32(&mut self) -> Result<i32, SteamError> {
339        Ok(self.read_u32()? as i32)
340    }
341
342    /// Reads a single unsigned 64 bit integer.
343    pub fn read_u64(&mut self) -> Result<u64, SteamError> {
344        let bytes = self.read_exact(8)?;
345        Ok(u64::from_le_bytes([
346            bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
347        ]))
348    }
349
350    /// Reads a single signed 64 bit integer.
351    pub fn read_i64(&mut self) -> Result<i64, SteamError> {
352        Ok(self.read_u64()? as i64)
353    }
354
355    /// Reads a single 32 bit float.
356    pub fn read_f32(&mut self) -> Result<f32, SteamError> {
357        Ok(f32::from_bits(self.read_u32()?))
358    }
359
360    /// Reads a single 64 bit double.
361    pub fn read_f64(&mut self) -> Result<f64, SteamError> {
362        Ok(f64::from_bits(self.read_u64()?))
363    }
364
365    /// Reads a null terminated UTF-8 string, consuming the terminator.
366    pub fn read_null_term_string(&mut self) -> Result<String, SteamError> {
367        let mut bytes = Vec::new();
368        loop {
369            let byte = self.read_u8()?;
370            if byte == 0 {
371                break;
372            }
373            bytes.push(byte);
374        }
375        Ok(String::from_utf8_lossy(&bytes).into_owned())
376    }
377
378    /// Same as [`read_i8`](Self::read_i8).
379    pub fn read_int8(&mut self) -> Result<i8, SteamError> {
380        self.read_i8()
381    }
382
383    /// Same as [`read_i8`](Self::read_i8).
384    pub fn read_sbyte(&mut self) -> Result<i8, SteamError> {
385        self.read_i8()
386    }
387
388    /// Same as [`read_u8`](Self::read_u8).
389    pub fn read_uint8(&mut self) -> Result<u8, SteamError> {
390        self.read_u8()
391    }
392
393    /// Same as [`read_u8`](Self::read_u8).
394    pub fn read_byte(&mut self) -> Result<u8, SteamError> {
395        self.read_u8()
396    }
397
398    /// Same as [`read_i16`](Self::read_i16).
399    pub fn read_int16(&mut self) -> Result<i16, SteamError> {
400        self.read_i16()
401    }
402
403    /// Same as [`read_i16`](Self::read_i16).
404    pub fn read_short(&mut self) -> Result<i16, SteamError> {
405        self.read_i16()
406    }
407
408    /// Same as [`read_u16`](Self::read_u16).
409    pub fn read_uint16(&mut self) -> Result<u16, SteamError> {
410        self.read_u16()
411    }
412
413    /// Same as [`read_u16`](Self::read_u16).
414    pub fn read_ushort(&mut self) -> Result<u16, SteamError> {
415        self.read_u16()
416    }
417
418    /// Same as [`read_i32`](Self::read_i32).
419    pub fn read_int32(&mut self) -> Result<i32, SteamError> {
420        self.read_i32()
421    }
422
423    /// Same as [`read_i32`](Self::read_i32).
424    pub fn read_int(&mut self) -> Result<i32, SteamError> {
425        self.read_i32()
426    }
427
428    /// Same as [`read_u32`](Self::read_u32).
429    pub fn read_uint32(&mut self) -> Result<u32, SteamError> {
430        self.read_u32()
431    }
432
433    /// Same as [`read_u32`](Self::read_u32).
434    pub fn read_uint(&mut self) -> Result<u32, SteamError> {
435        self.read_u32()
436    }
437
438    /// Same as [`read_i64`](Self::read_i64).
439    pub fn read_int64(&mut self) -> Result<i64, SteamError> {
440        self.read_i64()
441    }
442
443    /// Same as [`read_i64`](Self::read_i64).
444    pub fn read_long(&mut self) -> Result<i64, SteamError> {
445        self.read_i64()
446    }
447
448    /// Same as [`read_u64`](Self::read_u64).
449    pub fn read_uint64(&mut self) -> Result<u64, SteamError> {
450        self.read_u64()
451    }
452
453    /// Same as [`read_u64`](Self::read_u64).
454    pub fn read_ulong(&mut self) -> Result<u64, SteamError> {
455        self.read_u64()
456    }
457
458    /// Same as [`read_f32`](Self::read_f32).
459    pub fn read_single(&mut self) -> Result<f32, SteamError> {
460        self.read_f32()
461    }
462
463    /// Same as [`read_f32`](Self::read_f32).
464    pub fn read_float(&mut self) -> Result<f32, SteamError> {
465        self.read_f32()
466    }
467
468    /// Same as [`read_f64`](Self::read_f64).
469    pub fn read_double(&mut self) -> Result<f64, SteamError> {
470        self.read_f64()
471    }
472}