135 lines
3.0 KiB
Rust
135 lines
3.0 KiB
Rust
use core::{
|
|
convert::Infallible,
|
|
ffi::c_int,
|
|
ops::{ControlFlow, FromResidual, Try},
|
|
};
|
|
|
|
use crate::header::{errno::Errno, stdio::EOF};
|
|
|
|
pub trait CZeroResult {
|
|
fn into_zero_status(self) -> c_int;
|
|
fn into_eof_status(self) -> c_int;
|
|
}
|
|
|
|
pub trait CSizeResult {
|
|
fn into_size_status(self) -> usize;
|
|
}
|
|
|
|
pub trait TryFromExt<T>: Sized {
|
|
fn e_try_from(value: T) -> EResult<Self>;
|
|
}
|
|
|
|
pub trait OptionExt<T> {
|
|
fn e_ok_or(self, err: yggdrasil_rt::Error) -> EResult<T>;
|
|
}
|
|
|
|
// TODO thread_local
|
|
#[no_mangle]
|
|
pub static mut errno: Errno = Errno(0);
|
|
|
|
pub enum EResult<T> {
|
|
Ok(T),
|
|
Err(yggdrasil_rt::Error),
|
|
Errno(Errno),
|
|
}
|
|
|
|
impl<T> From<Result<T, yggdrasil_rt::Error>> for EResult<T> {
|
|
fn from(value: Result<T, yggdrasil_rt::Error>) -> Self {
|
|
match value {
|
|
Ok(value) => Self::Ok(value),
|
|
Err(error) => Self::Err(error),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T> EResult<T> {
|
|
pub fn into_set_errno(self) -> EResult<T> {
|
|
match self {
|
|
Self::Ok(value) => Self::Ok(value),
|
|
Self::Errno(e) => Self::Errno(e),
|
|
Self::Err(err) => {
|
|
let e = Errno::from(err);
|
|
unsafe {
|
|
errno = e;
|
|
}
|
|
Self::Errno(e)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CZeroResult for Result<(), Errno> {
|
|
fn into_zero_status(self) -> c_int {
|
|
match self {
|
|
Self::Ok(_) => 0,
|
|
Self::Err(_) => -1,
|
|
}
|
|
}
|
|
|
|
fn into_eof_status(self) -> c_int {
|
|
match self {
|
|
Self::Ok(_) => 0,
|
|
Self::Err(_) => EOF,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CSizeResult for Result<usize, Errno> {
|
|
fn into_size_status(self) -> usize {
|
|
match self {
|
|
Self::Ok(value) => value,
|
|
Self::Err(_) => 0,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T> FromResidual<Errno> for EResult<T> {
|
|
fn from_residual(residual: Errno) -> Self {
|
|
Self::Errno(residual)
|
|
}
|
|
}
|
|
|
|
impl<T> FromResidual<yggdrasil_rt::Error> for EResult<T> {
|
|
fn from_residual(residual: yggdrasil_rt::Error) -> Self {
|
|
Self::Err(residual)
|
|
}
|
|
}
|
|
|
|
impl<T> FromResidual<Result<Infallible, Errno>> for EResult<T> {
|
|
fn from_residual(residual: Result<Infallible, Errno>) -> Self {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
impl<T> Try for EResult<T> {
|
|
type Output = T;
|
|
type Residual = Result<Infallible, Errno>;
|
|
|
|
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
|
|
match self.into_set_errno() {
|
|
Self::Ok(value) => ControlFlow::Continue(value),
|
|
Self::Errno(e) => ControlFlow::Break(Err(e)),
|
|
Self::Err(error) => unreachable!(),
|
|
}
|
|
}
|
|
|
|
fn from_output(output: Self::Output) -> Self {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
impl<T> OptionExt<T> for Option<T> {
|
|
fn e_ok_or(self, err: yggdrasil_rt::Error) -> EResult<T> {
|
|
match self {
|
|
Some(value) => EResult::Ok(value),
|
|
None => EResult::Err(err),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn set_errno(e: Errno) {
|
|
unsafe {
|
|
errno = e;
|
|
}
|
|
}
|