feat: Add synchronous binary reading utilities
This commit is contained in:
parent
78eb25368c
commit
d1ff738098
3 changed files with 161 additions and 0 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -73,6 +73,12 @@ version = "0.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c"
|
checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
|
@ -628,6 +634,7 @@ checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
||||||
name = "sdk"
|
name = "sdk"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"csv-async",
|
"csv-async",
|
||||||
"futures",
|
"futures",
|
||||||
|
|
|
@ -4,6 +4,7 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
byteorder = "1.4.3"
|
||||||
color-eyre = "0.6.2"
|
color-eyre = "0.6.2"
|
||||||
csv-async = { version = "1.2.4", features = ["tokio", "serde"] }
|
csv-async = { version = "1.2.4", features = ["tokio", "serde"] }
|
||||||
futures = "0.3.25"
|
futures = "0.3.25"
|
||||||
|
|
|
@ -152,3 +152,156 @@ where
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod sync {
|
||||||
|
use std::io::{self, Read, Seek, SeekFrom, Write};
|
||||||
|
|
||||||
|
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||||
|
use color_eyre::eyre::WrapErr;
|
||||||
|
use color_eyre::{Help, Result, SectionExt};
|
||||||
|
|
||||||
|
macro_rules! make_read {
|
||||||
|
($func:ident, $read:ident, $type:ty) => {
|
||||||
|
fn $read(&mut self) -> io::Result<$type> {
|
||||||
|
ReadBytesExt::$func::<LittleEndian>(&mut self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn $func(&mut self) -> Result<$type> {
|
||||||
|
let res = ReadExt::$read(&mut self)
|
||||||
|
.wrap_err(concat!("failed to read ", stringify!($type)));
|
||||||
|
|
||||||
|
if res.is_ok() {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
let pos = self.stream_position();
|
||||||
|
if pos.is_ok() {
|
||||||
|
res.with_section(|| {
|
||||||
|
format!("{pos:#X} ({pos})", pos = pos.unwrap()).header("Position: ")
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! make_write {
|
||||||
|
($func:ident, $write:ident, $type:ty) => {
|
||||||
|
fn $write(&mut self, val: $type) -> io::Result<()> {
|
||||||
|
WriteBytesExt::$func::<LittleEndian>(&mut self, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn $func(&mut self, val: $type) -> Result<()> {
|
||||||
|
let res = WriteExt::$write(&mut self, val)
|
||||||
|
.wrap_err(concat!("failed to write ", stringify!($type)));
|
||||||
|
|
||||||
|
if res.is_ok() {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
let pos = self.stream_position();
|
||||||
|
if pos.is_ok() {
|
||||||
|
res.with_section(|| {
|
||||||
|
format!("{pos:#X} ({pos})", pos = pos.unwrap()).header("Position: ")
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! make_skip {
|
||||||
|
($func:ident, $read:ident, $type:ty) => {
|
||||||
|
fn $func(&mut self, cmp: $type) -> Result<()> {
|
||||||
|
let val = ReadExt::$read(&mut self)?;
|
||||||
|
|
||||||
|
if val != cmp {
|
||||||
|
let pos = self.stream_position().unwrap_or(u64::MAX);
|
||||||
|
tracing::debug!(
|
||||||
|
pos,
|
||||||
|
expected = cmp,
|
||||||
|
actual = val,
|
||||||
|
"Unexpected value for skipped {}",
|
||||||
|
stringify!($type)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ReadExt: ReadBytesExt + Seek {
|
||||||
|
fn read_u8(&mut self) -> io::Result<u8> {
|
||||||
|
ReadBytesExt::read_u8(&mut self)
|
||||||
|
}
|
||||||
|
|
||||||
|
make_read!(read_u32, read_u32_le, u32);
|
||||||
|
make_read!(read_u64, read_u64_le, u64);
|
||||||
|
|
||||||
|
make_skip!(skip_u8, read_u8, u8);
|
||||||
|
make_skip!(skip_u32, read_u32, u32);
|
||||||
|
|
||||||
|
fn skip_padding(&mut self) -> io::Result<()> {
|
||||||
|
let pos = self.stream_position()?;
|
||||||
|
let padding_size = 16 - (pos % 16);
|
||||||
|
|
||||||
|
if padding_size < 16 && padding_size > 0 {
|
||||||
|
tracing::trace!(pos, padding_size, "Skipping padding");
|
||||||
|
self.seek(SeekFrom::Current(padding_size as i64))?;
|
||||||
|
} else {
|
||||||
|
tracing::trace!(pos, padding_size, "No padding to skip");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait WriteExt: WriteBytesExt + Seek {
|
||||||
|
make_write!(write_u32, write_u32_le, u32);
|
||||||
|
make_write!(write_u64, write_u64_le, u64);
|
||||||
|
|
||||||
|
fn write_padding(&mut self) -> io::Result<usize> {
|
||||||
|
let pos = self.stream_position()?;
|
||||||
|
let size = 16 - (pos % 16) as usize;
|
||||||
|
|
||||||
|
tracing::trace!(padding_size = size, "Writing padding");
|
||||||
|
|
||||||
|
if size > 0 && size < 16 {
|
||||||
|
let buf = vec![0; size];
|
||||||
|
self.write_all(&buf)?;
|
||||||
|
Ok(size)
|
||||||
|
} else {
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: ReadBytesExt + Seek + ?Sized> ReadExt for R {}
|
||||||
|
impl<W: WriteBytesExt + Seek + ?Sized> WriteExt for W {}
|
||||||
|
|
||||||
|
pub(crate) fn _read_up_to<R>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
|
||||||
|
where
|
||||||
|
R: Read + Seek,
|
||||||
|
{
|
||||||
|
let pos = r.stream_position()?;
|
||||||
|
|
||||||
|
let err = {
|
||||||
|
match r.read_exact(buf) {
|
||||||
|
Ok(_) => return Ok(buf.len()),
|
||||||
|
Err(err) if err.kind() == std::io::ErrorKind::UnexpectedEof => {
|
||||||
|
r.seek(SeekFrom::Start(pos))?;
|
||||||
|
match r.read_to_end(buf) {
|
||||||
|
Ok(read) => return Ok(read),
|
||||||
|
Err(err) => err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => err,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Err(err).with_section(|| format!("{pos:#X} ({pos})", pos = pos).header("Position: "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue