pub mod debug;
pub mod file;
#[cfg(target_arch = "wasm32")]
pub mod wasm;
#[cfg(not(target_arch = "wasm32"))]
use crate::file::FileChunkReader;
#[cfg(target_arch = "wasm32")]
use crate::wasm::HttpWasmChunkReader;
use async_trait::async_trait;
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ResourceId(String);
impl ResourceId {
pub fn new(id: impl Into<String>) -> Self {
Self(id.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl From<String> for ResourceId {
fn from(s: String) -> Self {
Self(s)
}
}
impl From<&str> for ResourceId {
fn from(s: &str) -> Self {
Self(s.to_string())
}
}
#[derive(Debug)]
pub enum ChunkReaderError {
ResourceNotFound(ResourceId),
HttpError(u16),
IoError {
resource: ResourceId,
source: std::io::Error,
},
}
impl std::error::Error for ChunkReaderError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
ChunkReaderError::IoError { source, .. } => Some(source),
_ => None,
}
}
}
impl fmt::Display for ChunkReaderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ResourceNotFound(id) => write!(f, "resource not found: {}", id.as_str()),
Self::HttpError(code) => write!(f, "HTTP error: {}", code),
Self::IoError { resource, source } => {
write!(f, "IO error for resource {}: {}", resource.as_str(), source)
}
}
}
}
impl From<std::io::Error> for ChunkReaderError {
fn from(error: std::io::Error) -> Self {
Self::IoError {
resource: ResourceId::new(""),
source: error,
}
}
}
#[async_trait(?Send)]
pub trait ChunkReader {
async fn fetch_octets(&self, id: ResourceId) -> Result<Vec<u8>, ChunkReaderError>;
}
#[must_use]
pub fn get_platform_reader(path: &str) -> Box<dyn ChunkReader> {
#[cfg(not(target_arch = "wasm32"))]
return Box::new(FileChunkReader::new(path));
#[cfg(target_arch = "wasm32")]
return Box::new(HttpWasmChunkReader::new(path));
}