gloss_utils/
io.rs

1//from https://github.com/takahirox/wgpu-rust-renderer/blob/main/src/utils/file_loader.rs#L10
2pub struct FileLoader {}
3
4// Non-Wasm
5#[cfg(not(target_arch = "wasm32"))]
6use std::fs::File;
7
8#[cfg(not(target_arch = "wasm32"))]
9impl FileLoader {
10    /// # Panics
11    /// Will panic if the path cannot be opened
12    #[allow(clippy::unused_async)] //we want to maintain the same code signature as the wasm version which needs
13                                   // async
14    pub async fn open(file_path: &str) -> File {
15        File::open(file_path).unwrap()
16    }
17}
18
19// Wasm
20#[cfg(target_arch = "wasm32")]
21use {
22    std::io::Cursor,
23    wasm_bindgen::JsCast,
24    wasm_bindgen_futures::JsFuture,
25    web_sys::{Request, RequestInit, RequestMode, Response},
26};
27
28// @TODO: Proper error handling
29#[cfg(target_arch = "wasm32")]
30impl FileLoader {
31    pub async fn open(file_path: &str) -> Cursor<Vec<u8>> {
32        let result = fetch_as_binary(file_path).await.unwrap();
33        Cursor::new(result)
34    }
35}
36
37// @TODO: Proper error handling
38#[cfg(target_arch = "wasm32")]
39pub async fn fetch_as_binary(url: &str) -> Result<Vec<u8>, String> {
40    let mut opts = RequestInit::new();
41    #[allow(deprecated)]
42    opts.method("GET");
43    #[allow(deprecated)]
44    opts.mode(RequestMode::Cors); // @TODO: Should be able to opt-out
45
46    let request = match Request::new_with_str_and_init(&url, &opts) {
47        Ok(request) => request,
48        Err(_e) => return Err("Failed to create request".to_string()),
49    };
50
51    let window = web_sys::window().unwrap();
52    let response = match JsFuture::from(window.fetch_with_request(&request)).await {
53        Ok(response) => response,
54        Err(_e) => return Err("Failed to fetch".to_string()),
55    };
56
57    let response: Response = match response.dyn_into() {
58        Ok(response) => response,
59        Err(_e) => return Err("Failed to dyn_into Response".to_string()),
60    };
61
62    let buffer = match response.array_buffer() {
63        Ok(buffer) => buffer,
64        Err(_e) => return Err("Failed to get as array buffer".to_string()),
65    };
66
67    let buffer = match JsFuture::from(buffer).await {
68        Ok(buffer) => buffer,
69        Err(_e) => return Err("Failed to ...?".to_string()),
70    };
71
72    Ok(js_sys::Uint8Array::new(&buffer).to_vec())
73}
74
75// https://www.reddit.com/r/rust/comments/11hcyv4/best_way_of_associating_enums_with_values/jav1kgf/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button
76/// associating a extension with a enum
77use strum::IntoEnumIterator;
78use strum_macros::EnumIter;
79#[derive(Debug, EnumIter)]
80pub enum FileType {
81    Obj,
82    Ply,
83    Unknown,
84}
85impl FileType {
86    pub fn value(&self) -> &'static [&'static str] {
87        match self {
88            Self::Obj => &["obj"],
89            Self::Ply => &["ply"],
90            // Self::Ply => &["ply"],
91            Self::Unknown => &[""],
92        }
93    }
94    pub fn find_match(ext: &str) -> Self {
95        Self::iter()
96            .find(|filetype| filetype.value().contains(&(ext.to_lowercase()).as_str()))
97            .unwrap_or(FileType::Unknown)
98    }
99}