use std::error::Error;
use std::convert::From;
use core::any::TypeId;
#[doc(hidden)]
pub mod macros;
pub type Borkable<T> = Result<T, Box<dyn BorkChain>>;
pub trait BorkWith<T>{
fn bork_with(self, e: Box<dyn BorkChain>) -> Result<T, Box<dyn BorkChain>>;
}
pub trait BorkWithMsg{
fn msg(m: &'static str) -> Box<Self> where Self: Sized + BorkChain;
}
pub trait BorkNoMsg{
fn no_msg() -> Box<Self> where Self: Sized + BorkChain;
}
pub trait BorkChain: 'static + Send + Sync{
fn chain(&mut self, cause: Box<dyn BorkChain>)-> &dyn BorkChain;
fn name(&self) -> String;
fn cause(&self) -> Option<&'static dyn BorkChain>;
fn new() -> Option<Box<Self>> where Self: Sized + BorkChain;
fn __private_get_type_id__(&self) -> TypeId{
TypeId::of::<Self>()
}
}
impl std::fmt::Debug for dyn BorkChain {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "BorkChain (name: {name}, cause: {cause:?})",
name = self.name(),
cause = self.cause())
}
}
impl std::fmt::Display for dyn BorkChain{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let cause_str = match self.cause(){
Some(c) => format!(" => Cause: [{}]", c),
None => "".to_string(),
};
write!(f, "Error: {name}{cause_str}",
name = self.name(),
cause_str = cause_str)
}
}
impl Error for dyn BorkChain{}
impl <E: Error + 'static + Send + Sync> From<E> for Box<dyn BorkChain>{
fn from(e: E)-> Self{
return Box::new(e);
}
}
impl <T, E: Error + 'static + Send + Sync> BorkWith<T> for Result<T, E> where Box<dyn BorkChain>: From<E> {
fn bork_with(self, mut e: Box<dyn BorkChain>) -> Result<T, Box<dyn BorkChain>>{
match self{
Ok(v) => return Ok(v),
Err(prev_err) => {
e.chain(prev_err.into());
return Err(e);
},
}
}
}
impl <T> BorkWith<T> for Result<T, Box<dyn BorkChain>>{
fn bork_with(self, mut e: Box<dyn BorkChain>) -> Result<T, Box<dyn BorkChain>>{
match self{
Ok(v) => return Ok(v),
Err(prev_err) => {
e.chain(prev_err);
return Err(e);
},
}
}
}
impl BorkChain for Box<dyn BorkChain>{
fn chain(&mut self, cause: Box<dyn BorkChain>)-> &dyn BorkChain{
return (**self).chain(cause);
}
fn name(&self) -> String{
return (**self).name();
}
fn new() -> Option<Box<Self>>{
return None;
}
fn cause(&self) -> Option<&'static dyn BorkChain>{
return (**self).cause();
}
}
impl<E: Error + 'static + Send + Sync> BorkChain for E{
fn chain(&mut self, _cause: Box<dyn BorkChain>)-> &dyn BorkChain{
return self;
}
fn name(&self) -> String{
return format!("{}", self);
}
fn new() -> Option<Box<Self>>{
return None;
}
fn cause(&self) -> Option<&'static dyn BorkChain>{None}
}
impl dyn BorkChain{
pub fn downcast_ref<T: BorkChain>(&self) ->Option<&T>{
if self.__private_get_type_id__() == TypeId::of::<T>(){
return unsafe{
Some(&*(self as *const dyn BorkChain as *const T))
};
}
else{
return None;
}
}
}
#[derive(Debug)]
pub struct BaseBork{
pub name: String,
pub cause: Option<Box<dyn BorkChain>>,
}
impl std::error::Error for BaseBork{}
unsafe impl Send for BaseBork {}
unsafe impl Sync for BaseBork {}
impl std::fmt::Display for BaseBork {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name)
}
}
impl BorkWithMsg for BaseBork{
fn msg(m: &'static str) -> Box<Self>{
return Box::new(Self {name: m.into(), cause: None});
}
}
impl BorkNoMsg for BaseBork{
fn no_msg() -> Box<Self>{
return Self::new().unwrap();
}
}
#[cfg(test)]
mod tests;