ffmpeg_sidecar/
comma_iter.rs

1//! An internal utility used to parse comma-separated values in FFmpeg logs.
2
3use std::str::Chars;
4
5/// An iterator over comma-separated values, **ignoring commas inside parentheses**.
6///
7/// ## Examples
8///
9/// ```rust
10/// use ffmpeg_sidecar::comma_iter::CommaIter;
11///
12/// let string = "foo(bar,baz),quux";
13/// let mut iter = CommaIter::new(string);
14///
15/// assert_eq!(iter.next(), Some("foo(bar,baz)"));
16/// assert_eq!(iter.next(), Some("quux"));
17/// assert_eq!(iter.next(), None);
18/// ```
19pub struct CommaIter<'a> {
20  chars: Chars<'a>,
21}
22
23impl<'a> CommaIter<'a> {
24  pub fn new(string: &'a str) -> Self {
25    Self {
26      chars: string.chars(),
27    }
28  }
29}
30
31impl<'a> Iterator for CommaIter<'a> {
32  type Item = &'a str;
33
34  /// Return the next comma-separated section, not including the comma.
35  fn next(&mut self) -> Option<Self::Item> {
36    let chars_clone = self.chars.clone();
37    let mut i = 0;
38
39    while let Some(char) = self.chars.next() {
40      match char {
41        '(' => {
42          // advance until closing paren (only handles one level nesting)
43          for close_paren in self.chars.by_ref() {
44            i += 1;
45            if close_paren == ')' {
46              break;
47            }
48          }
49        }
50        ',' => break,
51        _ => {}
52      }
53      i += 1;
54    }
55
56    match i {
57      0 => None,
58      _ => Some(&chars_clone.as_str()[..i]),
59    }
60  }
61}