#![allow(dead_code)]
use super::{DataReaderTrait, DataWriterBlob};
use crate::{Blob, ByteRange};
use anyhow::{Result, ensure};
use async_trait::async_trait;
use std::io::{Cursor, Read};
use versatiles_derive::context;
#[derive(Debug)]
pub struct DataReaderBlob {
blob: Cursor<Vec<u8>>,
}
impl DataReaderBlob {
#[must_use]
pub fn len(&self) -> usize {
self.blob.get_ref().len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.blob.get_ref().len() == 0
}
}
#[async_trait]
impl DataReaderTrait for DataReaderBlob {
#[context("while reading range {range:?} from DataReaderBlob")]
async fn read_range(&self, range: &ByteRange) -> Result<Blob> {
let start = usize::try_from(range.offset).context("Offset too large for this platform")?;
let end = usize::try_from(range.offset + range.length).context("End offset too large for this platform")?;
let blob = self.blob.get_ref();
ensure!(
end <= blob.len(),
"end of range ({start}..{end}) is outside blob ({})",
blob.len()
);
Ok(Blob::from(&blob[start..end]))
}
#[context("while reading all data from DataReaderBlob")]
async fn read_all(&self) -> Result<Blob> {
Ok(Blob::from(self.blob.get_ref()))
}
fn get_name(&self) -> &'static str {
"memory"
}
}
impl Read for DataReaderBlob {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.blob.read(buf)
}
}
impl From<Box<DataWriterBlob>> for DataReaderBlob {
fn from(value: Box<DataWriterBlob>) -> Self {
DataReaderBlob::from(value.into_blob())
}
}
impl From<DataWriterBlob> for DataReaderBlob {
fn from(value: DataWriterBlob) -> Self {
DataReaderBlob::from(value.into_blob())
}
}
impl From<Blob> for DataReaderBlob {
fn from(value: Blob) -> Self {
DataReaderBlob {
blob: Cursor::new(value.into_vec()),
}
}
}
impl From<Vec<u8>> for DataReaderBlob {
fn from(value: Vec<u8>) -> Self {
DataReaderBlob {
blob: Cursor::new(value),
}
}
}
#[cfg(test)]
mod tests {
use super::{super::DataWriterTrait, *};
#[tokio::test]
async fn from_blob() -> Result<()> {
let blob = Blob::from(vec![0, 1, 2, 3, 4, 5, 6, 7]);
let data_reader = DataReaderBlob::from(blob.clone());
assert_eq!(data_reader.get_name(), "memory");
assert_eq!(data_reader.read_range(&ByteRange::new(0, 8)).await?, blob);
assert_eq!(
data_reader.read_range(&ByteRange::new(0, 4)).await?.as_slice(),
&blob.as_slice()[0..4]
);
assert!(data_reader.read_range(&ByteRange::new(0, 9)).await.is_err());
Ok(())
}
#[tokio::test]
async fn from_vec() -> Result<()> {
let data = vec![10, 20, 30, 40, 50, 60, 70, 80];
let data_reader = DataReaderBlob::from(data.clone());
assert_eq!(data_reader.get_name(), "memory");
assert_eq!(data_reader.len(), data.len());
let range = ByteRange::new(2, 4);
let result = data_reader.read_range(&range).await?;
assert_eq!(result.as_slice(), &data[2..6]);
Ok(())
}
#[tokio::test]
async fn from_data_writer_blob() -> Result<()> {
let data = [100u8, 101, 102, 103, 104, 105].as_slice();
let mut data_writer = DataWriterBlob::new()?;
data_writer.append(&Blob::from(data))?;
let data_reader: DataReaderBlob = data_writer.into();
assert_eq!(data_reader.get_name(), "memory");
assert_eq!(data_reader.len(), 6);
let range = ByteRange::new(0, 6);
let result = data_reader.read_range(&range).await?;
assert_eq!(result.as_slice(), data);
Ok(())
}
#[tokio::test]
async fn from_boxed_data_writer_blob() -> Result<()> {
let data = [100u8, 101, 102, 103, 104, 105].as_slice();
let mut data_writer = DataWriterBlob::new()?;
data_writer.append(&Blob::from(data))?;
let data_reader: DataReaderBlob = Box::new(data_writer).into();
assert_eq!(data_reader.get_name(), "memory");
assert_eq!(data_reader.len(), 6);
let range = ByteRange::new(0, 6);
let result = data_reader.read_range(&range).await?;
assert_eq!(result.as_slice(), data);
Ok(())
}
#[tokio::test]
async fn test_len() {
let data = vec![1, 2, 3, 4, 5];
let data_reader = DataReaderBlob::from(data.clone());
assert_eq!(data_reader.len(), data.len());
}
#[tokio::test]
async fn test_read() {
let data = vec![1, 2, 3, 4, 5];
let mut data_reader = DataReaderBlob::from(data);
let mut buffer = [0; 3];
let n = data_reader.read(&mut buffer).unwrap();
assert_eq!(n, 3);
assert_eq!(buffer, [1, 2, 3]);
let n = data_reader.read(&mut buffer).unwrap();
assert_eq!(n, 2);
assert_eq!(&buffer[..2], &[4, 5]);
}
#[tokio::test]
async fn test_read_range_edge_cases() -> Result<()> {
let data = vec![10, 20, 30, 40, 50, 60, 70, 80];
let data_reader = DataReaderBlob::from(data);
assert!(data_reader.read_range(&ByteRange::new(8, 1)).await.is_err());
assert!(data_reader.read_range(&ByteRange::new(6, 3)).await.is_err());
Ok(())
}
}