use std::collections::HashMap;
use std::ops::Range;
use std::sync::Arc;
use vfs::VfsError;
use vfs::error::VfsErrorKind;
use crate::data::idx_vfs::Prime;
#[derive(Debug, Default, Clone)]
pub struct BytesPkgSource {
volumes: HashMap<String, Arc<[u8]>>,
}
impl BytesPkgSource {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, volume: impl Into<String>, data: impl Into<Arc<[u8]>>) {
self.volumes.insert(volume.into(), data.into());
}
pub fn from_volumes<N, D>(volumes: impl IntoIterator<Item = (N, D)>) -> Self
where
N: Into<String>,
D: Into<Arc<[u8]>>,
{
let mut src = Self::new();
for (name, data) in volumes {
src.insert(name, data);
}
src
}
}
#[derive(Clone, Debug)]
pub struct BytesSlice {
data: Arc<[u8]>,
range: Range<usize>,
}
impl AsRef<[u8]> for BytesSlice {
fn as_ref(&self) -> &[u8] {
&self.data[self.range.clone()]
}
}
impl Prime for BytesPkgSource {
fn prime_volume(&self, volume: &str, range: Range<usize>) -> Result<impl AsRef<[u8]>, VfsError> {
let data = self.volumes.get(volume).ok_or_else(|| VfsError::from(VfsErrorKind::FileNotFound))?;
if range.end > data.len() {
return Err(VfsError::from(VfsErrorKind::Other(format!(
"range {}..{} exceeds volume {volume} length {}",
range.start,
range.end,
data.len()
))));
}
Ok(BytesSlice { data: Arc::clone(data), range })
}
}
#[cfg(feature = "async_vfs")]
#[async_trait::async_trait]
impl crate::data::idx_vfs::AsyncPrime for BytesPkgSource {
async fn prime_volume(&self, volume: &str, range: Range<usize>) -> Result<impl AsRef<[u8]>, VfsError> {
Prime::prime_volume(self, volume, range)
}
}