use std::future::Future;
use crate::error::CopcError;
pub trait ByteSource {
fn read_range(
&self,
offset: u64,
length: u64,
) -> impl Future<Output = Result<Vec<u8>, CopcError>>;
fn size(&self) -> impl Future<Output = Result<Option<u64>, CopcError>>;
fn read_ranges(
&self,
ranges: &[(u64, u64)],
) -> impl Future<Output = Result<Vec<Vec<u8>>, CopcError>> {
async move {
let mut results = Vec::with_capacity(ranges.len());
for &(offset, length) in ranges {
results.push(self.read_range(offset, length).await?);
}
Ok(results)
}
}
}
impl ByteSource for Vec<u8> {
async fn read_range(&self, offset: u64, length: u64) -> Result<Vec<u8>, CopcError> {
let start = offset as usize;
let end = start + length as usize;
if end > self.len() {
return Err(CopcError::Io(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
format!(
"read_range({offset}, {length}) out of bounds (size {})",
self.len()
),
)));
}
Ok(self[start..end].to_vec())
}
async fn size(&self) -> Result<Option<u64>, CopcError> {
Ok(Some(self.len() as u64))
}
}
impl ByteSource for &[u8] {
async fn read_range(&self, offset: u64, length: u64) -> Result<Vec<u8>, CopcError> {
let start = offset as usize;
let end = start + length as usize;
if end > self.len() {
return Err(CopcError::Io(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
format!(
"read_range({offset}, {length}) out of bounds (size {})",
self.len()
),
)));
}
Ok(self[start..end].to_vec())
}
async fn size(&self) -> Result<Option<u64>, CopcError> {
Ok(Some(self.len() as u64))
}
}