Skip to main content

gaia_binary/
lib.rs

1#![warn(missing_docs)]
2//! Binary encoding and decoding for Gaia project.
3//!
4//! This crate provides utilities for reading and writing binary data with support for
5//! different byte orders and position tracking.
6
7/// Binary reader implementation with position tracking.
8pub mod reader;
9/// Binary format traits for encoding/decoding data.
10pub mod traits;
11/// Binary writer implementation with position tracking.
12pub mod writer;
13
14use gaia_types::{GaiaError, GaiaErrorKind, Result};
15use std::{
16    io::{Read, Write},
17    marker::PhantomData,
18};
19
20pub use reader::BinaryReader;
21pub use traits::BinaryFormat;
22pub use writer::BinaryWriter;
23
24/// A reader wrapper that tracks position.
25#[derive(Debug)]
26pub struct TrackingReader<R: Read> {
27    /// Inner reader.
28    pub inner: R,
29    /// Current position.
30    pub position: u64,
31}
32
33impl<R: Read> Read for TrackingReader<R> {
34    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
35        let n = self.inner.read(buf)?;
36        self.position += n as u64;
37        Ok(n)
38    }
39}
40
41impl<R: Read + std::io::Seek> std::io::Seek for TrackingReader<R> {
42    fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
43        self.position = self.inner.seek(pos)?;
44        Ok(self.position)
45    }
46}
47
48/// A writer wrapper that tracks position.
49#[derive(Debug)]
50pub struct TrackingWriter<W: Write> {
51    /// Inner writer.
52    pub inner: W,
53    /// Current position.
54    pub position: u64,
55}
56
57impl<W: Write + std::io::Seek> std::io::Seek for TrackingWriter<W> {
58    fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
59        self.position = self.inner.seek(pos)?;
60        Ok(self.position)
61    }
62}
63
64impl<W: Write> Write for TrackingWriter<W> {
65    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
66        let n = self.inner.write(buf)?;
67        self.position += n as u64;
68        Ok(n)
69    }
70
71    fn flush(&mut self) -> std::io::Result<()> {
72        self.inner.flush()
73    }
74}
75
76/// Byte order traits.
77pub trait ByteOrder {
78    /// Read u16.
79    fn read_u16(buf: &[u8]) -> u16;
80    /// Read u32.
81    fn read_u32(buf: &[u8]) -> u32;
82    /// Read u64.
83    fn read_u64(buf: &[u8]) -> u64;
84    /// Write u16.
85    fn write_u16(buf: &mut [u8], n: u16);
86    /// Write u32.
87    fn write_u32(buf: &mut [u8], n: u32);
88    /// Write u64.
89    fn write_u64(buf: &mut [u8], n: u64);
90}
91
92/// Big endian implementation.
93pub struct BigEndian;
94impl ByteOrder for BigEndian {
95    fn read_u16(buf: &[u8]) -> u16 {
96        u16::from_be_bytes(buf.try_into().unwrap())
97    }
98    fn read_u32(buf: &[u8]) -> u32 {
99        u32::from_be_bytes(buf.try_into().unwrap())
100    }
101    fn read_u64(buf: &[u8]) -> u64 {
102        u64::from_be_bytes(buf.try_into().unwrap())
103    }
104    fn write_u16(buf: &mut [u8], n: u16) {
105        buf.copy_from_slice(&n.to_be_bytes())
106    }
107    fn write_u32(buf: &mut [u8], n: u32) {
108        buf.copy_from_slice(&n.to_be_bytes())
109    }
110    fn write_u64(buf: &mut [u8], n: u64) {
111        buf.copy_from_slice(&n.to_be_bytes())
112    }
113}
114
115/// Little endian implementation.
116pub struct LittleEndian;
117impl ByteOrder for LittleEndian {
118    fn read_u16(buf: &[u8]) -> u16 {
119        u16::from_le_bytes(buf.try_into().unwrap())
120    }
121    fn read_u32(buf: &[u8]) -> u32 {
122        u32::from_le_bytes(buf.try_into().unwrap())
123    }
124    fn read_u64(buf: &[u8]) -> u64 {
125        u64::from_le_bytes(buf.try_into().unwrap())
126    }
127    fn write_u16(buf: &mut [u8], n: u16) {
128        buf.copy_from_slice(&n.to_le_bytes())
129    }
130    fn write_u32(buf: &mut [u8], n: u32) {
131        buf.copy_from_slice(&n.to_le_bytes())
132    }
133    fn write_u64(buf: &mut [u8], n: u64) {
134        buf.copy_from_slice(&n.to_le_bytes())
135    }
136}
137
138/// Fixed-size encoding with a specific byte order.
139pub struct Fixed<E: ByteOrder>(PhantomData<E>);
140
141impl<E: ByteOrder> BinaryFormat for Fixed<E> {
142    fn read_u16<R: Read>(reader: &mut R) -> Result<u16> {
143        let mut buf = [0u8; 2];
144        reader.read_exact(&mut buf).map_err(|_| GaiaError::truncated())?;
145        Ok(E::read_u16(&buf))
146    }
147    fn write_u16<W: Write>(writer: &mut W, value: u16) -> Result<()> {
148        let mut buf = [0u8; 2];
149        E::write_u16(&mut buf, value);
150        writer.write_all(&buf).map_err(|_| GaiaErrorKind::TruncatedData.into())
151    }
152    fn read_u32<R: Read>(reader: &mut R) -> Result<u32> {
153        let mut buf = [0u8; 4];
154        reader.read_exact(&mut buf).map_err(|_| GaiaError::truncated())?;
155        Ok(E::read_u32(&buf))
156    }
157    fn write_u32<W: Write>(writer: &mut W, value: u32) -> Result<()> {
158        let mut buf = [0u8; 4];
159        E::write_u32(&mut buf, value);
160        writer.write_all(&buf).map_err(|_| GaiaError::truncated())
161    }
162    fn read_u64<R: Read>(reader: &mut R) -> Result<u64> {
163        let mut buf = [0u8; 8];
164        reader.read_exact(&mut buf).map_err(|_| GaiaError::truncated())?;
165        Ok(E::read_u64(&buf))
166    }
167    fn write_u64<W: Write>(writer: &mut W, value: u64) -> Result<()> {
168        let mut buf = [0u8; 8];
169        E::write_u64(&mut buf, value);
170        writer.write_all(&buf).map_err(|_| GaiaError::truncated())
171    }
172    fn read_i16<R: Read>(reader: &mut R) -> Result<i16> {
173        Ok(Self::read_u16(reader)? as i16)
174    }
175    fn write_i16<W: Write>(writer: &mut W, value: i16) -> Result<()> {
176        Self::write_u16(writer, value as u16)
177    }
178    fn read_i32<R: Read>(reader: &mut R) -> Result<i32> {
179        Ok(Self::read_u32(reader)? as i32)
180    }
181    fn write_i32<W: Write>(writer: &mut W, value: i32) -> Result<()> {
182        Self::write_u32(writer, value as u32)
183    }
184    fn read_i64<R: Read>(reader: &mut R) -> Result<i64> {
185        Ok(Self::read_u64(reader)? as i64)
186    }
187    fn write_i64<W: Write>(writer: &mut W, value: i64) -> Result<()> {
188        Self::write_u64(writer, value as u64)
189    }
190    fn read_f32<R: Read>(reader: &mut R) -> Result<f32> {
191        Ok(f32::from_bits(Self::read_u32(reader)?))
192    }
193    fn write_f32<W: Write>(writer: &mut W, value: f32) -> Result<()> {
194        Self::write_u32(writer, value.to_bits())
195    }
196    fn read_f64<R: Read>(reader: &mut R) -> Result<f64> {
197        Ok(f64::from_bits(Self::read_u64(reader)?))
198    }
199    fn write_f64<W: Write>(writer: &mut W, value: f64) -> Result<()> {
200        Self::write_u64(writer, value.to_bits())
201    }
202}
203
204/// Extension trait for reading binary data.
205pub trait ReadBytesExt: Read {
206    /// Read a u16 value.
207    fn read_u16<T: ByteOrder>(&mut self) -> std::io::Result<u16> {
208        let mut buf = [0u8; 2];
209        self.read_exact(&mut buf)?;
210        Ok(T::read_u16(&buf))
211    }
212    /// Read a u32 value.
213    fn read_u32<T: ByteOrder>(&mut self) -> std::io::Result<u32> {
214        let mut buf = [0u8; 4];
215        self.read_exact(&mut buf)?;
216        Ok(T::read_u32(&buf))
217    }
218    /// Read a u64 value.
219    fn read_u64<T: ByteOrder>(&mut self) -> std::io::Result<u64> {
220        let mut buf = [0u8; 8];
221        self.read_exact(&mut buf)?;
222        Ok(T::read_u64(&buf))
223    }
224    /// Read an i16 value.
225    fn read_i16<T: ByteOrder>(&mut self) -> std::io::Result<i16> {
226        Ok(self.read_u16::<T>()? as i16)
227    }
228    /// Read an i32 value.
229    fn read_i32<T: ByteOrder>(&mut self) -> std::io::Result<i32> {
230        Ok(self.read_u32::<T>()? as i32)
231    }
232    /// Read an i64 value.
233    fn read_i64<T: ByteOrder>(&mut self) -> std::io::Result<i64> {
234        Ok(self.read_u64::<T>()? as i64)
235    }
236    /// Read an f32 value.
237    fn read_f32<T: ByteOrder>(&mut self) -> std::io::Result<f32> {
238        Ok(f32::from_bits(self.read_u32::<T>()?))
239    }
240    /// Read an f64 value.
241    fn read_f64<T: ByteOrder>(&mut self) -> std::io::Result<f64> {
242        Ok(f64::from_bits(self.read_u64::<T>()?))
243    }
244    /// Read a u8 value.
245    fn read_u8(&mut self) -> std::io::Result<u8> {
246        let mut buf = [0u8; 1];
247        self.read_exact(&mut buf)?;
248        Ok(buf[0])
249    }
250    /// Read an i8 value.
251    fn read_i8(&mut self) -> std::io::Result<i8> {
252        Ok(self.read_u8()? as i8)
253    }
254}
255
256impl<R: Read + ?Sized> ReadBytesExt for R {}
257
258/// Extension trait for writing binary data.
259pub trait WriteBytesExt: Write {
260    /// Write a u16 value.
261    fn write_u16<T: ByteOrder>(&mut self, n: u16) -> std::io::Result<()> {
262        let mut buf = [0u8; 2];
263        T::write_u16(&mut buf, n);
264        self.write_all(&buf)
265    }
266    /// Write a u32 value.
267    fn write_u32<T: ByteOrder>(&mut self, n: u32) -> std::io::Result<()> {
268        let mut buf = [0u8; 4];
269        T::write_u32(&mut buf, n);
270        self.write_all(&buf)
271    }
272    /// Write a u64 value.
273    fn write_u64<T: ByteOrder>(&mut self, n: u64) -> std::io::Result<()> {
274        let mut buf = [0u8; 8];
275        T::write_u64(&mut buf, n);
276        self.write_all(&buf)
277    }
278    /// Write an i16 value.
279    fn write_i16<T: ByteOrder>(&mut self, n: i16) -> std::io::Result<()> {
280        self.write_u16::<T>(n as u16)
281    }
282    /// Write an i32 value.
283    fn write_i32<T: ByteOrder>(&mut self, n: i32) -> std::io::Result<()> {
284        self.write_u32::<T>(n as u32)
285    }
286    /// Write an i64 value.
287    fn write_i64<T: ByteOrder>(&mut self, n: i64) -> std::io::Result<()> {
288        self.write_u64::<T>(n as u64)
289    }
290    /// Write an f32 value.
291    fn write_f32<T: ByteOrder>(&mut self, n: f32) -> std::io::Result<()> {
292        self.write_u32::<T>(n.to_bits())
293    }
294    /// Write an f64 value.
295    fn write_f64<T: ByteOrder>(&mut self, n: f64) -> std::io::Result<()> {
296        self.write_u64::<T>(n.to_bits())
297    }
298    /// Write a u8 value.
299    fn write_u8(&mut self, n: u8) -> std::io::Result<()> {
300        self.write_all(&[n])
301    }
302    /// Write an i8 value.
303    fn write_i8(&mut self, n: i8) -> std::io::Result<()> {
304        self.write_u8(n as u8)
305    }
306}
307
308impl<W: Write + ?Sized> WriteBytesExt for W {}
309
310/// Variable-length encoding (LEB128).
311pub struct Leb128<E: ByteOrder = LittleEndian>(PhantomData<E>);
312
313impl<E: ByteOrder> BinaryFormat for Leb128<E> {
314    fn read_u16<R: Read>(reader: &mut R) -> Result<u16> {
315        Ok(read_u32_leb128(reader)? as u16)
316    }
317    fn write_u16<W: Write>(writer: &mut W, value: u16) -> Result<()> {
318        write_u32_leb128(writer, value as u32)
319    }
320    fn read_u32<R: Read>(reader: &mut R) -> Result<u32> {
321        read_u32_leb128(reader)
322    }
323    fn write_u32<W: Write>(writer: &mut W, value: u32) -> Result<()> {
324        write_u32_leb128(writer, value)
325    }
326    fn read_u64<R: Read>(reader: &mut R) -> Result<u64> {
327        read_u64_leb128(reader)
328    }
329    fn write_u64<W: Write>(writer: &mut W, value: u64) -> Result<()> {
330        write_u64_leb128(writer, value)
331    }
332    fn read_i16<R: Read>(reader: &mut R) -> Result<i16> {
333        Fixed::<E>::read_i16(reader)
334    }
335    fn write_i16<W: Write>(writer: &mut W, value: i16) -> Result<()> {
336        Fixed::<E>::write_i16(writer, value)
337    }
338    fn read_i32<R: Read>(reader: &mut R) -> Result<i32> {
339        read_i32_leb128(reader)
340    }
341    fn write_i32<W: Write>(writer: &mut W, value: i32) -> Result<()> {
342        write_i32_leb128(writer, value)
343    }
344    fn read_i64<R: Read>(reader: &mut R) -> Result<i64> {
345        read_i64_leb128(reader)
346    }
347    fn write_i64<W: Write>(writer: &mut W, value: i64) -> Result<()> {
348        write_i64_leb128(writer, value)
349    }
350    fn read_f32<R: Read>(reader: &mut R) -> Result<f32> {
351        Fixed::<E>::read_f32(reader)
352    }
353    fn write_f32<W: Write>(writer: &mut W, value: f32) -> Result<()> {
354        Fixed::<E>::write_f32(writer, value)
355    }
356    fn read_f64<R: Read>(reader: &mut R) -> Result<f64> {
357        Fixed::<E>::read_f64(reader)
358    }
359    fn write_f64<W: Write>(writer: &mut W, value: f64) -> Result<()> {
360        Fixed::<E>::write_f64(writer, value)
361    }
362}
363
364/// ZigZag transformation wrapper for signed integers.
365pub struct ZigZag<F: BinaryFormat>(PhantomData<F>);
366
367impl<F: BinaryFormat> BinaryFormat for ZigZag<F> {
368    fn read_u16<R: Read>(reader: &mut R) -> Result<u16> {
369        F::read_u16(reader)
370    }
371    fn write_u16<W: Write>(writer: &mut W, value: u16) -> Result<()> {
372        F::write_u16(writer, value)
373    }
374    fn read_u32<R: Read>(reader: &mut R) -> Result<u32> {
375        F::read_u32(reader)
376    }
377    fn write_u32<W: Write>(writer: &mut W, value: u32) -> Result<()> {
378        F::write_u32(writer, value)
379    }
380    fn read_u64<R: Read>(reader: &mut R) -> Result<u64> {
381        F::read_u64(reader)
382    }
383    fn write_u64<W: Write>(writer: &mut W, value: u64) -> Result<()> {
384        F::write_u64(writer, value)
385    }
386
387    fn read_i16<R: Read>(reader: &mut R) -> Result<i16> {
388        let val = F::read_u16(reader)?;
389        Ok(((val >> 1) as i16) ^ -((val & 1) as i16))
390    }
391    fn write_i16<W: Write>(writer: &mut W, value: i16) -> Result<()> {
392        let val = ((value << 1) ^ (value >> 15)) as u16;
393        F::write_u16(writer, val)
394    }
395
396    fn read_i32<R: Read>(reader: &mut R) -> Result<i32> {
397        let val = F::read_u32(reader)?;
398        Ok(((val >> 1) as i32) ^ -((val & 1) as i32))
399    }
400    fn write_i32<W: Write>(writer: &mut W, value: i32) -> Result<()> {
401        let val = ((value << 1) ^ (value >> 31)) as u32;
402        F::write_u32(writer, val)
403    }
404
405    fn read_i64<R: Read>(reader: &mut R) -> Result<i64> {
406        let val = F::read_u64(reader)?;
407        Ok(((val >> 1) as i64) ^ -((val & 1) as i64))
408    }
409    fn write_i64<W: Write>(writer: &mut W, value: i64) -> Result<()> {
410        let val = ((value << 1) ^ (value >> 63)) as u64;
411        F::write_u64(writer, val)
412    }
413
414    fn read_f32<R: Read>(reader: &mut R) -> Result<f32> {
415        F::read_f32(reader)
416    }
417    fn write_f32<W: Write>(writer: &mut W, value: f32) -> Result<()> {
418        F::write_f32(writer, value)
419    }
420    fn read_f64<R: Read>(reader: &mut R) -> Result<f64> {
421        F::read_f64(reader)
422    }
423    fn write_f64<W: Write>(writer: &mut W, value: f64) -> Result<()> {
424        F::write_f64(writer, value)
425    }
426}
427
428/// Read an i64 from LEB128 encoding.
429pub fn read_i64_leb128<R: Read>(reader: &mut R) -> Result<i64> {
430    let val = read_u64_leb128(reader)?;
431    Ok(((val >> 1) as i64) ^ -((val & 1) as i64))
432}
433
434/// Write an i64 to LEB128 encoding.
435pub fn write_i64_leb128<W: Write>(writer: &mut W, value: i64) -> Result<()> {
436    let val = ((value << 1) ^ (value >> 63)) as u64;
437    write_u64_leb128(writer, val)
438}
439
440/// Read a u32 from LEB128 encoding.
441pub fn read_u32_leb128<R: Read>(reader: &mut R) -> Result<u32> {
442    let mut result = 0;
443    let mut shift = 0;
444    loop {
445        let mut buf = [0u8; 1];
446        reader.read_exact(&mut buf).map_err(|_| GaiaError::truncated())?;
447        let byte = buf[0];
448        result |= ((byte & 0x7F) as u32) << shift;
449        if byte & 0x80 == 0 {
450            break;
451        }
452        shift += 7;
453    }
454    Ok(result)
455}
456
457/// Write a u32 to LEB128 encoding.
458pub fn write_u32_leb128<W: Write>(writer: &mut W, mut value: u32) -> Result<()> {
459    loop {
460        let mut byte = (value & 0x7F) as u8;
461        value >>= 7;
462        if value != 0 {
463            byte |= 0x80;
464        }
465        writer.write_all(&[byte]).map_err(|_| GaiaError::from(GaiaErrorKind::TruncatedData))?;
466        if value == 0 {
467            break;
468        }
469    }
470    Ok(())
471}
472
473/// Read a u64 from LEB128 encoding.
474pub fn read_u64_leb128<R: Read>(reader: &mut R) -> Result<u64> {
475    let mut result = 0;
476    let mut shift = 0;
477    loop {
478        let mut buf = [0u8; 1];
479        reader.read_exact(&mut buf).map_err(|_| GaiaError::truncated())?;
480        let byte = buf[0];
481        result |= ((byte & 0x7F) as u64) << shift;
482        if byte & 0x80 == 0 {
483            break;
484        }
485        shift += 7;
486    }
487    Ok(result)
488}
489
490/// Write a u64 to LEB128 encoding.
491pub fn write_u64_leb128<W: Write>(writer: &mut W, mut value: u64) -> Result<()> {
492    loop {
493        let mut byte = (value & 0x7F) as u8;
494        value >>= 7;
495        if value != 0 {
496            byte |= 0x80;
497        }
498        writer.write_all(&[byte]).map_err(|_| GaiaError::from(GaiaErrorKind::TruncatedData))?;
499        if value == 0 {
500            break;
501        }
502    }
503    Ok(())
504}
505
506/// Read an i32 from LEB128 encoding.
507pub fn read_i32_leb128<R: Read>(reader: &mut R) -> Result<i32> {
508    let val = read_u32_leb128(reader)?;
509    Ok(((val >> 1) as i32) ^ -((val & 1) as i32))
510}
511
512/// Write an i32 to LEB128 encoding.
513pub fn write_i32_leb128<W: Write>(writer: &mut W, value: i32) -> Result<()> {
514    let val = ((value << 1) ^ (value >> 31)) as u32;
515    write_u32_leb128(writer, val)
516}