#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum TxInputStreamType {
TsOnly,
GenericStream,
Both,
Reserved(u8),
}
impl TxInputStreamType {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v {
0x00 => Self::TsOnly,
0x01 => Self::GenericStream,
0x02 => Self::Both,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::TsOnly => 0x00,
Self::GenericStream => 0x01,
Self::Both => 0x02,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum GuardInterval {
G1_32,
G1_16,
G1_8,
G1_4,
G1_128,
G19_128,
G19_256,
Reserved(u8),
}
impl GuardInterval {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x07 {
0 => Self::G1_32,
1 => Self::G1_16,
2 => Self::G1_8,
3 => Self::G1_4,
4 => Self::G1_128,
5 => Self::G19_128,
6 => Self::G19_256,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::G1_32 => 0,
Self::G1_16 => 1,
Self::G1_8 => 2,
Self::G1_4 => 3,
Self::G1_128 => 4,
Self::G19_128 => 5,
Self::G19_256 => 6,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum L1Modulation {
Bpsk,
Qpsk,
Qam16,
Qam64,
Reserved(u8),
}
impl L1Modulation {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x0F {
0 => Self::Bpsk,
1 => Self::Qpsk,
2 => Self::Qam16,
3 => Self::Qam64,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::Bpsk => 0,
Self::Qpsk => 1,
Self::Qam16 => 2,
Self::Qam64 => 3,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum L1CodeRate {
R1_2,
Reserved(u8),
}
impl L1CodeRate {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x03 {
0 => Self::R1_2,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::R1_2 => 0,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum L1FecType {
Ldpc16K,
Reserved(u8),
}
impl L1FecType {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x03 {
0 => Self::Ldpc16K,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::Ldpc16K => 0,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum PilotPattern {
Pp1,
Pp2,
Pp3,
Pp4,
Pp5,
Pp6,
Pp7,
Pp8,
Reserved(u8),
}
impl PilotPattern {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x0F {
0 => Self::Pp1,
1 => Self::Pp2,
2 => Self::Pp3,
3 => Self::Pp4,
4 => Self::Pp5,
5 => Self::Pp6,
6 => Self::Pp7,
7 => Self::Pp8,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::Pp1 => 0,
Self::Pp2 => 1,
Self::Pp3 => 2,
Self::Pp4 => 3,
Self::Pp5 => 4,
Self::Pp6 => 5,
Self::Pp7 => 6,
Self::Pp8 => 7,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum T2Version {
V1_1_1,
V1_2_1,
V1_3_1,
Reserved(u8),
}
impl T2Version {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x0F {
0 => Self::V1_1_1,
1 => Self::V1_2_1,
2 => Self::V1_3_1,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::V1_1_1 => 0,
Self::V1_2_1 => 1,
Self::V1_3_1 => 2,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum PlpType {
Common,
DataType1,
DataType2,
Reserved(u8),
}
impl PlpType {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x07 {
0 => Self::Common,
1 => Self::DataType1,
2 => Self::DataType2,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::Common => 0,
Self::DataType1 => 1,
Self::DataType2 => 2,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum PlpPayloadType {
Gfps,
Gcs,
Gse,
Ts,
Reserved(u8),
}
impl PlpPayloadType {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x1F {
0 => Self::Gfps,
1 => Self::Gcs,
2 => Self::Gse,
3 => Self::Ts,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::Gfps => 0,
Self::Gcs => 1,
Self::Gse => 2,
Self::Ts => 3,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum PlpModulation {
Qpsk,
Qam16,
Qam64,
Qam256,
Reserved(u8),
}
impl PlpModulation {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x07 {
0 => Self::Qpsk,
1 => Self::Qam16,
2 => Self::Qam64,
3 => Self::Qam256,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::Qpsk => 0,
Self::Qam16 => 1,
Self::Qam64 => 2,
Self::Qam256 => 3,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum PlpFecType {
Ldpc16K,
Ldpc64K,
Reserved(u8),
}
impl PlpFecType {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x03 {
0 => Self::Ldpc16K,
1 => Self::Ldpc64K,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::Ldpc16K => 0,
Self::Ldpc64K => 1,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum PlpMode {
NotSpecified,
Normal,
HighEfficiency,
Reserved(u8),
}
impl PlpMode {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x03 {
0 => Self::NotSpecified,
1 => Self::Normal,
2 => Self::HighEfficiency,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::NotSpecified => 0,
Self::Normal => 1,
Self::HighEfficiency => 2,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum AuxStreamType {
TxSig,
Reserved(u8),
}
impl AuxStreamType {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x0F {
0 => Self::TxSig,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::TxSig => 0,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum PaprReductionV0 {
NoReduction,
AceOnly,
TrOnly,
AceAndTr,
Reserved(u8),
}
impl PaprReductionV0 {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x0F {
0 => Self::NoReduction,
1 => Self::AceOnly,
2 => Self::TrOnly,
3 => Self::AceAndTr,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::NoReduction => 0,
Self::AceOnly => 1,
Self::TrOnly => 2,
Self::AceAndTr => 3,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum PaprReductionVn {
L1AceTrOnP2,
L1AceAndAce,
L1AceAndTr,
L1AceAceAndTr,
Reserved(u8),
}
impl PaprReductionVn {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x0F {
0 => Self::L1AceTrOnP2,
1 => Self::L1AceAndAce,
2 => Self::L1AceAndTr,
3 => Self::L1AceAceAndTr,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::L1AceTrOnP2 => 0,
Self::L1AceAndAce => 1,
Self::L1AceAndTr => 2,
Self::L1AceAceAndTr => 3,
Self::Reserved(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum PaprReduction {
V0(PaprReductionV0),
Vn(PaprReductionVn),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum PlpCodeRate {
R1_2,
R3_5,
R2_3,
R3_4,
R4_5,
R5_6,
Reserved(u8),
}
impl PlpCodeRate {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x07 {
0 => Self::R1_2,
1 => Self::R3_5,
2 => Self::R2_3,
3 => Self::R3_4,
4 => Self::R4_5,
5 => Self::R5_6,
other => Self::Reserved(other),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::R1_2 => 0,
Self::R3_5 => 1,
Self::R2_3 => 2,
Self::R3_4 => 3,
Self::R4_5 => 4,
Self::R5_6 => 5,
Self::Reserved(v) => v,
}
}
}
impl TxInputStreamType {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::TsOnly => "TS",
Self::GenericStream => "Generic Stream",
Self::Both => "TS + Generic",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(TxInputStreamType, Reserved);
impl GuardInterval {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::G1_32 => "1/32",
Self::G1_16 => "1/16",
Self::G1_8 => "1/8",
Self::G1_4 => "1/4",
Self::G1_128 => "1/128",
Self::G19_128 => "19/128",
Self::G19_256 => "19/256",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(GuardInterval, Reserved);
impl L1Modulation {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::Bpsk => "BPSK",
Self::Qpsk => "QPSK",
Self::Qam16 => "16-QAM",
Self::Qam64 => "64-QAM",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(L1Modulation, Reserved);
impl L1CodeRate {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::R1_2 => "1/2",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(L1CodeRate, Reserved);
impl L1FecType {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::Ldpc16K => "16K LDPC",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(L1FecType, Reserved);
impl PilotPattern {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::Pp1 => "PP1",
Self::Pp2 => "PP2",
Self::Pp3 => "PP3",
Self::Pp4 => "PP4",
Self::Pp5 => "PP5",
Self::Pp6 => "PP6",
Self::Pp7 => "PP7",
Self::Pp8 => "PP8",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(PilotPattern, Reserved);
impl T2Version {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::V1_1_1 => "1.1.1",
Self::V1_2_1 => "1.2.1",
Self::V1_3_1 => "1.3.1",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(T2Version, Reserved);
impl PlpType {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::Common => "Common",
Self::DataType1 => "Data Type 1",
Self::DataType2 => "Data Type 2",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(PlpType, Reserved);
impl PlpPayloadType {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::Gfps => "GFPS",
Self::Gcs => "GCS",
Self::Gse => "GSE",
Self::Ts => "TS",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(PlpPayloadType, Reserved);
impl PlpModulation {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::Qpsk => "QPSK",
Self::Qam16 => "16-QAM",
Self::Qam64 => "64-QAM",
Self::Qam256 => "256-QAM",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(PlpModulation, Reserved);
impl PlpFecType {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::Ldpc16K => "16K LDPC",
Self::Ldpc64K => "64K LDPC",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(PlpFecType, Reserved);
impl PlpMode {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::NotSpecified => "Not specified",
Self::Normal => "Normal",
Self::HighEfficiency => "High Efficiency",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(PlpMode, Reserved);
impl AuxStreamType {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::TxSig => "TX-SIG",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(AuxStreamType, Reserved);
impl PaprReductionV0 {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::NoReduction => "No PAPR reduction",
Self::AceOnly => "ACE-PAPR only",
Self::TrOnly => "TR-PAPR only",
Self::AceAndTr => "ACE and TR",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(PaprReductionV0, Reserved);
impl PaprReductionVn {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::L1AceTrOnP2 => "L1-ACE, TR on P2 only",
Self::L1AceAndAce => "L1-ACE and ACE",
Self::L1AceAndTr => "L1-ACE and TR",
Self::L1AceAceAndTr => "L1-ACE, ACE and TR",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(PaprReductionVn, Reserved);
impl PaprReduction {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::V0(inner) => inner.name(),
Self::Vn(inner) => inner.name(),
}
}
}
dvb_common::impl_spec_display!(PaprReduction);
impl PlpCodeRate {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::R1_2 => "1/2",
Self::R3_5 => "3/5",
Self::R2_3 => "2/3",
Self::R3_4 => "3/4",
Self::R4_5 => "4/5",
Self::R5_6 => "5/6",
Self::Reserved(_) => "reserved",
}
}
}
dvb_common::impl_spec_display!(PlpCodeRate, Reserved);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn spec_label_known_and_reserved() {
assert_eq!(GuardInterval::G19_256.name(), "19/256");
assert_eq!(GuardInterval::G19_256.to_string(), "19/256");
assert_eq!(PlpModulation::Qam256.to_string(), "256-QAM");
assert_eq!(GuardInterval::Reserved(0x07).name(), "reserved");
assert_eq!(GuardInterval::Reserved(0x07).to_string(), "reserved(0x07)");
assert_eq!(
PaprReduction::V0(PaprReductionV0::AceOnly).to_string(),
"ACE-PAPR only"
);
}
#[test]
fn tx_input_stream_type_round_trip() {
for v in 0u8..=2 {
let e = TxInputStreamType::from_u8(v);
assert_eq!(e.to_u8(), v);
assert!(!matches!(e, TxInputStreamType::Reserved(_)));
}
assert!(matches!(
TxInputStreamType::from_u8(3),
TxInputStreamType::Reserved(3)
));
assert!(matches!(
TxInputStreamType::from_u8(0xFF),
TxInputStreamType::Reserved(0xFF)
));
}
#[test]
fn guard_interval_round_trip() {
for v in 0u8..=6 {
let e = GuardInterval::from_u8(v);
assert_eq!(e.to_u8(), v);
assert!(!matches!(e, GuardInterval::Reserved(_)));
}
assert!(matches!(
GuardInterval::from_u8(7),
GuardInterval::Reserved(7)
));
}
#[test]
fn l1_modulation_round_trip() {
for v in 0u8..=3 {
let e = L1Modulation::from_u8(v);
assert_eq!(e.to_u8(), v);
assert!(!matches!(e, L1Modulation::Reserved(_)));
}
assert!(matches!(
L1Modulation::from_u8(0x0F),
L1Modulation::Reserved(_)
));
}
#[test]
fn l1_code_rate_round_trip() {
assert_eq!(L1CodeRate::from_u8(0).to_u8(), 0);
assert!(!matches!(L1CodeRate::from_u8(0), L1CodeRate::Reserved(_)));
assert!(matches!(L1CodeRate::from_u8(1), L1CodeRate::Reserved(1)));
assert!(matches!(L1CodeRate::from_u8(3), L1CodeRate::Reserved(3)));
}
#[test]
fn l1_fec_type_round_trip() {
assert_eq!(L1FecType::from_u8(0).to_u8(), 0);
assert!(matches!(L1FecType::from_u8(1), L1FecType::Reserved(1)));
}
#[test]
fn pilot_pattern_round_trip() {
for v in 0u8..=7 {
let e = PilotPattern::from_u8(v);
assert_eq!(e.to_u8(), v);
assert!(!matches!(e, PilotPattern::Reserved(_)));
}
assert!(matches!(
PilotPattern::from_u8(8),
PilotPattern::Reserved(8)
));
}
#[test]
fn t2_version_round_trip() {
for v in 0u8..=2 {
let e = T2Version::from_u8(v);
assert_eq!(e.to_u8(), v);
assert!(!matches!(e, T2Version::Reserved(_)));
}
assert!(matches!(T2Version::from_u8(3), T2Version::Reserved(3)));
}
#[test]
fn plp_type_round_trip() {
for v in 0u8..=2 {
let e = PlpType::from_u8(v);
assert_eq!(e.to_u8(), v);
assert!(!matches!(e, PlpType::Reserved(_)));
}
assert!(matches!(PlpType::from_u8(7), PlpType::Reserved(7)));
}
#[test]
fn plp_payload_type_round_trip() {
for v in 0u8..=3 {
let e = PlpPayloadType::from_u8(v);
assert_eq!(e.to_u8(), v);
assert!(!matches!(e, PlpPayloadType::Reserved(_)));
}
assert!(matches!(
PlpPayloadType::from_u8(0x1F),
PlpPayloadType::Reserved(_)
));
}
#[test]
fn plp_modulation_round_trip() {
for v in 0u8..=3 {
let e = PlpModulation::from_u8(v);
assert_eq!(e.to_u8(), v);
assert!(!matches!(e, PlpModulation::Reserved(_)));
}
assert!(matches!(
PlpModulation::from_u8(7),
PlpModulation::Reserved(7)
));
}
#[test]
fn plp_fec_type_round_trip() {
for v in 0u8..=1 {
let e = PlpFecType::from_u8(v);
assert_eq!(e.to_u8(), v);
assert!(!matches!(e, PlpFecType::Reserved(_)));
}
assert!(matches!(PlpFecType::from_u8(2), PlpFecType::Reserved(2)));
}
#[test]
fn plp_mode_round_trip() {
for v in 0u8..=2 {
let e = PlpMode::from_u8(v);
assert_eq!(e.to_u8(), v);
assert!(!matches!(e, PlpMode::Reserved(_)));
}
assert!(matches!(PlpMode::from_u8(3), PlpMode::Reserved(3)));
}
#[test]
fn aux_stream_type_round_trip() {
assert_eq!(AuxStreamType::from_u8(0).to_u8(), 0);
assert!(matches!(
AuxStreamType::from_u8(0x0F),
AuxStreamType::Reserved(_)
));
}
#[test]
fn plp_code_rate_round_trip() {
for v in 0u8..=5 {
let e = PlpCodeRate::from_u8(v);
assert_eq!(e.to_u8(), v);
assert!(!matches!(e, PlpCodeRate::Reserved(_)));
}
assert!(matches!(PlpCodeRate::from_u8(6), PlpCodeRate::Reserved(6)));
assert!(matches!(PlpCodeRate::from_u8(7), PlpCodeRate::Reserved(7)));
}
}