1use crate::{lldb_pid_t, sys, LaunchFlags, SBFileSpec, SBListener};
8use std::ffi::{CStr, CString};
9use std::os::raw::c_char;
10use std::ptr;
11
12#[derive(Debug)]
18pub struct SBLaunchInfo {
19 pub raw: sys::SBLaunchInfoRef,
21}
22
23impl SBLaunchInfo {
24 pub fn new() -> SBLaunchInfo {
26 SBLaunchInfo::wrap(unsafe { sys::CreateSBLaunchInfo(ptr::null_mut()) })
27 }
28
29 pub(crate) fn wrap(raw: sys::SBLaunchInfoRef) -> SBLaunchInfo {
31 SBLaunchInfo { raw }
32 }
33
34 #[allow(missing_docs)]
35 pub fn process_id(&self) -> lldb_pid_t {
36 unsafe { sys::SBLaunchInfoGetProcessID(self.raw) }
37 }
38
39 #[allow(missing_docs)]
40 pub fn user_id(&self) -> Option<u32> {
41 if unsafe { sys::SBLaunchInfoUserIDIsValid(self.raw) } {
42 Some(unsafe { sys::SBLaunchInfoGetUserID(self.raw) })
43 } else {
44 None
45 }
46 }
47
48 #[allow(missing_docs)]
49 pub fn set_user_id(&self, user_id: u32) {
50 unsafe { sys::SBLaunchInfoSetUserID(self.raw, user_id) };
51 }
52
53 #[allow(missing_docs)]
54 pub fn group_id(&self) -> Option<u32> {
55 if unsafe { sys::SBLaunchInfoGroupIDIsValid(self.raw) } {
56 Some(unsafe { sys::SBLaunchInfoGetGroupID(self.raw) })
57 } else {
58 None
59 }
60 }
61
62 #[allow(missing_docs)]
63 pub fn set_group_id(&self, group_id: u32) {
64 unsafe { sys::SBLaunchInfoSetGroupID(self.raw, group_id) };
65 }
66
67 #[allow(missing_docs)]
68 pub fn executable_file(&self) -> Option<SBFileSpec> {
69 SBFileSpec::maybe_wrap(unsafe { sys::SBLaunchInfoGetExecutableFile(self.raw) })
70 }
71
72 pub fn set_executable_file(&self, filespec: &SBFileSpec, add_as_first_arg: bool) {
94 unsafe { sys::SBLaunchInfoSetExecutableFile(self.raw, filespec.raw, add_as_first_arg) };
95 }
96
97 pub fn listener(&self) -> Option<SBListener> {
103 SBListener::maybe_wrap(unsafe { sys::SBLaunchInfoGetListener(self.raw) })
104 }
105
106 pub fn set_listener(&self, listener: &SBListener) {
116 unsafe { sys::SBLaunchInfoSetListener(self.raw, listener.raw) };
117 }
118
119 #[allow(missing_docs)]
120 pub fn launch_flags(&self) -> LaunchFlags {
121 LaunchFlags::from_bits_truncate(unsafe { sys::SBLaunchInfoGetLaunchFlags(self.raw) })
122 }
123
124 #[allow(missing_docs)]
125 pub fn set_launch_flags(&self, launch_flags: LaunchFlags) {
126 unsafe { sys::SBLaunchInfoSetLaunchFlags(self.raw, launch_flags.bits()) }
127 }
128
129 pub fn set_arguments<'a>(&self, args: impl IntoIterator<Item = &'a str>, append: bool) {
131 let cstrs: Vec<CString> = args.into_iter().map(|a| CString::new(a).unwrap()).collect();
132 let mut ptrs: Vec<*const c_char> = cstrs.iter().map(|cs| cs.as_ptr()).collect();
133 ptrs.push(ptr::null());
134 let argv = ptrs.as_ptr();
135 unsafe { sys::SBLaunchInfoSetArguments(self.raw, argv, append) };
136 }
137
138 pub fn arguments(&self) -> impl Iterator<Item = &str> {
140 SBLaunchInfoArgumentsIter {
141 launch_info: self,
142 index: 0,
143 }
144 }
145
146 #[allow(missing_docs)]
147 fn num_arguments(&self) -> u32 {
148 unsafe { sys::SBLaunchInfoGetNumArguments(self.raw) }
149 }
150
151 #[allow(missing_docs)]
152 fn argument_at_index(&self, index: u32) -> &str {
153 unsafe {
154 match CStr::from_ptr(sys::SBLaunchInfoGetArgumentAtIndex(self.raw, index)).to_str() {
155 Ok(s) => s,
156 _ => panic!("Invalid string?"),
157 }
158 }
159 }
160
161 #[allow(missing_docs)]
162 pub fn process_plugin_name(&self) -> Option<&str> {
163 unsafe {
164 match CStr::from_ptr(sys::SBLaunchInfoGetProcessPluginName(self.raw)).to_str() {
165 Ok(s) => Some(s),
166 _ => None,
167 }
168 }
169 }
170
171 #[allow(missing_docs)]
172 pub fn set_process_plugin_name(&self, plugin: &str) {
173 let plugin = CString::new(plugin).unwrap();
174 unsafe { sys::SBLaunchInfoSetProcessPluginName(self.raw, plugin.as_ptr()) };
175 }
176
177 #[allow(missing_docs)]
178 pub fn shell(&self) -> Option<&str> {
179 unsafe {
180 match CStr::from_ptr(sys::SBLaunchInfoGetShell(self.raw)).to_str() {
181 Ok(s) => Some(s),
182 _ => None,
183 }
184 }
185 }
186
187 #[allow(missing_docs)]
188 pub fn set_shell(&self, shell: &str) {
189 let shell = CString::new(shell).unwrap();
190 unsafe { sys::SBLaunchInfoSetShell(self.raw, shell.as_ptr()) };
191 }
192
193 #[allow(missing_docs)]
194 pub fn shell_expand_arguments(&self) -> bool {
195 unsafe { sys::SBLaunchInfoGetShellExpandArguments(self.raw) }
196 }
197
198 #[allow(missing_docs)]
199 pub fn set_shell_expand_arguments(&self, expand: bool) {
200 unsafe { sys::SBLaunchInfoSetShellExpandArguments(self.raw, expand) };
201 }
202
203 #[allow(missing_docs)]
204 pub fn resume_count(&self) -> u32 {
205 unsafe { sys::SBLaunchInfoGetResumeCount(self.raw) }
206 }
207
208 #[allow(missing_docs)]
209 pub fn set_resume_count(&self, resume_count: u32) {
210 unsafe { sys::SBLaunchInfoSetResumeCount(self.raw, resume_count) };
211 }
212
213 #[allow(missing_docs)]
214 pub fn add_close_file_action(&self, fd: i32) -> bool {
215 unsafe { sys::SBLaunchInfoAddCloseFileAction(self.raw, fd) }
216 }
217
218 #[allow(missing_docs)]
219 pub fn add_duplicate_file_action(&self, fd: i32, dup_fd: i32) -> bool {
220 unsafe { sys::SBLaunchInfoAddDuplicateFileAction(self.raw, fd, dup_fd) }
221 }
222
223 #[allow(missing_docs)]
224 pub fn add_open_file_action(&self, fd: i32, path: &str, read: bool, write: bool) -> bool {
225 let path = CString::new(path).unwrap();
226 unsafe { sys::SBLaunchInfoAddOpenFileAction(self.raw, fd, path.as_ptr(), read, write) }
227 }
228
229 #[allow(missing_docs)]
230 pub fn add_suppress_file_action(&self, fd: i32, read: bool, write: bool) -> bool {
231 unsafe { sys::SBLaunchInfoAddSuppressFileAction(self.raw, fd, read, write) }
232 }
233
234 #[allow(missing_docs)]
235 pub fn launch_event_data(&self) -> Option<&str> {
236 unsafe {
237 match CStr::from_ptr(sys::SBLaunchInfoGetLaunchEventData(self.raw)).to_str() {
238 Ok(s) => Some(s),
239 _ => None,
240 }
241 }
242 }
243
244 #[allow(missing_docs)]
245 pub fn set_launch_event_data(&self, data: &str) {
246 let data = CString::new(data).unwrap();
247 unsafe { sys::SBLaunchInfoSetLaunchEventData(self.raw, data.as_ptr()) };
248 }
249
250 #[allow(missing_docs)]
251 pub fn detach_on_error(&self) -> bool {
252 unsafe { sys::SBLaunchInfoGetDetachOnError(self.raw) }
253 }
254 #[allow(missing_docs)]
255 pub fn set_detach_on_error(&self, detach: bool) {
256 unsafe { sys::SBLaunchInfoSetDetachOnError(self.raw, detach) };
257 }
258}
259
260impl Clone for SBLaunchInfo {
261 fn clone(&self) -> SBLaunchInfo {
262 SBLaunchInfo {
263 raw: unsafe { sys::CloneSBLaunchInfo(self.raw) },
264 }
265 }
266}
267
268impl Default for SBLaunchInfo {
269 fn default() -> SBLaunchInfo {
270 SBLaunchInfo::new()
271 }
272}
273
274impl Drop for SBLaunchInfo {
275 fn drop(&mut self) {
276 unsafe { sys::DisposeSBLaunchInfo(self.raw) };
277 }
278}
279
280unsafe impl Send for SBLaunchInfo {}
281unsafe impl Sync for SBLaunchInfo {}
282
283pub struct SBLaunchInfoArgumentsIter<'d> {
284 launch_info: &'d SBLaunchInfo,
285 index: u32,
286}
287
288impl<'d> Iterator for SBLaunchInfoArgumentsIter<'d> {
289 type Item = &'d str;
290
291 fn next(&mut self) -> Option<&'d str> {
292 if self.index < self.launch_info.num_arguments() {
293 self.index += 1;
294 Some(self.launch_info.argument_at_index(self.index - 1))
295 } else {
296 None
297 }
298 }
299
300 fn size_hint(&self) -> (usize, Option<usize>) {
301 let sz = self.launch_info.num_arguments();
302 (sz as usize - self.index as usize, Some(sz as usize))
303 }
304}
305
306impl ExactSizeIterator for SBLaunchInfoArgumentsIter<'_> {}