1use ffi_convert_derive::RawPointerConverter;
5
6use std::any::TypeId;
7use std::ffi::{CStr, CString};
8use std::ops::Range;
9use std::ptr;
10
11use crate as ffi_convert;
12use crate::conversions::*;
13
14#[repr(C)]
24#[derive(Debug, RawPointerConverter)]
25pub struct CStringArray {
26 pub data: *const *const libc::c_char,
28 pub size: usize,
30}
31
32unsafe impl Sync for CStringArray {}
33
34impl AsRust<Vec<String>> for CStringArray {
35 fn as_rust(&self) -> Result<Vec<String>, AsRustError> {
36 let mut result = vec![];
37
38 let strings = unsafe {
39 std::slice::from_raw_parts_mut(self.data as *mut *mut libc::c_char, self.size)
40 };
41
42 for s in strings {
43 result.push(unsafe { CStr::raw_borrow(*s) }?.as_rust()?)
44 }
45
46 Ok(result)
47 }
48}
49
50impl CReprOf<Vec<String>> for CStringArray {
51 fn c_repr_of(input: Vec<String>) -> Result<Self, CReprOfError> {
52 Ok(Self {
53 size: input.len(),
54 data: Box::into_raw(
55 input
56 .into_iter()
57 .map::<Result<*const libc::c_char, CReprOfError>, _>(|s| {
58 Ok(CString::c_repr_of(s)?.into_raw_pointer())
59 })
60 .collect::<Result<Vec<_>, _>>()?
61 .into_boxed_slice(),
62 ) as *const *const libc::c_char,
63 })
64 }
65}
66
67impl CDrop for CStringArray {
68 fn do_drop(&mut self) -> Result<(), CDropError> {
69 unsafe {
70 let y = Box::from_raw(std::slice::from_raw_parts_mut(
71 self.data as *mut *mut libc::c_char,
72 self.size,
73 ));
74 for p in y.iter() {
75 let _ = CString::from_raw_pointer(*p)?; }
77 }
78 Ok(())
79 }
80}
81
82impl Drop for CStringArray {
83 fn drop(&mut self) {
84 let _ = self.do_drop();
85 }
86}
87
88#[repr(C)]
115#[derive(Debug)]
116pub struct CArray<T> {
117 pub data_ptr: *const T,
119 pub size: usize,
121}
122
123impl<U: AsRust<V> + 'static, V> AsRust<Vec<V>> for CArray<U> {
124 fn as_rust(&self) -> Result<Vec<V>, AsRustError> {
125 let mut vec = Vec::with_capacity(self.size);
126
127 if self.size > 0 {
128 let values =
129 unsafe { std::slice::from_raw_parts_mut(self.data_ptr as *mut U, self.size) };
130
131 if is_primitive(TypeId::of::<U>()) {
132 unsafe {
133 ptr::copy(values.as_ptr() as *const V, vec.as_mut_ptr(), self.size);
134 vec.set_len(self.size);
135 }
136 } else {
137 for value in values {
138 vec.push(value.as_rust()?);
139 }
140 }
141 }
142 Ok(vec)
143 }
144}
145
146impl<U: CReprOf<V> + CDrop, V: 'static> CReprOf<Vec<V>> for CArray<U> {
147 fn c_repr_of(input: Vec<V>) -> Result<Self, CReprOfError> {
148 let input_size = input.len();
149 let mut output: CArray<U> = CArray {
150 data_ptr: ptr::null(),
151 size: input_size,
152 };
153
154 if input_size > 0 {
155 if is_primitive(TypeId::of::<V>()) {
156 output.data_ptr = Box::into_raw(input.into_boxed_slice()) as *const U;
157 } else {
158 output.data_ptr = Box::into_raw(
159 input
160 .into_iter()
161 .map(U::c_repr_of)
162 .collect::<Result<Vec<_>, CReprOfError>>()
163 .expect("Could not convert to C representation")
164 .into_boxed_slice(),
165 ) as *const U;
166 }
167 } else {
168 output.data_ptr = ptr::null();
169 }
170 Ok(output)
171 }
172}
173
174impl<T> CDrop for CArray<T> {
175 fn do_drop(&mut self) -> Result<(), CDropError> {
176 if !self.data_ptr.is_null() {
177 let _ = unsafe {
178 Box::from_raw(std::slice::from_raw_parts_mut(
179 self.data_ptr as *mut T,
180 self.size,
181 ))
182 };
183 }
184 Ok(())
185 }
186}
187
188impl<T> Drop for CArray<T> {
189 fn drop(&mut self) {
190 let _ = self.do_drop();
191 }
192}
193
194impl<T> RawPointerConverter<CArray<T>> for CArray<T> {
195 fn into_raw_pointer(self) -> *const CArray<T> {
196 convert_into_raw_pointer(self)
197 }
198
199 fn into_raw_pointer_mut(self) -> *mut CArray<T> {
200 convert_into_raw_pointer_mut(self)
201 }
202
203 unsafe fn from_raw_pointer(
204 input: *const CArray<T>,
205 ) -> Result<Self, UnexpectedNullPointerError> {
206 take_back_from_raw_pointer(input)
207 }
208
209 unsafe fn from_raw_pointer_mut(
210 input: *mut CArray<T>,
211 ) -> Result<Self, UnexpectedNullPointerError> {
212 take_back_from_raw_pointer_mut(input)
213 }
214}
215
216fn is_primitive(id: TypeId) -> bool {
217 id == TypeId::of::<u8>()
218 || id == TypeId::of::<i8>()
219 || id == TypeId::of::<u16>()
220 || id == TypeId::of::<i16>()
221 || id == TypeId::of::<u32>()
222 || id == TypeId::of::<i32>()
223 || id == TypeId::of::<f32>()
224 || id == TypeId::of::<f64>()
225}
226
227#[repr(C)]
268#[derive(Clone, Debug, PartialEq, Eq)]
269pub struct CRange<T> {
270 pub start: T,
271 pub end: T,
272}
273
274impl<U: AsRust<V>, V: PartialOrd + PartialEq> AsRust<Range<V>> for CRange<U> {
275 fn as_rust(&self) -> Result<Range<V>, AsRustError> {
276 Ok(Range {
277 start: self.start.as_rust()?,
278 end: self.end.as_rust()?,
279 })
280 }
281}
282
283impl<U: CReprOf<V> + CDrop, V: PartialOrd + PartialEq> CReprOf<Range<V>> for CRange<U> {
284 fn c_repr_of(input: Range<V>) -> Result<Self, CReprOfError> {
285 Ok(Self {
286 start: U::c_repr_of(input.start)?,
287 end: U::c_repr_of(input.end)?,
288 })
289 }
290}
291
292impl<T> CDrop for CRange<T> {
293 fn do_drop(&mut self) -> Result<(), CDropError> {
294 Ok(())
295 }
296}
297
298impl<T> Drop for CRange<T> {
299 fn drop(&mut self) {
300 let _ = self.do_drop();
301 }
302}