use crate::error::{Error, Result};
use crate::h222_bits::impl_h222_descriptor;
use alloc::vec::Vec;
pub const TAG: u8 = 0x37;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum TransportProfile {
Unspecified,
Complete,
Adaptive,
Reserved(u8),
UserPrivate(u8),
}
impl TransportProfile {
#[must_use]
pub const fn from_u8(v: u8) -> Self {
match v {
0x00 => Self::Unspecified,
0x01 => Self::Complete,
0x02 => Self::Adaptive,
0x03..=0x0E => Self::Reserved(v),
other => Self::UserPrivate(other),
}
}
#[must_use]
pub const fn to_u8(self) -> u8 {
match self {
Self::Unspecified => 0x00,
Self::Complete => 0x01,
Self::Adaptive => 0x02,
Self::Reserved(v) | Self::UserPrivate(v) => v,
}
}
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::Unspecified => "unspecified",
Self::Complete => "complete profile",
Self::Adaptive => "adaptive profile",
Self::Reserved(_) => "reserved",
Self::UserPrivate(_) => "user_private",
}
}
}
broadcast_common::impl_spec_display!(TransportProfile, Reserved, UserPrivate);
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
#[non_exhaustive]
pub struct TransportProfileDescriptor {
pub transport_profile: TransportProfile,
pub private_data: Vec<u8>,
}
impl TransportProfileDescriptor {
#[must_use]
pub fn new(transport_profile: TransportProfile) -> Self {
Self {
transport_profile,
private_data: Vec::new(),
}
}
fn parse_body(body: &[u8]) -> Result<Self> {
let (&profile, rest) = body.split_first().ok_or(Error::BufferTooShort {
need: 1,
have: 0,
what: "TransportProfileDescriptor",
})?;
Ok(Self {
transport_profile: TransportProfile::from_u8(profile),
private_data: rest.to_vec(),
})
}
fn write_body(&self) -> Result<Vec<u8>> {
let mut v = Vec::with_capacity(1 + self.private_data.len());
v.push(self.transport_profile.to_u8());
v.extend_from_slice(&self.private_data);
Ok(v)
}
}
impl_h222_descriptor!(
TransportProfileDescriptor,
TAG,
"TransportProfileDescriptor",
"TRANSPORT_PROFILE"
);
#[cfg(test)]
#[allow(clippy::unusual_byte_groupings)] mod tests {
use super::*;
use broadcast_common::{Parse, Serialize};
#[test]
fn profiles_and_private_data() {
for (b, p) in [
(0u8, TransportProfile::Unspecified),
(1, TransportProfile::Complete),
(2, TransportProfile::Adaptive),
(0x0E, TransportProfile::Reserved(0x0E)),
(0x0F, TransportProfile::UserPrivate(0x0F)),
] {
let bytes = [TAG, 3, b, 0xDE, 0xAD];
let d = TransportProfileDescriptor::parse(&bytes).unwrap();
assert_eq!(d.transport_profile, p);
assert_eq!(d.private_data, [0xDE, 0xAD]);
let mut out = vec![0u8; d.serialized_len()];
d.serialize_into(&mut out).unwrap();
assert_eq!(out, bytes);
}
assert!(TransportProfileDescriptor::parse(&[TAG, 0]).is_err());
let mut d = TransportProfileDescriptor::new(TransportProfile::Complete);
d.private_data = vec![0; 255];
assert!(d.serialize_into(&mut [0u8; 300]).is_err());
}
}