closedcaption: Port to combine 4

This commit is contained in:
Sebastian Dröge 2020-01-30 10:27:05 +02:00 committed by Sebastian Dröge
parent 660e325bbc
commit 8370fb8a11
5 changed files with 135 additions and 120 deletions

View file

@ -9,7 +9,7 @@ repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs"
[dependencies] [dependencies]
glib = { git = "https://github.com/gtk-rs/glib" } glib = { git = "https://github.com/gtk-rs/glib" }
combine = "3.6" combine = "4.0"
either = "1" either = "1"
uuid = { version = "0.8", features = ["v4"] } uuid = { version = "0.8", features = ["v4"] }
chrono = "0.4" chrono = "0.4"

View file

@ -94,7 +94,7 @@ struct State {
need_flush_stop: bool, need_flush_stop: bool,
} }
type CombineError<'a> = combine::easy::Errors<u8, &'a [u8], combine::stream::PointerOffset>; type CombineError<'a> = combine::easy::ParseError<&'a [u8]>;
impl Default for State { impl Default for State {
fn default() -> Self { fn default() -> Self {

View file

@ -21,6 +21,7 @@ use combine;
use combine::parser::byte::hex_digit; use combine::parser::byte::hex_digit;
use combine::parser::range::{range, take_while1}; use combine::parser::range::{range, take_while1};
use combine::parser::repeat::skip_many; use combine::parser::repeat::skip_many;
use combine::parser::EasyParser;
use combine::{any, choice, eof, from_str, many1, one_of, optional, token, unexpected_any, value}; use combine::{any, choice, eof, from_str, many1, one_of, optional, token, unexpected_any, value};
use combine::{ParseError, Parser, RangeStream}; use combine::{ParseError, Parser, RangeStream};
@ -59,22 +60,20 @@ pub struct MccParser {
} }
/// Parser for parsing a run of ASCII, decimal digits and converting them into a `u32` /// Parser for parsing a run of ASCII, decimal digits and converting them into a `u32`
fn digits<'a, I: 'a>() -> impl Parser<Input = I, Output = u32> fn digits<'a, I: 'a>() -> impl Parser<I, Output = u32>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
from_str(take_while1(|c: u8| c >= b'0' && c <= b'9').message("while parsing digits")) from_str(take_while1(|c: u8| c >= b'0' && c <= b'9').message("while parsing digits"))
} }
/// Parser for a run of decimal digits, that converts them into a `u32` and checks if the result is /// Parser for a run of decimal digits, that converts them into a `u32` and checks if the result is
/// in the allowed range. /// in the allowed range.
fn digits_range<'a, I: 'a, R: std::ops::RangeBounds<u32>>( fn digits_range<'a, I: 'a, R: std::ops::RangeBounds<u32>>(range: R) -> impl Parser<I, Output = u32>
range: R,
) -> impl Parser<Input = I, Output = u32>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
digits().then(move |v| { digits().then(move |v| {
if range.contains(&v) { if range.contains(&v) {
@ -86,10 +85,10 @@ where
} }
/// Parser for a timecode in the form `hh:mm:ss:fs` /// Parser for a timecode in the form `hh:mm:ss:fs`
fn timecode<'a, I: 'a>() -> impl Parser<Input = I, Output = TimeCode> fn timecode<'a, I: 'a>() -> impl Parser<I, Output = TimeCode>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
( (
digits(), digits(),
@ -111,10 +110,10 @@ where
} }
/// Parser that checks for EOF and optionally `\n` or `\r\n` before EOF /// Parser that checks for EOF and optionally `\n` or `\r\n` before EOF
fn end_of_line<'a, I: 'a>() -> impl Parser<Input = I, Output = ()> + 'a fn end_of_line<'a, I: 'a>() -> impl Parser<I, Output = ()> + 'a
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
( (
optional(choice((range(b"\n".as_ref()), range(b"\r\n".as_ref())))), optional(choice((range(b"\n".as_ref()), range(b"\r\n".as_ref())))),
@ -125,10 +124,10 @@ where
} }
/// Parser for the MCC header /// Parser for the MCC header
fn header<'a, I: 'a>() -> impl Parser<Input = I, Output = MccLine<'a>> fn header<'a, I: 'a>() -> impl Parser<I, Output = MccLine<'a>>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
( (
range(b"File Format=MacCaption_MCC V".as_ref()), range(b"File Format=MacCaption_MCC V".as_ref()),
@ -140,10 +139,10 @@ where
} }
/// Parser that accepts only an empty line /// Parser that accepts only an empty line
fn empty_line<'a, I: 'a>() -> impl Parser<Input = I, Output = MccLine<'a>> fn empty_line<'a, I: 'a>() -> impl Parser<I, Output = MccLine<'a>>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
end_of_line() end_of_line()
.map(|_| MccLine::Empty) .map(|_| MccLine::Empty)
@ -152,10 +151,10 @@ where
/// Parser for an MCC comment, i.e. a line starting with `//`. We don't return the actual comment /// Parser for an MCC comment, i.e. a line starting with `//`. We don't return the actual comment
/// text as it's irrelevant for us. /// text as it's irrelevant for us.
fn comment<'a, I: 'a>() -> impl Parser<Input = I, Output = MccLine<'a>> fn comment<'a, I: 'a>() -> impl Parser<I, Output = MccLine<'a>>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
(token(b'/'), token(b'/'), skip_many(any())) (token(b'/'), token(b'/'), skip_many(any()))
.map(|_| MccLine::Comment) .map(|_| MccLine::Comment)
@ -163,10 +162,10 @@ where
} }
/// Parser for the MCC UUID line. /// Parser for the MCC UUID line.
fn uuid<'a, I: 'a>() -> impl Parser<Input = I, Output = MccLine<'a>> fn uuid<'a, I: 'a>() -> impl Parser<I, Output = MccLine<'a>>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
( (
range(b"UUID=".as_ref()), range(b"UUID=".as_ref()),
@ -178,10 +177,10 @@ where
} }
/// Parser for the MCC Time Code Rate line. /// Parser for the MCC Time Code Rate line.
fn time_code_rate<'a, I: 'a>() -> impl Parser<Input = I, Output = MccLine<'a>> fn time_code_rate<'a, I: 'a>() -> impl Parser<I, Output = MccLine<'a>>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
( (
range(b"Time Code Rate=".as_ref()), range(b"Time Code Rate=".as_ref()),
@ -195,10 +194,10 @@ where
} }
/// Parser for generic MCC metadata lines in the form `key=value`. /// Parser for generic MCC metadata lines in the form `key=value`.
fn metadata<'a, I: 'a>() -> impl Parser<Input = I, Output = MccLine<'a>> fn metadata<'a, I: 'a>() -> impl Parser<I, Output = MccLine<'a>>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
( (
take_while1(|b| b != b'='), take_while1(|b| b != b'='),
@ -215,55 +214,73 @@ where
/// ///
/// It returns an `Either` of the single hex encoded byte or the short-cut byte sequence as a /// It returns an `Either` of the single hex encoded byte or the short-cut byte sequence as a
/// static byte slice. /// static byte slice.
fn mcc_payload_item<'a, I: 'a>() -> impl Parser<Input = I, Output = Either<u8, &'static [u8]>> fn mcc_payload_item<'a, I: 'a>() -> impl Parser<I, Output = Either<u8, &'static [u8]>>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
choice!( // FIXME: Switch back to the choice! macro once https://github.com/rust-lang/rust/issues/68666
// is fixed and we depend on a new enough Rust version.
choice((
token(b'G').map(|_| Either::Right([0xfau8, 0x00, 0x00].as_ref())), token(b'G').map(|_| Either::Right([0xfau8, 0x00, 0x00].as_ref())),
token(b'H').map(|_| Either::Right([0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00].as_ref())), token(b'H').map(|_| Either::Right([0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00].as_ref())),
token(b'I').map(|_| Either::Right( token(b'I').map(|_| {
[0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00].as_ref() Either::Right([0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00].as_ref())
)), }),
token(b'J').map(|_| Either::Right( token(b'J').map(|_| {
[0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00].as_ref() Either::Right(
)), [
token(b'K').map(|_| Either::Right( 0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
[ ]
0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, .as_ref(),
0x00, 0x00 )
] }),
.as_ref() token(b'K').map(|_| {
)), Either::Right(
token(b'L').map(|_| Either::Right( [
[ 0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
0x00, 0x00, 0xfa, 0x00, 0x00 ]
] .as_ref(),
.as_ref() )
)), }),
token(b'M').map(|_| Either::Right( token(b'L').map(|_| {
[ Either::Right(
0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, [
0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00 0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
] 0x00, 0x00, 0xfa, 0x00, 0x00,
.as_ref() ]
)), .as_ref(),
token(b'N').map(|_| Either::Right( )
[ }),
0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, token(b'M').map(|_| {
0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00 Either::Right(
] [
.as_ref() 0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
)), 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
token(b'O').map(|_| Either::Right( ]
[ .as_ref(),
0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, )
0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00 }),
] token(b'N').map(|_| {
.as_ref() Either::Right(
)), [
0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
]
.as_ref(),
)
}),
token(b'O').map(|_| {
Either::Right(
[
0xfau8, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00,
0x00,
]
.as_ref(),
)
}),
token(b'P').map(|_| Either::Right([0xfbu8, 0x80, 0x80].as_ref())), token(b'P').map(|_| Either::Right([0xfbu8, 0x80, 0x80].as_ref())),
token(b'Q').map(|_| Either::Right([0xfcu8, 0x80, 0x80].as_ref())), token(b'Q').map(|_| Either::Right([0xfcu8, 0x80, 0x80].as_ref())),
token(b'R').map(|_| Either::Right([0xfdu8, 0x80, 0x80].as_ref())), token(b'R').map(|_| Either::Right([0xfdu8, 0x80, 0x80].as_ref())),
@ -280,8 +297,8 @@ where
}; };
let val = (hex_to_u8(u) << 4) | hex_to_u8(l); let val = (hex_to_u8(u) << 4) | hex_to_u8(l);
Either::Left(val) Either::Left(val)
}) }),
) ))
.message("while parsing MCC payload") .message("while parsing MCC payload")
} }
@ -311,10 +328,10 @@ impl<'a> Extend<Either<u8, &'a [u8]>> for VecExtend {
} }
/// Parser for the whole MCC payload with conversion to the underlying byte values. /// Parser for the whole MCC payload with conversion to the underlying byte values.
fn mcc_payload<'a, I: 'a>() -> impl Parser<Input = I, Output = Vec<u8>> fn mcc_payload<'a, I: 'a>() -> impl Parser<I, Output = Vec<u8>>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
many1(mcc_payload_item()) many1(mcc_payload_item())
.map(|v: VecExtend| v.0) .map(|v: VecExtend| v.0)
@ -322,10 +339,10 @@ where
} }
/// Parser for a MCC caption line in the form `timecode\tpayload`. /// Parser for a MCC caption line in the form `timecode\tpayload`.
fn caption<'a, I: 'a>(parse_payload: bool) -> impl Parser<Input = I, Output = MccLine<'a>> fn caption<'a, I: 'a>(parse_payload: bool) -> impl Parser<I, Output = MccLine<'a>>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
( (
timecode(), timecode(),
@ -368,8 +385,7 @@ impl MccParser {
&mut self, &mut self,
line: &'a [u8], line: &'a [u8],
parse_payload: bool, parse_payload: bool,
) -> Result<MccLine<'a>, combine::easy::Errors<u8, &'a [u8], combine::stream::PointerOffset>> ) -> Result<MccLine<'a>, combine::easy::ParseError<&'a [u8]>> {
{
match self.state { match self.state {
State::Header => header() State::Header => header()
.message("while in Header state") .message("while in Header state")

View file

@ -51,7 +51,7 @@ struct State {
last_timecode: Option<gst_video::ValidVideoTimeCode>, last_timecode: Option<gst_video::ValidVideoTimeCode>,
} }
type CombineError<'a> = combine::easy::Errors<u8, &'a [u8], combine::stream::PointerOffset>; type CombineError<'a> = combine::easy::ParseError<&'a [u8]>;
impl Default for State { impl Default for State {
fn default() -> Self { fn default() -> Self {

View file

@ -19,6 +19,7 @@
use combine; use combine;
use combine::parser::byte::hex_digit; use combine::parser::byte::hex_digit;
use combine::parser::range::{range, take_while1}; use combine::parser::range::{range, take_while1};
use combine::parser::EasyParser;
use combine::{choice, eof, from_str, many1, one_of, optional, token, unexpected_any, value}; use combine::{choice, eof, from_str, many1, one_of, optional, token, unexpected_any, value};
use combine::{ParseError, Parser, RangeStream}; use combine::{ParseError, Parser, RangeStream};
@ -51,22 +52,20 @@ pub struct SccParser {
} }
/// Parser for parsing a run of ASCII, decimal digits and converting them into a `u32` /// Parser for parsing a run of ASCII, decimal digits and converting them into a `u32`
fn digits<'a, I: 'a>() -> impl Parser<Input = I, Output = u32> fn digits<'a, I: 'a>() -> impl Parser<I, Output = u32>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
from_str(take_while1(|c: u8| c >= b'0' && c <= b'9').message("while parsing digits")) from_str(take_while1(|c: u8| c >= b'0' && c <= b'9').message("while parsing digits"))
} }
/// Parser for a run of decimal digits, that converts them into a `u32` and checks if the result is /// Parser for a run of decimal digits, that converts them into a `u32` and checks if the result is
/// in the allowed range. /// in the allowed range.
fn digits_range<'a, I: 'a, R: std::ops::RangeBounds<u32>>( fn digits_range<'a, I: 'a, R: std::ops::RangeBounds<u32>>(range: R) -> impl Parser<I, Output = u32>
range: R,
) -> impl Parser<Input = I, Output = u32>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
digits().then(move |v| { digits().then(move |v| {
if range.contains(&v) { if range.contains(&v) {
@ -78,10 +77,10 @@ where
} }
/// Parser for a timecode in the form `hh:mm:ss:fs` /// Parser for a timecode in the form `hh:mm:ss:fs`
fn timecode<'a, I: 'a>() -> impl Parser<Input = I, Output = TimeCode> fn timecode<'a, I: 'a>() -> impl Parser<I, Output = TimeCode>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
( (
digits(), digits(),
@ -103,10 +102,10 @@ where
} }
/// Parser that checks for EOF and optionally `\n` or `\r\n` before EOF /// Parser that checks for EOF and optionally `\n` or `\r\n` before EOF
fn end_of_line<'a, I: 'a>() -> impl Parser<Input = I, Output = ()> + 'a fn end_of_line<'a, I: 'a>() -> impl Parser<I, Output = ()> + 'a
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
( (
optional(choice((range(b"\n".as_ref()), range(b"\r\n".as_ref())))), optional(choice((range(b"\n".as_ref()), range(b"\r\n".as_ref())))),
@ -117,10 +116,10 @@ where
} }
/// Parser for the SCC header /// Parser for the SCC header
fn header<'a, I: 'a>() -> impl Parser<Input = I, Output = SccLine> + 'a fn header<'a, I: 'a>() -> impl Parser<I, Output = SccLine> + 'a
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
(range(b"Scenarist_SCC V1.0".as_ref()), end_of_line()) (range(b"Scenarist_SCC V1.0".as_ref()), end_of_line())
.map(|_| SccLine::Header) .map(|_| SccLine::Header)
@ -128,10 +127,10 @@ where
} }
/// Parser that accepts only an empty line /// Parser that accepts only an empty line
fn empty_line<'a, I: 'a>() -> impl Parser<Input = I, Output = SccLine> + 'a fn empty_line<'a, I: 'a>() -> impl Parser<I, Output = SccLine> + 'a
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
end_of_line() end_of_line()
.map(|_| SccLine::Empty) .map(|_| SccLine::Empty)
@ -140,10 +139,10 @@ where
/// A single SCC payload item. This is ASCII hex encoded bytes. /// A single SCC payload item. This is ASCII hex encoded bytes.
/// It returns an tuple of `(u8, u8)` of the hex encoded bytes. /// It returns an tuple of `(u8, u8)` of the hex encoded bytes.
fn scc_payload_item<'a, I: 'a>() -> impl Parser<Input = I, Output = (u8, u8)> fn scc_payload_item<'a, I: 'a>() -> impl Parser<I, Output = (u8, u8)>
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
((hex_digit(), hex_digit(), hex_digit(), hex_digit()).map(|(u, l, m, n)| { ((hex_digit(), hex_digit(), hex_digit(), hex_digit()).map(|(u, l, m, n)| {
let hex_to_u8 = |v: u8| match v { let hex_to_u8 = |v: u8| match v {
@ -182,10 +181,10 @@ impl Extend<(u8, u8)> for VecExtend {
} }
/// Parser for the whole SCC payload with conversion to the underlying byte values. /// Parser for the whole SCC payload with conversion to the underlying byte values.
fn scc_payload<'a, I: 'a>() -> impl Parser<Input = I, Output = Vec<u8>> + 'a fn scc_payload<'a, I: 'a>() -> impl Parser<I, Output = Vec<u8>> + 'a
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
many1( many1(
( (
@ -199,10 +198,10 @@ where
} }
/// Parser for a SCC caption line in the form `timecode\tpayload`. /// Parser for a SCC caption line in the form `timecode\tpayload`.
fn caption<'a, I: 'a>() -> impl Parser<Input = I, Output = SccLine> + 'a fn caption<'a, I: 'a>() -> impl Parser<I, Output = SccLine> + 'a
where where
I: RangeStream<Item = u8, Range = &'a [u8]>, I: RangeStream<Token = u8, Range = &'a [u8]>,
I::Error: ParseError<I::Item, I::Range, I::Position>, I::Error: ParseError<I::Token, I::Range, I::Position>,
{ {
(timecode(), token(b'\t'), scc_payload(), end_of_line()) (timecode(), token(b'\t'), scc_payload(), end_of_line())
.map(|(tc, _, value, _)| SccLine::Caption(tc, value)) .map(|(tc, _, value, _)| SccLine::Caption(tc, value))
@ -224,7 +223,7 @@ impl SccParser {
pub fn parse_line<'a>( pub fn parse_line<'a>(
&mut self, &mut self,
line: &'a [u8], line: &'a [u8],
) -> Result<SccLine, combine::easy::Errors<u8, &'a [u8], combine::stream::PointerOffset>> { ) -> Result<SccLine, combine::easy::ParseError<&'a [u8]>> {
match self.state { match self.state {
State::Header => header() State::Header => header()
.message("while in Header state") .message("while in Header state")