wl_proxy/
handler.rs

1//! Helpers for event handlers.
2//!
3//! These types are similar to [`Ref`] and [`RefMut`] but allow the handler to be replaced
4//! while it is borrowed. When this happens, the handler will be replaced before the next
5//! event is emitted.
6
7use {
8    crate::utils::cold_path::cold_path,
9    std::{
10        cell::{Cell, Ref, RefCell, RefMut},
11        fmt::{Debug, Display, Formatter},
12        mem::{self},
13        ops::{Deref, DerefMut},
14    },
15    thiserror::Error,
16};
17
18#[cfg(test)]
19mod tests;
20
21pub(crate) struct HandlerHolder<T: ?Sized> {
22    handler: RefCell<Option<Box<T>>>,
23    needs_update: Cell<bool>,
24    new: Cell<Option<Option<Box<T>>>>,
25}
26
27trait HandlerHolderDyn {
28    fn update(&self);
29}
30
31#[derive(Clone)]
32struct HandlerHolderUpdate<'a> {
33    needs_update: &'a Cell<bool>,
34    holder: &'a dyn HandlerHolderDyn,
35}
36
37/// A mutable reference to a handler.
38pub struct HandlerMut<'a, U: ?Sized> {
39    handler: RefMut<'a, U>,
40    update: HandlerHolderUpdate<'a>,
41}
42
43/// A shared reference to a handler.
44pub struct HandlerRef<'a, U: ?Sized> {
45    handler: Ref<'a, U>,
46    update: HandlerHolderUpdate<'a>,
47}
48
49/// An error returned when trying to access a handler.
50#[derive(Debug, Error)]
51pub enum HandlerAccessError {
52    /// The handler is already borrowed.
53    #[error("the handler is already borrowed")]
54    AlreadyBorrowed,
55    /// The object has no handler.
56    #[error("the object has no handler")]
57    NoHandler,
58    /// The handler has a different type.
59    #[error("the handler has a different type")]
60    InvalidType,
61}
62
63impl<T: ?Sized> HandlerHolderDyn for HandlerHolder<T> {
64    fn update(&self) {
65        let _old;
66        if let Ok(mut handler) = self.handler.try_borrow_mut() {
67            if let Some(new) = self.new.take() {
68                _old = mem::replace(&mut *handler, new);
69            }
70            self.needs_update.set(false);
71        }
72    }
73}
74
75impl<T: ?Sized> Default for HandlerHolder<T> {
76    fn default() -> Self {
77        Self {
78            handler: Default::default(),
79            needs_update: Default::default(),
80            new: Default::default(),
81        }
82    }
83}
84
85impl<T: ?Sized> HandlerHolder<T> {
86    #[inline]
87    fn update(&self) -> HandlerHolderUpdate<'_> {
88        HandlerHolderUpdate {
89            needs_update: &self.needs_update,
90            holder: self,
91        }
92    }
93
94    #[inline]
95    pub(crate) fn borrow_mut(&self) -> HandlerMut<'_, Option<Box<T>>> {
96        HandlerMut {
97            handler: self.handler.borrow_mut(),
98            update: self.update(),
99        }
100    }
101
102    #[inline]
103    pub(crate) fn try_borrow(&self) -> Option<HandlerRef<'_, Option<Box<T>>>> {
104        Some(HandlerRef {
105            handler: self.handler.try_borrow().ok()?,
106            update: self.update(),
107        })
108    }
109
110    #[inline]
111    pub(crate) fn try_borrow_mut(&self) -> Option<HandlerMut<'_, Option<Box<T>>>> {
112        Some(HandlerMut {
113            handler: self.handler.try_borrow_mut().ok()?,
114            update: self.update(),
115        })
116    }
117
118    pub(crate) fn set(&self, handler: Option<Box<T>>) {
119        let _prev;
120        if let Ok(mut cell) = self.handler.try_borrow_mut() {
121            _prev = mem::replace(&mut *cell, handler);
122        } else {
123            cold_path();
124            self.new.set(Some(handler));
125            self.needs_update.set(true);
126        }
127    }
128}
129
130impl<T: ?Sized> Deref for HandlerRef<'_, T> {
131    type Target = T;
132
133    #[inline]
134    fn deref(&self) -> &Self::Target {
135        &self.handler
136    }
137}
138
139impl<T: ?Sized> Deref for HandlerMut<'_, T> {
140    type Target = T;
141
142    #[inline]
143    fn deref(&self) -> &Self::Target {
144        &self.handler
145    }
146}
147
148impl<T: ?Sized> DerefMut for HandlerMut<'_, T> {
149    #[inline]
150    fn deref_mut(&mut self) -> &mut Self::Target {
151        &mut self.handler
152    }
153}
154
155impl<T: ?Sized> HandlerRef<'_, T> {
156    /// Copies a `HandlerRef`.
157    ///
158    /// This is an associated function that needs to be used as `HandlerRef::clone(...)`.
159    #[expect(clippy::should_implement_trait)]
160    pub fn clone(orig: &Self) -> Self {
161        Self {
162            handler: Ref::clone(&orig.handler),
163            update: orig.update.clone(),
164        }
165    }
166}
167
168impl<'a, T: ?Sized> HandlerRef<'a, T> {
169    /// Makes a new `HandlerRef` for a component of the borrowed data.
170    ///
171    /// This is an associated function that needs to be used as `HandlerRef::map(...)`.
172    /// A method would interfere with methods of the same name on the contents
173    /// of a handler used through `Deref`.
174    #[inline]
175    pub fn map<U: ?Sized, F>(orig: Self, f: F) -> HandlerRef<'a, U>
176    where
177        F: FnOnce(&T) -> &U,
178    {
179        HandlerRef {
180            handler: Ref::map(orig.handler, f),
181            update: orig.update,
182        }
183    }
184}
185
186impl<'a, T: ?Sized> HandlerMut<'a, T> {
187    /// Makes a new `HandlerMut` for a component of the borrowed data.
188    ///
189    /// This is an associated function that needs to be used as `HandlerMut::map(...)`.
190    /// A method would interfere with methods of the same name on the contents
191    /// of a handler used through `Deref`.
192    #[inline]
193    pub fn map<U: ?Sized, F>(orig: Self, f: F) -> HandlerMut<'a, U>
194    where
195        F: FnOnce(&mut T) -> &mut U,
196    {
197        HandlerMut {
198            handler: RefMut::map(orig.handler, f),
199            update: orig.update,
200        }
201    }
202}
203
204impl Drop for HandlerHolderUpdate<'_> {
205    #[inline]
206    fn drop(&mut self) {
207        if self.needs_update.get() {
208            cold_path();
209            self.holder.update();
210        }
211    }
212}
213
214impl<T: ?Sized> Debug for HandlerRef<'_, T>
215where
216    T: Debug,
217{
218    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
219        self.handler.fmt(f)
220    }
221}
222
223impl<T: ?Sized> Debug for HandlerMut<'_, T>
224where
225    T: Debug,
226{
227    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
228        self.handler.fmt(f)
229    }
230}
231
232impl<T: ?Sized> Display for HandlerRef<'_, T>
233where
234    T: Display,
235{
236    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
237        self.handler.fmt(f)
238    }
239}
240
241impl<T: ?Sized> Display for HandlerMut<'_, T>
242where
243    T: Display,
244{
245    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
246        self.handler.fmt(f)
247    }
248}