use thiserror::Error;
#[derive(Error, Debug)]
pub enum AudioInitError {
#[error("RaylibAudio cannot be instantiated more then once at a time")]
DoubleInit,
#[error("failed to initialize audio device")]
InitFailed,
}
#[derive(Error, Debug)]
pub enum ExportWaveError {
#[error("wave data must be 16 bit per sample for QOA format export (actual: {0})")]
QoaBadSamples(i32),
#[error("failed to export wave data")]
ExportFailed,
}
#[derive(Error, Debug)]
pub enum LoadSoundError {
#[error("failed to load sound\npath: {path:?}")]
LoadFailed {
path: String,
},
#[error("failed to load sound from wave")]
LoadFromWaveFailed,
#[error("cannot load wave\npath: {path:?}")]
LoadWaveFromFileFailed {
path: String,
},
#[error("wave data is null, check provided buffer data")]
Null,
#[error("music could not be loaded from file\npath: {path:?}")]
LoadMusicFromFileFailed {
path: String,
},
#[error("music's buffer data is null, check provided buffer data")]
MusicNull,
}
#[derive(Error, Debug)]
pub enum UpdateAudioStreamError {
#[error("update data format must match sound: expected {expected} bits, got {provided} bits")]
SampleSizeMismatch {
expected: usize,
provided: usize,
},
#[error("Attempting to write too many frames to buffer: provided {provided}, max {max}")]
TooManyFrames {
max: usize,
provided: usize,
},
#[error(
"AudioStream's callback slot is already in use; call unset_audio_stream_callback() to clear it"
)]
CallbackSlotBusy,
}
#[derive(Error, Debug)]
pub enum AllocationError {
#[error("memory request exceeds capacity")]
NullAlloc,
#[error("memory request in bytes exceeds unsigned integer maximum")]
IntoUIntFailed,
#[error("requested zero bytes of memory")]
ZeroBytes,
}
#[derive(Error, Debug)]
pub enum InvalidMeshError {
#[error("mesh should have 3 indices/vertices for each triangle")]
TrianglePointMiscount,
#[error("indices should be within the number of vertices")]
IndexOutOfBounds,
#[error("mesh with indices should not exceed u16::MAX vertices")]
VertexUnindexible(std::num::TryFromIntError),
#[error("mesh should have one texcoord per vertex")]
TexcoordsMiscount,
#[error("mesh with texcoords2 should have one per vertex")]
Texcoords2Miscount,
#[error("mesh with normals should have one per vertex")]
NormalsMiscount,
#[error("mesh with tangents should have one per vertex")]
TangentsMiscount,
#[error("mesh with colors should have one per vertex")]
ColorsMiscount,
}
#[derive(Error, Debug)]
pub enum GenMeshError {
#[error("provided mesh data does not correspond to a valid mesh")]
InvalidMesh(#[from] InvalidMeshError),
#[error("could not allocate memory for the mesh data")]
Allocation(#[from] AllocationError),
}
#[derive(Error, Debug)]
pub enum CompressionError {
#[error("could not compress data")]
CompressionFailed,
}
#[derive(Error, Debug)]
pub enum Base64Error {
#[error("could not decode base64 data")]
DecodeFailed,
#[error("could not encode base64 data")]
EncodeFailed,
}
#[derive(Error, Debug)]
pub enum LoadModelError {
#[error("could not load model\npath: {path:?}")]
LoadFromFileFailed {
path: String,
},
#[error("could not load model from mesh")]
LoadFromMeshFailed,
}
#[derive(Error, Debug)]
pub enum LoadModelAnimError {
#[error("no model animations loaded\npath: {path:?}")]
NoAnimationsLoaded {
path: String,
},
}
#[derive(Error, Debug)]
pub enum SetMaterialError {
#[error("mesh_id greater than mesh count")]
MeshIdOutOfBounds,
#[error("material_id greater than material count")]
MaterialIdOutOfBounds,
}
#[derive(Error, Debug)]
pub enum LoadMaterialError {
#[error("no materials loaded\npath: {path:?}")]
NoneLoaded {
path: String,
},
}
#[derive(Error, Debug)]
pub enum LoadFontError {
#[error(
"error loading font; check if the file exists and if it's the right type\npath: {path:?}"
)]
LoadFromFileFailed {
path: String,
},
#[error("error loading font from image")]
LoadFromImageFailed,
#[error("error loading font from memory; check if the file's type is correct")]
LoadFromMemoryFailed,
}
#[derive(Error, Debug)]
pub enum InvalidImageError {
#[error("invalid image: width is 0")]
ZeroWidth,
#[error("invalid image: height is 0")]
ZeroHeight,
#[error("invalid image: data is null")]
NullData,
#[error("image data is null, either the file doesnt exist or the image type is unsupported")]
NullDataFromFile,
#[error("invalid file data")]
InvalidFile,
#[error("image data is null, check provided buffer data")]
NullDataFromMemory,
#[error("failed to retrieve pixel data")]
NullDataFromTexture,
#[error("unsupported format")]
UnsupportedFormat,
#[error("convolution kernel must be square to be applied")]
NonSquareKernel,
}
#[derive(Error, Debug)]
pub enum UpdateTextureError {
#[error("data is wrong size (expected {expect} bytes, got {actual})")]
WrongDataSize {
expect: usize,
actual: usize,
},
#[error("destination rectangle cannot exceed texture bounds")]
OutOfBounds,
#[error("destination rectangle cannot have negative extents")]
NegativeSize,
}
#[derive(Error, Debug)]
pub enum LoadTextureError {
#[error("failed to load the texture\npath: {path:?}")]
TextureFromFileFailed {
path: String,
},
#[error("failed to load image as a texture cubemap")]
CubemapFromImageFailed,
#[error("failed to load image as a texture")]
TextureFromImageFailed,
#[error("failed to create render texture")]
CreateRenderTextureFailed,
#[error("data is not valid to load texture")]
InvalidData,
}
#[derive(Error, Debug)]
pub enum RaylibError {
#[error("audio initialization error")]
AudioInit(#[from] AudioInitError),
#[error("wave export error")]
ExportWave(#[from] ExportWaveError),
#[error("sound loading error")]
LoadSound(#[from] LoadSoundError),
#[error("allocation error")]
Allocation(#[from] AllocationError),
#[error("compression error")]
Compression(#[from] CompressionError),
#[error("model loading error")]
LoadModel(#[from] LoadModelError),
#[error("model animation loading error")]
LoadModelAnim(#[from] LoadModelAnimError),
#[error("material update error")]
SetMaterial(#[from] SetMaterialError),
#[error("material loading error")]
LoadMaterial(#[from] LoadMaterialError),
#[error("font loading error")]
LoadFont(#[from] LoadFontError),
#[error("image error")]
InvalidImage(#[from] InvalidImageError),
#[error("texture update error")]
UpdateTexture(#[from] UpdateTextureError),
#[error("texture loading error")]
LoadTexture(#[from] LoadTextureError),
}
#[derive(Debug, thiserror::Error)]
pub enum LoadIconsError {
#[error("icons file not found: {0:?}")]
FileNotFound(std::path::PathBuf),
#[error("icons file too short: need >=12 bytes for header, got {0}")]
HeaderTruncated(usize),
#[error("invalid .rgi signature: expected 'rGI ', got {0:?}")]
InvalidSignature([u8; 4]),
#[error("unsupported icon size: expected {expected}, got {actual}")]
UnsupportedIconSize {
expected: u16,
actual: u16,
},
#[error("too many icons: max {max}, got {actual}")]
TooManyIcons {
max: u16,
actual: u16,
},
#[error("data length {0} overflows i32")]
LengthOverflow(usize),
#[error(transparent)]
Io(#[from] std::io::Error),
}
#[derive(Debug, thiserror::Error)]
pub enum LoadStyleFromMemoryError {
#[error("data length {0} overflows i32")]
LengthOverflow(usize),
}
#[cfg(test)]
mod load_icons_error_tests {
use super::*;
use std::path::PathBuf;
#[test]
fn load_icons_error_variants_display() {
let err = LoadIconsError::FileNotFound(PathBuf::from("a.rgi"));
assert!(err.to_string().contains("a.rgi"));
let err = LoadIconsError::HeaderTruncated(7);
assert_eq!(
err.to_string(),
"icons file too short: need >=12 bytes for header, got 7"
);
let err = LoadIconsError::InvalidSignature(*b"XXXX");
assert!(err.to_string().contains("expected 'rGI '"));
let err = LoadIconsError::UnsupportedIconSize {
expected: 16,
actual: 32,
};
assert_eq!(
err.to_string(),
"unsupported icon size: expected 16, got 32"
);
let err = LoadIconsError::TooManyIcons {
max: 256,
actual: 300,
};
assert_eq!(err.to_string(), "too many icons: max 256, got 300");
let err = LoadIconsError::LengthOverflow(usize::MAX);
assert!(err.to_string().contains("overflows i32"));
}
#[test]
fn load_style_from_memory_error_display() {
let err = LoadStyleFromMemoryError::LengthOverflow(usize::MAX);
assert!(err.to_string().contains("overflows i32"));
}
#[test]
fn load_icons_error_io_from_impl() {
let io_err = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "denied");
let err: LoadIconsError = io_err.into();
assert!(err.to_string().contains("denied"));
assert!(matches!(err, LoadIconsError::Io(_)));
}
}