Share prefix pattern data in execpolicy2 instead of cloning

This commit is contained in:
kevin zhao
2025-11-12 16:51:18 -05:00
parent 0f51ed0baa
commit 7b5916cb4b
2 changed files with 14 additions and 10 deletions

View File

@@ -12,6 +12,7 @@ use starlark::values::Value;
use starlark::values::list::ListRef;
use starlark::values::list::UnpackList;
use starlark::values::none::NoneType;
use std::sync::Arc;
use crate::decision::Decision;
use crate::error::Error;
@@ -209,11 +210,13 @@ fn policy_builtins(builder: &mut GlobalsBuilder) {
.split_first()
.ok_or_else(|| Error::InvalidPattern("pattern cannot be empty".to_string()))?;
let rest: Arc<[PatternToken]> = remaining_tokens.to_vec().into();
for head in first_token.alternatives() {
let rule = Rule::Prefix(PrefixRule {
pattern: PrefixPattern {
first: head,
rest: remaining_tokens.to_vec(),
first: Arc::from(head.as_str()),
rest: rest.clone(),
},
decision,
});

View File

@@ -4,6 +4,7 @@ use crate::error::Result;
use serde::Deserialize;
use serde::Serialize;
use shlex::try_join;
use std::sync::Arc;
/// Matches a single command token, either a fixed string or one of several allowed alternatives.
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -20,10 +21,10 @@ impl PatternToken {
}
}
pub fn alternatives(&self) -> Vec<String> {
pub fn alternatives(&self) -> &[String] {
match self {
Self::Single(expected) => vec![expected.clone()],
Self::Alts(alternatives) => alternatives.clone(),
Self::Single(expected) => std::slice::from_ref(expected),
Self::Alts(alternatives) => alternatives,
}
}
}
@@ -38,14 +39,14 @@ impl std::fmt::Display for PatternToken {
/// First token is fixed since we key by the first token in policy.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PrefixPattern {
pub first: String,
pub rest: Vec<PatternToken>,
pub first: Arc<str>,
pub rest: Arc<[PatternToken]>,
}
impl PrefixPattern {
pub fn matches_prefix(&self, cmd: &[String]) -> Option<Vec<String>> {
let pattern_length = self.rest.len() + 1;
if cmd.len() < pattern_length || cmd[0] != self.first {
if cmd.len() < pattern_length || cmd[0] != self.first.as_ref() {
return None;
}
@@ -122,7 +123,7 @@ impl std::fmt::Display for RuleMatch {
impl Rule {
pub fn program(&self) -> &str {
match self {
Self::Prefix(rule) => &rule.pattern.first,
Self::Prefix(rule) => rule.pattern.first.as_ref(),
}
}
@@ -192,7 +193,7 @@ fn join_command(command: &[String]) -> String {
}
fn render_pattern(pattern: &PrefixPattern) -> String {
let mut tokens = vec![pattern.first.clone()];
let mut tokens = vec![pattern.first.as_ref().to_string()];
tokens.extend(pattern.rest.iter().map(render_pattern_token));
tokens.join(", ")
}