source/Rules.h (79 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #include <memory> #include <unordered_map> #include <vector> #include <boost/iterator/transform_iterator.hpp> #include <json/json.h> #include <mariana-trench/Context.h> #include <mariana-trench/Kind.h> #include <mariana-trench/MultiSourceMultiSinkRule.h> #include <mariana-trench/PartialKind.h> #include <mariana-trench/Rule.h> namespace marianatrench { class Rules final { private: struct ExposeRulePointer { const Rule* operator()( const std::pair<const int, std::unique_ptr<Rule>>& pair) const { return pair.second.get(); } }; public: // C++ container concept member types using iterator = boost::transform_iterator< ExposeRulePointer, std::unordered_map<int, std::unique_ptr<Rule>>::const_iterator>; using const_iterator = iterator; using value_type = const Rule*; using difference_type = std::ptrdiff_t; using size_type = std::size_t; using const_reference = const Rule*; using const_pointer = typename iterator::pointer; private: // Safety checks of `boost::transform_iterator`. static_assert(std::is_same_v<typename iterator::value_type, value_type>); static_assert( std::is_same_v<typename iterator::difference_type, difference_type>); static_assert(std::is_same_v<typename iterator::reference, const_reference>); public: explicit Rules(); explicit Rules(Context& context, std::vector<std::unique_ptr<Rule>> rules); explicit Rules(Context& context, const Json::Value& rules_value); /* Load the rules from the json file specified in the given options. */ static Rules load(Context& context, const Options& options); Rules(const Rules&) = delete; Rules(Rules&&) = default; Rules& operator=(const Rules&) = delete; Rules& operator=(Rules&&) = delete; ~Rules() = default; /* This is NOT thread-safe. */ void add(Context& context, std::unique_ptr<Rule> rule); /** * Return the set of rules matching the given source kind and sink kind. * Satisfying these rules should result in the creation of an issue (this * is the responsibility of the caller). */ const std::vector<const Rule*>& rules( const Kind* source_kind, const Kind* sink_kind) const; /** * Return the set of rules matching the given source kind and sink kind. * Only for multi-source/sink rules. The rule is partially satisfied. The * other sink in the rule still needs to be met with its corresponding source * for an issue to be created (also the responsibility of the caller). */ const std::vector<const MultiSourceMultiSinkRule*>& partial_rules( const Kind* source_kind, const PartialKind* sink_kind) const; std::unordered_set<const Kind*> collect_unused_kinds( const Kinds& kinds) const; std::size_t size() const { return rules_.size(); } iterator begin() const { return boost::make_transform_iterator(rules_.cbegin(), ExposeRulePointer()); } iterator end() const { return boost::make_transform_iterator(rules_.cend(), ExposeRulePointer()); } private: std::unordered_map<int, std::unique_ptr<Rule>> rules_; std::unordered_map< const Kind*, std::unordered_map<const Kind*, std::vector<const Rule*>>> source_to_sink_to_rules_; std::unordered_map< const Kind*, std::unordered_map< const PartialKind*, std::vector<const MultiSourceMultiSinkRule*>>> source_to_partial_sink_to_rules_; std::vector<const Rule*> empty_rule_set_; std::vector<const MultiSourceMultiSinkRule*> empty_multi_source_rule_set_; }; } // namespace marianatrench