khora_core/context.rs
1// Copyright 2025 eraflo
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Core engine context providing access to foundational subsystems.
16
17use crate::lane::{LaneBus, OutputDeck};
18use crate::runtime::Runtime;
19use std::any::Any;
20use std::sync::Arc;
21
22/// How an agent's `execute` may reach the ECS `World` this frame, granted by
23/// the scheduler according to the agent's
24/// [`Agent::access`](crate::agent::Agent::access) declaration.
25///
26/// The parallel executor uses this to hand a serial (`Exclusive`) agent a
27/// mutable world while giving concurrently-running read-only (`Shared`) agents
28/// a shared reference — `World` is `Sync`, so many `&World` readers are safe,
29/// but a mutable borrow must be exclusive.
30pub enum WorldAccess<'a> {
31 /// No world access — the agent reads only the `LaneBus` and writes its deck.
32 None,
33 /// Shared, read-only world. Multiple `Shared` agents may run concurrently.
34 Shared(&'a dyn Any),
35 /// Exclusive, mutable world. The agent runs serially.
36 Exclusive(&'a mut dyn Any),
37}
38
39/// Engine context providing access to various subsystems.
40///
41/// Built once per frame by the Scheduler and passed to every Agent's
42/// `execute()`. The Agent forwards `bus` and `deck` to its `LaneContext`
43/// so that lanes can read [`Flow`] outputs and write their own outputs.
44///
45/// The `runtime` bundle exposes the three runtime containers
46/// ([`Services`](crate::runtime::Services),
47/// [`Backends`](crate::runtime::Backends),
48/// [`Resources`](crate::runtime::Resources)) — agents pick the right one
49/// based on what they're looking for.
50///
51/// [`Flow`]: ../../../khora_data/flow/index.html
52pub struct EngineContext<'a> {
53 /// The ECS `World` access this agent was granted — see [`WorldAccess`].
54 /// Reach it through [`world_ref`](Self::world_ref) (read) or
55 /// [`world_mut`](Self::world_mut) (mutate), never by matching directly.
56 pub world: WorldAccess<'a>,
57
58 /// Runtime containers — services (business APIs), backends (trait
59 /// impls), resources (shared state).
60 pub runtime: Arc<Runtime>,
61
62 /// Read-only typed bus of [`Flow`](../../../khora_data/flow/index.html)
63 /// outputs produced this tick. Lanes consume Views from here.
64 pub bus: &'a LaneBus,
65
66 /// Mutable typed deck for lane outputs (recorded GPU commands, draw
67 /// lists, etc.). Drained by the engine at the I/O boundary.
68 pub deck: &'a mut OutputDeck,
69}
70
71impl EngineContext<'_> {
72 /// Read-only access to the type-erased `World`, if any was granted.
73 /// Available under both `Shared` and `Exclusive` access (a mutable grant
74 /// also permits reads). `None` for an `Isolated` (world-free) agent.
75 pub fn world_ref(&self) -> Option<&dyn Any> {
76 match &self.world {
77 WorldAccess::Shared(w) => Some(*w),
78 WorldAccess::Exclusive(w) => Some(&**w),
79 WorldAccess::None => None,
80 }
81 }
82
83 /// Mutable access to the type-erased `World`, granted only under
84 /// `Exclusive` access. `None` for `Shared` or `Isolated` agents — a
85 /// read-only or world-free agent must never mutate the world.
86 pub fn world_mut(&mut self) -> Option<&mut dyn Any> {
87 match &mut self.world {
88 WorldAccess::Exclusive(w) => Some(&mut **w),
89 _ => None,
90 }
91 }
92}