Path: blob/main/crates/wit-bindgen/src/config.rs
1693 views
use crate::{LookupItem, lookup_keys};1use anyhow::Result;2use wit_parser::{Function, FunctionKind, Resolve, WorldKey};34bitflags::bitflags! {5#[derive(Default, Copy, Clone, Debug)]6pub struct FunctionFlags: u8 {7const ASYNC = 1 << 0;8const TRAPPABLE = 1 << 1;9const STORE = 1 << 2;10const TRACING = 1 << 3;11const VERBOSE_TRACING = 1 << 4;12const IGNORE_WIT = 1 << 5;13const EXACT = 1 << 6;14}15}1617#[derive(Default, Debug, Clone)]18pub struct FunctionConfig {19rules: Vec<FunctionRule>,20default: FunctionFlags,21}2223#[derive(Debug, Clone)]24struct FunctionRule {25filter: String,26flags: FunctionFlags,27used: bool,28}2930#[derive(Debug, Clone)]31pub enum FunctionFilter {32Name(String),33Default,34}3536impl FunctionConfig {37/// Creates a blank set of configuration.38pub fn new() -> FunctionConfig {39FunctionConfig::default()40}4142/// Adds a new rule to this configuration.43///44/// Note that the order rules are added is significant as only the first45/// matching rule is used for a function.46pub fn push(&mut self, filter: FunctionFilter, flags: FunctionFlags) {47match filter {48FunctionFilter::Name(filter) => {49self.rules.push(FunctionRule {50filter,51flags,52used: false,53});54}55FunctionFilter::Default => {56self.default = flags;57}58}59}6061/// Returns the set of configuration flags associated with `func`.62///63/// The `name` provided should include the full name of the function64/// including its interface. The `kind` is the classification of the65/// function in WIT which affects the default set of flags.66pub(crate) fn flags(67&mut self,68resolve: &Resolve,69ns: Option<&WorldKey>,70func: &Function,71) -> FunctionFlags {72let mut wit_flags = FunctionFlags::empty();7374// If the kind is async, then set the async/store flags as that's a75// concurrent function which requires access to both.76match &func.kind {77FunctionKind::Freestanding78| FunctionKind::Method(_)79| FunctionKind::Static(_)80| FunctionKind::Constructor(_) => {}8182FunctionKind::AsyncFreestanding83| FunctionKind::AsyncMethod(_)84| FunctionKind::AsyncStatic(_) => {85wit_flags |= FunctionFlags::ASYNC | FunctionFlags::STORE;86}87}8889let mut ret = FunctionFlags::empty();90self.add_function_flags(resolve, ns, &func.name, &mut ret);91if !ret.contains(FunctionFlags::IGNORE_WIT) {92ret |= wit_flags;93}94ret95}9697pub(crate) fn resource_drop_flags(98&mut self,99resolve: &Resolve,100ns: Option<&WorldKey>,101resource_name: &str,102) -> FunctionFlags {103let mut ret = FunctionFlags::empty();104self.add_function_flags(resolve, ns, &format!("[drop]{resource_name}"), &mut ret);105ret106}107108fn add_function_flags(109&mut self,110resolve: &Resolve,111key: Option<&WorldKey>,112name: &str,113base: &mut FunctionFlags,114) {115let mut apply_rules = |name: &str, is_exact: bool| {116for rule in self.rules.iter_mut() {117if name != rule.filter {118continue;119}120if !is_exact && rule.flags.contains(FunctionFlags::EXACT) {121continue;122}123rule.used = true;124*base |= rule.flags;125126// only the first rule is used.127return true;128}129130false131};132match key {133Some(key) => {134for (lookup, projection) in lookup_keys(resolve, key, LookupItem::Name(name)) {135if apply_rules(&lookup, projection.is_empty()) {136return;137}138}139}140None => {141if apply_rules(name, true) {142return;143}144}145}146147*base |= self.default;148}149150pub(crate) fn assert_all_rules_used(&self, kind: &str) -> Result<()> {151let mut unused = Vec::new();152for rule in self.rules.iter().filter(|r| !r.used) {153unused.push(format!("{:?}: {:?}", rule.filter, rule.flags));154}155156if unused.is_empty() {157return Ok(());158}159160anyhow::bail!("unused `{kind}` rules found: {unused:?}");161}162}163164165