loading_bytes/
lib.rs

1//! Abstraction over loading bytes on WASM or other.
2use snafu::prelude::*;
3
4/// Enumeration of all errors this library may result in.
5#[derive(Debug, Snafu)]
6pub enum LoadingBytesError {
7    #[snafu(display("loading '{path}' by WASM error: {msg:#?}"))]
8    Wasm {
9        path: String,
10        msg: wasm_bindgen::JsValue,
11    },
12    #[snafu(display("loading '{path}' by filesystem from CWD '{}' error: {source}", cwd.display()))]
13    Fs {
14        path: String,
15        cwd: std::path::PathBuf,
16        source: std::io::Error,
17    },
18}
19
20/// Load the file at the given url fragment or path and return it as a vector of bytes, if
21/// possible.
22pub async fn load(path: &str) -> Result<Vec<u8>, LoadingBytesError> {
23    #[cfg(target_arch = "wasm32")]
24    {
25        use wasm_bindgen::JsCast;
26
27        let path = path.to_string();
28        let mut opts = web_sys::RequestInit::new();
29        opts.method("GET");
30        let request = web_sys::Request::new_with_str_and_init(&path, &opts).map_err(|msg| {
31            LoadingBytesError::Wasm {
32                path: path.clone(),
33                msg,
34            }
35        })?;
36        let window = web_sys::window().unwrap();
37        let resp_value = wasm_bindgen_futures::JsFuture::from(window.fetch_with_request(&request))
38            .await
39            .map_err(|msg| LoadingBytesError::Wasm {
40                path: path.clone(),
41                msg,
42            })?;
43        let resp: web_sys::Response =
44            resp_value
45                .dyn_into()
46                .map_err(|msg| LoadingBytesError::Wasm {
47                    path: path.clone(),
48                    msg,
49                })?;
50        let array_promise = resp.array_buffer().map_err(|msg| LoadingBytesError::Wasm {
51            path: path.clone(),
52            msg,
53        })?;
54        let buffer = wasm_bindgen_futures::JsFuture::from(array_promise)
55            .await
56            .map_err(|msg| LoadingBytesError::Wasm {
57                path: path.clone(),
58                msg,
59            })?;
60        assert!(buffer.is_instance_of::<js_sys::ArrayBuffer>());
61        let array: js_sys::Uint8Array = js_sys::Uint8Array::new(&buffer);
62        let mut bytes: Vec<u8> = vec![0; array.length() as usize];
63        array.copy_to(&mut bytes);
64        Ok(bytes)
65    }
66    #[cfg(not(target_arch = "wasm32"))]
67    {
68        let bytes: Vec<u8> = async_fs::read(path).await.with_context(|_| FsSnafu {
69            path: path.to_string(),
70            cwd: std::env::current_dir().unwrap(),
71        })?;
72        Ok(bytes)
73    }
74}