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}