Skip to main content

scosh_core/
events.rs

1//! Host-facing events and effect acknowledgements.
2
3use std::fmt;
4
5use crate::{
6    input::{InputId, InputRequest, InputResult},
7    types::{StateRevision, TerminalDelta, TerminalSnapshot, TerminalState},
8};
9
10/// Lifecycle state visible to a host application.
11#[derive(Clone, Copy, Debug, Eq, PartialEq)]
12pub enum SessionStatus {
13    Connecting,
14    Live,
15    Recovering,
16    Suspended,
17    Closed,
18    Failed,
19}
20
21/// Why the host must install a fresh authoritative snapshot.
22#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub enum SnapshotRequiredReason {
24    NoBase,
25    RevisionGap,
26    InvalidDelta,
27}
28
29/// A reason-neutral acknowledgement for a host-side terminal effect.
30#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
31pub struct CommitReceipt(pub(crate) u64);
32
33impl CommitReceipt {
34    /// Returns the opaque value that the host must pass back to acknowledge
35    /// this effect.
36    pub const fn get(self) -> u64 {
37        self.0
38    }
39}
40
41impl fmt::Debug for CommitReceipt {
42    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
43        formatter.write_str("CommitReceipt(<opaque>)")
44    }
45}
46
47/// Result of acknowledging a reliable host-side effect.
48#[derive(Clone, Copy, Debug, Eq, PartialEq)]
49pub enum AcknowledgeResult {
50    Committed,
51    Duplicate,
52    RejectedStale,
53    RejectedUnknown,
54}
55
56/// Effects that must be committed by the host terminal exactly once.
57#[derive(Clone, Debug, Eq, PartialEq)]
58pub enum TerminalEffect {
59    PrimaryScroll { rows: Vec<crate::PrimaryScrollRow> },
60    Screen { alternate: bool },
61    InputModes { modes: u16 },
62}
63
64/// Events delivered by the portable core.  No wire frame, endpoint, token, or
65/// server session identifier crosses this boundary.
66#[derive(Clone, Debug, Eq, PartialEq)]
67pub enum SessionEvent {
68    Snapshot {
69        snapshot: TerminalSnapshot,
70    },
71    Delta {
72        delta: TerminalDelta,
73        effects: Vec<TerminalEffect>,
74        receipt: Option<CommitReceipt>,
75    },
76    SnapshotRequired {
77        expected: StateRevision,
78        received: StateRevision,
79        reason: SnapshotRequiredReason,
80    },
81    StatusChanged(SessionStatus),
82    InputQueued {
83        request: InputRequest,
84    },
85    InputCompleted {
86        id: InputId,
87        outcome: crate::InputOutcome,
88    },
89    ConsumerStalled,
90}
91
92impl SessionEvent {
93    /// Return the complete state carried by a snapshot event.
94    pub fn snapshot_state(&self) -> Option<&TerminalState> {
95        match self {
96            Self::Snapshot { snapshot } => Some(&snapshot.state),
97            _ => None,
98        }
99    }
100
101    /// Return the input result carried by an input completion event.
102    pub fn input_result(&self) -> Option<InputResult> {
103        match self {
104            Self::InputCompleted { id, outcome } => Some(InputResult {
105                id: *id,
106                outcome: *outcome,
107            }),
108            _ => None,
109        }
110    }
111}