chunk_reader/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/piot/swamp-render
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5
6//! A platform-agnostic chunk reader implementation that provides different backends
7//! for file system and WebAssembly environments.
8//!
9//! This crate provides a unified interface for reading chunks of data from either
10//! the local filesystem or via HTTP when running in a WebAssembly environment.
11
12pub mod debug;
13pub mod file;
14#[cfg(target_arch = "wasm32")]
15pub mod wasm;
16
17#[cfg(not(target_arch = "wasm32"))]
18use crate::file::FileChunkReader;
19#[cfg(target_arch = "wasm32")]
20use crate::wasm::HttpWasmChunkReader;
21
22use async_trait::async_trait;
23use std::fmt;
24
25#[derive(Debug, Clone, PartialEq, Eq, Hash)]
26pub struct ResourceId(String);
27
28impl ResourceId {
29    pub fn new(id: impl Into<String>) -> Self {
30        Self(id.into())
31    }
32
33    pub fn as_str(&self) -> &str {
34        &self.0
35    }
36}
37
38impl From<String> for ResourceId {
39    fn from(s: String) -> Self {
40        Self(s)
41    }
42}
43
44impl From<&str> for ResourceId {
45    fn from(s: &str) -> Self {
46        Self(s.to_string())
47    }
48}
49
50#[derive(Debug)]
51pub enum ChunkReaderError {
52    ResourceNotFound(ResourceId),
53    HttpError(u16),
54    IoError {
55        resource: ResourceId,
56        source: std::io::Error,
57    },
58}
59
60impl std::error::Error for ChunkReaderError {
61    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
62        match self {
63            ChunkReaderError::IoError { source, .. } => Some(source),
64            _ => None,
65        }
66    }
67}
68
69impl fmt::Display for ChunkReaderError {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        match self {
72            Self::ResourceNotFound(id) => write!(f, "resource not found: {}", id.as_str()),
73            Self::HttpError(code) => write!(f, "HTTP error: {}", code),
74            Self::IoError { resource, source } => {
75                write!(f, "IO error for resource {}: {}", resource.as_str(), source)
76            }
77        }
78    }
79}
80
81impl From<std::io::Error> for ChunkReaderError {
82    fn from(error: std::io::Error) -> Self {
83        Self::IoError {
84            resource: ResourceId::new(""),
85            source: error,
86        }
87    }
88}
89
90/// Trait for reading chunks of data from a source.
91///
92/// This trait provides a platform-agnostic way to read data chunks, with different
93/// implementations for file system and WebAssembly environments.
94#[async_trait(?Send)]
95pub trait ChunkReader {
96    /// Fetches a chunk of data from the specified resource.
97    ///
98    /// # Arguments
99    /// * `id` - The identifier for the resource to read
100    ///
101    /// # Returns
102    /// * `Ok(Vec<u8>)` - The bytes read from the resource
103    /// * `Err(ChunkReaderError)` - If the read operation fails
104    async fn fetch_octets(&self, id: ResourceId) -> Result<Vec<u8>, ChunkReaderError>;
105}
106
107/// Creates a new platform-specific chunk reader.
108///
109/// Returns a file-based reader for native platforms and an HTTP-based reader for WebAssembly.
110///
111/// # Arguments
112/// * `path` - The base path for the reader
113#[must_use]
114pub fn get_platform_reader(path: &str) -> Box<dyn ChunkReader> {
115    #[cfg(not(target_arch = "wasm32"))]
116    return Box::new(FileChunkReader::new(path));
117    #[cfg(target_arch = "wasm32")]
118    return Box::new(HttpWasmChunkReader::new(path));
119}