Skip to main content

qubit_function/tasks/callable_with/
rc_callable_with.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10// qubit-style: allow explicit-imports
11//! Defines the `RcCallableWith` public type.
12
13use std::cell::RefCell;
14use std::rc::Rc;
15
16use crate::{
17    macros::{
18        impl_common_name_methods,
19        impl_common_new_methods,
20        impl_rc_conversions,
21    },
22    tasks::{
23        callable_with::{
24            BoxCallableWith,
25            CallableWith,
26        },
27        runnable_with::BoxRunnableWith,
28    },
29};
30
31type RcCallableWithFn<T, R, E> = Rc<RefCell<dyn FnMut(&mut T) -> Result<R, E>>>;
32
33/// Single-threaded shared callable with mutable input.
34///
35/// `RcCallableWith<T, R, E>` stores a
36/// `Rc<RefCell<dyn FnMut(&mut T) -> Result<R, E>>>`.
37///
38pub struct RcCallableWith<T, R, E> {
39    /// The stateful closure executed by this callable.
40    pub(super) function: RcCallableWithFn<T, R, E>,
41    /// The optional name of this callable.
42    pub(super) name: Option<String>,
43}
44
45impl<T, R, E> Clone for RcCallableWith<T, R, E> {
46    #[inline]
47    fn clone(&self) -> Self {
48        Self {
49            function: Rc::clone(&self.function),
50            name: self.name.clone(),
51        }
52    }
53}
54
55impl<T, R, E> RcCallableWith<T, R, E> {
56    impl_common_new_methods!(
57        (FnMut(&mut T) -> Result<R, E> + 'static),
58        |function| Rc::new(RefCell::new(function)),
59        "callable-with"
60    );
61
62    impl_common_name_methods!("callable-with");
63}
64
65impl<T, R, E> CallableWith<T, R, E> for RcCallableWith<T, R, E> {
66    /// Executes the shared callable with mutable input.
67    #[inline]
68    fn call_with(&mut self, input: &mut T) -> Result<R, E> {
69        (self.function.borrow_mut())(input)
70    }
71
72    impl_rc_conversions!(
73        RcCallableWith<T, R, E>,
74        BoxCallableWith,
75        FnMut(input: &mut T) -> Result<R, E>
76    );
77
78    /// Converts this shared callable into a boxed runnable while preserving its
79    /// name.
80    #[inline]
81    fn into_runnable_with(self) -> BoxRunnableWith<T, E>
82    where
83        Self: Sized + 'static,
84    {
85        let name = self.name;
86        let function = self.function;
87        BoxRunnableWith::new_with_optional_name(
88            move |input| (function.borrow_mut())(input).map(|_| ()),
89            name,
90        )
91    }
92}