#![warn(missing_docs)]
pub mod reader;
pub mod traits;
pub mod writer;
use gaia_types::{GaiaError, GaiaErrorKind, Result};
use std::{
io::{Read, Write},
marker::PhantomData,
};
pub use reader::BinaryReader;
pub use traits::BinaryFormat;
pub use writer::BinaryWriter;
#[derive(Debug)]
pub struct TrackingReader<R: Read> {
pub inner: R,
pub position: u64,
}
impl<R: Read> Read for TrackingReader<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let n = self.inner.read(buf)?;
self.position += n as u64;
Ok(n)
}
}
impl<R: Read + std::io::Seek> std::io::Seek for TrackingReader<R> {
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
self.position = self.inner.seek(pos)?;
Ok(self.position)
}
}
#[derive(Debug)]
pub struct TrackingWriter<W: Write> {
pub inner: W,
pub position: u64,
}
impl<W: Write + std::io::Seek> std::io::Seek for TrackingWriter<W> {
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
self.position = self.inner.seek(pos)?;
Ok(self.position)
}
}
impl<W: Write> Write for TrackingWriter<W> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let n = self.inner.write(buf)?;
self.position += n as u64;
Ok(n)
}
fn flush(&mut self) -> std::io::Result<()> {
self.inner.flush()
}
}
pub trait ByteOrder {
fn read_u16(buf: &[u8]) -> u16;
fn read_u32(buf: &[u8]) -> u32;
fn read_u64(buf: &[u8]) -> u64;
fn write_u16(buf: &mut [u8], n: u16);
fn write_u32(buf: &mut [u8], n: u32);
fn write_u64(buf: &mut [u8], n: u64);
}
pub struct BigEndian;
impl ByteOrder for BigEndian {
fn read_u16(buf: &[u8]) -> u16 {
u16::from_be_bytes(buf.try_into().unwrap())
}
fn read_u32(buf: &[u8]) -> u32 {
u32::from_be_bytes(buf.try_into().unwrap())
}
fn read_u64(buf: &[u8]) -> u64 {
u64::from_be_bytes(buf.try_into().unwrap())
}
fn write_u16(buf: &mut [u8], n: u16) {
buf.copy_from_slice(&n.to_be_bytes())
}
fn write_u32(buf: &mut [u8], n: u32) {
buf.copy_from_slice(&n.to_be_bytes())
}
fn write_u64(buf: &mut [u8], n: u64) {
buf.copy_from_slice(&n.to_be_bytes())
}
}
pub struct LittleEndian;
impl ByteOrder for LittleEndian {
fn read_u16(buf: &[u8]) -> u16 {
u16::from_le_bytes(buf.try_into().unwrap())
}
fn read_u32(buf: &[u8]) -> u32 {
u32::from_le_bytes(buf.try_into().unwrap())
}
fn read_u64(buf: &[u8]) -> u64 {
u64::from_le_bytes(buf.try_into().unwrap())
}
fn write_u16(buf: &mut [u8], n: u16) {
buf.copy_from_slice(&n.to_le_bytes())
}
fn write_u32(buf: &mut [u8], n: u32) {
buf.copy_from_slice(&n.to_le_bytes())
}
fn write_u64(buf: &mut [u8], n: u64) {
buf.copy_from_slice(&n.to_le_bytes())
}
}
pub struct Fixed<E: ByteOrder>(PhantomData<E>);
impl<E: ByteOrder> BinaryFormat for Fixed<E> {
fn read_u16<R: Read>(reader: &mut R) -> Result<u16> {
let mut buf = [0u8; 2];
reader.read_exact(&mut buf).map_err(|_| GaiaError::truncated())?;
Ok(E::read_u16(&buf))
}
fn write_u16<W: Write>(writer: &mut W, value: u16) -> Result<()> {
let mut buf = [0u8; 2];
E::write_u16(&mut buf, value);
writer.write_all(&buf).map_err(|_| GaiaErrorKind::TruncatedData.into())
}
fn read_u32<R: Read>(reader: &mut R) -> Result<u32> {
let mut buf = [0u8; 4];
reader.read_exact(&mut buf).map_err(|_| GaiaError::truncated())?;
Ok(E::read_u32(&buf))
}
fn write_u32<W: Write>(writer: &mut W, value: u32) -> Result<()> {
let mut buf = [0u8; 4];
E::write_u32(&mut buf, value);
writer.write_all(&buf).map_err(|_| GaiaError::truncated())
}
fn read_u64<R: Read>(reader: &mut R) -> Result<u64> {
let mut buf = [0u8; 8];
reader.read_exact(&mut buf).map_err(|_| GaiaError::truncated())?;
Ok(E::read_u64(&buf))
}
fn write_u64<W: Write>(writer: &mut W, value: u64) -> Result<()> {
let mut buf = [0u8; 8];
E::write_u64(&mut buf, value);
writer.write_all(&buf).map_err(|_| GaiaError::truncated())
}
fn read_i16<R: Read>(reader: &mut R) -> Result<i16> {
Ok(Self::read_u16(reader)? as i16)
}
fn write_i16<W: Write>(writer: &mut W, value: i16) -> Result<()> {
Self::write_u16(writer, value as u16)
}
fn read_i32<R: Read>(reader: &mut R) -> Result<i32> {
Ok(Self::read_u32(reader)? as i32)
}
fn write_i32<W: Write>(writer: &mut W, value: i32) -> Result<()> {
Self::write_u32(writer, value as u32)
}
fn read_i64<R: Read>(reader: &mut R) -> Result<i64> {
Ok(Self::read_u64(reader)? as i64)
}
fn write_i64<W: Write>(writer: &mut W, value: i64) -> Result<()> {
Self::write_u64(writer, value as u64)
}
fn read_f32<R: Read>(reader: &mut R) -> Result<f32> {
Ok(f32::from_bits(Self::read_u32(reader)?))
}
fn write_f32<W: Write>(writer: &mut W, value: f32) -> Result<()> {
Self::write_u32(writer, value.to_bits())
}
fn read_f64<R: Read>(reader: &mut R) -> Result<f64> {
Ok(f64::from_bits(Self::read_u64(reader)?))
}
fn write_f64<W: Write>(writer: &mut W, value: f64) -> Result<()> {
Self::write_u64(writer, value.to_bits())
}
}
pub trait ReadBytesExt: Read {
fn read_u16<T: ByteOrder>(&mut self) -> std::io::Result<u16> {
let mut buf = [0u8; 2];
self.read_exact(&mut buf)?;
Ok(T::read_u16(&buf))
}
fn read_u32<T: ByteOrder>(&mut self) -> std::io::Result<u32> {
let mut buf = [0u8; 4];
self.read_exact(&mut buf)?;
Ok(T::read_u32(&buf))
}
fn read_u64<T: ByteOrder>(&mut self) -> std::io::Result<u64> {
let mut buf = [0u8; 8];
self.read_exact(&mut buf)?;
Ok(T::read_u64(&buf))
}
fn read_i16<T: ByteOrder>(&mut self) -> std::io::Result<i16> {
Ok(self.read_u16::<T>()? as i16)
}
fn read_i32<T: ByteOrder>(&mut self) -> std::io::Result<i32> {
Ok(self.read_u32::<T>()? as i32)
}
fn read_i64<T: ByteOrder>(&mut self) -> std::io::Result<i64> {
Ok(self.read_u64::<T>()? as i64)
}
fn read_f32<T: ByteOrder>(&mut self) -> std::io::Result<f32> {
Ok(f32::from_bits(self.read_u32::<T>()?))
}
fn read_f64<T: ByteOrder>(&mut self) -> std::io::Result<f64> {
Ok(f64::from_bits(self.read_u64::<T>()?))
}
fn read_u8(&mut self) -> std::io::Result<u8> {
let mut buf = [0u8; 1];
self.read_exact(&mut buf)?;
Ok(buf[0])
}
fn read_i8(&mut self) -> std::io::Result<i8> {
Ok(self.read_u8()? as i8)
}
}
impl<R: Read + ?Sized> ReadBytesExt for R {}
pub trait WriteBytesExt: Write {
fn write_u16<T: ByteOrder>(&mut self, n: u16) -> std::io::Result<()> {
let mut buf = [0u8; 2];
T::write_u16(&mut buf, n);
self.write_all(&buf)
}
fn write_u32<T: ByteOrder>(&mut self, n: u32) -> std::io::Result<()> {
let mut buf = [0u8; 4];
T::write_u32(&mut buf, n);
self.write_all(&buf)
}
fn write_u64<T: ByteOrder>(&mut self, n: u64) -> std::io::Result<()> {
let mut buf = [0u8; 8];
T::write_u64(&mut buf, n);
self.write_all(&buf)
}
fn write_i16<T: ByteOrder>(&mut self, n: i16) -> std::io::Result<()> {
self.write_u16::<T>(n as u16)
}
fn write_i32<T: ByteOrder>(&mut self, n: i32) -> std::io::Result<()> {
self.write_u32::<T>(n as u32)
}
fn write_i64<T: ByteOrder>(&mut self, n: i64) -> std::io::Result<()> {
self.write_u64::<T>(n as u64)
}
fn write_f32<T: ByteOrder>(&mut self, n: f32) -> std::io::Result<()> {
self.write_u32::<T>(n.to_bits())
}
fn write_f64<T: ByteOrder>(&mut self, n: f64) -> std::io::Result<()> {
self.write_u64::<T>(n.to_bits())
}
fn write_u8(&mut self, n: u8) -> std::io::Result<()> {
self.write_all(&[n])
}
fn write_i8(&mut self, n: i8) -> std::io::Result<()> {
self.write_u8(n as u8)
}
}
impl<W: Write + ?Sized> WriteBytesExt for W {}
pub struct Leb128<E: ByteOrder = LittleEndian>(PhantomData<E>);
impl<E: ByteOrder> BinaryFormat for Leb128<E> {
fn read_u16<R: Read>(reader: &mut R) -> Result<u16> {
Ok(read_u32_leb128(reader)? as u16)
}
fn write_u16<W: Write>(writer: &mut W, value: u16) -> Result<()> {
write_u32_leb128(writer, value as u32)
}
fn read_u32<R: Read>(reader: &mut R) -> Result<u32> {
read_u32_leb128(reader)
}
fn write_u32<W: Write>(writer: &mut W, value: u32) -> Result<()> {
write_u32_leb128(writer, value)
}
fn read_u64<R: Read>(reader: &mut R) -> Result<u64> {
read_u64_leb128(reader)
}
fn write_u64<W: Write>(writer: &mut W, value: u64) -> Result<()> {
write_u64_leb128(writer, value)
}
fn read_i16<R: Read>(reader: &mut R) -> Result<i16> {
Fixed::<E>::read_i16(reader)
}
fn write_i16<W: Write>(writer: &mut W, value: i16) -> Result<()> {
Fixed::<E>::write_i16(writer, value)
}
fn read_i32<R: Read>(reader: &mut R) -> Result<i32> {
read_i32_leb128(reader)
}
fn write_i32<W: Write>(writer: &mut W, value: i32) -> Result<()> {
write_i32_leb128(writer, value)
}
fn read_i64<R: Read>(reader: &mut R) -> Result<i64> {
read_i64_leb128(reader)
}
fn write_i64<W: Write>(writer: &mut W, value: i64) -> Result<()> {
write_i64_leb128(writer, value)
}
fn read_f32<R: Read>(reader: &mut R) -> Result<f32> {
Fixed::<E>::read_f32(reader)
}
fn write_f32<W: Write>(writer: &mut W, value: f32) -> Result<()> {
Fixed::<E>::write_f32(writer, value)
}
fn read_f64<R: Read>(reader: &mut R) -> Result<f64> {
Fixed::<E>::read_f64(reader)
}
fn write_f64<W: Write>(writer: &mut W, value: f64) -> Result<()> {
Fixed::<E>::write_f64(writer, value)
}
}
pub struct ZigZag<F: BinaryFormat>(PhantomData<F>);
impl<F: BinaryFormat> BinaryFormat for ZigZag<F> {
fn read_u16<R: Read>(reader: &mut R) -> Result<u16> {
F::read_u16(reader)
}
fn write_u16<W: Write>(writer: &mut W, value: u16) -> Result<()> {
F::write_u16(writer, value)
}
fn read_u32<R: Read>(reader: &mut R) -> Result<u32> {
F::read_u32(reader)
}
fn write_u32<W: Write>(writer: &mut W, value: u32) -> Result<()> {
F::write_u32(writer, value)
}
fn read_u64<R: Read>(reader: &mut R) -> Result<u64> {
F::read_u64(reader)
}
fn write_u64<W: Write>(writer: &mut W, value: u64) -> Result<()> {
F::write_u64(writer, value)
}
fn read_i16<R: Read>(reader: &mut R) -> Result<i16> {
let val = F::read_u16(reader)?;
Ok(((val >> 1) as i16) ^ -((val & 1) as i16))
}
fn write_i16<W: Write>(writer: &mut W, value: i16) -> Result<()> {
let val = ((value << 1) ^ (value >> 15)) as u16;
F::write_u16(writer, val)
}
fn read_i32<R: Read>(reader: &mut R) -> Result<i32> {
let val = F::read_u32(reader)?;
Ok(((val >> 1) as i32) ^ -((val & 1) as i32))
}
fn write_i32<W: Write>(writer: &mut W, value: i32) -> Result<()> {
let val = ((value << 1) ^ (value >> 31)) as u32;
F::write_u32(writer, val)
}
fn read_i64<R: Read>(reader: &mut R) -> Result<i64> {
let val = F::read_u64(reader)?;
Ok(((val >> 1) as i64) ^ -((val & 1) as i64))
}
fn write_i64<W: Write>(writer: &mut W, value: i64) -> Result<()> {
let val = ((value << 1) ^ (value >> 63)) as u64;
F::write_u64(writer, val)
}
fn read_f32<R: Read>(reader: &mut R) -> Result<f32> {
F::read_f32(reader)
}
fn write_f32<W: Write>(writer: &mut W, value: f32) -> Result<()> {
F::write_f32(writer, value)
}
fn read_f64<R: Read>(reader: &mut R) -> Result<f64> {
F::read_f64(reader)
}
fn write_f64<W: Write>(writer: &mut W, value: f64) -> Result<()> {
F::write_f64(writer, value)
}
}
pub fn read_i64_leb128<R: Read>(reader: &mut R) -> Result<i64> {
let val = read_u64_leb128(reader)?;
Ok(((val >> 1) as i64) ^ -((val & 1) as i64))
}
pub fn write_i64_leb128<W: Write>(writer: &mut W, value: i64) -> Result<()> {
let val = ((value << 1) ^ (value >> 63)) as u64;
write_u64_leb128(writer, val)
}
pub fn read_u32_leb128<R: Read>(reader: &mut R) -> Result<u32> {
let mut result = 0;
let mut shift = 0;
loop {
let mut buf = [0u8; 1];
reader.read_exact(&mut buf).map_err(|_| GaiaError::truncated())?;
let byte = buf[0];
result |= ((byte & 0x7F) as u32) << shift;
if byte & 0x80 == 0 {
break;
}
shift += 7;
}
Ok(result)
}
pub fn write_u32_leb128<W: Write>(writer: &mut W, mut value: u32) -> Result<()> {
loop {
let mut byte = (value & 0x7F) as u8;
value >>= 7;
if value != 0 {
byte |= 0x80;
}
writer.write_all(&[byte]).map_err(|_| GaiaError::from(GaiaErrorKind::TruncatedData))?;
if value == 0 {
break;
}
}
Ok(())
}
pub fn read_u64_leb128<R: Read>(reader: &mut R) -> Result<u64> {
let mut result = 0;
let mut shift = 0;
loop {
let mut buf = [0u8; 1];
reader.read_exact(&mut buf).map_err(|_| GaiaError::truncated())?;
let byte = buf[0];
result |= ((byte & 0x7F) as u64) << shift;
if byte & 0x80 == 0 {
break;
}
shift += 7;
}
Ok(result)
}
pub fn write_u64_leb128<W: Write>(writer: &mut W, mut value: u64) -> Result<()> {
loop {
let mut byte = (value & 0x7F) as u8;
value >>= 7;
if value != 0 {
byte |= 0x80;
}
writer.write_all(&[byte]).map_err(|_| GaiaError::from(GaiaErrorKind::TruncatedData))?;
if value == 0 {
break;
}
}
Ok(())
}
pub fn read_i32_leb128<R: Read>(reader: &mut R) -> Result<i32> {
let val = read_u32_leb128(reader)?;
Ok(((val >> 1) as i32) ^ -((val & 1) as i32))
}
pub fn write_i32_leb128<W: Write>(writer: &mut W, value: i32) -> Result<()> {
let val = ((value << 1) ^ (value >> 31)) as u32;
write_u32_leb128(writer, val)
}