use std::path::PathBuf;
#[derive(Debug)]
#[non_exhaustive]
pub enum AssetError {
MissingUuid { source: String },
ImageDecode {
path: PathBuf,
source: image::ImageError,
},
ObjLoad {
path: PathBuf,
source: tobj::LoadError,
},
ObjEmpty { path: PathBuf },
ObjIndexOutOfRange {
path: PathBuf,
kind: ObjIndexKind,
index: usize,
len: usize,
},
GltfImport {
path: PathBuf,
source: gltf::Error,
},
ZeroDimensionTexture {
cache_key: String,
width: u32,
height: u32,
},
Fetch { url: String, message: String },
HeightmapTooSmall {
path: PathBuf,
width: u32,
height: u32,
},
RgbaSizeMismatch {
cache_key: String,
got: usize,
expected: usize,
width: u32,
height: u32,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum ObjIndexKind {
Position,
Normal,
TexCoord,
}
impl std::fmt::Display for ObjIndexKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
ObjIndexKind::Position => "position",
ObjIndexKind::Normal => "normal",
ObjIndexKind::TexCoord => "texcoord",
};
f.write_str(s)
}
}
impl std::fmt::Display for AssetError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AssetError::MissingUuid { source } => {
write!(f, "missing UUID reference: {source}")
}
AssetError::ImageDecode { path, .. } => {
write!(f, "cannot read texture ({})", path.display())
}
AssetError::ObjLoad { path, .. } => {
write!(f, "OBJ load failed ({})", path.display())
}
AssetError::ObjEmpty { path } => {
write!(f, "OBJ file contains no models: {}", path.display())
}
AssetError::ObjIndexOutOfRange {
path,
kind,
index,
len,
} => write!(
f,
"OBJ ({}): {kind} index {index} out of range (len={len})",
path.display()
),
AssetError::GltfImport { path, .. } => {
write!(f, "glTF import failed ({})", path.display())
}
AssetError::Fetch { url, message } => {
write!(f, "fetch failed for '{url}': {message}")
}
AssetError::HeightmapTooSmall {
path,
width,
height,
} => write!(
f,
"heightmap must be at least 2x2 to build terrain: {}x{} ({})",
width,
height,
path.display()
),
AssetError::ZeroDimensionTexture {
cache_key,
width,
height,
} => write!(
f,
"cannot create texture with zero dimension: {width}x{height} (key={cache_key})"
),
AssetError::RgbaSizeMismatch {
cache_key,
got,
expected,
width,
height,
} => write!(
f,
"RGBA size mismatch for '{cache_key}': got {got} bytes, expected {expected} ({width}x{height}x4)"
),
}
}
}
impl std::error::Error for AssetError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
AssetError::ImageDecode { source, .. } => Some(source),
AssetError::ObjLoad { source, .. } => Some(source),
AssetError::GltfImport { source, .. } => Some(source),
_ => None,
}
}
}