Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 10 additions & 17 deletions whatsrust/src/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@ pub trait CallbackTranslator<T> {
unsafe fn to_rust(c_value: T) -> Self;
}

// impl<T, U: From<T>> CallbackTranslator<T> for U {
// unsafe fn to_rust(c_value: T) -> Self {
// Self::from(c_value)
// }
// }

macro_rules! setup_handler {
($fn_name:ident, $c_func:ident) => {
setup_handler!($fn_name, $c_func,);
Expand All @@ -23,30 +17,29 @@ macro_rules! setup_handler {
where
F: FnMut($($rs_type),*) + 'static,
{
// Go has no unregister API, so this allocation intentionally lives for the
// process lifetime. The shim must only borrow it; reconstructing a Box on
// each call creates concurrent owners for the same allocation.
type CallbackType = dyn FnMut($($rs_type),*);
let callback: Box<CallbackType> = Box::new(callback);
let callback_state = Box::new(std::sync::Arc::new(std::sync::Mutex::new(callback)));
let callback_state = Box::new(std::sync::Arc::new(
std::sync::Mutex::new(callback),
));
let user_data = Box::into_raw(callback_state) as *mut std::ffi::c_void;

// Shim callback compatible with C
extern "C" fn shim(
$( $param_name: $c_type, )*
user_data: *mut std::ffi::c_void
) {
unsafe {
let callback_state =
&*(user_data
as *const std::sync::Arc<std::sync::Mutex<Box<CallbackType>>>);
let callback_state = &*(user_data
as *const std::sync::Arc<
std::sync::Mutex<Box<CallbackType>>,
>);
let closure = std::sync::Arc::clone(callback_state);
let mut guard = closure.lock().unwrap();

guard($(
<$rs_type>::to_rust($param_name),
<$rs_type as $crate::callbacks::CallbackTranslator<$c_type>>::to_rust(
$param_name,
),
)*);

}
}

Expand Down
79 changes: 6 additions & 73 deletions whatsrust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::{

#[macro_use]
mod callbacks;
mod registrations;
mod abi;
mod caches;
mod events;
Expand All @@ -17,7 +18,11 @@ mod models;
use abi::*;
pub use abi::{LogoutStatus, ReceiptKind};
pub use events::set_event_handler;
use callbacks::CallbackTranslator;
pub use callbacks::CallbackTranslator;
pub use registrations::{
connect, set_log_handler, set_message_handler,
set_optimistic_text_sent_handler, set_presence_handler,
};
pub(crate) use models::file_kind_discriminant;
pub use models::{
ChatSettings, CommunitiesError, CommunityInfo, Contact, DownloadFailed, Event, FileContent,
Expand Down Expand Up @@ -656,78 +661,6 @@ impl CallbackTranslator<i64> for i64 {
}
}

pub fn set_presence_handler<F>(mut callback: F)
where
F: FnMut(PresenceUpdate) + 'static,
{
setup_presence_handler(move |from, unavailable, last_seen| {
if std::env::var("WPTUI_PRESENCE_DEBUG").as_deref() == Ok("1") {
PRESENCE_CALLBACK_INGRESS.fetch_add(1, Ordering::Relaxed);
}
callback(PresenceUpdate {
from,
unavailable,
last_seen,
});
});
}

setup_handler!(
setup_presence_handler,
C_SetPresenceHandler,
from: CJID => JID,
unavailable: bool => bool,
last_seen: i64 => i64
);

impl CallbackTranslator<bool> for bool {
unsafe fn to_rust(ptr: bool) -> bool {
ptr
}
}

impl CallbackTranslator<u64> for u64 {
unsafe fn to_rust(value: u64) -> Self {
value
}
}

setup_handler!(
set_message_handler,
C_SetMessageHandler,
msg: *const CMessage => Message,
is_sync: bool => bool
);

setup_handler!(
set_optimistic_text_sent_handler,
C_SetOptimisticTextSentHandler,
local_send_id: u64 => u64,
msg: *const CMessage => Message
);

impl CallbackTranslator<*const c_char> for String {
unsafe fn to_rust(ptr: *const c_char) -> String {
let c_str = unsafe { CStr::from_ptr(ptr) };
c_str.to_string_lossy().into_owned()
}
}

impl CallbackTranslator<u8> for u8 {
unsafe fn to_rust(ptr: u8) -> u8 {
ptr
}
}

setup_handler!(
set_log_handler,
C_SetLogHandler,
msg: *const c_char => String,
level: u8 => u8
);

setup_handler!(connect, C_Connect, qr: *const c_char => String);

pub fn disconnect() {
unsafe { C_Disconnect() }
}
Expand Down
73 changes: 73 additions & 0 deletions whatsrust/src/registrations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use super::*;

impl CallbackTranslator<bool> for bool {
unsafe fn to_rust(value: bool) -> Self {
value
}
}

impl CallbackTranslator<u64> for u64 {
unsafe fn to_rust(value: u64) -> Self {
value
}
}

impl CallbackTranslator<*const c_char> for String {
unsafe fn to_rust(ptr: *const c_char) -> String {
let c_str = unsafe { CStr::from_ptr(ptr) };
c_str.to_string_lossy().into_owned()
}
}

impl CallbackTranslator<u8> for u8 {
unsafe fn to_rust(value: u8) -> Self {
value
}
}

pub fn set_presence_handler<F>(mut callback: F)
where
F: FnMut(PresenceUpdate) + 'static,
{
setup_presence_handler(move |from, unavailable, last_seen| {
if std::env::var("WPTUI_PRESENCE_DEBUG").as_deref() == Ok("1") {
PRESENCE_CALLBACK_INGRESS.fetch_add(1, Ordering::Relaxed);
}
callback(PresenceUpdate {
from,
unavailable,
last_seen,
});
});
}

setup_handler!(
setup_presence_handler,
C_SetPresenceHandler,
from: CJID => JID,
unavailable: bool => bool,
last_seen: i64 => i64
);

setup_handler!(
set_message_handler,
C_SetMessageHandler,
msg: *const CMessage => Message,
is_sync: bool => bool
);

setup_handler!(
set_optimistic_text_sent_handler,
C_SetOptimisticTextSentHandler,
local_send_id: u64 => u64,
msg: *const CMessage => Message
);

setup_handler!(
set_log_handler,
C_SetLogHandler,
msg: *const c_char => String,
level: u8 => u8
);

setup_handler!(connect, C_Connect, qr: *const c_char => String);
Loading