use crate::sys as ffi;
use crate::error::{Error, Result};
use crate::geometry::{Point, Rectangle, Size};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ControlType {
None,
Bool,
Byte,
Unsigned16,
Unsigned32,
Int32,
Int64,
Float,
String,
Rectangle,
Size,
Point,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Direction {
In,
Out,
InOut,
}
#[derive(Debug, Clone)]
pub struct ControlId {
id: u32,
name: &'static str,
control_type: ControlType,
direction: Direction,
}
impl ControlId {
pub const fn new(
id: u32,
name: &'static str,
control_type: ControlType,
direction: Direction,
) -> Self {
Self {
id,
name,
control_type,
direction,
}
}
pub fn id(&self) -> u32 {
self.id
}
pub fn name(&self) -> &'static str {
self.name
}
pub fn control_type(&self) -> ControlType {
self.control_type
}
pub fn direction(&self) -> Direction {
self.direction
}
}
pub struct ControlList {
ptr: *mut ffi::lc_control_list_t,
_owned: bool,
}
unsafe impl Send for ControlList {}
impl ControlList {
pub(crate) fn from_raw(ptr: *mut ffi::lc_control_list_t, owned: bool) -> Self {
Self { ptr, _owned: owned }
}
pub fn size(&self) -> usize {
unsafe { ffi::lc_control_list_size(self.ptr) }
}
pub fn contains(&self, id: &ControlId) -> bool {
unsafe { ffi::lc_control_list_contains(self.ptr, id.id()) }
}
pub fn get_bool(&self, id: &ControlId) -> Result<bool> {
let mut out = false;
let ok = unsafe { ffi::lc_control_list_get_bool(self.ptr, id.id(), &mut out) };
if ok {
Ok(out)
} else {
Err(Error::ControlGetFailed)
}
}
pub fn get_i32(&self, id: &ControlId) -> Result<i32> {
let mut out = 0i32;
let ok = unsafe { ffi::lc_control_list_get_int32(self.ptr, id.id(), &mut out) };
if ok {
Ok(out)
} else {
Err(Error::ControlGetFailed)
}
}
pub fn get_i64(&self, id: &ControlId) -> Result<i64> {
let mut out = 0i64;
let ok = unsafe { ffi::lc_control_list_get_int64(self.ptr, id.id(), &mut out) };
if ok {
Ok(out)
} else {
Err(Error::ControlGetFailed)
}
}
pub fn get_f32(&self, id: &ControlId) -> Result<f32> {
let mut out = 0.0f32;
let ok = unsafe { ffi::lc_control_list_get_float(self.ptr, id.id(), &mut out) };
if ok {
Ok(out)
} else {
Err(Error::ControlGetFailed)
}
}
pub fn get_string(&self, id: &ControlId) -> Result<&str> {
let mut ptr = std::ptr::null();
let mut len = 0usize;
let ok = unsafe { ffi::lc_control_list_get_string(self.ptr, id.id(), &mut ptr, &mut len) };
if ok && !ptr.is_null() {
let bytes = unsafe { std::slice::from_raw_parts(ptr.cast::<u8>(), len) };
std::str::from_utf8(bytes).map_err(|_| Error::ControlGetFailed)
} else {
Err(Error::ControlGetFailed)
}
}
pub fn get_size(&self, id: &ControlId) -> Result<Size> {
let mut out = ffi::lc_size_t::default();
let ok = unsafe { ffi::lc_control_list_get_size(self.ptr, id.id(), &mut out) };
if ok {
Ok(Size::from_raw(out))
} else {
Err(Error::ControlGetFailed)
}
}
pub fn get_rectangle(&self, id: &ControlId) -> Result<Rectangle> {
let mut out = ffi::lc_rectangle_t::default();
let ok = unsafe { ffi::lc_control_list_get_rectangle(self.ptr, id.id(), &mut out) };
if ok {
Ok(Rectangle::from_raw(out))
} else {
Err(Error::ControlGetFailed)
}
}
pub fn get_f32_array(&self, id: &ControlId) -> Result<&[f32]> {
let mut ptr = std::ptr::null();
let mut count = 0usize;
let ok = unsafe {
ffi::lc_control_list_get_float_array(self.ptr, id.id(), &mut ptr, &mut count)
};
if ok && !ptr.is_null() {
Ok(unsafe { std::slice::from_raw_parts(ptr, count) })
} else {
Err(Error::ControlGetFailed)
}
}
pub fn get_i32_array(&self, id: &ControlId) -> Result<&[i32]> {
let mut ptr = std::ptr::null();
let mut count = 0usize;
let ok = unsafe {
ffi::lc_control_list_get_int32_array(self.ptr, id.id(), &mut ptr, &mut count)
};
if ok && !ptr.is_null() {
Ok(unsafe { std::slice::from_raw_parts(ptr, count) })
} else {
Err(Error::ControlGetFailed)
}
}
pub fn get_i64_array(&self, id: &ControlId) -> Result<&[i64]> {
let mut ptr = std::ptr::null();
let mut count = 0usize;
let ok = unsafe {
ffi::lc_control_list_get_int64_array(self.ptr, id.id(), &mut ptr, &mut count)
};
if ok && !ptr.is_null() {
Ok(unsafe { std::slice::from_raw_parts(ptr, count) })
} else {
Err(Error::ControlGetFailed)
}
}
pub fn get_u8(&self, id: &ControlId) -> Result<u8> {
let mut out = 0u8;
let ok = unsafe { ffi::lc_control_list_get_byte(self.ptr, id.id(), &mut out) };
if ok {
Ok(out)
} else {
Err(Error::ControlGetFailed)
}
}
pub fn get_u8_array(&self, id: &ControlId) -> Result<&[u8]> {
let mut ptr = std::ptr::null();
let mut count = 0usize;
let ok =
unsafe { ffi::lc_control_list_get_byte_array(self.ptr, id.id(), &mut ptr, &mut count) };
if ok && !ptr.is_null() {
Ok(unsafe { std::slice::from_raw_parts(ptr, count) })
} else {
Err(Error::ControlGetFailed)
}
}
pub fn get_rectangle_array(&self, id: &ControlId) -> Result<Vec<Rectangle>> {
let mut ptr: *const ffi::lc_rectangle_t = std::ptr::null();
let mut count = 0usize;
let ok = unsafe {
ffi::lc_control_list_get_rectangle_array(self.ptr, id.id(), &mut ptr, &mut count)
};
if ok && !ptr.is_null() {
let slice = unsafe { std::slice::from_raw_parts(ptr, count) };
Ok(slice.iter().map(|r| Rectangle::from_raw(*r)).collect())
} else {
Err(Error::ControlGetFailed)
}
}
pub fn get_point_array(&self, id: &ControlId) -> Result<Vec<Point>> {
let mut ptr: *const ffi::lc_point_t = std::ptr::null();
let mut count = 0usize;
let ok = unsafe {
ffi::lc_control_list_get_point_array(self.ptr, id.id(), &mut ptr, &mut count)
};
if ok && !ptr.is_null() {
let slice = unsafe { std::slice::from_raw_parts(ptr, count) };
Ok(slice.iter().map(|p| Point::from_raw(*p)).collect())
} else {
Err(Error::ControlGetFailed)
}
}
pub fn set_bool(&mut self, id: &ControlId, value: bool) {
unsafe { ffi::lc_control_list_set_bool(self.ptr, id.id(), value) };
}
pub fn set_i32(&mut self, id: &ControlId, value: i32) {
unsafe { ffi::lc_control_list_set_int32(self.ptr, id.id(), value) };
}
pub fn set_i64(&mut self, id: &ControlId, value: i64) {
unsafe { ffi::lc_control_list_set_int64(self.ptr, id.id(), value) };
}
pub fn set_f32(&mut self, id: &ControlId, value: f32) {
unsafe { ffi::lc_control_list_set_float(self.ptr, id.id(), value) };
}
pub fn set_rectangle(&mut self, id: &ControlId, value: Rectangle) {
unsafe { ffi::lc_control_list_set_rectangle(self.ptr, id.id(), value.to_raw()) };
}
pub fn set_f32_array(&mut self, id: &ControlId, values: &[f32]) {
unsafe {
ffi::lc_control_list_set_float_array(self.ptr, id.id(), values.as_ptr(), values.len())
};
}
pub fn set_i32_array(&mut self, id: &ControlId, values: &[i32]) {
unsafe {
ffi::lc_control_list_set_int32_array(self.ptr, id.id(), values.as_ptr(), values.len())
};
}
pub fn set_i64_array(&mut self, id: &ControlId, values: &[i64]) {
unsafe {
ffi::lc_control_list_set_int64_array(self.ptr, id.id(), values.as_ptr(), values.len())
};
}
pub fn set_u8(&mut self, id: &ControlId, value: u8) {
unsafe { ffi::lc_control_list_set_byte(self.ptr, id.id(), value) };
}
pub fn set_u8_array(&mut self, id: &ControlId, values: &[u8]) {
unsafe {
ffi::lc_control_list_set_byte_array(self.ptr, id.id(), values.as_ptr(), values.len())
};
}
pub fn set_rectangle_array(&mut self, id: &ControlId, values: &[Rectangle]) {
let raw: Vec<ffi::lc_rectangle_t> = values.iter().map(|r| r.to_raw()).collect();
unsafe {
ffi::lc_control_list_set_rectangle_array(self.ptr, id.id(), raw.as_ptr(), raw.len())
};
}
pub fn set_point_array(&mut self, id: &ControlId, values: &[Point]) {
let raw: Vec<ffi::lc_point_t> = values.iter().map(|p| p.to_raw()).collect();
unsafe { ffi::lc_control_list_set_point_array(self.ptr, id.id(), raw.as_ptr(), raw.len()) };
}
}
impl Drop for ControlList {
fn drop(&mut self) {
unsafe { ffi::lc_control_list_ref_destroy(self.ptr) };
}
}