//! Error types and conversion functions. use std::error::Error; use std::fmt; use std::string::FromUtf8Error; use std::sync::mpsc::SendError; use std::sync::{Arc, PoisonError}; /// An enum containing all kinds of game framework errors. #[derive(Debug, Clone)] pub enum GameError { /// An error in the filesystem layout FilesystemError(String), /// An error in the config file ConfigError(String), /// Happens when an `winit::EventsLoopProxy` attempts to /// wake up an `winit::EventsLoop` that no longer exists. EventLoopError(String), /// An error trying to load a resource, such as getting an invalid image file. ResourceLoadError(String), /// Unable to find a resource; the `Vec` is the paths it searched for and associated errors ResourceNotFound(String, Vec<(std::path::PathBuf, GameError)>), /// Something went wrong in the renderer RenderError(String), /// Something went wrong in the audio playback AudioError(String), /// Something went wrong trying to set or get window properties. WindowError(String), /// Something went wrong trying to read from a file IOError(Arc), /// Something went wrong trying to load/render a font FontError(String), /// Something went wrong applying video settings. VideoError(String), /// Something went wrong compiling shaders ShaderProgramError(String), /// Something went wrong with the `gilrs` gamepad-input library. GamepadError(String), /// Something went wrong with the `lyon` shape-tesselation library. LyonError(String), /// Something went wrong while parsing something. ParseError(String), /// Something went wrong while converting a value. InvalidValue(String), /// Something went wrong while executing a debug command line command. CommandLineError(String), /// Something went wrong while initializing logger LoggerError(String), } impl fmt::Display for GameError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { GameError::ConfigError(ref s) => write!(f, "Config error: {}", s), GameError::ResourceLoadError(ref s) => write!(f, "Error loading resource: {}", s), GameError::ResourceNotFound(ref s, ref paths) => { write!(f, "Resource not found: {}, searched in paths {:?}", s, paths) } GameError::WindowError(ref e) => write!(f, "Window creation error: {}", e), _ => write!(f, "GameError {:?}", self), } } } impl Error for GameError { fn cause(&self) -> Option<&dyn Error> { match self { GameError::IOError(e) => Some(e as &dyn Error), _ => None, } } } /// A convenient result type consisting of a return type and a `GameError` pub type GameResult = Result; impl From for GameError { fn from(e: std::io::Error) -> GameError { GameError::IOError(Arc::new(e)) } } impl From for GameError { fn from(e: image::ImageError) -> GameError { let errstr = format!("Image load error: {}", e); GameError::ResourceLoadError(errstr) } } impl From for GameError { fn from(e: FromUtf8Error) -> Self { let errstr = format!("UTF-8 decoding error: {:?}", e); GameError::ConfigError(errstr) } } impl From for GameError { fn from(e: serde_json::Error) -> Self { let errstr = format!("JSON error: {:?}", e); GameError::ParseError(errstr) } } #[cfg(target_os = "android")] impl From for GameError { fn from(e: jni::errors::Error) -> GameError { GameError::WindowError(e.to_string()) } } impl From for GameError { fn from(s: strum::ParseError) -> GameError { let errstr = format!("Strum parse error: {}", s); GameError::ParseError(errstr) } } impl From for GameError { fn from(s: cpal::DefaultStreamConfigError) -> GameError { let errstr = format!("Default stream config error: {}", s); GameError::AudioError(errstr) } } impl From for GameError { fn from(s: cpal::PlayStreamError) -> GameError { let errstr = format!("Play stream error: {}", s); GameError::AudioError(errstr) } } impl From for GameError { fn from(s: cpal::BuildStreamError) -> GameError { let errstr = format!("Build stream error: {}", s); GameError::AudioError(errstr) } } impl From> for GameError { fn from(s: PoisonError) -> GameError { let errstr = format!("Poison error: {}", s); GameError::EventLoopError(errstr) } } impl From> for GameError { fn from(s: SendError) -> GameError { let errstr = format!("Send error: {}", s); GameError::EventLoopError(errstr) } } impl From for GameError { fn from(s: log::SetLoggerError) -> GameError { let errstr = format!("Set logger error: {}", s); GameError::LoggerError(errstr) } }