use std::ffi::{CStr, CString};
use std::marker::PhantomData;
use std::rc::Rc;
use wxdragon_sys as ffi;
pub struct ArrayString {
ptr: *mut ffi::wxd_ArrayString_t,
owns_ptr: bool,
_nosend_nosync: PhantomData<Rc<()>>,
}
impl Clone for ArrayString {
fn clone(&self) -> Self {
assert!(!self.ptr.is_null(), "Cannot clone ArrayString with null pointer");
let new_ptr = unsafe { ffi::wxd_ArrayString_Clone(self.ptr) };
assert!(!new_ptr.is_null(), "Failed to clone wxArrayString");
ArrayString {
ptr: new_ptr,
owns_ptr: true,
_nosend_nosync: PhantomData,
}
}
}
impl ArrayString {
pub fn new() -> Self {
let ptr = unsafe { ffi::wxd_ArrayString_Create() };
assert!(!ptr.is_null(), "Failed to create wxArrayString");
ArrayString {
ptr,
owns_ptr: true,
_nosend_nosync: PhantomData,
}
}
pub fn len(&self) -> usize {
self.get_count()
}
pub fn get_count(&self) -> usize {
unsafe { ffi::wxd_ArrayString_GetCount(self.ptr) as usize }
}
pub fn is_empty(&self) -> bool {
self.get_count() == 0
}
pub fn get_string(&self, index: usize) -> Option<String> {
if index >= self.get_count() {
return None;
}
let index = index as i32;
let len = unsafe { ffi::wxd_ArrayString_GetString(self.ptr, index, std::ptr::null_mut(), 0) };
if len < 0 {
return None; }
let mut buf = vec![0; len as usize + 1];
unsafe { ffi::wxd_ArrayString_GetString(self.ptr, index, buf.as_mut_ptr(), buf.len()) };
Some(unsafe { CStr::from_ptr(buf.as_ptr()).to_string_lossy().into_owned() })
}
pub fn add<T: AsRef<str>>(&mut self, s: T) -> bool {
let c_str = match CString::new(s.as_ref()) {
Ok(cs) => cs,
Err(_) => return false,
};
unsafe { ffi::wxd_ArrayString_Add(self.ptr, c_str.as_ptr()) }
}
pub fn add_many<T: AsRef<str>>(&mut self, strings: &[T]) -> usize {
let mut count = 0;
for s in strings {
if self.add(s) {
count += 1;
}
}
count
}
pub fn clear(&mut self) {
unsafe { ffi::wxd_ArrayString_Clear(self.ptr) };
}
pub fn get_strings(&self) -> Vec<String> {
let count = self.get_count();
let mut vec = Vec::with_capacity(count);
for i in 0..count {
if let Some(s) = self.get_string(i) {
vec.push(s);
} else {
vec.push(String::new());
}
}
vec
}
pub fn as_const_ptr(&self) -> *const ffi::wxd_ArrayString_t {
self.ptr as *const _
}
pub fn as_mut_ptr(&mut self) -> *mut ffi::wxd_ArrayString_t {
self.ptr
}
pub fn into_raw_mut(mut self) -> *mut ffi::wxd_ArrayString_t {
assert!(
self.owns_ptr,
"into_raw_mut can only be called on owning ArrayString instances"
);
let ptr = self.ptr;
self.ptr = std::ptr::null_mut();
ptr
}
pub fn into_raw_const(self) -> *const ffi::wxd_ArrayString_t {
assert!(
!self.owns_ptr,
"into_raw_const must only be used on non-owning (borrowed) wrappers"
);
self.ptr as *const _
}
}
impl Drop for ArrayString {
fn drop(&mut self) {
if !self.ptr.is_null() && self.owns_ptr {
unsafe { ffi::wxd_ArrayString_Free(self.ptr) };
self.ptr = std::ptr::null_mut();
}
}
}
impl Default for ArrayString {
fn default() -> Self {
Self::new()
}
}
impl<T: AsRef<str>> From<Vec<T>> for ArrayString {
fn from(strings: Vec<T>) -> Self {
strings.into_iter().collect()
}
}
impl<T: AsRef<str>> From<&[T]> for ArrayString {
fn from(strings: &[T]) -> Self {
strings.iter().map(|s| s.as_ref()).collect()
}
}
impl<S: AsRef<str>> std::iter::FromIterator<S> for ArrayString {
fn from_iter<I: IntoIterator<Item = S>>(iter: I) -> Self {
let mut array = ArrayString::new();
for s in iter {
array.add(s.as_ref());
}
array
}
}
impl From<ArrayString> for Vec<String> {
fn from(array: ArrayString) -> Self {
array.get_strings()
}
}
impl From<*const ffi::wxd_ArrayString_t> for ArrayString {
fn from(ptr: *const ffi::wxd_ArrayString_t) -> Self {
assert!(!ptr.is_null(), "invalid null pointer passed to ArrayString::from");
ArrayString {
ptr: ptr as *mut _,
owns_ptr: false,
_nosend_nosync: PhantomData,
}
}
}
impl From<*mut ffi::wxd_ArrayString_t> for ArrayString {
fn from(ptr: *mut ffi::wxd_ArrayString_t) -> Self {
assert!(!ptr.is_null(), "invalid null pointer passed to ArrayString::from");
ArrayString {
ptr,
owns_ptr: true,
_nosend_nosync: PhantomData,
}
}
}