fn next()

in src/compiler/msvc.rs [1304:1368]


    fn next(&mut self) -> Option<String> {
        let mut in_quotes = false;
        let mut backslash_count: usize = 0;

        // Strip any leading whitespace before relevant characters
        let is_whitespace = |c| matches!(c, ' ' | '\t' | '\n' | '\r');
        self.file_content = self.file_content.trim_start_matches(is_whitespace);

        if self.file_content.is_empty() {
            return None;
        }

        // The argument string to return, built by analyzing the current slice in the iterator.
        let mut arg = String::new();
        // All characters still in the string slice. Will be mutated by consuming
        // values until the current arg is built.
        let mut chars = self.file_content.chars();
        // Build the argument by evaluating each character in the string slice.
        for c in &mut chars {
            match c {
                // In order to handle the escape character based on the char(s) which come after it,
                // they are counted instead of appended literally, until a non-backslash character is encountered.
                '\\' => backslash_count += 1,
                // Either starting or ending a quoted argument, or appending a literal character (if the quote was escaped).
                '"' => {
                    // Only append half the number of backslashes encountered, because this is an escaped string.
                    // This will reduce `backslash_count` to either 0 or 1.
                    Self::append_backslashes_to(&mut arg, &mut backslash_count, 2);
                    match backslash_count == 0 {
                        // If there are no remaining encountered backslashes,
                        // then we have found either the start or end of a quoted argument.
                        true => in_quotes = !in_quotes,
                        // The quote character is escaped, so it is treated as a literal and appended to the arg string.
                        false => {
                            backslash_count = 0;
                            arg.push('"');
                        }
                    }
                }
                // If whitespace is encountered, only preserve it if we are currently in quotes.
                // Otherwise it marks the end of the current argument.
                ' ' | '\t' | '\n' | '\r' => {
                    Self::append_backslashes_to(&mut arg, &mut backslash_count, 1);
                    // If not in a quoted string, then this is the end of the argument.
                    if !in_quotes {
                        break;
                    }
                    // Otherwise, the whitespace must be preserved in the argument.
                    arg.push(c);
                }
                // All other characters treated as is
                _ => {
                    Self::append_backslashes_to(&mut arg, &mut backslash_count, 1);
                    arg.push(c);
                }
            }
        }

        // Flush any backslashes at the end of the string.
        Self::append_backslashes_to(&mut arg, &mut backslash_count, 1);
        // Save the current remaining characters for the next step in the iterator.
        self.file_content = chars.as_str();

        Some(arg)
    }