use wasm_bindgen::prelude::*;
#[derive(Clone, Debug)]
pub struct ApiError(JsValue);
pub type ApiResult<T> = Result<T, ApiError>;
impl From<ApiError> for JsValue {
fn from(err: ApiError) -> Self {
err.0
}
}
impl From<JsValue> for ApiError {
fn from(err: JsValue) -> Self {
Self(err)
}
}
macro_rules! define_api_error {
( $($t:ty),* ) => {
$(
impl From<$t> for ApiError {
fn from(err: $t) -> Self {
ApiError(JsValue::from(format!("{}", err)))
}
}
)*
}
}
define_api_error!(
serde_json::Error,
serde_wasm_bindgen::Error,
std::io::Error,
rmp_serde::encode::Error,
rmp_serde::decode::Error,
&str,
String,
futures::channel::oneshot::Canceled,
base64::DecodeError,
chrono::ParseError
);
pub trait ToApiError<T> {
fn into_apierror(self) -> ApiResult<T>;
fn as_apierror(&self) -> Result<&T, ApiError>;
}
impl<T> ToApiError<T> for Option<T> {
fn into_apierror(self) -> ApiResult<T> {
self.ok_or_else(|| "Unwrap on None".into())
}
fn as_apierror(&self) -> Result<&T, ApiError> {
self.as_ref().ok_or_else(|| "Unwrap on None".into())
}
}
impl ToApiError<JsValue> for Result<(), ApiResult<JsValue>> {
fn into_apierror(self) -> ApiResult<JsValue> {
self.map_or_else(|x| x, |()| Ok(JsValue::UNDEFINED))
}
fn as_apierror(&self) -> Result<&JsValue, ApiError> {
self.as_ref().map_or_else(
|x| match x {
Ok(ref x) => Ok(x),
Err(err) => Err(err.clone()),
},
|()| Ok(js_intern::js_intern!("test")),
)
}
}