1
#pragma once
2

            
3
#include "envoy/matcher/matcher.h"
4

            
5
#include "source/common/matcher/field_matcher.h"
6

            
7
namespace Envoy {
8
namespace Matcher {
9

            
10
/**
11
 * A match tree that iterates over a list of matchers to find the first one that matches. If one
12
 * does, the ActionMatchResult will be the one specified by the individual matcher.
13
 */
14
template <class DataType> class ListMatcher : public MatchTree<DataType> {
15
public:
16
591
  explicit ListMatcher(absl::optional<OnMatch<DataType>> on_no_match) : on_no_match_(on_no_match) {}
17

            
18
  ActionMatchResult match(const DataType& matching_data,
19
1403
                          SkippedMatchCb skipped_match_cb = nullptr) override {
20
2440
    for (const auto& matcher : matchers_) {
21
2440
      MatchResult result = matcher.first->match(matching_data);
22

            
23
      // One of the matchers don't have enough information, bail on evaluating the match.
24
2440
      if (result == MatchResult::InsufficientData) {
25
14
        return ActionMatchResult::insufficientData();
26
14
      }
27
2426
      if (result == MatchResult::NoMatch) {
28
1616
        continue;
29
1616
      }
30

            
31
810
      ActionMatchResult processed_result = MatchTree<DataType>::handleRecursionAndSkips(
32
810
          matcher.second, matching_data, skipped_match_cb);
33
      // Continue to next matcher if the result is a no-match or is skipped.
34
810
      if (processed_result.isNoMatch()) {
35
30
        continue;
36
30
      }
37
780
      return processed_result;
38
810
    }
39

            
40
    // Return on-no-match, after keep_matching and/or recursion handling.
41
609
    return MatchTree<DataType>::handleRecursionAndSkips(on_no_match_, matching_data,
42
609
                                                        skipped_match_cb);
43
1403
  }
44

            
45
1021
  void addMatcher(FieldMatcherPtr<DataType>&& matcher, OnMatch<DataType> action) {
46
1021
    matchers_.emplace_back(std::move(matcher), std::move(action));
47
1021
  }
48

            
49
private:
50
  absl::optional<OnMatch<DataType>> on_no_match_;
51
  std::vector<std::pair<FieldMatcherPtr<DataType>, OnMatch<DataType>>> matchers_;
52
};
53

            
54
} // namespace Matcher
55
} // namespace Envoy