#![allow(clippy::forget_ref)]
#![allow(clippy::forget_copy)]
use std::{fmt, mem, ptr, convert::TryFrom};
use crate::{NCurseswWinError, cstring::*, form::{FieldType, FIELDTYPE_ENUM, IsFieldType}};
type Entry = *const i8;
#[derive(PartialEq, Eq, Hash)]
pub struct Enumerate<'a> {
fieldtype: &'a FieldType,
arguments: u8,
value_list: *const Entry,
check_case: bool,
check_unique: bool
}
impl<'a> Enumerate<'a> {
pub fn new(value_list: &[&str], check_case: bool, check_unique: bool) -> result!(Self) {
let entry_handles = unsafe { libc::calloc(value_list.len() + 1, mem::size_of::<Entry>()) as *const Entry };
if entry_handles.is_null() {
Err(NCurseswWinError::OutOfMemory { func: "Enumerate::new".to_string() })
} else {
for (offset, value) in value_list.iter().enumerate() {
let entry = c_str_with_nul!(value);
unsafe { ptr::write(entry_handles.offset(isize::try_from(offset)?) as *mut _, entry.as_ptr()) };
mem::forget(entry);
}
mem::forget(entry_handles);
Ok(Self { fieldtype: &*FIELDTYPE_ENUM, arguments: 3, value_list: entry_handles, check_case, check_unique })
}
}
}
impl<'a> IsFieldType<'a, *const Entry, i32, i32> for Enumerate<'a> {
fn fieldtype(&self) -> &'a FieldType {
self.fieldtype
}
fn arguments(&self) -> u8 {
self.arguments
}
fn arg1(&self) -> *const Entry {
self.value_list
}
fn arg2(&self) -> i32 {
i32::from(self.check_case)
}
fn arg3(&self) -> i32 {
i32::from(self.check_unique)
}
}
impl<'a> Drop for Enumerate<'a> {
fn drop(&mut self) {
let mut offset = 0;
unsafe {
let mut entry_ptr = ptr::read(self.value_list);
while !entry_ptr.is_null() {
libc::free(self.value_list.offset(offset) as *mut libc::c_void);
offset += 1;
entry_ptr = ptr::read(self.value_list.offset(offset));
}
libc::free(self.value_list as *mut libc::c_void);
}
}
}
unsafe impl<'a> Send for Enumerate<'a> { } unsafe impl<'a> Sync for Enumerate<'a> { }
impl <'a>AsRef<Enumerate<'a>> for Enumerate<'a> {
fn as_ref(&self) -> &Self {
self
}
}
impl <'a>AsMut<Enumerate<'a>> for Enumerate<'a> {
fn as_mut(&mut self) -> &mut Self {
self
}
}
impl<'a> fmt::Debug for Enumerate<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{{ fieldtype: {:?}, arguments: {}, value_list: {:p}, check_case: {}, check_unique: {} }}",
self.fieldtype,
self.arguments,
self.value_list,
self.check_case,
self.check_unique
)
}
}