aimdb_core/
context.rs

1//! Runtime context for AimDB services
2//!
3//! Provides a unified interface to runtime capabilities like sleep and timestamp
4//! functions, abstracting away the specific runtime adapter implementation.
5
6#[cfg(not(feature = "std"))]
7extern crate alloc;
8
9use aimdb_executor::Runtime;
10use core::future::Future;
11
12/// Unified runtime context for AimDB services
13///
14/// Provides access to runtime capabilities (sleep, timestamps) through
15/// a unified API, abstracting the underlying runtime implementation.
16///
17/// Services receive this context for timing operations without knowing
18/// about the specific runtime adapter.
19#[derive(Clone)]
20pub struct RuntimeContext<R>
21where
22    R: Runtime,
23{
24    #[cfg(feature = "std")]
25    runtime: std::sync::Arc<R>,
26    #[cfg(not(feature = "std"))]
27    runtime: &'static R,
28}
29
30#[cfg(feature = "std")]
31impl<R> RuntimeContext<R>
32where
33    R: Runtime,
34{
35    /// Create a new RuntimeContext (std version uses Arc internally)
36    pub fn new(runtime: R) -> Self {
37        Self {
38            runtime: std::sync::Arc::new(runtime),
39        }
40    }
41
42    /// Create from an existing Arc to avoid double-wrapping
43    pub fn from_arc(runtime: std::sync::Arc<R>) -> Self {
44        Self { runtime }
45    }
46
47    /// Extract runtime context from type-erased Arc (std version)
48    ///
49    /// This is a helper for runtime adapters to convert the raw `Arc<dyn Any>`
50    /// context passed to `.source_raw()` and `.tap_raw()` into a typed `RuntimeContext`.
51    ///
52    /// # Panics
53    /// Panics if the runtime type doesn't match `R`.
54    pub fn extract_from_any(ctx_any: std::sync::Arc<dyn core::any::Any + Send + Sync>) -> Self {
55        let runtime = ctx_any
56            .downcast::<R>()
57            .expect("Runtime type mismatch - expected matching runtime adapter");
58        Self::from_arc(runtime.clone())
59    }
60}
61
62#[cfg(not(feature = "std"))]
63impl<R> RuntimeContext<R>
64where
65    R: Runtime,
66{
67    /// Create a new RuntimeContext with static reference (no_std version)
68    pub fn new(runtime: &'static R) -> Self {
69        Self { runtime }
70    }
71
72    /// Extract runtime context from type-erased Arc (no_std version)
73    ///
74    /// This is a helper for runtime adapters to convert the raw `Arc<dyn Any>`
75    /// context passed to `.source_raw()` and `.tap_raw()` into a typed `RuntimeContext`.
76    ///
77    /// For no_std, this leaks the Arc to obtain a `&'static` reference, which is safe
78    /// because the runtime lives for the entire program lifetime in embedded contexts.
79    ///
80    /// # Panics
81    /// Panics if the runtime type doesn't match `R`.
82    pub fn extract_from_any(ctx_any: alloc::sync::Arc<dyn core::any::Any + Send + Sync>) -> Self {
83        let runtime = ctx_any
84            .downcast::<R>()
85            .expect("Runtime type mismatch - expected matching runtime adapter");
86
87        // Convert Arc<R> to &'static R by leaking it
88        // This is safe because in embedded contexts, the runtime lives for the entire program
89        let runtime_ref: &'static R = &*alloc::boxed::Box::leak(runtime.into());
90
91        Self::new(runtime_ref)
92    }
93}
94
95impl<R> RuntimeContext<R>
96where
97    R: Runtime,
98{
99    /// Access time utilities
100    ///
101    /// Returns a time accessor for duration creation, sleep, and timing operations.
102    pub fn time(&self) -> Time<'_, R> {
103        Time { ctx: self }
104    }
105
106    /// Access logging utilities
107    pub fn log(&self) -> Log<'_, R> {
108        Log { ctx: self }
109    }
110
111    /// Get access to the underlying runtime
112    ///
113    /// This provides direct access to the runtime for advanced use cases.
114    #[cfg(feature = "std")]
115    pub fn runtime(&self) -> &R {
116        &self.runtime
117    }
118
119    #[cfg(not(feature = "std"))]
120    pub fn runtime(&self) -> &'static R {
121        self.runtime
122    }
123}
124
125#[cfg(feature = "std")]
126impl<R> RuntimeContext<R>
127where
128    R: Runtime,
129{
130    /// Create a RuntimeContext from a runtime adapter (std version with Arc)
131    pub fn from_runtime(runtime: R) -> Self {
132        Self::new(runtime)
133    }
134}
135
136/// Create a RuntimeContext from any Runtime implementation (std version)
137#[cfg(feature = "std")]
138pub fn create_runtime_context<R>(runtime: R) -> RuntimeContext<R>
139where
140    R: Runtime,
141{
142    RuntimeContext::from_runtime(runtime)
143}
144
145/// Time utilities accessor for RuntimeContext
146///
147/// Provides duration creation, sleep, and timing measurements.
148pub struct Time<'a, R: Runtime> {
149    ctx: &'a RuntimeContext<R>,
150}
151
152impl<'a, R: Runtime> Time<'a, R> {
153    /// Create a duration from milliseconds
154    pub fn millis(&self, millis: u64) -> R::Duration {
155        self.ctx.runtime.millis(millis)
156    }
157
158    /// Create a duration from seconds
159    pub fn secs(&self, secs: u64) -> R::Duration {
160        self.ctx.runtime.secs(secs)
161    }
162
163    /// Create a duration from microseconds
164    pub fn micros(&self, micros: u64) -> R::Duration {
165        self.ctx.runtime.micros(micros)
166    }
167
168    /// Sleep for the specified duration
169    pub fn sleep(&self, duration: R::Duration) -> impl Future<Output = ()> + Send + '_ {
170        self.ctx.runtime.sleep(duration)
171    }
172
173    /// Get the current timestamp
174    pub fn now(&self) -> R::Instant {
175        self.ctx.runtime.now()
176    }
177
178    /// Get the duration between two instants
179    ///
180    /// Returns None if `later` is before `earlier`.
181    pub fn duration_since(&self, later: R::Instant, earlier: R::Instant) -> Option<R::Duration> {
182        self.ctx.runtime.duration_since(later, earlier)
183    }
184}
185
186/// Log utilities accessor for RuntimeContext
187///
188/// Provides structured logging operations.
189pub struct Log<'a, R: Runtime> {
190    ctx: &'a RuntimeContext<R>,
191}
192
193impl<'a, R: Runtime> Log<'a, R> {
194    /// Log an informational message
195    pub fn info(&self, message: &str) {
196        self.ctx.runtime.info(message)
197    }
198
199    /// Log a debug message
200    pub fn debug(&self, message: &str) {
201        self.ctx.runtime.debug(message)
202    }
203
204    /// Log a warning message
205    pub fn warn(&self, message: &str) {
206        self.ctx.runtime.warn(message)
207    }
208
209    /// Log an error message
210    pub fn error(&self, message: &str) {
211        self.ctx.runtime.error(message)
212    }
213}