safa_abi/
errors.rs

1#[allow(dead_code)]
2#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3#[repr(u16)]
4pub enum ErrorStatus {
5    /// use when no ErrorStatus is available for xyz and you cannot add a new one
6    Generic = 1,
7    OperationNotSupported = 2,
8    /// for example an elf class is not supported, there is a difference between NotSupported and
9    /// OperationNotSupported
10    NotSupported = 3,
11    /// for example a magic value is invalid
12    Corrupted = 4,
13    InvalidSyscall = 5,
14    InvalidResource = 6,
15    InvalidPid = 7,
16    InvalidOffset = 8,
17    /// instead of panicking syscalls will return this on null and unaligned pointers
18    /// some operations may accept null pointers
19    InvalidPtr = 9,
20    /// for operations that requires a valid utf8 str...
21    InvalidStr = 0xA,
22    /// for operations that requires a str that doesn't exceed a max length such as
23    /// file names (128 bytes)
24    StrTooLong = 0xB,
25    InvalidPath = 0xC,
26    NoSuchAFileOrDirectory = 0xD,
27    NotAFile = 0xE,
28    NotADirectory = 0xF,
29    AlreadyExists = 0x10,
30    NotExecutable = 0x11,
31    // would be useful when i add remove related operations to the vfs
32    DirectoryNotEmpty = 0x12,
33    // Generic permissions(protection) related error
34    MissingPermissions = 0x13,
35    // memory allocations and mapping error, most likely that memory is full
36    MMapError = 0x14,
37    Busy = 0x15,
38    // errors sent by processes
39    NotEnoughArguments = 0x16,
40    OutOfMemory = 0x17,
41}
42
43impl ErrorStatus {
44    // update when a new error is added
45    const MAX: u16 = Self::OutOfMemory as u16;
46
47    #[inline(always)]
48    /// Gives a string description of the error
49    pub fn as_str(&self) -> &'static str {
50        use ErrorStatus::*;
51        match *self {
52            Generic => "Generic Error",
53            OperationNotSupported => "Operation Not Supported",
54            NotSupported => "Object Not Supported",
55            Corrupted => "Corrupted",
56            InvalidSyscall => "Invalid Syscall",
57            InvalidResource => "Invalid Resource",
58            InvalidPid => "Invalid PID",
59            InvalidOffset => "Invalid Offset",
60            InvalidPtr => "Invalid Ptr (not aligned or null)",
61            InvalidStr => "Invalid Str (not utf8)",
62            StrTooLong => "Str too Long",
63            InvalidPath => "Invalid Path",
64            NoSuchAFileOrDirectory => "No Such a File or Directory",
65            NotAFile => "Not a File",
66            NotADirectory => "Not a Directory",
67            AlreadyExists => "Already Exists",
68            NotExecutable => "Not Executable",
69            DirectoryNotEmpty => "Directory not Empty",
70            MissingPermissions => "Missing Permissions",
71            MMapError => "Memory Map Error (most likely out of memory)",
72            Busy => "Resource Busy",
73            NotEnoughArguments => "Not Enough Arguments",
74            OutOfMemory => "Out of Memory",
75        }
76    }
77}
78
79impl TryFrom<u16> for ErrorStatus {
80    type Error = ();
81
82    fn try_from(value: u16) -> Result<Self, Self::Error> {
83        if value > 0 && value <= Self::MAX {
84            Ok(unsafe { core::mem::transmute(value) })
85        } else {
86            Err(())
87        }
88    }
89}
90#[derive(Debug, Clone, Copy, PartialEq, Eq)]
91pub enum SysResult {
92    Success,
93    Error(ErrorStatus),
94}
95
96impl From<ErrorStatus> for SysResult {
97    #[inline(always)]
98    fn from(value: ErrorStatus) -> Self {
99        SysResult::Error(value)
100    }
101}
102
103impl From<Result<(), ErrorStatus>> for SysResult {
104    #[inline(always)]
105    fn from(value: Result<(), ErrorStatus>) -> Self {
106        match value {
107            Ok(()) => SysResult::Success,
108            Err(err) => SysResult::Error(err),
109        }
110    }
111}
112
113impl TryFrom<u16> for SysResult {
114    type Error = ();
115    #[inline(always)]
116    fn try_from(value: u16) -> Result<Self, ()> {
117        match value {
118            0 => Ok(SysResult::Success),
119            other => {
120                let err = ErrorStatus::try_from(other).map_err(|_| ())?;
121                Ok(SysResult::Error(err))
122            }
123        }
124    }
125}
126
127impl From<SysResult> for Result<(), ErrorStatus> {
128    #[inline(always)]
129    fn from(value: SysResult) -> Self {
130        match value {
131            SysResult::Success => Ok(()),
132            SysResult::Error(err) => Err(err),
133        }
134    }
135}
136
137impl Into<u16> for SysResult {
138    #[inline(always)]
139    fn into(self) -> u16 {
140        match self {
141            SysResult::Success => 0,
142            SysResult::Error(err) => err as u16,
143        }
144    }
145}
146
147pub trait IntoErr {
148    fn into_err(self) -> ErrorStatus;
149}
150
151impl<T: IntoErr> From<T> for ErrorStatus {
152    fn from(value: T) -> Self {
153        value.into_err()
154    }
155}
156
157#[cfg(feature = "std")]
158mod std_only {
159    use super::SysResult;
160    use std::process::ExitCode;
161    use std::process::Termination;
162    impl Termination for SysResult {
163        fn report(self) -> ExitCode {
164            let u16: u16 = self.into();
165            ExitCode::from(u16 as u8)
166        }
167    }
168}