Skip to main content

oaat_core/
session.rs

1use crate::error::OaatError;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum SessionState {
5    Discovery,
6    Handshake,
7    Idle,
8    Negotiation,
9    Streaming,
10    Paused,
11    Stopped,
12    Disconnected,
13}
14
15impl SessionState {
16    pub fn can_transition_to(self, next: Self) -> bool {
17        use SessionState::*;
18        matches!(
19            (self, next),
20            (Discovery, Handshake)
21                | (Handshake, Idle)
22                | (Handshake, Disconnected)
23                | (Idle, Negotiation)
24                | (Idle, Disconnected)
25                | (Negotiation, Streaming)
26                | (Negotiation, Idle)
27                | (Negotiation, Disconnected)
28                | (Streaming, Paused)
29                | (Streaming, Stopped)
30                | (Streaming, Disconnected)
31                | (Paused, Streaming)
32                | (Paused, Stopped)
33                | (Paused, Disconnected)
34                | (Stopped, Negotiation)
35                | (Stopped, Idle)
36                | (Stopped, Disconnected)
37                | (Disconnected, Discovery)
38        )
39    }
40
41    pub fn transition(self, next: Self) -> Result<Self, OaatError> {
42        if self.can_transition_to(next) {
43            Ok(next)
44        } else {
45            Err(OaatError::InvalidStateTransition {
46                from: self,
47                to: next,
48            })
49        }
50    }
51}
52
53impl std::fmt::Display for SessionState {
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        match self {
56            Self::Discovery => write!(f, "Discovery"),
57            Self::Handshake => write!(f, "Handshake"),
58            Self::Idle => write!(f, "Idle"),
59            Self::Negotiation => write!(f, "Negotiation"),
60            Self::Streaming => write!(f, "Streaming"),
61            Self::Paused => write!(f, "Paused"),
62            Self::Stopped => write!(f, "Stopped"),
63            Self::Disconnected => write!(f, "Disconnected"),
64        }
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71
72    #[test]
73    fn valid_transitions() {
74        let s = SessionState::Discovery;
75        let s = s.transition(SessionState::Handshake).unwrap();
76        let s = s.transition(SessionState::Idle).unwrap();
77        let s = s.transition(SessionState::Negotiation).unwrap();
78        let s = s.transition(SessionState::Streaming).unwrap();
79        let s = s.transition(SessionState::Paused).unwrap();
80        let s = s.transition(SessionState::Streaming).unwrap();
81        let s = s.transition(SessionState::Stopped).unwrap();
82        let s = s.transition(SessionState::Disconnected).unwrap();
83        assert_eq!(s, SessionState::Disconnected);
84    }
85
86    #[test]
87    fn invalid_transition() {
88        let s = SessionState::Idle;
89        assert!(s.transition(SessionState::Streaming).is_err());
90    }
91}