moq_lite/ietf/
announce.rs1use std::borrow::Cow;
4
5use crate::{coding::*, Path};
6
7use super::util::{decode_namespace, encode_namespace};
8
9#[derive(Clone, Debug)]
12pub struct Announce<'a> {
13 pub track_namespace: Path<'a>,
14}
15
16impl<'a> Message for Announce<'a> {
17 fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
18 let track_namespace = decode_namespace(r)?;
19
20 let num_params = u8::decode(r)?;
21 if num_params > 0 {
22 return Err(DecodeError::InvalidValue);
23 }
24
25 Ok(Self { track_namespace })
26 }
27
28 fn encode<W: bytes::BufMut>(&self, w: &mut W) {
29 encode_namespace(w, &self.track_namespace);
30 0u8.encode(w); }
32}
33
34#[derive(Clone, Debug)]
36pub struct AnnounceOk<'a> {
37 pub track_namespace: Path<'a>,
38}
39
40impl<'a> Message for AnnounceOk<'a> {
41 fn encode<W: bytes::BufMut>(&self, w: &mut W) {
42 encode_namespace(w, &self.track_namespace);
43 }
44
45 fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
46 let track_namespace = decode_namespace(r)?;
47 Ok(Self { track_namespace })
48 }
49}
50
51#[derive(Clone, Debug)]
53pub struct AnnounceError<'a> {
54 pub track_namespace: Path<'a>,
55 pub error_code: u64,
56 pub reason_phrase: Cow<'a, str>,
57}
58
59impl<'a> Message for AnnounceError<'a> {
60 fn encode<W: bytes::BufMut>(&self, w: &mut W) {
61 encode_namespace(w, &self.track_namespace);
62 self.error_code.encode(w);
63 self.reason_phrase.encode(w);
64 }
65
66 fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
67 let track_namespace = decode_namespace(r)?;
68 let error_code = u64::decode(r)?;
69 let reason_phrase = Cow::<str>::decode(r)?;
70
71 Ok(Self {
72 track_namespace,
73 error_code,
74 reason_phrase,
75 })
76 }
77}
78
79#[derive(Clone, Debug)]
81pub struct Unannounce<'a> {
82 pub track_namespace: Path<'a>,
83}
84
85impl<'a> Message for Unannounce<'a> {
86 fn encode<W: bytes::BufMut>(&self, w: &mut W) {
87 encode_namespace(w, &self.track_namespace);
88 }
89
90 fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
91 let track_namespace = decode_namespace(r)?;
92 Ok(Self { track_namespace })
93 }
94}
95
96#[derive(Clone, Debug)]
98pub struct AnnounceCancel<'a> {
99 pub track_namespace: Path<'a>,
100 pub error_code: u64,
101 pub reason_phrase: Cow<'a, str>,
102}
103
104impl<'a> Message for AnnounceCancel<'a> {
105 fn encode<W: bytes::BufMut>(&self, w: &mut W) {
106 encode_namespace(w, &self.track_namespace);
107 self.error_code.encode(w);
108 self.reason_phrase.encode(w);
109 }
110
111 fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
112 let track_namespace = decode_namespace(r)?;
113 let error_code = u64::decode(r)?;
114 let reason_phrase = Cow::<str>::decode(r)?;
115
116 Ok(Self {
117 track_namespace,
118 error_code,
119 reason_phrase,
120 })
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127 use bytes::BytesMut;
128
129 fn encode_message<M: Message>(msg: &M) -> Vec<u8> {
130 let mut buf = BytesMut::new();
131 msg.encode(&mut buf);
132 buf.to_vec()
133 }
134
135 fn decode_message<M: Message>(bytes: &[u8]) -> Result<M, DecodeError> {
136 let mut buf = bytes::Bytes::from(bytes.to_vec());
137 M::decode(&mut buf)
138 }
139
140 #[test]
141 fn test_announce_round_trip() {
142 let msg = Announce {
143 track_namespace: Path::new("test/broadcast"),
144 };
145
146 let encoded = encode_message(&msg);
147 let decoded: Announce = decode_message(&encoded).unwrap();
148
149 assert_eq!(decoded.track_namespace.as_str(), "test/broadcast");
150 }
151
152 #[test]
153 fn test_announce_ok() {
154 let msg = AnnounceOk {
155 track_namespace: Path::new("foo"),
156 };
157
158 let encoded = encode_message(&msg);
159 let decoded: AnnounceOk = decode_message(&encoded).unwrap();
160
161 assert_eq!(decoded.track_namespace.as_str(), "foo");
162 }
163
164 #[test]
165 fn test_announce_error() {
166 let msg = AnnounceError {
167 track_namespace: Path::new("test"),
168 error_code: 404,
169 reason_phrase: "Unauthorized".into(),
170 };
171
172 let encoded = encode_message(&msg);
173 let decoded: AnnounceError = decode_message(&encoded).unwrap();
174
175 assert_eq!(decoded.track_namespace.as_str(), "test");
176 assert_eq!(decoded.error_code, 404);
177 assert_eq!(decoded.reason_phrase, "Unauthorized");
178 }
179
180 #[test]
181 fn test_unannounce() {
182 let msg = Unannounce {
183 track_namespace: Path::new("old/stream"),
184 };
185
186 let encoded = encode_message(&msg);
187 let decoded: Unannounce = decode_message(&encoded).unwrap();
188
189 assert_eq!(decoded.track_namespace.as_str(), "old/stream");
190 }
191
192 #[test]
193 fn test_announce_cancel() {
194 let msg = AnnounceCancel {
195 track_namespace: Path::new("canceled"),
196 error_code: 1,
197 reason_phrase: "Shutdown".into(),
198 };
199
200 let encoded = encode_message(&msg);
201 let decoded: AnnounceCancel = decode_message(&encoded).unwrap();
202
203 assert_eq!(decoded.track_namespace.as_str(), "canceled");
204 assert_eq!(decoded.error_code, 1);
205 assert_eq!(decoded.reason_phrase, "Shutdown");
206 }
207
208 #[test]
209 fn test_announce_rejects_parameters() {
210 #[rustfmt::skip]
211 let invalid_bytes = vec![
212 0x01, 0x04, 0x74, 0x65, 0x73, 0x74, 0x01, ];
216
217 let result: Result<Announce, _> = decode_message(&invalid_bytes);
218 assert!(result.is_err());
219 }
220}