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}