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}