123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
- // SPDX-License-Identifier: Apache-2.0
- // SPDX-License-Identifier: MIT
- use cocoa::base::{id, nil, NO, YES};
- use objc::*;
- use serde_json::Value as JsonValue;
- use swift_rs::{swift, SRString, SwiftArg};
- use std::{
- ffi::c_void,
- os::raw::{c_char, c_int},
- };
- type PluginMessageCallbackFn = unsafe extern "C" fn(c_int, c_int, *const c_char);
- pub struct PluginMessageCallback(pub PluginMessageCallbackFn);
- impl<'a> SwiftArg<'a> for PluginMessageCallback {
- type ArgType = PluginMessageCallbackFn;
- unsafe fn as_arg(&'a self) -> Self::ArgType {
- self.0
- }
- }
- swift!(pub fn post_ipc_message(
- webview: *const c_void,
- name: &SRString,
- method: &SRString,
- data: *const c_void,
- callback: usize,
- error: usize
- ));
- swift!(pub fn run_plugin_method(
- id: i32,
- name: &SRString,
- method: &SRString,
- data: *const c_void,
- callback: PluginMessageCallback
- ));
- swift!(pub fn register_plugin(
- name: &SRString,
- plugin: *const c_void,
- config: *const c_void,
- webview: *const c_void
- ));
- swift!(pub fn on_webview_created(webview: *const c_void, controller: *const c_void));
- pub fn json_to_dictionary(json: &JsonValue) -> id {
- if let serde_json::Value::Object(map) = json {
- unsafe {
- let dictionary: id = msg_send![class!(NSMutableDictionary), alloc];
- let data: id = msg_send![dictionary, init];
- for (key, value) in map {
- add_json_entry_to_dictionary(data, key, value);
- }
- data
- }
- } else {
- nil
- }
- }
- const UTF8_ENCODING: usize = 4;
- struct NSString(id);
- impl NSString {
- fn new(s: &str) -> Self {
- // Safety: objc runtime calls are unsafe
- NSString(unsafe {
- let ns_string: id = msg_send![class!(NSString), alloc];
- let ns_string: id = msg_send![ns_string,
- initWithBytes:s.as_ptr()
- length:s.len()
- encoding:UTF8_ENCODING];
- // The thing is allocated in rust, the thing must be set to autorelease in rust to relinquish control
- // or it can not be released correctly in OC runtime
- let _: () = msg_send![ns_string, autorelease];
- ns_string
- })
- }
- }
- unsafe fn add_json_value_to_array(array: id, value: &JsonValue) {
- match value {
- JsonValue::Null => {
- let null: id = msg_send![class!(NSNull), null];
- let () = msg_send![array, addObject: null];
- }
- JsonValue::Bool(val) => {
- let value = if *val { YES } else { NO };
- let v: id = msg_send![class!(NSNumber), numberWithBool: value];
- let () = msg_send![array, addObject: v];
- }
- JsonValue::Number(val) => {
- let number: id = if let Some(v) = val.as_i64() {
- msg_send![class!(NSNumber), numberWithInteger: v]
- } else if let Some(v) = val.as_u64() {
- msg_send![class!(NSNumber), numberWithUnsignedLongLong: v]
- } else if let Some(v) = val.as_f64() {
- msg_send![class!(NSNumber), numberWithDouble: v]
- } else {
- unreachable!()
- };
- let () = msg_send![array, addObject: number];
- }
- JsonValue::String(val) => {
- let () = msg_send![array, addObject: NSString::new(&val)];
- }
- JsonValue::Array(val) => {
- let nsarray: id = msg_send![class!(NSMutableArray), alloc];
- let inner_array: id = msg_send![nsarray, init];
- for value in val {
- add_json_value_to_array(inner_array, value);
- }
- let () = msg_send![array, addObject: inner_array];
- }
- JsonValue::Object(val) => {
- let dictionary: id = msg_send![class!(NSMutableDictionary), alloc];
- let data: id = msg_send![dictionary, init];
- for (key, value) in val {
- add_json_entry_to_dictionary(data, key, value);
- }
- let () = msg_send![array, addObject: data];
- }
- }
- }
- unsafe fn add_json_entry_to_dictionary(data: id, key: &str, value: &JsonValue) {
- let key = NSString::new(&key);
- match value {
- JsonValue::Null => {
- let null: id = msg_send![class!(NSNull), null];
- let () = msg_send![data, setObject:null forKey: key];
- }
- JsonValue::Bool(val) => {
- let flag = if *val { YES } else { NO };
- let value: id = msg_send![class!(NSNumber), numberWithBool: flag];
- let () = msg_send![data, setObject:value forKey: key];
- }
- JsonValue::Number(val) => {
- let number: id = if let Some(v) = val.as_i64() {
- msg_send![class!(NSNumber), numberWithInteger: v]
- } else if let Some(v) = val.as_u64() {
- msg_send![class!(NSNumber), numberWithUnsignedLongLong: v]
- } else if let Some(v) = val.as_f64() {
- msg_send![class!(NSNumber), numberWithDouble: v]
- } else {
- unreachable!()
- };
- let () = msg_send![data, setObject:number forKey: key];
- }
- JsonValue::String(val) => {
- let () = msg_send![data, setObject:NSString::new(&val) forKey: key];
- }
- JsonValue::Array(val) => {
- let nsarray: id = msg_send![class!(NSMutableArray), alloc];
- let array: id = msg_send![nsarray, init];
- for value in val {
- add_json_value_to_array(array, value);
- }
- let () = msg_send![data, setObject:array forKey: key];
- }
- JsonValue::Object(val) => {
- let dictionary: id = msg_send![class!(NSMutableDictionary), alloc];
- let inner_data: id = msg_send![dictionary, init];
- for (key, value) in val {
- add_json_entry_to_dictionary(inner_data, key, value);
- }
- let () = msg_send![data, setObject:inner_data forKey: key];
- }
- }
- }
|