std/sys/process/unix/common/
cstring_array.rs1use crate::ffi::{CStr, CString, c_char};
2use crate::ops::Index;
3use crate::{fmt, mem, ptr};
4
5pub struct CStringArray {
11 ptrs: Vec<*const c_char>,
12}
13
14impl CStringArray {
15 pub fn with_capacity(capacity: usize) -> Self {
18 let mut result = CStringArray { ptrs: Vec::with_capacity(capacity + 1) };
19 result.ptrs.push(ptr::null());
20 result
21 }
22
23 pub fn write(&mut self, index: usize, item: CString) {
25 let argc = self.ptrs.len() - 1;
26 let ptr = &mut self.ptrs[..argc][index];
27 let old = mem::replace(ptr, item.into_raw());
28 drop(unsafe { CString::from_raw(old.cast_mut()) });
33 }
34
35 pub fn push(&mut self, item: CString) {
37 let argc = self.ptrs.len() - 1;
38 self.ptrs.push(ptr::null());
42 self.ptrs[argc] = item.into_raw();
44 }
45
46 pub fn as_ptr(&self) -> *const *const c_char {
48 self.ptrs.as_ptr()
49 }
50
51 pub fn iter(&self) -> CStringIter<'_> {
53 CStringIter { iter: self.ptrs[..self.ptrs.len() - 1].iter() }
54 }
55}
56
57impl Index<usize> for CStringArray {
58 type Output = CStr;
59 fn index(&self, index: usize) -> &CStr {
60 let ptr = self.ptrs[..self.ptrs.len() - 1][index];
61 unsafe { CStr::from_ptr(ptr) }
65 }
66}
67
68impl fmt::Debug for CStringArray {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 f.debug_list().entries(self.iter()).finish()
71 }
72}
73
74unsafe impl Send for CStringArray {}
76unsafe impl Sync for CStringArray {}
78
79impl Drop for CStringArray {
80 fn drop(&mut self) {
81 self.ptrs[..self.ptrs.len() - 1]
85 .iter()
86 .for_each(|&p| drop(unsafe { CString::from_raw(p.cast_mut()) }))
87 }
88}
89
90#[derive(Clone)]
92pub struct CStringIter<'a> {
93 iter: crate::slice::Iter<'a, *const c_char>,
94}
95
96impl<'a> Iterator for CStringIter<'a> {
97 type Item = &'a CStr;
98 fn next(&mut self) -> Option<&'a CStr> {
99 self.iter.next().map(|&p| unsafe { CStr::from_ptr(p) })
103 }
104
105 fn size_hint(&self) -> (usize, Option<usize>) {
106 self.iter.size_hint()
107 }
108}
109
110impl<'a> ExactSizeIterator for CStringIter<'a> {
111 fn len(&self) -> usize {
112 self.iter.len()
113 }
114 fn is_empty(&self) -> bool {
115 self.iter.is_empty()
116 }
117}