use candor_report::EFFECTS;
pub mod policy;
#[cfg(test)]
mod policy_props;
pub mod surface;
pub mod propagate;
pub mod gate;
pub mod accept;
pub fn classify_extra(
crate_name: &str,
path: &str,
extra: &[(&'static str, bool, String)],
) -> Option<&'static str> {
for (eff, is_crate, prefix) in extra {
let hit = if *is_crate { crate_name.starts_with(prefix.as_str()) } else { path.starts_with(prefix.as_str()) };
if hit {
return Some(eff);
}
}
None
}
pub const CALIBRATED_CRATES: [&str; 82] = [
"reqwest", "isahc", "ureq", "curl", "aws_config", "git2", "tokio_tcp", "tokio_udp", "async_net",
"async_nats", "lapin", "lettre", "tungstenite", "elasticsearch", "tonic", "rdkafka", "pnet",
"ignore", "notify",
"sqlx", "rusqlite", "postgres", "tokio_postgres", "diesel", "redis", "mongodb",
"mysql", "mysql_async", "sea_orm", "deadpool_postgres",
"memmap2", "fs_err", "async_fs", "tempfile", "glob",
"rand", "getrandom", "fastrand",
"argon2", "bcrypt", "scrypt", "pbkdf2", "password_hash", "rand_core",
"portable_pty", "async_process", "duct",
"dotenvy", "dotenv",
"chrono", "time", "tracing", "log", "arboard",
"rustc_lint", "rustc_errors",
"libc", "nix", "rustix",
"rustls", "native_tls_crate", "tokio_native_tls",
"etcetera", "wild", "lscolors",
"sqlx_core", "walkdir", "filetime", "clircle",
"execute", "ctrlc", "clap", "jiff", "env_logger",
"dialoguer", "console", "terminal_colorsaurus", "backoff", "grep_cli",
"crossterm", "ratatui",
"tracing_subscriber",
];
pub const CALIBRATED_PREFIXES: [&str; 3] = ["aws_sdk_", "aws_smithy", "cap_"];
pub const PATH_CALIBRATED_CRATES: [&str; 3] = ["tokio", "async_std", "mio"];
pub const CALIBRATED_BUT_PARTIAL_CRATES: [&str; 3] = ["libc", "nix", "rustix"];
pub const CALIBRATED_CEILINGS: [(&str, &str); 70] = [
("arboard", "3.6.1"),
("argon2", "0.6.0"),
("async_nats", "0.35.1"),
("async_process", "2.5.0"),
("aws_config", "1.12.0"),
("backoff", "0.4.0"),
("bcrypt", "0.19.3"),
("chrono", "0.4.45"),
("clap", "4.6.6"),
("clircle", "0.6.1"),
("console", "0.15.11"),
("crossterm", "0.28.1"),
("ctrlc", "3.5.2"),
("curl", "0.4.50"),
("deadpool_postgres", "0.14.2"),
("dialoguer", "0.12.0"),
("diesel", "2.3.13"),
("dotenv", "0.15.0"),
("dotenvy", "0.15.7"),
("duct", "1.1.2"),
("elasticsearch", "8.19.0-alpha.1"),
("env_logger", "0.11.11"),
("etcetera", "0.11.0"),
("execute", "0.3.0"),
("fastrand", "2.5.0"),
("filetime", "0.2.29"),
("fs_err", "3.3.1"),
("git2", "0.20.4"),
("glob", "0.3.4"),
("grep_cli", "0.1.12"),
("ignore", "0.4.33"),
("isahc", "2.0.1"),
("jiff", "0.2.35"),
("lapin", "4.10.0"),
("lettre", "0.11.23"),
("log", "0.4.34"),
("lscolors", "0.21.0"),
("memmap2", "0.9.11"),
("mongodb", "3.8.1"),
("mysql", "28.0.0"),
("mysql_async", "0.37.0"),
("native_tls_crate", "0.2.18"),
("notify", "8.2.0"),
("password_hash", "0.6.1"),
("pbkdf2", "0.13.0"),
("pnet", "0.35.0"),
("portable_pty", "0.9.0"),
("rand", "0.10.2"),
("ratatui", "0.29.0"),
("rdkafka", "0.39.0"),
("redis", "1.6.0"),
("reqwest", "0.13.4"),
("rusqlite", "0.39"),
("rustls", "0.23.43"),
("scrypt", "0.12.0"),
("sea_orm", "1.1.20"),
("sqlx", "0.9.0"),
("sqlx_core", "0.9.0"),
("tempfile", "3.27.0"),
("terminal_colorsaurus", "1.0.3"),
("time", "0.3.55"),
("tokio_native_tls", "0.3.1"),
("tokio_postgres", "0.7.18"),
("tonic", "0.12.3"),
("tracing", "0.1.44"),
("tracing_subscriber", "0.3.23"),
("tungstenite", "0.30.0"),
("ureq", "2.12.1"),
("walkdir", "2.5.0"),
("wild", "2.2.1"),
];
pub fn calibration_exceeded_raw(a: &str, b: &str) -> bool {
let parts = |v: &str| -> Vec<u64> {
v.split(['+', '-']).next().unwrap_or("")
.split('.')
.map(|p| p.parse::<u64>().unwrap_or(0))
.collect()
};
let (x, y) = (parts(a), parts(b));
for i in 0..x.len().max(y.len()) {
let (p, q) = (x.get(i).copied().unwrap_or(0), y.get(i).copied().unwrap_or(0));
if p != q {
return p > q;
}
}
a != b
}
pub fn calibration_exceeded(crate_name: &str, resolved: &str) -> bool {
let Some((_, ceiling)) = CALIBRATED_CEILINGS.iter().find(|(c, _)| *c == crate_name) else {
return false;
};
let parts = |v: &str| -> Vec<u64> {
v.split(['+', '-']).next().unwrap_or("")
.split('.')
.map(|p| p.parse::<u64>().unwrap_or(0))
.collect()
};
let (r, c) = (parts(resolved), parts(ceiling));
if r.is_empty() {
return false;
}
for i in 0..r.len().max(c.len()) {
let (a, b) = (r.get(i).copied().unwrap_or(0), c.get(i).copied().unwrap_or(0));
if a != b {
return a > b;
}
}
let suffix = |v: &str| -> String { v.find(['+', '-']).map(|i| v[i..].to_string()).unwrap_or_default() };
suffix(resolved) != suffix(ceiling)
}
pub const REVIEWED_PURE_CRATES: [&str; 5] = ["serde_json", "serde_yml", "toml", "regex", "sha2"];
pub const REVIEWED_PURE_ENTRIES: &[(&str, &str)] = &[
("curl", "curl::Multi::timeout"),
("execute", "execute::command"),
("execute", "execute::shell"),
("elasticsearch", "elasticsearch::Response::content_type"),
("rusqlite", "rusqlite::Context::get_connection"),
("dialoguer", "dialoguer::Paging::render_prompt"),
("mysql", "mysql::Stream::connect_socket"),
("ureq", "ureq::Agent::new_with_config"),
("ureq", "ureq::Agent::with_parts"),
("chrono", "chrono::DateTime::fixed_offset"),
("chrono", "chrono::DateTime::years_since"),
("chrono", "chrono::DateTime::parse_and_remainder"),
("chrono", "chrono::DateTime::parse_from_rfc2822"),
("chrono", "chrono::DateTime::parse_from_rfc3339"),
("chrono", "chrono::DateTime::parse_from_str"),
("chrono", "chrono::Parsed::to_datetime"),
("mysql_async", "mysql_async::Arc::to_statement"),
("mysql_async", "mysql_async::Box::to_statement"),
("mysql_async", "mysql_async::Cow::to_statement"),
("mysql_async", "mysql_async::String::to_statement"),
("mysql_async", "mysql_async::Vec::to_statement"),
("sqlx_core", "sqlx_core::pool::connection::PoolConnection::detach"),
("sqlx_core", "sqlx_core::pool::connection::PoolConnection::leak"),
("redis", "redis::client::Client::build_with_tls"),
("redis", "redis::cluster_handling::client::ClusterClientBuilder::build"),
("lettre", "lettre::transport::smtp::transport::SmtpTransport::unencrypted_localhost"),
("lettre", "lettre::transport::smtp::async_transport::AsyncSmtpTransport::unencrypted_localhost"),
("lapin", "lapin::channel::Channel::wait_for_confirms"),
("mysql", "mysql::conn::pool::PooledConn::unwrap"),
("reqwest", "reqwest::async_impl::h3_client::pool::PoolClient::send_request"),
];
pub const OPEN_ENTRY_VERDICTS: &[(&str, &str, &str)] = &[
("ureq", "ureq::unversioned::transport::Box::await_input", "R1554:conditional"),
("ureq", "ureq::unversioned::transport::Box::is_open", "R1554:conditional"),
("ureq", "ureq::unversioned::transport::Box::transmit_output", "R1554:conditional"),
("ureq", "ureq::unversioned::transport::chain::ChainedConnector::connect", "R1554:conditional"),
("ureq", "ureq::config::ConfigBuilder::accept", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::accept_encoding", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::allow_non_standard_methods", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::http_status_as_error", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::https_only", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::input_buffer_size", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::ip_family", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::max_idle_age", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::max_idle_connections", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::max_idle_connections_per_host", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::max_redirects", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::max_redirects_will_error", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::max_response_header_size", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::middleware", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::no_delay", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::output_buffer_size", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::proxy", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::redirect_auth_headers", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::save_redirect_history", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::timeout_await_100", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::timeout_connect", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::timeout_global", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::timeout_per_call", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::timeout_recv_body", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::timeout_recv_response", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::timeout_resolve", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::timeout_send_body", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::timeout_send_request", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::tls_config", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::user_agent", "R1553:conditional"),
("ureq", "ureq::unversioned::transport::chain::Either::await_input", "R1554:conditional"),
("ureq", "ureq::unversioned::transport::chain::Either::is_open", "R1554:conditional"),
("ureq", "ureq::unversioned::transport::chain::Either::transmit_output", "R1554:conditional"),
("ureq", "ureq::config::typestate::RequestScope::config", "R1553:conditional"),
("ureq", "ureq::connect", "R1555:silent"),
("ureq", "ureq::delete", "R1555:silent"),
("ureq", "ureq::get", "R1555:silent"),
("ureq", "ureq::head", "R1555:silent"),
("ureq", "ureq::options", "R1555:silent"),
("ureq", "ureq::patch", "R1555:silent"),
("ureq", "ureq::post", "R1555:silent"),
("ureq", "ureq::put", "R1555:silent"),
("ureq", "ureq::trace", "R1555:silent"),
("chrono", "chrono::date::Date::with_timezone", "R1557:conditional"),
("chrono", "chrono::datetime::DateTime::checked_add_months", "R1557:conditional"),
("chrono", "chrono::datetime::DateTime::checked_sub_months", "R1557:conditional"),
("chrono", "chrono::round::DateTime::duration_round", "R1557:conditional"),
("chrono", "chrono::round::DateTime::duration_round_up", "R1557:conditional"),
("chrono", "chrono::round::DateTime::duration_trunc", "R1557:conditional"),
("chrono", "chrono::datetime::DateTime::with_timezone", "R1557:conditional"),
("chrono", "chrono::naive::datetime::NaiveDateTime::and_local_timezone", "R1557:conditional"),
("chrono", "chrono::format::parsed::Parsed::to_datetime_with_timezone", "R1557:conditional"),
("tracing_subscriber", "tracing_subscriber::layer::context::Context::event", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::filter::layer_filters::Filtered::on_close", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::filter::layer_filters::Filtered::on_enter", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::filter::layer_filters::Filtered::on_event", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::filter::layer_filters::Filtered::on_exit", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::filter::layer_filters::Filtered::on_new_span", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::fmt::format::json::Format::format_event", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::fmt::format::Format::format_event", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::fmt::format::pretty::Format::format_event", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::fmt::fmt_layer::Layer::on_close", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::fmt::fmt_layer::Layer::on_enter", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::fmt::fmt_layer::Layer::on_event", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::fmt::fmt_layer::Layer::on_exit", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::fmt::fmt_layer::Layer::on_new_span", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::layer::layered::Layered::on_close", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::layer::layered::Layered::on_enter", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::layer::layered::Layered::on_event", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::layer::layered::Layered::on_exit", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::layer::layered::Layered::on_new_span", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::layer::Option::on_close", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::layer::Option::on_enter", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::layer::Option::on_event", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::layer::Option::on_exit", "R1558:conditional"),
("tracing_subscriber", "tracing_subscriber::layer::Option::on_new_span", "R1558:conditional"),
("jiff", "jiff::fmt::strtime::BrokenDownTime::to_zoned_with", "R1559:conditional"),
("jiff", "jiff::fmt::temporal::pieces::Pieces::to_time_zone_with", "R1559:conditional"),
("jiff", "jiff::fmt::temporal::pieces::TimeZoneAnnotation::to_time_zone_with", "R1559:conditional"),
("jiff", "jiff::tz::db::TimeZoneDatabase::bundled", "R1559:conditional"),
("sea_orm", "sea_orm::query::loader::Vec::load_many", "R1570:silent"),
("sea_orm", "sea_orm::query::loader::Vec::load_one", "R1570:silent"),
("sea_orm", "sea_orm::query::loader::Vec::load_self", "R1570:silent"),
("sea_orm", "sea_orm::query::loader::Vec::load_self_many", "R1570:silent"),
("sea_orm", "sea_orm::query::loader::Vec::load_self_via", "R1570:silent"),
("sea_orm", "sea_orm::query::loader::Vec::load_self_via_rev", "R1570:silent"),
("sea_orm", "sea_orm::driver::rusqlite::RusqliteSharedConnection::acquire", "R1571:silent"),
("sea_orm", "sea_orm::driver::rusqlite::RusqliteSharedConnection::begin", "R1571:silent"),
("sea_orm", "sea_orm::driver::rusqlite::RusqliteSharedConnection::close", "R1571:silent"),
("sea_orm", "sea_orm::driver::rusqlite::RusqliteSharedConnection::close_by_ref", "R1571:silent"),
("sea_orm", "sea_orm::driver::rusqlite::RusqliteSharedConnection::ping", "R1571:silent"),
("sea_orm", "sea_orm::driver::rusqlite::RusqliteSharedConnection::transaction", "R1571:silent"),
("async_nats", "async_nats::jetstream::new", "R1576:silent"),
("async_nats", "async_nats::jetstream::with_domain", "R1576:silent"),
("async_nats", "async_nats::jetstream::with_prefix", "R1576:silent"),
("async_nats", "async_nats::jetstream::context::ContextBuilder::build", "R1576:silent"),
("rdkafka", "rdkafka::consumer::base_consumer::BaseConsumer::assignment", "R1582:silent"),
("rdkafka", "rdkafka::consumer::base_consumer::BaseConsumer::close_queue", "R1583:conditional"),
("rdkafka", "rdkafka::consumer::base_consumer::BaseConsumer::incremental_unassign", "R1582:silent"),
("rdkafka", "rdkafka::consumer::base_consumer::BaseConsumer::position", "R1582:silent"),
("rdkafka", "rdkafka::consumer::base_consumer::BaseConsumer::subscription", "R1582:silent"),
("rdkafka", "rdkafka::producer::base_producer::BaseProducer::begin_transaction", "R1582:silent"),
("rdkafka", "rdkafka::message::BorrowedHeaders::detach", "R1582:silent"),
("rdkafka", "rdkafka::message::BorrowedMessage::detach", "R1582:silent"),
("rdkafka", "rdkafka::config::ClientConfig::create_native_config", "R1582:silent"),
("rdkafka", "rdkafka::producer::future_producer::FutureProducer::begin_transaction", "R1582:silent"),
("rdkafka", "rdkafka::producer::future_producer::FutureProducerContext::error", "R1581:conditional"),
("rdkafka", "rdkafka::producer::future_producer::FutureProducerContext::log", "R1581:conditional"),
("rdkafka", "rdkafka::producer::future_producer::FutureProducerContext::stats", "R1581:conditional"),
("rdkafka", "rdkafka::producer::future_producer::FutureProducerContext::stats_raw", "R1581:conditional"),
("rdkafka", "rdkafka::message::OwnedHeaders::new", "R1582:silent"),
("rdkafka", "rdkafka::message::OwnedHeaders::new_with_capacity", "R1582:silent"),
("rdkafka", "rdkafka::consumer::stream_consumer::StreamConsumer::assignment", "R1582:silent"),
("rdkafka", "rdkafka::consumer::stream_consumer::StreamConsumer::incremental_unassign", "R1582:silent"),
("rdkafka", "rdkafka::consumer::stream_consumer::StreamConsumer::position", "R1582:silent"),
("rdkafka", "rdkafka::consumer::stream_consumer::StreamConsumer::subscription", "R1582:silent"),
("rdkafka", "rdkafka::producer::base_producer::ThreadedProducer::begin_transaction", "R1582:silent"),
("rdkafka", "rdkafka::topic_partition_list::TopicPartitionList::from_topic_map", "R1582:silent"),
("rdkafka", "rdkafka::topic_partition_list::TopicPartitionList::new", "R1582:silent"),
("rdkafka", "rdkafka::topic_partition_list::TopicPartitionList::with_capacity", "R1582:silent"),
("mongodb", "mongodb::client::auth::AuthMechanism::validate_credential", "R1584:conditional"),
("mongodb", "mongodb::client::options::ConnectionString::parse", "R1584:conditional"),
("mongodb", "mongodb::client::options::parse::ParseConnectionString::execute", "R1584:conditional"),
("mongodb", "mongodb::client::csfle::client_encryption::ClientEncryption::new", "R1585:silent"),
("mongodb", "mongodb::client::csfle::client_encryption::ClientEncryptionBuilder::build", "R1585:silent"),
("mongodb", "mongodb::client::csfle::client_encryption::create_data_key::CreateDataKey::execute", "R1585:silent"),
("mongodb", "mongodb::client::csfle::client_encryption::encrypt::Encrypt::execute", "R1585:silent"),
("mongodb", "mongodb::client::csfle::client_builder::EncryptedClientBuilder::build", "R1585:silent"),
("mysql_async", "mysql_async::opts::PathOrBuf::read", "R1586:silent"),
("mysql_async", "mysql_async::queryable::query_result::QueryResult::map", "R1586:silent"),
("aws_config", "aws_config::meta::region::Box::region", "R1588:conditional"),
("aws_config", "aws_config::meta::region::RegionProviderChain::region", "R1588:conditional"),
("aws_config", "aws_config::profile::credentials::Builder::build", "R1588:silent"),
("aws_config", "aws_config::profile::token::Builder::build", "R1588:silent"),
("sqlx_core", "sqlx_core::pool::Pool::connect_lazy", "R1589:conditional"),
("sqlx_core", "sqlx_core::pool::Pool::connect_lazy_with", "R1589:conditional"),
("sqlx_core", "sqlx_core::pool::options::PoolOptions::connect_lazy", "R1589:conditional"),
("sqlx_core", "sqlx_core::pool::options::PoolOptions::connect_lazy_with", "R1589:conditional"),
("sqlx_core", "sqlx_core::net::socket::Box::poll_flush", "R1589:conditional"),
("sqlx_core", "sqlx_core::net::socket::Box::poll_read_ready", "R1589:conditional"),
("sqlx_core", "sqlx_core::net::socket::Box::poll_shutdown", "R1589:conditional"),
("sqlx_core", "sqlx_core::net::socket::Box::poll_write_ready", "R1589:conditional"),
("sqlx_core", "sqlx_core::migrate::source::PathBuf::resolve", "R1589:silent"),
("sqlx_core", "sqlx_core::migrate::source::ResolveWith::resolve", "R1589:silent"),
("redis", "redis::aio::multiplexed_connection::MultiplexedConnection::new", "R1590:conditional"),
("redis", "redis::aio::multiplexed_connection::MultiplexedConnection::new_with_config", "R1590:conditional"),
("redis", "redis::entra_id::EntraIdCredentialsProvider::start", "R1590:conditional"),
("redis", "redis::sentinel::Sentinel::build", "R1590:silent"),
("redis", "redis::sentinel::SentinelClient::build", "R1590:silent"),
("redis", "redis::sentinel::SentinelClientBuilder::build", "R1590:silent"),
("isahc", "isahc::cookies::jar::CookieJar::get_by_name", "R1592:conditional"),
("isahc", "isahc::cookies::jar::CookieJar::get_for_uri", "R1592:conditional"),
("isahc", "isahc::cookies::jar::CookieJar::set", "R1592:conditional"),
("isahc", "isahc::response::Response::text", "R1592:conditional"),
("lettre", "lettre::transport::smtp::transport::SmtpTransportBuilder::build", "R1592:conditional"),
("lettre", "lettre::transport::smtp::async_transport::AsyncSmtpTransportBuilder::build", "R1592:conditional"),
("lettre", "lettre::transport::smtp::commands::Auth::new_from_response", "R1592:conditional"),
("lapin", "lapin::connection::Connection::connector", "R1593:conditional"),
("lapin", "lapin::connection::Connection::run", "R1593:conditional"),
("lapin", "lapin::consumer::Consumer::set_delegate", "R1593:conditional"),
("tonic", "tonic::codec::decode::Streaming::message", "R1594:conditional"),
("tonic", "tonic::codec::decode::Streaming::trailers", "R1594:conditional"),
("tonic", "tonic::status::Code::from_bytes", "R1594:conditional"),
("tonic", "tonic::status::Status::from_header_map", "R1594:conditional"),
("tonic", "tonic::transport::channel::endpoint::Endpoint::tls_config", "R1594:conditional"),
("tonic", "tonic::transport::channel::endpoint::Endpoint::tls_config_with_verifier", "R1594:conditional"),
("tonic", "tonic::transport::server::Router::serve_with_incoming", "R1594:conditional"),
("tonic", "tonic::transport::server::Router::serve_with_incoming_shutdown", "R1594:conditional"),
("tonic", "tonic::transport::server::Server::serve_with_incoming", "R1594:conditional"),
("tonic", "tonic::transport::server::Server::serve_with_incoming_shutdown", "R1594:conditional"),
("tempfile", "tempfile::file::TempPath::from_path", "R1595:conditional"),
("tempfile", "tempfile::file::TempPath::try_from_path", "R1595:conditional"),
("tempfile", "tempfile::dir::TempDir::keep", "R1595:overcharge"),
("tempfile", "tempfile::dir::TempDir::into_path", "R1595:overcharge"),
("crossterm", "crossterm::style::Print::write_ansi", "R1595:conditional"),
("crossterm", "crossterm::terminal::SetTitle::write_ansi", "R1595:conditional"),
("crossterm", "crossterm::terminal::SetTitle::execute_winapi", "R1595:silent"),
("crossterm", "crossterm::ansi_support::supports_ansi", "R1595:silent"),
("deadpool_postgres", "deadpool_postgres::config::Config::get_pg_config", "R1598:conditional"),
("deadpool_postgres", "deadpool_postgres::config::Config::builder", "R1598:conditional"),
("deadpool_postgres", "deadpool_postgres::config::Config::create_pool", "R1598:conditional"),
("grep_cli", "grep_cli::decompress::DecompressionMatcher::new", "R1598:conditional"),
("grep_cli", "grep_cli::decompress::DecompressionMatcherBuilder::build", "R1598:conditional"),
("grep_cli", "grep_cli::decompress::resolve_binary", "R1598:conditional"),
("grep_cli", "grep_cli::is_readable_stdin", "R1598:conditional"),
("rand", "rand::rng::u8::fill_slice", "R1598:conditional"),
("tokio_postgres", "tokio_postgres::connection::Connection::poll_message", "R1598:conditional"),
("chrono", "chrono::date::Date::and_hms", "R1693:conditional"),
("chrono", "chrono::date::Date::and_hms_micro", "R1693:conditional"),
("chrono", "chrono::date::Date::and_hms_micro_opt", "R1693:conditional"),
("chrono", "chrono::date::Date::and_hms_milli", "R1693:conditional"),
("chrono", "chrono::date::Date::and_hms_milli_opt", "R1693:conditional"),
("chrono", "chrono::date::Date::and_hms_nano", "R1693:conditional"),
("chrono", "chrono::date::Date::and_hms_nano_opt", "R1693:conditional"),
("chrono", "chrono::date::Date::and_hms_opt", "R1693:conditional"),
("chrono", "chrono::date::Date::and_time", "R1693:conditional"),
("chrono", "chrono::datetime::DateTime::checked_add_days", "R1693:conditional"),
("chrono", "chrono::datetime::DateTime::checked_add_signed", "R1693:conditional"),
("chrono", "chrono::datetime::DateTime::checked_sub_days", "R1693:conditional"),
("chrono", "chrono::datetime::DateTime::checked_sub_signed", "R1693:conditional"),
("chrono", "chrono::datetime::DateTime::with_time", "R1693:conditional"),
("diesel", "diesel::pg::types::date_and_time::chrono::DateTime::from_sql", "R1693:conditional"),
("diesel", "diesel::sqlite::types::date_and_time::chrono::DateTime::from_sql", "R1693:conditional"),
("chrono", "chrono::format::parsed::Parsed::to_naive_datetime_with_offset", "R1694:overcharge"),
("chrono", "chrono::naive::datetime::NaiveDateTime::parse_and_remainder", "R1694:overcharge"),
("chrono", "chrono::naive::datetime::NaiveDateTime::parse_from_str", "R1694:overcharge"),
("ureq", "ureq::config::Config::new_agent", "R1694:overcharge"),
("ureq", "ureq::body::Body::as_reader", "R1695:conditional"),
("ureq", "ureq::body::Body::into_reader", "R1695:conditional"),
("ureq", "ureq::body::Body::read_json", "R1695:conditional"),
("ureq", "ureq::body::Body::read_to_string", "R1695:conditional"),
("ureq", "ureq::body::Body::read_to_vec", "R1695:conditional"),
("ureq", "ureq::body::BodyWithConfig::read_json", "R1695:conditional"),
("ureq", "ureq::body::BodyWithConfig::read_to_string", "R1695:conditional"),
("ureq", "ureq::body::BodyWithConfig::read_to_vec", "R1695:conditional"),
("ureq", "ureq::body::BodyWithConfig::reader", "R1695:conditional"),
("ureq", "ureq::send_body::Body::as_body", "R1695:conditional"),
("ureq", "ureq::unversioned::resolver::DefaultResolver::host_and_port", "R1695:conditional"),
("ureq", "ureq::config::ConfigBuilder::timeout_per_read", "R1553:conditional"),
("ureq", "ureq::config::ConfigBuilder::timeout_per_write", "R1553:conditional"),
("ureq", "ureq::unversioned::transport::tcp::TcpStream::shutdown", "R1696:conditional"),
("reqwest", "reqwest::blocking::multipart::Form::text", "R1732:overcharge"),
("reqwest", "reqwest::blocking::multipart::Part::bytes", "R1732:overcharge"),
("reqwest", "reqwest::blocking::multipart::Part::text", "R1732:overcharge"),
("rustls", "rustls::server::server_conn::Accepted::into_connection", "R1733:conditional"),
("redis", "redis::cluster_handling::client::ClusterClient::new", "R1734:overcharge"),
];
pub const CALIBRATION_PROBE_TAILS: &[&str] = &[
"::X::send", "::X::execute", "::X::call", "::X::query", "::X::fetch_one", "::Remote::fetch",
"::datalink::channel", "::WalkBuilder::build_parallel", "::RecommendedWatcher::new",
"::X::connect", "::Utc::now", "::X::load", "::__private_api::log", "::tempfile", "::glob",
"::X::run", "::dotenv", "::random", "::emit", "::X::emit_span_lint", "::X::anything",
"::X::draw",
"::SaltString::generate", "::hash", "::OsRng::fill_bytes",
"::Mmap::map", "::event", "::u32", "::Clipboard::get_text", "::spawn_command",
"::read_tls", "::home_dir", "::args", "::from_env", "::IntoIter::next", "::set_file_mtime",
"::surely_conflicts_with", "::set_handler", "::get_matches", "::init", "::interact",
"::write_line", "::background_color", "::retry", "::build",
];
pub const DB_CRATES: [&str; 11] = [
"sqlx", "rusqlite", "postgres", "tokio_postgres", "diesel", "redis", "mongodb",
"mysql", "mysql_async", "sea_orm", "deadpool_postgres",
];
const PURE_FD_TRANSFER: &[&str] = &[
"from_raw_fd", "from_raw_socket", "from_raw_handle",
"into_raw_fd", "into_raw_socket", "into_raw_handle",
"as_raw_fd", "as_raw_socket", "as_raw_handle",
"into_std",
"from_pathname",
];
const STD_EFFECT_HANDLES: &[&str] = &[
"std::process::Command",
"std::process::Child",
"std::net::TcpStream",
"std::net::TcpListener",
"std::net::UdpSocket",
"std::os::unix::net::UnixStream",
"std::os::unix::net::UnixListener",
"std::os::unix::net::UnixDatagram",
"std::fs::File",
"std::fs::OpenOptions",
"std::fs::DirBuilder",
];
pub fn is_std_effect_handle(ty: &str) -> bool {
STD_EFFECT_HANDLES.contains(&ty)
}
pub fn classify(crate_name: &str, path: &str) -> Option<&'static str> {
if PURE_FD_TRANSFER.contains(&path.rsplit("::").next().unwrap_or(path)) {
return None;
}
if let Some(verdict) = b11_r1528(crate_name, path) {
return verdict;
}
if crate_name.starts_with("aws_sdk_") || crate_name.starts_with("aws_smithy") {
if path.ends_with("::send") || path.ends_with("::send_with") {
return Some("Net");
}
return None;
}
if crate_name == "aws_config" {
if path.ends_with("::load") || path.ends_with("::load_defaults") || path.ends_with("::load_from_env") {
return Some("Net");
}
return aws_config_r1528(path);
}
if crate_name == "git2" {
if path.ends_with("::fetch")
|| path.ends_with("::push")
|| path.ends_with("::download")
|| path.ends_with("::connect")
|| path.ends_with("::connect_auth")
|| path.ends_with("::ls")
|| path.ends_with("::upload")
|| path == "git2::Repository::clone"
|| path == "git2::Repository::clone_recurse"
|| path == "git2::build::RepoBuilder::clone"
|| path == "git2::Submodule::clone"
|| path == "git2::Submodule::update"
|| path == "git2::Remote::list"
|| path == "git2::RemoteConnection::list"
{
return Some("Net");
}
if path == "git2::Config::add_file"
|| path == "git2::Config::open"
|| path == "git2::Config::open_default"
|| path == "git2::Index::add_all"
|| path == "git2::Index::add_path"
|| path == "git2::Index::read"
|| path == "git2::Index::write"
|| path == "git2::Index::write_tree"
|| path == "git2::Index::write_tree_to"
|| path == "git2::Odb::read"
|| path == "git2::Odb::reader"
|| path == "git2::Odb::write"
|| path == "git2::Odb::writer"
|| path == "git2::PackBuilder::write"
|| path == "git2::Reference::delete"
|| path == "git2::Reference::set_target"
|| path == "git2::Repository::blob_path"
|| path == "git2::Repository::checkout_head"
|| path == "git2::Repository::checkout_index"
|| path == "git2::Repository::checkout_tree"
|| path == "git2::Repository::commit"
|| path == "git2::Repository::discover"
|| path == "git2::Repository::discover_path"
|| path == "git2::Repository::init"
|| path == "git2::Repository::init_bare"
|| path == "git2::Repository::init_opts"
|| path == "git2::Repository::open"
|| path == "git2::Repository::open_bare"
|| path == "git2::Repository::open_ext"
|| path == "git2::Repository::open_from_env"
|| path == "git2::Repository::reference"
|| path == "git2::Repository::tag"
|| path == "git2::TreeBuilder::write"
{
return Some("Fs");
}
if path == "git2::Cred::credential_helper" || path == "git2::CredentialHelper::execute" {
return Some("Exec");
}
return None;
}
if crate_name == "libc" || crate_name == "nix" || crate_name == "rustix" {
let f = path.rsplit("::").next().unwrap_or(path);
const FS: &[&str] = LIBC_FS;
const NET: &[&str] = LIBC_NET;
const EXEC: &[&str] = LIBC_EXEC;
const IPC: &[&str] = &[
"pipe", "pipe2", "mkfifo", "mkfifoat", "socketpair", "msgget", "msgsnd", "msgrcv", "msgctl",
"semget", "semop", "semtimedop", "semctl", "shmget", "shmat", "shmdt", "shmctl", "mq_open",
"mq_send", "mq_receive", "mq_timedsend", "mq_timedreceive", "mq_close", "mq_unlink",
];
const ENV: &[&str] = &["getenv", "secure_getenv", "setenv", "putenv", "unsetenv", "clearenv"];
const CLOCK: &[&str] = &[
"time", "gettimeofday", "clock_gettime", "clock_getres", "nanosleep", "clock_nanosleep",
"clock_settime", "settimeofday", "stime", "adjtime", "adjtimex", "clock_adjtime",
];
const RAND: &[&str] = &["getrandom", "getentropy", "arc4random", "arc4random_buf", "arc4random_uniform"];
if FS.contains(&f) {
return Some("Fs");
}
if NET.contains(&f) {
return Some("Net");
}
if EXEC.contains(&f) {
return Some("Exec");
}
if IPC.contains(&f) {
return Some("Ipc");
}
if ENV.contains(&f) {
return Some("Env");
}
if CLOCK.contains(&f) {
return Some("Clock");
}
if RAND.contains(&f) {
return Some("Rand");
}
return None;
}
{
let leaf = path.rsplit("::").next().unwrap_or(path);
if let Some(rest) = leaf.strip_prefix("sqlite3_") {
let _ = rest;
const DB: &[&str] = &[
"sqlite3_open", "sqlite3_open_v2", "sqlite3_open16", "sqlite3_close", "sqlite3_close_v2",
"sqlite3_exec", "sqlite3_step", "sqlite3_prepare", "sqlite3_prepare_v2",
"sqlite3_prepare_v3", "sqlite3_prepare16", "sqlite3_prepare16_v2", "sqlite3_prepare16_v3",
"sqlite3_get_table", "sqlite3_backup_init", "sqlite3_backup_step", "sqlite3_backup_finish",
"sqlite3_blob_open", "sqlite3_blob_read", "sqlite3_blob_write", "sqlite3_blob_reopen",
"sqlite3_load_extension", "sqlite3_wal_checkpoint", "sqlite3_wal_checkpoint_v2",
"sqlite3_auto_extension", "sqlite3_cancel_auto_extension", "sqlite3_reset_auto_extension",
"sqlite3_enable_load_extension",
"sqlite3_deserialize", "sqlite3_serialize", "sqlite3_db_cacheflush",
"sqlite3_file_control", "sqlite3_wal_autocheckpoint",
];
return DB.contains(&leaf).then_some("Db");
}
if leaf.starts_with("git_") {
const NET: &[&str] = &[
"git_clone", "git_remote_connect", "git_remote_connect_ext", "git_remote_fetch",
"git_remote_download", "git_remote_upload", "git_remote_push", "git_remote_ls",
"git_submodule_clone", "git_submodule_update",
];
const FS: &[&str] = &[
"git_repository_open", "git_repository_open_ext", "git_repository_open_bare",
"git_repository_init", "git_repository_init_ext", "git_repository_discover",
"git_checkout_tree", "git_checkout_head", "git_checkout_index", "git_index_read",
"git_index_write", "git_index_write_tree", "git_index_write_tree_to",
"git_index_add_bypath", "git_index_add_all", "git_odb_open", "git_odb_read",
"git_odb_write", "git_odb_open_wstream", "git_odb_open_rstream",
"git_blob_create_fromdisk", "git_blob_create_fromworkdir", "git_blob_create_from_disk",
"git_blob_create_from_workdir", "git_blob_create_from_stream", "git_commit_create",
"git_commit_create_v", "git_reference_create", "git_reference_set_target",
"git_reference_delete", "git_config_open_default", "git_config_open_ondisk",
"git_config_add_file_ondisk", "git_tag_create", "git_treebuilder_write",
"git_packbuilder_write",
];
if NET.contains(&leaf) {
return Some("Net");
}
if FS.contains(&leaf) {
return Some("Fs");
}
return None;
}
if leaf.starts_with("curl_") {
const NET: &[&str] = &[
"curl_easy_perform", "curl_easy_send", "curl_easy_recv", "curl_easy_upkeep",
"curl_multi_perform", "curl_multi_socket_action",
];
return NET.contains(&leaf).then_some("Net");
}
if let Some(op) = leaf.strip_prefix("SSL_") {
const SSL_NET: &[&str] = &[
"connect", "accept", "do_handshake", "read", "read_ex", "write", "write_ex", "peek",
"peek_ex", "shutdown",
];
return SSL_NET.contains(&op).then_some("Net");
}
}
if crate_name == "reqwest" || crate_name == "isahc" {
if crate_name == "isahc" {
if let Some(effect) = isahc_r1528(path) {
return Some(effect);
}
}
if path.ends_with("::send")
|| path.ends_with("::execute")
|| path == "reqwest::get"
|| path == "reqwest::blocking::get"
|| path == "isahc::get"
{
return Some("Net");
}
if http_header_get_r1604(path) {
return None;
}
if path.ends_with("::get")
|| path.ends_with("::post")
|| path.ends_with("::put")
|| path.ends_with("::delete")
|| path.ends_with("::patch")
|| path.ends_with("::head")
|| path.ends_with("::request")
{
return Some("Net");
}
if crate_name == "isahc"
&& (path == "isahc::get_async"
|| path == "isahc::head_async"
|| path == "isahc::post_async"
|| path == "isahc::put_async"
|| path == "isahc::delete_async"
|| path == "isahc::send_async"
|| path.ends_with("HttpClient::new")
|| path.ends_with("HttpClientBuilder::build"))
{
return Some("Net");
}
if crate_name == "reqwest"
&& path.contains("Response::")
&& (path.ends_with("::text")
|| path.ends_with("::text_with_charset")
|| path.ends_with("::json")
|| path.ends_with("::bytes")
|| path.ends_with("::chunk")
|| path.ends_with("::bytes_stream")
|| path.ends_with("::copy_to"))
{
return Some("Net");
}
if crate_name == "reqwest" {
if let Some(effect) = reqwest_r1528(path) {
return Some(effect);
}
}
if crate_name == "reqwest"
&& (path.ends_with("::Identity::from_pkcs12_der")
|| path.ends_with("::Identity::from_pkcs8_pem"))
{
return Some("Fs");
}
if crate_name == "reqwest" && path.ends_with("::Part::file") {
return Some("Fs");
}
return None;
}
if crate_name == "ureq" && path.ends_with("::call") {
return Some("Net");
}
if crate_name == "ureq"
&& (path.ends_with("::send")
|| path.ends_with("::send_bytes")
|| path.ends_with("::send_form")
|| path.ends_with("::send_json")
|| path.ends_with("::send_string")
|| path == "ureq::agent"
|| path == "ureq::request"
|| path == "ureq::request_url"
|| path == "ureq::unversioned::transport::RustlsConnector::connect"
|| path == "ureq::tls::rustls::RustlsConnector::connect"
|| path == "ureq::RustlsConnector::connect")
{
return Some("Net");
}
if crate_name == "ureq" {
if path == "ureq::run" {
return Some("Net");
}
if let Some((ty, m)) = type_method(
path,
"ureq",
&["", "agent", "request", "request_ext", "config", "config::typestate", "middleware", "proxy",
"unversioned::transport", "unversioned::transport::tcp", "unversioned::transport::connect",
"unversioned::transport::socks", "unversioned::transport::time", "unversioned::resolver",
"unversioned::multipart", "multipart", "tls::native_tls", "tls", "send_body"],
) {
let hit = match (ty, m) {
("Agent", "run") | ("WithAgent", "run") | ("ConfigBuilder", "run")
| ("RequestBuilder", "send_empty") | ("MiddlewareNext", "handle")
| ("DefaultResolver", "resolve") => Some("Net"),
("TcpConnector" | "DefaultConnector" | "ConnectProxyConnector" | "SocksConnector"
| "NativeTlsConnector", "connect") => Some("Net"),
("TcpTransport", "transmit_output" | "await_input" | "is_open") => Some("Net"),
("Agent", "shutdown") => Some("Net"),
("Config", "builder" | "default") | ("Agent", "config_builder" | "new_with_defaults")
| ("Proxy", "try_from_env") => Some("Env"),
("Form", "file") | ("Part", "file") | ("File", "as_body") => Some("Fs"),
("Form", "new") => Some("Rand"),
("Instant", "now") => Some("Clock"),
_ => None,
};
if hit.is_some() {
return hit;
}
}
}
if crate_name == "curl"
&& (path.ends_with("::perform")
|| path.ends_with("::send")
|| path.ends_with("::recv")
|| path.ends_with("::upkeep")
|| path.ends_with("::action"))
{
return Some("Net");
}
match crate_name {
"hyper" if path.ends_with("::send_request") || path.ends_with("::handshake") => return Some("Net"),
"hyper_util" if path.ends_with("::request") || path.ends_with("::connect") => return Some("Net"),
"hickory_resolver"
if path.ends_with("::lookup_ip") || path.ends_with("::lookup") || path.ends_with("_lookup")
|| path.ends_with("::resolve") => return Some("Net"),
"h3" if path.ends_with("::send_request") || path.ends_with("::recv_data")
|| path.ends_with("::recv_response") || path.ends_with("::send_data") => return Some("Net"),
"quinn" if path.ends_with("::connect") || path.ends_with("::accept") || path.ends_with("::open_bi")
|| path.ends_with("::open_uni") || path.ends_with("::accept_bi") || path.ends_with("::accept_uni")
|| path.ends_with("::send_datagram") || path.ends_with("::read_datagram")
|| path.ends_with("::read") || path.ends_with("::read_chunk") || path.ends_with("::read_chunks")
|| path.ends_with("::read_to_end") || path.ends_with("::write") || path.ends_with("::write_all")
|| path.ends_with("::write_chunk") || path.ends_with("::write_chunks")
|| path.ends_with("::finish") => return Some("Net"),
"tokio_rustls" | "native_tls"
if path.ends_with("::connect") || path.ends_with("::accept") || path.ends_with("::handshake") =>
return Some("Net"),
"tokio_vsock" if path.ends_with("::connect") || path.ends_with("::bind") || path.ends_with("::accept") =>
return Some("Ipc"),
"rustls_native_certs" if path.ends_with("::load_native_certs") => return Some("Fs"),
"rlimit" if path.ends_with("::getrlimit") || path.ends_with("::setrlimit")
|| path.ends_with("::increase_nofile_limit") => return Some("Env"),
"rustls" if path.ends_with("::read_tls") || path.ends_with("::write_tls")
|| path.ends_with("::complete_io") => return Some("Net"),
"native_tls_crate" | "tokio_native_tls"
if path.ends_with("::connect") || path.ends_with("::accept")
|| path.ends_with("::handshake") => return Some("Net"),
_ => {}
}
if matches!(crate_name, "native_tls" | "native_tls_crate")
&& (path.ends_with("TlsConnector::new")
|| path.ends_with("TlsConnector::builder")
|| path.ends_with("Identity::from_pkcs8")
|| path.ends_with("Identity::from_pkcs12"))
{
return Some("Fs");
}
if crate_name == "rustls" && path.ends_with("KeyLogFile::new") {
return Some("Fs");
}
if crate_name == "rustls"
&& matches!(path, "rustls::KeyLogFile::log" | "rustls::key_log_file::KeyLogFile::log")
{
return Some("Fs");
}
if crate_name == "async_nats" {
if path.ends_with("::connect")
|| path.contains("::publish")
|| path.ends_with("::subscribe")
|| path.ends_with("::queue_subscribe")
|| path.contains("::request")
|| path.ends_with("::flush")
{
return Some("Net");
}
if path == "async_nats::connect_with_options" {
return Some("Net");
}
if path == "async_nats::ConnectOptions::credentials_file"
|| path == "async_nats::ConnectOptions::with_credentials_file"
{
return Some("Fs");
}
if path == "async_nats::ServerAddr::socket_addrs" {
return Some("Net");
}
if let Some(effect) = async_nats_r1528(path) {
return Some(effect);
}
return None;
}
if crate_name == "lapin" {
if path.ends_with("::connect")
|| path.ends_with("::create_channel")
|| path.contains("::basic_")
|| path.contains("::queue_")
|| path.contains("::exchange_")
|| path.contains("::tx_")
|| path.ends_with("::confirm_select")
|| path.ends_with("::close")
{
return Some("Net");
}
return lapin_r1528(path);
}
if crate_name == "lettre" {
if let Some(effect) = lettre_send_r1597(path) {
return Some(effect);
}
if lettre_stub_send_r1604(path) {
return None;
}
if path.ends_with("::send") || path.ends_with("::send_raw") {
return Some("Net");
}
if let Some(effect) = lettre_r1528(path) {
return Some(effect);
}
if let Some((ty, m)) = type_method(path, "lettre", &["", "transport::smtp::client"]) {
const CONN: &[&str] = &["connect", "connect_tokio1", "connect_with_transport", "starttls", "quit",
"abort", "test_connected", "auth", "message", "message_iter", "command", "read_response"];
let hit = match ty {
"SmtpConnection" | "AsyncSmtpConnection" => CONN.contains(&m),
"AsyncNetworkStream" => matches!(m, "connect_tokio1" | "upgrade_tls"),
"Tokio1Executor" => m == "connect",
_ => false,
};
if hit {
return Some("Net");
}
}
if path.ends_with("::Identity::from_pem") {
return Some("Fs");
}
if path == "lettre::TlsParametersBuilder::build"
|| path == "lettre::transport::smtp::client::TlsParametersBuilder::build"
|| path == "lettre::TlsParametersBuilder::build_rustls"
|| path == "lettre::transport::smtp::client::TlsParametersBuilder::build_rustls"
|| path == "lettre::TlsParameters::new"
|| path == "lettre::transport::smtp::client::TlsParameters::new"
|| path == "lettre::TlsParameters::new_rustls"
|| path == "lettre::transport::smtp::client::TlsParameters::new_rustls"
|| path == "lettre::TlsParameters::new_native"
|| path == "lettre::transport::smtp::client::TlsParameters::new_native"
|| path == "lettre::TlsParametersBuilder::build_native"
|| path == "lettre::transport::smtp::client::TlsParametersBuilder::build_native"
|| path == "lettre::SmtpTransport::from_url"
|| path == "lettre::SmtpTransport::relay"
|| path == "lettre::SmtpTransport::starttls_relay"
|| path == "lettre::AsyncSmtpTransport::from_url"
|| path == "lettre::AsyncSmtpTransport::relay"
|| path == "lettre::AsyncSmtpTransport::starttls_relay"
|| path == "lettre::FileTransport::read"
{
return Some("Fs");
}
if path == "lettre::AsyncStd1Executor::connect"
|| path == "lettre::AsyncSmtpConnection::connect_asyncstd1"
|| path == "lettre::transport::smtp::client::AsyncSmtpConnection::connect_asyncstd1"
|| path == "lettre::AsyncNetworkStream::connect_asyncstd1"
|| path == "lettre::transport::smtp::client::AsyncNetworkStream::connect_asyncstd1"
{
return Some("Net");
}
if path == "lettre::AsyncStd1Executor::fs_read" || path == "lettre::AsyncStd1Executor::fs_write" {
return Some("Fs");
}
return None;
}
if crate_name == "tungstenite" {
if let Some(effect) = tungstenite_r1528(path) {
return Some(effect);
}
if path.ends_with("::connect")
|| path.ends_with("::connect_with_config")
|| path.ends_with("::client")
|| path.ends_with("::client_with_config")
|| path.ends_with("::client_tls")
|| path.ends_with("::client_tls_with_config")
|| path.ends_with("::accept")
|| path.ends_with("::accept_with_config")
|| path.ends_with("::accept_hdr")
|| path.ends_with("::accept_hdr_with_config")
|| path.ends_with("::read")
|| path.ends_with("::write")
|| path.ends_with("::send")
|| path.ends_with("::close")
|| path.ends_with("::flush")
|| path.ends_with("::read_message")
|| path.ends_with("::write_message")
{
return Some("Net");
}
return None;
}
if crate_name == "elasticsearch"
&& path.contains("Response::")
&& (path.ends_with("::json")
|| path.ends_with("::text")
|| path.ends_with("::bytes")
|| path.ends_with("::exception"))
{
return Some("Net");
}
if crate_name == "elasticsearch" && path.ends_with("::send") {
return Some("Net");
}
if crate_name == "tonic" {
if path.ends_with("::connect")
|| path.ends_with("::unary")
|| path.ends_with("::server_streaming")
|| path.ends_with("::client_streaming")
|| path.ends_with("::streaming")
|| path.ends_with("::Router::serve")
|| path.ends_with("::Router::serve_with_shutdown")
|| path == "tonic::TcpIncoming::new"
|| path == "tonic::transport::server::TcpIncoming::new"
{
return Some("Net");
}
return tonic_r1528(path);
}
if crate_name == "rdkafka" {
if path.ends_with("::send")
|| path.ends_with("::send_result")
|| path.ends_with("::recv")
|| path.ends_with("::poll")
|| path.ends_with("::subscribe")
|| path.ends_with("::commit")
|| path.ends_with("::commit_message")
|| path.ends_with("::commit_consumer_state")
|| path.ends_with("::store_offset")
|| path.ends_with("::seek")
|| path.ends_with("::fetch_metadata")
|| path.ends_with("::fetch_watermarks")
|| path.ends_with("::fetch_group_list")
|| path.ends_with("::flush")
{
return Some("Net");
}
return rdkafka_r1528(path);
}
if crate_name.starts_with("cap_") {
if path.contains("::net::Unix") || path.contains("::os::") {
return Some("Ipc");
}
if path.contains("::net") {
return Some("Net");
}
if path.contains("::time") {
return Some("Clock");
}
if path.contains("::fs") || crate_name == "cap_tempfile" || crate_name == "cap_directories" {
return Some("Fs");
}
return None;
}
if path.starts_with("tokio::net::Unix")
|| path.starts_with("std::os::unix::net")
|| path.starts_with("async_std::os::unix::net")
|| path.starts_with("async_net::unix")
{
return Some("Ipc");
}
if crate_name == "pnet" || crate_name == "pnet_datalink" || crate_name == "pnet_transport" {
if path.ends_with("::channel") || path.ends_with("::transport_channel") {
return Some("Net");
}
return None;
}
if crate_name == "ignore" {
if path == "ignore::WalkBuilder::build"
|| path == "ignore::WalkBuilder::build_parallel"
|| path.ends_with("::WalkParallel::run")
|| path == "ignore::WalkBuilder::add_ignore"
|| path == "ignore::Walk::new"
|| path == "ignore::Walk::from_iter"
{
return Some("Fs");
}
if path == "ignore::gitignore::Gitignore::new"
|| path == "ignore::gitignore::Gitignore::global"
|| path == "ignore::gitignore::GitignoreBuilder::add"
|| path == "ignore::gitignore::GitignoreBuilder::build_global"
|| path == "ignore::gitignore::gitconfig_excludes_path"
|| path == "ignore::WalkBuilder::build_matchers"
|| path == "ignore::IncrementalIgnore::matched"
|| path == "ignore::IncrementalIgnore::matched_with_errors"
|| path == "ignore::DirEntry::metadata"
|| path == "ignore::walk::DirEntry::metadata"
|| path == "ignore::WalkParallel::visit"
|| path == "ignore::walk::WalkParallel::visit"
{
return Some("Fs");
}
return None;
}
if crate_name == "notify" {
if path.ends_with("Watcher::new")
|| path.ends_with("::recommended_watcher")
|| path.ends_with("::watch")
|| path.ends_with("::unwatch")
|| path.ends_with("ReadDirectoryChangesWatcher::create")
{
return Some("Fs");
}
return None;
}
if path.ends_with("::to_socket_addrs")
|| path == "std::net::lookup_host"
|| path.ends_with("ToSocketAddrs::to_socket_addrs")
{
return Some("Net");
}
if path.starts_with("std::net::TcpStream")
|| path.starts_with("std::net::TcpListener")
|| path.starts_with("std::net::UdpSocket")
|| path.starts_with("tokio::net::")
{
if path.ends_with("::local_addr")
|| path.ends_with("::peer_addr")
|| path.ends_with("::nodelay")
|| path.ends_with("::ttl")
|| path.ends_with("::take_error")
{
return None;
}
return Some("Net");
}
if matches!(crate_name, "tokio_tcp" | "tokio_udp") {
return Some("Net");
}
if path.starts_with("async_std::net::")
|| path.starts_with("mio::net::")
|| crate_name == "async_net"
{
return Some("Net");
}
if DB_CRATES.contains(&crate_name) {
if crate_name == "sqlx" {
if let Some(effect) = sqlx_r1528("sqlx", path) {
return Some(effect);
}
}
if matches!(crate_name, "postgres" | "tokio_postgres" | "deadpool_postgres" | "rusqlite") {
const PG: &[&str] = PG_DB_VERBS;
if PG.iter().any(|v| path.ends_with(v)) {
return Some("Db");
}
if matches!(crate_name, "tokio_postgres" | "postgres")
&& path.ends_with("CancelToken::cancel_query")
{
return Some("Net");
}
if crate_name == "tokio_postgres"
&& (path.ends_with("::Client::cancel_query")
|| path.ends_with("::Transaction::cancel_query"))
{
return Some("Net");
}
if crate_name == "postgres" && path.ends_with("::Client::is_valid") {
return Some("Db");
}
if crate_name == "deadpool_postgres"
&& matches!(path, "deadpool_postgres::Pool::get" | "deadpool_postgres::Pool::timeout_get")
{
return Some("Db");
}
if let Some((head, "start")) = path.rsplit_once("::") {
if matches!(
head,
"tokio_postgres::Client" | "tokio_postgres::TransactionBuilder"
| "postgres::Client" | "postgres::TransactionBuilder"
| "deadpool_postgres::Client" | "deadpool_postgres::Object" | "deadpool_postgres::TransactionBuilder"
) {
return Some("Db");
}
}
if crate_name == "rusqlite"
&& (path.contains("::Connection::open")
|| path.ends_with("::Connection::blob_open")
|| path.ends_with("::Blob::reopen"))
{
return Some("Db");
}
if crate_name == "rusqlite"
&& (path == "rusqlite::Backup::new"
|| path == "rusqlite::backup::Backup::new"
|| path == "rusqlite::Backup::new_with_names"
|| path == "rusqlite::backup::Backup::new_with_names"
|| path == "rusqlite::Backup::step"
|| path == "rusqlite::backup::Backup::step"
|| path == "rusqlite::Backup::run_to_completion"
|| path == "rusqlite::backup::Backup::run_to_completion"
|| path == "rusqlite::Connection::backup"
|| path == "rusqlite::Connection::restore"
|| path == "rusqlite::Blob::read_at"
|| path == "rusqlite::blob::Blob::read_at"
|| path == "rusqlite::Blob::read_at_exact"
|| path == "rusqlite::blob::Blob::read_at_exact"
|| path == "rusqlite::Blob::raw_read_at"
|| path == "rusqlite::blob::Blob::raw_read_at"
|| path == "rusqlite::Blob::raw_read_at_exact"
|| path == "rusqlite::blob::Blob::raw_read_at_exact"
|| path == "rusqlite::Blob::write_at"
|| path == "rusqlite::blob::Blob::write_at"
|| path == "rusqlite::Blob::write_all_at"
|| path == "rusqlite::blob::Blob::write_all_at"
|| path == "rusqlite::Connection::from_handle"
|| path == "rusqlite::Connection::from_handle_owned"
|| path == "rusqlite::Connection::extension_init2"
|| path == "rusqlite::init_auto_extension"
|| path == "rusqlite::auto_extension::init_auto_extension"
|| path == "rusqlite::Statement::insert"
|| path == "rusqlite::statement::Statement::insert"
|| path == "rusqlite::Statement::raw_execute"
|| path == "rusqlite::statement::Statement::raw_execute"
|| path == "rusqlite::Rows::next"
|| path == "rusqlite::row::Rows::next"
|| path == "rusqlite::Rows::advance"
|| path == "rusqlite::row::Rows::advance")
{
return Some("Db");
}
if crate_name == "rusqlite" {
if let Some((ty, m)) = type_method(path, "rusqlite", &["", "transaction", "pragma"]) {
let hit = match ty {
"Transaction" => matches!(m, "new" | "new_unchecked" | "commit" | "rollback" | "finish"
| "savepoint" | "savepoint_with_name"),
"Savepoint" => matches!(m, "new" | "with_name" | "savepoint" | "savepoint_with_name"
| "commit" | "rollback" | "finish"),
"Connection" => matches!(m, "transaction_with_behavior" | "unchecked_transaction"
| "savepoint" | "savepoint_with_name" | "pragma" | "pragma_query"
| "pragma_query_value" | "pragma_update" | "pragma_update_and_check"),
_ => false,
};
if hit {
return Some("Db");
}
}
}
if let Some((ty, m)) = type_method(path, "rusqlite", &["", "serialize", "hooks", "statement",
"load_extension_guard"])
{
let hit = match ty {
"Connection" => matches!(m, "close" | "cache_flush" | "serialize" | "deserialize"
| "deserialize_bytes" | "deserialize_read_exact" | "load_extension"
| "load_extension_enable" | "load_extension_disable"),
"Statement" => m == "exists",
"LoadExtensionGuard" => m == "new",
"Wal" => matches!(m, "checkpoint" | "checkpoint_v2"),
_ => false,
};
if hit {
return Some("Db");
}
}
if matches!(
path,
"rusqlite::register_auto_extension" | "rusqlite::auto_extension::register_auto_extension"
| "rusqlite::cancel_auto_extension" | "rusqlite::auto_extension::cancel_auto_extension"
| "rusqlite::reset_auto_extension" | "rusqlite::auto_extension::reset_auto_extension"
) {
return Some("Db");
}
return None;
}
if crate_name == "redis"
&& (path.starts_with("redis::sentinel::") || path.contains("::Sentinel"))
{
let m = path.rsplit("::").next().unwrap_or(path);
if m == "build" || m == "new" || m.starts_with("set_") {
return None;
}
if candor_report::env::trace("CANDOR_ALIAS_DEBUG") {
eprintln!("R335SENTINEL {path}");
}
return Some("Db");
}
if crate_name == "redis" {
if let Some((ty, m)) = type_method(path, "redis", &["", "connection"]) {
if (ty == "Connection" && matches!(m, "send_packed_command" | "recv_response"))
|| (ty == "PubSub" && m == "get_message")
{
return Some("Net");
}
}
}
if crate_name == "redis" {
if let Some(effect) = redis_r1528(path) {
return Some(effect);
}
}
if crate_name == "redis"
&& (path.contains("Commands::")
|| (path.contains("::get_connection") && !path.ends_with("::get_connection_info"))
|| path.contains("::get_async_connection")
|| path.contains("::get_multiplexed_async_connection")
|| (path.contains("ConnectionManager") && !path.contains("ConnectionManagerConfig")
&& !path.ends_with("::clone"))
|| path.ends_with("::query")
|| path.ends_with("::query_async")
|| path.ends_with("::req_command")
|| path.ends_with("::req_packed_command")
|| path.ends_with("::req_packed_commands"))
{
return Some("Db");
}
if crate_name == "mongodb" {
const MONGO: [&str; 28] = [
"::with_uri_str", "::with_options", "::connect", "::find", "::find_one", "::insert_one",
"::insert_many", "::update_one", "::update_many", "::delete_one",
"::delete_many", "::replace_one", "::aggregate", "::count_documents",
"::estimated_document_count", "::count", "::distinct", "::run_command",
"::find_one_and_update", "::find_one_and_delete", "::find_one_and_replace",
"::list_collections", "::list_collection_names", "::list_databases",
"::list_database_names", "::create_collection", "::create_index", "::watch",
];
if MONGO.iter().any(|v| path.ends_with(v)) {
return Some("Db");
}
if path.ends_with("ClientEncryption::decrypt") {
return Some("Net");
}
return mongodb_r1528(path);
}
if matches!(crate_name, "mysql" | "mysql_async") {
if path.ends_with("::Conn::new") {
return Some("Db");
}
const MY: [&str; 16] = [
"::query", "::query_first", "::query_iter", "::query_map", "::query_fold",
"::query_drop", "::exec", "::exec_first", "::exec_iter", "::exec_map",
"::exec_fold", "::exec_drop", "::exec_batch", "::prep", "::ping", "::get_conn",
];
if MY.iter().any(|v| path.ends_with(v)) {
return Some("Db");
}
if path == "mysql_async::Conn::from_url" {
return Some("Db");
}
if path.ends_with("WhiteListFsHandler::handle") {
return Some("Fs");
}
if crate_name == "mysql" {
if let Some(effect) = mysql_r1528(path) {
return Some(effect);
}
}
return mysql_async_r1528(path);
}
if crate_name == "sea_orm" {
if path.contains("sea_query") {
return None;
}
if path.ends_with("::all")
|| path.ends_with("::one")
|| path.ends_with("::count")
|| path.ends_with("::stream")
|| path.ends_with("::exec")
|| path.ends_with("::exec_with_returning")
|| path.ends_with("::exec_without_returning")
|| path.ends_with("::connect")
|| path.ends_with("::connect_proxy")
|| path.ends_with("::execute")
|| path.ends_with("::execute_unprepared")
|| path.ends_with("::query_one")
|| path.ends_with("::query_all")
|| path.ends_with("::fetch_page")
|| path.ends_with("::num_items")
|| r1607_active_model_query(path)
{
return Some("Db");
}
if path == "sea_orm::DatabaseConnection::transaction"
|| path == "sea_orm::DatabaseConnection::transaction_with_config"
|| path == "sea_orm::DatabaseConnection::ping"
|| path == "sea_orm::DatabaseConnection::begin"
|| path == "sea_orm::DatabaseConnection::begin_with_config"
|| path == "sea_orm::DatabaseTransaction::commit"
|| path == "sea_orm::DatabaseTransaction::rollback"
|| path == "sea_orm::SqlxMySqlPoolConnection::begin"
|| path == "sea_orm::SqlxMySqlPoolConnection::ping"
|| path == "sea_orm::SqlxMySqlPoolConnection::transaction"
|| path == "sea_orm::SqlxPostgresPoolConnection::begin"
|| path == "sea_orm::SqlxPostgresPoolConnection::ping"
|| path == "sea_orm::SqlxPostgresPoolConnection::transaction"
|| path == "sea_orm::SqlxSqlitePoolConnection::begin"
|| path == "sea_orm::SqlxSqlitePoolConnection::ping"
|| path == "sea_orm::SqlxSqlitePoolConnection::transaction"
|| path == "sea_orm::Paginator::fetch"
|| path == "sea_orm::Paginator::fetch_and_next"
|| path == "sea_orm::Paginator::into_stream"
|| path == "sea_orm::Paginator::num_pages"
|| path == "sea_orm::Paginator::num_items_and_pages"
|| path.ends_with("::exec_with_returning_keys")
|| path.ends_with("::exec_with_returning_many")
{
return Some("Db");
}
if path.ends_with("::require_one") || path.ends_with("::stream_partial_model") {
return Some("Db");
}
if let Some(("SqlxPostgresConnector", "accepts")) =
type_method(path, "sea_orm", &["", "driver", "driver::sqlx_postgres"])
{
return Some("Env");
}
if let Some((ty, m)) = type_method(path, "sea_orm", &[""]) {
if matches!(
(ty, m),
("DatabaseConnection", "begin_with_options" | "transaction_async" | "transaction_with_config_async"
| "execute_raw" | "query_one_raw" | "query_all_raw" | "stream_raw")
| ("DatabaseExecutor", "begin" | "begin_with_config" | "begin_with_options" | "execute_raw"
| "query_one_raw" | "query_all_raw" | "transaction" | "transaction_async"
| "transaction_with_config" | "transaction_with_config_async")
| ("DatabaseTransaction", "begin" | "begin_with_config" | "begin_with_options" | "execute_raw"
| "query_one_raw" | "query_all_raw" | "stream_raw" | "transaction" | "transaction_async"
| "transaction_with_config" | "transaction_with_config_async")
| ("RestrictedConnection", "begin" | "begin_with_config" | "begin_with_options" | "transaction"
| "transaction_async" | "transaction_with_config" | "transaction_with_config_async")
| ("RestrictedTransaction", "begin" | "begin_with_config" | "begin_with_options" | "commit"
| "rollback" | "transaction" | "transaction_async" | "transaction_with_config"
| "transaction_with_config_async")
) {
return Some("Db");
}
}
if let Some((ty, m)) = type_method(path, "sea_orm", &["rbac", "rbac::context"]) {
if ty == "RbacContext"
&& matches!(m, "load" | "add_tables" | "add_crud_permissions" | "add_roles" | "add_role_permissions"
| "remove_role_permissions" | "add_user_override" | "add_role_hierarchy" | "assign_user_role")
{
return Some("Db");
}
}
if path == "sea_orm::rbac::schema::create_tables" {
return Some("Db");
}
if let Some((ty, m)) = type_method(path, "sea_orm", &["", "schema", "schema::builder"]) {
if ty == "SchemaBuilder" && matches!(m, "apply" | "sync") {
return Some("Db");
}
}
if let Some((ty, m)) = type_method(path, "sea_orm", &["", "entity", "entity::registry"]) {
if (ty, m) == ("EntityRegistry", "build_schema") {
return Some("Log");
}
}
if let Some((ty, m)) = type_method(path, "sea_orm", &[""]) {
if matches!((ty, m), ("DatabaseConnection" | "DatabaseExecutor", "get_schema_registry")) {
return Some("Log");
}
}
return None;
}
if crate_name == "diesel" {
if let Some(effect) = diesel_r1528(path) {
return Some(effect);
}
}
const VERBS: [&str; 20] = [
"::execute", "::query_row", "::query_map", "::query_one", "::fetch_one",
"::fetch_all", "::fetch_optional", "::fetch", "::fetch_many", "::connect",
"::acquire", "::begin", "::commit", "::rollback", "::load", "::load_iter",
"::first", "::get_result", "::get_results", "::establish",
];
if VERBS.iter().any(|v| path.ends_with(v)) {
return Some("Db");
}
return None;
}
if let Some(m) = path
.strip_prefix("std::path::Path::")
.or_else(|| path.strip_prefix("std::path::PathBuf::"))
{
const STAT: &[&str] = &[
"metadata", "symlink_metadata", "canonicalize", "read_link", "read_dir", "exists",
"try_exists", "is_file", "is_dir", "is_symlink",
];
return STAT.contains(&m).then_some("Fs");
}
if let Some(m) = path.strip_prefix("std::fs::OpenOptions::") {
const PURE: &[&str] = &[
"new", "read", "write", "append", "truncate", "create", "create_new",
"mode", "custom_flags", "security_qos_flags", "access_mode", "share_mode", "attributes",
"clone", "default", "fmt", "eq", "ne", "hash",
];
return (!PURE.contains(&m)).then_some("Fs");
}
if let Some(m) = path.strip_prefix("std::fs::DirBuilder::") {
const PURE: &[&str] = &["new", "recursive", "mode", "clone", "default", "fmt"];
return (!PURE.contains(&m)).then_some("Fs");
}
if let Some(rest) = path
.strip_prefix("std::os::unix::fs::")
.or_else(|| path.strip_prefix("std::os::windows::fs::"))
.or_else(|| path.strip_prefix("std::os::wasi::fs::"))
{
const PURE_TRAITS: &[&str] = &[
"MetadataExt::", "DirEntryExt::", "DirEntryExt2::", "FileTypeExt::",
"PermissionsExt::", "OpenOptionsExt::", "DirBuilderExt::",
];
return (!PURE_TRAITS.iter().any(|t| rest.starts_with(t))).then_some("Fs");
}
if let Some(rest) = path
.strip_prefix("std::os::unix::process::")
.or_else(|| path.strip_prefix("std::os::windows::process::"))
.or_else(|| path.strip_prefix("std::os::wasi::process::"))
{
const PURE: &[&str] =
&["ExitStatusExt::", "ExitStatusError::", "ExitCodeExt::", "parent_id"];
return (!PURE.iter().any(|t| rest.starts_with(t))).then_some("Exec");
}
if path.starts_with("std::fs::")
|| path.starts_with("tokio::fs::")
|| path.starts_with("async_std::fs::")
|| crate_name == "async_fs"
|| crate_name == "fs_err"
{
return Some("Fs");
}
if crate_name == "memmap2" {
let m = path.rsplit("::").next().unwrap_or(path);
if m.starts_with("map")
|| m == "flush"
|| m == "flush_async"
|| m == "flush_range"
|| m == "flush_async_range"
|| m == "remap"
|| m.starts_with("make_")
|| m == "advise"
|| m == "advise_range"
|| m == "lock"
|| m == "unlock"
{
return Some("Fs");
}
return None;
}
if crate_name == "tempfile" {
if matches!(type_method(path, "tempfile", &["", "dir"]), Some(("TempDir", "keep"))) {
return None;
}
if let Some(effect) = tempfile_r1528(path) {
return Some(effect);
}
}
if crate_name == "tempfile"
&& (path.ends_with("::tempfile")
|| path.ends_with("::tempfile_in")
|| path.ends_with("::tempdir")
|| path.ends_with("::tempdir_in")
|| path.ends_with("NamedTempFile::new")
|| path.ends_with("NamedTempFile::new_in")
|| path.ends_with("TempDir::new")
|| path.ends_with("TempDir::new_in")
|| path.ends_with("::persist")
|| path.ends_with("::persist_noclobber")
|| path.ends_with("::keep"))
{
return Some("Fs");
}
if crate_name == "tempfile"
&& (path == "tempfile::Builder::make"
|| path == "tempfile::Builder::make_in"
|| path == "tempfile::NamedTempFile::with_prefix"
|| path == "tempfile::NamedTempFile::with_prefix_in"
|| path == "tempfile::NamedTempFile::with_suffix"
|| path == "tempfile::NamedTempFile::with_suffix_in"
|| path == "tempfile::NamedTempFile::reopen"
|| path == "tempfile::SpooledTempFile::set_len"
|| path.ends_with("::close"))
{
return Some("Fs");
}
if crate_name == "tempfile"
&& (path == "tempfile::NamedTempFile::into_file"
|| path == "tempfile::TempDir::with_prefix"
|| path == "tempfile::TempDir::with_prefix_in"
|| path == "tempfile::TempDir::with_suffix"
|| path == "tempfile::TempDir::with_suffix_in")
{
return Some("Fs");
}
if crate_name == "glob" && (path.ends_with("::glob") || path.ends_with("::glob_with")) {
return Some("Fs");
}
if matches!(crate_name, "argon2" | "scrypt" | "pbkdf2" | "password_hash") {
if path.contains("SaltString::generate")
|| path.ends_with("::generate_salt")
|| path.ends_with("::try_generate_salt")
|| path.ends_with("::hash_password")
|| path.ends_with("::hash_password_with_rng")
{
return Some("Rand");
}
return None;
}
if crate_name == "bcrypt" {
if path.ends_with("::hash")
|| path.ends_with("::hash_with_result")
|| path.ends_with("::non_truncating_hash")
|| path.ends_with("::hash_bytes")
|| path.ends_with("::non_truncating_hash_bytes")
|| path.ends_with("::non_truncating_hash_with_result")
{
return Some("Rand");
}
return None;
}
if crate_name == "rand_core" {
if path.contains("OsRng")
|| path.ends_with("::next_u32")
|| path.ends_with("::next_u64")
|| path.ends_with("::fill_bytes")
|| path.ends_with("::try_next_u32")
|| path.ends_with("::try_next_u64")
|| path.ends_with("::try_fill_bytes")
{
return Some("Rand");
}
return None;
}
if crate_name == "getrandom" {
if path.split("::").skip(1).any(|s| s.trim_start_matches('&') == "Error") {
return None;
}
return Some("Rand");
}
if crate_name == "fastrand" {
let m = path.rsplit("::").next().unwrap_or(path);
if m == "with_seed" || m == "fork" || m == "clone" {
return None;
}
return Some("Rand");
}
if crate_name == "rand" {
let rng_verb = path.ends_with("::gen")
|| path.ends_with("::gen_range")
|| path.ends_with("::gen_bool")
|| path.ends_with("::gen_ratio")
|| path.ends_with("::random")
|| path.ends_with("::random_range")
|| path.ends_with("::random_bool")
|| path.ends_with("::random_ratio")
|| path.ends_with("::random_iter") || path.ends_with("::gen_iter")
|| path.ends_with("::fill")
|| path.ends_with("::fill_bytes")
|| path.ends_with("::try_fill")
|| path.ends_with("::try_fill_bytes")
|| path.ends_with("::sample")
|| path.ends_with("::sample_iter")
|| path.ends_with("::next_u32")
|| path.ends_with("::next_u64")
|| path.ends_with("::try_next_u32")
|| path.ends_with("::try_next_u64")
|| path.ends_with("::thread_rng")
|| path.ends_with("::rng")
|| path.ends_with("::from_entropy")
|| path.ends_with("::from_os_rng");
let m = path.rsplit("::").next().unwrap_or(path);
let os_rng = path.contains("OsRng") && !matches!(m, "clone" | "fork" | "default");
let sys_rng = path.contains("SysRng") && !matches!(m, "clone" | "fork" | "default");
if sys_rng && candor_report::env::trace("CANDOR_ALIAS_DEBUG") {
eprintln!("R320SYSRNG {path}");
}
if rng_verb || os_rng || sys_rng {
return Some("Rand");
}
return None;
}
if path.starts_with("std::process::Command")
|| path.starts_with("std::process::Child")
|| path.starts_with("tokio::process::Command")
|| path.starts_with("tokio::process::Child")
|| path.starts_with("async_std::process::Command")
|| path.starts_with("async_std::process::Child")
{
if path.ends_with("::get_program")
|| path.ends_with("::get_args")
|| path.ends_with("::get_envs")
|| path.ends_with("::get_current_dir")
|| path.ends_with("Child::id")
{
return None;
}
return Some("Exec");
}
if crate_name == "async_process" || crate_name == "portable_pty" {
let m = path.rsplit("::").next().unwrap_or(path);
if m == "get_shell" {
return Some("Fs");
}
if m.starts_with("get_") || m == "as_unix_command_line" {
return None;
}
if matches!(
m,
"default" | "new" | "piped" | "null" | "inherit" | "from_raw_fd"
| "arg" | "args" | "arg0" | "env" | "envs" | "env_clear" | "env_remove"
| "cwd" | "current_dir" | "rows" | "cols"
| "clone" | "fmt" | "eq" | "ne" | "hash"
) {
return None;
}
return Some("Exec");
}
if crate_name == "duct"
&& (path.ends_with("::run")
|| path.ends_with("::read")
|| path.ends_with("::start")
|| path.ends_with("::read_chars")
|| path.ends_with("Expression::reader"))
{
return Some("Exec");
}
if path.starts_with("std::env::") {
return Some("Env");
}
if matches!(crate_name, "dotenvy" | "dotenv")
&& (path.ends_with("::dotenv")
|| path.ends_with("::dotenv_override")
|| path.ends_with("::from_path")
|| path.ends_with("::from_path_override")
|| path.ends_with("::from_filename")
|| path.ends_with("::from_filename_override")
|| path.ends_with("::from_read")
|| path.ends_with("::from_read_override")
|| path.ends_with("::load")
|| path.ends_with("::var")
|| path.ends_with("::vars"))
{
return Some("Env");
}
if matches!(crate_name, "dotenvy" | "dotenv")
&& (path.ends_with("::dotenv_iter")
|| path.ends_with("::from_filename_iter")
|| path.ends_with("::from_path_iter"))
{
return Some("Env");
}
if (crate_name == "chrono" || path.starts_with("std::time::")) && path.ends_with("::now") {
return Some("Clock");
}
if crate_name == "chrono" && (path.ends_with("Utc::today") || path.ends_with("Local::today")) {
return Some("Clock");
}
if crate_name == "chrono" {
if let Some((ty, m)) = type_method(path, "chrono", &["", "offset", "offset::local"]) {
if ty == "Local"
&& matches!(m, "offset_from_utc_datetime" | "offset_from_local_datetime" | "offset_from_utc_date"
| "offset_from_local_date")
{
return Some("Clock");
}
if ty == "Local"
&& matches!(m, "from_utc_datetime" | "from_utc_date" | "from_local_datetime" | "from_local_date"
| "with_ymd_and_hms" | "ymd" | "ymd_opt" | "yo" | "yo_opt" | "isoywd" | "isoywd_opt" | "timestamp"
| "timestamp_opt" | "timestamp_millis" | "timestamp_millis_opt" | "timestamp_nanos" | "timestamp_micros"
| "datetime_from_str")
{
return Some("Clock");
}
}
}
if crate_name == "time"
&& (path.ends_with("::now_utc") || path.ends_with("::now_local") || path.ends_with("::now"))
{
return Some("Clock");
}
if path.ends_with("::now")
&& (path.starts_with("tokio::time::Instant::")
|| matches!(crate_name, "quanta" | "minstant" | "web_time" | "instant" | "coarsetime"))
{
return Some("Clock");
}
if crate_name == "tracing" {
let m = path.rsplit("::").next().unwrap_or(path);
if m == "trace" || m == "debug" || m == "info" || m == "warn" || m == "error"
|| m == "trace_span" || m == "debug_span" || m == "info_span" || m == "warn_span"
|| m == "error_span" || m == "span"
|| m == "event"
|| m == "new_span"
|| m == "record"
|| m == "record_follows_from"
|| m == "enter"
|| m == "exit"
|| m == "in_scope"
|| m == "entered"
|| path.contains("::__macro_support")
|| path.contains("::__tracing")
|| path.contains("Subscriber::event")
|| path.contains("Subscriber::new_span")
|| path.contains("Subscriber::enter")
|| path.contains("Subscriber::exit")
{
return Some("Log");
}
return None;
}
if crate_name == "log" {
let m = path.rsplit("::").next().unwrap_or(path);
if path.contains("::__private_api")
|| m == "error" || m == "warn" || m == "info" || m == "debug" || m == "trace" || m == "log"
{
return Some("Log");
}
}
if crate_name == "rustc_lint"
&& (path.ends_with("::emit_span_lint")
|| path.ends_with("::span_lint")
|| path.ends_with("::span_lint_hir"))
{
return Some("Log");
}
if crate_name == "rustc_errors"
&& (path.ends_with("::emit")
|| path.ends_with("::emit_diagnostic")
|| path.ends_with("::emit_now"))
{
return Some("Log");
}
if crate_name == "arboard" {
let m = path.rsplit("::").next().unwrap_or(path);
if m == "new"
|| m == "get"
|| m == "set"
|| m == "clear"
|| m == "get_text"
|| m == "set_text"
|| m == "set_html"
|| m == "get_image"
|| m == "set_image"
|| m == "text"
|| m == "image"
|| m == "html"
|| m == "file_list"
|| m == "default"
{
return Some("Clipboard");
}
return None;
}
if crate_name == "etcetera" {
let m = path.rsplit("::").next().unwrap_or(path);
if m == "home_dir"
|| m == "choose_base_strategy" || m == "choose_native_strategy" || m == "choose_app_strategy"
|| m == "config_dir" || m == "data_dir" || m == "cache_dir"
|| m == "state_dir" || m == "runtime_dir" || m == "data_local_dir"
{
return Some("Env");
}
return None;
}
if crate_name == "sqlx_core" {
if path.ends_with("::connect") || path.ends_with("::connect_with") {
return Some("Net");
}
if let Some(effect) = sqlx_r1528("sqlx_core", path) {
return Some(effect);
}
if path.ends_with("::fetch") || path.ends_with("::fetch_all") || path.ends_with("::fetch_one")
|| path.ends_with("::fetch_optional") || path.ends_with("::fetch_many")
|| path.ends_with("::execute") || path.ends_with("::execute_many")
|| path.ends_with("::prepare") || path.ends_with("::prepare_with")
|| path.ends_with("::acquire") || path.ends_with("::begin") || path.ends_with("::ping")
{
return Some("Db");
}
if path == "sqlx_core::fs::read"
|| path == "sqlx_core::fs::read_to_string"
|| path == "sqlx_core::fs::create_dir_all"
|| path == "sqlx_core::fs::remove_file"
|| path == "sqlx_core::fs::remove_dir"
|| path == "sqlx_core::fs::remove_dir_all"
|| path == "sqlx_core::fs::read_dir"
|| path.ends_with("::migrate::resolve_blocking")
|| path.ends_with("::migrate::resolve_blocking_with_config")
|| path == "sqlx_core::config::Config::try_from_path"
|| path == "sqlx_core::Config::try_from_path"
|| path == "sqlx_core::config::Config::try_from_path_or_default"
|| path == "sqlx_core::Config::try_from_path_or_default"
|| path == "sqlx_core::config::Config::try_from_crate_or_default"
|| path == "sqlx_core::Config::try_from_crate_or_default"
{
return Some("Fs");
}
if path.ends_with("::net::tls::handshake") {
return Some("Net");
}
return None;
}
if crate_name == "walkdir" {
if path.ends_with("::WalkDir::new")
|| path.ends_with("::IntoIter::next")
|| path.ends_with("::DirEntry::metadata")
{
return Some("Fs");
}
return None;
}
if crate_name == "filetime" {
if path.ends_with("::set_file_mtime") || path.ends_with("::set_file_atime")
|| path.ends_with("::set_file_times") || path.ends_with("::set_symlink_file_times")
|| path.ends_with("::set_file_handle_times")
{
return Some("Fs");
}
if path.ends_with("::FileTime::now") {
return Some("Clock");
}
return None;
}
if crate_name == "execute" {
if path.contains("::execute") {
return Some("Exec");
}
return None;
}
if crate_name == "ctrlc" {
if path.ends_with("::set_handler") || path.ends_with("::try_set_handler") {
return Some("Ipc");
}
return None;
}
if crate_name == "clap" {
if path.ends_with("::get_matches") || path.ends_with("::get_matches_mut")
|| path.ends_with("::try_get_matches")
|| path.ends_with("::parse") || path.ends_with("::try_parse")
|| path.ends_with("::env") || path.ends_with("::env_os")
{
return Some("Env");
}
return None;
}
if crate_name == "jiff" {
if path.ends_with("::now") || path.ends_with("::now_with") {
return Some("Clock");
}
if path.ends_with("::TimeZone::system") || path.ends_with("::TimeZone::get")
|| path.ends_with("::TimeZoneDatabase::get")
|| path.ends_with("::TimeZone::try_system")
{
return Some("Fs");
}
if let Some((ty, m)) = type_method(
path,
"jiff",
&["", "civil", "civil::date", "civil::datetime", "timestamp", "zoned", "tz", "tz::db", "fmt", "fmt::strtime",
"fmt::temporal", "fmt::temporal::pieces", "fmt::temporal::mod"],
) {
if matches!(
(ty, m),
("Date" | "DateTime" | "Timestamp" | "Zoned", "in_tz")
| ("TimeZoneDatabase", "from_env" | "from_dir" | "from_concatenated_path")
| ("DateTimeParser", "parse_zoned" | "parse_time_zone")
| ("BrokenDownTime", "to_zoned")
| ("Pieces" | "TimeZoneAnnotation", "to_time_zone")
) {
return Some("Fs");
}
}
if path == "jiff::db" || path == "jiff::tz::db" || path == "jiff::tz::db::db" {
return Some("Fs");
}
return None;
}
if crate_name == "env_logger" {
if path.ends_with("::init") || path.ends_with("::try_init")
|| path.ends_with("::init_from_env") || path.ends_with("::try_init_from_env")
{
return Some("Log");
}
return None;
}
if crate_name == "dialoguer" {
if path.ends_with("::interact") || path.ends_with("::interact_on")
|| path.ends_with("::interact_text") || path.ends_with("::interact_text_on")
|| path.ends_with("::interact_opt") || path.ends_with("::interact_on_opt")
{
return Some("Ipc");
}
if path.ends_with("Editor::edit") {
return Some("Exec");
}
if path.ends_with("Editor::new") || path.ends_with("Editor::default") {
return Some("Env");
}
return None;
}
if crate_name == "tracing_subscriber" {
if path.ends_with("::init") || path.ends_with("::try_init") {
return Some("Log");
}
if path.ends_with("::fmt::Layer::new") || path.ends_with("::fmt_layer::Layer::new") {
return Some("Env");
}
if path == "tracing_subscriber::fmt::layer" || path == "tracing_subscriber::fmt::fmt"
|| path == "tracing_subscriber::fmt"
|| path.ends_with("::fmt::Layer::default") || path.ends_with("::fmt_layer::Layer::default")
|| path == "tracing_subscriber::FmtSubscriber::builder" || path.ends_with("::fmt::Subscriber::builder")
|| path.ends_with("::fmt::Subscriber::default") || path.ends_with("::fmt::SubscriberBuilder::default")
{
return Some("Env");
}
if let Some((ty, m)) = type_method(
path,
"tracing_subscriber",
&["", "fmt", "fmt::time", "fmt::time::time_crate", "fmt::time::chrono_crate", "time"],
) {
if (m == "format_time"
&& matches!(ty, "SystemTime" | "UtcTime" | "LocalTime" | "OffsetTime" | "ChronoLocal" | "ChronoUtc"))
|| (ty == "Uptime" && m == "default")
|| (ty == "OffsetTime" && m == "local_rfc_3339")
{
return Some("Clock");
}
}
if path == "tracing_subscriber::uptime" || path == "tracing_subscriber::fmt::uptime"
|| path == "tracing_subscriber::fmt::time::uptime"
{
return Some("Clock");
}
if path.ends_with("::from_default_env") || path.ends_with("::try_from_default_env")
|| path.ends_with("::from_env") || path.ends_with("::from_env_lossy")
|| path.ends_with("::try_from_env")
{
return Some("Env");
}
return None;
}
if crate_name == "crossterm" {
if let Some(effect) = crossterm_r1528(path) {
return Some(effect);
}
if path.ends_with("::execute") || path.ends_with("::queue")
|| path.ends_with("::event::read") || path.ends_with("::event::poll")
|| path.ends_with("::enable_raw_mode") || path.ends_with("::disable_raw_mode")
|| path.ends_with("::size") || path.ends_with("::window_size")
|| path.ends_with("::is_raw_mode_enabled")
{
return Some("Ipc");
}
if path.ends_with("::supports_keyboard_enhancement") {
return Some("Ipc");
}
return None;
}
if crate_name == "ratatui" {
if path.contains("::canvas::") {
return None;
}
if path.ends_with("::draw") || path.ends_with("::try_draw") || path.ends_with("::flush")
|| path.ends_with("::autoresize") || path.ends_with("::clear")
|| path.ends_with("::hide_cursor") || path.ends_with("::show_cursor")
|| path.ends_with("::insert_before")
|| path.ends_with("::set_cursor_position") || path.ends_with("::get_cursor_position")
{
return Some("Ipc");
}
return None;
}
if crate_name == "console" {
if path.ends_with("::write_line") || path.ends_with("::read_line")
|| path.ends_with("::read_line_initial_text") || path.ends_with("::read_char")
|| path.ends_with("::read_key") || path.ends_with("::read_key_raw")
|| path.ends_with("::read_secure_line")
|| path.ends_with("Term::write") || path.ends_with("Term::flush")
|| path.ends_with("Term::read")
{
return Some("Ipc");
}
if path.ends_with("::colors_enabled") || path.ends_with("::colors_enabled_stderr")
|| path.ends_with("::user_attended") || path.ends_with("::user_attended_stderr")
{
return Some("Env");
}
return None;
}
if crate_name == "terminal_colorsaurus" {
if path.ends_with("::background_color") || path.ends_with("::foreground_color")
|| path.ends_with("::color_palette")
|| path == "terminal_colorsaurus::theme_mode"
{
return Some("Ipc");
}
return None;
}
if crate_name == "backoff" {
if path.ends_with("::retry") || path.ends_with("::retry_notify") {
return Some("Clock");
}
return None;
}
if crate_name == "lscolors" {
if path.ends_with("::from_env") {
return Some("Env");
}
return None;
}
if crate_name == "wild" {
if path.ends_with("::args") || path.ends_with("::args_os") {
return Some("Env");
}
return None;
}
if crate_name == "grep_cli" {
if path.ends_with("::build") {
return Some("Exec");
}
if path == "grep_cli::CommandReader::new"
|| path == "grep_cli::CommandReader::close"
|| path == "grep_cli::CommandReader::read"
|| path == "grep_cli::DecompressionMatcher::command"
|| path == "grep_cli::DecompressionReader::new"
|| path == "grep_cli::DecompressionReader::close"
|| path == "grep_cli::DecompressionReader::read"
|| path == "grep_cli::decompress::DecompressionReader::close"
|| path == "grep_cli::decompress::DecompressionReader::read"
|| path == "grep_cli::process::CommandReader::close"
|| path == "grep_cli::process::CommandReader::read"
{
return Some("Exec");
}
if path == "grep_cli::patterns_from_path" {
return Some("Fs");
}
return None;
}
if crate_name == "clircle" {
if path.ends_with("::try_from") || path.ends_with("::surely_conflicts_with") {
return Some("Fs");
}
return None;
}
None
}
pub fn cap_from_name(name: &str) -> Option<&'static str> {
EFFECTS.iter().copied().find(|e| *e == name)
}
pub fn fs_kind(path: &str) -> &'static [&'static str] {
let leaf = path.rsplit("::").next().unwrap_or(path);
if path.rsplit("::").nth(1) == Some("OpenOptions") {
return &[];
}
if matches!(leaf, "copy" | "rename" | "hard_link" | "soft_link" | "symlink") {
return &["read", "write"];
}
const WRITE: &[&str] = &[
"write", "write_all", "write_fmt", "write_vectored", "create", "create_new", "create_dir",
"create_dir_all", "remove_file", "remove_dir", "remove_dir_all", "set_permissions",
"set_len", "set_modified", "set_times", "append", "flush", "sync_all", "sync_data",
"write_at", "truncate",
];
const READ: &[&str] = &[
"read", "read_to_string", "read_to_end", "read_exact", "read_dir", "read_link",
"metadata", "symlink_metadata", "exists", "try_exists", "canonicalize", "open",
"read_at", "file_type", "permissions", "modified", "accessed", "created", "len",
];
if WRITE.contains(&leaf) { return &["write"]; }
if READ.contains(&leaf) { return &["read"]; }
if leaf.starts_with("write") || leaf.starts_with("append") { return &["write"]; }
if leaf.starts_with("read") { return &["read"]; }
&[]
}
pub fn classify_command_head(cmd: &str) -> &'static [&'static str] {
match cmd.rsplit(['/', '\\']).next().unwrap_or(cmd) {
"curl" | "wget" | "http" | "ssh" | "scp" | "sftp" | "ftp" | "telnet" => &["Net"],
"psql" | "mysql" | "sqlite3" | "mongosh" | "mongo" | "redis-cli" | "cqlsh" | "influx" => &["Db"],
"candor" | "candor-run.sh" | "candor-scan" | "candor-query" | "candor-java"
| "candor-classify" | "candor-report" | "cargo-candor" => &["Env", "Fs"],
_ => &[],
}
}
pub const MODEL_HOSTS: &[&str] = &[
"api.openai.com",
"api.anthropic.com",
"generativelanguage.googleapis.com",
"api.mistral.ai",
"api.cohere.ai",
"api.cohere.com",
"api.groq.com",
"api.together.xyz",
"api.perplexity.ai",
"openrouter.ai",
];
pub fn is_model_host(host_literal: &str) -> bool {
let host = policy::host_part(host_literal).to_ascii_lowercase();
if let Some((_, port)) = host_literal.rsplit_once(':') {
if port == "11434" {
return matches!(host.as_str(), "localhost" | "127.0.0.1" | "::1");
}
}
if MODEL_HOSTS.contains(&host.as_str()) {
return true;
}
if MODEL_HOSTS.iter().any(|m| host.ends_with(&format!(".{m}"))) {
return true;
}
host.ends_with(".amazonaws.com")
&& matches!(host.split('.').next(), Some("bedrock-runtime") | Some("bedrock-agent-runtime"))
}
pub const TELEMETRY_HOSTS: &[&str] = &[
"sentry.io",
"bugsnag.com",
"rollbar.com",
"segment.io",
"segment.com",
"mixpanel.com",
"amplitude.com",
"google-analytics.com",
"analytics.google.com",
"datadoghq.com",
"datadoghq.eu",
"newrelic.com",
"nr-data.net",
"honeycomb.io",
"logtail.com",
"posthog.com",
"plausible.io",
"usefathom.com",
"heapanalytics.com",
"fullstory.com",
"hotjar.com",
"logrocket.com",
"cloudflareinsights.com",
];
pub fn host_in_set(host_literal: &str, set: &[&str]) -> bool {
let host = policy::host_part(host_literal).to_ascii_lowercase();
set.contains(&host.as_str()) || set.iter().any(|e| host.ends_with(&format!(".{e}")))
}
pub fn is_telemetry_host(host_literal: &str) -> bool {
host_in_set(host_literal, TELEMETRY_HOSTS)
}
pub fn net_dest_class(host_literal: &str, partners: &std::collections::BTreeSet<String>) -> &'static str {
if is_telemetry_host(host_literal) {
return "known-telemetry";
}
if partner_for(host_literal, partners).is_some() || is_model_host(host_literal) {
return "known-partner";
}
"unknown-host"
}
pub fn partner_for(
host_literal: &str,
partners: &std::collections::BTreeSet<String>,
) -> Option<String> {
if partners.is_empty() {
return None;
}
let host = policy::host_part(host_literal).to_ascii_lowercase();
if partners.contains(&host) {
return Some(host);
}
partners
.iter()
.find(|p| host.ends_with(&format!(".{p}")))
.cloned()
}
pub const NET_DEST_CLASSES: &[&str] = &["known-telemetry", "known-partner", "unknown-host"];
pub const MODEL_SDK_CRATES: &[&str] = &[
"async_openai", "anthropic_sdk", "anthropic", "aws_sdk_bedrockruntime", "ollama_rs", "langchain_rust", "mistralai", "genai", ];
pub fn is_model_sdk_crate(crate_name: &str) -> bool {
MODEL_SDK_CRATES.contains(&crate_name)
}
pub const LIBC_FS: &[&str] = &[
"open", "open64", "openat", "openat2", "creat", "creat64", "stat", "stat64", "lstat",
"lstat64", "fstatat", "fstatat64", "newfstatat", "statx", "access", "faccessat",
"faccessat2", "mkdir", "mkdirat", "rmdir", "unlink", "unlinkat", "rename", "renameat",
"renameat2", "link", "linkat", "symlink", "symlinkat", "readlink", "readlinkat", "chmod",
"fchmodat", "chown", "lchown", "fchownat", "truncate", "truncate64", "ftruncate",
"ftruncate64", "opendir", "fdopendir", "readdir", "readdir64", "readdir_r", "closedir",
"rewinddir", "seekdir", "telldir", "scandir", "mkstemp", "mkstemps", "mkostemp", "mkdtemp",
"mknod", "mknodat", "chdir", "fchdir", "getcwd", "get_current_dir_name", "chroot",
"pivot_root", "statfs", "statfs64", "fstatfs", "fstatfs64", "statvfs", "fstatvfs", "mount",
"umount", "umount2", "fsync", "fdatasync", "sync", "syncfs", "sync_file_range", "fallocate",
"posix_fallocate", "posix_fadvise", "sendfile", "sendfile64", "copy_file_range", "flock",
"getdents", "getdents64", "utime", "utimes", "lutimes", "futimens", "utimensat", "futimesat",
"realpath",
];
pub const LIBC_NET: &[&str] = &[
"socket", "setsockopt", "getsockopt", "bind", "listen", "accept", "accept4", "connect",
"shutdown", "send", "sendto", "sendmsg", "sendmmsg", "recv", "recvfrom", "recvmsg",
"recvmmsg", "getpeername", "getsockname", "getaddrinfo", "freeaddrinfo", "getnameinfo",
];
pub const LIBC_EXEC: &[&str] = &[
"fork", "vfork", "clone", "clone3", "execl", "execlp", "execle", "execv", "execvp",
"execvpe", "execve", "execveat", "fexecve", "posix_spawn", "posix_spawnp", "system",
"popen", "pclose", "wait", "waitpid", "wait3", "wait4", "waitid",
];
fn r1607_active_model_query(path: &str) -> bool {
let Some((head, m)) = path.rsplit_once("::") else { return false };
if head.ends_with("::ActiveModelTrait") || head == "ActiveModelTrait" {
return matches!(
m,
"insert" | "update" | "update_without_returning" | "save" | "delete" | "establish_links" | "establish_links_self"
| "establish_links_self_rev" | "delete_links" | "delete_links_self"
);
}
(head.ends_with("::ModelTrait") || head == "ModelTrait") && m == "delete"
}
fn type_method<'a>(path: &'a str, krate: &str, mods: &[&str]) -> Option<(&'a str, &'a str)> {
let rest = path.strip_prefix(krate)?.strip_prefix("::")?;
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
mods.contains(&module).then_some((ty, method))
}
fn isahc_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("isahc::")?;
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
match (module, ty, method) {
("" | "client", "HttpClient", "get_async" | "head_async" | "post_async" | "put_async" | "delete_async" | "send_async")
| ("" | "request", "Request", "send_async") => Some("Net"),
("" | "tls" | "tls::trust", "TrustStore", "native") => Some("Env"),
_ => None,
}
}
fn lettre_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("lettre::")?;
if matches!(rest, "message::dkim::dkim_sign" | "message::dkim_sign" | "dkim_sign") {
return Some("Clock");
}
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
match (module, ty, method) {
("" | "message", "MessageBuilder" | "Message", "body" | "singlepart" | "multipart" | "date_now") => Some("Clock"),
("" | "message", "Message", "sign") => Some("Clock"),
("" | "message::header" | "message::header::date", "Date", "now") => Some("Clock"),
("" | "message", "MessageBuilder" | "Message", "message_id") => Some("Rand"),
("" | "message" | "message::mimebody", "MultiPartBuilder" | "MultiPart", "kind") => Some("Rand"),
(
"" | "message" | "message::mimebody",
"MultiPart",
"mixed" | "alternative" | "related" | "signed" | "encrypted" | "alternative_plain_html",
) => Some("Rand"),
("" | "transport::file", "AsyncFileTransport", "read") => Some("Fs"),
("" | "executor", "Executor" | "Tokio1Executor" | "AsyncStd1Executor", "fs_read" | "fs_write") => Some("Fs"),
_ => None,
}
}
fn http_header_get_r1604(path: &str) -> bool {
matches!(
path,
"reqwest::header::HeaderMap::get"
| "reqwest::Response::get"
| "reqwest::blocking::Response::get"
| "reqwest::Request::get"
| "reqwest::blocking::Request::get"
| "isahc::Response::get"
| "isahc::http::Response::get"
| "isahc::http::response::Response::get"
| "isahc::http::HeaderMap::get"
| "isahc::http::header::HeaderMap::get"
)
}
fn lettre_stub_send_r1604(path: &str) -> bool {
matches!(
path,
"lettre::transport::stub::StubTransport::send"
| "lettre::transport::stub::StubTransport::send_raw"
| "lettre::transport::stub::AsyncStubTransport::send"
| "lettre::transport::stub::AsyncStubTransport::send_raw"
)
}
fn lettre_send_r1597(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("lettre::")?;
let (head, method) = rest.rsplit_once("::")?;
if !matches!(method, "send" | "send_raw") {
return None;
}
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
match (module, ty) {
("" | "transport::file", "FileTransport" | "AsyncFileTransport") => Some("Fs"),
("" | "transport::sendmail", "SendmailTransport" | "AsyncSendmailTransport") => Some("Exec"),
_ => None,
}
}
fn tempfile_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("tempfile::")?;
if matches!(rest, "temp_dir" | "env::temp_dir") {
return Some("Env");
}
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
match (module, ty, method) {
("" | "spooled", "SpooledTempFile", "into_file" | "roll") => Some("Fs"),
_ => None,
}
}
fn tungstenite_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("tungstenite::")?;
if matches!(rest, "handshake::client::generate_key" | "client::generate_key" | "generate_key") {
return Some("Rand");
}
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
match (module, ty, method) {
("" | "http" | "client" | "http::uri", "Uri", "into_client_request") => Some("Rand"),
("" | "client", "ClientRequestBuilder", "into_client_request") => Some("Rand"),
("" | "stream", "MaybeTlsStream" | "TcpStream" | "NoDelay", "set_nodelay") => Some("Net"),
("" | "protocol", "WebSocket", "write_pending") => Some("Net"),
_ => None,
}
}
fn b11_r1528(crate_name: &str, path: &str) -> Option<Option<&'static str>> {
let rest = path.strip_prefix(crate_name)?.strip_prefix("::")?;
match (crate_name, rest) {
("console", "is_dumb" | "term::is_dumb") => return Some(Some("Env")),
("console", "set_colors_enabled" | "utils::set_colors_enabled" | "set_colors_enabled_stderr"
| "utils::set_colors_enabled_stderr" | "set_true_colors_enabled" | "utils::set_true_colors_enabled"
| "set_true_colors_enabled_stderr" | "utils::set_true_colors_enabled_stderr" | "true_colors_enabled"
| "utils::true_colors_enabled" | "true_colors_enabled_stderr" | "utils::true_colors_enabled_stderr") => {
return Some(Some("Env"))
}
("rand", "make_rng") => return Some(Some("Rand")),
_ => {}
}
let (head, method) = rest.rsplit_once("::")?;
let ty = head.rsplit("::").next().unwrap_or(head);
let hit = |e: &'static str| Some(Some(e));
match (crate_name, ty, method) {
("env_logger", "Formatter", "timestamp" | "timestamp_seconds" | "timestamp_millis" | "timestamp_micros" | "timestamp_nanos") => hit("Clock"),
("env_logger", "ConfigurableFormat", "format") => hit("Clock"),
("elasticsearch", "Transport", "single_node" | "static_node_list" | "sniffing_node_list" | "cloud") => hit("Env"),
("elasticsearch", "TransportBuilder", "build") => hit("Env"),
("elasticsearch", "MultiNodeConnectionPool", "reseed") => hit("Clock"),
("tokio_postgres" | "deadpool_postgres" | "postgres", "Client" | "Transaction" | "ClientWrapper", "execute_raw" | "execute_typed"
| "query_typed_raw" | "query_typed_one" | "query_typed_opt" | "query_scalar" | "query_one_scalar"
| "query_opt_scalar" | "bind" | "bind_raw" | "query_portal" | "query_portal_raw" | "commit" | "rollback"
| "savepoint") => hit("Db"),
("tokio_postgres" | "deadpool_postgres" | "postgres", "Client" | "ClientWrapper", "simple_query_raw" | "check_connection") => hit("Db"),
("deadpool_postgres", "GenericClient", "execute_raw") => hit("Db"),
("tokio_postgres", "ToStatementType", "into_statement") => hit("Db"),
("grep_cli", "DecompressionMatcherBuilder", "build") => Some(None),
("grep_cli", "DecompressionMatcherBuilder", "associate" | "try_associate") => hit("Env"),
("backoff", "ExponentialBackoff", "get_elapsed_time" | "reset" | "default") => hit("Clock"),
("backoff", "ExponentialBackoff", "next_backoff") => hit("Rand"),
("backoff", "ExponentialBackoffBuilder", "build") => hit("Clock"),
("backoff", "SystemClock", "now") => hit("Clock"),
("rustls", "ClientConnection" | "UnbufferedClientConnection", "new" | "new_with_alpn") => hit("Rand"),
("etcetera", "Apple" | "Xdg" | "Unix" | "Windows", "new") => hit("Env"),
("time", "Instant", "elapsed") => hit("Clock"),
("time", "SignedDuration" | "Duration", "time_fn") => hit("Clock"),
("time", "UtcOffset", "current_local_offset") => hit("Clock"),
("portable_pty", "CommandBuilder", "new" | "from_argv" | "new_default_prog") => hit("Env"),
("notify", "PollWatcher", "with_initial_scan") => hit("Clock"),
("native_tls_crate" | "native_tls", "TlsConnectorBuilder", "build") => hit("Fs"),
("duct", "Handle", "wait_timeout" | "wait_deadline") => hit("Clock"),
("dotenvy", "Iter", "load_override") => hit("Env"),
_ => None,
}
}
fn crossterm_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("crossterm::")?;
match rest {
"style::available_color_count" | "available_color_count" | "style::force_color_output" | "force_color_output" => {
return Some("Env")
}
"cursor::position" | "position" | "cursor::sys::unix::position" | "cursor::sys::position" => return Some("Ipc"),
_ => {}
}
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
match (module, ty, method) {
(
"" | "style" | "style::types" | "style::types::colored",
"Colored",
"ansi_color_disabled" | "ansi_color_disabled_memoized" | "set_ansi_color_disabled",
) => Some("Env"),
("" | "event" | "event::stream", "EventStream", "new" | "next" | "poll_next") => Some("Ipc"),
_ => None,
}
}
fn reqwest_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("reqwest::")?;
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
match (module, ty, method) {
("" | "async_impl::client" | "blocking" | "blocking::client", "ClientBuilder" | "Client", "build") => Some("Env"),
("" | "blocking" | "blocking::client", "Client", "new") => Some("Env"),
("" | "multipart" | "async_impl::multipart" | "blocking::multipart", "Form", "file") => Some("Fs"),
("" | "proxy", "NoProxy", "from_env") => Some("Env"),
_ => None,
}
}
fn mysql_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("mysql::")?;
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
match (module, ty, method) {
("" | "conn", "Conn", "reset" | "change_user" | "start_transaction" | "get_binlog_stream") => Some("Db"),
("" | "conn::pool", "PooledConn", "change_user" | "start_transaction" | "get_binlog_stream") => Some("Db"),
("" | "conn::pool", "Pool", "new" | "try_get_conn" | "start_transaction") => Some("Db"),
_ => None,
}
}
fn diesel_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("diesel::")?;
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
match (module, ty, method) {
("" | "sqlite" | "sqlite::connection" | "pg" | "pg::connection" | "connection", "SqliteConnection" | "PgConnection" | "SimpleConnection", "batch_execute") => Some("Db"),
(
"" | "sqlite" | "sqlite::connection",
"SqliteConnection",
"immediate_transaction" | "exclusive_transaction" | "serialize_database_to_buffer" | "deserialize_readonly_database_from_buffer",
) => Some("Db"),
("" | "connection" | "connection::transaction_manager", "AnsiTransactionManager", "begin_transaction_sql") => Some("Db"),
("" | "sqlite" | "sqlite::connection" | "pg" | "pg::connection" | "connection", "SqliteConnection" | "PgConnection" | "Connection", "transaction") => {
Some("Db")
}
("" | "pg" | "pg::transaction", "TransactionBuilder", "run") => Some("Db"),
("" | "pg" | "pg::connection", "PgConnection", "run") => Some("Db"),
_ => None,
}
}
fn lapin_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("lapin::")?;
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
match (module, ty, method) {
(
"" | "connection",
"Connection",
"connect_uri" | "connect_uri_with_runtime" | "connect_uri_with_config" | "connect_with_config"
| "connect_with_runtime" | "update_secret",
) => Some("Net"),
("" | "connection" | "uri", "AMQPUri" | "Connect", "connect_with_config") => Some("Net"),
("" | "channel" | "generated::channel", "Channel", "access_request" | "channel_flow") => Some("Net"),
("" | "acker", "Acker", "ack" | "nack" | "reject") => Some("Net"),
_ => None,
}
}
fn tonic_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("tonic::")?;
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
match (module, ty, method) {
("" | "transport" | "transport::server" | "server", "Server", "serve" | "serve_with_shutdown") => Some("Net"),
("" | "transport" | "transport::server" | "transport::server::incoming" | "server::incoming", "TcpIncoming", "bind") => {
Some("Net")
}
_ => None,
}
}
fn aws_config_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("aws_config::")?;
match rest {
"default_provider::endpoint_url::endpoint_url_provider"
| "default_provider::endpoint_url::endpoint_url_provider_with_origin"
| "default_provider::ignore_configured_endpoint_urls::ignore_configured_endpoint_urls_provider"
| "default_provider::checksums::request_checksum_calculation_provider"
| "default_provider::checksums::response_checksum_validation_provider"
| "default_provider::use_dual_stack::use_dual_stack_provider"
| "default_provider::use_fips::use_fips_provider" => return Some("Fs"),
"default_provider::credentials::default_provider" | "default_provider::token::default_provider" => {
return Some("Net")
}
_ => {}
}
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
match (module, ty, method) {
("default_provider::app_name", "Builder", "app_name")
| ("default_provider::retry_config", "Builder", "retry_config")
| ("profile::region", "ProfileFileRegionProvider", "region") => Some("Fs"),
("default_provider::region", "DefaultRegionChain", "region")
| ("imds::region", "ImdsRegionProvider", "region")
| ("provider_config", "ProviderConfig", "load_default_region" | "with_default_region")
| ("default_provider::credentials", "DefaultCredentialsChain" | "Builder", "build")
| ("default_provider::token", "DefaultTokenChain" | "Builder", "build")
| ("sts" | "sts::assume_role", "AssumeRoleProvider" | "AssumeRoleProviderBuilder", "build" | "build_from_provider")
| ("sso::token", "SsoTokenProvider" | "Builder", "build")
| ("ecs", "EcsCredentialsProvider", "credentials")
| ("meta::credentials::chain" | "meta::credentials" | "", "CredentialsProviderChain", "default_provider" | "or_default_provider")
| ("meta::token" | "", "TokenProviderChain", "default_provider" | "or_default_provider") => Some("Net"),
_ => None,
}
}
fn sqlx_r1528(krate: &str, path: &str) -> Option<&'static str> {
let rest = path.strip_prefix(krate)?.strip_prefix("::")?;
if krate == "sqlx_core" {
match rest {
"net::connect_tcp" | "net::socket::connect_tcp" => return Some("Net"),
"migrate::source::resolve_blocking" | "migrate::source::resolve_blocking_with_config" => {
return Some("Fs")
}
_ => {}
}
}
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
let pool = ty == "Pool" || (krate == "sqlx" && ty.ends_with("Pool"));
if pool && matches!(module, "" | "pool" | "postgres" | "mysql" | "sqlite" | "any") && method == "begin_with" {
return Some("Db");
}
if krate == "sqlx"
&& method == "connect_with"
&& matches!(module, "" | "pool" | "mysql" | "postgres" | "sqlite" | "any")
&& (ty.ends_with("Connection") || ty.ends_with("Pool") || ty.ends_with("PoolOptions"))
{
return Some("Db");
}
if krate == "sqlx" {
if let Some(effect) = sqlx_r1623(module, ty, method) {
return Some(effect);
}
}
match (module, ty, method) {
("" | "pool" | "pool::connection", "PoolConnection", "close") => Some("Net"),
("" | "pool" | "pool::connection", "PoolConnection", "return_to_pool") => Some("Db"),
("" | "migrate" | "migrate::migrator", "Migrator", "new") => Some("Fs"),
("" | "migrate" | "migrate::migrator", "Migrator", "run" | "run_to" | "skip" | "undo" | "run_direct") => Some("Db"),
("fs", "ReadDir", "next") if krate == "sqlx_core" => Some("Fs"),
("logger", "QueryLogger", "new") if krate == "sqlx_core" => Some("Clock"),
("logger", "QueryLogger", "finish") if krate == "sqlx_core" => Some("Log"),
_ => None,
}
}
fn sqlx_r1623(module: &str, ty: &str, method: &str) -> Option<&'static str> {
if !matches!(module, "" | "postgres" | "mysql" | "sqlite" | "any" | "pool") {
return None;
}
let pg_mod = matches!(module, "" | "postgres");
match (ty, method) {
("PgConnectOptions", "new" | "new_without_pgpass" | "default" | "from_str" | "from_url") if pg_mod => Some("Env"),
("PgPool" | "PgPoolOptions", "connect_lazy") if pg_mod => Some("Env"),
("PgListener", "connect_with") if pg_mod => Some("Db"),
(t, "try_begin") if t == "Pool" || t.ends_with("Pool") => Some("Db"),
_ => None,
}
}
fn redis_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("redis::")?;
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
let cluster_mod = matches!(
module,
"cluster" | "cluster_async" | "cluster_handling::sync_connection" | "cluster_handling::async_connection"
);
let hit = match ty {
"Client" => {
matches!(module, "" | "client")
&& matches!(method, "is_open" | "check_connection" | "get_async_pubsub" | "get_async_monitor")
}
"Cmd" => matches!(module, "" | "cmd") && method == "iter_async",
"PubSub" => {
matches!(module, "" | "connection")
&& matches!(method, "subscribe" | "psubscribe" | "unsubscribe" | "punsubscribe" | "ping" | "ping_message")
}
"MultiplexedConnection" => {
(matches!(module, "aio" | "aio::multiplexed_connection")
&& matches!(method, "send_packed_command" | "send_packed_commands" | "connect_with_config"))
|| (cluster_mod && method == "connect_with_config")
}
"ClusterConnection" => cluster_mod && method == "route_command",
"ClusterPipeline" => {
(cluster_mod || module == "cluster_handling::sync_connection::pipeline") && method == "exec"
}
"ClusterClient" => {
matches!(module, "cluster" | "cluster_handling::client")
&& method == "get_pending_async_connection_with_config"
}
_ => false,
};
if hit {
return Some("Db");
}
let rand = match ty {
"RandomReplicaStrategy" => {
matches!(module, "cluster_read_routing" | "cluster_handling::read_routing::random_replica")
&& method == "route_read"
}
"Replicas" => {
matches!(module, "cluster_read_routing" | "cluster_handling::read_routing::interface")
&& method == "choose_random"
}
_ => false,
};
rand.then_some("Rand")
}
fn async_nats_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("async_nats::")?;
if rest == "datetime::now" {
return Some("Clock");
}
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
let js = |m: &str| module == "jetstream" || module == m;
let hit = match ty {
"Context" => {
js("jetstream::context")
&& matches!(
method,
"query_account" | "create_stream" | "get_stream" | "get_or_create_stream" | "delete_stream"
| "update_stream" | "create_or_update_stream" | "stream_by_subject" | "send_publish"
| "send_request" | "get_key_value" | "create_key_value" | "update_key_value"
| "create_or_update_key_value" | "delete_key_value" | "get_consumer_from_stream"
| "delete_consumer_from_stream" | "create_consumer_on_stream" | "update_consumer_on_stream"
| "create_consumer_strict_on_stream" | "create_object_store" | "get_object_store"
| "delete_object_store"
)
}
"Stream" | "DirectGetBuilder" | "RawMessageBuilder" | "StreamInfoBuilder" => {
js("jetstream::stream")
&& matches!(
method,
"info" | "get_info" | "info_with_subjects" | "consumer_info" | "create_consumer"
| "create_consumer_strict" | "update_consumer" | "get_consumer" | "get_or_create_consumer"
| "delete_consumer" | "pause_consumer" | "resume_consumer" | "reset_consumer"
| "unpin_consumer"
| "delete_message" | "purge_subject" | "direct_get" | "direct_get_first_for_subject"
| "direct_get_last_for_subject" | "direct_get_next_for_subject" | "get_raw_message"
| "get_first_raw_message_by_subject" | "get_next_raw_message_by_subject"
| "get_last_raw_message_by_subject" | "send" | "fetch"
)
}
"Store" => {
module == "jetstream::kv"
&& matches!(
method,
"create" | "create_with_ttl" | "put" | "entry" | "entry_for_revision" | "get" | "update"
| "delete" | "delete_expect_revision" | "purge" | "purge_with_ttl"
| "purge_expect_revision" | "purge_expect_revision_with_ttl" | "history" | "keys"
| "watch" | "watch_many" | "watch_from_revision" | "watch_with_history"
| "watch_many_with_history" | "watch_all" | "watch_all_from_revision"
)
}
"ObjectStore" => {
module == "jetstream::object_store"
&& matches!(
method,
"get" | "delete" | "info" | "put" | "watch" | "watch_with_history" | "list" | "seal"
| "update_metadata" | "add_link" | "add_bucket_link"
)
}
"Consumer" | "PullConsumer" | "PushConsumer" | "OrderedPullConsumer" | "OrderedPushConsumer" => {
matches!(module, "jetstream::consumer" | "jetstream::consumer::pull" | "jetstream::consumer::push")
&& matches!(method, "info" | "get_info" | "reset" | "messages")
}
"StreamBuilder" | "FetchBuilder" | "BatchBuilder" => {
module == "jetstream::consumer::pull" && method == "messages"
}
"Message" | "Acker" => {
js("jetstream::message") && matches!(method, "ack" | "ack_with" | "double_ack" | "double_ack_with")
}
"Client" if matches!(module, "" | "client" | "service") => {
return match method {
"add_service" | "start" | "send_request" => Some("Net"),
"new_inbox" => Some("Rand"),
_ => None,
};
}
"ServiceBuilder" => module == "service" && method == "start",
"Service" | "Group" | "EndpointBuilder" => {
module == "service" && matches!(method, "endpoint" | "add")
}
_ => false,
};
if !hit {
return None;
}
Some("Net")
}
fn rdkafka_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("rdkafka::")?;
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
let from_config = matches!(method, "from_config" | "from_config_and_context");
let txn = matches!(method, "init_transactions" | "commit_transaction" | "abort_transaction" | "send_offsets_to_transaction");
let consumer_net = matches!(method, "committed" | "offsets_for_timestamp" | "incremental_assign" | "seek_partitions");
let hit = match ty {
"ClientConfig" => matches!(module, "" | "config") && matches!(method, "create" | "create_with_context"),
"Client" => matches!(module, "" | "client") && method == "new",
"MockCluster" => matches!(module, "" | "mocking") && method == "new",
"AdminClient" => {
matches!(module, "" | "admin")
&& (from_config
|| matches!(
method,
"create_topics" | "delete_topics" | "create_partitions" | "delete_groups" | "delete_records"
| "describe_configs" | "alter_configs"
))
}
"BaseConsumer" => {
matches!(module, "" | "consumer" | "consumer::base_consumer") && (from_config || consumer_net)
}
"StreamConsumer" => {
matches!(module, "" | "consumer" | "consumer::stream_consumer") && (from_config || consumer_net)
}
"BaseProducer" | "ThreadedProducer" => {
matches!(module, "" | "producer" | "producer::base_producer") && (from_config || txn)
}
"FutureProducer" => {
matches!(module, "" | "producer" | "producer::future_producer") && (from_config || txn)
}
"Timestamp" => {
return (matches!(module, "" | "message") && method == "now").then_some("Clock");
}
"util" => {
return (module.is_empty() && method == "current_time_millis").then_some("Clock");
}
_ => false,
};
hit.then_some("Net")
}
fn mongodb_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("mongodb::")?;
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
let consumer = module.is_empty() || module == "sync" || module.starts_with("action") || module.starts_with("sync::");
let hit = match (ty, method) {
("ClientSession", "commit_transaction" | "abort_transaction" | "and_run" | "and_run2") => consumer,
("Client", "shutdown" | "bulk_write") => consumer,
("Database", "drop" | "run_cursor_command") => consumer,
("Collection", "drop" | "drop_index" | "drop_indexes" | "list_indexes" | "list_index_names"
| "create_search_index" | "create_search_indexes") => consumer,
("ChangeStream", "next_if_any") => {
matches!(module, "" | "sync" | "change_stream" | "sync::change_stream")
}
("SessionChangeStream", "next" | "next_if_any") => {
matches!(module, "" | "sync" | "change_stream" | "change_stream::session" | "sync::change_stream")
}
("GridFsBucket", "delete") | ("GridFsUploadStream", "abort") => {
matches!(module, "" | "sync" | "gridfs" | "sync::gridfs")
}
("StartTransaction", "and_run" | "and_run2") => true,
("Aggregate" | "AbortTransaction" | "CommitTransaction" | "BulkWrite" | "CountDocuments" | "CreateCollection"
| "CreateSearchIndex" | "DropCollection" | "DropDatabase" | "DropIndex" | "Find" | "FindOneAndDelete"
| "FindOneAndReplace" | "FindOneAndUpdate" | "ListCollections" | "ListDatabases" | "ListIndexes"
| "RunCommand" | "RunCursorCommand" | "Shutdown" | "Watch", "execute" | "batch") => true,
("Delete", "execute") => module.contains("gridfs"),
("Callback", "human" | "machine") => {
return matches!(module, "" | "options::oidc" | "client::auth::oidc").then_some("Clock");
}
_ => false,
};
hit.then_some("Db")
}
fn mysql_async_r1528(path: &str) -> Option<&'static str> {
let rest = path.strip_prefix("mysql_async::")?;
let (head, method) = rest.rsplit_once("::")?;
let (module, ty) = head.rsplit_once("::").unwrap_or(("", head));
if ty == "test_misc" && module.is_empty() {
return matches!(method, "get_opts" | "test_compression" | "test_ssl").then_some("Env");
}
let hit = match ty {
"Conn" => {
matches!(module, "" | "conn" | "conn::binlog_stream" | "queryable" | "queryable::transaction")
&& matches!(method, "change_user" | "reset" | "disconnect" | "get_binlog_stream" | "close" | "start_transaction")
}
"BinlogStream" => matches!(module, "" | "conn::binlog_stream") && method == "close",
"Connection" => matches!(module, "" | "queryable") && method == "close",
"Transaction" => {
matches!(module, "" | "queryable" | "queryable::transaction") && matches!(method, "close" | "commit" | "rollback")
}
"Pool" => {
matches!(module, "" | "conn::pool" | "connection_like") && matches!(method, "start_transaction" | "to_connection")
}
"QueryResult" => {
matches!(module, "" | "queryable::query_result" | "queryable::query_result::result_set_stream")
&& matches!(
method,
"next" | "collect" | "try_collect" | "collect_and_drop" | "try_collect_and_drop" | "for_each"
| "for_each_and_drop" | "map_and_drop" | "reduce" | "reduce_and_drop" | "drop_result"
| "stream" | "stream_and_drop"
)
}
"QueryWithParams" => {
matches!(module, "" | "query")
&& matches!(method, "run" | "batch" | "first" | "fetch" | "ignore" | "reduce" | "stream")
}
"Query" => {
module == "prelude" && matches!(method, "run" | "first" | "fetch" | "ignore" | "reduce" | "stream")
}
"BatchQuery" => module == "prelude" && method == "batch",
"Q" => matches!(module, "" | "query") && method == "run",
_ => false,
};
hit.then_some("Db")
}
pub const PG_DB_VERBS: &[&str] = &[
"::query", "::query_one", "::query_opt", "::query_raw", "::execute",
"::batch_execute", "::simple_query", "::prepare", "::prepare_typed",
"::copy_in", "::copy_out", "::transaction", "::connect",
"::connect_raw",
"::query_row", "::query_map", "::query_and_then", "::execute_batch",
"::prepare_cached", "::query_typed",
"::prepare_typed_cached",
"::query_row_and_then", "::prepare_with_flags",
];
pub const PG_DB_VERBS_NO_SQL: &[&str] = &["::transaction", "::connect", "::connect_raw"];
pub const LIBC_FS_NO_PATH: &[&str] = &[
"ftruncate", "ftruncate64", "fdopendir", "readdir", "readdir64", "readdir_r", "closedir",
"rewinddir", "seekdir", "telldir", "fchdir", "getcwd", "get_current_dir_name", "fstatfs",
"fstatfs64", "fstatvfs", "fsync", "fdatasync", "sync", "syncfs", "sync_file_range", "fallocate",
"posix_fallocate", "posix_fadvise", "sendfile", "sendfile64", "copy_file_range", "flock",
"getdents", "getdents64", "futimens",
];
pub const LIBC_EXEC_NO_PROGRAM: &[&str] = &[
"fork", "vfork", "clone", "clone3", "wait", "waitpid", "wait3", "wait4", "waitid", "pclose",
];
pub const LIBC_NET_NO_DESTINATION: &[&str] = &[
"socket", "setsockopt", "getsockopt", "bind", "listen", "accept", "accept4", "shutdown", "send",
"recv", "recvfrom", "recvmsg", "recvmmsg", "getpeername", "getsockname", "freeaddrinfo",
];
pub fn is_syscall_crate(crate_name: &str) -> bool {
matches!(crate_name, "libc" | "nix" | "rustix")
}
pub fn is_cmd_builder_method(method: &str) -> bool {
matches!(
method,
"arg" | "args" | "arg0" | "env" | "envs" | "env_clear" | "env_remove" | "current_dir"
| "cwd" | "stdin" | "stdout" | "stderr" | "pre_exec" | "creation_flags" | "uid" | "gid"
| "groups" | "process_group"
)
}
pub fn is_cmd_naming_method(method: &str) -> bool {
matches!(method, "new" | "cmd")
}
pub fn is_net_establishing(method: &str) -> bool {
method.ends_with("_lookup")
|| matches!(
method,
"connect"
| "connect_timeout"
| "get"
| "post"
| "put"
| "patch"
| "delete"
| "head"
| "request"
| "send_to"
| "lookup_host"
| "to_socket_addrs"
| "lookup"
| "lookup_ip"
| "resolve"
)
}
pub fn is_net_host_arg1(method: &str) -> bool {
matches!(method, "request" | "send_to")
}
pub fn is_net_binding(method: &str) -> bool {
matches!(method, "bind" | "listen" | "bind_to_device")
}
pub fn is_net_accepting(path: &str, leaf: &str) -> bool {
matches!(leaf, "accept" | "accept4" | "poll_accept" | "incoming" | "into_incoming")
|| (path.starts_with("tonic::")
&& (path.ends_with("::Router::serve")
|| path.ends_with("::Router::serve_with_shutdown")
|| path.ends_with("::TcpIncoming::new")))
}
pub fn is_fs_path_arg(leaf: &str) -> bool {
matches!(
leaf,
"chown"
| "lchown"
| "chroot"
| "write"
| "read"
| "read_to_string"
| "read_dir"
| "read_link"
| "copy"
| "rename"
| "remove_file"
| "remove_dir"
| "remove_dir_all"
| "create_dir"
| "create_dir_all"
| "hard_link"
| "soft_link"
| "symlink"
| "symlink_file"
| "symlink_dir"
| "symlink_metadata"
| "canonicalize"
| "metadata"
| "set_permissions"
| "exists"
| "try_exists"
| "open"
| "create"
| "create_new"
)
}
pub fn is_entropy_source_ident(seg: &str) -> bool {
matches!(seg, "OsRng" | "SysRng")
}
pub struct AlsoEffect {
pub krate: &'static [&'static str],
pub on: AlsoOn,
pub effects: &'static [&'static str],
pub fs_kind: &'static [&'static str],
pub row: &'static str,
pub evidence: &'static str,
}
pub enum AlsoOn {
Method(&'static str, &'static [&'static str]),
Leaf(&'static [&'static str]),
Exact(&'static [&'static str]),
FreeFn,
}
impl AlsoOn {
pub fn matches(&self, path: &str) -> bool {
match self {
AlsoOn::Method(ty, methods) => path.rsplit_once("::").is_some_and(|(head, m)| {
methods.contains(&m) && head.rsplit("::").next() == Some(*ty)
}),
AlsoOn::Leaf(leaves) => leaves.iter().any(|l| path.strip_suffix(l).is_some_and(|h| h.ends_with("::"))),
AlsoOn::Exact(paths) => paths.contains(&path),
AlsoOn::FreeFn => path.split("::").skip(1).all(|seg| seg.starts_with(|c: char| c.is_ascii_lowercase() || c == '_')),
}
}
}
pub const ALSO_EFFECTS: &[AlsoEffect] = &[
AlsoEffect {
krate: &["tungstenite"],
on: AlsoOn::Leaf(&["client_tls", "client_tls_with_config"]),
effects: &["Fs"],
fs_kind: &["read"],
row: "R338",
evidence: "openssl backend: TlsConnector::new loads the probed cert file/dir; client_tls passes no connector \
(tungstenite-0.30.0 src/tls.rs:54). macOS (Security framework) reads no file.",
},
AlsoEffect {
krate: &["elasticsearch"],
on: AlsoOn::Method("Transport", &["single_node", "static_node_list", "sniffing_node_list", "cloud"]),
effects: &["Fs"],
fs_kind: &["read"],
row: "R1598",
evidence: "EXECUTED under strace in rust:1-bookworm: Transport::single_node opens openssl.cnf, cert.pem, certs/, \
ca-certificates.crt; 0 opens on macOS. Primary Env is the proxy-variable read.",
},
AlsoEffect {
krate: &["elasticsearch"],
on: AlsoOn::Method("TransportBuilder", &["build"]),
effects: &["Fs"],
fs_kind: &["read"],
row: "R1598",
evidence: "as Transport::single_node (EXECUTED under strace, Linux/openssl).",
},
AlsoEffect {
krate: &["backoff"],
on: AlsoOn::Method("ExponentialBackoff", &["next_backoff"]),
effects: &["Clock"],
fs_kind: &[],
row: "R1612",
evidence: "EXECUTED (macOS, DYLD interposer): next_backoff on a default ExponentialBackoff = 1 getentropy (the \
Rand primary) + 1 clock_gettime (the max_elapsed_time check reads clock.now()). Pure neighbour \
ExponentialBackoffBuilder::new: 0 events.",
},
AlsoEffect {
krate: &["grep_cli"],
on: AlsoOn::Method("DecompressionMatcherBuilder", &["associate", "try_associate"]),
effects: &["Fs"],
fs_kind: &["read"],
row: "R1612",
evidence: "EXECUTED (macOS, DYLD interposer): a relative program (`gzip`) = getenv(PATH) (the Env primary) + \
stat(<PATH dir>/gzip) per directory until found; an absolute program = 0 events, the same accepted \
over-charge as the Env primary. Pure neighbour DecompressionMatcherBuilder::new: 0 events.",
},
AlsoEffect {
krate: &["time"],
on: AlsoOn::Method("UtcOffset", &["current_local_offset"]),
effects: &["Fs"],
fs_kind: &["read"],
row: "R1612",
evidence: "EXECUTED (macOS, DYLD interposer), TZ unset: 1 clock_gettime (the Clock primary) + localtime_r + \
access(/etc/localtime). With TZ set the interposer saw no file call (libc's own zone-file open is \
not interposable), so the TZ-set arm is not claimed either way. libc caches the zone: first call per \
process. Pure neighbour UtcOffset::from_hms: 0 events.",
},
AlsoEffect {
krate: &["portable_pty"],
on: AlsoOn::Method("CommandBuilder", &["new", "from_argv", "new_default_prog"]),
effects: &["Fs"],
fs_kind: &["read"],
row: "R1612",
evidence: "EXECUTED (macOS, DYLD interposer), SHELL unset: each of the three ctors = access(<passwd shell>, X_OK) \
(get_base_env -> get_shell, cmdbuilder.rs:43-71); SHELL set: 0 events. Charged on the unset arm, \
which is the default in containers and service managers; SHELL-set callers are the stated \
over-charge. Pure neighbour CommandBuilder::arg: 0 events.",
},
AlsoEffect {
krate: &["tokio_postgres", "postgres"],
on: AlsoOn::Method(
"Client",
&["query", "query_one", "query_opt", "query_raw", "execute", "batch_execute", "simple_query", "prepare",
"prepare_typed", "copy_in", "copy_out", "transaction"],
),
effects: &["Log"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED, logger at DEBUG: 1 `log` record from tokio_postgres per call (query* query.rs:45, execute query.rs:220, \
batch_execute/transaction simple_query.rs:47, simple_query :35, prepare* prepare.rs:122, copy_out copy_out.rs:14, \
copy_in copy_in.rs:195); a `&str` statement adds the prepare.rs:122 record. 0 at INFO. Pure neighbours \
is_closed/cancel_token/build_transaction: 0. Same records via postgres::Client (it wraps tokio_postgres).",
},
AlsoEffect {
krate: &["tokio_postgres"],
on: AlsoOn::Method("Client", &["execute_raw", "simple_query_raw"]),
effects: &["Log"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED, logger at DEBUG: execute_raw query.rs:220, simple_query_raw simple_query.rs:35, 1 record each. 0 at INFO. \
Not charged (0 records, EXECUTED): query_typed_raw, query_typed_one, execute_typed.",
},
AlsoEffect {
krate: &["postgres"],
on: AlsoOn::Method("Client", &["is_valid"]),
effects: &["Log"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED, logger at DEBUG: is_valid sends simple_query(\"\") -> simple_query.rs:35, 1 record.",
},
AlsoEffect {
krate: &["tokio_postgres", "postgres"],
on: AlsoOn::Method(
"Transaction",
&["query", "query_one", "query_opt", "query_raw", "execute", "batch_execute", "simple_query", "prepare",
"prepare_typed", "copy_in", "copy_out", "transaction", "commit", "rollback"],
),
effects: &["Log"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED, logger at DEBUG, inside an open transaction: the same record per verb as Client (query* query.rs:45, \
execute :220, prepare* prepare.rs:122, copy_* copy_out.rs:14/copy_in.rs:195, simple_query :35); \
batch_execute/transaction/commit/rollback each 1 simple_query.rs:47 record. 0 at INFO. Not charged: query_typed (0).",
},
AlsoEffect {
krate: &["deadpool_postgres"],
on: AlsoOn::Method(
"Client",
&["query", "query_one", "query_opt", "query_raw", "execute", "batch_execute", "prepare", "prepare_typed",
"prepare_cached", "prepare_typed_cached", "transaction"],
),
effects: &["Log"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED, logger at DEBUG, through deadpool's GenericClient spelling and its inherent prepare_cached/\
prepare_typed_cached: tokio_postgres records as above. prepare_cached/prepare_typed_cached log only on a \
statement-cache MISS (prepare.rs:122); a warm cache hit: 0 records (EXECUTED), the same cold-cache arm the \
Db primary already charges unconditionally.",
},
AlsoEffect {
krate: &["deadpool_postgres"],
on: AlsoOn::Method("ClientWrapper", &["prepare_cached", "prepare_typed_cached", "transaction"]),
effects: &["Log"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED, logger at DEBUG: the inherent ClientWrapper methods; prepare_* only on a statement-cache miss (warm: 0).",
},
AlsoEffect {
krate: &["deadpool_postgres"],
on: AlsoOn::Method(
"Transaction",
&["query", "query_one", "query_opt", "query_raw", "execute", "batch_execute", "prepare", "prepare_typed",
"prepare_cached", "prepare_typed_cached", "transaction", "commit", "rollback"],
),
effects: &["Log"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED, logger at DEBUG, deadpool Transaction through GenericClient: tokio_postgres records as Client; \
commit/rollback/transaction 1 simple_query.rs:47 each; prepare_*_cached only on a cache miss.",
},
AlsoEffect {
krate: &["reqwest"],
on: AlsoOn::Method("Client", &["execute"]),
effects: &["Log"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED (async Client + blocking::Client), logger + tracing subscriber installed: pooled reuse 4 tracing events \
(hyper_util pool.rs); new connection 11 (connect.rs:929 `log` + hyper_util); HTTP_PROXY adds connect.rs:784. \
Client::get/build: 0.",
},
AlsoEffect {
krate: &["reqwest"],
on: AlsoOn::Method("RequestBuilder", &["send"]),
effects: &["Log"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED (async + blocking), as Client::execute: 11 records on a new connection. RequestBuilder::get/build: 0.",
},
AlsoEffect {
krate: &["tokio_postgres", "postgres"],
on: AlsoOn::Method("Config", &["connect"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED (postgres:16, interposer): TCP host = connect(127.0.0.1:port) [Net]; unix host = connect(unix:<dir>/.s.PGSQL.n) \
[Ipc]; SCRAM server = 1 getentropy [Rand], trust server = 0. Pure neighbour Config::from_str / Config::host: 0 events. \
connect_raw (caller's stream) is not claimed.",
},
AlsoEffect {
krate: &["tokio_postgres"],
on: AlsoOn::Exact(&["tokio_postgres::connect"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED as Config::connect (tokio_postgres::connect parses the string and calls it): TCP 127.0.0.1 Net, unix \
socket Ipc, SCRAM nonce 1 getentropy Rand (trust server: 0).",
},
AlsoEffect {
krate: &["postgres"],
on: AlsoOn::Method("Client", &["connect"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED as Config::connect (postgres::Client::connect parses and calls it): TCP Net, SCRAM Rand. (The unix-host arm \
was EXECUTED through postgres::Config::connect.)",
},
AlsoEffect {
krate: &["deadpool_postgres"],
on: AlsoOn::Method("Pool", &["get", "timeout_get"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1618",
evidence: "EXECUTED cold pool: connect(127.0.0.1:55432) + 1 getentropy; warm pool (idle object): 0 of both. get and timeout_get \
identical. Pure neighbours status/is_closed/manager/resize/close: 0 events.",
},
AlsoEffect {
krate: &["tokio_postgres", "postgres", "deadpool_postgres"],
on: AlsoOn::Method("Client", &["start"]),
effects: &["Log"],
fs_kind: &[],
row: "R1618",
evidence: "EXECUTED, logger at DEBUG: build_transaction().start() = 1 record, simple_query.rs:47 (also with isolation_level/read_only \
in the chain). 0 at INFO. build_transaction / isolation_level / read_only alone: 0.",
},
AlsoEffect {
krate: &["tokio_postgres", "postgres", "deadpool_postgres"],
on: AlsoOn::Method("TransactionBuilder", &["start"]),
effects: &["Log"],
fs_kind: &[],
row: "R1618",
evidence: "EXECUTED, logger at DEBUG: a held TransactionBuilder's start = 1 record, simple_query.rs:47 (sync postgres: 2, BEGIN and the \
drop's ROLLBACK).",
},
AlsoEffect {
krate: &["deadpool_postgres"],
on: AlsoOn::Method("Object", &["start"]),
effects: &["Log"],
fs_kind: &[],
row: "R1618",
evidence: "EXECUTED, logger at DEBUG: pooled Object .build_transaction().start() = 1 record, simple_query.rs:47.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("MySqlConnection", &["connect", "connect_with"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1618",
evidence: "EXECUTED (mysql:8, interposer): connect(127.0.0.1) + 5 getentropy on the default/required TLS arms; ssl-mode=disabled: connect \
only; ?socket= : connect(AF_UNIX). Neighbour connect_lazy and MySqlConnectOptions parse/new: 0 events.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("MySqlPool", &["connect", "connect_with"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1618",
evidence: "EXECUTED (mysql:8): Pool::connect / connect_with open one connection eagerly = connect + 5 getentropy; connect_lazy: 0.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("MySqlPoolOptions", &["connect", "connect_with"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1618",
evidence: "EXECUTED (mysql:8): PoolOptions::connect / connect_with = connect + 5 getentropy. max_connections / new: 0.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("MySqlConnectOptions", &["connect"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1618",
evidence: "EXECUTED (mysql:8): ConnectOptions::connect on MySqlConnectOptions = connect + 5 getentropy.",
},
AlsoEffect {
krate: &["fastrand"],
on: AlsoOn::FreeFn,
effects: &["Clock"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED (fresh thread, interposer): fastrand::u32/seed/get_seed/alphabetic = 1 clock read on the thread's FIRST use \
(Instant::now() seeds the thread-local RNG), 0 on the second call.",
},
AlsoEffect {
krate: &["fastrand"],
on: AlsoOn::Method("Rng", &["new", "default"]),
effects: &["Clock"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED (fresh thread): Rng::new and Rng::default fork the thread-local generator, whose first use reads the clock: \
1 on the first call per thread, 0 after. Rng::with_seed: 0.",
},
AlsoEffect {
krate: &["tempfile"],
on: AlsoOn::Method(
"Builder",
&["tempfile", "tempfile_in", "make", "make_in", "tempdir", "tempdir_in"],
),
effects: &["Clock"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED (fresh thread, interposer): 1 clock read on the first name generated per thread (create_helper -> \
fastrand::Rng::new), 0 on the second call. Builder::new().prefix().suffix().rand_bytes(): 0.",
},
AlsoEffect {
krate: &["tempfile"],
on: AlsoOn::Method(
"NamedTempFile",
&["new", "new_in", "with_prefix", "with_prefix_in", "with_suffix", "with_suffix_in"],
),
effects: &["Clock"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED (fresh thread): 1 clock read on the first name generated per thread, 0 on the second. NamedTempFile::close \
and ::persist (no name generation): 0.",
},
AlsoEffect {
krate: &["tempfile"],
on: AlsoOn::Method(
"TempDir",
&["new", "new_in", "with_prefix", "with_prefix_in", "with_suffix", "with_suffix_in"],
),
effects: &["Clock"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED (fresh thread): 1 clock read on the first name generated per thread, 0 on the second.",
},
AlsoEffect {
krate: &["tempfile"],
on: AlsoOn::Leaf(&["tempfile", "tempfile_in", "tempdir", "tempdir_in"]),
effects: &["Clock"],
fs_kind: &[],
row: "R1617",
evidence: "EXECUTED (fresh thread): the free functions tempfile()/tempfile_in()/tempdir()/tempdir_in(), 1 clock read on the \
first name generated per thread.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgConnection", &["connect", "connect_with"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (postgres:16, TLS+SCRAM, interposer): 1 connect (AF_UNIX for a socket host) + 1-6 getentropy per call with options already built; a warm pool's acquire/begin: 0 of both.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgPool", &["connect", "connect_with"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (postgres:16, TLS+SCRAM, interposer): 1 connect (AF_UNIX for a socket host) + 1-6 getentropy per call with options already built; a warm pool's acquire/begin: 0 of both.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgPoolOptions", &["connect", "connect_with"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (postgres:16, TLS+SCRAM, interposer): 1 connect (AF_UNIX for a socket host) + 1-6 getentropy per call with options already built; a warm pool's acquire/begin: 0 of both.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgListener", &["connect", "connect_with"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (postgres:16, TLS+SCRAM, interposer): 1 connect (AF_UNIX for a socket host) + 1-6 getentropy per call with options already built; a warm pool's acquire/begin: 0 of both.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgConnectOptions", &["connect"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (postgres:16, TLS+SCRAM, interposer): 1 connect (AF_UNIX for a socket host) + 1-6 getentropy per call with options already built; a warm pool's acquire/begin: 0 of both.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgPool", &["acquire", "begin", "begin_with"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (postgres:16, TLS+SCRAM, interposer): 1 connect (AF_UNIX for a socket host) + 1-6 getentropy per call with options already built; a warm pool's acquire/begin: 0 of both.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgPoolOptions", &["acquire", "begin", "begin_with"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (postgres:16, TLS+SCRAM, interposer): 1 connect (AF_UNIX for a socket host) + 1-6 getentropy per call with options already built; a warm pool's acquire/begin: 0 of both.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("MySqlPool", &["acquire", "begin", "begin_with"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (mysql:8, interposer): a cold pool's acquire/begin = 1 connect + 5 getentropy; a warm pool's acquire: 0 of both.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("MySqlPoolOptions", &["acquire", "begin", "begin_with"]),
effects: &["Net", "Ipc", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (mysql:8, interposer): a cold pool's acquire/begin = 1 connect + 5 getentropy; a warm pool's acquire: 0 of both.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgConnection", &["connect"]),
effects: &["Env", "Fs"],
fs_kind: &["read"],
row: "R1623",
evidence: "EXECUTED (postgres:16, interposer): a URL spelling parses the URL = 12 PG* getenv + 3 stat of the unix-socket candidate dirs (+ HOME/PGPASSFILE and an open of ~/.pgpass when the URL has no password). connect_with(&opts) parses nothing.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgPool", &["connect"]),
effects: &["Env", "Fs"],
fs_kind: &["read"],
row: "R1623",
evidence: "EXECUTED (postgres:16, interposer): a URL spelling parses the URL = 12 PG* getenv + 3 stat of the unix-socket candidate dirs (+ HOME/PGPASSFILE and an open of ~/.pgpass when the URL has no password). connect_with(&opts) parses nothing.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgPoolOptions", &["connect"]),
effects: &["Env", "Fs"],
fs_kind: &["read"],
row: "R1623",
evidence: "EXECUTED (postgres:16, interposer): a URL spelling parses the URL = 12 PG* getenv + 3 stat of the unix-socket candidate dirs (+ HOME/PGPASSFILE and an open of ~/.pgpass when the URL has no password). connect_with(&opts) parses nothing.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgListener", &["connect"]),
effects: &["Env", "Fs"],
fs_kind: &["read"],
row: "R1623",
evidence: "EXECUTED (postgres:16, interposer): a URL spelling parses the URL = 12 PG* getenv + 3 stat of the unix-socket candidate dirs (+ HOME/PGPASSFILE and an open of ~/.pgpass when the URL has no password). connect_with(&opts) parses nothing.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgPool", &["connect_lazy"]),
effects: &["Fs"],
fs_kind: &["read"],
row: "R1623",
evidence: "EXECUTED (postgres:16, interposer): connect_lazy(url) = 12 PG* getenv [Env primary] + 3 stat, 0 connections.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgPoolOptions", &["connect_lazy"]),
effects: &["Fs"],
fs_kind: &["read"],
row: "R1623",
evidence: "EXECUTED (postgres:16, interposer): connect_lazy(url) = 12 PG* getenv [Env primary] + 3 stat, 0 connections.",
},
AlsoEffect {
krate: &["tracing_subscriber"],
on: AlsoOn::Method("OffsetTime", &["local_rfc_3339"]),
effects: &["Fs"],
fs_kind: &["read"],
row: "R1528",
evidence: "EXECUTED (tracing-subscriber 0.3.23, macOS interposer, TZ unset): 1 clock_gettime [Clock primary] + access(/etc/localtime) \
(the `time` crate's current_local_offset, R1612); a pure control: 0.",
},
AlsoEffect {
krate: &["sea_orm"],
on: AlsoOn::Method("SqlxPostgresConnector", &["accepts"]),
effects: &["Fs"],
fs_kind: &["read"],
row: "R1528",
evidence: "EXECUTED (sea-orm 2.0.4, macOS interposer): accepts(\"postgres://u@h/db\") = 13 PG* getenv [Env primary] + stat of \
/var/run/postgresql, /private/tmp, /tmp `.s.PGSQL.5432` + open ~/.pgpass; a `mysql://` string and a pure control: 0.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("PgConnectOptions", &["new", "new_without_pgpass", "default", "from_str", "from_url"]),
effects: &["Fs"],
fs_kind: &["read"],
row: "R1623",
evidence: "EXECUTED (postgres:16, interposer): 12 PG* getenv [Env primary] + 3 stat of the unix-socket candidate dirs; new()/default() also open ~/.pgpass (14 getenv) when no password is set.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("SqliteConnection", &["connect", "connect_with"]),
effects: &["Env", "Fs", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (sqlite via sqlx 0.9.0, interposer): connect opens the db file read-write (+creat under mode=rwc) with stat/lstat of its path, opens /dev/urandom (first sqlite use in the process), reads SQLITE_TMPDIR/TMPDIR/RUST_MIN_STACK. sqlite::memory: opens only /dev/urandom. Fs direction depends on mode=: unknown.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("SqlitePool", &["connect", "connect_with"]),
effects: &["Env", "Fs", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (sqlite via sqlx 0.9.0, interposer): connect opens the db file read-write (+creat under mode=rwc) with stat/lstat of its path, opens /dev/urandom (first sqlite use in the process), reads SQLITE_TMPDIR/TMPDIR/RUST_MIN_STACK. sqlite::memory: opens only /dev/urandom. Fs direction depends on mode=: unknown.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("SqlitePoolOptions", &["connect", "connect_with"]),
effects: &["Env", "Fs", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (sqlite via sqlx 0.9.0, interposer): connect opens the db file read-write (+creat under mode=rwc) with stat/lstat of its path, opens /dev/urandom (first sqlite use in the process), reads SQLITE_TMPDIR/TMPDIR/RUST_MIN_STACK. sqlite::memory: opens only /dev/urandom. Fs direction depends on mode=: unknown.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("SqliteConnectOptions", &["connect", "connect_with"]),
effects: &["Env", "Fs", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (sqlite via sqlx 0.9.0, interposer): connect opens the db file read-write (+creat under mode=rwc) with stat/lstat of its path, opens /dev/urandom (first sqlite use in the process), reads SQLITE_TMPDIR/TMPDIR/RUST_MIN_STACK. sqlite::memory: opens only /dev/urandom. Fs direction depends on mode=: unknown.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("SqlitePool", &["acquire", "begin", "begin_with"]),
effects: &["Env", "Fs", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (sqlite, interposer): a cold pool's acquire/begin = the connect above; a warm pool's: 0 events.",
},
AlsoEffect {
krate: &["sqlx"],
on: AlsoOn::Method("SqlitePoolOptions", &["acquire", "begin", "begin_with"]),
effects: &["Env", "Fs", "Rand"],
fs_kind: &[],
row: "R1623",
evidence: "EXECUTED (sqlite, interposer): a cold pool's acquire/begin = the connect above; a warm pool's: 0 events.",
},
];
pub fn also_effects(crate_name: &str, path: &str) -> Vec<&'static str> {
let Some(primary) = classify(crate_name, path) else { return Vec::new() };
let mut out: Vec<&'static str> = Vec::new();
for row in ALSO_EFFECTS {
if row.krate.contains(&crate_name) && row.on.matches(path) {
for e in row.effects {
if *e != primary && !out.contains(e) {
out.push(e);
}
}
}
}
out
}
pub fn also_effects_by_method(crate_name: &str, method: &str) -> Vec<&'static str> {
let mut out: Vec<&'static str> = Vec::new();
for row in ALSO_EFFECTS {
if row.krate.contains(&crate_name) && matches!(row.on, AlsoOn::Method(_, ms) if ms.contains(&method)) {
for e in row.effects {
if !out.contains(e) {
out.push(e);
}
}
}
}
out
}
pub fn also_fs_kind(crate_name: &str, path: &str) -> Vec<&'static str> {
let mut out: Vec<&'static str> = Vec::new();
for row in ALSO_EFFECTS {
if row.krate.contains(&crate_name) && row.on.matches(path) && row.effects.contains(&"Fs") {
if row.fs_kind.is_empty() {
return Vec::new();
}
for k in row.fs_kind {
if !out.contains(k) {
out.push(k);
}
}
}
}
out
}
pub fn classify_all(crate_name: &str, path: &str) -> Option<Vec<&'static str>> {
let primary = classify(crate_name, path)?;
let mut v = vec![primary];
v.extend(also_effects(crate_name, path));
Some(v)
}
pub fn classify_rendered(crate_name: &str, path: &str) -> Option<String> {
classify_all(crate_name, path).map(|v| v.join("+"))
}
pub fn also_hides_locator(eff: &str) -> bool {
matches!(eff, "Fs" | "Net" | "Llm" | "Exec" | "Db")
}
pub fn password_hash_explicit_salt(crate_name: &str, path: &str, argc: u8, method: bool) -> bool {
if !matches!(crate_name, "argon2" | "scrypt" | "pbkdf2" | "password_hash")
|| !path.ends_with("::hash_password")
{
return false;
}
if argc == 0 {
return false; }
let non_receiver = if method { argc } else { argc - 1 };
let hit = non_receiver == 2;
if hit && candor_report::env::trace("CANDOR_ALIAS_DEBUG") {
eprintln!("R330EXPLICITSALT {path} argc={argc} method={method}");
}
hit
}
pub fn fs_path_arity(leaf: &str) -> usize {
match leaf {
"copy" | "rename" | "hard_link" | "soft_link" | "symlink" | "symlink_file" | "symlink_dir" => 2,
_ => 1,
}
}
pub fn is_fs_receiver_locator(call_path: &str) -> bool {
let mut segs = call_path.rsplit("::");
let (Some(_leaf), Some(recv)) = (segs.next(), segs.next()) else { return false };
matches!(recv, "Path" | "PathBuf" | "Utf8Path" | "Utf8PathBuf")
}
pub fn is_exec_receiver_locator(call_path: &str) -> bool {
let mut segs = call_path.rsplit("::");
let (Some(leaf), Some(recv)) = (segs.next(), segs.next()) else { return false };
matches!(recv, "Command" | "CommandExt") && !is_cmd_builder_method(leaf) && !leaf.starts_with("get_")
}
pub fn is_fs_path_arg_method(call_path: &str) -> bool {
if call_path.ends_with("OpenOptions::open") || call_path.ends_with("DirBuilder::create") {
return true;
}
let mut segs = call_path.rsplit("::");
let (Some(leaf), Some(recv)) = (segs.next(), segs.next()) else { return false };
if recv != "Dir" {
return false;
}
!matches!(
leaf,
"try_clone"
| "into_std_file"
| "from_std_file"
| "into_std"
| "from_std"
| "entries"
| "entries_utf8"
| "dir_metadata"
| "reopen_dir"
| "remove_open_dir"
| "remove_open_dir_all"
| "open_parent_dir"
| "rewind"
| "as_raw_fd"
| "as_fd"
)
}
pub fn is_db_query_arg(leaf: &str) -> bool {
if matches!(
leaf,
"sqlite3_exec"
| "sqlite3_prepare"
| "sqlite3_prepare_v2"
| "sqlite3_prepare_v3"
| "sqlite3_prepare16"
| "sqlite3_prepare16_v2"
| "sqlite3_prepare16_v3"
| "sqlite3_get_table"
) {
return true;
}
matches!(
leaf,
"execute"
| "execute_batch"
| "execute_unprepared"
| "batch_execute"
| "simple_query"
| "query"
| "query_one"
| "query_opt"
| "query_raw"
| "query_row"
| "query_map"
| "query_drop"
| "query_iter"
| "query_first"
| "query_fold"
| "copy_in"
| "copy_out"
| "query_and_then"
| "query_typed"
| "query_all"
| "prepare"
| "prepare_typed"
| "prepare_cached"
| "exec"
| "exec_first"
| "exec_iter"
| "exec_map"
| "exec_fold"
| "exec_drop"
| "exec_batch"
| "prep"
| "run_command"
)
}
pub fn masks_locator(eff: &str, crate_name: &str, path: &str, leaf: &str, method: bool) -> bool {
let by_list = match eff {
"Net" => is_net_establishing(leaf),
"Exec" => is_cmd_naming_method(leaf) || is_exec_receiver_locator(path),
"Fs" => {
(!method && is_fs_path_arg(leaf))
|| (method && is_fs_path_arg_method(path))
|| (method && is_fs_receiver_locator(path))
}
"Db" => is_db_query_arg(leaf),
_ => false,
};
by_list || masks_locator_by_table(eff, crate_name, path, leaf)
}
pub fn masks_locator_by_table(eff: &str, crate_name: &str, path: &str, leaf: &str) -> bool {
let syscall = is_syscall_crate(crate_name);
match eff {
"Net" => {
syscall
&& LIBC_NET.contains(&leaf)
&& !LIBC_NET_NO_DESTINATION.contains(&leaf)
&& !(crate_name == "rustix" && leaf == "sendmsg")
}
"Exec" => syscall && LIBC_EXEC.contains(&leaf) && !LIBC_EXEC_NO_PROGRAM.contains(&leaf),
"Fs" => syscall && LIBC_FS.contains(&leaf) && !LIBC_FS_NO_PATH.contains(&leaf),
"Db" => {
(matches!(crate_name, "postgres" | "tokio_postgres" | "deadpool_postgres" | "rusqlite")
&& PG_DB_VERBS.iter().any(|v| path.ends_with(v))
&& !PG_DB_VERBS_NO_SQL.iter().any(|v| path.ends_with(v)))
|| (crate_name == "sqlx_core" && leaf == "prepare_with")
}
_ => false,
}
}
pub fn capstd_cap(crate_name: &str, type_name: &str) -> Option<&'static str> {
if !crate_name.starts_with("cap_") {
return None;
}
Some(match type_name {
"Dir" => "Fs",
"TcpListener" | "TcpStream" | "UdpSocket" | "Pool" => "Net",
"UnixListener" | "UnixStream" | "UnixDatagram" => "Ipc",
"SystemClock" | "MonotonicClock" => "Clock",
_ => return None,
})
}
pub fn tables_in_sql(sql: &str) -> Vec<String> {
const STMT: &[&str] =
&["select", "insert", "update", "delete", "create", "drop", "alter", "truncate", "merge", "replace", "with"];
const SKIP: &[&str] = &["only", "if", "not", "exists", "table"];
const STOP: &[&str] = &[
"select", "set", "where", "values", "on", "using", "group", "order", "by", "limit",
"returning", "as", "inner", "outer", "left", "right", "cross", "lateral", "natural",
"union", "all", "distinct", "case", "when", "null", "default", "skip", "nowait", "of",
"from", "join", "into", "update", "delete", "insert",
];
let cleaned: String = sql
.to_lowercase()
.chars()
.flat_map(|c| match c {
'(' | ')' | ';' => vec![' '],
',' => vec![' ', ',', ' '],
_ => vec![c],
})
.collect();
let toks: Vec<&str> = cleaned.split_whitespace().collect();
let Some(first) = toks.first() else { return Vec::new() };
if !STMT.contains(first) {
return Vec::new(); }
let ident = |t: &str| -> Option<String> {
let t = t.trim_matches(|c| matches!(c, '"' | '`' | '\''));
let mut chars = t.chars();
let ok_first = chars.next().is_some_and(|c| c.is_ascii_alphabetic() || c == '_');
let ok_rest = t.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '_' | '.' | '$' | '"' | '`'));
(ok_first && ok_rest && !STOP.contains(&t)).then(|| t.replace(['"', '`'], ""))
};
let mut out: Vec<String> = Vec::new();
let mut push = |t: Option<String>| {
if let Some(t) = t {
if !out.contains(&t) {
out.push(t);
}
}
};
for (i, tok) in toks.iter().enumerate() {
let table_pos = match *tok {
"from" | "join" | "into" | "table" => true,
"update" | "truncate" => i == 0,
_ => false,
};
if !table_pos {
continue;
}
let mut j = i + 1;
while j < toks.len() && SKIP.contains(&toks[j]) {
j += 1;
}
let Some(next) = toks.get(j) else { continue };
let Some(first) = ident(next) else { continue };
push(Some(first));
while j + 2 < toks.len() && toks[j + 1] == "," {
let Some(more) = ident(toks[j + 2]) else { break };
push(Some(more));
j += 2;
}
}
out
}
#[cfg(test)]
mod tests {
#[test]
fn r1150_getrandom_error_values_draw_nothing_but_the_draws_do() {
for p in ["getrandom::Error::eq", "getrandom::&Error::eq", "getrandom::Error::raw_os_error", "getrandom::Error::fmt",
"getrandom::error::Error::new_custom", "getrandom::Error::UNSUPPORTED"] {
assert_eq!(classify("getrandom", p), None, "{p}");
}
for p in ["getrandom::fill", "getrandom::fill_uninit", "getrandom::u32", "getrandom::u64", "getrandom::getrandom",
"getrandom::SysRng::try_fill_bytes", "getrandom::getrandom_uninit"] {
assert_eq!(classify("getrandom", p), Some("Rand"), "{p}");
}
}
#[test]
fn model_host_recognizes_known_providers_and_special_forms() {
use super::is_model_host as m;
assert!(m("api.openai.com"));
assert!(m("API.OpenAI.com"));
assert!(m("api.anthropic.com:443"));
assert!(m("generativelanguage.googleapis.com"));
assert!(m("api.mistral.ai"));
assert!(m("api.cohere.ai"));
assert!(m("api.cohere.com")); assert!(m("api.groq.com"));
assert!(m("api.together.xyz"));
assert!(m("api.perplexity.ai"));
assert!(m("openrouter.ai"));
assert!(m("eu.api.openai.com"));
assert!(m("localhost:11434"));
assert!(m("127.0.0.1:11434"));
assert!(!m("ollama.internal:11434")); assert!(m("bedrock-runtime.us-east-1.amazonaws.com"));
assert!(m("bedrock-runtime.eu-west-1.amazonaws.com"));
assert!(m("bedrock-agent-runtime.us-east-1.amazonaws.com"));
assert!(!m("example.com"));
assert!(!m("api.stripe.com"));
assert!(!m("localhost:8080")); assert!(!m("s3.us-east-1.amazonaws.com")); assert!(!m("bedrock-backups.s3.amazonaws.com")); assert!(!m("bedrock.us-east-1.amazonaws.com")); assert!(!m("openai.com.evil.com")); }
#[test]
fn model_sdk_crate_is_crate_level_no_method_gating() {
use super::is_model_sdk_crate as s;
assert!(s("async_openai"));
assert!(s("aws_sdk_bedrockruntime"));
assert!(s("ollama_rs"));
assert!(s("langchain_rust"));
assert!(!s("reqwest"));
assert!(!s("aws_sdk_s3"));
}
#[test]
fn sql_table_extraction_is_conservative() {
use super::tables_in_sql as t;
assert_eq!(t("SELECT id FROM users WHERE x = 1"), vec!["users"]);
assert_eq!(t("select * from ledger.entries e join customers c on c.id = e.cid"),
vec!["ledger.entries", "customers"]);
assert_eq!(t("INSERT INTO audit_log (a) VALUES (?1)"), vec!["audit_log"]);
assert_eq!(t("UPDATE accounts SET v = ?"), vec!["accounts"]);
assert_eq!(t("DELETE FROM sessions WHERE id = ?"), vec!["sessions"]);
assert_eq!(t("CREATE TABLE IF NOT EXISTS cache (k TEXT)"), vec!["cache"]);
assert_eq!(t("TRUNCATE TABLE staging"), vec!["staging"]);
assert_eq!(t("SELECT * FROM jobs FOR UPDATE SKIP LOCKED"), vec!["jobs"]);
assert_eq!(t("SELECT * FROM (SELECT 1) q"), Vec::<String>::new());
assert_eq!(t("/tmp/some/path"), Vec::<String>::new());
assert_eq!(t("hello world from nowhere"), Vec::<String>::new());
assert_eq!(t("SELECT a FROM t1, t2, s.t3 WHERE x = 1"), vec!["t1", "t2", "s.t3"]);
assert_eq!(t("SELECT a FROM t1 a1, t2 WHERE x = 1"), vec!["t1"]);
assert_eq!(t("INSERT INTO t (a, b) VALUES (1, 2)"), vec!["t"]);
assert_eq!(t("SELECT a FROM t1, (SELECT 1) q"), vec!["t1"]);
}
use super::*;
#[test]
fn std_effect_handles_have_a_whole_type_rule_and_exclude_the_pure_surfaces() {
for ty in STD_EFFECT_HANDLES {
let probe = format!("{ty}::__candor_probe_verb");
assert!(
classify("std", &probe).is_some(),
"`{ty}` is routed into the classifier by receiver inference, but an arbitrary method \
on it classifies to NOTHING — the routing cannot close any under-report"
);
assert!(is_std_effect_handle(ty), "the predicate must agree with the list");
}
for ty in [
"std::fs::ReadDir",
"std::fs::Metadata", "std::fs::DirEntry", "std::fs::Permissions", "std::fs::FileType",
"std::path::Path", "std::path::PathBuf", "std::vec::Vec",
] {
assert!(!is_std_effect_handle(ty),
"`{ty}` has a pure surface the coarse prefix rules would charge — it must not be \
routed as a handle (Path/PathBuf route through their own verb-precise carve-out)");
}
}
#[test]
fn routed_std_handles_keep_their_pure_accessor_carve_outs() {
for p in [
"std::process::Command::get_program", "std::process::Command::get_args",
"std::process::Command::get_envs", "std::process::Command::get_current_dir",
"std::process::Child::id",
"std::net::TcpStream::local_addr", "std::net::TcpStream::peer_addr",
"std::net::TcpStream::nodelay", "std::net::TcpStream::ttl",
"std::net::UdpSocket::take_error",
"std::fs::File::as_raw_fd", "std::fs::File::into_raw_fd",
"std::os::unix::net::UnixStream::as_raw_fd",
"std::fs::OpenOptions::new", "std::fs::OpenOptions::read", "std::fs::OpenOptions::write",
"std::fs::OpenOptions::append", "std::fs::OpenOptions::truncate",
"std::fs::OpenOptions::create", "std::fs::OpenOptions::create_new",
"std::fs::OpenOptions::mode", "std::fs::OpenOptions::custom_flags",
"std::fs::DirBuilder::new", "std::fs::DirBuilder::recursive", "std::fs::DirBuilder::mode",
] {
assert_eq!(classify("std", p), None, "`{p}` is a pure read-back");
}
for (p, want) in [
("std::process::Command::spawn", "Exec"),
("std::process::Child::wait", "Exec"),
("std::fs::File::write_all", "Fs"),
("std::net::TcpStream::write_all", "Net"),
("std::os::unix::net::UnixStream::send", "Ipc"),
("std::fs::OpenOptions::open", "Fs"),
("std::fs::DirBuilder::create", "Fs"),
] {
assert_eq!(classify("std", p), Some(want), "`{p}` must stay {want}");
}
}
#[test]
fn db_crates_are_calibrated() {
for c in DB_CRATES {
assert!(
CALIBRATED_CRATES.contains(&c),
"DB crate `{c}` is matched by classify() but missing from CALIBRATED_CRATES"
);
}
}
#[test]
fn reviewed_pure_and_calibrated_are_disjoint() {
for c in REVIEWED_PURE_CRATES {
assert!(!CALIBRATED_CRATES.contains(&c),
"`{c}` is in BOTH lists — it cannot be rule-covered AND effect-free");
assert!(!PATH_CALIBRATED_CRATES.contains(&c), "`{c}` is in BOTH lists (path-calibrated)");
assert!(!CALIBRATED_PREFIXES.iter().any(|p| c.starts_with(p)),
"`{c}` is covered by a calibrated PREFIX as well as the pure list");
}
}
#[test]
fn reviewed_pure_crates_classify_as_pure() {
for c in REVIEWED_PURE_CRATES {
for t in CALIBRATION_PROBE_TAILS {
assert!(classify(c, &format!("{c}{t}")).is_none(),
"`{c}` is listed REVIEWED-PURE but classify() gives it an effect on `{c}{t}` — \
one of the two is wrong, and the list is the claim");
}
}
}
#[test]
fn calibration_ceilings_match_the_recorded_review() {
let src = include_str!("lib.rs");
let flat = src
.replace("\n //", " ")
.replace("\n //", " ")
.replace("\n //", " ");
let flat: String = flat.split_whitespace().collect::<Vec<_>>().join(" ");
let ceilings: std::collections::HashMap<&str, &str> =
CALIBRATED_CEILINGS.iter().copied().collect();
let deliberate = ["postgres", "async_fs", "getrandom", "rand_core"];
let mut problems: Vec<String> = Vec::new();
for c in CALIBRATED_CRATES {
if deliberate.contains(&c) {
continue;
}
let mut cited: Vec<String> = Vec::new();
for form in [c.to_string(), c.replace('_', "-")] {
for verb in ["verified against ", "validated against "] {
let pat = format!("{verb}{form} ");
let mut from = 0usize;
while let Some(i) = flat[from..].find(&pat) {
let at = from + i + pat.len();
let tail: String = flat[at..]
.chars()
.take_while(|ch| ch.is_ascii_digit() || *ch == '.' || *ch == '/')
.collect();
for v in tail.split('/') {
let v = v.trim_end_matches('.').to_string();
if v.split('.').count() >= 2 && !cited.contains(&v) {
cited.push(v);
}
}
from = at;
}
}
}
if cited.is_empty() {
continue;
}
match ceilings.get(c) {
None => problems.push(format!(
"{c}: rules cite {} but there is NO ceiling — the exemption is unconditional",
cited.join("/")
)),
Some(have) => {
let ok = cited.iter().any(|v| have.starts_with(v) || v.starts_with(*have))
|| cited.iter().any(|v| calibration_exceeded_raw(v, have));
if !ok {
problems.push(format!(
"{c}: ceiling {have} is ABOVE every recorded review ({}) — it grants \
reviewed-purity over source no comment records anyone reading",
cited.join("/")
));
}
}
}
}
assert!(
problems.is_empty(),
"CALIBRATED_CEILINGS disagrees with the review record:\n {}\n\n\
A ceiling ABOVE the recorded review grants reviewed-purity over source nobody read (SILENT); \
a ceiling BELOW it is noisy but safe. Either way the table and the record must agree, or \
neither is evidence.",
problems.join("\n ")
);
}
#[test]
fn calibrated_crates_are_live() {
for c in CALIBRATED_CRATES {
assert!(
CALIBRATION_PROBE_TAILS.iter().any(|t| classify(c, &format!("{c}{t}")).is_some()),
"calibrated crate `{c}` is matched by no path in classify() — dead list entry"
);
}
}
#[test]
fn async_http_stack_classifies() {
assert_eq!(classify("hyper", "hyper::client::conn::http1::SendRequest::send_request"), Some("Net"));
assert_eq!(classify("hyper", "hyper::client::conn::http1::handshake"), Some("Net"));
assert_eq!(classify("hyper_util", "hyper_util::client::legacy::Client::request"), Some("Net"));
assert_eq!(classify("hickory_resolver", "hickory_resolver::Resolver::lookup_ip"), Some("Net"));
assert_eq!(classify("quinn", "quinn::Endpoint::connect"), Some("Net"));
assert_eq!(classify("quinn", "quinn::RecvStream::read_to_end"), Some("Net")); assert_eq!(classify("quinn", "quinn::SendStream::write_all"), Some("Net"));
assert_eq!(classify("tokio_rustls", "tokio_rustls::TlsConnector::connect"), Some("Net"));
assert_eq!(classify("native_tls", "native_tls::TlsConnector::connect"), Some("Net"));
assert_eq!(classify("tokio_vsock", "tokio_vsock::VsockStream::connect"), Some("Ipc"));
assert_eq!(classify("rustls_native_certs", "rustls_native_certs::load_native_certs"), Some("Fs"));
assert_eq!(classify("rlimit", "rlimit::setrlimit"), Some("Env"));
assert_eq!(classify("num_cpus", "num_cpus::get"), None);
assert_eq!(classify("num_cpus", "num_cpus::get_physical"), None);
assert_eq!(classify("hyper", "hyper::Request::builder"), None);
assert_eq!(classify("hyper", "hyper::body::Bytes::new"), None);
assert_eq!(classify("native_tls", "native_tls::TlsConnectorBuilder::min_protocol_version"), None);
assert_eq!(classify("serde", "serde::Deserialize::request"), None); }
#[test]
fn coverage_differential_crates_classify() {
assert_eq!(classify("rustls", "rustls::ClientConnection::read_tls"), Some("Net"));
assert_eq!(classify("rustls", "rustls::ConnectionCommon::write_tls"), Some("Net"));
assert_eq!(classify("rustls", "rustls::Connection::complete_io"), Some("Net"));
assert_eq!(classify("rustls", "rustls::ConnectionCommon::process_new_packets"), None); assert_eq!(classify("rustls", "rustls::ClientConfig::builder"), None);
assert_eq!(classify("native_tls_crate", "native_tls_crate::TlsConnector::connect"), Some("Net"));
assert_eq!(classify("tokio_native_tls", "tokio_native_tls::TlsAcceptor::accept"), Some("Net"));
assert_eq!(classify("native_tls_crate", "native_tls_crate::TlsConnectorBuilder::min_protocol_version"), None);
assert_eq!(classify("etcetera", "etcetera::home_dir"), Some("Env"));
assert_eq!(classify("etcetera", "etcetera::base_strategy::choose_base_strategy"), Some("Env"));
assert_eq!(classify("etcetera", "etcetera::base_strategy::Xdg::config_dir"), Some("Env"));
assert_eq!(classify("etcetera", "etcetera::app_strategy::AppStrategyArgs::new"), None);
assert_eq!(classify("sqlx_core", "sqlx_core::connection::Connection::connect"), Some("Net"));
assert_eq!(classify("sqlx_core", "sqlx_core::executor::Executor::fetch_one"), Some("Db"));
assert_eq!(classify("sqlx_core", "sqlx_core::executor::Executor::execute"), Some("Db"));
assert_eq!(classify("sqlx_core", "sqlx_core::pool::Pool::acquire"), Some("Db"));
assert_eq!(classify("sqlx_core", "sqlx_core::pool::PoolOptions::max_connections"), None);
assert_eq!(classify("walkdir", "walkdir::WalkDir::new"), Some("Fs"));
assert_eq!(classify("walkdir", "walkdir::IntoIter::next"), Some("Fs"));
assert_eq!(classify("walkdir", "walkdir::DirEntry::metadata"), Some("Fs"));
assert_eq!(classify("walkdir", "walkdir::WalkDir::into_iter"), None); assert_eq!(classify("walkdir", "walkdir::WalkDir::max_depth"), None); assert_eq!(classify("walkdir", "walkdir::DirEntry::file_type"), None);
assert_eq!(classify("filetime", "filetime::set_file_mtime"), Some("Fs"));
assert_eq!(classify("filetime", "filetime::set_file_handle_times"), Some("Fs"));
assert_eq!(classify("filetime", "filetime::FileTime::now"), Some("Clock"));
assert_eq!(classify("filetime", "filetime::FileTime::from_unix_time"), None);
assert_eq!(classify("filetime", "filetime::FileTime::from_last_modification_time"), None);
assert_eq!(classify("execute", "execute::Execute::execute"), Some("Exec"));
assert_eq!(classify("execute", "execute::Execute::execute_output"), Some("Exec"));
assert_eq!(classify("execute", "execute::Execute::execute_multiple_output"), Some("Exec"));
assert_eq!(classify("execute", "execute::command"), None); assert_eq!(classify("execute", "execute::shell"), None);
assert_eq!(classify("ctrlc", "ctrlc::set_handler"), Some("Ipc"));
assert_eq!(classify("ctrlc", "ctrlc::try_set_handler"), Some("Ipc"));
assert_eq!(classify("clap", "clap::Command::get_matches"), Some("Env"));
assert_eq!(classify("clap", "clap::Command::try_get_matches"), Some("Env"));
assert_eq!(classify("clap", "clap::Parser::parse"), Some("Env"));
assert_eq!(classify("clap", "clap::Command::new"), None); assert_eq!(classify("clap", "clap::Arg::about"), None); assert_eq!(classify("clap", "clap::Command::get_matches_from"), None); assert_eq!(classify("clap", "clap::Arg::env"), Some("Env"));
assert_eq!(classify("clap", "clap::Arg::env_os"), Some("Env"));
assert_eq!(classify("jiff", "jiff::Timestamp::now"), Some("Clock"));
assert_eq!(classify("jiff", "jiff::Zoned::now_with"), Some("Clock"));
assert_eq!(classify("jiff", "jiff::tz::TimeZone::system"), Some("Fs"));
assert_eq!(classify("jiff", "jiff::tz::TimeZone::get"), Some("Fs"));
assert_eq!(classify("jiff", "jiff::Span::checked_add"), None);
assert_eq!(classify("crossterm", "crossterm::ExecutableCommand::execute"), Some("Ipc"));
assert_eq!(classify("crossterm", "crossterm::QueueableCommand::queue"), Some("Ipc"));
assert_eq!(classify("crossterm", "crossterm::event::read"), Some("Ipc"));
assert_eq!(classify("crossterm", "crossterm::event::poll"), Some("Ipc"));
assert_eq!(classify("crossterm", "crossterm::terminal::enable_raw_mode"), Some("Ipc"));
assert_eq!(classify("crossterm", "crossterm::terminal::size"), Some("Ipc"));
assert_eq!(classify("crossterm", "crossterm::style::Print"), None);
assert_eq!(classify("crossterm", "crossterm::cursor::MoveTo"), None);
assert_eq!(classify("ratatui", "ratatui::Terminal::draw"), Some("Ipc"));
assert_eq!(classify("ratatui", "ratatui::Terminal::flush"), Some("Ipc"));
assert_eq!(classify("ratatui", "ratatui::Terminal::clear"), Some("Ipc"));
assert_eq!(classify("ratatui", "ratatui::Terminal::hide_cursor"), Some("Ipc"));
assert_eq!(classify("ratatui", "ratatui::widgets::canvas::Context::draw"), None);
assert_eq!(classify("ratatui", "ratatui::widgets::canvas::Context::layer"), None);
assert_eq!(classify("ratatui", "ratatui::backend::CrosstermBackend::flush"), Some("Ipc"));
assert_eq!(classify("ratatui", "ratatui::widgets::Paragraph::new"), None);
assert_eq!(classify("ratatui", "ratatui::layout::Layout::split"), None);
assert_eq!(classify("ratatui", "ratatui::style::Style::fg"), None);
assert_eq!(classify("ratatui", "ratatui::buffer::Buffer::set_string"), None);
assert_eq!(classify("tracing_subscriber", "tracing_subscriber::fmt::init"), Some("Log"));
assert_eq!(classify("tracing_subscriber", "tracing_subscriber::fmt::try_init"), Some("Log"));
assert_eq!(classify("tracing_subscriber", "tracing_subscriber::fmt::SubscriberBuilder::init"), Some("Log"));
assert_eq!(classify("tracing_subscriber", "tracing_subscriber::EnvFilter::from_default_env"), Some("Env"));
assert_eq!(classify("tracing_subscriber", "tracing_subscriber::EnvFilter::from_env"), Some("Env"));
assert_eq!(classify("tracing_subscriber", "tracing_subscriber::fmt::layer"), Some("Env"));
assert_eq!(classify("tracing_subscriber", "tracing_subscriber::fmt::SubscriberBuilder::with_target"), None);
assert_eq!(classify("tracing_subscriber", "tracing_subscriber::EnvFilter::new"), None);
assert_eq!(classify("env_logger", "env_logger::init"), Some("Log"));
assert_eq!(classify("env_logger", "env_logger::try_init"), Some("Log"));
assert_eq!(classify("env_logger", "env_logger::Builder::init"), Some("Log"));
assert_eq!(classify("env_logger", "env_logger::Builder::format_timestamp"), None); assert_eq!(classify("env_logger", "env_logger::Builder::build"), None);
assert_eq!(classify("dialoguer", "dialoguer::Input::interact_text"), Some("Ipc"));
assert_eq!(classify("dialoguer", "dialoguer::Confirm::interact"), Some("Ipc"));
assert_eq!(classify("dialoguer", "dialoguer::Select::interact_opt"), Some("Ipc"));
assert_eq!(classify("dialoguer", "dialoguer::Input::with_prompt"), None); assert_eq!(classify("dialoguer", "dialoguer::Editor::new"), Some("Env"));
assert_eq!(classify("dialoguer", "dialoguer::Editor::default"), Some("Env"));
assert_eq!(classify("dialoguer", "dialoguer::Editor::edit"), Some("Exec"));
assert_eq!(classify("dialoguer", "dialoguer::Editor::extension"), None);
assert_eq!(classify("console", "console::Term::write_line"), Some("Ipc"));
assert_eq!(classify("console", "console::Term::read_key"), Some("Ipc"));
assert_eq!(classify("console", "console::colors_enabled"), Some("Env"));
assert_eq!(classify("console", "console::Style::cyan"), None); assert_eq!(classify("console", "console::strip_ansi_codes"), None); assert_eq!(classify("console", "console::Term::write"), Some("Ipc"));
assert_eq!(classify("console", "console::Term::flush"), Some("Ipc"));
assert_eq!(classify("console", "console::Term::read"), Some("Ipc"));
assert_eq!(classify("terminal_colorsaurus", "terminal_colorsaurus::background_color"), Some("Ipc"));
assert_eq!(classify("terminal_colorsaurus", "terminal_colorsaurus::color_palette"), Some("Ipc"));
assert_eq!(classify("backoff", "backoff::retry"), Some("Clock"));
assert_eq!(classify("backoff", "backoff::retry_notify"), Some("Clock"));
assert_eq!(classify("backoff", "backoff::ExponentialBackoff::default"), Some("Clock"));
assert_eq!(classify("lscolors", "lscolors::LsColors::from_env"), Some("Env"));
assert_eq!(classify("lscolors", "lscolors::LsColors::from_string"), None);
assert_eq!(classify("lscolors", "lscolors::LsColors::style_for_path"), None);
assert_eq!(classify("wild", "wild::args"), Some("Env"));
assert_eq!(classify("wild", "wild::args_os"), Some("Env"));
assert_eq!(classify("grep_cli", "grep_cli::CommandReaderBuilder::build"), Some("Exec"));
assert_eq!(classify("grep_cli", "grep_cli::is_readable_stdin"), None); assert_eq!(classify("grep_cli", "grep_cli::is_tty_stdout"), None);
assert_eq!(classify("clircle", "clircle::Identifier::try_from"), Some("Fs"));
assert_eq!(classify("clircle", "clircle::Clircle::surely_conflicts_with"), Some("Fs"));
}
#[test]
fn log_tracing_emit_macros_classify_pre_expansion() {
assert_eq!(classify("log", "log::info"), Some("Log"));
assert_eq!(classify("log", "log::error"), Some("Log"));
assert_eq!(classify("tracing", "tracing::warn"), Some("Log"));
assert_eq!(classify("tracing", "tracing::info_span"), Some("Log"));
assert_eq!(classify("log", "log::Level::as_str"), None);
assert_eq!(classify("tracing", "tracing::Level::INFO"), None);
}
#[test]
fn classify_core_effects() {
assert_eq!(classify("std", "std::fs::read_to_string"), Some("Fs"));
assert_eq!(classify("std", "std::path::Path::symlink_metadata"), Some("Fs"));
assert_eq!(classify("std", "std::path::PathBuf::read_dir"), Some("Fs"));
assert_eq!(classify("std", "std::path::Path::exists"), Some("Fs"));
assert_eq!(classify("std", "std::path::Path::join"), None); assert_eq!(classify("std", "std::path::PathBuf::file_name"), None);
assert_eq!(classify("std", "std::path::Path::parent"), None);
assert_eq!(classify("std", "std::process::Command::new"), Some("Exec"));
assert_eq!(classify("std", "std::env::var"), Some("Env"));
assert_eq!(classify("reqwest", "reqwest::Client::execute"), Some("Net"));
assert_eq!(classify("reqwest", "reqwest::get"), Some("Net"));
assert_eq!(classify("reqwest", "reqwest::blocking::get"), Some("Net"));
assert_eq!(classify("reqwest", "reqwest::Client::get"), Some("Net"));
assert_eq!(classify("reqwest", "reqwest::Client::post"), Some("Net"));
assert_eq!(classify("reqwest", "reqwest::Client::put"), Some("Net"));
assert_eq!(classify("reqwest", "reqwest::Client::delete"), Some("Net"));
assert_eq!(classify("reqwest", "reqwest::Client::request"), Some("Net"));
assert_eq!(classify("reqwest", "reqwest::RequestBuilder::header"), None);
assert_eq!(classify("reqwest", "reqwest::RequestBuilder::json"), None);
assert_eq!(classify("reqwest", "reqwest::ClientBuilder::build"), Some("Env"));
assert_eq!(classify("libc", "libc::connect"), Some("Net"));
assert_eq!(classify("libc", "libc::socket"), Some("Net"));
assert_eq!(classify("libc", "libc::bind"), Some("Net"));
assert_eq!(classify("libc", "libc::accept"), Some("Net"));
assert_eq!(classify("nix", "nix::fcntl::open"), Some("Fs"));
assert_eq!(classify("nix", "nix::sys::socket::connect"), Some("Net"));
assert_eq!(classify("nix", "nix::sys::socket::socket"), Some("Net"));
assert_eq!(classify("nix", "nix::unistd::execvp"), Some("Exec"));
assert_eq!(classify("nix", "nix::unistd::write"), None); assert_eq!(classify("nix", "nix::unistd::getpid"), None); assert_eq!(classify("rustix", "rustix::time::clock_settime"), Some("Clock"));
assert_eq!(classify("rustix", "rustix::fs::symlink"), Some("Fs"));
assert_eq!(classify("rustix", "rustix::net::connect"), Some("Net"));
assert_eq!(classify("rustix", "rustix::io::read"), None); assert_eq!(classify("pnet", "pnet::datalink::channel"), Some("Net"));
assert_eq!(classify("pnet", "pnet::transport::transport_channel"), Some("Net"));
assert_eq!(classify("pnet_datalink", "pnet_datalink::channel"), Some("Net"));
assert_eq!(classify("pnet", "pnet::packet::ethernet::EthernetPacket::new"), None);
assert_eq!(classify("pnet_base", "pnet_base::MacAddr::new"), None);
assert_eq!(classify("ignore", "ignore::WalkBuilder::build_parallel"), Some("Fs"));
assert_eq!(classify("ignore", "ignore::WalkBuilder::build"), Some("Fs"));
assert_eq!(classify("ignore", "ignore::WalkParallel::run"), Some("Fs"));
assert_eq!(classify("ignore", "ignore::WalkBuilder::add_ignore"), Some("Fs")); assert_eq!(classify("ignore", "ignore::overrides::OverrideBuilder::build"), None); assert_eq!(classify("ignore", "ignore::gitignore::GitignoreBuilder::build"), None); assert_eq!(classify("ignore", "ignore::DirEntry::path"), None); assert_eq!(classify("ignore", "ignore::Walk::new"), Some("Fs"));
assert_eq!(classify("ignore", "ignore::Walk::from_iter"), Some("Fs"));
assert_eq!(classify("walkdir", "walkdir::Walk::new"), None);
assert_eq!(classify("some_local_crate", "some_local_crate::Walk::new"), None);
assert_eq!(classify("notify", "notify::RecommendedWatcher::new"), Some("Fs"));
assert_eq!(classify("notify", "notify::PollWatcher::new"), Some("Fs"));
assert_eq!(classify("notify", "notify::recommended_watcher"), Some("Fs"));
assert_eq!(classify("notify", "notify::INotifyWatcher::watch"), Some("Fs"));
assert_eq!(classify("notify", "notify::Config::default"), None); assert_eq!(classify("notify", "notify::Event::new"), None); assert_eq!(classify("rusqlite", "rusqlite::Connection::execute"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Connection::query_row"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Statement::query_map"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Connection::execute_batch"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Connection::prepare_cached"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Connection::open"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Connection::open_in_memory"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Connection::open_in_memory_with_flags"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Connection::open_with_flags_and_vfs"), Some("Db"));
assert_eq!(
classify("rusqlite", "rusqlite::Connection::open_in_memory_with_flags_and_vfs"),
Some("Db")
);
assert_eq!(classify("rusqlite", "rusqlite::Connection::blob_open"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::blob::Blob::reopen"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::pragma::Sql::open_brace"), None);
assert_eq!(classify("rusqlite", "rusqlite::Backup::new"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Backup::new_with_names"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Backup::step"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Backup::run_to_completion"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Connection::backup"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Connection::restore"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Blob::read_at"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Blob::read_at_exact"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Blob::raw_read_at"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Blob::raw_read_at_exact"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Blob::write_at"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Blob::write_all_at"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Connection::from_handle"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Connection::from_handle_owned"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::Connection::extension_init2"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::init_auto_extension"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::backup::Backup::new"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::blob::Blob::read_at"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::auto_extension::init_auto_extension"), Some("Db"));
assert_eq!(classify("rusqlite", "rusqlite::InnerConnection::close"), None);
assert_eq!(classify("rusqlite", "rusqlite::RawStatement::step"), None);
assert_eq!(classify("postgres", "postgres::Client::open"), None);
assert_eq!(classify("tokio_postgres", "tokio_postgres::Client::query_typed"), Some("Db"));
assert_eq!(classify("tokio_postgres", "tokio_postgres::Config::connect_raw"), Some("Db"));
assert_eq!(classify("diesel", "diesel::RunQueryDsl::first"), Some("Db"));
assert_eq!(classify("diesel", "diesel::RunQueryDsl::load_iter"), Some("Db"));
assert_eq!(classify("diesel", "diesel::sqlite::SqliteConnection::establish"), Some("Db"));
assert_eq!(classify("diesel", "diesel::pg::PgConnection::establish"), Some("Db"));
assert_eq!(classify("diesel", "diesel::mysql::MysqlConnection::establish"), Some("Db"));
assert_eq!(classify("diesel", "diesel::Connection::establish"), Some("Db"));
assert_eq!(classify("diesel", "diesel::sqlite::SqliteConnection::establish_inner"), None);
assert_eq!(classify("sqlx", "sqlx::query::Query::fetch_many"), Some("Db"));
assert_eq!(classify("sqlx", "sqlx::query"), None);
assert_eq!(classify("tracing", "tracing::event"), Some("Log"));
assert_eq!(classify("tracing", "tracing::Span::new_span"), Some("Log"));
assert_eq!(classify("tracing", "tracing::Span::record"), Some("Log"));
assert_eq!(classify("tracing", "tracing::Span::enter"), Some("Log"));
assert_eq!(classify("tracing", "tracing::Level::as_str"), None); assert_eq!(classify("tracing", "tracing::Span::is_disabled"), None); assert_eq!(classify("tracing", "tracing::Span::metadata"), None); assert_eq!(classify("tracing", "tracing::metadata::Level::TRACE"), None); assert_eq!(classify("tracing", "tracing::field::Field::name"), None); assert_eq!(classify("git2", "git2::Remote::fetch"), Some("Net"));
assert_eq!(classify("git2", "git2::Remote::push"), Some("Net"));
assert_eq!(classify("git2", "git2::Remote::download"), Some("Net"));
assert_eq!(classify("git2", "git2::Remote::connect"), Some("Net"));
assert_eq!(classify("git2", "git2::Remote::connect_auth"), Some("Net"));
assert_eq!(classify("git2", "git2::Remote::ls"), Some("Net"));
assert_eq!(classify("git2", "git2::Remote::upload"), Some("Net"));
assert_eq!(classify("git2", "git2::Repository::open"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::init"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::open_bare"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::open_ext"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::open_from_env"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::discover"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::discover_path"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::init_bare"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::init_opts"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::blob_path"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::checkout_head"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::checkout_index"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::checkout_tree"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::commit"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::reference"), Some("Fs"));
assert_eq!(classify("git2", "git2::Repository::tag"), Some("Fs"));
assert_eq!(classify("git2", "git2::Config::add_file"), Some("Fs"));
assert_eq!(classify("git2", "git2::Config::open"), Some("Fs"));
assert_eq!(classify("git2", "git2::Config::open_default"), Some("Fs"));
assert_eq!(classify("git2", "git2::Index::add_all"), Some("Fs"));
assert_eq!(classify("git2", "git2::Index::add_path"), Some("Fs"));
assert_eq!(classify("git2", "git2::Index::read"), Some("Fs"));
assert_eq!(classify("git2", "git2::Index::write"), Some("Fs"));
assert_eq!(classify("git2", "git2::Index::write_tree"), Some("Fs"));
assert_eq!(classify("git2", "git2::Index::write_tree_to"), Some("Fs"));
assert_eq!(classify("git2", "git2::Odb::read"), Some("Fs"));
assert_eq!(classify("git2", "git2::Odb::reader"), Some("Fs"));
assert_eq!(classify("git2", "git2::Odb::write"), Some("Fs"));
assert_eq!(classify("git2", "git2::Odb::writer"), Some("Fs"));
assert_eq!(classify("git2", "git2::PackBuilder::write"), Some("Fs"));
assert_eq!(classify("git2", "git2::Reference::delete"), Some("Fs"));
assert_eq!(classify("git2", "git2::Reference::set_target"), Some("Fs"));
assert_eq!(classify("git2", "git2::TreeBuilder::write"), Some("Fs"));
assert_eq!(classify("git2", "git2::Remote::list"), Some("Net"));
assert_eq!(classify("git2", "git2::RemoteConnection::list"), Some("Net"));
assert_eq!(classify("git2", "git2::Cred::credential_helper"), Some("Exec"));
assert_eq!(classify("git2", "git2::CredentialHelper::execute"), Some("Exec"));
assert_eq!(classify("git2", "git2::Repository::state"), None);
assert_eq!(classify("git2", "git2::Blob::content"), None);
assert_eq!(classify("tonic", "tonic::transport::server::Router::serve"), Some("Net"));
assert_eq!(
classify("tonic", "tonic::transport::server::Router::serve_with_shutdown"),
Some("Net")
);
assert_eq!(classify("tonic", "tonic::TcpIncoming::new"), Some("Net"));
assert_eq!(classify("tonic", "tonic::transport::server::Server::serve_with_shutdown"), Some("Net"));
assert_eq!(classify("tonic", "tonic::transport::Server::serve_with_shutdown"), Some("Net"));
assert_eq!(classify("git2", "git2::Repository::clone"), Some("Net"));
assert_eq!(classify("git2", "git2::Repository::clone_recurse"), Some("Net"));
assert_eq!(classify("git2", "git2::build::RepoBuilder::clone"), Some("Net"));
assert_eq!(classify("git2", "git2::Remote::clone"), None);
assert_eq!(classify("git2", "git2::Submodule::clone"), Some("Net"));
assert_eq!(classify("git2", "git2::Submodule::update"), Some("Net"));
assert_eq!(classify("git2", "git2::build::CheckoutBuilder::update_only"), None);
assert_eq!(classify("git2", "git2::DiffOptions::update_index"), None);
assert_eq!(classify("git2", "git2::Submodule::update_strategy"), None);
assert_eq!(classify("memmap2", "memmap2::MmapOptions::map"), Some("Fs"));
assert_eq!(classify("memmap2", "memmap2::MmapOptions::map_mut"), Some("Fs"));
assert_eq!(classify("memmap2", "memmap2::Mmap::flush"), Some("Fs"));
assert_eq!(classify("memmap2", "memmap2::MmapMut::make_read_only"), Some("Fs"));
assert_eq!(classify("memmap2", "memmap2::Mmap::len"), None); assert_eq!(classify("memmap2", "memmap2::Mmap::is_empty"), None); assert_eq!(classify("memmap2", "memmap2::Mmap::as_ptr"), None); assert_eq!(classify("memmap2", "memmap2::MmapOptions::new"), None); assert_eq!(classify("arboard", "arboard::Clipboard::new"), Some("Clipboard"));
assert_eq!(classify("arboard", "arboard::Clipboard::get_text"), Some("Clipboard"));
assert_eq!(classify("arboard", "arboard::Clipboard::set_text"), Some("Clipboard"));
assert_eq!(classify("arboard", "arboard::Clipboard::clear"), Some("Clipboard"));
assert_eq!(classify("arboard", "arboard::Error::to_string"), None); assert_eq!(classify("arboard", "arboard::Error::fmt"), None); assert_eq!(classify("arboard", "arboard::ImageData::to_owned_img"), None); assert_eq!(classify("arboard", "arboard::Get::file_list"), Some("Clipboard"));
assert_eq!(classify("arboard", "arboard::Set::file_list"), Some("Clipboard"));
assert_eq!(classify("arboard", "arboard::Clear::default"), Some("Clipboard"));
assert_eq!(classify("fastrand", "fastrand::u32"), Some("Rand")); assert_eq!(classify("fastrand", "fastrand::Rng::usize"), Some("Rand"));
assert_eq!(classify("fastrand", "fastrand::Rng::shuffle"), Some("Rand"));
assert_eq!(classify("fastrand", "fastrand::Rng::new"), Some("Rand")); assert_eq!(classify("fastrand", "fastrand::Rng::with_seed"), None); assert_eq!(classify("fastrand", "fastrand::Rng::fork"), None); assert_eq!(classify("fastrand", "fastrand::Rng::clone"), None); assert_eq!(classify("portable_pty", "portable_pty::PtySystem::openpty"), Some("Exec"));
assert_eq!(classify("portable_pty", "portable_pty::SlavePty::spawn_command"), Some("Exec"));
assert_eq!(classify("portable_pty", "portable_pty::CommandBuilder::get_argv"), None); assert_eq!(classify("portable_pty", "portable_pty::CommandBuilder::get_cwd"), None); assert_eq!(classify("portable_pty", "portable_pty::PtySize::default"), None); assert_eq!(classify("async_process", "async_process::Command::spawn"), Some("Exec"));
assert_eq!(classify("async_process", "async_process::Command::output"), Some("Exec"));
assert_eq!(classify("async_process", "async_process::Stdio::piped"), None); assert_eq!(classify("async_process", "async_process::Stdio::null"), None); assert_eq!(classify("libc", "libc::open"), Some("Fs"));
assert_eq!(classify("libc", "libc::connect"), Some("Net"));
assert_eq!(classify("libc", "libc::read"), None); assert_eq!(classify("ffi", "ffi::sqlite3_step"), Some("Db"));
assert_eq!(classify("ffi", "ffi::sqlite3_auto_extension"), Some("Db"));
assert_eq!(classify("ffi", "ffi::sqlite3_cancel_auto_extension"), Some("Db"));
assert_eq!(classify("ffi", "ffi::sqlite3_reset_auto_extension"), Some("Db"));
assert_eq!(classify("ffi", "ffi::sqlite3_enable_load_extension"), Some("Db"));
assert_eq!(classify("ffi", "ffi::sqlite3_deserialize"), Some("Db"));
assert_eq!(classify("ffi", "ffi::sqlite3_serialize"), Some("Db"));
assert_eq!(classify("ffi", "ffi::sqlite3_db_cacheflush"), Some("Db"));
assert_eq!(classify("ffi", "ffi::sqlite3_file_control"), Some("Db"));
assert_eq!(classify("ffi", "ffi::sqlite3_wal_autocheckpoint"), Some("Db"));
assert_eq!(classify("ffi", "ffi::sqlite3_column_int64"), None);
assert_eq!(classify("ffi", "ffi::sqlite3_create_function_v2"), None);
assert_eq!(classify("raw", "raw::git_remote_fetch"), Some("Net"));
assert_eq!(classify("raw", "raw::git_clone"), Some("Net"));
assert_eq!(classify("raw", "raw::git_submodule_clone"), Some("Net"));
assert_eq!(classify("raw", "raw::git_submodule_update"), Some("Net"));
assert_eq!(classify("raw", "raw::git_submodule_open"), None); assert_eq!(classify("curl_sys", "curl_sys::curl_easy_perform"), Some("Net"));
assert_eq!(classify("curl_sys", "curl_sys::curl_easy_send"), Some("Net"));
assert_eq!(classify("curl_sys", "curl_sys::curl_multi_perform"), Some("Net"));
assert_eq!(classify("curl_sys", "curl_sys::curl_multi_socket_action"), Some("Net"));
assert_eq!(classify("curl_sys", "curl_sys::curl_easy_setopt"), None); assert_eq!(classify("curl_sys", "curl_sys::curl_easy_init"), None); assert_eq!(classify("curl_sys", "curl_sys::curl_multi_wait"), None); assert_eq!(classify("curl", "curl::easy::Easy::perform"), Some("Net"));
assert_eq!(classify("curl", "curl::multi::Multi::perform"), Some("Net"));
assert_eq!(classify("curl", "curl::easy::Easy::send"), Some("Net"));
assert_eq!(classify("curl", "curl::easy::Easy::url"), None); assert_eq!(classify("curl", "curl::easy::Easy::timeout"), None); assert_eq!(classify("ffi", "ffi::SSL_connect"), Some("Net"));
assert_eq!(classify("serde", "serde::Serialize::serialize"), None);
assert_eq!(classify("std", "std::vec::Vec::push"), None);
assert_eq!(classify("std", "std::net::TcpStream::connect"), Some("Net"));
assert_eq!(classify("std", "std::net::TcpStream::local_addr"), None);
assert_eq!(classify("std", "std::net::TcpStream::nodelay"), None);
assert_eq!(classify("std", "std::net::TcpStream::ttl"), None);
assert_eq!(classify("std", "std::net::UdpSocket::peer_addr"), None);
assert_eq!(classify("std", "std::net::lookup_host"), Some("Net"));
assert_eq!(classify("std", "core::net::ToSocketAddrs::to_socket_addrs"), Some("Net"));
assert_eq!(classify("std", "std::process::Command::get_program"), None);
assert_eq!(classify("std", "std::process::Command::get_args"), None);
assert_eq!(classify("std", "std::process::Child::id"), None);
assert_eq!(classify("std", "std::process::Command::spawn"), Some("Exec"));
assert_eq!(classify("redis", "redis::aio::ConnectionManager::clone"), None);
assert_eq!(classify("redis", "redis::aio::ConnectionManager::send_packed_command"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::sea_query::Func::count"), None);
assert_eq!(classify("sea_orm", "sea_orm::sea_query::Condition::all"), None);
assert_eq!(classify("sea_orm", "sea_orm::Select::all"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::Database::connect_proxy"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::DatabaseConnection::transaction"), Some("Db"));
assert_eq!(
classify("sea_orm", "sea_orm::DatabaseConnection::transaction_with_config"),
Some("Db")
);
assert_eq!(classify("sea_orm", "sea_orm::DatabaseConnection::ping"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::DatabaseConnection::begin"), Some("Db"));
assert_eq!(
classify("sea_orm", "sea_orm::DatabaseConnection::begin_with_config"),
Some("Db")
);
assert_eq!(classify("sea_orm", "sea_orm::DatabaseTransaction::commit"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::DatabaseTransaction::rollback"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::SqlxMySqlPoolConnection::begin"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::SqlxMySqlPoolConnection::ping"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::SqlxMySqlPoolConnection::transaction"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::SqlxPostgresPoolConnection::begin"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::SqlxSqlitePoolConnection::ping"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::Paginator::fetch"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::Paginator::fetch_and_next"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::Paginator::into_stream"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::Paginator::num_pages"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::Paginator::num_items_and_pages"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::Insert::exec_with_returning_keys"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::Inserter::exec_with_returning_many"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::TryInsert::exec_with_returning_keys"), Some("Db"));
assert_eq!(classify("sea_orm", "sea_orm::MockDatabaseConnection::ping"), None);
assert_eq!(classify("sea_orm", "sea_orm::MockDatabaseConnection::begin"), None);
assert_eq!(classify("sea_orm", "sea_orm::ProxyDatabaseConnection::commit"), None);
assert_eq!(classify("sea_orm", "sea_orm::ProxyDatabaseConnection::ping"), None);
}
#[test]
fn lettre_tls_setup_and_connection_family_is_covered() {
assert_eq!(
classify("lettre", "lettre::transport::smtp::client::TlsParametersBuilder::build_rustls"),
Some("Fs")
);
assert_eq!(classify("lettre", "lettre::TlsParametersBuilder::build"), Some("Fs"));
assert_eq!(classify("lettre", "lettre::TlsParameters::new"), Some("Fs"));
assert_eq!(classify("lettre", "lettre::TlsParameters::new_rustls"), Some("Fs"));
assert_eq!(classify("lettre", "lettre::SmtpTransport::from_url"), Some("Fs"));
assert_eq!(classify("lettre", "lettre::SmtpTransport::relay"), Some("Fs"));
assert_eq!(classify("lettre", "lettre::SmtpTransport::starttls_relay"), Some("Fs"));
assert_eq!(classify("lettre", "lettre::AsyncSmtpTransport::from_url"), Some("Fs"));
assert_eq!(classify("lettre", "lettre::AsyncSmtpTransport::relay"), Some("Fs"));
assert_eq!(classify("lettre", "lettre::AsyncSmtpTransport::starttls_relay"), Some("Fs"));
assert_eq!(classify("lettre", "lettre::FileTransport::read"), Some("Fs"));
assert_eq!(classify("lettre", "lettre::AsyncStd1Executor::connect"), Some("Net"));
assert_eq!(classify("lettre", "lettre::AsyncStd1Executor::fs_read"), Some("Fs"));
assert_eq!(classify("lettre", "lettre::AsyncStd1Executor::fs_write"), Some("Fs"));
assert_eq!(
classify(
"lettre",
"lettre::transport::smtp::client::AsyncSmtpConnection::connect_asyncstd1"
),
Some("Net")
);
assert_eq!(
classify(
"lettre",
"lettre::transport::smtp::client::AsyncNetworkStream::connect_asyncstd1"
),
Some("Net")
);
assert_eq!(classify("lettre", "lettre::NetworkStream::shutdown"), None);
assert_eq!(classify("lettre", "lettre::NetworkStream::set_read_timeout"), None);
}
#[test]
fn rand_osrng_handle_ops_are_pure_but_draws_are_rand() {
assert_eq!(classify("rand", "rand::rngs::OsRng::clone"), None);
assert_eq!(classify("rand", "rand::rngs::OsRng::default"), None);
assert_eq!(classify("rand", "rand::rngs::OsRng::fill_bytes"), Some("Rand")); assert_eq!(classify("rand", "rand::rngs::OsRng::next_u32"), Some("Rand"));
assert_eq!(classify("rand", "rand::Rng::gen"), Some("Rand")); assert_eq!(classify("rand", "rand::distributions::Uniform::new"), None); }
#[test]
fn redis_connection_manager_config_builder_is_pure() {
assert_eq!(classify("redis", "redis::aio::ConnectionManagerConfig::new"), None);
assert_eq!(classify("redis", "redis::aio::ConnectionManagerConfig::set_max_delay"), None);
assert_eq!(classify("redis", "redis::aio::ConnectionManager::new"), Some("Db"));
assert_eq!(classify("redis", "redis::Commands::get"), Some("Db"));
}
#[test]
fn redis_get_connection_info_is_a_pure_accessor_not_swept_by_the_substring() {
assert_eq!(classify("redis", "redis::Client::get_connection_info"), None);
assert_eq!(classify("redis", "redis::Client::get_connection"), Some("Db"));
assert_eq!(classify("redis", "redis::Client::get_async_connection"), Some("Db"));
assert_eq!(
classify("redis", "redis::Client::get_multiplexed_async_connection"),
Some("Db")
);
}
#[test]
fn aws_config_load_from_env_is_loads_own_convenience_wrapper() {
assert_eq!(classify("aws_config", "aws_config::load"), Some("Net"));
assert_eq!(classify("aws_config", "aws_config::load_defaults"), Some("Net"));
assert_eq!(classify("aws_config", "aws_config::load_from_env"), Some("Net"));
assert_eq!(classify("aws_config", "aws_config::from_env"), None); }
#[test]
fn tungstenite_stream_first_handshake_entry_points_are_net() {
assert_eq!(classify("tungstenite", "tungstenite::client::client"), Some("Net"));
assert_eq!(classify("tungstenite", "tungstenite::client::client_with_config"), Some("Net"));
assert_eq!(classify("tungstenite", "tungstenite::tls::client_tls"), Some("Net"));
assert_eq!(classify("tungstenite", "tungstenite::tls::client_tls_with_config"), Some("Net"));
assert_eq!(classify("tungstenite", "tungstenite::server::accept"), Some("Net"));
assert_eq!(classify("tungstenite", "tungstenite::server::accept_with_config"), Some("Net"));
assert_eq!(classify("tungstenite", "tungstenite::server::accept_hdr"), Some("Net"));
assert_eq!(classify("tungstenite", "tungstenite::server::accept_hdr_with_config"), Some("Net"));
assert_eq!(classify("tungstenite", "tungstenite::client::connect_with_config"), Some("Net"));
}
#[test]
fn mysql_conn_new_is_the_real_connect() {
assert_eq!(classify("mysql", "mysql::Conn::new"), Some("Db"));
assert_eq!(classify("mysql_async", "mysql_async::Conn::new"), Some("Db"));
assert_eq!(classify("mysql", "mysql::Opts::new"), None);
assert_eq!(classify("mysql", "mysql::PoolConstraints::new"), None);
assert_eq!(classify("mysql_async", "mysql_async::TxOpts::new"), None);
}
#[test]
fn mongodb_with_options_is_the_same_effect_as_with_uri_str() {
assert_eq!(classify("mongodb", "mongodb::Client::with_uri_str"), Some("Db"));
assert_eq!(classify("mongodb", "mongodb::Client::with_options"), Some("Db"));
assert_eq!(classify("mongodb", "mongodb::sync::Client::with_options"), Some("Db"));
assert_eq!(classify("mongodb", "mongodb::Collection::find_one"), Some("Db"));
assert_eq!(classify("some_other_crate", "some_other_crate::Widget::with_options"), None);
}
#[test]
fn pure_fd_transfer_is_not_an_effect() {
assert_eq!(classify("std", "std::net::TcpStream::from_raw_fd"), None);
assert_eq!(classify("std", "std::net::TcpStream::into_raw_fd"), None);
assert_eq!(classify("std", "std::net::TcpStream::as_raw_fd"), None);
assert_eq!(classify("std", "std::net::TcpListener::from_raw_fd"), None);
assert_eq!(classify("std", "std::net::UdpSocket::from_raw_socket"), None);
assert_eq!(classify("std", "std::fs::File::from_raw_fd"), None);
assert_eq!(classify("std", "std::fs::File::into_raw_fd"), None);
assert_eq!(classify("std", "std::fs::File::as_raw_handle"), None);
assert_eq!(classify("std", "std::os::unix::net::UnixStream::from_raw_fd"), None);
assert_eq!(classify("std", "std::os::unix::net::SocketAddr::from_pathname"), None);
assert_eq!(classify("tokio", "tokio::net::TcpStream::from_raw_fd"), None);
assert_eq!(classify("tokio", "tokio::net::TcpStream::into_std"), None); assert_eq!(classify("tokio", "tokio::fs::File::into_std"), None);
assert_eq!(classify("std", "std::net::TcpStream::connect"), Some("Net"));
assert_eq!(classify("std", "std::fs::File::open"), Some("Fs"));
assert_eq!(classify("std", "std::fs::read"), Some("Fs"));
assert_eq!(classify("std", "std::os::unix::net::UnixStream::connect"), Some("Ipc"));
assert_eq!(classify("tokio", "tokio::net::TcpStream::connect"), Some("Net"));
assert_eq!(classify("tokio", "tokio::time::Instant::now"), Some("Clock"));
assert_eq!(classify("tokio", "tokio::time::Instant::from_std"), None);
assert_eq!(classify("quanta", "quanta::Instant::now"), Some("Clock"));
assert_eq!(classify("web_time", "web_time::Instant::now"), Some("Clock"));
}
#[test]
fn the_platform_fs_modules_are_filesystem_io_and_their_data_traits_are_not() {
for p in [
"std::os::unix::fs::symlink", "std::os::unix::fs::chown", "std::os::unix::fs::lchown",
"std::os::unix::fs::fchown", "std::os::unix::fs::chroot",
"std::os::windows::fs::symlink_dir", "std::os::windows::fs::symlink_file",
"std::os::windows::fs::junction_point",
"std::os::unix::fs::FileExt::read_at", "std::os::unix::fs::FileExt::write_at",
"std::os::windows::fs::FileExt::seek_read", "std::os::windows::fs::FileExt::seek_write",
] {
assert_eq!(classify("std", p), Some("Fs"), "{p} performs filesystem I/O");
}
for p in [
"std::os::unix::fs::MetadataExt::uid", "std::os::unix::fs::MetadataExt::mode",
"std::os::unix::fs::PermissionsExt::mode", "std::os::unix::fs::PermissionsExt::set_mode",
"std::os::unix::fs::OpenOptionsExt::custom_flags",
"std::os::unix::fs::DirBuilderExt::mode",
"std::os::unix::fs::DirEntryExt::ino", "std::os::unix::fs::FileTypeExt::is_fifo",
"std::os::windows::fs::MetadataExt::file_attributes",
] {
assert_eq!(classify("std", p), None,
"{p} reads or configures data already in hand — charging it would FABRICATE Fs");
}
assert_eq!(classify("std", "std::os::unix::net::UnixStream::connect"), Some("Ipc"));
}
#[test]
fn the_platform_process_modules_are_exec_and_their_status_traits_are_not() {
for p in [
"std::os::unix::process::CommandExt::exec",
"std::os::unix::process::CommandExt::pre_exec",
"std::os::unix::process::CommandExt::arg0",
"std::os::unix::process::CommandExt::uid",
"std::os::unix::process::CommandExt::gid",
"std::os::unix::process::CommandExt::groups",
"std::os::unix::process::CommandExt::process_group",
"std::os::windows::process::CommandExt::creation_flags",
"std::os::windows::process::CommandExt::raw_arg",
"std::os::windows::process::ChildExt::main_thread_handle",
"std::os::wasi::process::CommandExt::exec",
] {
assert_eq!(classify("std", p), Some("Exec"), "{p} is subprocess machinery");
}
for p in [
"std::os::unix::process::ExitStatusExt::signal",
"std::os::unix::process::ExitStatusExt::core_dumped",
"std::os::unix::process::ExitStatusExt::from_raw",
"std::os::unix::process::ExitStatusExt::into_raw",
"std::os::unix::process::ExitStatusError::signal",
"std::os::windows::process::ExitStatusExt::from_raw",
"std::os::windows::process::ExitCodeExt::from_raw",
"std::os::unix::process::parent_id",
] {
assert_eq!(classify("std", p), None,
"{p} reads a status already collected (or this process's own pid) — charging it \
would FABRICATE Exec");
}
assert_eq!(classify("std", "std::os::unix::fs::FileExt::read_at"), Some("Fs"));
assert_eq!(classify("std", "std::os::unix::net::UnixStream::connect"), Some("Ipc"));
}
#[test]
fn command_head_refines_the_exec_cliff() {
use super::classify_command_head as h;
assert_eq!(h("curl"), &["Net"]);
assert_eq!(h("telnet"), &["Net"]);
assert_eq!(h("sftp"), &["Net"]);
assert_eq!(h("/usr/local/bin/psql"), &["Db"]); assert_eq!(h("mongo"), &["Db"]);
assert_eq!(h("cqlsh"), &["Db"]);
assert_eq!(h("candor-scan"), &["Env", "Fs"]);
assert_eq!(h("candor-run.sh"), &["Env", "Fs"]);
assert_eq!(h("some-unknown-tool"), &[] as &[&str]);
assert_eq!(h("make"), &[] as &[&str]);
assert_eq!(h("npm"), &[] as &[&str]);
assert_eq!(h("git"), &[] as &[&str]);
assert_eq!(h("rsync"), &[] as &[&str]);
assert!(is_cmd_builder_method("env") && is_cmd_builder_method("arg") && is_cmd_builder_method("current_dir"));
assert!(!is_cmd_builder_method("new")); assert!(!is_cmd_builder_method("cmd")); assert!(is_cmd_naming_method("new") && is_cmd_naming_method("cmd"));
assert!(!is_cmd_naming_method("get_env")); assert!(!is_cmd_naming_method("arg") && !is_cmd_naming_method("env") && !is_cmd_naming_method("current_dir"));
}
#[test]
fn db_query_arg_covers_the_sqlite3_sql_bearing_family() {
for f in ["sqlite3_exec", "sqlite3_prepare", "sqlite3_prepare_v2", "sqlite3_prepare_v3",
"sqlite3_prepare16", "sqlite3_prepare16_v2", "sqlite3_prepare16_v3",
"sqlite3_get_table"] {
assert!(is_db_query_arg(f), "{f} carries SQL — a runtime query there is invisible (R386)");
}
for f in ["sqlite3_step", "sqlite3_close", "sqlite3_open", "sqlite3_open_v2", "sqlite3_open16",
"sqlite3_serialize", "sqlite3_deserialize", "sqlite3_finalize", "sqlite3_reset",
"sqlite3_backup_init", "sqlite3_backup_step", "sqlite3_blob_open", "sqlite3_blob_read"] {
assert!(!is_db_query_arg(f),
"{f} carries no SQL — masking it claims an incomplete surface over nothing, and for \
the open* family it would claim a Db surface for a FILENAME");
}
for f in ["execute", "query", "prepare", "prepare_cached", "simple_query"] {
assert!(is_db_query_arg(f), "{f} was already covered and must stay covered");
}
}
#[test]
fn fs_path_arg_methods_are_the_receiver_pairs_not_the_leaf() {
for p in ["std::fs::OpenOptions::open", "tokio::fs::OpenOptions::open",
"cap_primitives::fs::OpenOptions::open", "fs_err::OpenOptions::open",
"std::fs::DirBuilder::create", "tokio::fs::DirBuilder::create"] {
assert!(is_fs_path_arg_method(p), "{p} takes its path as an ARGUMENT — R383");
}
for p in ["std::fs::File::read_to_string", "std::fs::File::write", "std::fs::File::write_all",
"std::fs::File::read", "std::fs::File::seek", "std::path::Path::exists",
"std::fs::OpenOptions::read", "std::fs::OpenOptions::truncate",
"std::fs::OpenOptions::map_err", "tokio::fs::OpenOptions::mode"] {
assert!(!is_fs_path_arg_method(p),
"{p} hides no path — it is a builder modifier, a combinator, or a use-verb whose \
path was fixed at open. Masking it is the over-mask this allowlist avoids.");
}
}
#[test]
fn net_establishing_allowlist() {
for m in ["connect", "connect_timeout", "get", "post", "put", "patch", "delete", "head",
"request", "send_to", "lookup_host", "to_socket_addrs"] {
assert!(is_net_establishing(m), "`{m}` takes the host as an argument and must establish");
}
for m in ["lookup", "lookup_ip", "resolve", "reverse_lookup", "srv_lookup", "mx_lookup",
"txt_lookup", "ipv4_lookup", "ipv6_lookup", "ns_lookup", "soa_lookup"] {
assert!(is_net_establishing(m),
"`{m}` resolves a caller-supplied host — R379. Without it, `allow Net <benign \
literal>` exits 0 over a DNS lookup of a runtime hostname.");
}
for m in ["write", "read", "send", "flush", "recv", "peek", "write_all", "read_to_end",
"write_vectored", "shutdown", "status", "headers", "text", "json"] {
assert!(!is_net_establishing(m), "`{m}` is a use-verb on an established connection");
}
}
#[test]
fn r817_accepting_is_not_binding() {
for (path, leaf) in [
("std::net::TcpListener::accept", "accept"),
("std::net::TcpListener::incoming", "incoming"),
("std::net::TcpListener::into_incoming", "into_incoming"),
("tokio::net::TcpListener::accept", "accept"),
("tokio::net::TcpListener::poll_accept", "poll_accept"),
("libc::accept", "accept"),
("libc::accept4", "accept4"),
("quinn::Endpoint::accept", "accept"),
("tonic::transport::server::Router::serve", "serve"),
("tonic::transport::server::Router::serve_with_shutdown", "serve_with_shutdown"),
("tonic::transport::server::TcpIncoming::new", "new"),
] {
assert!(is_net_accepting(path, leaf), "`{path}` accepts connections: its peers are unseen");
assert!(!is_net_binding(leaf), "`{leaf}` must not be a binding verb — binding withholds and marks nothing");
}
for (path, leaf) in [
("std::net::UdpSocket::bind", "bind"),
("std::net::TcpListener::bind", "bind"),
("libc::listen", "listen"),
("quinn::Connection::accept_bi", "accept_bi"),
("quinn::Connection::accept_uni", "accept_uni"),
("std::net::UdpSocket::recv_from", "recv_from"),
("tonic::transport::server::Server::serve_with_shutdown", "serve_with_shutdown"),
("reqwest::Client::new", "new"),
] {
assert!(!is_net_accepting(path, leaf), "`{path}` does not accept a connection");
}
for m in ["bind", "listen", "bind_to_device"] {
assert!(is_net_binding(m), "`{m}` names a LOCAL address");
}
}
#[test]
fn the_rejected_denylist_leaks_are_not_establishing() {
for m in ["bind", "into", "from", "from_std", "as_socket", "setsockopt", "getsockopt",
"map_err", "map", "ok", "try_clone", "complete_io"] {
assert!(!is_net_establishing(m),
"`{m}` hides no host and must not mark a surface incomplete. It was a MEASURED \
trigger of the rejected denylist inversion (544 rows gained `incomplete` over the \
registry, 0 lost) — a whole-crate-Net crate classifies every method as Net, which \
is why the allowlist is the precise side here. See R379.");
}
}
#[test]
fn fs_path_arg_allowlist() {
assert!(is_fs_path_arg("write") && is_fs_path_arg("read") && is_fs_path_arg("read_to_string"));
assert!(is_fs_path_arg("open") && is_fs_path_arg("create") && is_fs_path_arg("create_new"));
assert!(is_fs_path_arg("remove_file") && is_fs_path_arg("rename") && is_fs_path_arg("copy"));
assert!(is_fs_path_arg("create_dir_all") && is_fs_path_arg("canonicalize") && is_fs_path_arg("metadata"));
assert!(!is_fs_path_arg("write_all") && !is_fs_path_arg("flush") && !is_fs_path_arg("read_exact"));
assert!(!is_fs_path_arg("new") && !is_fs_path_arg("sync_all") && !is_fs_path_arg("set_len"));
}
#[test]
fn db_query_arg_allowlist() {
assert!(is_db_query_arg("execute") && is_db_query_arg("query") && is_db_query_arg("query_one"));
assert!(is_db_query_arg("prepare") && is_db_query_arg("batch_execute") && is_db_query_arg("execute_batch"));
assert!(is_db_query_arg("query_row") && is_db_query_arg("query_map") && is_db_query_arg("exec"));
assert!(!is_db_query_arg("fetch_all") && !is_db_query_arg("load") && !is_db_query_arg("first"));
assert!(!is_db_query_arg("all") && !is_db_query_arg("one") && !is_db_query_arg("stream"));
assert!(!is_db_query_arg("connect") && !is_db_query_arg("open") && !is_db_query_arg("begin"));
assert!(!is_db_query_arg("commit") && !is_db_query_arg("ping") && !is_db_query_arg("get_conn"));
}
}
#[cfg(test)]
mod fs_kind_tests {
use super::fs_kind;
#[test]
fn write_verbs() {
for p in ["std::fs::write", "std::fs::create_dir_all", "std::fs::remove_file",
"File::create", "std::fs::set_permissions", "f::write_all"] {
assert_eq!(fs_kind(p), &["write"], "{p} mutates the disk");
}
}
#[test]
fn read_verbs() {
for p in ["std::fs::read_to_string", "std::fs::read_dir", "std::fs::metadata",
"File::open", "std::fs::canonicalize", "f::read_to_end"] {
assert_eq!(fs_kind(p), &["read"], "{p} observes without mutating");
}
}
#[test]
fn two_locator_verbs_are_both() {
for p in ["std::fs::copy", "std::fs::rename", "std::fs::hard_link"] {
assert_eq!(fs_kind(p), &["read", "write"], "{p}");
}
}
#[test]
fn unrevealing_verbs_make_no_claim() {
for p in ["std::fs::OpenOptions", "some_crate::do_thing", "std::fs::File", "f::seek"] {
assert!(fs_kind(p).is_empty(), "{p} must not claim a direction it did not reveal");
}
}
#[test]
fn openoptions_open_claims_no_direction_but_file_open_still_reads() {
for p in ["std::fs::OpenOptions::open", "fs_err::OpenOptions::open",
"tokio::fs::OpenOptions::open"] {
assert!(fs_kind(p).is_empty(),
"{p}'s direction was set by the builder chain, which this function cannot see");
}
assert_eq!(fs_kind("std::fs::File::open"), &["read"], "`File::open` is unambiguously a read");
}
}
#[cfg(test)]
mod masks_locator_tests {
use super::*;
#[test]
fn every_no_locator_denylist_is_a_subset_of_its_charging_table() {
for n in LIBC_FS_NO_PATH {
assert!(LIBC_FS.contains(n), "LIBC_FS_NO_PATH names `{n}`, which LIBC_FS does not charge");
}
for n in LIBC_EXEC_NO_PROGRAM {
assert!(LIBC_EXEC.contains(n), "LIBC_EXEC_NO_PROGRAM names `{n}`, absent from LIBC_EXEC");
}
for n in LIBC_NET_NO_DESTINATION {
assert!(LIBC_NET.contains(n), "LIBC_NET_NO_DESTINATION names `{n}`, absent from LIBC_NET");
}
for n in PG_DB_VERBS_NO_SQL {
assert!(PG_DB_VERBS.contains(n), "PG_DB_VERBS_NO_SQL names `{n}`, absent from PG_DB_VERBS");
}
}
#[test]
fn every_charged_libc_leaf_off_the_denylist_masks() {
for (eff, table, deny) in [
("Fs", LIBC_FS, LIBC_FS_NO_PATH),
("Exec", LIBC_EXEC, LIBC_EXEC_NO_PROGRAM),
("Net", LIBC_NET, LIBC_NET_NO_DESTINATION),
] {
for leaf in table.iter().filter(|l| !deny.contains(l)) {
for cr in ["libc", "nix"] {
let path = format!("{cr}::{leaf}");
assert_eq!(classify(cr, &path), Some(eff), "{path} must still be charged {eff}");
assert!(masks_locator(eff, cr, &path, leaf, false), "{path} names a locator — must mask");
}
}
for leaf in deny.iter() {
let path = format!("libc::{leaf}");
assert!(!masks_locator(eff, "libc", &path, leaf, false) || is_net_establishing(leaf),
"{path} is on the no-locator denylist — must not mask via the table");
}
}
for (eff, leaf) in [("Fs", "unlink"), ("Fs", "unlinkat"), ("Fs", "utimensat"), ("Exec", "system"),
("Exec", "popen"), ("Exec", "execvp"), ("Exec", "posix_spawn"), ("Net", "getaddrinfo"),
("Net", "sendto")] {
assert!(masks_locator(eff, "libc", &format!("libc::{leaf}"), leaf, false), "libc::{leaf}");
}
assert!(!masks_locator("Fs", "mycrate", "mycrate::unlink", "unlink", false));
assert!(!masks_locator("Net", "rustix", "rustix::net::sendmsg", "sendmsg", false));
assert!(masks_locator("Net", "libc", "libc::sendmsg", "sendmsg", false));
}
#[test]
fn pg_verbs_take_sql_except_the_named_three() {
for v in PG_DB_VERBS.iter().filter(|v| !PG_DB_VERBS_NO_SQL.contains(v)) {
let path = format!("deadpool_postgres::Client{v}");
let leaf = &v[2..];
assert!(masks_locator("Db", "deadpool_postgres", &path, leaf, true), "{path} takes SQL — must mask");
}
assert!(masks_locator("Db", "tokio_postgres", "tokio_postgres::Client::prepare_typed_cached",
"prepare_typed_cached", true));
assert!(!masks_locator("Db", "tokio_postgres", "tokio_postgres::Client::transaction", "transaction", true));
assert!(masks_locator("Db", "sqlx_core", "sqlx_core::executor::Executor::prepare_with", "prepare_with", true));
assert!(!masks_locator("Db", "sqlx_core", "sqlx_core::query::Query::fetch_all", "fetch_all", true),
"a Query terminal takes an EXECUTOR at arg 0 — masking it would swallow every literal query");
}
#[test]
fn coverage_gate_refresh_2026_10_08_rules() {
for p in ["rusqlite::Transaction::commit", "rusqlite::transaction::Transaction::new",
"rusqlite::Savepoint::rollback", "rusqlite::Connection::pragma_update",
"rusqlite::Connection::unchecked_transaction", "rusqlite::Connection::savepoint_with_name"] {
assert_eq!(classify("rusqlite", p), Some("Db"), "{p}");
}
for p in ["rusqlite::Transaction::drop_behavior", "rusqlite::Savepoint::set_drop_behavior"] {
assert_eq!(classify("rusqlite", p), None, "{p}");
}
for p in ["redis::Connection::send_packed_command", "redis::connection::Connection::recv_response",
"redis::PubSub::get_message"] {
assert_eq!(classify("redis", p), Some("Net"), "{p}");
}
assert_eq!(classify("redis", "redis::aio::MultiplexedConnection::recv_response"), None);
assert_eq!(classify("redis", "redis::Connection::set_write_timeout"), None);
for p in ["lettre::SmtpConnection::command", "lettre::transport::smtp::client::SmtpConnection::connect",
"lettre::AsyncSmtpConnection::read_response",
"lettre::transport::smtp::client::AsyncNetworkStream::connect_tokio1",
"lettre::Tokio1Executor::connect"] {
assert_eq!(classify("lettre", p), Some("Net"), "{p}");
}
for p in ["lettre::SmtpConnection::server_info", "lettre::NetworkStream::peer_addr",
"lettre::AsyncSmtpConnection::is_encrypted"] {
assert_eq!(classify("lettre", p), None, "{p}");
}
assert_eq!(classify("rustls", "rustls::KeyLogFile::log"), Some("Fs"));
assert_eq!(classify("rustls", "rustls::NoKeyLog::log"), None);
}
#[test]
fn r1528_b11_rows_classify_with_pure_neighbours() {
let eff = |c: &str, p: &str| classify(c, p);
for m in ["timestamp", "timestamp_seconds", "timestamp_millis", "timestamp_micros", "timestamp_nanos"] {
assert_eq!(eff("env_logger", &format!("env_logger::fmt::humantime::Formatter::{m}")), Some("Clock"));
assert_eq!(eff("env_logger", &format!("env_logger::fmt::Formatter::{m}")), Some("Clock"));
}
assert_eq!(eff("env_logger", "env_logger::fmt::ConfigurableFormat::format"), Some("Clock"));
assert_eq!(eff("env_logger", "env_logger::fmt::ConfigurableFormat::timestamp"), None); assert_eq!(eff("env_logger", "env_logger::fmt::Formatter::style"), None);
for m in ["single_node", "static_node_list", "sniffing_node_list", "cloud"] {
let p = format!("elasticsearch::http::transport::Transport::{m}");
assert_eq!(eff("elasticsearch", &p), Some("Env"), "{p}");
assert_eq!(also_effects("elasticsearch", &p), vec!["Fs"], "{p} must carry the trust-store read");
}
assert_eq!(eff("elasticsearch", "elasticsearch::http::transport::TransportBuilder::build"), Some("Env"));
assert_eq!(also_effects("elasticsearch", "elasticsearch::http::transport::TransportBuilder::build"), vec!["Fs"]);
assert_eq!(eff("elasticsearch", "elasticsearch::http::transport::MultiNodeConnectionPool::reseed"), Some("Clock"));
assert_eq!(eff("elasticsearch", "elasticsearch::http::transport::TransportBuilder::auth"), None);
assert!(also_effects("elasticsearch", "elasticsearch::http::transport::TransportBuilder::auth").is_empty());
assert!(also_effects("elasticsearch", "elasticsearch::http::transport::Transport::send").is_empty());
assert!(also_effects("reqwest", "reqwest::ClientBuilder::build").is_empty(), "reqwest is not claimed here");
for m in ["execute_raw", "execute_typed", "query_typed_raw", "query_typed_one", "query_typed_opt", "query_scalar",
"query_one_scalar", "query_opt_scalar", "bind", "bind_raw", "query_portal", "query_portal_raw",
"commit", "rollback", "savepoint"] {
for ty in ["Client", "Transaction"] {
assert_eq!(eff("tokio_postgres", &format!("tokio_postgres::{ty}::{m}")), Some("Db"), "{ty}::{m}");
assert_eq!(eff("deadpool_postgres", &format!("deadpool_postgres::{ty}::{m}")), Some("Db"), "dp {ty}::{m}");
}
}
for m in ["simple_query_raw", "check_connection"] {
assert_eq!(eff("tokio_postgres", &format!("tokio_postgres::client::Client::{m}")), Some("Db"));
}
assert_eq!(eff("deadpool_postgres", "deadpool_postgres::GenericClient::execute_raw"), Some("Db"));
assert_eq!(eff("tokio_postgres", "tokio_postgres::to_statement::private::ToStatementType::into_statement"), Some("Db"));
for p in ["tokio_postgres::Client::is_closed", "tokio_postgres::Client::cancel_token", "tokio_postgres::Client::clear_type_cache",
"tokio_postgres::Transaction::client", "tokio_postgres::Connection::poll_message"] {
assert_eq!(eff("tokio_postgres", p), None, "{p} sends nothing (poll_message is filed R1598:conditional)");
}
assert_eq!(eff("deadpool_postgres", "deadpool_postgres::config::Config::get_pg_config"), None); for m in ["associate", "try_associate"] {
assert_eq!(eff("grep_cli", &format!("grep_cli::decompress::DecompressionMatcherBuilder::{m}")), Some("Env"));
}
assert_eq!(eff("grep_cli", "grep_cli::decompress::DecompressionMatcherBuilder::build"), None, "EXECUTED 0 spawns");
assert_eq!(eff("grep_cli", "grep_cli::decompress::DecompressionReaderBuilder::build"), Some("Exec"));
assert_eq!(eff("grep_cli", "grep_cli::process::CommandReaderBuilder::build"), Some("Exec"));
assert_eq!(eff("grep_cli", "grep_cli::decompress::DecompressionMatcherBuilder::new"), None);
for m in ["get_elapsed_time", "reset", "default"] {
assert_eq!(eff("backoff", &format!("backoff::exponential::ExponentialBackoff::{m}")), Some("Clock"), "{m}");
}
assert_eq!(eff("backoff", "backoff::exponential::ExponentialBackoff::next_backoff"), Some("Rand"));
assert_eq!(eff("backoff", "backoff::exponential::ExponentialBackoffBuilder::build"), Some("Clock"));
assert_eq!(eff("backoff", "backoff::exponential::ExponentialBackoffBuilder::new"), None);
assert_eq!(eff("backoff", "backoff::exponential::ExponentialBackoffBuilder::with_max_elapsed_time"), None);
assert_eq!(eff("backoff", "backoff::clock::SystemClock::now"), Some("Clock"));
for p in ["rustls::client::client_conn::connection::ClientConnection::new", "rustls::ClientConnection::new_with_alpn",
"rustls::client::client_conn::UnbufferedClientConnection::new", "rustls::client::UnbufferedClientConnection::new_with_alpn",
"rustls::quic::connection::ClientConnection::new", "rustls::quic::connection::ClientConnection::new_with_alpn"] {
assert_eq!(eff("rustls", p), Some("Rand"), "{p}");
}
assert_eq!(eff("rustls", "rustls::ServerConnection::new"), None);
assert_eq!(eff("rustls", "rustls::ClientConfig::builder"), None);
assert_eq!(eff("rustls", "rustls::KeyLogFile::new"), Some("Fs"));
for p in ["etcetera::base_strategy::apple::Apple::new", "etcetera::base_strategy::xdg::Xdg::new", "etcetera::base_strategy::windows::Windows::new",
"etcetera::app_strategy::unix::Unix::new", "etcetera::app_strategy::xdg::Xdg::new", "etcetera::app_strategy::apple::Apple::new"] {
assert_eq!(eff("etcetera", p), Some("Env"), "{p}");
}
assert_eq!(eff("etcetera", "etcetera::app_strategy::AppStrategyArgs::new"), None);
assert_eq!(eff("time", "time::instant::Instant::elapsed"), Some("Clock"));
assert_eq!(eff("time", "time::signed_duration::SignedDuration::time_fn"), Some("Clock"));
assert_eq!(eff("time", "time::Duration::time_fn"), Some("Clock"));
assert_eq!(eff("time", "time::utc_offset::UtcOffset::current_local_offset"), Some("Clock"));
assert_eq!(eff("time", "time::Instant::checked_add"), None);
assert_eq!(eff("time", "time::UtcOffset::from_hms"), None);
for p in ["console::is_dumb", "console::term::is_dumb", "console::set_colors_enabled", "console::utils::set_colors_enabled_stderr",
"console::set_true_colors_enabled", "console::true_colors_enabled_stderr", "console::colors_enabled"] {
assert_eq!(eff("console", p), Some("Env"), "{p}");
}
assert_eq!(eff("console", "console::style"), None);
assert_eq!(eff("console", "console::measure_text_width"), None);
assert_eq!(eff("rand", "rand::make_rng"), Some("Rand"));
assert_eq!(eff("rand", "rand::SeedableRng::seed_from_u64"), None);
assert_eq!(eff("rand", "rand::rng::u8::fill_slice"), None); for m in ["new", "from_argv", "new_default_prog"] {
assert_eq!(eff("portable_pty", &format!("portable_pty::cmdbuilder::CommandBuilder::{m}")), Some("Env"), "{m}");
}
assert_eq!(eff("portable_pty", "portable_pty::CommandBuilder::spawn_command"), Some("Exec"));
assert_eq!(eff("portable_pty", "portable_pty::CommandBuilder::arg"), None);
assert_eq!(eff("portable_pty", "portable_pty::CommandBuilder::get_shell"), Some("Fs"));
assert_eq!(eff("notify", "notify::poll::PollWatcher::with_initial_scan"), Some("Clock"));
assert_eq!(eff("notify", "notify::poll::PollWatcher::poll"), None);
assert_eq!(eff("native_tls_crate", "native_tls_crate::TlsConnectorBuilder::build"), Some("Fs"));
assert_eq!(eff("native_tls_crate", "native_tls_crate::TlsConnectorBuilder::min_protocol_version"), None);
assert_eq!(eff("duct", "duct::Handle::wait_timeout"), Some("Clock"));
assert_eq!(eff("duct", "duct::Handle::wait_deadline"), Some("Clock"));
assert_eq!(eff("duct", "duct::Handle::try_wait"), None);
assert_eq!(eff("duct", "duct::Handle::wait"), None);
assert_eq!(eff("dotenvy", "dotenvy::iter::Iter::load_override"), Some("Env"));
assert_eq!(eff("dotenvy", "dotenvy::iter::Iter::load"), Some("Env"));
}
#[test]
fn r1528_b10_rows_classify_with_pure_neighbours() {
for p in ["tempfile::SpooledTempFile::into_file", "tempfile::spooled::SpooledTempFile::roll"] {
assert_eq!(classify("tempfile", p), Some("Fs"), "{p}");
}
assert_eq!(classify("tempfile", "tempfile::env::temp_dir"), Some("Env"));
assert_eq!(classify("tempfile", "tempfile::temp_dir"), Some("Env"));
for p in ["tempfile::SpooledTempFile::new", "tempfile::SpooledTempFile::flush", "tempfile::TempDir::path",
"tempfile::env::override_temp_dir", "tempfile::TempPath::from_path", "tempfile::TempPath::try_from_path"] {
assert_eq!(classify("tempfile", p), None, "{p}");
}
assert_eq!(classify("tungstenite", "tungstenite::handshake::client::generate_key"), Some("Rand"));
for p in ["tungstenite::http::Uri::into_client_request", "tungstenite::client::ClientRequestBuilder::into_client_request"] {
assert_eq!(classify("tungstenite", p), Some("Rand"), "{p}");
}
assert_eq!(classify("tungstenite", "tungstenite::http::Request::into_client_request"), None);
assert_eq!(classify("tungstenite", "tungstenite::client::ClientRequestBuilder::new"), None);
assert_eq!(classify("tungstenite", "tungstenite::client::ClientRequestBuilder::with_header"), None);
for p in ["tungstenite::stream::MaybeTlsStream::set_nodelay", "tungstenite::stream::NoDelay::set_nodelay",
"tungstenite::WebSocket::write_pending", "tungstenite::protocol::WebSocket::write_pending"] {
assert_eq!(classify("tungstenite", p), Some("Net"), "{p}");
}
assert_eq!(classify("tungstenite", "tungstenite::Message::text"), None);
for p in ["crossterm::style::Colored::ansi_color_disabled", "crossterm::style::Colored::ansi_color_disabled_memoized",
"crossterm::Colored::set_ansi_color_disabled", "crossterm::style::force_color_output",
"crossterm::style::available_color_count"] {
assert_eq!(classify("crossterm", p), Some("Env"), "{p}");
}
for p in ["crossterm::cursor::position", "crossterm::cursor::sys::unix::position", "crossterm::event::EventStream::new",
"crossterm::event::EventStream::next"] {
assert_eq!(classify("crossterm", p), Some("Ipc"), "{p}");
}
for p in ["crossterm::style::Print::write_ansi", "crossterm::terminal::SetTitle::write_ansi",
"crossterm::terminal::SetTitle::execute_winapi", "crossterm::ansi_support::supports_ansi",
"crossterm::style::Colored::ForegroundColor", "crossterm::style::Print", "crossterm::style::Color::Red"] {
assert_eq!(classify("crossterm", p), None, "{p}");
}
for p in ["reqwest::ClientBuilder::build", "reqwest::blocking::ClientBuilder::build", "reqwest::Client::build",
"reqwest::blocking::Client::build", "reqwest::Client::new", "reqwest::NoProxy::from_env"] {
assert_eq!(classify("reqwest", p), Some("Env"), "{p}");
}
for p in ["reqwest::multipart::Form::file", "reqwest::blocking::multipart::Form::file"] {
assert_eq!(classify("reqwest", p), Some("Fs"), "{p}");
}
assert_eq!(classify("reqwest", "reqwest::blocking::Response::copy_to"), Some("Net"));
for p in ["reqwest::ClientBuilder::new", "reqwest::Client::builder", "reqwest::multipart::Form::new",
"reqwest::multipart::Form::text", "reqwest::NoProxy::from_string",
"reqwest::async_impl::h3_client::pool::PoolClient::send_request"] {
assert_eq!(classify("reqwest", p), None, "{p}");
}
for p in ["mysql::Conn::reset", "mysql::Conn::change_user", "mysql::PooledConn::change_user", "mysql::Pool::new",
"mysql::Pool::try_get_conn", "mysql::Pool::start_transaction", "mysql::PooledConn::get_binlog_stream",
"mysql::Conn::start_transaction", "mysql::PooledConn::start_transaction", "mysql::Conn::get_binlog_stream",
"mysql::conn::pool::Pool::new"] {
assert_eq!(classify("mysql", p), Some("Db"), "{p}");
}
for p in ["mysql::PooledConn::unwrap", "mysql::Pool::opts", "mysql::PoolConstraints::new", "mysql::Opts::from_url",
"mysql::TxOpts::default", "mysql::BinlogRequest::new"] {
assert_eq!(classify("mysql", p), None, "{p}");
}
for p in ["diesel::sqlite::SqliteConnection::batch_execute", "diesel::SqliteConnection::immediate_transaction",
"diesel::sqlite::SqliteConnection::exclusive_transaction", "diesel::connection::AnsiTransactionManager::begin_transaction_sql",
"diesel::sqlite::SqliteConnection::serialize_database_to_buffer",
"diesel::sqlite::SqliteConnection::deserialize_readonly_database_from_buffer", "diesel::pg::TransactionBuilder::run",
"diesel::pg::PgConnection::run", "diesel::pg::PgConnection::transaction", "diesel::sqlite::SqliteConnection::transaction"] {
assert_eq!(classify("diesel", p), Some("Db"), "{p}");
}
for p in ["diesel::pg::PgConnection::build_transaction", "diesel::connection::AnsiTransactionManager::new",
"diesel::sqlite::SqliteConnection::set_instrumentation"] {
assert_eq!(classify("diesel", p), None, "{p}");
}
}
#[test]
fn r1597_lettre_send_charges_the_transports_own_effect() {
for p in ["lettre::FileTransport::send", "lettre::FileTransport::send_raw", "lettre::AsyncFileTransport::send",
"lettre::AsyncFileTransport::send_raw", "lettre::transport::file::FileTransport::send",
"lettre::transport::file::AsyncFileTransport::send"] {
assert_eq!(classify("lettre", p), Some("Fs"), "{p}");
}
for p in ["lettre::SendmailTransport::send", "lettre::AsyncSendmailTransport::send",
"lettre::transport::sendmail::SendmailTransport::send_raw"] {
assert_eq!(classify("lettre", p), Some("Exec"), "{p}");
}
for p in ["lettre::SmtpTransport::send", "lettre::AsyncSmtpTransport::send", "lettre::transport::smtp::SmtpTransport::send_raw",
"lettre::Transport::send", "lettre::AsyncTransport::send"] {
assert_eq!(classify("lettre", p), Some("Net"), "{p}");
}
assert_eq!(classify("lettre", "lettre::FileTransport::read"), Some("Fs"));
}
#[test]
fn r1528_verified_rows_classify() {
assert_eq!(classify("tempfile", "tempfile::NamedTempFile::into_file"), Some("Fs"));
for v in ["with_prefix", "with_prefix_in", "with_suffix", "with_suffix_in"] {
assert_eq!(classify("tempfile", &format!("tempfile::TempDir::{v}")), Some("Fs"), "{v}");
}
assert_eq!(classify("tempfile", "tempfile::TempDir::into_path"), None, "flag flip only (R1528 FALSE)");
assert_eq!(classify("tempfile", "tempfile::TempDir::keep"), None, "flag flip only, carved out of ::keep");
assert_eq!(classify("tempfile", "tempfile::NamedTempFile::keep"), Some("Fs"), "NamedTempFile::keep is not carved out");
assert_eq!(classify("tempfile", "tempfile::TempPath::keep"), Some("Fs"), "TempPath::keep is not carved out");
assert_eq!(classify("tempfile", "tempfile::NamedTempFile::path"), None);
assert_eq!(classify("tempfile", "tempfile::SpooledTempFile::into_file"), Some("Fs"));
assert_eq!(classify("chrono", "chrono::Utc::today"), Some("Clock"));
assert_eq!(classify("chrono", "chrono::Local::today"), Some("Clock"));
assert_eq!(classify("chrono", "chrono::offset::utc::Utc::today"), Some("Clock"));
assert_eq!(classify("chrono", "chrono::NaiveDate::today"), None);
assert_eq!(classify("chrono", "chrono::DateTime::parse_from_rfc2822"), None, "oracle fabrication, R1420(a)");
assert_eq!(classify("tokio_postgres", "tokio_postgres::Client::cancel_query"), Some("Net"));
assert_eq!(classify("tokio_postgres", "tokio_postgres::Transaction::cancel_query"), Some("Net"));
assert_eq!(classify("tokio_postgres", "tokio_postgres::Client::is_closed"), None);
assert_eq!(classify("postgres", "postgres::Client::is_valid"), Some("Db"));
assert_eq!(classify("tokio_postgres", "tokio_postgres::Client::is_valid"), None);
for p in ["rdkafka::Client::fetch_group_list", "rdkafka::BaseConsumer::fetch_group_list",
"rdkafka::StreamConsumer::fetch_group_list", "rdkafka::consumer::Consumer::fetch_group_list"] {
assert_eq!(classify("rdkafka", p), Some("Net"), "{p}");
}
assert_eq!(classify("tracing_subscriber", "tracing_subscriber::fmt::Layer::new"), Some("Env"));
assert_eq!(classify("tracing_subscriber", "tracing_subscriber::fmt::fmt_layer::Layer::new"), Some("Env"));
assert_eq!(classify("tracing_subscriber", "tracing_subscriber::fmt::Layer::with_writer"), None);
}
#[test]
fn r1528_clock_env_rows_classify() {
for p in ["Local::offset_from_utc_datetime", "offset::local::Local::offset_from_local_datetime",
"Local::offset_from_utc_date", "offset::Local::offset_from_local_date"] {
assert_eq!(classify("chrono", &format!("chrono::{p}")), Some("Clock"), "{p}");
}
for p in ["TimeZone::offset_from_utc_datetime", "FixedOffset::offset_from_utc_datetime",
"Utc::offset_from_utc_datetime", "DateTime::with_timezone", "Date::with_timezone",
"DateTime::checked_add_months", "DateTime::checked_sub_months", "DateTime::duration_round",
"DateTime::duration_round_up", "DateTime::duration_trunc", "NaiveDateTime::and_local_timezone",
"Parsed::to_datetime_with_timezone", "DateTime::fixed_offset", "DateTime::years_since",
"DateTime::parse_from_rfc3339", "DateTime::parse_from_rfc2822", "DateTime::parse_from_str",
"DateTime::parse_and_remainder", "Parsed::to_datetime", "NaiveDate::today"] {
assert_eq!(classify("chrono", &format!("chrono::{p}")), None, "{p}");
}
assert_eq!(classify("mycrate", "mycrate::Local::offset_from_utc_datetime"), None);
for m in ["from_utc_datetime", "from_local_datetime", "timestamp_opt", "with_ymd_and_hms", "ymd_opt", "datetime_from_str"] {
assert_eq!(classify("chrono", &format!("chrono::Local::{m}")), Some("Clock"), "{m}");
assert_eq!(classify("chrono", &format!("chrono::offset::local::Local::{m}")), Some("Clock"), "{m}");
assert_eq!(classify("chrono", &format!("chrono::Utc::{m}")), None, "{m}");
assert_eq!(classify("chrono", &format!("chrono::FixedOffset::{m}")), None, "{m}");
}
for p in ["SystemTime::format_time", "fmt::time::SystemTime::format_time", "UtcTime::format_time",
"fmt::time::time_crate::LocalTime::format_time", "OffsetTime::format_time",
"ChronoLocal::format_time", "fmt::time::chrono_crate::ChronoUtc::format_time", "Uptime::default",
"fmt::time::Uptime::default", "uptime", "fmt::time::uptime"] {
assert_eq!(classify("tracing_subscriber", &format!("tracing_subscriber::{p}")), Some("Clock"), "{p}");
}
for p in ["fmt::layer", "fmt::fmt", "fmt", "Layer::default", "fmt::Layer::default", "fmt::fmt_layer::Layer::default",
"fmt::Subscriber::builder", "FmtSubscriber::builder", "fmt::Subscriber::default",
"fmt::SubscriberBuilder::default"] {
let want = if p == "Layer::default" { None } else { Some("Env") };
assert_eq!(classify("tracing_subscriber", &format!("tracing_subscriber::{p}")), want, "{p}");
}
for p in ["Layer::on_event", "Layer::on_new_span", "Layer::on_enter", "Layer::on_exit", "Layer::on_close",
"Layered::on_event", "Filtered::on_event", "Option::on_event", "Context::event",
"Format::format_event", "fmt::format::json::Format::format_event", "Uptime::format_time",
"Uptime::from", "time", "fmt::time::time", "SubscriberBuilder::with_target",
"fmt::SubscriberBuilder::with_writer"] {
assert_eq!(classify("tracing_subscriber", &format!("tracing_subscriber::{p}")), None, "{p}");
}
for p in ["Date::in_tz", "civil::DateTime::in_tz", "Timestamp::in_tz", "zoned::Zoned::in_tz",
"TimeZoneDatabase::from_env", "tz::db::TimeZoneDatabase::from_dir",
"TimeZoneDatabase::from_concatenated_path", "DateTimeParser::parse_zoned",
"fmt::temporal::DateTimeParser::parse_time_zone", "BrokenDownTime::to_zoned",
"fmt::strtime::BrokenDownTime::to_zoned", "Pieces::to_time_zone",
"fmt::temporal::pieces::TimeZoneAnnotation::to_time_zone", "db", "tz::db", "tz::db::db"] {
assert_eq!(classify("jiff", &format!("jiff::{p}")), Some("Fs"), "{p}");
}
for p in ["BrokenDownTime::to_zoned_with", "Pieces::to_time_zone_with", "TimeZoneAnnotation::to_time_zone_with",
"TimeZoneDatabase::bundled", "DateTimeParser::parse_zoned_with", "Date::to_zoned", "TimeZone::fixed",
"Span::checked_add", "Timestamp::from_second"] {
assert_eq!(classify("jiff", &format!("jiff::{p}")), None, "{p}");
}
assert_eq!(classify("mycrate", "mycrate::Date::in_tz"), None);
}
#[test]
fn r1528_sea_orm_rows_classify() {
let db = |ty: &str, ms: &[&str]| -> Vec<(String, &'static str)> {
ms.iter().map(|m| (format!("sea_orm::{ty}::{m}"), "Db")).collect()
};
let mut want: Vec<(String, &'static str)> = Vec::new();
want.extend(db("DatabaseConnection", &["begin_with_options", "transaction_async", "transaction_with_config_async",
"execute_raw", "query_one_raw", "query_all_raw", "stream_raw"]));
want.extend(db("DatabaseExecutor", &["begin", "begin_with_config", "begin_with_options", "execute_raw",
"query_one_raw", "query_all_raw", "transaction", "transaction_async", "transaction_with_config",
"transaction_with_config_async"]));
want.extend(db("DatabaseTransaction", &["begin", "begin_with_config", "begin_with_options", "execute_raw",
"query_one_raw", "query_all_raw", "stream_raw", "transaction", "transaction_async",
"transaction_with_config", "transaction_with_config_async"]));
want.extend(db("RestrictedConnection", &["begin", "begin_with_config", "begin_with_options", "transaction",
"transaction_async", "transaction_with_config", "transaction_with_config_async"]));
want.extend(db("RestrictedTransaction", &["begin", "begin_with_config", "begin_with_options", "commit",
"rollback", "transaction", "transaction_async", "transaction_with_config",
"transaction_with_config_async"]));
for m in ["load", "add_tables", "add_crud_permissions", "add_roles", "add_role_permissions",
"remove_role_permissions", "add_user_override", "add_role_hierarchy", "assign_user_role"] {
want.push((format!("sea_orm::rbac::RbacContext::{m}"), "Db"));
want.push((format!("sea_orm::rbac::context::RbacContext::{m}"), "Db"));
}
want.push(("sea_orm::rbac::schema::create_tables".into(), "Db"));
for m in ["apply", "sync"] {
want.push((format!("sea_orm::SchemaBuilder::{m}"), "Db"));
want.push((format!("sea_orm::schema::builder::SchemaBuilder::{m}"), "Db"));
}
for ty in ["Select", "SelectTwo", "SelectTwoRequired", "Selector", "SelectorRaw"] {
want.push((format!("sea_orm::{ty}::require_one"), "Db"));
}
for ty in ["Select", "SelectTwo", "SelectTwoRequired", "SelectThree", "SelectFour"] {
want.push((format!("sea_orm::{ty}::stream_partial_model"), "Db"));
}
for p in ["sea_orm::DatabaseConnection::get_schema_registry", "sea_orm::DatabaseExecutor::get_schema_registry",
"sea_orm::EntityRegistry::build_schema", "sea_orm::entity::registry::EntityRegistry::build_schema"] {
want.push((p.into(), "Log"));
}
for (p, eff) in &want {
assert_eq!(classify("sea_orm", p), Some(*eff), "{p}");
}
for p in [
"RestrictedConnection::execute_raw", "RestrictedConnection::query_one_raw",
"RestrictedConnection::query_all_raw", "RestrictedTransaction::execute_raw",
"rbac::RbacContext::get_role", "SchemaBuilder::register", "Schema::new", "Schema::builder",
"DatabaseConnection::get_database_backend", "DatabaseConnection::get_schema_builder",
"DatabaseExecutor::is_transaction", "DatabaseExecutor::get_schema_builder",
"RestrictedConnection::user_id", "RestrictedConnection::user_can", "RestrictedTransaction::user_can_run",
"MockDatabaseConnection::begin_with_options", "MockDatabaseConnection::transaction_async",
"ProxyDatabaseConnection::execute_raw", "ProxyDatabaseConnection::query_all_raw",
"Vec::load_many", "Vec::load_one", "Vec::load_self", "Vec::load_self_many", "Vec::load_self_via",
"Vec::load_self_via_rev", "RusqliteSharedConnection::acquire", "RusqliteSharedConnection::begin",
"RusqliteSharedConnection::close", "RusqliteSharedConnection::close_by_ref",
"RusqliteSharedConnection::ping", "RusqliteSharedConnection::transaction",
"driver::rusqlite::RusqliteSharedConnection::ping",
] {
assert_eq!(classify("sea_orm", &format!("sea_orm::{p}")), None, "{p}");
}
assert_eq!(classify("mycrate", "mycrate::DatabaseTransaction::execute_raw"), None);
assert_eq!(classify("mycrate", "mycrate::rbac::RbacContext::load"), None);
}
#[test]
fn r1528_ureq3_rows_classify() {
for (p, eff) in [
("Agent::run", "Net"), ("agent::Agent::run", "Net"), ("WithAgent::run", "Net"),
("request_ext::WithAgent::run", "Net"), ("ConfigBuilder::run", "Net"),
("RequestBuilder::send_empty", "Net"), ("request::RequestBuilder::send_empty", "Net"),
("MiddlewareNext::handle", "Net"), ("middleware::MiddlewareNext::handle", "Net"),
("run", "Net"),
("DefaultResolver::resolve", "Net"), ("unversioned::resolver::DefaultResolver::resolve", "Net"),
("TcpConnector::connect", "Net"), ("unversioned::transport::TcpConnector::connect", "Net"),
("DefaultConnector::connect", "Net"), ("ConnectProxyConnector::connect", "Net"),
("SocksConnector::connect", "Net"), ("NativeTlsConnector::connect", "Net"),
("tls::native_tls::NativeTlsConnector::connect", "Net"),
("TcpTransport::transmit_output", "Net"), ("TcpTransport::await_input", "Net"),
("unversioned::transport::tcp::TcpTransport::is_open", "Net"),
("Config::builder", "Env"), ("config::Config::builder", "Env"), ("Config::default", "Env"),
("Agent::config_builder", "Env"), ("Agent::new_with_defaults", "Env"), ("Proxy::try_from_env", "Env"),
("proxy::Proxy::try_from_env", "Env"),
("Form::file", "Fs"), ("Part::file", "Fs"), ("unversioned::multipart::Part::file", "Fs"),
("File::as_body", "Fs"), ("Form::new", "Rand"), ("multipart::Form::new", "Rand"),
("Instant::now", "Clock"), ("unversioned::transport::time::Instant::now", "Clock"),
] {
assert_eq!(classify("ureq", &format!("ureq::{p}")), Some(eff), "{p}");
}
for p in ["get", "post", "put", "delete", "head", "patch", "options", "trace", "connect",
"ConfigBuilder::timeout_global", "ConfigBuilder::user_agent", "RequestScope::config",
"Either::await_input", "Box::transmit_output", "ChainedConnector::connect",
"Agent::new_with_config", "Agent::with_parts", "Agent::config", "Config::https_only",
"Part::text", "Part::file_name", "Proxy::new", "Instant::duration_since"] {
assert_eq!(classify("ureq", &format!("ureq::{p}")), None, "{p}");
}
assert_eq!(classify("mycrate", "mycrate::Agent::run"), None);
assert_eq!(classify("reqwest", "reqwest::Config::builder"), None);
}
#[test]
fn r1528_async_nats_rows_classify() {
for (p, eff) in [
("jetstream::Context::create_stream", "Net"), ("jetstream::context::Context::get_stream", "Net"),
("jetstream::Context::get_or_create_stream", "Net"), ("jetstream::Context::delete_stream", "Net"),
("jetstream::Context::update_stream", "Net"), ("jetstream::Context::create_or_update_stream", "Net"),
("jetstream::Context::query_account", "Net"), ("jetstream::Context::send_publish", "Net"),
("jetstream::Context::send_request", "Net"), ("jetstream::Context::stream_by_subject", "Net"),
("jetstream::Context::create_key_value", "Net"), ("jetstream::Context::get_key_value", "Net"),
("jetstream::Context::update_key_value", "Net"), ("jetstream::Context::delete_key_value", "Net"),
("jetstream::Context::create_or_update_key_value", "Net"),
("jetstream::Context::create_object_store", "Net"), ("jetstream::Context::get_object_store", "Net"),
("jetstream::Context::delete_object_store", "Net"),
("jetstream::Context::create_consumer_on_stream", "Net"),
("jetstream::Context::create_consumer_strict_on_stream", "Net"),
("jetstream::Context::update_consumer_on_stream", "Net"),
("jetstream::Context::get_consumer_from_stream", "Net"),
("jetstream::Context::delete_consumer_from_stream", "Net"),
("jetstream::stream::Stream::info", "Net"), ("jetstream::stream::Stream::get_info", "Net"),
("jetstream::stream::Stream::info_with_subjects", "Net"),
("jetstream::stream::Stream::consumer_info", "Net"), ("jetstream::stream::Stream::create_consumer", "Net"),
("jetstream::stream::Stream::create_consumer_strict", "Net"),
("jetstream::stream::Stream::update_consumer", "Net"), ("jetstream::stream::Stream::get_consumer", "Net"),
("jetstream::stream::Stream::get_or_create_consumer", "Net"),
("jetstream::stream::Stream::delete_consumer", "Net"), ("jetstream::stream::Stream::pause_consumer", "Net"),
("jetstream::stream::Stream::resume_consumer", "Net"), ("jetstream::stream::Stream::reset_consumer", "Net"),
("jetstream::stream::Stream::delete_message", "Net"), ("jetstream::stream::Stream::purge_subject", "Net"),
("jetstream::stream::Stream::direct_get", "Net"),
("jetstream::stream::Stream::direct_get_first_for_subject", "Net"),
("jetstream::stream::Stream::direct_get_last_for_subject", "Net"),
("jetstream::stream::Stream::direct_get_next_for_subject", "Net"),
("jetstream::stream::Stream::get_raw_message", "Net"),
("jetstream::stream::Stream::get_first_raw_message_by_subject", "Net"),
("jetstream::stream::Stream::get_next_raw_message_by_subject", "Net"),
("jetstream::stream::Stream::get_last_raw_message_by_subject", "Net"),
("jetstream::stream::Stream::send", "Net"), ("jetstream::stream::Stream::fetch", "Net"),
("jetstream::stream::DirectGetBuilder::send", "Net"), ("jetstream::stream::RawMessageBuilder::send", "Net"),
("jetstream::stream::StreamInfoBuilder::fetch", "Net"),
("jetstream::kv::Store::create", "Net"), ("jetstream::kv::Store::create_with_ttl", "Net"),
("jetstream::kv::Store::put", "Net"), ("jetstream::kv::Store::get", "Net"),
("jetstream::kv::Store::entry", "Net"), ("jetstream::kv::Store::entry_for_revision", "Net"),
("jetstream::kv::Store::update", "Net"), ("jetstream::kv::Store::delete", "Net"),
("jetstream::kv::Store::delete_expect_revision", "Net"), ("jetstream::kv::Store::purge", "Net"),
("jetstream::kv::Store::purge_with_ttl", "Net"), ("jetstream::kv::Store::purge_expect_revision", "Net"),
("jetstream::kv::Store::purge_expect_revision_with_ttl", "Net"),
("jetstream::kv::Store::history", "Net"), ("jetstream::kv::Store::keys", "Net"),
("jetstream::kv::Store::watch", "Net"), ("jetstream::kv::Store::watch_many", "Net"),
("jetstream::kv::Store::watch_from_revision", "Net"), ("jetstream::kv::Store::watch_with_history", "Net"),
("jetstream::kv::Store::watch_many_with_history", "Net"), ("jetstream::kv::Store::watch_all", "Net"),
("jetstream::kv::Store::watch_all_from_revision", "Net"),
("jetstream::object_store::ObjectStore::get", "Net"), ("jetstream::object_store::ObjectStore::put", "Net"),
("jetstream::object_store::ObjectStore::info", "Net"), ("jetstream::object_store::ObjectStore::list", "Net"),
("jetstream::object_store::ObjectStore::watch", "Net"),
("jetstream::object_store::ObjectStore::watch_with_history", "Net"),
("jetstream::object_store::ObjectStore::delete", "Net"), ("jetstream::object_store::ObjectStore::seal", "Net"),
("jetstream::object_store::ObjectStore::update_metadata", "Net"),
("jetstream::object_store::ObjectStore::add_link", "Net"),
("jetstream::object_store::ObjectStore::add_bucket_link", "Net"),
("jetstream::consumer::Consumer::info", "Net"), ("jetstream::consumer::Consumer::get_info", "Net"),
("jetstream::consumer::Consumer::reset", "Net"), ("jetstream::consumer::PullConsumer::messages", "Net"),
("jetstream::consumer::PushConsumer::messages", "Net"),
("jetstream::consumer::OrderedPullConsumer::messages", "Net"),
("jetstream::consumer::OrderedPushConsumer::messages", "Net"),
("jetstream::consumer::pull::Consumer::messages", "Net"),
("jetstream::consumer::push::Consumer::messages", "Net"),
("jetstream::consumer::pull::StreamBuilder::messages", "Net"),
("jetstream::consumer::pull::FetchBuilder::messages", "Net"),
("jetstream::consumer::pull::BatchBuilder::messages", "Net"),
("jetstream::Message::double_ack", "Net"), ("jetstream::message::Message::double_ack_with", "Net"),
("jetstream::message::Acker::double_ack", "Net"), ("jetstream::message::Acker::double_ack_with", "Net"),
("jetstream::Message::ack", "Net"), ("jetstream::Message::ack_with", "Net"),
("jetstream::message::Acker::ack", "Net"), ("jetstream::message::Acker::ack_with", "Net"),
("Client::add_service", "Net"), ("service::Client::add_service", "Net"), ("Client::start", "Net"),
("Client::send_request", "Net"), ("client::Client::send_request", "Net"),
("service::ServiceBuilder::start", "Net"), ("service::Service::endpoint", "Net"),
("service::Group::endpoint", "Net"), ("service::EndpointBuilder::add", "Net"),
("service::Service::add", "Net"),
("Client::new_inbox", "Rand"), ("client::Client::new_inbox", "Rand"), ("datetime::now", "Clock"),
] {
assert_eq!(classify("async_nats", &format!("async_nats::{p}")), Some(eff), "{p}");
}
for p in ["jetstream::new", "jetstream::with_domain", "jetstream::with_prefix",
"jetstream::context::ContextBuilder::build", "jetstream::ContextBuilder::new",
"jetstream::Context::get_stream_no_info", "jetstream::Context::wait_for_acks",
"jetstream::Context::set_timeout", "jetstream::kv::Store::status",
"jetstream::stream::Stream::cached_info", "jetstream::stream::Stream::info_builder",
"jetstream::stream::Stream::direct_get_builder", "jetstream::stream::Stream::raw_message_builder",
"jetstream::consumer::PullConsumer::stream", "jetstream::consumer::PullConsumer::fetch",
"jetstream::consumer::PullConsumer::batch", "jetstream::consumer::Consumer::cached_info",
"service::Service::info", "service::Service::stats", "service::Service::reset",
"service::Service::group", "service::Service::endpoint_builder", "Client::timeout",
"Client::max_payload", "jetstream::consumer::pull::Stream::info", "other::Stream::info",
"jetstream::object_store::Object::info", "jetstream::stream::Stream::name"] {
assert_eq!(classify("async_nats", &format!("async_nats::{p}")), None, "{p}");
}
assert_eq!(classify("mycrate", "mycrate::jetstream::Context::create_stream"), None);
assert_eq!(classify("redis", "redis::kv::Store::put"), None);
}
#[test]
fn r1528_rdkafka_rows_classify() {
let mut net: Vec<String> = vec![
"ClientConfig::create".into(), "config::ClientConfig::create".into(), "ClientConfig::create_with_context".into(),
"config::ClientConfig::create_with_context".into(), "Client::new".into(), "client::Client::new".into(),
"MockCluster::new".into(), "mocking::MockCluster::new".into(),
];
for v in ["create_topics", "delete_topics", "create_partitions", "delete_groups", "delete_records",
"describe_configs", "alter_configs", "from_config", "from_config_and_context"] {
net.push(format!("AdminClient::{v}"));
net.push(format!("admin::AdminClient::{v}"));
}
for (ty, module) in [("BaseConsumer", "consumer::base_consumer"), ("StreamConsumer", "consumer::stream_consumer")] {
for v in ["from_config", "from_config_and_context", "committed", "offsets_for_timestamp",
"incremental_assign", "seek_partitions"] {
net.push(format!("{ty}::{v}"));
net.push(format!("consumer::{ty}::{v}"));
net.push(format!("{module}::{ty}::{v}"));
}
}
for (ty, module) in [("BaseProducer", "producer::base_producer"), ("ThreadedProducer", "producer::base_producer"),
("FutureProducer", "producer::future_producer")] {
for v in ["from_config", "from_config_and_context", "init_transactions", "commit_transaction",
"abort_transaction", "send_offsets_to_transaction"] {
net.push(format!("{ty}::{v}"));
net.push(format!("producer::{ty}::{v}"));
net.push(format!("{module}::{ty}::{v}"));
}
}
for p in &net {
assert_eq!(classify("rdkafka", &format!("rdkafka::{p}")), Some("Net"), "{p}");
}
for p in ["Timestamp::now", "message::Timestamp::now", "util::current_time_millis"] {
assert_eq!(classify("rdkafka", &format!("rdkafka::{p}")), Some("Clock"), "{p}");
}
for p in ["BaseConsumer::assignment", "BaseConsumer::subscription", "BaseConsumer::position",
"BaseConsumer::incremental_unassign", "StreamConsumer::assignment", "StreamConsumer::position",
"BaseProducer::begin_transaction", "ThreadedProducer::begin_transaction",
"FutureProducer::begin_transaction", "BaseConsumer::close_queue",
"ClientConfig::create_native_config", "TopicPartitionList::new", "TopicPartitionList::with_capacity",
"TopicPartitionList::from_topic_map", "OwnedHeaders::new", "OwnedHeaders::new_with_capacity",
"BorrowedHeaders::detach", "BorrowedMessage::detach", "FutureProducerContext::log",
"FutureProducerContext::error", "FutureProducerContext::stats", "FutureProducerContext::stats_raw",
"other::AdminClient::create_topics", "Consumer::committed", "consumer::BaseProducer::committed",
"producer::BaseConsumer::init_transactions", "Foo::from_config", "Timestamp::new",
"other::util::current_time_millis"] {
assert_eq!(classify("rdkafka", &format!("rdkafka::{p}")), None, "{p}");
}
assert_eq!(classify("mycrate", "mycrate::AdminClient::create_topics"), None);
assert_eq!(classify("lapin", "lapin::ClientConfig::create"), None);
}
#[test]
fn r1528_mongodb_rows_classify() {
let mut db: Vec<String> = vec![];
for m in ["", "sync::"] {
for (ty, v) in [
("ClientSession", "commit_transaction"), ("ClientSession", "abort_transaction"), ("ClientSession", "and_run"),
("ClientSession", "and_run2"), ("Client", "shutdown"), ("Client", "bulk_write"), ("Database", "drop"),
("Database", "run_cursor_command"), ("Collection", "drop"), ("Collection", "drop_index"),
("Collection", "drop_indexes"), ("Collection", "list_indexes"), ("Collection", "list_index_names"),
("Collection", "create_search_index"), ("Collection", "create_search_indexes"),
("ChangeStream", "next_if_any"), ("SessionChangeStream", "next"), ("SessionChangeStream", "next_if_any"),
("GridFsBucket", "delete"), ("GridFsUploadStream", "abort"),
] {
db.push(format!("{m}{ty}::{v}"));
}
}
for p in [
"change_stream::ChangeStream::next_if_any", "change_stream::session::SessionChangeStream::next",
"change_stream::session::SessionChangeStream::next_if_any", "sync::change_stream::ChangeStream::next_if_any",
"sync::change_stream::SessionChangeStream::next", "sync::change_stream::SessionChangeStream::next_if_any",
"action::shutdown::Client::shutdown", "gridfs::GridFsBucket::delete", "gridfs::GridFsUploadStream::abort",
"client::session::action::StartTransaction::and_run", "client::session::action::StartTransaction::and_run2",
"client::session::action::AbortTransaction::execute", "client::session::action::CommitTransaction::execute",
"client::action::shutdown::Shutdown::execute", "action::bulk_write::BulkWrite::execute",
"action::count::CountDocuments::execute", "db::action::create_collection::CreateCollection::execute",
"action::search_index::CreateSearchIndex::execute", "coll::action::drop::DropCollection::execute",
"action::drop::DropDatabase::execute", "action::drop_index::DropIndex::execute", "action::find::Find::execute",
"action::find::Find::batch", "action::find_and_modify::FindOneAndDelete::execute",
"action::find_and_modify::FindOneAndReplace::execute", "action::find_and_modify::FindOneAndUpdate::execute",
"action::list_collections::ListCollections::execute", "action::list_collections::ListCollections::batch",
"action::list_databases::ListDatabases::execute", "action::list_indexes::ListIndexes::execute",
"action::run_command::RunCommand::execute", "action::run_command::RunCursorCommand::execute",
"action::run_command::RunCursorCommand::batch", "action::watch::Watch::execute", "Find::execute",
"action::gridfs::delete::Delete::execute",
] {
db.push(p.to_string());
}
for p in &db {
assert_eq!(classify("mongodb", &format!("mongodb::{p}")), Some("Db"), "{p}");
}
for p in ["Callback::human", "Callback::machine", "options::oidc::Callback::human", "client::auth::oidc::Callback::machine"] {
assert_eq!(classify("mongodb", &format!("mongodb::{p}")), Some("Clock"), "{p}");
}
for p in [
"ClientSession::start_transaction", "ClientSession::end_session", "Collection::name", "Database::name",
"Collection::namespace", "options::ClientOptions::parse", "ClientOptions::parse", "options::ConnectionString::parse",
"ConnectionString::parse", "client::auth::AuthMechanism::validate_credential", "AuthMechanism::validate_credential",
"client::options::parse::ParseConnectionString::execute", "ClientEncryption::new",
"client::csfle::client_encryption::ClientEncryptionBuilder::build", "client::csfle::client_builder::EncryptedClientBuilder::build",
"client::csfle::client_encryption::create_data_key::CreateDataKey::execute", "client::csfle::client_encryption::encrypt::Encrypt::execute",
"Foo::commit_transaction", "Collection::commit_transaction", "other::Client::shutdown", "Delete::execute",
"action::delete::Delete::execute", "Callback::new", "other::Callback::human", "ChangeStream::next", "Cursor::next_if_any",
] {
assert_eq!(classify("mongodb", &format!("mongodb::{p}")), None, "{p}");
}
assert_eq!(classify("mycrate", "mycrate::ClientSession::commit_transaction"), None);
assert_eq!(classify("mysql_async", "mysql_async::ClientSession::commit_transaction"), None);
}
#[test]
fn r1528_mysql_async_rows_classify() {
let mut db: Vec<String> = vec![];
for (ty, ms, vs) in [
("Conn", vec!["", "conn::", "conn::binlog_stream::", "queryable::"], vec!["change_user", "reset", "disconnect", "get_binlog_stream", "close", "start_transaction"]),
("BinlogStream", vec!["", "conn::binlog_stream::"], vec!["close"]),
("Connection", vec!["", "queryable::"], vec!["close"]),
("Transaction", vec!["", "queryable::", "queryable::transaction::"], vec!["close", "commit", "rollback"]),
("Pool", vec!["", "conn::pool::", "connection_like::"], vec!["start_transaction", "to_connection"]),
("QueryResult", vec!["", "queryable::query_result::", "queryable::query_result::result_set_stream::"],
vec!["next", "collect", "try_collect", "collect_and_drop", "try_collect_and_drop", "for_each", "for_each_and_drop",
"map_and_drop", "reduce", "reduce_and_drop", "drop_result", "stream", "stream_and_drop"]),
("QueryWithParams", vec!["", "query::"], vec!["run", "batch", "first", "fetch", "ignore", "reduce", "stream"]),
("Query", vec!["prelude::"], vec!["run", "first", "fetch", "ignore", "reduce", "stream"]),
("BatchQuery", vec!["prelude::"], vec!["batch"]),
("Q", vec!["", "query::"], vec!["run"]),
] {
for m in &ms {
for v in &vs {
db.push(format!("{m}{ty}::{v}"));
}
}
}
for p in &db {
assert_eq!(classify("mysql_async", &format!("mysql_async::{p}")), Some("Db"), "{p}");
}
for p in ["test_misc::get_opts", "test_misc::test_compression", "test_misc::test_ssl"] {
assert_eq!(classify("mysql_async", &format!("mysql_async::{p}")), Some("Env"), "{p}");
}
assert_eq!(classify("mysql_async", "mysql_async::Conn::new"), Some("Db"));
assert_eq!(classify("mysql_async", "mysql_async::Pool::get_conn"), Some("Db"));
for p in [
"QueryResult::map", "queryable::query_result::QueryResult::map", "QueryWithParams::map", "prelude::Query::map",
"opts::PathOrBuf::read", "PathOrBuf::read", "Arc::to_statement", "String::to_statement", "Vec::to_statement",
"prelude::StatementLike::to_statement", "Conn::map", "Conn::opts", "Conn::tcp_port", "Pool::opts", "Pool::iter",
"Transaction::last_insert_id", "TxOpts::new", "TxOpts::with_readonly", "Opts::from_url", "Params::from",
"QueryResult::columns_ref", "QueryResult::columns", "QueryResult::affected_rows", "QueryResult::info",
"Foo::commit", "Pool::commit", "Conn::commit", "test_misc::other", "other::test_misc::get_opts",
"Query::map", "BatchQuery::run",
] {
assert_eq!(classify("mysql_async", &format!("mysql_async::{p}")), None, "{p}");
}
assert_eq!(classify("mysql", "mysql::Conn::reset"), Some("Db"));
assert_eq!(classify("mongodb", "mongodb::Conn::reset"), None);
}
#[test]
fn r1528_aws_config_rows_classify() {
for p in [
"default_provider::endpoint_url::endpoint_url_provider",
"default_provider::endpoint_url::endpoint_url_provider_with_origin",
"default_provider::ignore_configured_endpoint_urls::ignore_configured_endpoint_urls_provider",
"default_provider::checksums::request_checksum_calculation_provider",
"default_provider::checksums::response_checksum_validation_provider",
"default_provider::use_dual_stack::use_dual_stack_provider",
"default_provider::use_fips::use_fips_provider",
"default_provider::app_name::Builder::app_name",
"default_provider::retry_config::Builder::retry_config",
"profile::region::ProfileFileRegionProvider::region",
] {
assert_eq!(classify("aws_config", &format!("aws_config::{p}")), Some("Fs"), "{p}");
}
for p in [
"default_provider::region::DefaultRegionChain::region",
"imds::region::ImdsRegionProvider::region",
"provider_config::ProviderConfig::load_default_region",
"provider_config::ProviderConfig::with_default_region",
"default_provider::credentials::DefaultCredentialsChain::build",
"default_provider::credentials::Builder::build",
"default_provider::credentials::default_provider",
"default_provider::token::DefaultTokenChain::build",
"default_provider::token::Builder::build",
"default_provider::token::default_provider",
"sts::AssumeRoleProvider::build",
"sts::AssumeRoleProvider::build_from_provider",
"sts::assume_role::AssumeRoleProviderBuilder::build",
"sts::assume_role::AssumeRoleProviderBuilder::build_from_provider",
"sso::token::SsoTokenProvider::build",
"sso::token::Builder::build",
"ecs::EcsCredentialsProvider::credentials",
] {
assert_eq!(classify("aws_config", &format!("aws_config::{p}")), Some("Net"), "{p}");
}
for p in [
"meta::region::Box::region", "meta::region::RegionProviderChain::region",
"profile::credentials::Builder::build", "profile::token::Builder::build",
"profile::ProfileFileCredentialsProvider::build", "profile::ProfileFileTokenProvider::build",
"default_provider::credentials::DefaultCredentialsChain::region",
"default_provider::token::DefaultTokenChain::region",
"sso::token::SsoTokenProvider::region", "sso::token::SsoTokenProvider::session_name",
"default_provider::region::DefaultRegionChain::build",
"default_provider::region::DefaultRegionChain::profile_name",
"default_provider::region::default_provider", "default_provider::timeout_config::Builder::timeout_config",
"provider_config::ProviderConfig::empty", "provider_config::ProviderConfig::with_region",
"sts::AssumeRoleProvider::configure", "sts::AssumeRoleProvider::builder",
"imds::region::ImdsRegionProvider::build", "ecs::EcsCredentialsProvider::build",
"default_provider::use_fips::other", "other::default_provider::credentials::DefaultCredentialsChain::build",
] {
assert_eq!(classify("aws_config", &format!("aws_config::{p}")), None, "{p}");
}
assert_eq!(classify("aws_config", "aws_config::loader::ConfigLoader::load"), Some("Net"));
assert_eq!(classify("mycrate", "mycrate::default_provider::use_fips::use_fips_provider"), None);
}
#[test]
fn r1528_sqlx_core_rows_classify() {
for (k, p, e) in [
("sqlx_core", "pool::Pool::begin_with", "Db"), ("sqlx_core", "Pool::begin_with", "Db"),
("sqlx", "PgPool::begin_with", "Db"), ("sqlx", "Pool::begin_with", "Db"), ("sqlx", "MySqlPool::begin_with", "Db"),
("sqlx_core", "pool::PoolConnection::close", "Net"), ("sqlx", "pool::PoolConnection::close", "Net"),
("sqlx_core", "pool::connection::PoolConnection::close", "Net"),
("sqlx_core", "pool::PoolConnection::return_to_pool", "Db"), ("sqlx", "pool::PoolConnection::return_to_pool", "Db"),
("sqlx_core", "net::connect_tcp", "Net"), ("sqlx_core", "net::socket::connect_tcp", "Net"),
("sqlx_core", "migrate::Migrator::new", "Fs"), ("sqlx_core", "migrate::migrator::Migrator::new", "Fs"),
("sqlx", "migrate::Migrator::new", "Fs"),
("sqlx_core", "fs::ReadDir::next", "Fs"),
("sqlx_core", "migrate::source::resolve_blocking", "Fs"),
("sqlx_core", "migrate::source::resolve_blocking_with_config", "Fs"),
("sqlx_core", "migrate::resolve_blocking", "Fs"),
("sqlx_core", "logger::QueryLogger::new", "Clock"), ("sqlx_core", "logger::QueryLogger::finish", "Log"),
] {
assert_eq!(classify(k, &format!("{k}::{p}")), Some(e), "{k}::{p}");
}
for (k, p) in [
("sqlx_core", "pool::PoolConnection::detach"), ("sqlx_core", "pool::PoolConnection::leak"),
("sqlx", "pool::PoolConnection::detach"), ("sqlx", "pool::PoolConnection::leak"),
("sqlx_core", "pool::Pool::connect_lazy"), ("sqlx_core", "pool::Pool::connect_lazy_with"),
("sqlx_core", "pool::PoolOptions::connect_lazy"), ("sqlx_core", "pool::PoolOptions::connect_lazy_with"),
("sqlx", "MySqlPool::connect_lazy"), ("sqlx", "sqlite::SqlitePool::connect_lazy"),
("sqlx_core", "net::socket::Box::poll_flush"), ("sqlx_core", "net::Socket::poll_read_ready"),
("sqlx_core", "migrate::source::PathBuf::resolve"), ("sqlx_core", "migrate::source::ResolveWith::resolve"),
("sqlx_core", "migrate::ResolveConfig::new"), ("sqlx_core", "logger::QueryLogger::sql"),
("sqlx_core", "logger::QueryLogger::increment_rows_returned"),
("sqlx_core", "pool::PoolOptions::max_connections"), ("sqlx_core", "pool::PoolConnection::close_on_drop"),
("sqlx", "postgres::PgPoolOptions::new"), ("sqlx", "PgPool::size"), ("sqlx", "other::PgPool::begin_with"),
("sqlx", "Connection::close"), ("sqlx", "Transaction::new"),
] {
assert_eq!(classify(k, &format!("{k}::{p}")), None, "{k}::{p}");
}
assert_eq!(classify("sqlx", "sqlx::net::connect_tcp"), None);
assert_eq!(classify("mycrate", "mycrate::pool::PoolConnection::close"), None);
}
#[test]
fn r1528_redis_rows_classify() {
for (p, e) in [
("Client::is_open", "Db"), ("client::Client::is_open", "Db"), ("Client::check_connection", "Db"),
("Client::get_async_pubsub", "Db"), ("client::Client::get_async_monitor", "Db"),
("Cmd::iter_async", "Db"), ("cmd::Cmd::iter_async", "Db"),
("aio::MultiplexedConnection::send_packed_command", "Db"),
("aio::MultiplexedConnection::send_packed_commands", "Db"),
("aio::multiplexed_connection::MultiplexedConnection::send_packed_command", "Db"),
("aio::MultiplexedConnection::connect_with_config", "Db"),
("cluster_handling::async_connection::MultiplexedConnection::connect_with_config", "Db"),
("cluster::ClusterConnection::route_command", "Db"), ("cluster_async::ClusterConnection::route_command", "Db"),
("cluster_handling::sync_connection::ClusterConnection::route_command", "Db"),
("cluster_handling::async_connection::ClusterConnection::route_command", "Db"),
("cluster::ClusterPipeline::exec", "Db"), ("cluster_handling::sync_connection::pipeline::ClusterPipeline::exec", "Db"),
("cluster::ClusterClient::get_pending_async_connection_with_config", "Db"),
("cluster_handling::client::ClusterClient::get_pending_async_connection_with_config", "Db"),
("cluster_read_routing::Replicas::choose_random", "Rand"),
("cluster_handling::read_routing::interface::Replicas::choose_random", "Rand"),
("cluster_read_routing::RandomReplicaStrategy::route_read", "Rand"),
("cluster_handling::read_routing::random_replica::RandomReplicaStrategy::route_read", "Rand"),
] {
assert_eq!(classify("redis", &format!("redis::{p}")), Some(e), "{p}");
}
for p in [
"Client::build_with_tls", "client::Client::build_with_tls", "cluster::ClusterClient::build",
"cluster_handling::client::ClusterClientBuilder::build", "cluster::ClusterClientBuilder::retries",
"aio::MultiplexedConnection::new", "aio::MultiplexedConnection::new_with_config",
"aio::multiplexed_connection::MultiplexedConnection::new",
"entra_id::EntraIdCredentialsProvider::start", "Client::open", "Client::get_connection_info",
"Connection::is_open", "aio::MultiplexedConnection::is_open", "Other::route_command",
"cluster::ClusterClient::builder", "cluster_read_routing::Replicas::new", "cluster_read_routing::Replicas::iter",
"sentinel::Sentinel::new", "sentinel::SentinelClientBuilder::set_client_to_redis_db",
"sentinel::Sentinel::build", "sentinel::SentinelClient::build", "sentinel::SentinelClientBuilder::build",
"other::Client::is_open", "Cmd::arg", "Cmd::new",
] {
assert_eq!(classify("redis", &format!("redis::{p}")), None, "{p}");
}
assert_eq!(classify("mycrate", "mycrate::Client::is_open"), None);
}
#[test]
fn r1528_rusqlite_reachable_rows_classify() {
for p in ["Connection::close", "Connection::cache_flush", "Connection::serialize", "Connection::deserialize",
"Connection::deserialize_bytes", "Connection::deserialize_read_exact",
"Connection::load_extension", "Connection::load_extension_enable",
"Connection::load_extension_disable", "Connection::query_row_and_then",
"Connection::prepare_with_flags", "Statement::exists", "LoadExtensionGuard::new",
"Wal::checkpoint", "Wal::checkpoint_v2", "serialize::Connection::serialize",
"statement::Statement::exists", "hooks::Wal::checkpoint_v2",
"load_extension_guard::LoadExtensionGuard::new",
"register_auto_extension", "cancel_auto_extension", "reset_auto_extension",
"auto_extension::register_auto_extension", "auto_extension::cancel_auto_extension",
"auto_extension::reset_auto_extension"] {
assert_eq!(classify("rusqlite", &format!("rusqlite::{p}")), Some("Db"), "{p}");
}
for v in ["query_row_and_then", "prepare_with_flags"] {
assert!(masks_locator("Db", "rusqlite", &format!("rusqlite::Connection::{v}"), v, true), "{v}");
}
for p in ["Connection::is_autocommit", "Connection::changes", "Connection::last_insert_rowid",
"Connection::is_busy", "Connection::is_readonly", "Connection::path", "Statement::column_count",
"Wal::name", "LoadExtensionGuard::drop", "Connection::handle"] {
assert_eq!(classify("rusqlite", &format!("rusqlite::{p}")), None, "{p}");
}
assert_eq!(classify("mycrate", "mycrate::Connection::close"), None);
assert_eq!(classify("tokio_postgres", "tokio_postgres::Connection::close"), None);
}
#[test]
fn r1528_isahc_rows_classify() {
for m in ["get_async", "head_async", "post_async", "put_async", "delete_async", "send_async"] {
assert_eq!(classify("isahc", &format!("isahc::HttpClient::{m}")), Some("Net"), "{m}");
assert_eq!(classify("isahc", &format!("isahc::client::HttpClient::{m}")), Some("Net"), "{m}");
}
assert_eq!(classify("isahc", "isahc::Request::send_async"), Some("Net"));
assert_eq!(classify("isahc", "isahc::request::Request::send_async"), Some("Net"));
assert_eq!(classify("isahc", "isahc::tls::TrustStore::native"), Some("Env"));
assert_eq!(classify("isahc", "isahc::tls::trust::TrustStore::native"), Some("Env"));
for p in ["cookies::CookieJar::get_by_name", "cookies::CookieJar::get_for_uri", "cookies::CookieJar::set",
"cookies::jar::CookieJar::set", "Response::text", "response::Response::text", "HttpClient::builder",
"TrustStore::webpki_roots", "TrustStore::from_file", "tls::TrustStore::from_file"] {
assert_eq!(classify("isahc", &format!("isahc::{p}")), None, "{p}");
}
assert_eq!(classify("mycrate", "mycrate::HttpClient::get_async"), None);
}
#[test]
fn r1528_lettre_rows_classify() {
for t in ["MessageBuilder", "Message"] {
for m in ["body", "singlepart", "multipart", "date_now"] {
assert_eq!(classify("lettre", &format!("lettre::message::{t}::{m}")), Some("Clock"), "{t}::{m}");
}
assert_eq!(classify("lettre", &format!("lettre::message::{t}::message_id")), Some("Rand"), "{t}");
}
for p in ["message::Message::sign", "message::header::Date::now", "message::header::date::Date::now",
"message::dkim::dkim_sign"] {
assert_eq!(classify("lettre", &format!("lettre::{p}")), Some("Clock"), "{p}");
}
for p in ["message::MultiPartBuilder::kind", "message::MultiPart::kind", "message::mimebody::MultiPartBuilder::kind",
"message::MultiPart::mixed", "message::MultiPart::alternative", "message::MultiPart::related",
"message::MultiPart::signed", "message::MultiPart::encrypted", "message::MultiPart::alternative_plain_html"] {
assert_eq!(classify("lettre", &format!("lettre::{p}")), Some("Rand"), "{p}");
}
for p in ["AsyncFileTransport::read", "transport::file::AsyncFileTransport::read", "Executor::fs_read",
"Executor::fs_write", "Tokio1Executor::fs_read", "executor::Tokio1Executor::fs_write",
"AsyncStd1Executor::fs_read"] {
assert_eq!(classify("lettre", &format!("lettre::{p}")), Some("Fs"), "{p}");
}
for p in ["transport::smtp::SmtpTransportBuilder::build", "transport::smtp::AsyncSmtpTransportBuilder::build",
"transport::smtp::transport::SmtpTransport::unencrypted_localhost",
"transport::smtp::async_transport::AsyncSmtpTransport::unencrypted_localhost",
"transport::smtp::commands::Auth::new_from_response", "message::Message::builder",
"message::Message::to", "message::Message::subject", "message::MessageBuilder::subject",
"message::MessageBuilder::date", "message::Message::date", "message::MultiPart::builder",
"message::MultiPart::singlepart", "message::MultiPartBuilder::boundary", "message::Message::formatted",
"message::header::Date::new", "message::SinglePart::plain"] {
assert_eq!(classify("lettre", &format!("lettre::{p}")), None, "{p}");
}
assert_eq!(classify("mycrate", "mycrate::message::Message::body"), None);
}
#[test]
fn r1528_lapin_rows_classify() {
for m in ["connect_uri", "connect_uri_with_runtime", "connect_uri_with_config", "connect_with_config",
"connect_with_runtime", "update_secret"] {
assert_eq!(classify("lapin", &format!("lapin::Connection::{m}")), Some("Net"), "{m}");
assert_eq!(classify("lapin", &format!("lapin::connection::Connection::{m}")), Some("Net"), "{m}");
}
for p in ["AMQPUri::connect_with_config", "uri::AMQPUri::connect_with_config",
"connection::AMQPUri::connect_with_config", "Connect::connect_with_config"] {
assert_eq!(classify("lapin", &format!("lapin::{p}")), Some("Net"), "{p}");
}
for m in ["access_request", "channel_flow"] {
assert_eq!(classify("lapin", &format!("lapin::Channel::{m}")), Some("Net"), "{m}");
assert_eq!(classify("lapin", &format!("lapin::generated::channel::Channel::{m}")), Some("Net"), "{m}");
}
for m in ["ack", "nack", "reject"] {
assert_eq!(classify("lapin", &format!("lapin::Acker::{m}")), Some("Net"), "{m}");
assert_eq!(classify("lapin", &format!("lapin::acker::Acker::{m}")), Some("Net"), "{m}");
}
for p in ["Connection::connector", "connection::Connection::connector", "Connection::run",
"connection::Connection::run", "Consumer::set_delegate", "consumer::Consumer::set_delegate",
"Channel::wait_for_confirms", "channel::Channel::wait_for_confirms", "Channel::reject",
"Connection::ack", "Connection::status", "Channel::status", "Acker::poisoned", "Acker::usable",
"ConnectionProperties::default", "runtime::default_runtime"] {
assert_eq!(classify("lapin", &format!("lapin::{p}")), None, "{p}");
}
assert_eq!(classify("lapin", "lapin::Connection::connect"), Some("Net"));
assert_eq!(classify("mycrate", "mycrate::Acker::ack"), None);
}
#[test]
fn r1528_tonic_rows_classify() {
for p in ["Server::serve", "Server::serve_with_shutdown", "transport::Server::serve", "transport::Server::serve_with_shutdown",
"transport::server::Server::serve", "transport::server::Server::serve_with_shutdown",
"TcpIncoming::bind", "transport::server::TcpIncoming::bind", "transport::server::incoming::TcpIncoming::bind"] {
assert_eq!(classify("tonic", &format!("tonic::{p}")), Some("Net"), "{p}");
}
for p in ["transport::Server::serve_with_incoming", "transport::Server::serve_with_incoming_shutdown",
"transport::server::Server::serve_with_incoming", "transport::server::Router::serve_with_incoming",
"transport::server::Router::serve_with_incoming_shutdown",
"transport::Endpoint::tls_config", "transport::Endpoint::tls_config_with_verifier",
"transport::ClientTlsConfig::with_native_roots", "transport::ClientTlsConfig::use_key_log",
"Code::from_bytes", "Status::from_header_map", "Streaming::message", "Streaming::trailers",
"transport::Server::builder", "transport::Server::add_service", "transport::Server::tcp_nodelay",
"transport::server::TcpIncoming::with_nodelay"] {
assert_eq!(classify("tonic", &format!("tonic::{p}")), None, "{p}");
}
assert_eq!(classify("tonic", "tonic::transport::server::Router::serve"), Some("Net"));
assert_eq!(classify("tonic", "tonic::transport::Endpoint::connect"), Some("Net"));
assert_eq!(classify("mycrate", "mycrate::Server::serve"), None);
}
}