safe_vex/
error.rs

1//! # Error API
2
3use crate::bindings;
4
5// need to manually declare until https://github.com/rust-lang/libc/issues/1995 is resolved.
6extern "C" {
7    /// Gets a mutable pointer to the C/C++ `errno` value
8    pub fn __errno() -> *mut i32;
9}
10
11/// Possible PROS Errors
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13#[repr(i32)]
14pub enum PROSErr {
15    /// No errors
16    None = 0,
17    /// No such file or directory
18    NoEntry = 2,
19    /// I/O error
20    IO = 5,
21    /// No such device or address
22    NXIO = 6,
23    /// No more processes
24    Again = 11,
25    /// Permission denied
26    Access = 13,
27    /// Mount device busy
28    Busy = 16,
29    /// File exists
30    Exists = 17,
31    /// No such device
32    NoDev = 19,
33    /// Invalid argument
34    Invalid = 22,
35    /// Read-only file system
36    ReadOnlyFS = 30,
37    /// No more files
38    NoMoreFiles = 89,
39    /// No buffer space available
40    NoBuffSpace = 105,
41    /// Address already in use or not configured correctly
42    AddrInUse = 112,
43}
44
45/// Generates a [`PROSError`] from the value of `errno` for the current task
46pub fn from_errno() -> PROSErr {
47    unsafe {
48        // get errno pointer
49        let errno: *const i32 = __errno() as *const i32;
50        // cast the errno to a PROSErr through pointer magic
51        *(errno as *const PROSErr) // transmute would also work here too but this looks cooler
52    }
53}
54
55/// A type which may contain a [`PROSErr`] depending upon a sentinel value that represents errors
56///
57/// Implementations are provided for `i32`, `f64` and `*mut T` values based on either PRO's sentinel error values (`PROS_ERR` or `PROS_ERR_F` in C/C++) or a NULL pointer
58pub trait PROSResult: Sized {
59    /// Checks if the type is a valid (success value), giving an appropriate
60    /// error otherwise.
61    fn check(self) -> Result<Self, PROSErr>;
62}
63
64impl PROSResult for i32 {
65    fn check(self) -> Result<Self, PROSErr> {
66        if self == bindings::PROS_ERR_ {
67            Err(from_errno())
68        } else {
69            Ok(self)
70        }
71    }
72}
73
74impl PROSResult for f64 {
75    fn check(self) -> Result<Self, PROSErr> {
76        if self == bindings::PROS_ERR_F_ {
77            Err(from_errno())
78        } else {
79            Ok(self)
80        }
81    }
82}
83
84impl<T> PROSResult for *mut T {
85    fn check(self) -> Result<Self, PROSErr> {
86        if self.is_null() {
87            Err(from_errno())
88        } else {
89            Ok(self)
90        }
91    }
92}