Line data Source code
1 : #pragma once 2 : 3 : #include <string> 4 : 5 : #include "envoy/matcher/matcher.h" 6 : 7 : namespace Envoy { 8 : namespace Matcher { 9 : 10 : /** 11 : * Implementation of a map matcher which performs matches against the data provided by DataType. 12 : * If the match could not be completed, {MatchState::UnableToMatch, {}} will be returned. If the 13 : * match result was determined, {MatchState::MatchComplete, OnMatch} will be returned. If a match 14 : * result was determined to be no match, {MatchState::MatchComplete, {}} will be returned. 15 : */ 16 : template <class DataType> 17 : class MapMatcher : public MatchTree<DataType>, Logger::Loggable<Logger::Id::matcher> { 18 : public: 19 : MapMatcher(DataInputPtr<DataType>&& data_input, absl::optional<OnMatch<DataType>> on_no_match) 20 0 : : data_input_(std::move(data_input)), on_no_match_(std::move(on_no_match)) { 21 0 : auto input_type = data_input_->dataInputType(); 22 0 : if (input_type != DefaultMatchingDataType) { 23 0 : throwEnvoyExceptionOrPanic( 24 0 : absl::StrCat("Unsupported data input type: ", input_type, 25 0 : ", currently only string type is supported in map matcher")); 26 0 : } 27 0 : } 28 : 29 : // Adds a child to the map. 30 : virtual void addChild(std::string value, OnMatch<DataType>&& on_match) PURE; 31 : 32 0 : typename MatchTree<DataType>::MatchResult match(const DataType& data) override { 33 0 : const auto input = data_input_->get(data); 34 0 : ENVOY_LOG(trace, "Attempting to match {}", input); 35 0 : if (input.data_availability_ == DataInputGetResult::DataAvailability::NotAvailable) { 36 0 : return {MatchState::UnableToMatch, absl::nullopt}; 37 0 : } 38 : 39 : // Returns `on_no_match` when input data is empty. (i.e., is absl::monostate). 40 0 : if (absl::holds_alternative<absl::monostate>(input.data_)) { 41 0 : return {MatchState::MatchComplete, on_no_match_}; 42 0 : } 43 : 44 0 : const auto result = doMatch(absl::get<std::string>(input.data_)); 45 0 : if (result) { 46 0 : if (result->matcher_) { 47 0 : return result->matcher_->match(data); 48 0 : } else { 49 0 : return {MatchState::MatchComplete, OnMatch<DataType>{result->action_cb_, nullptr}}; 50 0 : } 51 0 : } else if (input.data_availability_ == 52 0 : DataInputGetResult::DataAvailability::MoreDataMightBeAvailable) { 53 : // It's possible that we were attempting a lookup with a partial value, so delay matching 54 : // until we know that we actually failed. 55 0 : return {MatchState::UnableToMatch, absl::nullopt}; 56 0 : } 57 : 58 0 : return {MatchState::MatchComplete, on_no_match_}; 59 0 : } 60 : 61 : protected: 62 : const DataInputPtr<DataType> data_input_; 63 : const absl::optional<OnMatch<DataType>> on_no_match_; 64 : 65 : // The inner match method. Attempts to match against the resulting data string. If the match 66 : // result was determined, the OnMatch will be returned. If a match result was determined to be no 67 : // match, {} will be returned. 68 : virtual absl::optional<OnMatch<DataType>> doMatch(const std::string& data) PURE; 69 : }; 70 : 71 : } // namespace Matcher 72 : } // namespace Envoy