use std::fmt;
use wasm_bindgen::prelude::JsValue;
pub enum Error {
Empty,
String(String),
Js(JsValue),
Native(NativeError),
}
pub enum NativeError {
Canvas2dContext,
WebGlContext,
WebGlProgram,
WebGlCanvas,
Window,
WindowWidth,
WindowHeight,
WebGlBufferSourceOneNonZero,
CanvasCreate,
AttributeLocation(Option<String>),
UniformLocation(Option<String>),
MipsPowerOf2,
NoExtension,
MissingShaderProgram,
NoCreateBuffer,
NoExistingBuffer,
NoCreateTexture,
MissingTexture,
MissingTextureSampler(Option<String>),
MissingBuffer,
UniformSize,
UniformMatrixMustBeFloat,
UniformType,
UniformBufferName,
UniformBufferParameter,
UniformBufferMissing(Option<String>),
UniformBufferOffsetMissing(Option<(String, String)>),
UniformBufferTarget,
VertexArrayMissing,
VertexArrayCreate,
JsValueExpectedBool,
JsValueExpectedNumber,
WebGl1TextureArray2d,
WebGl1Texture3d,
WebGl1TextureOffsetNonZero,
TextureCubeFaceNotCube,
TextureMissingCubeFace,
NoTextureTarget,
Internal,
}
impl Error {
pub fn to_js(self: &Self) -> JsValue {
match self {
Error::Empty => JsValue::null(),
Error::String(s) => JsValue::from_str(&s[..]),
Error::Js(jval) => jval.clone(),
Error::Native(err) => JsValue::from_str(err.to_string().as_str()),
}
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self {
Error::Empty => write!(f, "empty error"),
_ => write!(
f,
"{}",
self.to_js()
.as_string()
.unwrap_or("unknown error".to_string())
),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self {
Error::Empty => write!(f, "empty error"),
_ => write!(
f,
"{}",
self.to_js()
.as_string()
.unwrap_or("unknown error".to_string())
),
}
}
}
impl NativeError {
pub fn default_str(self: &Self) -> &'static str {
match self {
NativeError::Canvas2dContext => "couldn't create 2d canvas context",
NativeError::WebGlContext => "couldn't create webgl context",
NativeError::WebGlProgram => "couldn't create webgl program",
NativeError::WebGlCanvas => "couldn't get canvas from webgl context",
NativeError::Window => "couldn't get window",
NativeError::WindowWidth => "couldn't get window width",
NativeError::WindowHeight => "couldn't get window height",
NativeError::CanvasCreate => "Couldn't create canvas",
NativeError::AttributeLocation(_optional_name) => "Couldn't get attribute location",
NativeError::UniformLocation(_optional_name) => "Couldn't get uniform location",
NativeError::MipsPowerOf2 => "mipmapping requires that textures be power of 2",
NativeError::NoExtension => "extension not found",
NativeError::NoCreateBuffer => "couldn't create buffer",
NativeError::NoExistingBuffer => "no existing buffer",
NativeError::MissingShaderProgram => "No shader program activated",
NativeError::NoCreateTexture => "unable to create texture",
NativeError::MissingTexture => "couldn't get texture",
NativeError::MissingTextureSampler(_optional_name) => "couldn't get texture sampler",
NativeError::MissingBuffer => "couldn't get buffer",
NativeError::VertexArrayMissing => "no such vertex array",
NativeError::VertexArrayCreate => "unable to create vertex array",
NativeError::UniformMatrixMustBeFloat => "uniform matrix must be floats",
NativeError::UniformType => "wrong uniform type",
NativeError::UniformSize => "uniform data is not large enough",
NativeError::UniformBufferName => "couldn't get uniform block name",
NativeError::UniformBufferParameter => "couldn't get uniform block parameter",
NativeError::UniformBufferMissing(_optional_name) => "uniform buffer is missing",
NativeError::UniformBufferOffsetMissing(_optional_name) => {
"uniform buffer offset is missing"
}
NativeError::UniformBufferTarget => {
"buffer target must be UniformBuffer for uniform buffers"
}
NativeError::WebGlBufferSourceOneNonZero => {
"webgl 1 only supports sub buffer uploads from 0"
}
NativeError::WebGl1TextureOffsetNonZero => {
"webgl 1 only supports texture uploads from offset 0"
}
NativeError::WebGl1TextureArray2d => "webgl 1 doesn't support 2d texture arrays",
NativeError::WebGl1Texture3d => "webgl 1 doesn't support 3d textures",
NativeError::JsValueExpectedBool => "expected jsvalue to be a bool",
NativeError::JsValueExpectedNumber => "expected jsvalue to be a number",
NativeError::NoTextureTarget => {
"texture target must be known (call assign before activate)"
}
NativeError::TextureCubeFaceNotCube => "texture cube face is set but not cube target",
NativeError::TextureMissingCubeFace => "texture cube face missing for cube target",
NativeError::Internal => "internal error",
}
}
pub fn to_string(self: &Self) -> String {
match self {
NativeError::AttributeLocation(optional_name) => match optional_name {
None => self.default_str().to_string(),
Some(name) => format!("couldn't get attribute location named {}", name.as_str()),
},
NativeError::UniformLocation(optional_name) => match optional_name {
None => self.default_str().to_string(),
Some(name) => format!("couldn't get uniform location named {}", name.as_str()),
},
NativeError::UniformBufferMissing(optional_name) => match optional_name {
None => self.default_str().to_string(),
Some(name) => format!("couldn't get uniform buffer named {}", name.as_str()),
},
NativeError::UniformBufferOffsetMissing(optional_name) => match optional_name {
None => self.default_str().to_string(),
Some((block_name, uniform_name)) => format!(
"couldn't get offset for uniform named {} in buffer named {}",
uniform_name,
block_name.as_str()
),
},
NativeError::MissingTextureSampler(optional_name) => match optional_name {
None => self.default_str().to_string(),
Some(name) => format!("couldn't get texture sampler named {}", name.as_str()),
},
_ => self.default_str().to_string(),
}
}
}
impl From<Error> for JsValue {
fn from(err: Error) -> Self {
err.to_js()
}
}
impl From<NativeError> for Error {
fn from(err: NativeError) -> Self {
Error::Native(err)
}
}
impl From<JsValue> for Error {
fn from(err: JsValue) -> Self {
Error::Js(err)
}
}
impl From<js_sys::Error> for Error {
fn from(err: js_sys::Error) -> Self {
Error::Js(JsValue::from(err))
}
}
impl From<String> for Error {
fn from(err: String) -> Self {
Error::String(err)
}
}
impl From<&str> for Error {
fn from(err: &str) -> Self {
Error::String(String::from(err))
}
}