mirror of
https://github.com/sile/hls_m3u8.git
synced 2025-04-08 04:54:05 +00:00
Add tag/basic
module
This commit is contained in:
parent
a3b1b67447
commit
761360c0d3
5 changed files with 123 additions and 87 deletions
|
@ -5,8 +5,7 @@ extern crate trackable;
|
|||
|
||||
use std::io::{self, Read};
|
||||
use clap::{App, Arg};
|
||||
use hls_m3u8::master_playlist::MasterPlaylist;
|
||||
use hls_m3u8::media_playlist::MediaPlaylist;
|
||||
use hls_m3u8::{MasterPlaylist, MediaPlaylist};
|
||||
use trackable::error::Failure;
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -36,7 +36,7 @@ pub struct MasterPlaylist {
|
|||
impl fmt::Display for MasterPlaylist {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f, "{}", ExtM3u)?;
|
||||
if self.version.value() != ProtocolVersion::V1 {
|
||||
if self.version.version() != ProtocolVersion::V1 {
|
||||
writeln!(f, "{}", self.version)?;
|
||||
}
|
||||
for t in &self.media_tags {
|
||||
|
|
|
@ -43,7 +43,7 @@ pub struct MediaPlaylist {
|
|||
impl fmt::Display for MediaPlaylist {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f, "{}", ExtM3u)?;
|
||||
if self.version.value() != ProtocolVersion::V1 {
|
||||
if self.version.version() != ProtocolVersion::V1 {
|
||||
writeln!(f, "{}", self.version)?;
|
||||
}
|
||||
writeln!(f, "{}", self.target_duration)?;
|
||||
|
|
93
src/tag/basic.rs
Normal file
93
src/tag/basic.rs
Normal file
|
@ -0,0 +1,93 @@
|
|||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use {Error, ErrorKind, Result};
|
||||
use version::ProtocolVersion;
|
||||
|
||||
/// [4.3.1.1. EXTM3U]
|
||||
///
|
||||
/// [4.3.1.1. EXTM3U]: https://tools.ietf.org/html/rfc8216#section-4.3.1.1
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct ExtM3u;
|
||||
impl ExtM3u {
|
||||
pub(crate) const PREFIX: &'static str = "#EXTM3U";
|
||||
|
||||
/// Returns the protocol compatibility version that this tag requires.
|
||||
pub fn requires_version(&self) -> ProtocolVersion {
|
||||
ProtocolVersion::V1
|
||||
}
|
||||
}
|
||||
impl fmt::Display for ExtM3u {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Self::PREFIX.fmt(f)
|
||||
}
|
||||
}
|
||||
impl FromStr for ExtM3u {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
track_assert_eq!(s, Self::PREFIX, ErrorKind::InvalidInput);
|
||||
Ok(ExtM3u)
|
||||
}
|
||||
}
|
||||
|
||||
/// [4.3.1.2. EXT-X-VERSION]
|
||||
///
|
||||
/// [4.3.1.2. EXT-X-VERSION]: https://tools.ietf.org/html/rfc8216#section-4.3.1.2
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct ExtXVersion {
|
||||
version: ProtocolVersion,
|
||||
}
|
||||
impl ExtXVersion {
|
||||
pub(crate) const PREFIX: &'static str = "#EXT-X-VERSION:";
|
||||
|
||||
/// Makes a new `ExtXVersion` instance.
|
||||
pub fn new(version: ProtocolVersion) -> Self {
|
||||
ExtXVersion { version }
|
||||
}
|
||||
|
||||
/// Returns the protocol compatibility version of the playlist containing this tag.
|
||||
pub fn version(&self) -> ProtocolVersion {
|
||||
self.version
|
||||
}
|
||||
|
||||
/// Returns the protocol compatibility version that this tag requires.
|
||||
pub fn requires_version(&self) -> ProtocolVersion {
|
||||
ProtocolVersion::V1
|
||||
}
|
||||
}
|
||||
impl fmt::Display for ExtXVersion {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}{}", Self::PREFIX, self.version)
|
||||
}
|
||||
}
|
||||
impl FromStr for ExtXVersion {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
track_assert!(s.starts_with(Self::PREFIX), ErrorKind::InvalidInput);
|
||||
let suffix = s.split_at(Self::PREFIX.len()).1;
|
||||
let version = track!(suffix.parse())?;
|
||||
Ok(ExtXVersion { version })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use version::ProtocolVersion;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn extm3u() {
|
||||
assert_eq!("#EXTM3U".parse::<ExtM3u>().ok(), Some(ExtM3u));
|
||||
assert_eq!(ExtM3u.to_string(), "#EXTM3U");
|
||||
assert_eq!(ExtM3u.requires_version(), ProtocolVersion::V1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ext_x_version() {
|
||||
let tag = ExtXVersion::new(ProtocolVersion::V6);
|
||||
assert_eq!("#EXT-X-VERSION::6".parse::<ExtXVersion>().ok(), Some(tag));
|
||||
assert_eq!(tag.to_string(), "#EXT-X-VERSION:6");
|
||||
assert_eq!(tag.version(), ProtocolVersion::V6);
|
||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
||||
}
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
//! [4.3. Playlist Tags]
|
||||
//!
|
||||
//! [4.3. Playlist Tags]: https://tools.ietf.org/html/rfc8216#section-4.3
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
@ -15,15 +18,32 @@ macro_rules! may_invalid {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum TagKind {
|
||||
Basic,
|
||||
MediaSegment,
|
||||
MediaPlaylist,
|
||||
MasterPlaylist,
|
||||
MediaOrMasterPlaylist,
|
||||
macro_rules! impl_from {
|
||||
($to:ident, $from:ident) => {
|
||||
impl From<$from> for $to {
|
||||
fn from(f: $from) -> Self {
|
||||
$to::$from(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub use self::basic::{ExtM3u, ExtXVersion};
|
||||
|
||||
mod basic;
|
||||
|
||||
/// [4.3.1. Basic Tags]
|
||||
///
|
||||
/// [4.3.1. Basic Tags]: https://tools.ietf.org/html/rfc8216#section-4.3.1
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum BasicTag {
|
||||
ExtM3u(ExtM3u),
|
||||
ExtXVersion(ExtXVersion),
|
||||
}
|
||||
impl_from!(BasicTag, ExtM3u);
|
||||
impl_from!(BasicTag, ExtXVersion);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum MediaSegmentTag {
|
||||
ExtInf(ExtInf),
|
||||
|
@ -159,32 +179,6 @@ pub enum Tag {
|
|||
ExtXIndependentSegments(ExtXIndependentSegments),
|
||||
ExtXStart(ExtXStart),
|
||||
}
|
||||
impl Tag {
|
||||
pub fn kind(&self) -> TagKind {
|
||||
match *self {
|
||||
Tag::ExtM3u(_) | Tag::ExtXVersion(_) => TagKind::Basic,
|
||||
Tag::ExtInf(_)
|
||||
| Tag::ExtXByteRange(_)
|
||||
| Tag::ExtXDiscontinuity(_)
|
||||
| Tag::ExtXKey(_)
|
||||
| Tag::ExtXMap(_)
|
||||
| Tag::ExtXProgramDateTime(_)
|
||||
| Tag::ExtXDateRange(_) => TagKind::MediaSegment,
|
||||
Tag::ExtXTargetDuration(_)
|
||||
| Tag::ExtXMediaSequence(_)
|
||||
| Tag::ExtXDiscontinuitySequence(_)
|
||||
| Tag::ExtXEndList(_)
|
||||
| Tag::ExtXPlaylistType(_)
|
||||
| Tag::ExtXIFramesOnly(_) => TagKind::MediaPlaylist,
|
||||
Tag::ExtXMedia(_)
|
||||
| Tag::ExtXStreamInf(_)
|
||||
| Tag::ExtXIFrameStreamInf(_)
|
||||
| Tag::ExtXSessionData(_)
|
||||
| Tag::ExtXSessionKey(_) => TagKind::MasterPlaylist,
|
||||
Tag::ExtXIndependentSegments(_) | Tag::ExtXStart(_) => TagKind::MediaOrMasterPlaylist,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Display for Tag {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
|
@ -267,56 +261,6 @@ impl FromStr for Tag {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: MediaSegmentTag
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ExtM3u;
|
||||
impl ExtM3u {
|
||||
const PREFIX: &'static str = "#EXTM3U";
|
||||
}
|
||||
impl fmt::Display for ExtM3u {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Self::PREFIX.fmt(f)
|
||||
}
|
||||
}
|
||||
impl FromStr for ExtM3u {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
track_assert_eq!(s, Self::PREFIX, ErrorKind::InvalidInput);
|
||||
Ok(ExtM3u)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: A Playlist file MUST NOT contain more than one EXT-X-VERSION tag
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ExtXVersion {
|
||||
version: ProtocolVersion,
|
||||
}
|
||||
impl ExtXVersion {
|
||||
const PREFIX: &'static str = "#EXT-X-VERSION:";
|
||||
|
||||
pub fn new(version: ProtocolVersion) -> Self {
|
||||
ExtXVersion { version }
|
||||
}
|
||||
pub fn value(&self) -> ProtocolVersion {
|
||||
self.version
|
||||
}
|
||||
}
|
||||
impl fmt::Display for ExtXVersion {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}{}", Self::PREFIX, self.version)
|
||||
}
|
||||
}
|
||||
impl FromStr for ExtXVersion {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
track_assert!(s.starts_with(Self::PREFIX), ErrorKind::InvalidInput);
|
||||
let suffix = s.split_at(Self::PREFIX.len()).1;
|
||||
let version = track!(suffix.parse())?;
|
||||
Ok(ExtXVersion { version })
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This tag is REQUIRED for each Media Segment
|
||||
// TODO: if the compatibility version number is less than 3, durations MUST be integers.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
Loading…
Reference in a new issue