sheave_core/messages/
publish.rs

1mod invalid_publishing_type;
2
3use std::io::Result as IOResult;
4use crate::{
5    ByteBuffer,
6    Decoder,
7    Encoder,
8    messages::{
9        Channel,
10        ChunkData,
11        Command,
12        amf::v0::{
13            AmfString,
14            Null
15        },
16        headers::MessageType
17    }
18};
19pub use self::invalid_publishing_type::*;
20
21/// The command to tell publishing information.
22///
23/// Following format is required:
24///
25/// |Field|AMF Type|Value|
26/// | :- | :- | :- |
27/// ||[`Null`]|Nothing but an AMF's type marker is in.|
28/// |Publishing Name|[`String`]|A name for publishing a data to the server.|
29/// |Publishing Type|[`String`]|See [Publishing Type](#publishing-type).|
30///
31/// # Publishing Type
32///
33/// The publish command requires you to specify one of "Publishing Type" in its request.
34/// Publishing Type means:
35///
36/// |Pubishing Type|Description|
37/// | :- | :- |
38/// |`"live"`|Only streaming.<br />Its data will never be stored.|
39/// |`"record"`|Its data will be stored.<br />If publishing name duplicated, it is rewritten as a new file.|
40/// |`"append"`|Same as `"record"` excepts is appended its data if publishing name duplicated.|
41///
42/// [`String`]: crate::messages::amf::v0::AmfString
43/// [`Null`]: crate::messages::amf::v0::Null
44#[derive(Debug, Clone, PartialEq)]
45pub struct Publish {
46    publishing_name: AmfString,
47    publishing_type: AmfString
48}
49
50impl Publish {
51    /// Constructs a Publish command.
52    pub fn new(publishing_name: AmfString, publishing_type: AmfString) -> Self {
53        Self { publishing_name, publishing_type }
54    }
55
56    /// Gets the publishing identifier. (e.g. filename)
57    pub fn get_publishing_name(&self) -> &AmfString {
58        &self.publishing_name
59    }
60
61    /// Gets one of publishing type which is either `"live"`, `"record"` or `"append"`.
62    pub fn get_publishing_type(&self) -> &AmfString {
63        &self.publishing_type
64    }
65}
66
67impl From<Publish> for (AmfString, AmfString) {
68    fn from(publish: Publish) -> Self {
69        (publish.publishing_name, publish.publishing_type)
70    }
71}
72
73impl ChunkData for Publish {
74    const CHANNEL: Channel = Channel::Source;
75    const MESSAGE_TYPE: MessageType = MessageType::Command;
76}
77
78impl Command for Publish {}
79
80impl Decoder<Publish> for ByteBuffer {
81    /// Decodes bytes into a Publish command.
82    ///
83    /// # Errors
84    ///
85    /// * [`InsufficientBufferLength`]
86    ///
87    /// When some field misses.
88    ///
89    /// * [`InconsistentMarker`]
90    ///
91    /// When some value is inconsistent with its marker.
92    ///
93    /// * [`InvalidString`]
94    ///
95    /// When some value is invalid for UTF-8 string.
96    ///
97    /// * [`InvalidPublishingType`]
98    ///
99    /// When the publishing type is neither `"live"`, `"record"` nor `"append"`.
100    ///
101    /// # Examples
102    ///
103    /// ```rust
104    /// use sheave_core::{
105    ///     ByteBuffer,
106    ///     Decoder,
107    ///     Encoder,
108    ///     messages::{
109    ///         Publish,
110    ///         amf::v0::{
111    ///             AmfString,
112    ///             Null
113    ///         }
114    ///     }
115    /// };
116    ///
117    /// let mut buffer = ByteBuffer::default();
118    /// buffer.encode(&Null);
119    /// buffer.encode(&AmfString::default());
120    /// buffer.encode(&AmfString::from("live"));
121    /// assert!(Decoder::<Publish>::decode(&mut buffer).is_ok());
122    ///
123    /// let mut buffer = ByteBuffer::default();
124    /// buffer.encode(&Null);
125    /// buffer.encode(&AmfString::default());
126    /// buffer.encode(&AmfString::from("record"));
127    /// assert!(Decoder::<Publish>::decode(&mut buffer).is_ok());
128    ///
129    /// let mut buffer = ByteBuffer::default();
130    /// buffer.encode(&Null);
131    /// buffer.encode(&AmfString::default());
132    /// buffer.encode(&AmfString::from("append"));
133    /// assert!(Decoder::<Publish>::decode(&mut buffer).is_ok());
134    ///
135    /// let mut buffer = ByteBuffer::default();
136    /// buffer.encode(&Null);
137    /// buffer.encode(&AmfString::default());
138    /// buffer.encode(&AmfString::from("something else"));
139    /// assert!(Decoder::<Publish>::decode(&mut buffer).is_err())
140    /// ```
141    ///
142    /// [`InsufficientBufferLength`]: crate::byte_buffer::InsufficientBufferLength
143    /// [`InconsistentMarker`]: crate::messages::amf::InconsistentMarker
144    /// [`InvalidString`]: crate::messages::amf::InvalidString
145    /// [`InvalidPublishingType`]: InvalidPublishingType
146    fn decode(&mut self) -> IOResult<Publish> {
147        Decoder::<Null>::decode(self)?;
148        let publishing_name: AmfString = self.decode()?;
149        let publishing_type: AmfString = self.decode()?;
150
151        if publishing_type != "live" && publishing_type != "record" && publishing_type != "append" {
152            return Err(invalid_publishing_type(publishing_type))
153        }
154
155        Ok(Publish { publishing_name, publishing_type })
156    }
157}
158
159impl Encoder<Publish> for ByteBuffer {
160    /// Encodes a Publish command into bytes.
161    fn encode(&mut self, publish: &Publish) {
162        self.encode(&Null);
163        self.encode(publish.get_publishing_name());
164        self.encode(publish.get_publishing_type());
165    }
166}
167
168#[cfg(test)]
169mod tests {
170    use super::*;
171
172    #[test]
173    fn decode_publish() {
174        let mut buffer = ByteBuffer::default();
175        buffer.encode(&Null);
176        buffer.encode(&AmfString::default());
177        buffer.encode(&AmfString::from("live"));
178        let result: IOResult<Publish> = buffer.decode();
179        assert!(result.is_ok());
180        let actual = result.unwrap();
181        let expected = Publish::new(AmfString::default(), AmfString::from("live"));
182        assert_eq!(expected, actual)
183    }
184
185    #[test]
186    fn encode_publish() {
187        let mut buffer = ByteBuffer::default();
188        let expected_publishing_name = "";
189        let expected_publishing_type = "live";
190        let expected = Publish::new(AmfString::from(expected_publishing_name), AmfString::from(expected_publishing_type));
191        buffer.encode(&expected);
192        Decoder::<Null>::decode(&mut buffer).unwrap();
193        let actual_publishing_name: AmfString = buffer.decode().unwrap();
194        assert_eq!(expected_publishing_name, actual_publishing_name);
195        let actual_publishing_type: AmfString = buffer.decode().unwrap();
196        assert_eq!(expected_publishing_type, actual_publishing_type)
197    }
198}