use crate::Id;
use bytes::Bytes;
#[derive(Clone, Debug)]
pub struct Blob {
id: Id,
data: Bytes,
}
impl Blob {
pub fn compute(data: impl Into<Bytes>) -> Self {
let data = data.into();
Self {
id: Id::of(&data),
data,
}
}
pub fn new(id: Id, data: impl Into<Bytes>) -> Self {
Self {
id,
data: data.into(),
}
}
pub fn id(&self) -> &Id {
&self.id
}
pub fn len(&self) -> u64 {
self.data.len() as _
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
#[cfg(feature = "std")]
pub fn read(&self) -> BlobReader {
BlobReader(self.data.clone())
}
}
#[cfg(feature = "std")]
#[derive(Clone, Debug)]
pub struct BlobReader(Bytes);
#[cfg(feature = "std")]
impl futures_io::AsyncRead for BlobReader {
fn poll_read(
self: core::pin::Pin<&mut Self>,
_cx: &mut core::task::Context<'_>,
buf: &mut [u8],
) -> core::task::Poll<std::io::Result<usize>> {
let this = self.get_mut();
let n = this.0.len().min(buf.len());
let chunk = this.0.split_to(n);
buf[..n].copy_from_slice(&chunk);
core::task::Poll::Ready(Ok(n))
}
}
#[cfg(feature = "tokio")]
impl tokio::io::AsyncRead for BlobReader {
fn poll_read(
self: core::pin::Pin<&mut Self>,
_cx: &mut core::task::Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> core::task::Poll<std::io::Result<()>> {
let this = self.get_mut();
let n = this.0.len().min(buf.remaining());
let chunk = this.0.split_to(n);
buf.put_slice(&chunk);
core::task::Poll::Ready(Ok(()))
}
}