Repository: BurntSushi/ripgrep
File: grep/src/search.rs (Rust)

Code before:
    type Item = Match;

    fn next(&mut self) -> Option<Match> {
        let mut mat = Match::default();
        if !self.searcher.read_match(&mut mat, self.buf, self.start) {
            self.start = self.buf.len();
            return None;
        }
        self.start = mat.end;
        Some(mat)
    }
}

fn has_uppercase_literal(expr: &Expr) -> bool {
    use syntax::Expr::*;
    fn byte_is_upper(b: u8) -> bool { b'A' <= b && b <= b'Z' }
    match *expr {
        Literal { ref chars, casei } => {
            casei || chars.iter().any(|c| c.is_uppercase())
        }
        LiteralBytes { ref bytes, casei } => {
            casei || bytes.iter().any(|&b| byte_is_upper(b))
        }
        Class(ref ranges) => {
            for r in ranges {
                if r.start.is_uppercase() || r.end.is_uppercase() {
                    return true;
                }
            }
            false
        }
        ClassBytes(ref ranges) => {
            for r in ranges {
                if byte_is_upper(r.start) || byte_is_upper(r.end) {
                    return true;
                }
            }
            false
        }
        Group { ref e, .. } => has_uppercase_literal(e),
        Repeat { ref e, .. } => has_uppercase_literal(e),
        Concat(ref es) => es.iter().any(has_uppercase_literal),
        Alternate(ref es) => es.iter().any(has_uppercase_literal),
        _ => false,
    }
}

#[cfg(test)]
mod tests {
    #![allow(unused_imports)]


Review comment (suggestion):
This should just be `false` (no semi-colon) instead of `return false;`. :-)

Code after:
        }
        self.start = mat.end;
        Some(mat)
    }
}

/// Determine whether the pattern contains an uppercase character which should
/// negate the effect of the smart-case option.
///
/// Ideally we would be able to check the AST in order to correctly handle
/// things like '\p{Ll}' and '\p{Lu}' (which should be treated as explicitly
/// cased), but we don't currently have that option. For now, our 'good enough'
/// solution is to simply perform a semi-naïve scan of the input pattern and
/// ignore all characters following a '\'. The ExprBuilder will handle any
/// actual errors, and this at least lets us support the most common cases,
/// like 'foo\w' and 'foo\S', in an intuitive manner.
fn has_uppercase_literal(pattern: &str) -> bool {
    let mut chars = pattern.chars();
    while let Some(c) = chars.next() {
        if c == '\\' {
            chars.next();
        } else if c.is_uppercase() {
            return true;
        }
    }
    false
}

#[cfg(test)]
mod tests {
    #![allow(unused_imports)]

    use memchr::{memchr, memrchr};
    use regex::bytes::Regex;

    use super::{GrepBuilder, Match, has_uppercase_literal};

    static SHERLOCK: &'static [u8] = include_bytes!("./data/sherlock.txt");

    #[allow(dead_code)]
    fn s(bytes: &[u8]) -> String {
        String::from_utf8(bytes.to_vec()).unwrap()
    }

    fn find_lines(pat: &str, haystack: &[u8]) -> Vec<Match> {
        let re = Regex::new(pat).unwrap();
        let mut lines = vec![];
        for m in re.find_iter(haystack) {
            let start = memrchr(b'\n', &haystack[..m.start()])
                        .map_or(0, |i| i + 1);
            let end = memchr(b'\n', &haystack[m.end()..])