use base64::Engine; use thiserror::Error; use std::io; #[derive(Error, Debug)] pub enum UriReadError { #[error("IOError: '{0}'")] IoError(io::Error), // From is implemented for this field in each loader module #[error("Base64 decoding error: '{0}'")] Base64Decode(base64::DecodeError), #[error("Some data was missing from the uri")] None } /// Read a buffer's uri string into a byte buffer. /// /// * `containing_path`: The path of the containing folder of the buffers "parent", /// the parent being where this buffer is defined in, /// i.e. parent="resources/models/player.gltf", containing="reousrce/models" pub(crate) fn gltf_read_buffer_uri(containing_path: &str, uri: &str) -> Result, UriReadError> { let uri = uri.strip_prefix("data").ok_or(UriReadError::None)?; let (mime, data) = uri.split_once(",").ok_or(UriReadError::None)?; let (_mime, is_base64) = match mime.strip_suffix(";base64") { Some(mime) => (mime, true), None => (mime, false), }; if is_base64 { base64::engine::general_purpose::STANDARD.decode(data).map_err(|e| UriReadError::Base64Decode(e)) } else { let full_path = format!("{containing_path}/{data}"); std::fs::read(&full_path).map_err(|e| UriReadError::IoError(e)) } }