use crate::ids::{PaneId, TabId, ViewerId};
use bevy_ecs::prelude::*;
use std::collections::BTreeMap;
#[derive(Resource, Clone, Debug)]
pub struct Limits {
pub max_workspaces: usize,
pub max_tabs: usize,
pub max_panes: usize,
pub max_viewers: usize,
pub scrollback_lines: usize,
pub viewer_queue: usize,
pub retire_grace_ms: u64,
pub terminate_deadline_ms: u64,
pub output_event_interval_ms: u64,
pub frame_interval_ms: u64,
}
impl Limits {
#[must_use]
pub fn from_config(config: &crate::config::Config) -> Self {
Self {
max_workspaces: config.limits.max_workspaces,
max_tabs: config.limits.max_tabs,
max_panes: config.limits.max_panes,
max_viewers: crate::proto::attach::MAX_VIEWERS_PER_WORKSPACE,
scrollback_lines: usize::try_from(config.history.scrollback_lines)
.unwrap_or(usize::MAX),
viewer_queue: 256,
retire_grace_ms: 5_000,
terminate_deadline_ms: 10_000,
output_event_interval_ms: 250,
frame_interval_ms: 8,
}
}
}
#[derive(Resource, Clone, Debug, Default)]
pub struct Ids {
next_pane: u32,
next_stream: u64,
next_tab: u32,
pub panes: BTreeMap<PaneId, Entity>,
pub tabs: BTreeMap<TabId, Entity>,
pub viewers: BTreeMap<ViewerId, Entity>,
pub workspaces: BTreeMap<String, Entity>,
}
impl Ids {
pub fn next_stream(&mut self) -> Option<u64> {
self.next_stream = self.next_stream.checked_add(1)?;
Some(self.next_stream)
}
pub fn next_pane(&mut self) -> Option<PaneId> {
self.next_pane = self.next_pane.checked_add(1)?;
Some(PaneId(self.next_pane))
}
pub fn next_tab(&mut self) -> Option<TabId> {
self.next_tab = self.next_tab.checked_add(1)?;
Some(TabId(self.next_tab))
}
#[must_use]
pub fn pane(&self, id: PaneId) -> Option<Entity> {
self.panes.get(&id).copied()
}
#[must_use]
pub fn tab(&self, id: TabId) -> Option<Entity> {
self.tabs.get(&id).copied()
}
#[must_use]
pub fn viewer(&self, id: ViewerId) -> Option<Entity> {
self.viewers.get(&id).copied()
}
#[must_use]
pub fn workspace(&self, name: &str) -> Option<Entity> {
self.workspaces.get(name).copied()
}
}
#[derive(Resource, Clone, Copy, Debug, Default)]
pub struct Clock {
pub now_ms: u64,
pub step: u64,
}
#[derive(Resource, Clone, Copy, Debug, Default)]
pub struct Deadlines {
pub next_ms: Option<u64>,
}
impl Deadlines {
pub fn propose(&mut self, at_ms: u64) {
self.next_ms = Some(self.next_ms.map_or(at_ms, |current| current.min(at_ms)));
}
}
#[derive(Resource, Clone, Debug)]
pub struct Registry {
pub bindings: crate::commands::ClientBindings,
pub default_command: Vec<String>,
}
#[derive(Resource, Clone, Debug, Default)]
pub struct ServerIdentity {
pub pid: u32,
pub instance_nonce: String,
pub runtime_dir: std::path::PathBuf,
}
#[derive(Resource, Clone, Copy, Debug, Default)]
pub struct ShuttingDown(pub bool);
#[derive(Resource, Clone, Copy, Debug, Default)]
pub struct WorkspaceCounter(pub u32);
#[derive(Clone, Debug)]
pub struct PendingWait {
pub requester: crate::ecs::messages::Requester,
pub id: u64,
pub pane: PaneId,
pub workspace: Entity,
pub until: crate::proto::control::WaitUntil,
pub timeout_at_ms: u64,
pub last_seq: u64,
pub last_change_ms: u64,
}
#[derive(Resource, Clone, Debug, Default)]
pub struct Waits {
pub pending: Vec<PendingWait>,
}
pub const MAX_INPUT_OPERATIONS: usize = 128;
pub const INPUT_RETENTION_MS: u64 = 60_000;
pub struct InputRecord {
pub workspace: Entity,
pub receipt: crate::proto::control::InputReceipt,
pub bytes: Option<Vec<u8>>,
}
#[derive(Resource, Default)]
pub struct InputOperations {
pub next: u64,
pub records: BTreeMap<u64, InputRecord>,
}
pub const MAX_FINAL_RECORDS: usize = 128;
pub const FINAL_RETENTION_MS: u64 = 60_000;
#[derive(Resource, Default)]
pub struct FinalRecords(pub BTreeMap<PaneId, crate::proto::control::FinalRecord>);