sheave_core/messages/
release_stream.rs

1use std::io::Result as IOResult;
2use super::{
3    Channel,
4    ChunkData,
5    Command,
6    headers::MessageType
7};
8use crate::{
9    Decoder,
10    Encoder,
11    ByteBuffer,
12    messages::amf::v0::{
13        AmfString,
14        Null
15    }
16};
17
18/// The command to tell some path to the server.
19///
20/// Following format is required.
21///
22/// |Field|AMF Type|Value|
23/// | :- | :- | :- |
24/// |Command Name|[`String`]|`"releaseStream"`|
25/// |Transaction ID|[`Number`]|A number which is next of the connect.|
26/// ||[`Null`]|Nothing but an AMF's type marker is in.|
27/// |Path|[`String`]|Some path to audio/video data to make server opened.|
28///
29/// For example, path is defined as some file name in FFmpeg and OBS.
30///
31/// [`Number`]: crate::messages::amf::v0::Number
32/// [`String`]: crate::messages::amf::v0::AmfString
33/// [`Null`]: crate::messages::amf::v0::Null
34#[derive(Debug, Clone, PartialEq)]
35pub struct ReleaseStream(AmfString);
36
37impl ReleaseStream {
38    /// Constructs a ReleaseStream command.
39    pub fn new(topic_path: AmfString) -> Self {
40        Self(topic_path)
41    }
42
43    /// Gets the topic path.
44    pub fn get_topic_path(&self) -> &AmfString {
45        &self.0
46    }
47}
48
49impl From<ReleaseStream> for AmfString {
50    fn from(release_stream: ReleaseStream) -> Self {
51        release_stream.0
52    }
53}
54
55impl ChunkData for ReleaseStream {
56    const CHANNEL: Channel = Channel::System;
57    const MESSAGE_TYPE: MessageType = MessageType::Command;
58}
59
60impl Command for ReleaseStream {}
61
62impl Decoder<ReleaseStream> for ByteBuffer {
63    /// Decodes bytes into a ReleaseStream command.
64    ///
65    /// # Errors
66    ///
67    /// * [`InsufficientBufferLength`]
68    ///
69    /// When some field misses.
70    ///
71    /// * [`InconsistentMarker`]
72    ///
73    /// When some value is inconsistent with its marker.
74    ///
75    /// * [`InvalidString`]
76    ///
77    /// When some value is invalid for UTF-8 string.
78    ///
79    /// # Examples
80    ///
81    /// ```rust
82    /// use sheave_core::{
83    ///     ByteBuffer,
84    ///     Decoder,
85    ///     Encoder,
86    ///     messages::{
87    ///         ReleaseStream,
88    ///         amf::v0::{
89    ///             AmfString,
90    ///             Null
91    ///         }
92    ///     }
93    /// };
94    ///
95    /// let mut buffer = ByteBuffer::default();
96    /// buffer.encode(&Null);
97    /// buffer.encode(&AmfString::default());
98    /// assert!(Decoder::<ReleaseStream>::decode(&mut buffer).is_ok());
99    ///
100    /// let mut buffer = ByteBuffer::default();
101    /// assert!(Decoder::<ReleaseStream>::decode(&mut buffer).is_err())
102    /// ```
103    ///
104    /// [`InsufficientBufferLength`]: crate::byte_buffer::InsufficientBufferLength
105    /// [`InconsistentMarker`]: crate::messages::amf::InconsistentMarker
106    /// [`InvalidString`]: crate::messages::amf::InvalidString
107    fn decode(&mut self) -> IOResult<ReleaseStream> {
108        Decoder::<Null>::decode(self)?;
109        let topic_path: AmfString = self.decode()?;
110        Ok(ReleaseStream(topic_path))
111    }
112}
113
114impl Encoder<ReleaseStream> for ByteBuffer {
115    /// Encodes a ReleaseStream command into bytes.
116    fn encode(&mut self, release_stream: &ReleaseStream) {
117        self.encode(&Null);
118        self.encode(release_stream.get_topic_path());
119    }
120}
121
122#[cfg(test)]
123mod tests {
124    use super::*;
125
126    #[test]
127    fn decode_release_stream() {
128        let mut buffer = ByteBuffer::default();
129        buffer.encode(&Null);
130        buffer.encode(&AmfString::default());
131        let result: IOResult<ReleaseStream> = buffer.decode();
132        assert!(result.is_ok());
133        let actual = result.unwrap();
134        let expected = ReleaseStream::new(AmfString::default());
135        assert_eq!(expected, actual)
136    }
137
138    #[test]
139    fn encode_release_stream() {
140        let mut buffer = ByteBuffer::default();
141        let expected_topic_path = "";
142        let expected = ReleaseStream::new(AmfString::from(expected_topic_path));
143        buffer.encode(&expected);
144        Decoder::<Null>::decode(&mut buffer).unwrap();
145        let actual_topic_path: AmfString = buffer.decode().unwrap();
146        assert_eq!(expected_topic_path, actual_topic_path)
147    }
148}