From 13405a09eb867718afe64efa7c3f455ac9b140b3 Mon Sep 17 00:00:00 2001 From: Rutger Schoorstra Date: Fri, 6 Mar 2020 20:56:14 +0100 Subject: [PATCH 1/3] Upgraded docs to Nom 5 --- examples/with_nom_result.rs | 13 +++++------- src/lib.rs | 40 +++++++++++++++++-------------------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/examples/with_nom_result.rs b/examples/with_nom_result.rs index 0eaa49f..8e73c9e 100644 --- a/examples/with_nom_result.rs +++ b/examples/with_nom_result.rs @@ -3,7 +3,6 @@ extern crate m3u8_rs; use m3u8_rs::playlist::{Playlist}; use std::io::Read; -use nom::IResult; fn main() { let mut file = std::fs::File::open("playlist.m3u8").unwrap(); @@ -13,9 +12,8 @@ fn main() { let parsed = m3u8_rs::parse_playlist(&bytes); let playlist = match parsed { - IResult::Done(i, playlist) => playlist, - IResult::Error(e) => panic!("Parsing error: \n{}", e), - IResult::Incomplete(e) => panic!("Parsing error: \n{:?}", e), + Result::Ok((i, playlist)) => playlist, + Result::Err(e) => panic!("Parsing error: \n{}", e), }; match playlist { @@ -32,9 +30,8 @@ fn main_alt() { let parsed = m3u8_rs::parse_playlist(&bytes); match parsed { - IResult::Done(i, Playlist::MasterPlaylist(pl)) => println!("Master playlist:\n{:?}", pl), - IResult::Done(i, Playlist::MediaPlaylist(pl)) => println!("Media playlist:\n{:?}", pl), - IResult::Error(e) => panic!("Parsing error: \n{}", e), - IResult::Incomplete(e) => panic!("Parsing error: \n{:?}", e), + Result::Ok((i, Playlist::MasterPlaylist(pl))) => println!("Master playlist:\n{:?}", pl), + Result::Ok((i, Playlist::MediaPlaylist(pl))) => println!("Media playlist:\n{:?}", pl), + Result::Err(e) => panic!("Parsing error: \n{}", e), } } diff --git a/src/lib.rs b/src/lib.rs index b3adb8f..b635def 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ //! A library to parse m3u8 playlists (HTTP Live Streaming) [link] //! (https://tools.ietf.org/html/draft-pantos-http-live-streaming-19). //! -//! #Examples +//! # Examples //! //! Parsing a playlist and let the parser figure out if it's a media or master playlist. //! @@ -17,19 +17,10 @@ //! let mut bytes: Vec = Vec::new(); //! file.read_to_end(&mut bytes).unwrap(); //! -//! // Option 1: fn parse_playlist_res(input) -> Result -//! match m3u8_rs::parse_playlist_res(&bytes) { -//! Ok(Playlist::MasterPlaylist(pl)) => println!("Master playlist:\n{:?}", pl), -//! Ok(Playlist::MediaPlaylist(pl)) => println!("Media playlist:\n{:?}", pl), -//! Err(e) => println!("Error: {:?}", e) -//! } -//! -//! // Option 2: fn parse_playlist(input) -> IResult<_, Playlist, _> //! match m3u8_rs::parse_playlist(&bytes) { -//! IResult::Done(i, Playlist::MasterPlaylist(pl)) => println!("Master playlist:\n{:?}", pl), -//! IResult::Done(i, Playlist::MediaPlaylist(pl)) => println!("Media playlist:\n{:?}", pl), -//! IResult::Error(e) => panic!("Parsing error: \n{}", e), -//! IResult::Incomplete(e) => panic!("Parsing error: \n{:?}", e), +//! Result::Ok((i, Playlist::MasterPlaylist(pl))) => println!("Master playlist:\n{:?}", pl), +//! Result::Ok((i, Playlist::MediaPlaylist(pl))) => println!("Media playlist:\n{:?}", pl), +//! Result::Err(e) => panic!("Parsing error: \n{}", e), //! } //! } //! ``` @@ -47,7 +38,7 @@ //! let mut bytes: Vec = Vec::new(); //! file.read_to_end(&mut bytes).unwrap(); //! -//! if let IResult::Done(_, pl) = m3u8_rs::parse_master_playlist(&bytes) { +//! if let Result::Ok((_, pl)) = m3u8_rs::parse_master_playlist(&bytes) { //! println!("{:?}", pl); //! } //! } @@ -110,10 +101,14 @@ use playlist::*; // Playlist parser // ----------------------------------------------------------------------------------------------- -/// Parse a m3u8 playlist. +/// Parse an m3u8 playlist. /// -/// #Examples +/// # Examples /// +/// ``` +/// use std::io::Read; +/// use m3u8_rs::playlist::{Playlist}; +/// /// let mut file = std::fs::File::open("playlist.m3u8").unwrap(); /// let mut bytes: Vec = Vec::new(); /// file.read_to_end(&mut bytes).unwrap(); @@ -121,15 +116,15 @@ use playlist::*; /// let parsed = m3u8_rs::parse_playlist(&bytes); /// /// let playlist = match parsed { -/// IResult::Done(i, playlist) => playlist, -/// IResult::Error(e) => panic!("Parsing error: \n{}", e), -/// IResult::Incomplete(e) => panic!("Parsing error: \n{:?}", e), +/// Result::Ok((i, playlist)) => playlist, +/// Result::Err(e) => panic!("Parsing error: \n{}", e), /// }; /// /// match playlist { /// Playlist::MasterPlaylist(pl) => println!("Master playlist:\n{:?}", pl), /// Playlist::MediaPlaylist(pl) => println!("Media playlist:\n{:?}", pl), /// } +/// ``` pub fn parse_playlist(input: &[u8]) -> IResult<&[u8], Playlist> { match is_master_playlist(input) { true => map(parse_master_playlist, Playlist::MasterPlaylist)(input), @@ -137,9 +132,10 @@ pub fn parse_playlist(input: &[u8]) -> IResult<&[u8], Playlist> { } } -/// Parse a m3u8 playlist just like `parse_playlist`. This returns a Result. -/// -/// #Examples +/// Parses an m3u8 playlist just like `parse_playlist`, except that this returns an [std::result::Result](std::result::Result) instead of a [nom::IResult](https://docs.rs/nom/1.2.3/nom/enum.IResult.html). +/// However, since [nom::IResult](nom::IResult) is now an [alias to Result](https://github.com/Geal/nom/blob/master/doc/upgrading_to_nom_5.md), this is no longer needed. +/// +/// # Examples /// /// ``` /// use m3u8_rs::playlist::{Playlist}; From ab9c554eb44637ac8e303ffb5a346c931c17d628 Mon Sep 17 00:00:00 2001 From: Rutger Schoorstra Date: Fri, 6 Mar 2020 20:56:51 +0100 Subject: [PATCH 2/3] Upgraded tests to Nom 5 --- tests/lib.rs | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/tests/lib.rs b/tests/lib.rs index 46abc68..60f02c5 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -42,7 +42,7 @@ fn print_parse_playlist_test(playlist_name: &str) -> bool { println!("Parsing playlist file: {:?}", playlist_name); let parsed = parse_playlist(input.as_bytes()); - if let IResult::Done(i,o) = parsed { + if let Result::Ok((i,o)) = parsed { println!("{:?}", o); true } @@ -117,9 +117,9 @@ fn playlist_types() { let input = getm3u(path); let is_master = is_master_playlist(input.as_bytes()); - assert!(path.to_lowercase().contains("master") == is_master); - println!("{:?} = {:?}", path, is_master); + + assert!(path.to_lowercase().contains("master") == is_master); } } @@ -147,7 +147,7 @@ fn test_key_value_pairs_trailing_equals() { fn test_key_value_pairs_multiple_quoted_values() { assert_eq!( key_value_pairs(b"BANDWIDTH=86000,URI=\"low/iframe.m3u8\",PROGRAM-ID=1,RESOLUTION=\"1x1\",VIDEO=1\nrest"), - IResult::Done( + Result::Ok(( "\nrest".as_bytes(), vec![ ("BANDWIDTH".to_string(), "86000".to_string()), @@ -156,7 +156,7 @@ fn test_key_value_pairs_multiple_quoted_values() { ("RESOLUTION".to_string(), "1x1".to_string()), ("VIDEO".to_string(), "1".to_string()) ].into_iter().collect::>() - ) + )) ); } @@ -177,10 +177,10 @@ fn test_key_value_pairs() { fn test_key_value_pair() { assert_eq!( key_value_pair(b"PROGRAM-ID=1,rest"), - IResult::Done( + Result::Ok(( "rest".as_bytes(), ("PROGRAM-ID".to_string(), "1".to_string()) - ) + )) ); } @@ -188,7 +188,7 @@ fn test_key_value_pair() { fn comment() { assert_eq!( comment_tag(b"#Hello\nxxx"), - IResult::Done("xxx".as_bytes(), "Hello".to_string()) + Result::Ok(("xxx".as_bytes(), "Hello".to_string())) ); } @@ -196,7 +196,9 @@ fn comment() { fn quotes() { assert_eq!( quoted(b"\"value\"rest"), - IResult::Done("rest".as_bytes(), "value".to_string()) + Result::Ok(("rest".as_bytes(), "value".to_string())) + ); +} ); } @@ -210,7 +212,7 @@ fn consume_empty_line() { fn float_() { assert_eq!( float(b"33.22rest"), - IResult::Done("rest".as_bytes(), 33.22f32) + Result::Ok(("rest".as_bytes(), 33.22f32)) ); } @@ -218,7 +220,7 @@ fn float_() { fn float_no_decimal() { assert_eq!( float(b"33rest"), - IResult::Done("rest".as_bytes(), 33f32) + Result::Ok(("rest".as_bytes(), 33f32)) ); } @@ -226,7 +228,7 @@ fn float_no_decimal() { fn float_should_ignore_trailing_dot() { assert_eq!( float(b"33.rest"), - IResult::Done(".rest".as_bytes(), 33f32) + Result::Ok((".rest".as_bytes(), 33f32)) ); } @@ -234,7 +236,7 @@ fn float_should_ignore_trailing_dot() { fn parse_duration_title() { assert_eq!( duration_title_tag(b"2.002,title\nrest"), - IResult::Done("rest".as_bytes(), (2.002f32, Some("title".to_string()))) + Result::Ok(("rest".as_bytes(), (2.002f32, Some("title".to_string())))) ); } @@ -279,7 +281,7 @@ fn create_and_parse_master_playlist_full() { uri: "masterplaylist-uri".into(), bandwidth: "10010010".into(), average_bandwidth: Some("10010010".into()), - codecs: "TheCODEC".into(), + codecs: Some("TheCODEC".into()), resolution: Some("1000x3000".into()), frame_rate: Some("60".into()), audio: Some("audio".into()), From 100a57078a30e1a8a371ad4c85d4b07abfce03f5 Mon Sep 17 00:00:00 2001 From: Rutger Schoorstra Date: Fri, 6 Mar 2020 20:59:15 +0100 Subject: [PATCH 3/3] Fix failed test on CLRF --- src/lib.rs | 9 ++++----- tests/lib.rs | 22 +++++++++++++++++++--- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b635def..dc7132e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,7 +88,7 @@ use nom::{IResult}; use nom::{ delimited,none_of,peek,is_not,complete,terminated,tag, alt,do_parse,opt,named,map,map_res,eof,many0,take,take_until,char}; use nom::combinator::map; - +use nom::character::complete::{line_ending}; use std::str; use std::f32; use std::string; @@ -513,10 +513,9 @@ named!(pub unquoted, named!(pub consume_line, do_parse!( - l: map_res!(is_not!("\r\n"), from_utf8_slice) - >> take!(1) - >> - (l) + line: map_res!(is_not!("\r\n"), from_utf8_slice) + >> line_ending + >> (line) ) ); diff --git a/tests/lib.rs b/tests/lib.rs index 60f02c5..a41f0f1 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -199,13 +199,29 @@ fn quotes() { Result::Ok(("rest".as_bytes(), "value".to_string())) ); } + +#[test] +fn consume_line_empty() { + assert_eq!( + consume_line(b"\r\nrest"), + Result::Err(nom::Err::Error(("\r\nrest".as_bytes(), nom::error::ErrorKind::IsNot))) ); } #[test] -fn consume_empty_line() { - let line = consume_line(b"\r\nrest"); - println!("{:?}", line); +fn consume_line_n() { + assert_eq!( + consume_line(b"before\nrest"), + Result::Ok(("rest".as_bytes(), "before".into())) + ); +} + +#[test] +fn consume_line_rn() { + assert_eq!( + consume_line(b"before\r\nrest"), + Result::Ok(("rest".as_bytes(), "before".into())) + ); } #[test]