tools: add read/write convenience helpers

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2019-04-25 10:49:33 +00:00
parent d98c9a7a38
commit 897982e237
3 changed files with 95 additions and 0 deletions

View File

@ -31,6 +31,8 @@ pub mod tty;
pub mod signalfd;
pub mod daemon;
pub mod procfs;
pub mod read;
pub mod write;
mod process_locker;
pub use process_locker::*;

50
src/tools/read.rs Normal file
View File

@ -0,0 +1,50 @@
//! Utility traits for types which implement `std::io::Read` to quickly read primitively typed
//! values such as binary integers from a stream.
use std::io;
use std::mem;
use endian_trait::Endian;
pub trait ReadUtilOps {
/// Read a value of type `T`.
/// Note that it *should* be `repr(C, packed)` or similar.
fn read_value<T>(&mut self) -> io::Result<T>;
/// Read a big-endian value of type `T`.
/// Note that it *should* be `repr(C, packed)` or similar.
fn read_value_be<T: Endian>(&mut self) -> io::Result<T> {
Ok(self.read_value::<T>()?.from_be())
}
/// Read a little-endian value of type `T`.
/// Note that it *should* be `repr(C, packed)` or similar.
fn read_value_le<T: Endian>(&mut self) -> io::Result<T> {
Ok(self.read_value::<T>()?.from_le())
}
/// Read an exact number of bytes into a newly allocated vector.
fn read_exact_allocated(&mut self, size: usize) -> io::Result<Vec<u8>>;
}
impl<R: io::Read> ReadUtilOps for R {
fn read_value<T>(&mut self) -> io::Result<T> {
let mut data: T = unsafe { mem::uninitialized() };
self.read_exact(unsafe {
std::slice::from_raw_parts_mut(
&mut data as *mut T as *mut u8,
mem::size_of::<T>(),
)
})?;
Ok(data)
}
fn read_exact_allocated(&mut self, size: usize) -> io::Result<Vec<u8>> {
let mut out = Vec::with_capacity(size);
unsafe {
out.set_len(size);
}
self.read_exact(&mut out)?;
Ok(out)
}
}

43
src/tools/write.rs Normal file
View File

@ -0,0 +1,43 @@
//! Utility traits for types which implement `std::io::Write` to easily write primitively typed
//! values such as binary integers to a stream.
use std::io;
use std::mem;
use endian_trait::Endian;
pub trait WriteUtilOps {
/// Write a value of type `T`.
/// Note that it *should* be `repr(C, packed)` or similar.
fn write_value<T>(&mut self, value: &T) -> io::Result<usize>;
/// Write a big-endian value of type `T`.
/// Note that it *should* be `repr(C, packed)` or similar.
fn write_value_be<T: Endian>(&mut self, value: T) -> io::Result<usize> {
self.write_value(&value.to_be())
}
/// Write a little-endian value of type `T`.
/// Note that it *should* be `repr(C, packed)` or similar.
fn write_value_le<T: Endian>(&mut self, value: T) -> io::Result<usize> {
self.write_value(&value.to_le())
}
/// Convenience `write_all()` alternative returning the length instead of `()`.
fn write_all_len(&mut self, value: &[u8]) -> io::Result<usize>;
}
impl<R: io::Write> WriteUtilOps for R {
fn write_value<T>(&mut self, value: &T) -> io::Result<usize> {
let size = mem::size_of::<T>();
self.write_all(unsafe {
std::slice::from_raw_parts(value as *const T as *const u8, size)
})?;
Ok(size)
}
fn write_all_len(&mut self, value: &[u8]) -> io::Result<usize> {
self.write_all(value)?;
Ok(value.len())
}
}