use std::io::Result as IoResult;
use std::mem::MaybeUninit;
use zerocopy::Immutable;
use zerocopy::IntoBytes;
#[cfg(target_endian = "little")]
mod le;
#[cfg(target_endian = "little")]
pub use le::*;
#[cfg(target_endian = "big")]
mod be;
#[cfg(target_endian = "big")]
pub use be::*;
use crate::RespHeader;
mod private {
pub trait RSealed {}
impl<R> RSealed for R where R: std::io::Read {}
pub trait WSealed {}
impl<W> WSealed for W where W: std::io::Write {}
}
pub trait ReadFromDescriptorChain: private::RSealed {
fn read_obj<T: VmediaType>(&mut self) -> std::io::Result<T>;
}
impl<R> ReadFromDescriptorChain for R
where
R: std::io::Read,
{
fn read_obj<T: VmediaType>(&mut self) -> std::io::Result<T> {
let mut obj: MaybeUninit<LeWrapper<T>> = std::mem::MaybeUninit::zeroed();
let slice = unsafe {
std::slice::from_raw_parts_mut(obj.as_mut_ptr() as *mut u8, std::mem::size_of::<T>())
};
self.read_exact(slice)?;
Ok(unsafe { obj.assume_init() }.into_native())
}
}
pub trait WriteToDescriptorChain: private::WSealed {
fn write_obj<T: VmediaType>(&mut self, obj: T) -> IoResult<()>;
fn write_response<T: VmediaType>(&mut self, response: T) -> IoResult<()> {
self.write_obj(response)
}
fn write_err_response(&mut self, code: libc::c_int) -> IoResult<()> {
self.write_response(RespHeader::err(code))
}
}
impl<W> WriteToDescriptorChain for W
where
W: std::io::Write,
{
fn write_obj<T: VmediaType>(&mut self, obj: T) -> IoResult<()> {
self.write_all(obj.to_le().as_bytes())
}
}
#[repr(transparent)]
pub struct LeWrapper<T: VmediaType>(T);
impl<T: VmediaType> LeWrapper<T> {
pub fn into_native(self) -> T {
T::from_le(self)
}
}
unsafe impl<T: VmediaType> Immutable for LeWrapper<T> {
fn only_derive_is_allowed_to_implement_this_trait() {}
}
unsafe impl<T: VmediaType> IntoBytes for LeWrapper<T> {
fn only_derive_is_allowed_to_implement_this_trait()
where
Self: Sized,
{
}
}