mirror of
https://github.com/sile/hls_m3u8.git
synced 2024-11-25 08:31:00 +00:00
removed SingleLineString #9
This commit is contained in:
parent
6ffbe50322
commit
c28d6963a6
8 changed files with 35 additions and 122 deletions
|
@ -3,7 +3,6 @@ use std::ops::{Deref, DerefMut};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::tags;
|
use crate::tags;
|
||||||
use crate::types::SingleLineString;
|
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -54,7 +53,7 @@ impl FromStr for Lines {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Line::Uri(SingleLineString::new(line)?)
|
Line::Uri(line.trim().to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -92,7 +91,7 @@ impl DerefMut for Lines {
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum Line {
|
pub enum Line {
|
||||||
Tag(Tag),
|
Tag(Tag),
|
||||||
Uri(SingleLineString),
|
Uri(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
@ -120,7 +119,7 @@ pub enum Tag {
|
||||||
ExtXSessionKey(tags::ExtXSessionKey),
|
ExtXSessionKey(tags::ExtXSessionKey),
|
||||||
ExtXIndependentSegments(tags::ExtXIndependentSegments),
|
ExtXIndependentSegments(tags::ExtXIndependentSegments),
|
||||||
ExtXStart(tags::ExtXStart),
|
ExtXStart(tags::ExtXStart),
|
||||||
Unknown(SingleLineString),
|
Unknown(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Tag {
|
impl fmt::Display for Tag {
|
||||||
|
@ -202,7 +201,7 @@ impl FromStr for Tag {
|
||||||
} else if s.starts_with(tags::ExtXStart::PREFIX) {
|
} else if s.starts_with(tags::ExtXStart::PREFIX) {
|
||||||
s.parse().map(Tag::ExtXStart)
|
s.parse().map(Tag::ExtXStart)
|
||||||
} else {
|
} else {
|
||||||
SingleLineString::new(s).map(Tag::Unknown)
|
Ok(Tag::Unknown(s.to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use derive_builder::Builder;
|
||||||
use crate::tags::{
|
use crate::tags::{
|
||||||
ExtInf, ExtXByteRange, ExtXDateRange, ExtXDiscontinuity, ExtXKey, ExtXMap, ExtXProgramDateTime,
|
ExtInf, ExtXByteRange, ExtXDateRange, ExtXDiscontinuity, ExtXKey, ExtXMap, ExtXProgramDateTime,
|
||||||
};
|
};
|
||||||
use crate::types::{ProtocolVersion, SingleLineString};
|
use crate::types::ProtocolVersion;
|
||||||
|
|
||||||
/// Media segment.
|
/// Media segment.
|
||||||
#[derive(Debug, Clone, Builder)]
|
#[derive(Debug, Clone, Builder)]
|
||||||
|
@ -33,7 +33,7 @@ pub struct MediaSegment {
|
||||||
/// Sets an [ExtInf] tag.
|
/// Sets an [ExtInf] tag.
|
||||||
inf_tag: ExtInf,
|
inf_tag: ExtInf,
|
||||||
/// Sets an Uri.
|
/// Sets an Uri.
|
||||||
uri: SingleLineString,
|
uri: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MediaSegmentBuilder {
|
impl MediaSegmentBuilder {
|
||||||
|
@ -80,7 +80,7 @@ impl MediaSegment {
|
||||||
MediaSegmentBuilder::default()
|
MediaSegmentBuilder::default()
|
||||||
}
|
}
|
||||||
/// Returns the URI of the media segment.
|
/// Returns the URI of the media segment.
|
||||||
pub const fn uri(&self) -> &SingleLineString {
|
pub const fn uri(&self) -> &String {
|
||||||
&self.uri
|
&self.uri
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ use std::str::FromStr;
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
ClosedCaptions, DecimalFloatingPoint, DecimalResolution, HdcpLevel, ProtocolVersion,
|
ClosedCaptions, DecimalFloatingPoint, DecimalResolution, HdcpLevel, ProtocolVersion,
|
||||||
SingleLineString,
|
|
||||||
};
|
};
|
||||||
use crate::utils::{parse_u64, quote, tag, unquote};
|
use crate::utils::{parse_u64, quote, tag, unquote};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
@ -14,7 +13,7 @@ use crate::Error;
|
||||||
/// [4.3.4.2. EXT-X-STREAM-INF]: https://tools.ietf.org/html/rfc8216#section-4.3.4.2
|
/// [4.3.4.2. EXT-X-STREAM-INF]: https://tools.ietf.org/html/rfc8216#section-4.3.4.2
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ExtXStreamInf {
|
pub struct ExtXStreamInf {
|
||||||
uri: SingleLineString,
|
uri: String,
|
||||||
bandwidth: u64,
|
bandwidth: u64,
|
||||||
average_bandwidth: Option<u64>,
|
average_bandwidth: Option<u64>,
|
||||||
codecs: Option<String>,
|
codecs: Option<String>,
|
||||||
|
@ -33,7 +32,7 @@ impl ExtXStreamInf {
|
||||||
/// Makes a new `ExtXStreamInf` tag.
|
/// Makes a new `ExtXStreamInf` tag.
|
||||||
pub fn new<T: ToString>(uri: T, bandwidth: u64) -> Self {
|
pub fn new<T: ToString>(uri: T, bandwidth: u64) -> Self {
|
||||||
ExtXStreamInf {
|
ExtXStreamInf {
|
||||||
uri: SingleLineString::new(uri.to_string()).unwrap(),
|
uri: uri.to_string(),
|
||||||
bandwidth,
|
bandwidth,
|
||||||
average_bandwidth: None,
|
average_bandwidth: None,
|
||||||
codecs: None,
|
codecs: None,
|
||||||
|
@ -48,7 +47,7 @@ impl ExtXStreamInf {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the URI that identifies the associated media playlist.
|
/// Returns the URI that identifies the associated media playlist.
|
||||||
pub const fn uri(&self) -> &SingleLineString {
|
pub const fn uri(&self) -> &String {
|
||||||
&self.uri
|
&self.uri
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,12 +154,10 @@ impl FromStr for ExtXStreamInf {
|
||||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||||
let mut lines = input.lines();
|
let mut lines = input.lines();
|
||||||
let first_line = lines.next().ok_or(Error::missing_value("first_line"))?;
|
let first_line = lines.next().ok_or(Error::missing_value("first_line"))?;
|
||||||
let second_line = lines.next().ok_or(Error::missing_value("second_line"))?;
|
let uri = lines.next().ok_or(Error::missing_value("second_line"))?;
|
||||||
|
|
||||||
let first_line = tag(first_line, Self::PREFIX)?;
|
let first_line = tag(first_line, Self::PREFIX)?;
|
||||||
|
|
||||||
let uri = SingleLineString::new(second_line)?;
|
|
||||||
|
|
||||||
let mut bandwidth = None;
|
let mut bandwidth = None;
|
||||||
let mut average_bandwidth = None;
|
let mut average_bandwidth = None;
|
||||||
let mut codecs = None;
|
let mut codecs = None;
|
||||||
|
@ -194,7 +191,7 @@ impl FromStr for ExtXStreamInf {
|
||||||
let bandwidth = bandwidth.ok_or(Error::missing_value("EXT-X-BANDWIDTH"))?;
|
let bandwidth = bandwidth.ok_or(Error::missing_value("EXT-X-BANDWIDTH"))?;
|
||||||
|
|
||||||
Ok(ExtXStreamInf {
|
Ok(ExtXStreamInf {
|
||||||
uri,
|
uri: uri.to_string(),
|
||||||
bandwidth,
|
bandwidth,
|
||||||
average_bandwidth,
|
average_bandwidth,
|
||||||
codecs,
|
codecs,
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::types::{DecimalFloatingPoint, ProtocolVersion, SingleLineString};
|
use crate::types::{DecimalFloatingPoint, ProtocolVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -35,11 +35,10 @@ use crate::Error;
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::time::Duration;
|
/// use std::time::Duration;
|
||||||
/// use hls_m3u8::tags::ExtInf;
|
/// use hls_m3u8::tags::ExtInf;
|
||||||
/// use hls_m3u8::types::SingleLineString;
|
|
||||||
///
|
///
|
||||||
/// let ext_inf = ExtInf::with_title(
|
/// let ext_inf = ExtInf::with_title(
|
||||||
/// Duration::from_millis(88),
|
/// Duration::from_millis(88),
|
||||||
/// SingleLineString::new("title").unwrap()
|
/// "title"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// assert_eq!(ext_inf.duration(), Duration::from_millis(88));
|
/// assert_eq!(ext_inf.duration(), Duration::from_millis(88));
|
||||||
|
@ -48,7 +47,7 @@ use crate::Error;
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub struct ExtInf {
|
pub struct ExtInf {
|
||||||
duration: Duration,
|
duration: Duration,
|
||||||
title: Option<SingleLineString>,
|
title: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtInf {
|
impl ExtInf {
|
||||||
|
@ -63,10 +62,10 @@ impl ExtInf {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `ExtInf` tag with the given title.
|
/// Makes a new `ExtInf` tag with the given title.
|
||||||
pub const fn with_title(duration: Duration, title: SingleLineString) -> Self {
|
pub fn with_title<T: ToString>(duration: Duration, title: T) -> Self {
|
||||||
ExtInf {
|
ExtInf {
|
||||||
duration,
|
duration,
|
||||||
title: Some(title),
|
title: Some(title.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +75,7 @@ impl ExtInf {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the title of the associated media segment.
|
/// Returns the title of the associated media segment.
|
||||||
pub fn title(&self) -> Option<&SingleLineString> {
|
pub fn title(&self) -> Option<&String> {
|
||||||
self.title.as_ref()
|
self.title.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +126,7 @@ impl FromStr for ExtInf {
|
||||||
if tokens[1].trim().is_empty() {
|
if tokens[1].trim().is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(SingleLineString::new(tokens[1])?)
|
Some(tokens[1].to_string())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -160,19 +159,11 @@ mod test {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"#EXTINF:5.5,title".to_string(),
|
"#EXTINF:5.5,title".to_string(),
|
||||||
ExtInf::with_title(
|
ExtInf::with_title(Duration::from_millis(5500), "title").to_string()
|
||||||
Duration::from_millis(5500),
|
|
||||||
SingleLineString::new("title").unwrap()
|
|
||||||
)
|
|
||||||
.to_string()
|
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"#EXTINF:5,title".to_string(),
|
"#EXTINF:5,title".to_string(),
|
||||||
ExtInf::with_title(
|
ExtInf::with_title(Duration::from_secs(5), "title").to_string()
|
||||||
Duration::from_secs(5),
|
|
||||||
SingleLineString::new("title").unwrap()
|
|
||||||
)
|
|
||||||
.to_string()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,17 +188,11 @@ mod test {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"#EXTINF:5.5,title".parse::<ExtInf>().unwrap(),
|
"#EXTINF:5.5,title".parse::<ExtInf>().unwrap(),
|
||||||
ExtInf::with_title(
|
ExtInf::with_title(Duration::from_millis(5500), "title")
|
||||||
Duration::from_millis(5500),
|
|
||||||
SingleLineString::new("title").unwrap()
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"#EXTINF:5,title".parse::<ExtInf>().unwrap(),
|
"#EXTINF:5,title".parse::<ExtInf>().unwrap(),
|
||||||
ExtInf::with_title(
|
ExtInf::with_title(Duration::from_secs(5), "title")
|
||||||
Duration::from_secs(5),
|
|
||||||
SingleLineString::new("title").unwrap()
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,12 +200,8 @@ mod test {
|
||||||
fn test_title() {
|
fn test_title() {
|
||||||
assert_eq!(ExtInf::new(Duration::from_secs(5)).title(), None);
|
assert_eq!(ExtInf::new(Duration::from_secs(5)).title(), None);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ExtInf::with_title(
|
ExtInf::with_title(Duration::from_secs(5), "title").title(),
|
||||||
Duration::from_secs(5),
|
Some(&"title".to_string())
|
||||||
SingleLineString::new("title").unwrap()
|
|
||||||
)
|
|
||||||
.title(),
|
|
||||||
Some(&SingleLineString::new("title").unwrap())
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::types::{ProtocolVersion, SingleLineString};
|
use crate::types::ProtocolVersion;
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -9,21 +9,19 @@ use crate::Error;
|
||||||
///
|
///
|
||||||
/// [4.3.2.6. EXT-X-PROGRAM-DATE-TIME]: https://tools.ietf.org/html/rfc8216#section-4.3.2.6
|
/// [4.3.2.6. EXT-X-PROGRAM-DATE-TIME]: https://tools.ietf.org/html/rfc8216#section-4.3.2.6
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct ExtXProgramDateTime {
|
pub struct ExtXProgramDateTime(String);
|
||||||
date_time: SingleLineString,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExtXProgramDateTime {
|
impl ExtXProgramDateTime {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-PROGRAM-DATE-TIME:";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-PROGRAM-DATE-TIME:";
|
||||||
|
|
||||||
/// Makes a new `ExtXProgramDateTime` tag.
|
/// Makes a new `ExtXProgramDateTime` tag.
|
||||||
pub const fn new(date_time: SingleLineString) -> Self {
|
pub fn new<T: ToString>(date_time: T) -> Self {
|
||||||
ExtXProgramDateTime { date_time }
|
Self(date_time.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the date-time of the first sample of the associated media segment.
|
/// Returns the date-time of the first sample of the associated media segment.
|
||||||
pub const fn date_time(&self) -> &SingleLineString {
|
pub const fn date_time(&self) -> &String {
|
||||||
&self.date_time
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
/// Returns the protocol compatibility version that this tag requires.
|
||||||
|
@ -34,7 +32,7 @@ impl ExtXProgramDateTime {
|
||||||
|
|
||||||
impl fmt::Display for ExtXProgramDateTime {
|
impl fmt::Display for ExtXProgramDateTime {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}{}", Self::PREFIX, self.date_time)
|
write!(f, "{}{}", Self::PREFIX, self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,9 +44,7 @@ impl FromStr for ExtXProgramDateTime {
|
||||||
|
|
||||||
// TODO: parse with chrono
|
// TODO: parse with chrono
|
||||||
|
|
||||||
Ok(ExtXProgramDateTime {
|
Ok(Self::new(input))
|
||||||
date_time: (SingleLineString::new(input))?,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ mod media_type;
|
||||||
mod protocol_version;
|
mod protocol_version;
|
||||||
mod session_data;
|
mod session_data;
|
||||||
mod signed_decimal_floating_point;
|
mod signed_decimal_floating_point;
|
||||||
mod single_line_string;
|
|
||||||
|
|
||||||
pub use byte_range::*;
|
pub use byte_range::*;
|
||||||
pub use closed_captions::*;
|
pub use closed_captions::*;
|
||||||
|
@ -29,4 +28,3 @@ pub use media_type::*;
|
||||||
pub use protocol_version::*;
|
pub use protocol_version::*;
|
||||||
pub use session_data::*;
|
pub use session_data::*;
|
||||||
pub use signed_decimal_floating_point::*;
|
pub use signed_decimal_floating_point::*;
|
||||||
pub use single_line_string::*;
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
use crate::Error;
|
|
||||||
use std::fmt;
|
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
/// String that represents a single line in a playlist file.
|
|
||||||
///
|
|
||||||
/// See: [4.1. Definition of a Playlist]
|
|
||||||
///
|
|
||||||
/// [4.1. Definition of a Playlist]: https://tools.ietf.org/html/rfc8216#section-4.1
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
pub struct SingleLineString(String);
|
|
||||||
|
|
||||||
impl SingleLineString {
|
|
||||||
/// Makes a new `SingleLineString` instance.
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// If the given string contains any control characters,
|
|
||||||
/// this function will return an error which has the kind `ErrorKind::InvalidInput`.
|
|
||||||
pub fn new<T: Into<String>>(s: T) -> crate::Result<Self> {
|
|
||||||
let s = s.into();
|
|
||||||
if s.chars().any(|c| c.is_control()) {
|
|
||||||
Err(Error::invalid_input())
|
|
||||||
} else {
|
|
||||||
Ok(SingleLineString(s))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for SingleLineString {
|
|
||||||
type Target = str;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<str> for SingleLineString {
|
|
||||||
fn as_ref(&self) -> &str {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for SingleLineString {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
self.0.fmt(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn single_line_string() {
|
|
||||||
assert!(SingleLineString::new("foo").is_ok());
|
|
||||||
assert!(SingleLineString::new("b\rar").is_err());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -37,11 +37,11 @@ fn test_simple_playlist() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
media_playlist.segments()[0].uri(),
|
media_playlist.segments()[0].uri(),
|
||||||
&SingleLineString::new("http://media.example.com/entire1.ts").unwrap()
|
&"http://media.example.com/entire1.ts".to_string()
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
media_playlist.segments()[1].uri(),
|
media_playlist.segments()[1].uri(),
|
||||||
&SingleLineString::new("http://media.example.com/entire2.ts").unwrap()
|
&"http://media.example.com/entire2.ts".to_string()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue