Repository: starship/starship
File: src/context.rs (Rust)

Code before:
    #[must_use]
    pub const fn set_files(mut self, files: &'a [&'a str]) -> Self {
        self.files = files;
        self
    }

    #[must_use]
    pub const fn set_folders(mut self, folders: &'a [&'a str]) -> Self {
        self.folders = folders;
        self
    }

    /// Scans upwards starting from the initial path until a directory containing one of the given
    /// files or folders is found.
    ///
    /// The scan does not cross device boundaries.
    pub fn scan(&self) -> Option<&'a Path> {
        let path = self.path;
        let initial_device_id = path.device_id();

        // We want to avoid reallocations during the search so we pre-allocate a buffer with enough
        // capacity to hold the longest path + any marker (we could find the length of the longest
        // marker programmatically but that would actually cost more than preallocating a few bytes too many).
        let mut buf = PathBuf::with_capacity(path.as_os_str().len() + 15);

        for dir in path.ancestors() {
            if initial_device_id != dir.device_id() {
                break;
            }
            // Then for each dir, we do `dir`, clearing in case `dir` is not an absolute path for
            // some reason
            buf.clear();
            buf.push(dir);

            for file in self.files {
                // Then for each file, we look for `dir/file`
                buf.push(file);

                if buf.is_file() {
                    return Some(dir);
                }

                // Removing the last pushed item means removing `file`, to replace it with either
                // the next `file` or the first `folder`, if any
                buf.pop();
            }

            for folder in self.folders {
                // Then for each folder, we look for `dir/folder`
                buf.push(folder);


Review comment (performance):
I don't like all the manual state management, but I suppose the performance speed-up is worth it.

But to at least avoid the management of two path buffers, I would prefer to return a `PathBuf` and `pop()` it once for iteration (This may need to be `loop if` pseudo `do while`-loop to handle the initial level, but ideally that would re-use the cwd scan anyway)
```suggestion
        let mut dir = PathBuf::with_capacity(path.as_os_str().len() + 15);
        dir.push(self.path);
        while dir.pop() {
```

FWIW mimalloc also manages similar performance without code changes.

Code after:
    #[must_use]
    pub const fn set_files(mut self, files: &'a [&'a str]) -> Self {
        self.files = files;
        self
    }

    #[must_use]
    pub const fn set_folders(mut self, folders: &'a [&'a str]) -> Self {
        self.folders = folders;
        self
    }

    /// Scans upwards starting from the initial path until a directory containing one of the given
    /// files or folders is found.
    ///
    /// The scan does not cross device boundaries.
    pub fn scan(&self) -> Option<PathBuf> {
        let path = self.path;
        let initial_device_id = path.device_id();

        // We want to avoid reallocations during the search so we pre-allocate a buffer with enough
        // capacity to hold the longest path + any marker (we could find the length of the longest
        // marker programmatically but that would actually cost more than preallocating a few bytes too many).
        let mut buf = PathBuf::with_capacity(path.as_os_str().len() + 15);
        path.clone_into(&mut buf);

        loop {
            if initial_device_id != buf.device_id() {
                break;
            }

            for file in self.files {
                // Then for each file, we look for `buf/file`
                buf.push(file);

                if buf.is_file() {
                    buf.pop();
                    return Some(buf);
                }

                // Removing the last pushed item means removing `file`, to replace it with either
                // the next `file` or the first `folder`, if any
                buf.pop();
            }

            for folder in self.folders {
                // Then for each folder, we look for `buf/folder`
                buf.push(folder);

                if buf.is_dir() {
                    buf.pop();