mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
Replace the compiler's two cloned BTreeMap fields (alias_map and alias_modifiable) with a single Option<Rc<AliasRegistry>>. This eliminates cloning two 73K-entry maps on every compilation by sharing the registry through a reference-counted pointer. Additional improvements: - alias_map()/alias_modifiable_map() return &BTreeMap (zero-copy) - Safe .get() indexing in ingest_alias_entries and build_object_from_keys - Null-tolerant deserialization for AliasEntry.paths (~97% of real Azure catalog entries emit "paths": null) All changes are within the azure_policy feature gate. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
155 lines
5.9 KiB
Rust
155 lines
5.9 KiB
Rust
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
#![allow(dead_code)]
|
|
|
|
//! Azure Policy AST → RVM compiler.
|
|
//!
|
|
//! The compiler is split across several files:
|
|
//! - [`core`]: `Compiler` struct, main pipeline, register/emit helpers
|
|
//! - [`conditions`]: constraint / condition / LHS compilation
|
|
//! - [`conditions_wildcard`]: implicit allOf for unbound `[*]` fields
|
|
//! - [`count`]: `count` / `count.where` loops, existence-pattern optimization,
|
|
//! count-binding resolution and `current()` references
|
|
//! - [`expressions`]: template-expression and call-expression compilation
|
|
//! - [`fields`]: field-kind and resource-path compilation
|
|
//! - [`template_dispatch`]: ARM template function dispatch
|
|
//! - [`effects`]: effect compilation (dispatch + cross-resource)
|
|
//! - [`effects_modify_append`]: Modify / Append detail compilation
|
|
//! - [`metadata`]: annotation accumulation and population
|
|
//! - [`utils`]: pure helper functions (path splitting, JSON conversion)
|
|
|
|
mod conditions;
|
|
mod conditions_wildcard;
|
|
mod core;
|
|
mod count;
|
|
mod effects;
|
|
mod effects_modify_append;
|
|
mod expressions;
|
|
mod fields;
|
|
mod metadata;
|
|
mod template_dispatch;
|
|
mod utils;
|
|
|
|
use alloc::string::ToString as _;
|
|
|
|
use anyhow::Result;
|
|
|
|
use crate::languages::azure_policy::aliases::AliasRegistry;
|
|
use crate::languages::azure_policy::ast::{PolicyDefinition, PolicyRule};
|
|
use crate::rvm::program::Program;
|
|
use crate::{Rc, Value};
|
|
|
|
use self::core::Compiler;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Helpers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Initialise compiler language metadata and effect annotation.
|
|
fn init_effect_annotation(compiler: &mut Compiler, rule: &PolicyRule) {
|
|
compiler.program.metadata.language = "azure_policy".to_string();
|
|
let effect = compiler.resolve_effect_annotation(rule);
|
|
compiler
|
|
.program
|
|
.metadata
|
|
.annotations
|
|
.insert("effect".to_string(), Value::String(effect.as_str().into()));
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Public entry points
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Compile a parsed Azure Policy rule into an RVM program.
|
|
pub fn compile_policy_rule(rule: &PolicyRule) -> Result<Rc<Program>> {
|
|
let mut compiler = Compiler::new();
|
|
init_effect_annotation(&mut compiler, rule);
|
|
compiler.compile(rule)
|
|
}
|
|
|
|
/// Compile a parsed Azure Policy rule with alias resolution.
|
|
///
|
|
/// The registry provides alias-to-short-name resolution and modifiability
|
|
/// data. Pass it as an `Rc` to avoid cloning the internal alias maps.
|
|
pub fn compile_policy_rule_with_aliases(
|
|
rule: &PolicyRule,
|
|
registry: Rc<AliasRegistry>,
|
|
) -> Result<Rc<Program>> {
|
|
let mut compiler = Compiler::new();
|
|
compiler.alias_registry = Some(registry);
|
|
init_effect_annotation(&mut compiler, rule);
|
|
compiler.compile(rule)
|
|
}
|
|
|
|
/// Compile a parsed Azure Policy definition into an RVM program.
|
|
///
|
|
/// This extracts the `policyRule` from the definition and compiles it.
|
|
/// Parameter `defaultValue`s are collected so that later compiler passes
|
|
/// (effect compilation, metadata population) can reference them.
|
|
pub fn compile_policy_definition(defn: &PolicyDefinition) -> Result<Rc<Program>> {
|
|
let mut compiler = Compiler::new();
|
|
compiler.parameter_defaults = Some(build_parameter_defaults(&defn.parameters)?);
|
|
compiler.populate_definition_metadata(defn);
|
|
init_effect_annotation(&mut compiler, &defn.policy_rule);
|
|
compiler.compile(&defn.policy_rule)
|
|
}
|
|
|
|
/// Compile a parsed Azure Policy definition with alias resolution.
|
|
pub fn compile_policy_definition_with_aliases(
|
|
defn: &PolicyDefinition,
|
|
registry: Rc<AliasRegistry>,
|
|
) -> Result<Rc<Program>> {
|
|
let mut compiler = Compiler::new();
|
|
compiler.alias_registry = Some(registry);
|
|
compiler.parameter_defaults = Some(build_parameter_defaults(&defn.parameters)?);
|
|
compiler.populate_definition_metadata(defn);
|
|
init_effect_annotation(&mut compiler, &defn.policy_rule);
|
|
compiler.compile(&defn.policy_rule)
|
|
}
|
|
|
|
/// Compile a parsed Azure Policy definition with alias resolution and
|
|
/// optional fallback behaviour for unknown aliases.
|
|
///
|
|
/// When `alias_fallback_to_raw` is `true`, field paths that do not resolve to
|
|
/// a known alias are silently treated as raw property paths.
|
|
pub fn compile_policy_definition_with_aliases_opts(
|
|
defn: &PolicyDefinition,
|
|
registry: Rc<AliasRegistry>,
|
|
alias_fallback_to_raw: bool,
|
|
) -> Result<Rc<Program>> {
|
|
let mut compiler = Compiler::new();
|
|
compiler.alias_registry = Some(registry);
|
|
compiler.alias_fallback_to_raw = alias_fallback_to_raw;
|
|
compiler.parameter_defaults = Some(build_parameter_defaults(&defn.parameters)?);
|
|
compiler.populate_definition_metadata(defn);
|
|
init_effect_annotation(&mut compiler, &defn.policy_rule);
|
|
compiler.compile(&defn.policy_rule)
|
|
}
|
|
|
|
/// Build a `Value::Object` of `{ param_name: defaultValue }` from
|
|
/// the parsed parameter definitions.
|
|
fn build_parameter_defaults(
|
|
params: &[crate::languages::azure_policy::ast::ParameterDefinition],
|
|
) -> Result<Value> {
|
|
use crate::languages::azure_policy::compiler::expressions::check_json_depth;
|
|
use crate::languages::azure_policy::compiler::utils::json_value_to_runtime;
|
|
use alloc::format;
|
|
use anyhow::Context as _;
|
|
let mut obj = Value::new_object();
|
|
let map = obj.as_object_mut()?;
|
|
for param in params {
|
|
if let Some(ref default_val) = param.default_value {
|
|
check_json_depth(default_val, 0).with_context(|| {
|
|
format!(
|
|
"invalid defaultValue for parameter '{}': exceeds maximum JSON depth",
|
|
param.name
|
|
)
|
|
})?;
|
|
let runtime_val = json_value_to_runtime(default_val)
|
|
.with_context(|| format!("invalid defaultValue for parameter '{}'", param.name))?;
|
|
map.insert(Value::from(param.name.clone()), runtime_val);
|
|
}
|
|
}
|
|
Ok(obj)
|
|
}
|