63 lines · 1.6 KB · Rust
RawDownload
use bstr::ByteSlice; /// An iterator over line-wise ignore patterns parsed from a buffer.pub struct Lines<'a> {    lines: bstr::Lines<'a>,    line_no: usize,} impl<'a> Lines<'a> {    /// Create a new instance from `buf` to parse ignore patterns from.    pub fn new(buf: &'a [u8]) -> Self {        let bom = unicode_bom::Bom::from(buf);        Lines {            lines: buf[bom.len()..].lines(),            line_no: 0,        }    }} impl<'a> Iterator for Lines<'a> {    type Item = (gix_glob::Pattern, usize);     fn next(&mut self) -> Option<Self::Item> {        for line in self.lines.by_ref() {            self.line_no += 1;            if line.first() == Some(&b'#') {                continue;            }            match gix_glob::Pattern::from_bytes(truncate_non_escaped_trailing_spaces(line)) {                None => continue,                Some(pattern) => return Some((pattern, self.line_no)),            }        }        None    }} /// We always copy just because that's ultimately needed anyway, not because we always have to.fn truncate_non_escaped_trailing_spaces(buf: &[u8]) -> &[u8] {    let mut last_space_pos = None;    let mut bytes = buf.iter().enumerate();    while let Some((pos, b)) = bytes.next() {        match *b {            b' ' => {                last_space_pos.get_or_insert(pos);                continue;            }            b'\\' => {                if bytes.next().is_none() {                    return buf;                }            }            _ => {}        }        last_space_pos = None;    }     if let Some(pos) = last_space_pos {        &buf[..pos]    } else {        buf    }}