cel_cxx/
marker.rs

1/// Marker trait for runtime types.
2///
3/// This trait is used to mark types that represent different async runtimes
4/// (such as Tokio or async-std) or the absence of an async runtime.
5///
6/// # Examples
7///
8/// ```rust,no_run
9/// use cel_cxx::marker::RuntimeMarker;
10///
11/// // The unit type represents no async runtime
12/// fn sync_example<R: RuntimeMarker>() {
13///     // This works with any runtime marker
14/// }
15/// ```
16pub trait RuntimeMarker: private::Sealed {}
17
18/// Implementation for the unit type (no async runtime).
19impl RuntimeMarker for () {}
20
21/// Marker trait for function types.
22///
23/// This trait is used to distinguish between synchronous and asynchronous
24/// functions in the type system. It allows the library to provide different
25/// behavior based on whether functions are sync or async.
26///
27/// # Examples
28///
29/// ```rust,no_run
30/// use cel_cxx::marker::FnMarker;
31///
32/// // The unit type represents synchronous functions
33/// fn sync_function_example<F: FnMarker>() {
34///     // This works with any function marker
35/// }
36/// ```
37pub trait FnMarker: private::Sealed {}
38
39/// Trait for aggregating function markers.
40///
41/// This trait is used to combine function markers from different sources
42/// (environment, activation, etc.) to determine the overall function
43/// capabilities of a context.
44///
45/// # Type Parameters
46///
47/// * `Other` - The other function marker to aggregate with
48///
49/// # Associated Types
50///
51/// * `Output` - The resulting function marker after aggregation
52///
53/// # Examples
54///
55/// ```rust,no_run
56/// use cel_cxx::marker::{FnMarker, FnMarkerAggr};
57///
58/// fn aggregate_example<F1, F2>()
59/// where
60///     F1: FnMarker + FnMarkerAggr<F2>,
61///     F2: FnMarker,
62/// {
63///     // F1::Output represents the combined capabilities
64/// }
65/// ```
66pub trait FnMarkerAggr<Other: FnMarker>: FnMarker {
67    /// The resulting function marker after aggregation.
68    type Output: FnMarker;
69}
70
71/// Trait for determining function result types.
72///
73/// This trait maps function markers to their corresponding result types.
74/// For synchronous functions, this is just the value type. For asynchronous
75/// functions, this wraps the value in a Future.
76///
77/// # Type Parameters
78///
79/// * `'a` - Lifetime parameter for the result
80/// * `T` - The base type that will be wrapped according to the marker
81///
82/// # Associated Types
83///
84/// * `Output` - The actual result type (T for sync, `Future<T>` for async)
85///
86/// # Examples
87///
88/// ```rust,no_run
89/// use cel_cxx::marker::{FnMarker, FnResult};
90///
91/// fn result_example<'a, F, T>() -> F::Output
92/// where
93///     F: FnMarker + FnResult<'a, T>,
94/// {
95///     // Return type depends on the function marker
96///     todo!()
97/// }
98/// ```
99pub trait FnResult<'a, T>: FnMarker {
100    /// The output type for this function marker and base type.
101    type Output;
102}
103
104/// Synchronous function marker implementation.
105///
106/// The unit type `()` represents synchronous functions.
107impl FnMarker for () {}
108
109/// Synchronous function aggregation.
110///
111/// Aggregating with synchronous functions yields synchronous functions.
112impl FnMarkerAggr<()> for () {
113    type Output = ();
114}
115
116/// Synchronous function results.
117///
118/// For synchronous functions, the result type is just the base type.
119impl<'a, T> FnResult<'a, T> for () {
120    type Output = T;
121}
122
123/// Async-specific marker types and implementations.
124///
125/// This module contains the marker types and trait implementations for
126/// asynchronous function support. It's only available when the `async`
127/// feature is enabled.
128#[cfg(feature = "async")]
129#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
130pub use async_marker::*;
131
132#[cfg(feature = "async")]
133#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
134mod async_marker {
135    use super::{FnMarker, FnMarkerAggr, FnResult, RuntimeMarker};
136    use crate::r#async::Runtime;
137
138    /// Runtime marker implementation for async runtime types.
139    impl<T: Runtime> RuntimeMarker for T {}
140
141    /// Marker trait for asynchronous functions.
142    ///
143    /// This trait extends `FnMarker` to specifically mark asynchronous
144    /// function types.
145    ///
146    /// # Examples
147    ///
148    /// ```rust,no_run
149    /// # #[cfg(feature = "async")]
150    /// # fn example() {
151    /// use cel_cxx::marker::{FnMarkerAsync, Async};
152    ///
153    /// fn async_function_example<F: FnMarkerAsync>() {
154    ///     // This only works with async function markers
155    /// }
156    ///
157    /// // Async is an example of FnMarkerAsync
158    /// async_function_example::<Async>();
159    /// # }
160    /// ```
161    pub trait FnMarkerAsync: FnMarker {}
162
163    /// Marker type for asynchronous functions.
164    ///
165    /// This is a zero-sized type used to mark contexts that support
166    /// asynchronous function evaluation.
167    ///
168    /// # Examples
169    ///
170    /// ```rust,no_run
171    /// # #[cfg(feature = "async")]
172    /// # fn example() -> Result<(), cel_cxx::Error> {
173    /// use cel_cxx::{Env, marker::Async};
174    ///
175    /// // Create an async-capable environment
176    /// let env = Env::builder()
177    ///     .force_async()
178    ///     .build()?;
179    /// # Ok::<(), cel_cxx::Error>(())
180    /// # }
181    /// ```
182    #[allow(missing_debug_implementations)]
183    pub enum Async {}
184
185    /// Function marker implementation for async functions.
186    impl FnMarker for Async {}
187
188    /// Async function marker trait implementation.
189    impl FnMarkerAsync for Async {}
190
191    /// Aggregating sync with async yields async.
192    ///
193    /// When synchronous and asynchronous capabilities are combined,
194    /// the result supports asynchronous operations.
195    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
196    impl FnMarkerAggr<()> for Async {
197        type Output = Async;
198    }
199
200    /// Aggregating async with sync yields async.
201    ///
202    /// When asynchronous and synchronous capabilities are combined,
203    /// the result supports asynchronous operations.
204    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
205    impl FnMarkerAggr<Async> for () {
206        type Output = Async;
207    }
208
209    /// Aggregating async with async yields async.
210    ///
211    /// Combining two async contexts remains async.
212    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
213    impl FnMarkerAggr<Async> for Async {
214        type Output = Async;
215    }
216
217    /// Asynchronous function results.
218    ///
219    /// For asynchronous functions, the result type is wrapped in a BoxFuture.
220    /// This allows async functions to return futures that can be awaited.
221    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
222    impl<'a, T> FnResult<'a, T> for Async {
223        type Output = futures::future::BoxFuture<'a, T>;
224    }
225}
226
227/// Private sealed trait to prevent external implementations.
228///
229/// This module ensures that marker traits can only be implemented by types
230/// within this crate, providing type safety and preventing misuse.
231mod private {
232    #![allow(unused)]
233    use super::*;
234    #[cfg(feature = "async")]
235    use crate::r#async::Runtime;
236
237    /// Sealed trait to prevent external implementations.
238    ///
239    /// This trait is implemented only for types that are allowed to be
240    /// markers in the cel-cxx type system.
241    pub trait Sealed: 'static {}
242
243    /// Unit type can be a marker (represents sync operations).
244    impl Sealed for () {}
245
246    /// Async marker type can be a marker.
247    #[cfg(feature = "async")]
248    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
249    impl Sealed for Async {}
250
251    /// Runtime types can be runtime markers.
252    #[cfg(feature = "async")]
253    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
254    impl<T: Runtime> Sealed for T {}
255}
256
257#[cfg(test)]
258mod test {
259    #![allow(unused)]
260    #![allow(clippy::let_unit_value)]
261    use super::*;
262
263    fn test_fn_marker_aggregation<M1, M2>() -> <M1 as FnMarkerAggr<M2>>::Output
264    where
265        M1: FnMarker + FnMarkerAggr<M2>,
266        M2: FnMarker,
267    {
268        todo!()
269    }
270
271    fn test_eval_result<'a, M, T>() -> <M as FnResult<'a, T>>::Output
272    where
273        M: FnResult<'a, T> + FnMarker,
274    {
275        todo!()
276    }
277
278    fn t1() {
279        let x = test_fn_marker_aggregation::<(), ()>();
280        let v = test_eval_result::<(), i32>();
281
282        #[cfg(feature = "async")]
283        {
284            use crate::marker::Async;
285
286            let x = test_fn_marker_aggregation::<(), Async>();
287            let x = test_fn_marker_aggregation::<Async, ()>();
288            let x = test_fn_marker_aggregation::<Async, Async>();
289
290            let v = test_eval_result::<Async, i32>();
291        }
292    }
293}