Skip to main content

moqtap_client/draft15/
track_status.rs

1/// TrackStatus lifecycle states.
2#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3pub enum TrackStatusState {
4    /// Initial state before any TRACK_STATUS message is sent.
5    Idle,
6    /// TRACK_STATUS has been sent; awaiting OK or ERROR.
7    Pending,
8    /// Track status request has completed.
9    Done,
10}
11
12/// Errors that can occur during track status state transitions.
13#[derive(Debug, thiserror::Error, PartialEq, Eq)]
14pub enum TrackStatusError {
15    /// An event was received that is not valid for the current state.
16    #[error("invalid transition from {from:?} on event {event}")]
17    InvalidTransition {
18        /// The state the machine was in when the invalid event arrived.
19        from: TrackStatusState,
20        /// The name of the event that was rejected.
21        event: String,
22    },
23}
24
25/// Pure state machine for a MoQT track status request.
26/// Transitions: Idle -> Pending -> Done.
27pub struct TrackStatusStateMachine {
28    state: TrackStatusState,
29}
30
31impl Default for TrackStatusStateMachine {
32    fn default() -> Self {
33        Self::new()
34    }
35}
36
37impl TrackStatusStateMachine {
38    /// Creates a new state machine in the [`TrackStatusState::Idle`] state.
39    pub fn new() -> Self {
40        Self { state: TrackStatusState::Idle }
41    }
42
43    /// Returns the current state of the track status request.
44    pub fn state(&self) -> TrackStatusState {
45        self.state
46    }
47
48    /// Idle -> Pending (TRACK_STATUS sent).
49    pub fn on_track_status_sent(&mut self) -> Result<(), TrackStatusError> {
50        if self.state == TrackStatusState::Idle {
51            self.state = TrackStatusState::Pending;
52            Ok(())
53        } else {
54            Err(TrackStatusError::InvalidTransition {
55                from: self.state,
56                event: "on_track_status_sent".to_string(),
57            })
58        }
59    }
60
61    /// Pending -> Done (REQUEST_OK received).
62    pub fn on_track_status_ok(&mut self) -> Result<(), TrackStatusError> {
63        if self.state == TrackStatusState::Pending {
64            self.state = TrackStatusState::Done;
65            Ok(())
66        } else {
67            Err(TrackStatusError::InvalidTransition {
68                from: self.state,
69                event: "on_track_status_ok".to_string(),
70            })
71        }
72    }
73
74    /// Pending -> Done (REQUEST_ERROR received).
75    pub fn on_track_status_error(&mut self) -> Result<(), TrackStatusError> {
76        if self.state == TrackStatusState::Pending {
77            self.state = TrackStatusState::Done;
78            Ok(())
79        } else {
80            Err(TrackStatusError::InvalidTransition {
81                from: self.state,
82                event: "on_track_status_error".to_string(),
83            })
84        }
85    }
86}