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