sheave_core/messages/
fc_unpublish.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/// This command is same as [`FcPublish`] except this requests to delete the topic path.
19///
20/// [`FcPublish`]: super::FcPublish
21#[derive(Debug, Clone, PartialEq)]
22pub struct FcUnpublish(AmfString);
23
24impl FcUnpublish {
25    /// Constructs a FcUnpublish command.
26    pub fn new(topic_path: AmfString) -> Self {
27        Self(topic_path)
28    }
29
30    /// Gets the playpath.
31    pub fn get_topic_path(&self) -> &AmfString {
32        &self.0
33    }
34}
35
36impl From<FcUnpublish> for AmfString {
37    fn from(fc_unpublish: FcUnpublish) -> Self {
38        fc_unpublish.0
39    }
40}
41
42impl ChunkData for FcUnpublish {
43    const CHANNEL: Channel = Channel::System;
44    const MESSAGE_TYPE: MessageType = MessageType::Command;
45}
46
47impl Command for FcUnpublish {}
48
49impl Decoder<FcUnpublish> for ByteBuffer {
50    /// Decodes bytes into a FcUnpublish command.
51    ///
52    /// # Errors
53    ///
54    /// * [`InsufficientBufferLength`]
55    ///
56    /// When some field misses.
57    ///
58    /// * [`InconsistentMarker`]
59    ///
60    /// When some value is inconsistent with its marker.
61    ///
62    /// * [`InvalidString`]
63    ///
64    /// When some value is invalid for UTF-8 string.
65    ///
66    /// # Examples
67    ///
68    /// ```rust
69    /// use sheave_core::{
70    ///     ByteBuffer,
71    ///     Decoder,
72    ///     Encoder,
73    ///     messages::{
74    ///         FcUnpublish,
75    ///         amf::v0::{
76    ///             AmfString,
77    ///             Null
78    ///         }
79    ///     }
80    /// };
81    ///
82    /// let mut buffer = ByteBuffer::default();
83    /// buffer.encode(&Null);
84    /// buffer.encode(&AmfString::default());
85    /// assert!(Decoder::<FcUnpublish>::decode(&mut buffer).is_ok());
86    ///
87    /// let mut buffer = ByteBuffer::default();
88    /// assert!(Decoder::<FcUnpublish>::decode(&mut buffer).is_err())
89    /// ```
90    ///
91    /// [`InsufficientBufferLength`]: crate::byte_buffer::InsufficientBufferLength
92    /// [`InconsistentMarker`]: crate::messages::amf::InconsistentMarker
93    /// [`InvalidString`]: crate::messages::amf::InvalidString
94    fn decode(&mut self) -> IOResult<FcUnpublish> {
95        Decoder::<Null>::decode(self)?;
96        let topic_path: AmfString = self.decode()?;
97
98        Ok(FcUnpublish(topic_path))
99    }
100}
101
102impl Encoder<FcUnpublish> for ByteBuffer {
103    /// Encodes a FcUnpublish command into bytes.
104    fn encode(&mut self, fc_unpublish: &FcUnpublish) {
105        self.encode(&Null);
106        self.encode(fc_unpublish.get_topic_path());
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn decode_fc_unpublish() {
116        let mut buffer = ByteBuffer::default();
117        buffer.encode(&Null);
118        buffer.encode(&AmfString::default());
119
120        let result: IOResult<FcUnpublish> = buffer.decode();
121        assert!(result.is_ok());
122        let actual = result.unwrap();
123        let expected = FcUnpublish::new(AmfString::default());
124        assert_eq!(expected, actual)
125    }
126
127    #[test]
128    fn encode_fc_unpublish() {
129        let mut buffer = ByteBuffer::default();
130        let expected_topic_path = "";
131        let expected = FcUnpublish::new(AmfString::from(expected_topic_path));
132        buffer.encode(&expected);
133        Decoder::<Null>::decode(&mut buffer).unwrap();
134        let actual_topic_path: AmfString = buffer.decode().unwrap();
135        assert_eq!(expected_topic_path, actual_topic_path)
136    }
137}