diff options
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 63 |
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. |