safa_api/syscalls/
types.rs

1pub(crate) trait IntoSyscallArg {
2    type RegResults;
3    fn into_syscall_arg(self) -> Self::RegResults;
4}
5
6macro_rules! impl_into_syscall_as {
7    ($ty:ty) => {
8        impl IntoSyscallArg for $ty {
9            type RegResults = (usize,);
10            #[inline(always)]
11            fn into_syscall_arg(self) -> (usize,) {
12                (self as usize,)
13            }
14        }
15    };
16}
17
18impl_into_syscall_as!(usize);
19impl_into_syscall_as!(isize);
20impl_into_syscall_as!(u8);
21impl_into_syscall_as!(i8);
22impl_into_syscall_as!(u16);
23impl_into_syscall_as!(i16);
24impl_into_syscall_as!(u32);
25impl_into_syscall_as!(i32);
26impl_into_syscall_as!(u64);
27impl_into_syscall_as!(i64);
28impl_into_syscall_as!(u128);
29impl_into_syscall_as!(i128);
30impl_into_syscall_as!(bool);
31
32impl IntoSyscallArg for (usize,) {
33    type RegResults = (usize,);
34
35    #[inline(always)]
36    fn into_syscall_arg(self) -> (usize,) {
37        self
38    }
39}
40
41impl<T> IntoSyscallArg for *const T {
42    type RegResults = (usize,);
43
44    #[inline(always)]
45    fn into_syscall_arg(self) -> (usize,) {
46        (self as usize,)
47    }
48}
49
50impl<T> IntoSyscallArg for *mut T {
51    type RegResults = (usize,);
52
53    #[inline(always)]
54    fn into_syscall_arg(self) -> (usize,) {
55        (self as usize,)
56    }
57}
58
59impl IntoSyscallArg for safa_abi::fs::OpenOptions {
60    type RegResults = (usize,);
61
62    #[inline(always)]
63    fn into_syscall_arg(self) -> (usize,) {
64        let bits: u8 = unsafe { core::mem::transmute(self) };
65        bits.into_syscall_arg()
66    }
67}
68
69impl<T> IntoSyscallArg for Slice<T> {
70    type RegResults = (usize, usize);
71
72    #[inline(always)]
73    fn into_syscall_arg(self) -> (usize, usize) {
74        (self.as_ptr() as usize, self.len())
75    }
76}
77
78impl IntoSyscallArg for Str {
79    type RegResults = (usize, usize);
80
81    #[inline(always)]
82    fn into_syscall_arg(self) -> (usize, usize) {
83        (self.as_ptr() as usize, self.len())
84    }
85}
86
87impl<T> IntoSyscallArg for FFINonNull<T> {
88    type RegResults = (usize,);
89    fn into_syscall_arg(self) -> Self::RegResults {
90        (self.as_ptr() as usize,)
91    }
92}
93
94impl<T: NotZeroable + IntoSyscallArg> IntoSyscallArg for OptZero<T> {
95    type RegResults = T::RegResults;
96    fn into_syscall_arg(self) -> Self::RegResults {
97        let inner = unsafe { self.into_inner_unchecked() };
98        inner.into_syscall_arg()
99    }
100}
101
102use safa_abi::ffi::option::OptZero;
103use safa_abi::ffi::{ptr::FFINonNull, slice::Slice, str::Str};
104
105use safa_abi::ffi::NotZeroable;
106
107use crate::errors::ErrorStatus;
108
109/// A nullable muttable pointer to `T`
110///
111/// guaranteed to be accepted by the syscall if it is null,
112/// however the syscall will return [`ErrorStatus::InvalidPtr`] if it is not aligned to `align_of::<T>()`
113///
114/// this is typically for the syscall to return optional values
115pub type OptionalPtrMut<T> = OptZero<RequiredPtrMut<T>>;
116
117/// A nullable imuttable pointer to `T`
118///
119/// guaranteed to be accepted by the syscall if it is null,
120/// however the syscall will return [`ErrorStatus::InvalidPtr`] if it is not aligned to `align_of::<T>()`
121///
122/// this is typically for the syscall to return optional values
123pub type OptionalPtr<T> = OptZero<RequiredPtr<T>>;
124
125/// A muttable pointer to `T`
126///
127/// the syscall will return [`ErrorStatus::InvalidPtr`] if it is not aligned to `align_of::<T>()` or if it is null
128///
129/// typically used for the syscall to return a value
130pub type RequiredPtrMut<T> = FFINonNull<T>;
131
132/// An immuttable pointer to `T`
133///
134/// the syscall will return [`ErrorStatus::InvalidPtr`] if it is not aligned to `align_of::<T>()` or if it is null
135///
136/// typically used for the syscall to return a value
137pub type RequiredPtr<T> = FFINonNull<T>;
138
139/// An optional immuttable nullable utf8 byte slice
140///
141/// the syscall will return [`ErrorStatus::InvalidStr`] if it is not null and is not valid utf-8
142///
143/// typically followed by a `len` parameter to specify the length of the string
144///
145/// can be null
146pub type OptionalStr = OptZero<Str>;
147
148/// An optional muttable nullable utf8 byte slice
149///
150/// the syscall will return [`ErrorStatus::InvalidStr`] if it is not null and is not valid utf-8
151///
152/// typically followed by a `len` parameter to specify the length of the string
153///
154/// can be null
155pub type OptionalStrMut = OptZero<Str>;
156
157/// An opaque type that represents a syscall result
158/// the underlying type is a 16 bit unsigned integer, in which 0 is success and any other value is in error
159/// represented by the [`ErrorStatus`] enum
160#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161#[repr(transparent)]
162pub struct SyscallResult(u16);
163
164impl SyscallResult {
165    #[inline(always)]
166    pub const fn into_result(self) -> Result<(), ErrorStatus> {
167        match self.0 {
168            0 => Ok(()),
169            x => unsafe { Err(core::mem::transmute(x)) },
170        }
171    }
172
173    #[inline(always)]
174    pub const fn is_success(self) -> bool {
175        self.0 == 0
176    }
177}
178
179/// A process ID
180pub type Pid = u32;
181/// A thread ID
182pub type Cid = u32;
183
184/// A resource id
185/// this is a generic type that can be used to represent any resource (file, directory, device, directory iterator, etc.)
186pub type Ri = usize;