Skip to main content

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}