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