summary refs log tree commit diff stats
path: root/src/lib.rs
diff options
context:
space:
mode:
authorSoniEx2 <endermoneymod@gmail.com>2022-04-26 09:14:09 -0300
committerSoniEx2 <endermoneymod@gmail.com>2022-04-26 09:14:09 -0300
commit25d5d6f4e9ed901d284633691941c52c8556d17c (patch)
treec353158113eba06e67e37a77caf337a8bf1c270e /src/lib.rs
parent83db3d819b7402b4f3c6ca023ddfea6204fae4b4 (diff)
Project ValidContext to Fields<'_, '_, Contexts>
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs63
1 files changed, 48 insertions, 15 deletions
diff --git a/src/lib.rs b/src/lib.rs
index f0ee389..52d3d23 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -150,7 +150,7 @@
  *         -[ ] win_ptr
  *     -[x] hexchat_get_prefs
  *     -[x] hexchat_list_get
- *     -[ ] hexchat_list_fields
+ *     -[x] ~~hexchat_list_fields~~ not available. no alternative provided.
  *     -[x] hexchat_list_next
  *     -[x] hexchat_list_str
  *     -[x] hexchat_list_int
@@ -338,16 +338,21 @@ pub enum PrefValue {
 }
 
 mod valid_context {
+    use std::ptr;
+
+    use crate::list;
     use crate::PluginHandle;
 
-    /// A PluginHandle operating on a valid context.
+    /// A `PluginHandle` operating on a valid context.
     ///
-    /// This mechanism attempts to reduce the likelihood of segfaults in
-    /// hexchat code.
+    /// Methods that require a valid plugin context are only available through
+    /// this. Methods that may invalidate the plugin context also consume this.
     ///
     /// See also [`PluginHandle::ensure_valid_context`].
     pub struct ValidContext<'a, 'ph: 'a> {
-        pub(crate) ph: &'a mut PluginHandle<'ph>,
+        // NOTE: NOT mut(!)
+        pub(crate) ph: &'a PluginHandle<'ph>,
+        fields: list::Fields<'a, 'ph, list::Contexts>,
         _hidden: (),
     }
 
@@ -358,7 +363,29 @@ mod valid_context {
         ///
         /// The PluginHandle's context must be valid.
         pub(crate) unsafe fn new(ph: &'a mut PluginHandle<'ph>) -> Self {
-            Self { ph, _hidden: () }
+            static CONTEXTS: list::Contexts = list::Contexts;
+            Self {
+                ph: &*ph,
+                fields: list::Fields {
+                    context: &*ph,
+                    // this isn't actually documented but hexchat explicitly
+                    // supports passing in NULL for the current context.
+                    // this gives access to some properties that aren't
+                    // available through get_info.
+                    list: ptr::null_mut(),
+                    _t: &CONTEXTS,
+                    id: 0,
+                    valid: Default::default(),
+                },
+                _hidden: (),
+            }
+        }
+    }
+
+    impl<'a, 'ph: 'a> std::ops::Deref for ValidContext<'a, 'ph> {
+        type Target = list::Fields<'a, 'ph, list::Contexts>;
+        fn deref(&self) -> &Self::Target {
+            &self.fields
         }
     }
 }
@@ -749,13 +776,8 @@ impl<'ph> PluginHandle<'ph> {
     ///
     /// Returns `true` if the context is valid, `false` otherwise.
     pub fn set_context(&mut self, ctx: &Context<'ph>) -> bool {
-        if let Some(ctx) = ctx.ctx.upgrade() {
-            unsafe {
-                ph_call!(hexchat_set_context(self, *ctx)) != 0
-            }
-        } else {
-            false
-        }
+        // we could've made this &self but we didn't. avoid breaking API.
+        self.set_context_internal(ctx)
     }
 
     /// Do something in a valid context.
@@ -1278,6 +1300,17 @@ impl<'ph> PluginHandle<'ph> {
             ctx.map(|ctx| wrap_context(self, ctx))
         }
     }
+
+    /// Same as `set_context` but it takes `&self`.
+    fn set_context_internal(&self, ctx: &Context<'ph>) -> bool {
+        if let Some(ctx) = ctx.ctx.upgrade() {
+            unsafe {
+                ph_call!(hexchat_set_context(self, *ctx)) != 0
+            }
+        } else {
+            false
+        }
+    }
 }
 
 impl<'a> EventAttrs<'a> {
@@ -1544,7 +1577,7 @@ impl<'a, 'ph: 'a> ValidContext<'a, 'ph> {
             ph_call!(hexchat_list_get(ph, list.as_ptr()))
         };
         list::Entries {
-            context: self,
+            context: self.ph,
             list: list,
             t: t,
             valid: Default::default(),
@@ -1575,7 +1608,7 @@ impl<'a, 'ph: 'a> ValidContext<'a, 'ph> {
     // context.
     // So either way we're still in a valid context when this returns.
     pub fn set_context(&mut self, ctx: &Context<'ph>) -> bool {
-        self.ph.set_context(ctx)
+        self.ph.set_context_internal(ctx)
     }
 
     /// Prints to the hexchat buffer.