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}