LCOV - code coverage report
Current view: top level - source/common/matcher - field_matcher.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 0 70 0.0 %
Date: 2024-01-05 06:35:25 Functions: 0 28 0.0 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "envoy/matcher/matcher.h"
       4             : 
       5             : #include "absl/strings/str_join.h"
       6             : 
       7             : namespace Envoy {
       8             : namespace Matcher {
       9             : 
      10             : /**
      11             :  * The result of a field match.
      12             :  */
      13             : struct FieldMatchResult {
      14             :   // Encodes whether we were able to perform the match.
      15             :   MatchState match_state_;
      16             : 
      17             :   // The result, if matching was completed.
      18             :   absl::optional<bool> result_;
      19             : 
      20             :   // The unwrapped result. Should only be called if match_state_ == MatchComplete.
      21           0 :   bool result() const {
      22           0 :     ASSERT(match_state_ == MatchState::MatchComplete);
      23           0 :     ASSERT(result_.has_value());
      24           0 :     return *result_;
      25           0 :   }
      26             : };
      27             : 
      28             : /**
      29             :  * Base class for matching against a single input.
      30             :  */
      31             : template <class DataType> class FieldMatcher {
      32             : public:
      33           0 :   virtual ~FieldMatcher() = default;
      34             : 
      35             :   /**
      36             :    * Attempts to match against the provided data.
      37             :    * @returns absl::optional<bool> if matching was possible, the result of the match. Otherwise
      38             :    * absl::nullopt if the data is not available.
      39             :    */
      40             :   virtual FieldMatchResult match(const DataType& data) PURE;
      41             : };
      42             : template <class DataType> using FieldMatcherPtr = std::unique_ptr<FieldMatcher<DataType>>;
      43             : 
      44             : /**
      45             :  * A FieldMatcher that attempts to match multiple FieldMatchers, evaluating to true iff all the
      46             :  * FieldMatchers evaluate to true.
      47             :  *
      48             :  * If any of the underlying FieldMatchers are unable to produce a result, absl::nullopt is returned.
      49             :  */
      50             : template <class DataType> class AllFieldMatcher : public FieldMatcher<DataType> {
      51             : public:
      52             :   explicit AllFieldMatcher(std::vector<FieldMatcherPtr<DataType>>&& matchers)
      53           0 :       : matchers_(std::move(matchers)) {}
      54             : 
      55           0 :   FieldMatchResult match(const DataType& data) override {
      56           0 :     for (const auto& matcher : matchers_) {
      57           0 :       const auto result = matcher->match(data);
      58             : 
      59             :       // If we are unable to decide on a match at this point, propagate this up to defer
      60             :       // the match result until we have the requisite data.
      61           0 :       if (result.match_state_ == MatchState::UnableToMatch) {
      62           0 :         return result;
      63           0 :       }
      64             : 
      65           0 :       if (!result.result()) {
      66           0 :         return result;
      67           0 :       }
      68           0 :     }
      69             : 
      70           0 :     return {MatchState::MatchComplete, true};
      71           0 :   }
      72             : 
      73             : private:
      74             :   const std::vector<FieldMatcherPtr<DataType>> matchers_;
      75             : };
      76             : 
      77             : /**
      78             :  * A FieldMatcher that attempts to match multiple FieldMatchers, evaluating to true iff any of the
      79             :  * FieldMatchers evaluate to true.
      80             :  *
      81             :  * If any of the underlying FieldMatchers are unable to produce a result before we see a successful
      82             :  * match, absl::nullopt is returned.
      83             :  */
      84             : template <class DataType> class AnyFieldMatcher : public FieldMatcher<DataType> {
      85             : public:
      86             :   explicit AnyFieldMatcher(std::vector<FieldMatcherPtr<DataType>>&& matchers)
      87           0 :       : matchers_(std::move(matchers)) {}
      88             : 
      89           0 :   FieldMatchResult match(const DataType& data) override {
      90           0 :     bool unable_to_match_some_matchers = false;
      91           0 :     for (const auto& matcher : matchers_) {
      92           0 :       const auto result = matcher->match(data);
      93             : 
      94           0 :       if (result.match_state_ == MatchState::UnableToMatch) {
      95           0 :         unable_to_match_some_matchers = true;
      96           0 :         continue;
      97           0 :       }
      98             : 
      99           0 :       if (result.result()) {
     100           0 :         return {MatchState::MatchComplete, true};
     101           0 :       }
     102           0 :     }
     103             : 
     104             :     // If we didn't find a successful match but not all matchers could be evaluated,
     105             :     // return UnableToMatch to defer the match result.
     106           0 :     if (unable_to_match_some_matchers) {
     107           0 :       return {MatchState::UnableToMatch, absl::nullopt};
     108           0 :     }
     109             : 
     110           0 :     return {MatchState::MatchComplete, false};
     111           0 :   }
     112             : 
     113             : private:
     114             :   const std::vector<FieldMatcherPtr<DataType>> matchers_;
     115             : };
     116             : 
     117             : /**
     118             :  * A FieldMatcher that returns the invert of a FieldMatcher.
     119             :  */
     120             : template <class DataType> class NotFieldMatcher : public FieldMatcher<DataType> {
     121             : public:
     122           0 :   explicit NotFieldMatcher(FieldMatcherPtr<DataType> matcher) : matcher_(std::move(matcher)) {}
     123             : 
     124           0 :   FieldMatchResult match(const DataType& data) override {
     125           0 :     const auto result = matcher_->match(data);
     126           0 :     if (result.match_state_ == MatchState::UnableToMatch) {
     127           0 :       return result;
     128           0 :     }
     129             : 
     130           0 :     return {MatchState::MatchComplete, !result.result()};
     131           0 :   }
     132             : 
     133             : private:
     134             :   const FieldMatcherPtr<DataType> matcher_;
     135             : };
     136             : 
     137             : /**
     138             :  * Implementation of a FieldMatcher that extracts an input value from the provided data and attempts
     139             :  * to match using an InputMatcher. absl::nullopt is returned whenever the data is not available or
     140             :  * if we failed to match and there is more data available.
     141             :  * A consequence of this is that if a match result is desired, care should be taken so that matching
     142             :  * is done with all the data available at some point.
     143             :  */
     144             : template <class DataType>
     145             : class SingleFieldMatcher : public FieldMatcher<DataType>, Logger::Loggable<Logger::Id::matcher> {
     146             : public:
     147             :   SingleFieldMatcher(DataInputPtr<DataType>&& data_input, InputMatcherPtr&& input_matcher)
     148           0 :       : data_input_(std::move(data_input)), input_matcher_(std::move(input_matcher)) {
     149           0 :     auto supported_input_types = input_matcher_->supportedDataInputTypes();
     150           0 :     if (supported_input_types.find(data_input_->dataInputType()) == supported_input_types.end()) {
     151           0 :       std::string supported_types =
     152           0 :           absl::StrJoin(supported_input_types.begin(), supported_input_types.end(), ", ");
     153           0 :       throwEnvoyExceptionOrPanic(
     154           0 :           absl::StrCat("Unsupported data input type: ", data_input_->dataInputType(),
     155           0 :                        ". The matcher supports input type: ", supported_types));
     156           0 :     }
     157           0 :   }
     158             : 
     159           0 :   FieldMatchResult match(const DataType& data) override {
     160           0 :     const auto input = data_input_->get(data);
     161             : 
     162           0 :     ENVOY_LOG(trace, "Attempting to match {}", input);
     163           0 :     if (input.data_availability_ == DataInputGetResult::DataAvailability::NotAvailable) {
     164           0 :       return {MatchState::UnableToMatch, absl::nullopt};
     165           0 :     }
     166             : 
     167           0 :     bool current_match = input_matcher_->match(input.data_);
     168           0 :     if (!current_match && input.data_availability_ ==
     169           0 :                               DataInputGetResult::DataAvailability::MoreDataMightBeAvailable) {
     170           0 :       ENVOY_LOG(trace, "No match yet; delaying result as more data might be available.");
     171           0 :       return {MatchState::UnableToMatch, absl::nullopt};
     172           0 :     }
     173             : 
     174           0 :     ENVOY_LOG(trace, "Match result: {}", current_match);
     175             : 
     176           0 :     return {MatchState::MatchComplete, current_match};
     177           0 :   }
     178             : 
     179             : private:
     180             :   const DataInputPtr<DataType> data_input_;
     181             :   const InputMatcherPtr input_matcher_;
     182             : };
     183             : 
     184             : template <class DataType>
     185             : using SingleFieldMatcherPtr = std::unique_ptr<SingleFieldMatcher<DataType>>;
     186             : } // namespace Matcher
     187             : } // namespace Envoy

Generated by: LCOV version 1.15