#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum RunningStatus {
Undefined,
NotRunning,
StartsInAFewSeconds,
Pausing,
Running,
ServiceOffAir,
Reserved(u8),
}
impl RunningStatus {
#[must_use]
pub fn from_u8(v: u8) -> Self {
match v & 0x07 {
0 => Self::Undefined,
1 => Self::NotRunning,
2 => Self::StartsInAFewSeconds,
3 => Self::Pausing,
4 => Self::Running,
5 => Self::ServiceOffAir,
r => Self::Reserved(r),
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
match self {
Self::Undefined => 0,
Self::NotRunning => 1,
Self::StartsInAFewSeconds => 2,
Self::Pausing => 3,
Self::Running => 4,
Self::ServiceOffAir => 5,
Self::Reserved(v) => v & 0x07,
}
}
#[must_use]
pub fn name(self) -> &'static str {
match self {
Self::Undefined => "undefined",
Self::NotRunning => "not running",
Self::StartsInAFewSeconds => "starts in a few seconds",
Self::Pausing => "pausing",
Self::Running => "running",
Self::ServiceOffAir => "service off-air",
Self::Reserved(_) => "reserved",
}
}
}
#[cfg(test)]
mod running_status_tests {
use super::*;
#[test]
fn from_u8_maps_known_values() {
assert_eq!(RunningStatus::from_u8(0), RunningStatus::Undefined);
assert_eq!(RunningStatus::from_u8(1), RunningStatus::NotRunning);
assert_eq!(
RunningStatus::from_u8(2),
RunningStatus::StartsInAFewSeconds
);
assert_eq!(RunningStatus::from_u8(3), RunningStatus::Pausing);
assert_eq!(RunningStatus::from_u8(4), RunningStatus::Running);
assert_eq!(RunningStatus::from_u8(5), RunningStatus::ServiceOffAir);
assert_eq!(RunningStatus::from_u8(6), RunningStatus::Reserved(6));
assert_eq!(RunningStatus::from_u8(7), RunningStatus::Reserved(7));
}
#[test]
fn to_u8_from_u8_round_trips_all_byte_values() {
for v in 0u8..=0xFFu8 {
assert_eq!(RunningStatus::to_u8(RunningStatus::from_u8(v)), v & 0x07);
}
}
#[test]
fn name_returns_known_strings() {
assert_eq!(RunningStatus::Undefined.name(), "undefined");
assert_eq!(RunningStatus::NotRunning.name(), "not running");
assert_eq!(RunningStatus::Running.name(), "running");
assert_eq!(RunningStatus::ServiceOffAir.name(), "service off-air");
assert_eq!(RunningStatus::Reserved(6).name(), "reserved");
}
}
pub(crate) const SECTION_B1_FLAGS_PSI: u8 = 0xB0;
pub(crate) const SECTION_B1_FLAGS_DVB: u8 = 0xF0;
pub(crate) const SECTION_B1_SSI: u8 = 0x80;
pub(crate) const SECTION_B1_RESERVED_HI: u8 = 0x30;
pub(crate) const SECTION_B1_FLAGS_SHORT: u8 = 0x70;
pub(crate) fn check_section_length(
bytes_len: usize,
header_len: usize,
section_length: usize,
min_total: usize,
) -> crate::Result<usize> {
let total = header_len + section_length;
if bytes_len < total || total < min_total {
return Err(crate::error::Error::SectionLengthOverflow {
declared: section_length,
available: bytes_len.saturating_sub(header_len),
});
}
Ok(total)
}
pub mod any;
pub use any::AnyTableSection;
pub mod registry;
pub use registry::{TableObject, TableRegistry};
pub mod ait;
pub mod bat;
pub mod cat;
pub mod cit;
pub mod container;
pub mod dit;
pub mod downloadable_font_info;
pub mod dsmcc;
pub mod eit;
pub mod int;
pub mod mpe;
pub mod mpe_fec;
pub mod mpe_ifec;
pub mod nit;
pub mod pat;
pub mod pmt;
pub mod protection_message;
pub mod rct;
pub mod rnt;
pub mod rst;
pub mod sat;
pub mod sdt;
pub mod sit;
pub mod st;
pub mod tdt;
pub mod tot;
pub mod tsdt;
pub mod unt;