mirror of
https://github.com/sile/hls_m3u8.git
synced 2024-11-25 08:31:00 +00:00
parse Urls #9
This commit is contained in:
parent
c28d6963a6
commit
fa96a76ca9
6 changed files with 38 additions and 17 deletions
|
@ -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"
|
||||||
|
|
13
src/error.rs
13
src/error.rs
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue