parent
e5c3f0deb0
commit
f79f186dc5
@ -0,0 +1,152 @@
|
||||
//! Error handling, reporting and propagating.
|
||||
//!
|
||||
//! Allows us to take advantage of `Result<T,E>` and interop idiomatic Rust error reporing with the ffi C functions' error reporting.
|
||||
//! Functions returning or constructing `GHOST_TSuccess` will be able to be taken advantage of to be propagated and reported better.
|
||||
//!
|
||||
//! See [`GhostResult`] for more information.
|
||||
use super::*;
|
||||
use std::{
|
||||
error,
|
||||
fmt,
|
||||
};
|
||||
|
||||
/// A result that returns potentially an error. In the form of `GHOST_TSuccess`.
|
||||
///
|
||||
/// # Usage
|
||||
/// Its function is to provide more ergonomic error handling for Rust code, while still being able to easily interface with the C code.
|
||||
/// # Propagating
|
||||
/// Can be used to use `?` operator on functions returning `GHOST_TSuccess`.
|
||||
///
|
||||
/// When building on nightly, the following is possible.
|
||||
/// ```
|
||||
/// # use ghost::{error::GhostResult, c::GHOST_TSuccess};
|
||||
/// extern "C" {fn returns_tsuccess() -> GHOST_TSuccess;}
|
||||
///
|
||||
/// fn try_things_internal() -> GHOST_TSuccess
|
||||
/// {
|
||||
/// unsafe {
|
||||
/// returns_tsuccess()?;
|
||||
/// }
|
||||
///
|
||||
/// GHOST_TSuccess::Success
|
||||
/// }
|
||||
///
|
||||
/// fn caller()
|
||||
/// {
|
||||
/// match try_things_internal() {
|
||||
/// GHOST_TSuccess::Success => println!("Yay!"),
|
||||
/// GHOST_TSuccess::Failure => panic!("Fug"),
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// On stable, it must be rewritten a bit differently, however:
|
||||
///
|
||||
/// ```
|
||||
/// # use ghost::{error::GhostResult, c::GHOST_TSuccess};
|
||||
/// extern "C" {fn returns_tsuccess() -> GHOST_TSuccess;}
|
||||
///
|
||||
/// fn try_things_internal() -> GhostResult
|
||||
/// {
|
||||
/// unsafe {
|
||||
/// returns_tsuccess()?;
|
||||
/// }
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
///
|
||||
/// fn caller()
|
||||
/// {
|
||||
/// match try_things_internal() {
|
||||
/// Ok(_) => println!("Yay!"),
|
||||
/// Err(_) => panic!("Fug"),
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
/// The bottom scenario is preferrable for Rust, as we are using `Result<T,E>` instead of an integer.
|
||||
/// # When to use
|
||||
/// This type should be preferred in Rust code, and `GHOST_TSuccess` preferred when doing a lot of FFI at once.
|
||||
/// # Notes
|
||||
/// *Usually* the internal result will be `()`. But idk if that will always be the case so it's still possible to set.
|
||||
pub type GhostResult<T = ()> = Result<T, GhostError>;
|
||||
|
||||
/// Error type for failed GHOST calls.
|
||||
/// As of yet it doesn't contain any information and is just an opaque zero-sized structure.
|
||||
#[derive(Debug)]
|
||||
pub struct GhostError(());
|
||||
impl error::Error for GhostError{}
|
||||
impl fmt::Display for GhostError
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||
{
|
||||
write!(f, "GHOST function call failed")
|
||||
}
|
||||
}
|
||||
|
||||
impl From<types::GHOST_TSuccess> for GhostResult
|
||||
{
|
||||
#[inline] fn from(from: types::GHOST_TSuccess) -> Self
|
||||
{
|
||||
from.into_result()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GhostResult> for types::GHOST_TSuccess
|
||||
{
|
||||
#[inline] fn from(from: GhostResult) -> Self
|
||||
{
|
||||
Self::from_result(from)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for types::GHOST_TSuccess
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||
{
|
||||
match self {
|
||||
Self::Failure => write!(f, "Failure"),
|
||||
Self::Success => write!(f, "Success"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(nightly)]
|
||||
impl std::ops::Try for types::GHOST_TSuccess
|
||||
{
|
||||
type Ok = ();
|
||||
type Error = GhostError;
|
||||
|
||||
fn into_result(self) -> Result<Self::Ok, Self::Error>
|
||||
{
|
||||
self.into()
|
||||
}
|
||||
fn from_error(_: Self::Error) -> Self
|
||||
{
|
||||
Self::Failure
|
||||
}
|
||||
fn from_ok(_: Self::Ok) -> Self
|
||||
{
|
||||
Self::Success
|
||||
}
|
||||
}
|
||||
impl types::GHOST_TSuccess
|
||||
{
|
||||
/// Consume this instance into `Result<(), GhostError>`.
|
||||
///
|
||||
pub const fn into_result(self) -> GhostResult
|
||||
{
|
||||
match self {
|
||||
types::GHOST_TSuccess::Success => Ok(()),
|
||||
types::GHOST_TSuccess::Failure => Err(GhostError(())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a `GhostResult` into `GHOST_TSuccess`.
|
||||
pub const fn from_result(from: GhostResult) -> Self
|
||||
{
|
||||
match from {
|
||||
Ok(_) => Self::Success,
|
||||
Err(_) => Self::Failure,
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue