1
0
Fork 0
mirror of https://github.com/sile/hls_m3u8.git synced 2024-06-16 20:10:33 +00:00

parse Urls #9

This commit is contained in:
Luro02 2019-09-15 11:25:41 +02:00
parent c28d6963a6
commit fa96a76ca9
6 changed files with 38 additions and 17 deletions

View file

@ -19,6 +19,7 @@ codecov = {repository = "sile/hls_m3u8"}
getset = "0.0.8" getset = "0.0.8"
failure = "0.1.5" failure = "0.1.5"
derive_builder = "0.7.2" derive_builder = "0.7.2"
url = "2.1.0"
[dev-dependencies] [dev-dependencies]
clap = "2" clap = "2"

View file

@ -9,6 +9,9 @@ pub type Result<T> = std::result::Result<T, Error>;
/// The ErrorKind. /// The ErrorKind.
#[derive(Debug, Fail, Clone, PartialEq, Eq)] #[derive(Debug, Fail, Clone, PartialEq, Eq)]
pub enum ErrorKind { pub enum ErrorKind {
#[fail(display = "UrlParseError: {}", _0)]
/// An error from the [Url](url) crate.
UrlParseError(String),
#[fail(display = "UnknownError: {}", _0)] #[fail(display = "UnknownError: {}", _0)]
/// An unknown error occured. /// An unknown error occured.
UnknownError(String), UnknownError(String),
@ -177,6 +180,10 @@ impl Error {
pub(crate) fn builder_error<T: ToString>(value: T) -> Self { pub(crate) fn builder_error<T: ToString>(value: T) -> Self {
Self::from(ErrorKind::BuilderError(value.to_string())) Self::from(ErrorKind::BuilderError(value.to_string()))
} }
pub(crate) fn url<T: ToString>(value: T) -> Self {
Self::from(ErrorKind::UrlParseError(value.to_string()))
}
} }
impl From<::std::num::ParseIntError> for Error { impl From<::std::num::ParseIntError> for Error {
@ -196,3 +203,9 @@ impl From<::std::io::Error> for Error {
Error::io(value) Error::io(value)
} }
} }
impl From<::url::ParseError> for Error {
fn from(value: ::url::ParseError) -> Self {
Error::url(value)
}
}

View file

@ -2,6 +2,8 @@ use std::fmt;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::str::FromStr; use std::str::FromStr;
use url::Url;
use crate::tags; use crate::tags;
use crate::Error; use crate::Error;
@ -53,7 +55,7 @@ impl FromStr for Lines {
continue; continue;
} }
} else { } else {
Line::Uri(line.trim().to_string()) Line::Uri(line.trim().parse()?)
} }
} }
}; };
@ -91,7 +93,7 @@ impl DerefMut for Lines {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum Line { pub enum Line {
Tag(Tag), Tag(Tag),
Uri(String), Uri(Url),
} }
#[allow(clippy::large_enum_variant)] #[allow(clippy::large_enum_variant)]

View file

@ -2,6 +2,7 @@ use std::fmt;
use std::iter; use std::iter;
use derive_builder::Builder; use derive_builder::Builder;
use url::Url;
use crate::tags::{ use crate::tags::{
ExtInf, ExtXByteRange, ExtXDateRange, ExtXDiscontinuity, ExtXKey, ExtXMap, ExtXProgramDateTime, ExtInf, ExtXByteRange, ExtXDateRange, ExtXDiscontinuity, ExtXKey, ExtXMap, ExtXProgramDateTime,
@ -33,7 +34,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: String, uri: Url,
} }
impl MediaSegmentBuilder { impl MediaSegmentBuilder {
@ -80,7 +81,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) -> &String { pub const fn uri(&self) -> &Url {
&self.uri &self.uri
} }

View file

@ -1,6 +1,8 @@
use std::fmt; use std::fmt;
use std::str::FromStr; use std::str::FromStr;
use url::Url;
use crate::attribute::AttributePairs; use crate::attribute::AttributePairs;
use crate::types::{ use crate::types::{
ClosedCaptions, DecimalFloatingPoint, DecimalResolution, HdcpLevel, ProtocolVersion, ClosedCaptions, DecimalFloatingPoint, DecimalResolution, HdcpLevel, ProtocolVersion,
@ -13,7 +15,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: String, uri: Url,
bandwidth: u64, bandwidth: u64,
average_bandwidth: Option<u64>, average_bandwidth: Option<u64>,
codecs: Option<String>, codecs: Option<String>,
@ -30,9 +32,9 @@ impl ExtXStreamInf {
pub(crate) const PREFIX: &'static str = "#EXT-X-STREAM-INF:"; pub(crate) const PREFIX: &'static str = "#EXT-X-STREAM-INF:";
/// Makes a new `ExtXStreamInf` tag. /// Makes a new `ExtXStreamInf` tag.
pub fn new<T: ToString>(uri: T, bandwidth: u64) -> Self { pub const fn new(uri: Url, bandwidth: u64) -> Self {
ExtXStreamInf { ExtXStreamInf {
uri: uri.to_string(), uri,
bandwidth, bandwidth,
average_bandwidth: None, average_bandwidth: None,
codecs: None, codecs: None,
@ -47,7 +49,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) -> &String { pub const fn uri(&self) -> &Url {
&self.uri &self.uri
} }
@ -191,7 +193,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.to_string(), uri: uri.parse()?,
bandwidth, bandwidth,
average_bandwidth, average_bandwidth,
codecs, codecs,
@ -212,26 +214,29 @@ mod test {
#[test] #[test]
fn test_parser() { fn test_parser() {
let stream_inf = "#EXT-X-STREAM-INF:BANDWIDTH=1000\nfoo" let stream_inf = "#EXT-X-STREAM-INF:BANDWIDTH=1000\nhttp://www.example.com"
.parse::<ExtXStreamInf>() .parse::<ExtXStreamInf>()
.unwrap(); .unwrap();
assert_eq!(stream_inf, ExtXStreamInf::new("foo", 1000)); assert_eq!(
stream_inf,
ExtXStreamInf::new("http://www.example.com".parse().unwrap(), 1000)
);
} }
#[test] #[test]
fn test_requires_version() { fn test_requires_version() {
assert_eq!( assert_eq!(
ProtocolVersion::V1, ProtocolVersion::V1,
ExtXStreamInf::new("foo", 1000).requires_version() ExtXStreamInf::new("http://www.example.com".parse().unwrap(), 1000).requires_version()
); );
} }
#[test] #[test]
fn test_display() { fn test_display() {
assert_eq!( assert_eq!(
ExtXStreamInf::new("foo", 1000).to_string(), ExtXStreamInf::new("http://www.example.com".parse().unwrap(), 1000).to_string(),
"#EXT-X-STREAM-INF:BANDWIDTH=1000\nfoo".to_string() "#EXT-X-STREAM-INF:BANDWIDTH=1000\nhttp://www.example.com/".to_string()
); );
} }
} }

View file

@ -1,7 +1,6 @@
//! Credits go to //! Credits go to
//! - https://github.com/globocom/m3u8/blob/master/tests/playlists.py //! - https://github.com/globocom/m3u8/blob/master/tests/playlists.py
use hls_m3u8::tags::*; use hls_m3u8::tags::*;
use hls_m3u8::types::*;
use hls_m3u8::MediaPlaylist; use hls_m3u8::MediaPlaylist;
use std::time::Duration; use std::time::Duration;
@ -37,11 +36,11 @@ fn test_simple_playlist() {
assert_eq!( assert_eq!(
media_playlist.segments()[0].uri(), media_playlist.segments()[0].uri(),
&"http://media.example.com/entire1.ts".to_string() &"http://media.example.com/entire1.ts".parse().unwrap()
); );
assert_eq!( assert_eq!(
media_playlist.segments()[1].uri(), media_playlist.segments()[1].uri(),
&"http://media.example.com/entire2.ts".to_string() &"http://media.example.com/entire2.ts".parse().unwrap()
); );
} }