use std::{
ffi::{c_char, CStr, CString},
marker::PhantomData,
ptr::NonNull,
};
use webui_sys::*;
use crate::{EventType, WebUIError, Window, CONTEXT};
#[repr(transparent)]
pub struct Event<'a> {
pub(crate) inner: NonNull<webui_event_t>,
_marker: PhantomData<&'a webui_event_t>,
}
impl<'a> Event<'a> {
pub(crate) unsafe fn new(ptr: *mut webui_event_t) -> Option<Self> {
NonNull::new(ptr).map(|inner| Self {
inner,
_marker: std::marker::PhantomData,
})
}
pub(crate) fn get_event(&self) -> &webui_event_t {
unsafe { self.inner.as_ref() }
}
pub(crate) fn as_ptr(&self) -> *mut webui_event_t {
self.inner.as_ptr()
}
pub fn window(&self) -> Option<Window> {
let window = self.get_event().window;
CONTEXT
.lock()
.unwrap()
.get(&window)
.and_then(|x| x.upgrade())
.map(|inner| Window { inner })
}
pub(crate) fn bind_id(&self) -> usize {
self.get_event().bind_id
}
pub fn event_type(&self) -> EventType {
unsafe { std::mem::transmute(self.get_event().event_type) }
}
pub fn element(&self) -> String {
let element = self.get_event().element;
unsafe { CStr::from_ptr(element).to_string_lossy().to_string() }
}
pub fn event_number(&self) -> usize {
self.get_event().event_number
}
pub fn client_id(&self) -> usize {
self.get_event().client_id
}
pub fn connection_id(&self) -> usize {
self.get_event().connection_id
}
pub fn cookies(&self) -> Option<String> {
let cookies = self.get_event().cookies;
(!cookies.is_null()).then_some(unsafe { CStr::from_ptr(cookies).to_string_lossy().to_string() })
}
pub fn show_client(&self, content: &str) -> Result<(), WebUIError> {
let content = CString::new(content).unwrap();
let result = unsafe { webui_show_client(self.as_ptr(), content.as_ptr()) };
WebUIError::from_bool(result)
}
pub fn close_client(&self) {
unsafe { webui_close_client(self.as_ptr()) }
}
pub fn navigate_client(&self, url: &str) {
let url = CString::new(url).unwrap();
unsafe { webui_navigate_client(self.as_ptr(), url.as_ptr()) }
}
pub fn run_client(&self, script: &str) {
let script = CString::new(script).unwrap();
unsafe {
webui_run_client(self.as_ptr(), script.as_ptr());
}
}
pub fn script_client(&self, script: &str, timeout: usize, capacity: usize) -> Result<String, WebUIError> {
let mut buffer: Vec<c_char> = Vec::with_capacity(capacity);
let script = CString::new(script).unwrap();
unsafe { webui_script_client(self.as_ptr(), script.as_ptr(), timeout, buffer.as_mut_ptr(), capacity) }
.then(|| unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_string_lossy().to_string())
.ok_or(WebUIError::get_last_error())
}
pub fn get_count(&self) -> usize {
unsafe { webui_get_count(self.as_ptr()) }
}
pub fn get_int(&self) -> i64 {
unsafe { webui_get_int(self.as_ptr()) }
}
pub fn get_int_at(&self, index: usize) -> i64 {
unsafe { webui_get_int_at(self.as_ptr(), index) }
}
pub fn get_float(&self) -> f64 {
unsafe { webui_get_float(self.as_ptr()) }
}
pub fn get_float_at(&self, index: usize) -> f64 {
unsafe { webui_get_float_at(self.as_ptr(), index) }
}
pub fn get_string(&self) -> String {
unsafe {
let ptr = webui_get_string(self.as_ptr());
CStr::from_ptr(ptr).to_string_lossy().to_string()
}
}
pub fn get_string_at(&self, index: usize) -> String {
unsafe {
let ptr = webui_get_string_at(self.as_ptr(), index);
CStr::from_ptr(ptr).to_string_lossy().to_string()
}
}
pub fn get_bool(&self) -> bool {
unsafe { webui_get_bool(self.as_ptr()) }
}
pub fn get_bool_at(&self, index: usize) -> bool {
unsafe { webui_get_bool_at(self.as_ptr(), index) }
}
pub fn get_size(&self) -> usize {
unsafe { webui_get_size(self.as_ptr()) }
}
pub fn get_size_at(&self, index: usize) -> usize {
unsafe { webui_get_size_at(self.as_ptr(), index) }
}
pub fn return_int(&self, value: i64) {
unsafe { webui_return_int(self.as_ptr(), value) }
}
pub fn return_float(&self, value: f64) {
unsafe { webui_return_float(self.as_ptr(), value) }
}
pub fn return_string<S: AsRef<str>>(&self, value: S) {
let c_str = std::ffi::CString::new(value.as_ref()).unwrap_or_default();
unsafe { webui_return_string(self.as_ptr(), c_str.as_ptr()) }
}
pub fn return_bool(&self, value: bool) {
unsafe { webui_return_bool(self.as_ptr(), value) }
}
pub fn send_raw<T>(&self, function: &str, data: T)
where
T: Into<Vec<u8>>,
{
let function = CString::new(function).unwrap();
let data = data.into().into_boxed_slice();
unsafe { webui_send_raw_client(self.as_ptr(), function.as_ptr(), data.as_ptr() as _, data.len()) }
}
}