tauri-plugin-bare-kit 0.2.1

Effortless JavaScript backends for Tauri apps - Android 🤖 iOS 📱Linux 🐧 Macos 🖥️ Windows 💩
use std::{ffi::c_void, ptr::null_mut, slice};

use crate::runtime::bare_kit::ffi::*;

pub(crate) fn ipc_new(worklet: *mut bare_worklet_t) -> *mut bare_ipc_t {
    let mut ipc: *mut bare_ipc_t = null_mut();
    let err = unsafe { bare_ipc_alloc(&mut ipc) };
    assert!(err == 0);

    let err = unsafe { bare_ipc_init(ipc, worklet) };
    assert!(err == 0);

    ipc
}

pub(crate) fn ipc_destroy(ipc: *mut bare_ipc_t) {
    unsafe { bare_ipc_destroy(ipc) };
}

#[allow(dead_code)]
pub(crate) fn ipc_get_incoming(ipc: *mut bare_ipc_t) -> i32 {
    unsafe { bare_ipc_get_incoming(ipc) }
}

#[allow(dead_code)]
pub(crate) fn ipc_get_outgoing(ipc: *mut bare_ipc_t) -> i32 {
    unsafe { bare_ipc_get_outgoing(ipc) }
}

pub(crate) fn ipc_read(ipc: *mut bare_ipc_t) -> Option<Vec<u8>> {
    let mut len: usize = 0;
    let mut data = null_mut();
    let err = unsafe { bare_ipc_read(ipc, &mut data, &mut len) };
    assert!(err == 0 || err == bare_ipc_would_block);

    if err == bare_ipc_would_block {
        return None;
    }

    Some(unsafe { slice::from_raw_parts(data as *mut u8, len).to_vec() })
}

pub(crate) fn ipc_write(ipc: *mut bare_ipc_t, data: Option<Vec<u8>>) -> i32 {
    let err = match data {
        Some(data) => unsafe { bare_ipc_write(ipc, data.as_ptr() as *const _, data.len()) },
        None => unsafe { bare_ipc_write(ipc, null_mut(), 0) },
    };
    assert!(err >= 0 || err == bare_ipc_would_block);

    if err == bare_ipc_would_block {
        return 0;
    }

    err
}

struct PollCallback(Box<dyn FnMut(bool, bool)>);

pub(crate) fn ipc_poll_new(ipc: *mut bare_ipc_t) -> *mut bare_ipc_poll_t {
    let mut poll: *mut bare_ipc_poll_t = null_mut();
    let err = unsafe { bare_ipc_poll_alloc(&mut poll) };
    assert!(err == 0);

    let err = unsafe { bare_ipc_poll_init(poll, ipc) };
    assert!(err == 0);

    poll
}

pub(crate) fn ipc_poll_destroy(poll: *mut bare_ipc_poll_t) {
    unsafe { bare_ipc_poll_destroy(poll) };
}

#[allow(dead_code)]
pub(crate) fn ipc_poll_get_ipc(poll: *mut bare_ipc_poll_t) -> *mut bare_ipc_t {
    unsafe { bare_ipc_poll_get_ipc(poll) }
}

pub(crate) fn ipc_poll_start<F>(poll: *mut bare_ipc_poll_t, events: i32, callback: F) -> i32
where
    F: FnMut(bool, bool) + 'static,
{
    let callback = Box::new(PollCallback(Box::new(callback)));
    unsafe {
        bare_ipc_poll_set_data(poll, Box::into_raw(callback) as *mut c_void);
        bare_ipc_poll_start(poll, events, Some(on_poll))
    }
}

pub(crate) fn ipc_poll_stop(poll: *mut bare_ipc_poll_t) -> i32 {
    unsafe { bare_ipc_poll_stop(poll) }
}

unsafe extern "C" fn on_poll(poll: *mut bare_ipc_poll_t, events: i32) {
    let callback_ptr = bare_ipc_poll_get_data(poll) as *mut PollCallback;

    if !callback_ptr.is_null() {
        let callback = &mut *callback_ptr;
        let readable = (events & bare_ipc_readable as i32) != 0;
        let writable = (events & bare_ipc_writable as i32) != 0;

        (callback.0)(readable, writable);
    }
}