1use crate::effect::{AsyncDisposer, EffectHandle};
4use crate::events::{Event, EventOptions, EventResult, EventValue, EventsRoot, EventsService};
5use crate::fiber::{Fiber, FiberInner};
6use crate::logger::{LogArg, Logger, LoggerRoot, LoggerService};
7use crate::reflect::{Accessor, ReflectRoot, ReflectService};
8use crate::registry::{Inject, IntoPlugin, PluginOutput, RegistryRoot, RegistryService};
9use crate::{Config, Result, Value};
10use std::collections::HashMap;
11use std::fmt::{self, Debug, Formatter};
12use std::future::Future;
13use std::sync::atomic::{AtomicU64, Ordering};
14use std::sync::{Arc, OnceLock, Weak};
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
18pub struct Isolation(pub(crate) u64);
19
20impl Isolation {
21 pub const fn from_raw(value: u64) -> Self {
26 Self(value)
27 }
28
29 pub const fn as_raw(self) -> u64 {
31 self.0
32 }
33}
34
35pub type ContextFilter = Arc<dyn Fn(&Context) -> bool + Send + Sync + 'static>;
37
38#[derive(Clone, Default)]
40pub struct ContextMeta {
41 pub(crate) isolates: Arc<HashMap<String, Isolation>>,
42 pub(crate) intercepts: Arc<Vec<(String, Value)>>,
43 pub(crate) values: Arc<HashMap<String, Value>>,
44 pub(crate) filter: Option<ContextFilter>,
45 pub(crate) base_url: Option<Arc<str>>,
46}
47
48impl Debug for ContextMeta {
49 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
50 f.debug_struct("ContextMeta")
51 .field("isolates", &self.isolates)
52 .field("intercept_count", &self.intercepts.len())
53 .field("value_keys", &self.values.keys().collect::<Vec<_>>())
54 .field("has_filter", &self.filter.is_some())
55 .field("base_url", &self.base_url)
56 .finish()
57 }
58}
59
60pub(crate) struct RootInner {
61 pub(crate) reflect: ReflectRoot,
62 pub(crate) registry: RegistryRoot,
63 pub(crate) events: EventsRoot,
64 pub(crate) logger: LoggerRoot,
65 pub(crate) next_scope: AtomicU64,
66 pub(crate) next_fiber: AtomicU64,
67 pub(crate) next_effect: AtomicU64,
68 pub(crate) root_fiber: OnceLock<Fiber>,
69}
70
71impl RootInner {
72 fn new() -> Self {
73 Self {
74 reflect: ReflectRoot::new(),
75 registry: RegistryRoot::new(),
76 events: EventsRoot::new(),
77 logger: LoggerRoot::new(),
78 next_scope: AtomicU64::new(0),
80 next_fiber: AtomicU64::new(0),
81 next_effect: AtomicU64::new(0),
82 root_fiber: OnceLock::new(),
83 }
84 }
85
86 pub(crate) fn scope(&self) -> Isolation {
87 Isolation(self.next_scope.fetch_add(1, Ordering::Relaxed) + 1)
88 }
89
90 pub(crate) fn fiber_id(&self) -> u64 {
91 self.next_fiber.fetch_add(1, Ordering::Relaxed) + 1
92 }
93
94 pub(crate) fn effect_id(&self) -> u64 {
95 self.next_effect.fetch_add(1, Ordering::Relaxed) + 1
96 }
97}
98
99#[derive(Clone)]
104pub struct Context {
105 pub(crate) root: Arc<RootInner>,
106 pub(crate) fiber: Weak<FiberInner>,
107 pub(crate) meta: ContextMeta,
108}
109
110impl Context {
111 pub fn new() -> Self {
114 let root = Arc::new(RootInner::new());
115 let fiber = Fiber::new_root(Arc::downgrade(&root), ContextMeta::default());
116 root.root_fiber
117 .set(fiber.clone())
118 .unwrap_or_else(|_| unreachable!("new root has no fiber"));
119 fiber.context().expect("fresh root is alive")
120 }
121
122 pub fn same_root(&self, other: &Context) -> bool {
124 Arc::ptr_eq(&self.root, &other.root)
125 }
126
127 pub fn root(&self) -> Context {
129 self.root
130 .root_fiber
131 .get()
132 .expect("root fiber initialized")
133 .context()
134 .expect("root context has a live root")
135 }
136
137 pub fn fiber(&self) -> Result<Fiber> {
139 self.fiber
140 .upgrade()
141 .map(Fiber::from_inner)
142 .ok_or_else(|| crate::CordisError::new(crate::ErrorCode::InactiveEffect))
143 }
144
145 pub fn base_url(&self) -> Option<&str> {
147 self.meta.base_url.as_deref()
148 }
149
150 pub fn with_base_url(&self, base_url: impl Into<Arc<str>>) -> Context {
152 let mut child = self.clone();
153 child.meta.base_url = Some(base_url.into());
154 child
155 }
156
157 pub fn extend<T>(&self, name: impl Into<String>, value: T) -> Context
159 where
160 T: Send + Sync + 'static,
161 {
162 self.extend_value(name, Value::new(value))
163 }
164
165 pub fn extend_value(&self, name: impl Into<String>, value: Value) -> Context {
167 let mut values = (*self.meta.values).clone();
168 values.insert(name.into(), value);
169 let mut child = self.clone();
170 child.meta.values = Arc::new(values);
171 child
172 }
173
174 pub fn metadata<T>(&self, name: &str) -> Result<Option<Arc<T>>>
176 where
177 T: Send + Sync + 'static,
178 {
179 self.meta.values.get(name).map(Value::downcast).transpose()
180 }
181
182 pub fn new_isolation(&self) -> Isolation {
184 self.root.scope()
185 }
186
187 pub fn isolate(&self, name: impl Into<String>) -> Context {
190 let label = self.new_isolation();
191 self.isolate_with(name, label)
192 }
193
194 pub fn isolate_with(&self, name: impl Into<String>, label: Isolation) -> Context {
202 let mut isolates = (*self.meta.isolates).clone();
203 isolates.insert(name.into(), label);
204 let mut child = self.clone();
205 child.meta.isolates = Arc::new(isolates);
206 child
207 }
208
209 pub fn isolate_many(
219 &self,
220 names: impl IntoIterator<Item = impl Into<String>>,
221 label: Option<Isolation>,
222 ) -> Context {
223 let label = label.unwrap_or_else(|| self.new_isolation());
224 let mut child = self.clone();
225 let mut isolates = (*child.meta.isolates).clone();
226 for name in names {
227 isolates.insert(name.into(), label);
228 }
229 child.meta.isolates = Arc::new(isolates);
230 child
231 }
232
233 pub fn intercept<T>(&self, name: impl Into<String>, config: T) -> Context
235 where
236 T: Send + Sync + 'static,
237 {
238 self.intercept_value(name, Value::new(config))
239 }
240
241 pub fn intercept_value(&self, name: impl Into<String>, config: Value) -> Context {
243 let mut intercepts = (*self.meta.intercepts).clone();
244 intercepts.push((name.into(), config));
245 let mut child = self.clone();
246 child.meta.intercepts = Arc::new(intercepts);
247 child
248 }
249
250 pub fn intercepts<T>(&self, name: &str) -> Result<Vec<Arc<T>>>
252 where
253 T: Send + Sync + 'static,
254 {
255 self.meta
256 .intercepts
257 .iter()
258 .filter(|(entry, _)| entry == name)
259 .map(|(_, value)| value.downcast())
260 .collect()
261 }
262
263 pub fn with_filter<F>(&self, filter: F) -> Context
265 where
266 F: Fn(&Context) -> bool + Send + Sync + 'static,
267 {
268 let mut child = self.clone();
269 child.meta.filter = Some(Arc::new(filter));
270 child
271 }
272
273 pub fn events(&self) -> EventsService {
275 EventsService::new(self.clone())
276 }
277
278 pub fn reflect(&self) -> ReflectService {
280 ReflectService::new(self.clone())
281 }
282
283 pub fn registry(&self) -> RegistryService {
285 RegistryService::new(self.clone())
286 }
287
288 pub fn logger(&self) -> Logger {
290 LoggerService::new(self.clone()).logger(None)
291 }
292
293 pub fn named_logger(&self, name: impl Into<String>) -> Logger {
295 LoggerService::new(self.clone()).logger(Some(name.into()))
296 }
297
298 pub fn logger_service(&self) -> LoggerService {
300 LoggerService::new(self.clone())
301 }
302
303 pub fn effect<F>(&self, label: impl Into<String>, dispose: F) -> Result<EffectHandle>
305 where
306 F: FnOnce() -> Result<()> + Send + 'static,
307 {
308 self.fiber()?
309 .register_effect(label, AsyncDisposer::from_sync(dispose))
310 }
311
312 pub fn effect_infallible<F>(&self, label: impl Into<String>, dispose: F) -> Result<EffectHandle>
314 where
315 F: FnOnce() + Send + 'static,
316 {
317 self.fiber()?
318 .register_effect(label, AsyncDisposer::infallible(dispose))
319 }
320
321 pub fn effect_async<F, Fut>(&self, label: impl Into<String>, dispose: F) -> Result<EffectHandle>
323 where
324 F: FnOnce() -> Fut + Send + 'static,
325 Fut: Future<Output = Result<()>> + Send + 'static,
326 {
327 self.fiber()?
328 .register_effect(label, AsyncDisposer::from_async(dispose))
329 }
330
331 pub fn provide<T>(&self, name: impl Into<String>, value: T) -> Result<EffectHandle>
333 where
334 T: Send + Sync + 'static,
335 {
336 self.reflect()
337 .provide_value(name.into(), Value::new(value), None)
338 }
339
340 pub fn provide_arc<T>(&self, name: impl Into<String>, value: Arc<T>) -> Result<EffectHandle>
342 where
343 T: Send + Sync + 'static,
344 {
345 self.reflect()
346 .provide_value(name.into(), Value::from_arc(value), None)
347 }
348
349 pub fn get<T>(&self, name: &str) -> Result<Option<Arc<T>>>
351 where
352 T: Send + Sync + 'static,
353 {
354 self.reflect().get(name, true)
355 }
356
357 pub fn get_unchecked<T>(&self, name: &str) -> Result<Option<Arc<T>>>
359 where
360 T: Send + Sync + 'static,
361 {
362 self.reflect().get(name, false)
363 }
364
365 pub fn require<T>(&self, name: &str) -> Result<Arc<T>>
367 where
368 T: Send + Sync + 'static,
369 {
370 self.reflect().require(name)
371 }
372
373 pub fn set<T>(&self, name: &str, value: T) -> Result<()>
379 where
380 T: Send + Sync + 'static,
381 {
382 self.reflect().set_value(name, Value::new(value))
383 }
384
385 pub fn notify<I, S>(&self, names: I) -> Vec<Fiber>
387 where
388 I: IntoIterator<Item = S>,
389 S: AsRef<str>,
390 {
391 self.reflect().notify(names)
392 }
393
394 pub fn accessor(&self, name: impl Into<String>, accessor: Accessor) -> Result<EffectHandle> {
396 self.reflect().accessor(name.into(), accessor)
397 }
398
399 pub fn on<F>(&self, name: impl Into<String>, listener: F) -> Result<EffectHandle>
401 where
402 F: Fn(Event) -> EventResult + Send + Sync + 'static,
403 {
404 self.events().on(name, listener, EventOptions::default())
405 }
406
407 pub fn on_with<F>(
409 &self,
410 name: impl Into<String>,
411 listener: F,
412 options: EventOptions,
413 ) -> Result<EffectHandle>
414 where
415 F: Fn(Event) -> EventResult + Send + Sync + 'static,
416 {
417 self.events().on(name, listener, options)
418 }
419
420 pub fn on_async<F, Fut>(&self, name: impl Into<String>, listener: F) -> Result<EffectHandle>
425 where
426 F: Fn(Event) -> Fut + Send + Sync + 'static,
427 Fut: Future<Output = EventResult> + Send + 'static,
428 {
429 self.events()
430 .on_async(name, listener, EventOptions::default())
431 }
432
433 pub fn once<F>(&self, name: impl Into<String>, listener: F) -> Result<EffectHandle>
435 where
436 F: Fn(Event) -> EventResult + Send + Sync + 'static,
437 {
438 self.events().once(name, listener, EventOptions::default())
439 }
440
441 pub fn emit(
443 &self,
444 name: impl Into<String>,
445 args: impl IntoIterator<Item = EventValue>,
446 ) -> Result<()> {
447 self.events().emit(name, args)
448 }
449
450 pub async fn parallel(
452 &self,
453 name: impl Into<String>,
454 args: impl IntoIterator<Item = EventValue>,
455 ) -> Result<()> {
456 self.events().parallel(name, args).await
457 }
458
459 pub async fn serial(
461 &self,
462 name: impl Into<String>,
463 args: impl IntoIterator<Item = EventValue>,
464 ) -> EventResult {
465 self.events().serial(name, args).await
466 }
467
468 pub fn bail(
470 &self,
471 name: impl Into<String>,
472 args: impl IntoIterator<Item = EventValue>,
473 ) -> EventResult {
474 self.events().bail(name, args)
475 }
476
477 pub fn waterfall<F>(
479 &self,
480 name: impl Into<String>,
481 args: impl IntoIterator<Item = EventValue>,
482 inner: F,
483 ) -> EventResult
484 where
485 F: Fn() -> EventResult + Send + Sync + 'static,
486 {
487 self.events().waterfall(name, args, inner)
488 }
489
490 pub fn plugin<P, C>(&self, plugin: P, config: C) -> Fiber
492 where
493 P: IntoPlugin,
494 C: Send + Sync + 'static,
495 {
496 self.registry()
497 .plugin_value(plugin.into_plugin(), Config::new(config))
498 }
499
500 pub fn plugin_default<P>(&self, plugin: P) -> Fiber
502 where
503 P: IntoPlugin,
504 {
505 self.registry()
506 .plugin_value(plugin.into_plugin(), Config::default())
507 }
508
509 pub fn plugin_object<P, C>(&self, plugin: P, config: C) -> Fiber
511 where
512 P: crate::Plugin,
513 C: Send + Sync + 'static,
514 {
515 self.registry()
516 .plugin_value(crate::PluginHandle::new(plugin), Config::new(config))
517 }
518
519 pub fn plugin_object_default<P>(&self, plugin: P) -> Fiber
521 where
522 P: crate::Plugin,
523 {
524 self.registry()
525 .plugin_value(crate::PluginHandle::new(plugin), Config::default())
526 }
527
528 pub fn inject<F>(&self, inject: Inject, callback: F) -> Fiber
530 where
531 F: Fn(Context) -> Result<PluginOutput> + Send + Sync + 'static,
532 {
533 let plugin = crate::plugin_sync::<(), _>("anonymous", inject, move |ctx, _| callback(ctx));
534 self.plugin_default(plugin)
535 }
536
537 pub fn log_error(&self, error: impl ToString) {
539 self.logger().error(error.to_string(), Vec::<LogArg>::new());
540 }
541
542 pub(crate) fn scope_override(&self, name: &str) -> Option<Isolation> {
543 self.meta.isolates.get(name).copied()
544 }
545
546 pub(crate) fn filter(&self) -> Option<&ContextFilter> {
547 self.meta.filter.as_ref()
548 }
549
550 pub(crate) fn root_arc(&self) -> &Arc<RootInner> {
551 &self.root
552 }
553}
554
555impl Default for Context {
556 fn default() -> Self {
557 Self::new()
558 }
559}
560
561impl Debug for Context {
562 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
563 let name = self
564 .fiber()
565 .map(|fiber| fiber.name())
566 .unwrap_or_else(|_| "disposed".to_owned());
567 f.debug_tuple("Context").field(&name).finish()
568 }
569}