pub mod blocking_impl {
use crate::{
base::Header,
element::Element,
functional::Encode,
master::{Cluster, Segment},
};
use std::io::{Read, Write};
pub trait ReadFrom: Sized {
fn read_from<R: Read>(r: &mut R) -> crate::Result<Self>;
}
pub trait ReadElement: Sized + Element {
fn read_element<R: Read>(header: &Header, r: &mut R) -> crate::Result<Self> {
let body = header.read_body(r)?;
Self::decode_body(&mut &body[..])
}
}
impl<T: Element> ReadElement for T {}
impl Header {
pub(crate) fn read_body<R: Read>(&self, r: &mut R) -> crate::Result<Vec<u8>> {
let size = if self.size.is_unknown && [Segment::ID, Cluster::ID].contains(&self.id) {
return Err(crate::Error::ElementBodySizeUnknown(self.id));
} else {
*self.size
};
let cap = size.min(4096) as usize;
let mut buf = Vec::with_capacity(cap);
let n = std::io::copy(&mut r.take(size), &mut buf)?;
if size != n {
return Err(crate::Error::OutOfBounds);
}
Ok(buf)
}
}
pub trait WriteTo {
fn write_to<W: Write>(&self, w: &mut W) -> crate::Result<()>;
}
impl<T: Encode> WriteTo for T {
fn write_to<W: Write>(&self, w: &mut W) -> crate::Result<()> {
let mut buf = vec![];
self.encode(&mut buf)?;
w.write_all(&buf)?;
Ok(())
}
}
}
#[cfg(feature = "tokio")]
#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
pub mod tokio_impl {
use crate::{
base::Header,
element::Element,
master::{Cluster, Segment},
};
use std::future::Future;
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt};
pub trait AsyncReadFrom: Sized {
fn async_read_from<R: tokio::io::AsyncRead + Unpin>(
r: &mut R,
) -> impl Future<Output = crate::Result<Self>>;
}
pub trait AsyncReadElement: Sized + Element {
fn async_read_element<R: tokio::io::AsyncRead + Unpin>(
header: &Header,
r: &mut R,
) -> impl std::future::Future<Output = crate::Result<Self>> {
async {
let body = header.read_body_tokio(r).await?;
Self::decode_body(&mut &body[..])
}
}
}
impl<T: Element> AsyncReadElement for T {}
pub trait AsyncWriteTo {
fn async_write_to<W: tokio::io::AsyncWrite + Unpin>(
&self,
w: &mut W,
) -> impl std::future::Future<Output = crate::Result<()>>;
}
impl<T: crate::functional::Encode> AsyncWriteTo for T {
async fn async_write_to<W: tokio::io::AsyncWrite + Unpin>(
&self,
w: &mut W,
) -> crate::Result<()> {
let mut buf = vec![];
self.encode(&mut buf)?;
Ok(w.write_all(&buf).await?)
}
}
impl Header {
pub(crate) async fn read_body_tokio<R: AsyncRead + Unpin>(
&self,
r: &mut R,
) -> crate::Result<Vec<u8>> {
let size = if self.size.is_unknown && [Segment::ID, Cluster::ID].contains(&self.id) {
return Err(crate::Error::ElementBodySizeUnknown(self.id));
} else {
*self.size
};
let cap = size.min(4096) as usize;
let mut buf = Vec::with_capacity(cap);
let n = tokio::io::copy(&mut r.take(size), &mut buf).await?;
if size != n {
return Err(crate::Error::OutOfBounds);
}
Ok(buf)
}
}
}