Skip to content

Commit 985c31d

Browse files
authored
Merge branch 'servo:master' into tests-only
2 parents d241598 + 3e6b3d4 commit 985c31d

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

src/parser.rs

+40-4
Original file line numberDiff line numberDiff line change
@@ -639,17 +639,49 @@ impl<'i: 't, 't> Parser<'i, 't> {
639639
/// Parse a list of comma-separated values, all with the same syntax.
640640
///
641641
/// The given closure is called repeatedly with a "delimited" parser
642-
/// (see the `Parser::parse_until_before` method)
643-
/// so that it can over consume the input past a comma at this block/function nesting level.
642+
/// (see the `Parser::parse_until_before` method) so that it can over
643+
/// consume the input past a comma at this block/function nesting level.
644644
///
645645
/// Successful results are accumulated in a vector.
646646
///
647647
/// This method returns `Err(())` the first time that a closure call does,
648-
/// or if a closure call leaves some input before the next comma or the end of the input.
648+
/// or if a closure call leaves some input before the next comma or the end
649+
/// of the input.
649650
#[inline]
650651
pub fn parse_comma_separated<F, T, E>(
652+
&mut self,
653+
parse_one: F,
654+
) -> Result<Vec<T>, ParseError<'i, E>>
655+
where
656+
F: for<'tt> FnMut(&mut Parser<'i, 'tt>) -> Result<T, ParseError<'i, E>>,
657+
{
658+
self.parse_comma_separated_internal(parse_one, /* ignore_errors = */ false)
659+
}
660+
661+
/// Like `parse_comma_separated`, but ignores errors on unknown components,
662+
/// rather than erroring out in the whole list.
663+
///
664+
/// Caller must deal with the fact that the resulting list might be empty,
665+
/// if there's no valid component on the list.
666+
#[inline]
667+
pub fn parse_comma_separated_ignoring_errors<F, T, E: 'i>(
668+
&mut self,
669+
parse_one: F,
670+
) -> Vec<T>
671+
where
672+
F: for<'tt> FnMut(&mut Parser<'i, 'tt>) -> Result<T, ParseError<'i, E>>,
673+
{
674+
match self.parse_comma_separated_internal(parse_one, /* ignore_errors = */ true) {
675+
Ok(values) => values,
676+
Err(..) => unreachable!(),
677+
}
678+
}
679+
680+
#[inline]
681+
fn parse_comma_separated_internal<F, T, E>(
651682
&mut self,
652683
mut parse_one: F,
684+
ignore_errors: bool,
653685
) -> Result<Vec<T>, ParseError<'i, E>>
654686
where
655687
F: for<'tt> FnMut(&mut Parser<'i, 'tt>) -> Result<T, ParseError<'i, E>>,
@@ -661,7 +693,11 @@ impl<'i: 't, 't> Parser<'i, 't> {
661693
let mut values = Vec::with_capacity(1);
662694
loop {
663695
self.skip_whitespace(); // Unnecessary for correctness, but may help try() in parse_one rewind less.
664-
values.push(self.parse_until_before(Delimiter::Comma, &mut parse_one)?);
696+
match self.parse_until_before(Delimiter::Comma, &mut parse_one) {
697+
Ok(v) => values.push(v),
698+
Err(e) if !ignore_errors => return Err(e),
699+
Err(_) => {},
700+
}
665701
match self.next() {
666702
Err(_) => return Ok(values),
667703
Ok(&Token::Comma) => continue,

src/tests.rs

+14
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,20 @@ fn nth() {
429429
});
430430
}
431431

432+
#[test]
433+
fn parse_comma_separated_ignoring_errors() {
434+
let input = "red, green something, yellow, whatever, blue";
435+
let mut input = ParserInput::new(input);
436+
let mut input = Parser::new(&mut input);
437+
let result = input.parse_comma_separated_ignoring_errors(|input| {
438+
Color::parse(input).map_err(Into::<ParseError<()>>::into)
439+
});
440+
assert_eq!(result.len(), 3);
441+
assert_eq!(result[0].to_css_string(), "rgb(255, 0, 0)");
442+
assert_eq!(result[1].to_css_string(), "rgb(255, 255, 0)");
443+
assert_eq!(result[2].to_css_string(), "rgb(0, 0, 255)");
444+
}
445+
432446
#[test]
433447
fn unicode_range() {
434448
run_json_tests(include_str!("css-parsing-tests/urange.json"), |input| {

0 commit comments

Comments
 (0)