use std::borrow::Cow;
use num_enum::{IntoPrimitive, TryFromPrimitive};
use crate::{
Path,
coding::*,
ietf::{FilterType, GroupOrder, Parameters, RequestId},
};
use super::Message;
use super::namespace::{decode_namespace, encode_namespace};
use super::Version;
#[derive(Clone, Debug)]
pub struct TrackStatus<'a> {
pub request_id: RequestId,
pub track_namespace: Path<'a>,
pub track_name: Cow<'a, str>,
}
impl Message for TrackStatus<'_> {
const ID: u64 = 0x0d;
fn encode_msg<W: bytes::BufMut>(&self, w: &mut W, version: Version) -> Result<(), EncodeError> {
self.request_id.encode(w, version)?;
if version == Version::Draft17 {
0u64.encode(w, version)?; }
encode_namespace(w, &self.track_namespace, version)?;
self.track_name.encode(w, version)?;
match version {
Version::Draft14 => {
0u8.encode(w, version)?; GroupOrder::Descending.encode(w, version)?;
false.encode(w, version)?; FilterType::LargestObject.encode(w, version)?; 0u8.encode(w, version)?; }
Version::Draft15 | Version::Draft16 | Version::Draft17 => {
encode_params!(w, version,);
}
}
Ok(())
}
fn decode_msg<R: bytes::Buf>(r: &mut R, version: Version) -> Result<Self, DecodeError> {
let request_id = RequestId::decode(r, version)?;
if version == Version::Draft17 {
let _required_request_id_delta = u64::decode(r, version)?;
}
let track_namespace = decode_namespace(r, version)?;
let track_name = Cow::<str>::decode(r, version)?;
match version {
Version::Draft14 => {
let _subscriber_priority = u8::decode(r, version)?;
let _group_order = GroupOrder::decode(r, version)?;
let _forward = bool::decode(r, version)?;
let _filter_type = u64::decode(r, version)?;
let _params = Parameters::decode(r, version)?;
}
Version::Draft15 | Version::Draft16 | Version::Draft17 => {
decode_params!(r, version,);
}
}
Ok(Self {
request_id,
track_namespace,
track_name,
})
}
}
#[derive(Clone, Copy, Debug, TryFromPrimitive, IntoPrimitive)]
#[repr(u64)]
pub enum TrackStatusCode {
InProgress = 0x00,
NotFound = 0x01,
NotAuthorized = 0x02,
Ended = 0x03,
}
impl Encode<Version> for TrackStatusCode {
fn encode<W: bytes::BufMut>(&self, w: &mut W, version: Version) -> Result<(), EncodeError> {
u64::from(*self).encode(w, version)?;
Ok(())
}
}
impl Decode<Version> for TrackStatusCode {
fn decode<R: bytes::Buf>(r: &mut R, version: Version) -> Result<Self, DecodeError> {
Self::try_from(u64::decode(r, version)?).map_err(|_| DecodeError::InvalidValue)
}
}
#[cfg(test)]
mod tests {
use super::*;
use bytes::BytesMut;
fn encode_message<M: Message>(msg: &M, version: Version) -> Vec<u8> {
let mut buf = BytesMut::new();
msg.encode_msg(&mut buf, version).unwrap();
buf.to_vec()
}
fn decode_message<M: Message>(bytes: &[u8], version: Version) -> Result<M, DecodeError> {
let mut buf = bytes::Bytes::from(bytes.to_vec());
M::decode_msg(&mut buf, version)
}
#[test]
fn test_track_status_v14_round_trip() {
let msg = TrackStatus {
request_id: RequestId(1),
track_namespace: Path::new("test/ns"),
track_name: "video".into(),
};
let encoded = encode_message(&msg, Version::Draft14);
let decoded: TrackStatus = decode_message(&encoded, Version::Draft14).unwrap();
assert_eq!(decoded.request_id, RequestId(1));
assert_eq!(decoded.track_namespace.as_str(), "test/ns");
assert_eq!(decoded.track_name, "video");
}
#[test]
fn test_track_status_v15_round_trip() {
let msg = TrackStatus {
request_id: RequestId(1),
track_namespace: Path::new("test/ns"),
track_name: "video".into(),
};
let encoded = encode_message(&msg, Version::Draft15);
let decoded: TrackStatus = decode_message(&encoded, Version::Draft15).unwrap();
assert_eq!(decoded.request_id, RequestId(1));
assert_eq!(decoded.track_namespace.as_str(), "test/ns");
assert_eq!(decoded.track_name, "video");
}
#[test]
fn test_track_status_v17_round_trip() {
let msg = TrackStatus {
request_id: RequestId(1),
track_namespace: Path::new("test/ns"),
track_name: "video".into(),
};
let encoded = encode_message(&msg, Version::Draft17);
let decoded: TrackStatus = decode_message(&encoded, Version::Draft17).unwrap();
assert_eq!(decoded.request_id, RequestId(1));
assert_eq!(decoded.track_namespace.as_str(), "test/ns");
assert_eq!(decoded.track_name, "video");
}
#[test]
fn test_track_status_v16_round_trip() {
let msg = TrackStatus {
request_id: RequestId(1),
track_namespace: Path::new("test/ns"),
track_name: "video".into(),
};
let encoded = encode_message(&msg, Version::Draft16);
let decoded: TrackStatus = decode_message(&encoded, Version::Draft16).unwrap();
assert_eq!(decoded.request_id, RequestId(1));
assert_eq!(decoded.track_namespace.as_str(), "test/ns");
assert_eq!(decoded.track_name, "video");
}
}