1use core::num::NonZero;
3use core::ops::BitOr;
4
5use crate::ffi::num::ShouldNotBeZero;
6use crate::ffi::option::{COption, OptZero};
7use crate::ffi::ptr::FFINonNull;
8use crate::ffi::slice::Slice;
9use crate::ffi::str::Str;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12#[repr(C)]
13pub struct AbiStructures {
17 pub stdio: ProcessStdio,
18 pub parent_process_pid: u32,
20 pub available_cpus: u32,
22}
23
24impl AbiStructures {
25 pub fn new(stdio: ProcessStdio, parent_pid: u32, available_cpus: u32) -> Self {
26 Self {
27 available_cpus,
28 stdio,
29 parent_process_pid: parent_pid,
30 }
31 }
32}
33
34#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
36#[repr(C)]
37pub struct ProcessStdio {
38 pub stdout: COption<usize>,
39 pub stdin: COption<usize>,
40 pub stderr: COption<usize>,
41}
42
43impl ProcessStdio {
44 pub fn new(stdout: Option<u32>, stdin: Option<u32>, stderr: Option<u32>) -> Self {
45 Self {
46 stdout: stdout.map(|u32| u32 as usize).into(),
47 stdin: stdin.map(|u32| u32 as usize).into(),
48 stderr: stderr.map(|u32| u32 as usize).into(),
49 }
50 }
51
52 pub fn into_rust(self) -> (Option<u32>, Option<u32>, Option<u32>) {
54 (
55 match self.stdout {
56 COption::Some(stdout) => Some(stdout as u32),
57 COption::None => None,
58 },
59 match self.stdin {
60 COption::Some(stdin) => Some(stdin as u32),
61 COption::None => None,
62 },
63 match self.stderr {
64 COption::Some(stderr) => Some(stderr as u32),
65 COption::None => None,
66 },
67 )
68 }
69}
70
71#[derive(Debug, Clone, Copy)]
72#[repr(C)]
73pub struct SpawnFlags(u8);
75impl SpawnFlags {
76 pub const CLONE_RESOURCES: Self = Self(1 << 0);
77 pub const CLONE_CWD: Self = Self(1 << 1);
78 pub const EMPTY: Self = Self(0);
79}
80
81impl BitOr for SpawnFlags {
82 type Output = Self;
83 fn bitor(self, rhs: Self) -> Self::Output {
84 Self(self.0 | rhs.0)
85 }
86}
87
88#[repr(u8)]
89#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90pub enum RawContextPriority {
91 Default = 0,
96 Low = 1,
97 Medium = 2,
98 High = 3,
99}
100
101#[repr(C)]
103pub struct RawPSpawnConfig {
104 pub revision: u8,
110 _reserved: [u8; 7],
111 pub name: OptZero<Str>,
112 pub argv: OptZero<Slice<Str>>,
113 pub flags: SpawnFlags,
114 _reserved1: [u8; 7],
115 pub stdio: OptZero<FFINonNull<ProcessStdio>>,
116 pub env: OptZero<Slice<Slice<u8>>>,
118 pub priority: RawContextPriority,
120 _reserved2: [u8; 7],
121 pub custom_stack_size: OptZero<ShouldNotBeZero<usize>>,
123}
124
125impl RawPSpawnConfig {
126 #[inline(always)]
128 pub const fn new_from_raw(
129 name: OptZero<Str>,
130 argv: OptZero<Slice<Str>>,
131 env: OptZero<Slice<Slice<u8>>>,
132 flags: SpawnFlags,
133 stdio: OptZero<FFINonNull<ProcessStdio>>,
134 priority: RawContextPriority,
135 custom_stack_size: OptZero<ShouldNotBeZero<usize>>,
136 ) -> Self {
137 Self {
138 revision: 3,
139 name,
140 argv,
141 env,
142 flags,
143 stdio,
144 priority,
145 custom_stack_size,
146 _reserved2: [0; 7],
147 _reserved1: [0; 7],
148 _reserved: [0; 7],
149 }
150 }
151
152 #[inline]
153 pub unsafe fn new<'a>(
162 name: Option<&'a str>,
163 argv: Option<&'a mut [*mut str]>,
164 envv: Option<&'a mut [*mut [u8]]>,
165 flags: SpawnFlags,
166 stdio: Option<&'a ProcessStdio>,
167 priority: RawContextPriority,
168 custom_stack_size: Option<NonZero<usize>>,
169 ) -> Self {
170 Self::new_from_raw(
171 OptZero::from_option(name.map(|s| Str::from_str(s))),
172 OptZero::from_option(argv.map(|v| unsafe { Slice::from_str_slices_mut(v) })),
173 OptZero::from_option(envv.map(|v| unsafe { Slice::from_slices_ptr_mut(v) })),
174 flags,
175 OptZero::from_option(
176 stdio.map(|v| unsafe { FFINonNull::new_unchecked(v as *const _ as *mut _) }),
177 ),
178 priority,
179 OptZero::from_option(custom_stack_size.map(|v| v.into())),
180 )
181 }
182}
183
184#[repr(C)]
187pub struct RawTSpawnConfig {
188 pub revision: u32,
190 _reserved: u32,
191 pub argument_ptr: *const (),
192 pub priority: RawContextPriority,
193 pub cpu: COption<u8>,
195 _reserved1: [u8; 5],
196 pub custom_stack_size: OptZero<ShouldNotBeZero<usize>>,
198}
199
200impl RawTSpawnConfig {
201 #[inline(always)]
202 pub const fn new_from_raw(
204 argument_ptr: *const (),
205 priority: RawContextPriority,
206 cpu: COption<u8>,
207 custom_stack_size: OptZero<ShouldNotBeZero<usize>>,
208 ) -> Self {
209 Self {
210 revision: 1,
211 _reserved1: [0; 5],
212 _reserved: 0,
213 argument_ptr,
214 priority,
215 cpu,
216 custom_stack_size,
217 }
218 }
219
220 #[inline]
221 pub fn new(
223 argument_ptr: *const (),
224 priority: RawContextPriority,
225 cpu: Option<u8>,
226 custom_stack_size: Option<NonZero<usize>>,
227 ) -> Self {
228 Self::new_from_raw(
229 argument_ptr,
230 priority.into(),
231 cpu.into(),
232 match custom_stack_size {
233 Some(size) => OptZero::some(unsafe { ShouldNotBeZero::new_unchecked(size.get()) }),
234 None => OptZero::none(),
235 },
236 )
237 }
238}