ios.rs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use cocoa::base::{id, nil, NO, YES};
  5. use objc::*;
  6. use serde_json::Value as JsonValue;
  7. use swift_rs::{swift, SRString, SwiftArg};
  8. use std::{
  9. ffi::c_void,
  10. os::raw::{c_char, c_int},
  11. };
  12. type PluginMessageCallbackFn = unsafe extern "C" fn(c_int, c_int, *const c_char);
  13. pub struct PluginMessageCallback(pub PluginMessageCallbackFn);
  14. impl<'a> SwiftArg<'a> for PluginMessageCallback {
  15. type ArgType = PluginMessageCallbackFn;
  16. unsafe fn as_arg(&'a self) -> Self::ArgType {
  17. self.0
  18. }
  19. }
  20. swift!(pub fn post_ipc_message(
  21. webview: *const c_void,
  22. name: &SRString,
  23. method: &SRString,
  24. data: *const c_void,
  25. callback: usize,
  26. error: usize
  27. ));
  28. swift!(pub fn run_plugin_method(
  29. id: i32,
  30. name: &SRString,
  31. method: &SRString,
  32. data: *const c_void,
  33. callback: PluginMessageCallback
  34. ));
  35. swift!(pub fn register_plugin(
  36. name: &SRString,
  37. plugin: *const c_void,
  38. config: *const c_void,
  39. webview: *const c_void
  40. ));
  41. swift!(pub fn on_webview_created(webview: *const c_void, controller: *const c_void));
  42. pub fn json_to_dictionary(json: &JsonValue) -> id {
  43. if let serde_json::Value::Object(map) = json {
  44. unsafe {
  45. let dictionary: id = msg_send![class!(NSMutableDictionary), alloc];
  46. let data: id = msg_send![dictionary, init];
  47. for (key, value) in map {
  48. add_json_entry_to_dictionary(data, key, value);
  49. }
  50. data
  51. }
  52. } else {
  53. nil
  54. }
  55. }
  56. const UTF8_ENCODING: usize = 4;
  57. struct NSString(id);
  58. impl NSString {
  59. fn new(s: &str) -> Self {
  60. // Safety: objc runtime calls are unsafe
  61. NSString(unsafe {
  62. let ns_string: id = msg_send![class!(NSString), alloc];
  63. let ns_string: id = msg_send![ns_string,
  64. initWithBytes:s.as_ptr()
  65. length:s.len()
  66. encoding:UTF8_ENCODING];
  67. // The thing is allocated in rust, the thing must be set to autorelease in rust to relinquish control
  68. // or it can not be released correctly in OC runtime
  69. let _: () = msg_send![ns_string, autorelease];
  70. ns_string
  71. })
  72. }
  73. }
  74. unsafe fn add_json_value_to_array(array: id, value: &JsonValue) {
  75. match value {
  76. JsonValue::Null => {
  77. let null: id = msg_send![class!(NSNull), null];
  78. let () = msg_send![array, addObject: null];
  79. }
  80. JsonValue::Bool(val) => {
  81. let value = if *val { YES } else { NO };
  82. let v: id = msg_send![class!(NSNumber), numberWithBool: value];
  83. let () = msg_send![array, addObject: v];
  84. }
  85. JsonValue::Number(val) => {
  86. let number: id = if let Some(v) = val.as_i64() {
  87. msg_send![class!(NSNumber), numberWithInteger: v]
  88. } else if let Some(v) = val.as_u64() {
  89. msg_send![class!(NSNumber), numberWithUnsignedLongLong: v]
  90. } else if let Some(v) = val.as_f64() {
  91. msg_send![class!(NSNumber), numberWithDouble: v]
  92. } else {
  93. unreachable!()
  94. };
  95. let () = msg_send![array, addObject: number];
  96. }
  97. JsonValue::String(val) => {
  98. let () = msg_send![array, addObject: NSString::new(&val)];
  99. }
  100. JsonValue::Array(val) => {
  101. let nsarray: id = msg_send![class!(NSMutableArray), alloc];
  102. let inner_array: id = msg_send![nsarray, init];
  103. for value in val {
  104. add_json_value_to_array(inner_array, value);
  105. }
  106. let () = msg_send![array, addObject: inner_array];
  107. }
  108. JsonValue::Object(val) => {
  109. let dictionary: id = msg_send![class!(NSMutableDictionary), alloc];
  110. let data: id = msg_send![dictionary, init];
  111. for (key, value) in val {
  112. add_json_entry_to_dictionary(data, key, value);
  113. }
  114. let () = msg_send![array, addObject: data];
  115. }
  116. }
  117. }
  118. unsafe fn add_json_entry_to_dictionary(data: id, key: &str, value: &JsonValue) {
  119. let key = NSString::new(&key);
  120. match value {
  121. JsonValue::Null => {
  122. let null: id = msg_send![class!(NSNull), null];
  123. let () = msg_send![data, setObject:null forKey: key];
  124. }
  125. JsonValue::Bool(val) => {
  126. let flag = if *val { YES } else { NO };
  127. let value: id = msg_send![class!(NSNumber), numberWithBool: flag];
  128. let () = msg_send![data, setObject:value forKey: key];
  129. }
  130. JsonValue::Number(val) => {
  131. let number: id = if let Some(v) = val.as_i64() {
  132. msg_send![class!(NSNumber), numberWithInteger: v]
  133. } else if let Some(v) = val.as_u64() {
  134. msg_send![class!(NSNumber), numberWithUnsignedLongLong: v]
  135. } else if let Some(v) = val.as_f64() {
  136. msg_send![class!(NSNumber), numberWithDouble: v]
  137. } else {
  138. unreachable!()
  139. };
  140. let () = msg_send![data, setObject:number forKey: key];
  141. }
  142. JsonValue::String(val) => {
  143. let () = msg_send![data, setObject:NSString::new(&val) forKey: key];
  144. }
  145. JsonValue::Array(val) => {
  146. let nsarray: id = msg_send![class!(NSMutableArray), alloc];
  147. let array: id = msg_send![nsarray, init];
  148. for value in val {
  149. add_json_value_to_array(array, value);
  150. }
  151. let () = msg_send![data, setObject:array forKey: key];
  152. }
  153. JsonValue::Object(val) => {
  154. let dictionary: id = msg_send![class!(NSMutableDictionary), alloc];
  155. let inner_data: id = msg_send![dictionary, init];
  156. for (key, value) in val {
  157. add_json_entry_to_dictionary(inner_data, key, value);
  158. }
  159. let () = msg_send![data, setObject:inner_data forKey: key];
  160. }
  161. }
  162. }