summaryrefslogtreecommitdiffstats
path: root/vendor/gix-ignore/src/parse.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gix-ignore/src/parse.rs')
-rw-r--r--vendor/gix-ignore/src/parse.rs63
1 files changed, 63 insertions, 0 deletions
diff --git a/vendor/gix-ignore/src/parse.rs b/vendor/gix-ignore/src/parse.rs
new file mode 100644
index 000000000..11ceaabaf
--- /dev/null
+++ b/vendor/gix-ignore/src/parse.rs
@@ -0,0 +1,63 @@
+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
+ }
+}