tree_sitter_utils/combinators/boxed.rs
1//! The [`BoxedHandler`] type — type-erased dynamic dispatch.
2
3use crate::handler::{Handler, HandlerResult};
4use crate::input::Input;
5
6/// Type alias for the inner boxed function used by [`BoxedHandler`].
7type BoxFn<Ctx, R> =
8 Box<dyn for<'tree> Fn(Input<'tree, Ctx>) -> HandlerResult<R> + Send + Sync>;
9
10/// A type-erased handler that owns a `Box<dyn Fn(...)>`.
11///
12/// Use this only when you need to store handlers in a collection or return
13/// them from a function with an erased type. In hot paths, prefer the
14/// zero-cost combinator structs.
15///
16/// Constructed via [`HandlerExt::boxed`](crate::HandlerExt::boxed).
17///
18/// # Example
19///
20/// ```rust
21/// use tree_sitter_utils::{handler_fn, HandlerExt, BoxedHandler, Input};
22///
23/// let h: BoxedHandler<(), String> =
24/// handler_fn(|_: Input<()>| "hello".to_owned()).boxed();
25/// let _ = h;
26/// ```
27pub struct BoxedHandler<Ctx, R>(BoxFn<Ctx, R>);
28
29impl<Ctx, R> BoxedHandler<Ctx, R> {
30 /// Wrap a boxed closure as a [`BoxedHandler`].
31 pub fn new<F>(f: F) -> Self
32 where
33 F: for<'tree> Fn(Input<'tree, Ctx>) -> HandlerResult<R> + Send + Sync + 'static,
34 {
35 BoxedHandler(Box::new(f))
36 }
37}
38
39impl<Ctx, R> Handler<Ctx, R> for BoxedHandler<Ctx, R>
40where
41 Ctx: Copy,
42{
43 #[inline]
44 fn handle<'tree>(&self, input: Input<'tree, Ctx>) -> HandlerResult<R> {
45 (self.0)(input)
46 }
47}