dstar_gateway_core/session/client/
state.rs

1//! Sealed `ClientState` markers for the typestate session.
2
3/// Sealed marker for client connection states.
4pub trait ClientState: sealed::Sealed + 'static {}
5
6mod sealed {
7    pub trait Sealed {}
8}
9
10/// Built but no I/O happened.
11#[derive(Debug, Clone, Copy)]
12pub struct Configured;
13
14/// (`DPlus` only) TCP auth completed, host list cached.
15#[derive(Debug, Clone, Copy)]
16pub struct Authenticated;
17
18/// LINK1 sent, awaiting LINK1-ACK or LINK2-ACK.
19#[derive(Debug, Clone, Copy)]
20pub struct Connecting;
21
22/// Connected and operational. The only state where `send_*` exists.
23#[derive(Debug, Clone, Copy)]
24pub struct Connected;
25
26/// UNLINK sent, awaiting confirmation or timeout.
27#[derive(Debug, Clone, Copy)]
28pub struct Disconnecting;
29
30/// Terminal — must be rebuilt to use again.
31#[derive(Debug, Clone, Copy)]
32pub struct Closed;
33
34impl sealed::Sealed for Configured {}
35impl ClientState for Configured {}
36impl sealed::Sealed for Authenticated {}
37impl ClientState for Authenticated {}
38impl sealed::Sealed for Connecting {}
39impl ClientState for Connecting {}
40impl sealed::Sealed for Connected {}
41impl ClientState for Connected {}
42impl sealed::Sealed for Disconnecting {}
43impl ClientState for Disconnecting {}
44impl sealed::Sealed for Closed {}
45impl ClientState for Closed {}
46
47/// Runtime discriminator mirroring the typestate markers.
48#[non_exhaustive]
49#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
50pub enum ClientStateKind {
51    /// Configured.
52    Configured,
53    /// Authenticated (`DPlus` only).
54    Authenticated,
55    /// Connecting.
56    Connecting,
57    /// Connected.
58    Connected,
59    /// Disconnecting.
60    Disconnecting,
61    /// Closed.
62    Closed,
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn states_are_distinct_zero_sized_types() {
71        assert_eq!(size_of::<Configured>(), 0);
72        assert_eq!(size_of::<Connected>(), 0);
73        assert_eq!(size_of::<Closed>(), 0);
74    }
75
76    #[test]
77    fn state_kind_variants_distinct() {
78        assert_ne!(ClientStateKind::Configured, ClientStateKind::Connected);
79    }
80}