use tokio::sync::oneshot;
pub struct SwiftAsyncCallback<T> {
sender: oneshot::Sender<T>,
}
pub fn create_swift_async_call<T: Send + 'static>(
) -> (impl std::future::Future<Output = T>, *mut std::ffi::c_void) {
let (tx, rx) = oneshot::channel::<T>();
let wrapper = Box::new(SwiftAsyncCallback { sender: tx });
let ptr = Box::into_raw(wrapper) as *mut std::ffi::c_void;
let future = async move {
rx.await
.expect("Swift async callback was dropped without sending a result")
};
(future, ptr)
}
pub unsafe fn complete_swift_async<T>(wrapper_ptr: *mut std::ffi::c_void, result: T) {
let wrapper = Box::from_raw(wrapper_ptr as *mut SwiftAsyncCallback<T>);
let _ = wrapper.sender.send(result);
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_create_and_complete_async_call() {
let (future, wrapper_ptr) = create_swift_async_call::<u32>();
unsafe {
complete_swift_async(wrapper_ptr, 42u32);
}
let result = future.await;
assert_eq!(result, 42);
}
#[tokio::test]
async fn test_async_call_with_string() {
let (future, wrapper_ptr) = create_swift_async_call::<String>();
unsafe {
complete_swift_async(wrapper_ptr, "hello".to_string());
}
let result = future.await;
assert_eq!(result, "hello");
}
#[tokio::test]
async fn test_async_call_with_result_ok() {
let (future, wrapper_ptr) = create_swift_async_call::<Result<u32, String>>();
unsafe {
complete_swift_async(wrapper_ptr, Ok::<u32, String>(123));
}
let result = future.await;
assert_eq!(result, Ok(123));
}
#[tokio::test]
async fn test_async_call_with_result_err() {
let (future, wrapper_ptr) = create_swift_async_call::<Result<u32, String>>();
unsafe {
complete_swift_async(wrapper_ptr, Err::<u32, String>("error".to_string()));
}
let result = future.await;
assert_eq!(result, Err("error".to_string()));
}
#[tokio::test]
async fn test_async_call_with_unit() {
let (future, wrapper_ptr) = create_swift_async_call::<()>();
unsafe {
complete_swift_async(wrapper_ptr, ());
}
future.await;
}
}