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    /// Invalid Thread ID
42    InvalidTid = 0x18,
43}
44
45impl ErrorStatus {
46    // update when a new error is added
47    const MAX: u16 = Self::OutOfMemory as u16;
48
49    #[inline(always)]
50    /// Gives a string description of the error
51    pub fn as_str(&self) -> &'static str {
52        use ErrorStatus::*;
53        match *self {
54            Generic => "Generic Error",
55            OperationNotSupported => "Operation Not Supported",
56            NotSupported => "Object Not Supported",
57            Corrupted => "Corrupted",
58            InvalidSyscall => "Invalid Syscall",
59            InvalidResource => "Invalid Resource",
60            InvalidPid => "Invalid PID",
61            InvalidTid => "Invalid TID",
62            InvalidOffset => "Invalid Offset",
63            InvalidPtr => "Invalid Ptr (not aligned or null)",
64            InvalidStr => "Invalid Str (not utf8)",
65            StrTooLong => "Str too Long",
66            InvalidPath => "Invalid Path",
67            NoSuchAFileOrDirectory => "No Such a File or Directory",
68            NotAFile => "Not a File",
69            NotADirectory => "Not a Directory",
70            AlreadyExists => "Already Exists",
71            NotExecutable => "Not Executable",
72            DirectoryNotEmpty => "Directory not Empty",
73            MissingPermissions => "Missing Permissions",
74            MMapError => "Memory Map Error (most likely out of memory)",
75            Busy => "Resource Busy",
76            NotEnoughArguments => "Not Enough Arguments",
77            OutOfMemory => "Out of Memory",
78        }
79    }
80}
81
82impl TryFrom<u16> for ErrorStatus {
83    type Error = ();
84
85    fn try_from(value: u16) -> Result<Self, Self::Error> {
86        if value > 0 && value <= Self::MAX {
87            Ok(unsafe { core::mem::transmute(value) })
88        } else {
89            Err(())
90        }
91    }
92}
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94pub enum SysResult {
95    Success,
96    Error(ErrorStatus),
97}
98
99impl From<ErrorStatus> for SysResult {
100    #[inline(always)]
101    fn from(value: ErrorStatus) -> Self {
102        SysResult::Error(value)
103    }
104}
105
106impl From<Result<(), ErrorStatus>> for SysResult {
107    #[inline(always)]
108    fn from(value: Result<(), ErrorStatus>) -> Self {
109        match value {
110            Ok(()) => SysResult::Success,
111            Err(err) => SysResult::Error(err),
112        }
113    }
114}
115
116impl TryFrom<u16> for SysResult {
117    type Error = ();
118    #[inline(always)]
119    fn try_from(value: u16) -> Result<Self, ()> {
120        match value {
121            0 => Ok(SysResult::Success),
122            other => {
123                let err = ErrorStatus::try_from(other).map_err(|_| ())?;
124                Ok(SysResult::Error(err))
125            }
126        }
127    }
128}
129
130impl From<SysResult> for Result<(), ErrorStatus> {
131    #[inline(always)]
132    fn from(value: SysResult) -> Self {
133        match value {
134            SysResult::Success => Ok(()),
135            SysResult::Error(err) => Err(err),
136        }
137    }
138}
139
140impl Into<u16> for SysResult {
141    #[inline(always)]
142    fn into(self) -> u16 {
143        match self {
144            SysResult::Success => 0,
145            SysResult::Error(err) => err as u16,
146        }
147    }
148}
149
150pub trait IntoErr {
151    fn into_err(self) -> ErrorStatus;
152}
153
154impl<T: IntoErr> From<T> for ErrorStatus {
155    fn from(value: T) -> Self {
156        value.into_err()
157    }
158}
159
160#[cfg(feature = "std")]
161mod std_only {
162    use super::SysResult;
163    use std::process::ExitCode;
164    use std::process::Termination;
165    impl Termination for SysResult {
166        fn report(self) -> ExitCode {
167            let u16: u16 = self.into();
168            ExitCode::from(u16 as u8)
169        }
170    }
171}