Repository: microsoft/edit
File: crates/edit/src/glob.rs (Rust)

Code before:
    let mut nx = 0;
    let mut next_px = 0;
    let mut next_nx = 0;
    let mut next_double_px = 0;
    let mut next_double_nx = 0;

    while px < glob.len() || nx < path.len() {
        if px < glob.len() {
            match glob[px] {
                b'?' => {
                    // single-character wildcard
                    if nx < path.len() && !is_separator(path[nx] as char) {
                        px += 1;
                        nx += 1;
                        continue;
                    }
                }
                b'*' => {
                    // Check for doublestar
                    if px + 1 < glob.len() && glob[px + 1] == b'*' {
                        // doublestar - matches across path separators
                        // Handle trailing slash after ** (e.g., **/ should skip the slash)
                        let skip = if px + 2 < glob.len() && glob[px + 2] == b'/' { 3 } else { 2 };
                        // Try to match at nx first (zero-length match). If that doesn't work, restart at nx+1.
                        next_double_px = px;
                        next_double_nx = nx + 1;
                        px += skip;
                    } else {
                        // single star - does not match path separators
                        // Try to match at nx. If that doesn't work out, restart at nx+1 next.
                        next_px = px;
                        next_nx = nx + 1;
                        px += 1;
                    }
                    continue;
                }
                c => {
                    // ordinary character
                    if nx < path.len() && path[nx].eq_ignore_ascii_case(&c) {
                        px += 1;
                        nx += 1;
                        continue;
                    }
                }
            }
        }

        // Mismatch. Maybe restart.
        // Try single-star backtracking first, but only if we don't cross a separator
        if 0 < next_nx && next_nx <= path.len() && !is_separator(path[next_nx - 1] as char) {
            px = next_px;

Review comment (bug):
clever. the main matching loop seeks forward and you've checkpointed where you were in the pattern and path to jump back and retry matching if it fails. avoids seeking the path and pattern forward in multiple places.

Code after:
        })
    }

    #[cfg(not(windows))]
    path.eq_ignore_ascii_case(suffix)
}

// This code is based on https://research.swtch.com/glob.go
// It's not particularly fast, but it doesn't need to be. It doesn't run often.
#[cold]
fn slow_path(pattern: &[u8], name: &[u8]) -> bool {
    let mut px = 0;
    let mut nx = 0;
    let mut next_px = 0;
    let mut next_nx = 0;
    let mut is_double_star = false;

    while px < pattern.len() || nx < name.len() {
        if px < pattern.len() {
            match pattern[px] {
                b'*' => {
                    // Try to match at nx. If that doesn't work out, restart at nx+1 next.
                    next_px = px;
                    next_nx = nx + 1;
                    px += 1;
                    is_double_star = false;

                    if px < pattern.len() && pattern[px] == b'*' {
                        px += 1;
                        is_double_star = true;

                        // For convenience, /**/ also matches /
                        if px >= 3
                            && px < pattern.len()
                            && pattern[px] == b'/'
                            && pattern[px - 3] == b'/'
                        {
                            px += 1;
                        }
                    }
                    continue;
                }
                c => {
                    if nx < name.len() && name[nx].eq_ignore_ascii_case(&c) {
                        px += 1;
                        nx += 1;
                        continue;
                    }
                }
            }
        }