use crate::*; use paste::paste; use std::{convert::TryFrom, ffi::c_void, mem::size_of}; // Can't be autogenerated by bindgen since these are defined in a header. macro_rules! apk_array_funcs { ($x:ident) => { impl Drop for $x { fn drop(&mut self) { if self.num != 0 { unsafe { apk_array_resize(self as *mut Self as *mut c_void, 0, 0) }; } } } }; ($x:ident, $type:ty) => { apk_array_funcs!($x); paste! { pub unsafe fn [<$x _resize>](a: *mut *mut $x, size: usize) { *a = apk_array_resize(*a as *mut c_void, size, size_of::<$type>()) as *mut $x } pub unsafe fn [<$x _add>](a: *mut *mut $x) -> *mut $type { let size = (*(*a)).num + 1; [<$x _resize>](a, size); &mut (*(*a)).item.as_mut_slice(size)[size - 1] as *mut $type } pub unsafe fn [<$x _copy>](a: *mut *mut $x , b: *mut $x) { if *a == b { return; } [<$x _resize>](a, (*b).num); std::ptr::copy_nonoverlapping((*b).item.as_ptr(), (*(*a)).item.as_mut_ptr(), (*b).num); } } impl $x { pub fn as_slice(&self) -> Result<&[$type], std::num::TryFromIntError> { Ok(unsafe { self.item.as_slice(usize::try_from(self.num)?) }) } pub fn as_mut_slice(&mut self) -> Result<&mut [$type], std::num::TryFromIntError> { Ok(unsafe { self.item.as_mut_slice(usize::try_from(self.num)?) }) } pub fn iter(&self) -> Result, std::num::TryFromIntError> { self.as_slice().map(|s| s.iter()) } pub fn iter_mut( &mut self, ) -> Result, std::num::TryFromIntError> { self.as_mut_slice().map(|s| s.iter_mut()) } } }; } apk_array_funcs!(apk_string_array, *mut std::os::raw::c_char); apk_array_funcs!(apk_hash_array, hlist_head); apk_array_funcs!(apk_xattr_array, apk_xattr); apk_array_funcs!(apk_provider_array, apk_provider); apk_array_funcs!(apk_dependency_array, apk_dependency); apk_array_funcs!(apk_package_array, *mut apk_package); apk_array_funcs!(apk_name_array, *mut apk_name); apk_array_funcs!(apk_protected_path_array, apk_protected_path); apk_array_funcs!(apk_change_array, apk_change); impl Drop for apk_changeset { fn drop(&mut self) { unsafe { apk_array_resize(self.changes.cast(), 0, 0) }; } }