mirror of https://github.com/tildeio/helix
85 lines
2.2 KiB
Rust
85 lines
2.2 KiB
Rust
use super::{Class, ToRuby};
|
|
use std::{any, fmt};
|
|
use sys::{VALUE, SPRINTF_TO_S, c_string, rb_eRuntimeError, rb_raise};
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub struct Error {
|
|
class: Class,
|
|
message: ErrorMessage
|
|
}
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
enum ErrorMessage {
|
|
Static(c_string),
|
|
Dynamic(VALUE)
|
|
}
|
|
|
|
impl Error {
|
|
pub fn with_c_string(message: c_string) -> Error {
|
|
Error { class: unsafe { Class(rb_eRuntimeError) }, message: ErrorMessage::Static(message) }
|
|
}
|
|
|
|
pub fn with_value(message: VALUE) -> Error {
|
|
Error { class: unsafe { Class(rb_eRuntimeError) }, message: ErrorMessage::Dynamic(message) }
|
|
}
|
|
|
|
pub fn from_any(any: Box<any::Any>) -> Error {
|
|
any.downcast::<Error>()
|
|
.map(|e| *e)
|
|
.or_else(|any| any.downcast::<&str>().map(|e| e.to_error()))
|
|
.or_else(|any| any.downcast::<String>().map(|e| e.to_error()))
|
|
.unwrap_or_else(|any| format!("Unknown Error (caused by `{:?}`)", any).to_error())
|
|
}
|
|
|
|
pub fn with_class(self, class: Class) -> Error {
|
|
Error { class, message: self.message }
|
|
}
|
|
|
|
pub unsafe fn raise(self) -> ! {
|
|
match self.message {
|
|
ErrorMessage::Static(c_string) => rb_raise(self.class.to_value(), c_string),
|
|
ErrorMessage::Dynamic(value) => rb_raise(self.class.to_value(), SPRINTF_TO_S, value)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Error {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
match self.message {
|
|
ErrorMessage::Static(c_string) => {
|
|
use ::std::ffi::CStr;
|
|
write!(f, "{}", unsafe { CStr::from_ptr(c_string) }.to_str().unwrap())
|
|
},
|
|
ErrorMessage::Dynamic(value) => {
|
|
use super::FromRuby;
|
|
write!(f, "{}", String::from_ruby_unwrap(value))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
unsafe impl Send for Error {}
|
|
unsafe impl Sync for Error {}
|
|
|
|
pub trait ToError {
|
|
fn to_error(self) -> Error;
|
|
}
|
|
|
|
impl ToError for Error {
|
|
fn to_error(self) -> Error {
|
|
self
|
|
}
|
|
}
|
|
|
|
impl<'a> ToError for &'a str {
|
|
fn to_error(self) -> Error {
|
|
Error::with_value(self.to_ruby().unwrap())
|
|
}
|
|
}
|
|
|
|
impl ToError for String {
|
|
fn to_error(self) -> Error {
|
|
Error::with_value(self.to_ruby().unwrap())
|
|
}
|
|
}
|