1use crate::coding::{
2 Decode, DecodeError, Encode, EncodeError, KeyValuePairs, Location, TrackNamespace,
3};
4use crate::message::FilterType;
5use crate::message::GroupOrder;
6
7#[derive(Clone, Debug, Eq, PartialEq)]
10pub struct TrackStatus {
11 pub id: u64,
13
14 pub track_namespace: TrackNamespace,
16 pub track_name: String, pub subscriber_priority: u8,
20 pub group_order: GroupOrder,
21
22 pub forward: bool,
24
25 pub filter_type: FilterType,
27
28 pub start_location: Option<Location>,
30 pub end_group_id: Option<u64>,
32
33 pub params: KeyValuePairs,
35}
36
37impl Decode for TrackStatus {
38 fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
39 let id = u64::decode(r)?;
40
41 let track_namespace = TrackNamespace::decode(r)?;
42 let track_name = String::decode(r)?;
43
44 let subscriber_priority = u8::decode(r)?;
45 let group_order = GroupOrder::decode(r)?;
46
47 let forward = bool::decode(r)?;
48
49 let filter_type = FilterType::decode(r)?;
50 let start_location: Option<Location>;
51 let end_group_id: Option<u64>;
52 match filter_type {
53 FilterType::AbsoluteStart => {
54 start_location = Some(Location::decode(r)?);
55 end_group_id = None;
56 }
57 FilterType::AbsoluteRange => {
58 start_location = Some(Location::decode(r)?);
59 end_group_id = Some(u64::decode(r)?);
60 }
61 _ => {
62 start_location = None;
63 end_group_id = None;
64 }
65 }
66
67 let params = KeyValuePairs::decode(r)?;
68
69 Ok(Self {
70 id,
71 track_namespace,
72 track_name,
73 subscriber_priority,
74 group_order,
75 forward,
76 filter_type,
77 start_location,
78 end_group_id,
79 params,
80 })
81 }
82}
83
84impl Encode for TrackStatus {
85 fn encode<W: bytes::BufMut>(&self, w: &mut W) -> Result<(), EncodeError> {
86 self.id.encode(w)?;
87
88 self.track_namespace.encode(w)?;
89 self.track_name.encode(w)?;
90
91 self.subscriber_priority.encode(w)?;
92 self.group_order.encode(w)?;
93
94 self.forward.encode(w)?;
95
96 self.filter_type.encode(w)?;
97 match self.filter_type {
98 FilterType::AbsoluteStart => {
99 if let Some(start) = &self.start_location {
100 start.encode(w)?;
101 } else {
102 return Err(EncodeError::MissingField("LargestLocation".to_string()));
103 }
104 }
106 FilterType::AbsoluteRange => {
107 if let Some(start) = &self.start_location {
108 start.encode(w)?;
109 } else {
110 return Err(EncodeError::MissingField("LargestLocation".to_string()));
111 }
112 if let Some(end) = self.end_group_id {
113 end.encode(w)?;
114 } else {
115 return Err(EncodeError::MissingField("EndGroupId".to_string()));
116 }
117 }
118 _ => {}
119 }
120
121 self.params.encode(w)?;
122
123 Ok(())
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use bytes::BytesMut;
131
132 #[test]
133 fn encode_decode() {
134 let mut buf = BytesMut::new();
135
136 let mut kvps = KeyValuePairs::new();
138 kvps.set_bytesvalue(123, vec![0x00, 0x01, 0x02, 0x03]);
139
140 let msg = TrackStatus {
142 id: 12345,
143 track_namespace: TrackNamespace::from_utf8_path("test/path/to/resource"),
144 track_name: "audiotrack".to_string(),
145 subscriber_priority: 127,
146 group_order: GroupOrder::Publisher,
147 forward: true,
148 filter_type: FilterType::NextGroupStart,
149 start_location: None,
150 end_group_id: None,
151 params: kvps.clone(),
152 };
153 msg.encode(&mut buf).unwrap();
154 let decoded = TrackStatus::decode(&mut buf).unwrap();
155 assert_eq!(decoded, msg);
156
157 let msg = TrackStatus {
159 id: 12345,
160 track_namespace: TrackNamespace::from_utf8_path("test/path/to/resource"),
161 track_name: "audiotrack".to_string(),
162 subscriber_priority: 127,
163 group_order: GroupOrder::Publisher,
164 forward: true,
165 filter_type: FilterType::AbsoluteStart,
166 start_location: Some(Location::new(12345, 67890)),
167 end_group_id: None,
168 params: kvps.clone(),
169 };
170 msg.encode(&mut buf).unwrap();
171 let decoded = TrackStatus::decode(&mut buf).unwrap();
172 assert_eq!(decoded, msg);
173
174 let msg = TrackStatus {
176 id: 12345,
177 track_namespace: TrackNamespace::from_utf8_path("test/path/to/resource"),
178 track_name: "audiotrack".to_string(),
179 subscriber_priority: 127,
180 group_order: GroupOrder::Publisher,
181 forward: true,
182 filter_type: FilterType::AbsoluteRange,
183 start_location: Some(Location::new(12345, 67890)),
184 end_group_id: Some(23456),
185 params: kvps.clone(),
186 };
187 msg.encode(&mut buf).unwrap();
188 let decoded = TrackStatus::decode(&mut buf).unwrap();
189 assert_eq!(decoded, msg);
190 }
191
192 #[test]
193 fn encode_missing_fields() {
194 let mut buf = BytesMut::new();
195
196 let msg = TrackStatus {
198 id: 12345,
199 track_namespace: TrackNamespace::from_utf8_path("test/path/to/resource"),
200 track_name: "audiotrack".to_string(),
201 subscriber_priority: 127,
202 group_order: GroupOrder::Publisher,
203 forward: true,
204 filter_type: FilterType::AbsoluteStart,
205 start_location: None,
206 end_group_id: None,
207 params: Default::default(),
208 };
209 let encoded = msg.encode(&mut buf);
210 assert!(matches!(encoded.unwrap_err(), EncodeError::MissingField(_)));
211
212 let msg = TrackStatus {
214 id: 12345,
215 track_namespace: TrackNamespace::from_utf8_path("test/path/to/resource"),
216 track_name: "audiotrack".to_string(),
217 subscriber_priority: 127,
218 group_order: GroupOrder::Publisher,
219 forward: true,
220 filter_type: FilterType::AbsoluteRange,
221 start_location: None,
222 end_group_id: None,
223 params: Default::default(),
224 };
225 let encoded = msg.encode(&mut buf);
226 assert!(matches!(encoded.unwrap_err(), EncodeError::MissingField(_)));
227
228 let msg = TrackStatus {
230 id: 12345,
231 track_namespace: TrackNamespace::from_utf8_path("test/path/to/resource"),
232 track_name: "audiotrack".to_string(),
233 subscriber_priority: 127,
234 group_order: GroupOrder::Publisher,
235 forward: true,
236 filter_type: FilterType::AbsoluteRange,
237 start_location: Some(Location::new(12345, 67890)),
238 end_group_id: None,
239 params: Default::default(),
240 };
241 let encoded = msg.encode(&mut buf);
242 assert!(matches!(encoded.unwrap_err(), EncodeError::MissingField(_)));
243 }
244}