use crate::Result;
use crate::time::Timestamp;
use crate::ts::TsPacket;
use crate::util::{ReadBytesExt, WriteBytesExt};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::io::{Read, Write};
use std::ops::Deref;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Pid(u16);
impl Pid {
pub const MAX: u16 = (1 << 13) - 1;
pub const PAT: u16 = 0;
pub const NULL: u16 = 0x1FFF;
pub fn new(pid: u16) -> Result<Self> {
if pid > Self::MAX {
return Err(crate::Error::invalid_input(format!(
"Too large PID: {}",
pid
)));
}
Ok(Pid(pid))
}
pub fn as_u16(&self) -> u16 {
self.0
}
pub(super) fn read_from<R: Read>(mut reader: R) -> Result<Self> {
let n = reader.read_u16()?;
if (n & 0b1110_0000_0000_0000) != 0b1110_0000_0000_0000 {
return Err(crate::Error::invalid_input("Unexpected reserved bits"));
}
Ok(Pid(n & 0b0001_1111_1111_1111))
}
pub(super) fn write_to<W: Write>(&self, mut writer: W) -> Result<()> {
let n = 0b1110_0000_0000_0000 | self.0;
writer.write_u16(n)?;
Ok(())
}
}
impl From<u8> for Pid {
fn from(f: u8) -> Self {
Pid(u16::from(f))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ContinuityCounter(u8);
impl ContinuityCounter {
pub const MAX: u8 = (1 << 4) - 1;
pub fn new() -> Self {
ContinuityCounter(0)
}
pub fn from_u8(n: u8) -> Result<Self> {
if n > Self::MAX {
return Err(crate::Error::invalid_input(format!(
"Too large counter: {}",
n
)));
}
Ok(ContinuityCounter(n))
}
pub fn as_u8(&self) -> u8 {
self.0
}
pub fn increment(&mut self) {
self.0 = (self.0 + 1) & Self::MAX;
}
}
impl Default for ContinuityCounter {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct VersionNumber(u8);
impl VersionNumber {
pub const MAX: u8 = (1 << 5) - 1;
pub fn new() -> Self {
VersionNumber(0)
}
pub fn from_u8(n: u8) -> Result<Self> {
if n > Self::MAX {
return Err(crate::Error::invalid_input(format!(
"Too large version number: {}",
n
)));
}
Ok(VersionNumber(n))
}
pub fn as_u8(&self) -> u8 {
self.0
}
pub fn increment(&mut self) {
self.0 = (self.0 + 1) & Self::MAX;
}
}
impl Default for VersionNumber {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone)]
pub struct Bytes {
buf: [u8; Bytes::MAX_SIZE],
len: usize,
}
impl Bytes {
pub const MAX_SIZE: usize = TsPacket::SIZE - 4 ;
pub fn new(bytes: &[u8]) -> Result<Self> {
if bytes.len() > Self::MAX_SIZE {
return Err(crate::Error::invalid_input(format!(
"Too large: actual={} bytes, max={} bytes",
bytes.len(),
Self::MAX_SIZE
)));
}
let len = bytes.len();
let mut buf = [0; Self::MAX_SIZE];
buf[..len].copy_from_slice(bytes);
Ok(Bytes { buf, len })
}
pub(super) fn read_from<R: Read>(mut reader: R) -> Result<Self> {
let mut offset = 0;
let mut buf = [0; Self::MAX_SIZE];
loop {
let read_size = reader.read(&mut buf[offset..])?;
if read_size == 0 {
break;
}
offset += read_size;
}
Ok(Bytes { buf, len: offset })
}
pub(super) fn write_to<W: Write>(&self, mut writer: W) -> Result<()> {
writer.write_all(self.as_ref())?;
Ok(())
}
}
impl Deref for Bytes {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.buf[..self.len]
}
}
impl AsRef<[u8]> for Bytes {
fn as_ref(&self) -> &[u8] {
self.deref()
}
}
impl fmt::Debug for Bytes {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Bytes({:?})", self.deref())
}
}
impl PartialEq for Bytes {
fn eq(&self, other: &Self) -> bool {
self.as_ref() == other.as_ref()
}
}
impl Eq for Bytes {}
impl Hash for Bytes {
fn hash<H: Hasher>(&self, hasher: &mut H) {
self.as_ref().hash(hasher);
}
}
#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TransportScramblingControl {
NotScrambled = 0b00,
ScrambledWithEvenKey = 0b10,
ScrambledWithOddKey = 0b11,
}
impl TransportScramblingControl {
pub(super) fn from_u8(n: u8) -> Result<Self> {
Ok(match n {
0b00 => TransportScramblingControl::NotScrambled,
0b10 => TransportScramblingControl::ScrambledWithEvenKey,
0b11 => TransportScramblingControl::ScrambledWithOddKey,
0b01 => return Err(crate::Error::invalid_input("Reserved for future use")),
_ => {
return Err(crate::Error::invalid_input(format!(
"Unexpected value: {}",
n
)));
}
})
}
}
#[allow(missing_docs)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct LegalTimeWindow {
is_valid: bool,
offset: u16,
}
impl LegalTimeWindow {
pub const MAX_OFFSET: u16 = (1 << 15) - 1;
pub fn new(is_valid: bool, offset: u16) -> Result<Self> {
if offset > Self::MAX_OFFSET {
return Err(crate::Error::invalid_input(format!(
"Too large offset: {}",
offset
)));
}
Ok(LegalTimeWindow { is_valid, offset })
}
pub fn is_valid(&self) -> bool {
self.is_valid
}
pub fn offset(&self) -> u16 {
self.offset
}
pub(super) fn read_from<R: Read>(mut reader: R) -> Result<Self> {
let n = reader.read_u16()?;
Ok(LegalTimeWindow {
is_valid: (n & 0b1000_0000_0000_0000) != 0,
offset: n & 0b0111_1111_1111_1111,
})
}
pub(super) fn write_to<W: Write>(&self, mut writer: W) -> Result<()> {
let n = ((self.is_valid as u16) << 15) | self.offset;
writer.write_u16(n)?;
Ok(())
}
}
#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct PiecewiseRate(u32);
impl PiecewiseRate {
pub const MAX: u32 = (1 << 22) - 1;
pub fn new(rate: u32) -> Result<Self> {
if rate > Self::MAX {
return Err(crate::Error::invalid_input(format!(
"Too large rate: {}",
rate
)));
}
Ok(PiecewiseRate(rate))
}
pub fn as_u32(&self) -> u32 {
self.0
}
pub(super) fn read_from<R: Read>(mut reader: R) -> Result<Self> {
let n = reader.read_uint::<3>()? as u32;
Ok(PiecewiseRate(n & 0x3FFF_FFFF))
}
pub(super) fn write_to<W: Write>(&self, mut writer: W) -> Result<()> {
writer.write_uint::<3>(u64::from(self.0))?;
Ok(())
}
}
#[allow(missing_docs)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SeamlessSplice {
splice_type: u8,
dts_next_access_unit: Timestamp,
}
impl SeamlessSplice {
pub const MAX_SPLICE_TYPE: u8 = (1 << 4) - 1;
pub fn new(splice_type: u8, dts_next_access_unit: Timestamp) -> Result<Self> {
if splice_type > Self::MAX_SPLICE_TYPE {
return Err(crate::Error::invalid_input(format!(
"Too large splice type: {}",
splice_type
)));
}
Ok(SeamlessSplice {
splice_type,
dts_next_access_unit,
})
}
pub fn splice_type(&self) -> u8 {
self.splice_type
}
pub fn dts_next_access_unit(&self) -> Timestamp {
self.dts_next_access_unit
}
pub(super) fn read_from<R: Read>(mut reader: R) -> Result<Self> {
let n = reader.read_uint::<5>()?;
Ok(SeamlessSplice {
splice_type: (n >> 36) as u8,
dts_next_access_unit: Timestamp::from_u64(n & 0x0F_FFFF_FFFF)?,
})
}
pub(super) fn write_to<W: Write>(&self, mut writer: W) -> Result<()> {
self.dts_next_access_unit
.write_to(&mut writer, self.splice_type)?;
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn bytes_read_from() {
let bytes = Bytes::read_from(&[1, 2, 3][..]).unwrap();
assert_eq!(bytes.as_ref(), [1, 2, 3]);
let bytes = Bytes::read_from(&[0; 200][..]).unwrap();
assert_eq!(bytes.as_ref(), &[0; Bytes::MAX_SIZE][..]);
}
}