summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/internals.rs2
-rw-r--r--src/mock/mod.rs148
2 files changed, 134 insertions, 16 deletions
diff --git a/src/internals.rs b/src/internals.rs
index dc93aaa..d1b714f 100644
--- a/src/internals.rs
+++ b/src/internals.rs
@@ -83,7 +83,7 @@ pub struct Ph {
             fd: libc::c_int,
             flags: libc::c_int,
             /* CALLBACK */
-            callback: Option<unsafe extern "C" fn(fd: libc::c_int, flags: libc::c_int, user_data: *mut libc::c_void) -> libc::c_int>,
+            callback: unsafe extern "C" fn(fd: libc::c_int, flags: libc::c_int, user_data: *mut libc::c_void) -> libc::c_int,
             userdata: *mut libc::c_void) -> *const HexchatHook,
     pub hexchat_unhook: unsafe extern "C" fn(ph: *mut HexchatPlugin,
             hook: *const HexchatHook) -> *const libc::c_void,
diff --git a/src/mock/mod.rs b/src/mock/mod.rs
index 4edb907..f4193e0 100644
--- a/src/mock/mod.rs
+++ b/src/mock/mod.rs
@@ -1,20 +1,112 @@
+// This file is part of Hexchat Plugin API Bindings for Rust
+// Copyright (C) 2022 Soni L.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+//
+// Based on hexchat's plugin.c
+//
+/* X-Chat
+ * Copyright (C) 2002 Peter Zelezny.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
 //! Internal mock test framework.
 //!
 //! This API is not stable. Do not rely on this API to be stable.
 
+use std::cell::RefCell;
+use std::ffi::CStr;
+use std::ffi::CString;
+use std::marker::PhantomData;
+use std::pin::Pin;
+use std::ptr;
+
+use libc::c_char;
+
 #[repr(C)]
 pub struct MockPlugin {
     // NOTE: MUST be first thing in the struct.
     methods: crate::internals::Ph,
+    filename: *const c_char,
+    plugin_name: *const c_char,
+    plugin_desc: *const c_char,
+    plugin_vers: *const c_char,
+    free_strings: bool,
 }
 
-unsafe extern "C" fn hexchat_hook_command(ph: *mut crate::internals::HexchatPlugin,
-        name: *const libc::c_char,
-        pri: libc::c_int,
-        /* CALLBACK */
-        callback: unsafe extern "C" fn(word: *const *const libc::c_char, word_eol: *const *const libc::c_char, user_data: *mut libc::c_void) -> libc::c_int,
-        help_text: *const libc::c_char,
-        userdata: *mut libc::c_void) -> *const crate::internals::HexchatHook {
+enum MockCallback {
+    HookCommand {
+        help: Option<Box<str>>,
+        f: unsafe extern "C" fn(word: *const *const libc::c_char, word_eol: *const *const libc::c_char, user_data: *mut libc::c_void) -> libc::c_int,
+    },
+    HookServer {
+        f: unsafe extern "C" fn(word: *const *const libc::c_char, word_eol: *const *const libc::c_char, user_data: *mut libc::c_void) -> libc::c_int,
+    },
+    HookServerAttrs {
+        f: unsafe extern "C" fn(word: *const *const libc::c_char, word_eol: *const *const libc::c_char, attrs: *const crate::internals::HexchatEventAttrs, user_data: *mut libc::c_void) -> libc::c_int,
+    },
+    HookPrint {
+        f: unsafe extern "C" fn(word: *const *const libc::c_char, user_data: *mut libc::c_void) -> libc::c_int,
+    },
+    HookPrintAttrs {
+        f: unsafe extern "C" fn(word: *const *const libc::c_char, attrs: *const crate::internals::HexchatEventAttrs, user_data: *mut libc::c_void) -> libc::c_int
+    },
+    HookTimer {
+        tag: libc::c_int,
+        f: unsafe extern "C" fn(user_data: *mut libc::c_void) -> libc::c_int,
+    },
+    HookFd {
+        tag: libc::c_int,
+        f: unsafe extern "C" fn(fd: libc::c_int, flags: libc::c_int, user_data: *mut libc::c_void) -> libc::c_int
+    },
+    HookDeleted,
+}
+
+// This MockHook is deliberately incompatible with hexchat's own hook struct.
+struct MockHook {
+    pl: *mut MockPlugin,
+    cb: RefCell<MockCallback>,
+    name: Option<Box<str>>,
+    pri_or_fd: libc::c_int,
+}
+
+struct PluginEnvironment {
+}
+
+unsafe extern "C" fn hexchat_hook_command(
+    ph: *mut crate::internals::HexchatPlugin,
+    name: *const libc::c_char,
+    pri: libc::c_int,
+    /* CALLBACK */
+    callback: unsafe extern "C" fn(word: *const *const libc::c_char, word_eol: *const *const libc::c_char, user_data: *mut libc::c_void) -> libc::c_int,
+    help_text: *const libc::c_char,
+    userdata: *mut libc::c_void
+) -> *const crate::internals::HexchatHook {
+    let ph = ph as *mut MockPlugin;
     todo!();
 }
 unsafe extern "C" fn hexchat_hook_server(ph: *mut crate::internals::HexchatPlugin,
@@ -44,7 +136,7 @@ unsafe extern "C" fn hexchat_hook_fd(ph: *mut crate::internals::HexchatPlugin,
         fd: libc::c_int,
         flags: libc::c_int,
         /* CALLBACK */
-        callback: Option<unsafe extern "C" fn(fd: libc::c_int, flags: libc::c_int, user_data: *mut libc::c_void) -> libc::c_int>,
+        callback: unsafe extern "C" fn(fd: libc::c_int, flags: libc::c_int, user_data: *mut libc::c_void) -> libc::c_int,
         userdata: *mut libc::c_void) -> *const crate::internals::HexchatHook {
     todo!();
 }
@@ -56,7 +148,7 @@ unsafe extern "C" fn hexchat_print(ph: *mut crate::internals::HexchatPlugin,
         text: *const libc::c_char) {
     todo!();
 }
-pub unsafe extern "C" fn hexchat_printf_do_not_use(ph: *mut crate::internals::HexchatPlugin,
+pub unsafe extern "C" fn hexchat_printf(ph: *mut crate::internals::HexchatPlugin,
         format: *const libc::c_char, ...) {
     unimplemented!();
 }
@@ -64,7 +156,7 @@ unsafe extern "C" fn hexchat_command(ph: *mut crate::internals::HexchatPlugin,
         command: *const libc::c_char) {
     todo!();
 }
-unsafe extern "C" fn hexchat_commandf_do_not_use(ph: *mut crate::internals::HexchatPlugin,
+unsafe extern "C" fn hexchat_commandf(ph: *mut crate::internals::HexchatPlugin,
         format: *const libc::c_char, ...) {
     unimplemented!();
 }
@@ -226,8 +318,12 @@ unsafe extern "C" fn hexchat_event_attrs_free(ph: *mut crate::internals::Hexchat
 }
 
 impl MockPlugin {
-    fn new() -> MockPlugin {
-        MockPlugin {
+    pub fn new<T: for<'ph> crate::Plugin<'ph> + Default>(
+        filename: CString,
+        arg: Option<&CStr>,
+    ) -> Option<Pin<Box<MockPlugin>>> {
+        let filename = filename.into_raw();
+        let mut plug = Box::pin(MockPlugin {
             methods: crate::internals::Ph {
                 hexchat_hook_command,
                 hexchat_hook_server,
@@ -236,9 +332,9 @@ impl MockPlugin {
                 hexchat_hook_fd,
                 hexchat_unhook,
                 hexchat_print,
-                userdata: std::ptr::null_mut(),
+                userdata: hexchat_printf as *mut libc::c_void,
                 hexchat_command,
-                hexchat_commandf_do_not_use,
+                hexchat_commandf_do_not_use: hexchat_commandf,
                 hexchat_nickcmp,
                 hexchat_set_context,
                 hexchat_find_context,
@@ -271,7 +367,29 @@ impl MockPlugin {
                 hexchat_emit_print_attrs,
                 hexchat_event_attrs_create,
                 hexchat_event_attrs_free,
-            }
+            },
+            filename: filename,
+            plugin_name: filename,
+            plugin_desc: ptr::null(),
+            plugin_vers: ptr::null(),
+            free_strings: false,
+        });
+        if unsafe {
+            let ptr: *mut MockPlugin = &mut *plug;
+            crate::hexchat_plugin_init::<'_, T>(
+                crate::LtPhPtr {
+                    ph: ptr as *mut crate::internals::Ph,
+                    _lt: PhantomData,
+                },
+                ptr::addr_of_mut!((*ptr).plugin_name),
+                ptr::addr_of_mut!((*ptr).plugin_desc),
+                ptr::addr_of_mut!((*ptr).plugin_vers),
+                arg.map(|arg| arg.as_ptr()).unwrap_or(ptr::null()),
+            ) != 0
+        } {
+            Some(plug)
+        } else {
+            None
         }
     }
 }