Repository: microsoft/onefuzz
File: src/agent/coverage/src/allowlist.rs (Rust)

Code before:
                    }
                }
                Err(err) => {
                    // Ignore invalid lines, but warn.
                    let line_number = index + 1;
                    warn!("error at line {}: {}", line_number, err);
                }
            }
        }

        let allow = RegexSet::new(allow.iter().map(|re| re.as_str()))?;
        let deny = RegexSet::new(deny.iter().map(|re| re.as_str()))?;
        let allowlist = AllowList::new(allow, deny);

        Ok(allowlist)
    }

    pub fn is_allowed(&self, path: impl AsRef<str>) -> bool {
        let path = path.as_ref();

        // Allowed if rule-allowed but not excluded by a negative (deny) rule.
        self.allow.is_match(path) && !self.deny.is_match(path)
    }

    /// Build a new `Allowlist` that adds the allow and deny rules of `other` to `self`.
    pub fn extend(&mut self, other: &Self) {
        let allow = add_regexsets(&self.allow, &other.allow);
        let deny = add_regexsets(&self.deny, &other.deny);

        self.allow = allow;
        self.deny = deny;
    }
}

fn add_regexsets(lhs: &RegexSet, rhs: &RegexSet) -> RegexSet {
    let mut patterns = lhs.patterns().to_vec();
    patterns.extend(rhs.patterns().iter().map(|s| s.to_owned()));

    // Can't panic: patterns were accepted by input `RegexSet` ctors.
    RegexSet::new(patterns).unwrap()
}

impl Default for AllowList {
    fn default() -> Self {
        // Unwrap-safe due to valid constant expr.
        let allow = RegexSet::new([".*"]).unwrap();
        let deny = RegexSet::empty();

        AllowList::new(allow, deny)
    }
}

Review comment (suggestion):
you are changing he semantic of this function here. i suggest you create a new one called `extend_in_place`. To indicate that the AllowList is updated instead of copied.

Code after:
                    }
                }
                Err(err) => {
                    // Ignore invalid lines, but warn.
                    let line_number = index + 1;
                    warn!("error at line {}: {}", line_number, err);
                }
            }
        }

        let allow = RegexSet::new(allow.iter().map(|re| re.as_str()))?;
        let deny = RegexSet::new(deny.iter().map(|re| re.as_str()))?;
        let allowlist = AllowList::new(allow, deny);

        Ok(allowlist)
    }

    pub fn is_allowed(&self, path: impl AsRef<str>) -> bool {
        let path = path.as_ref();

        // Allowed if rule-allowed but not excluded by a negative (deny) rule.
        self.allow.is_match(path) && !self.deny.is_match(path)
    }

    /// Modifies the AllowList by adding the allow and deny rules of `other` to `self`.
    pub fn extend_in_place(&mut self, other: &Self) {
        let allow = add_regexsets(&self.allow, &other.allow);
        let deny = add_regexsets(&self.deny, &other.deny);

        self.allow = allow;
        self.deny = deny;
    }
}

fn add_regexsets(lhs: &RegexSet, rhs: &RegexSet) -> RegexSet {
    let mut patterns = lhs.patterns().to_vec();
    patterns.extend(rhs.patterns().iter().map(|s| s.to_owned()));

    // Can't panic: patterns were accepted by input `RegexSet` ctors.
    RegexSet::new(patterns).unwrap()
}

impl Default for AllowList {
    fn default() -> Self {
        // Unwrap-safe due to valid constant expr.
        let allow = RegexSet::new([".*"]).unwrap();
        let deny = RegexSet::empty();

        AllowList::new(allow, deny)
    }
}