summaryrefslogtreecommitdiff
path: root/grpc/src/core/lib/matchers/matchers.h
blob: af2ce59bf18d135ce54aa4133304e81d5736877d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright 2021 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef GRPC_CORE_LIB_MATCHERS_MATCHERS_H
#define GRPC_CORE_LIB_MATCHERS_MATCHERS_H

#include <grpc/support/port_platform.h>

#include <memory>
#include <string>

#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"

#include "re2/re2.h"

namespace grpc_core {

class StringMatcher {
 public:
  enum class Type {
    kExact,      // value stored in string_matcher_ field
    kPrefix,     // value stored in string_matcher_ field
    kSuffix,     // value stored in string_matcher_ field
    kSafeRegex,  // pattern stored in regex_matcher_ field
    kContains,   // value stored in string_matcher_ field
  };

  // Creates StringMatcher instance. Returns error status on failure.
  static absl::StatusOr<StringMatcher> Create(Type type,
                                              absl::string_view matcher,
                                              bool case_sensitive = true);

  StringMatcher() = default;
  StringMatcher(const StringMatcher& other);
  StringMatcher& operator=(const StringMatcher& other);
  StringMatcher(StringMatcher&& other) noexcept;
  StringMatcher& operator=(StringMatcher&& other) noexcept;
  bool operator==(const StringMatcher& other) const;

  bool Match(absl::string_view value) const;

  std::string ToString() const;

  Type type() const { return type_; }

  // Valid for kExact, kPrefix, kSuffix and kContains.
  const std::string& string_matcher() const { return string_matcher_; }

  // Valid for kSafeRegex.
  RE2* regex_matcher() const { return regex_matcher_.get(); }

  bool case_sensitive() const { return case_sensitive_; }

 private:
  StringMatcher(Type type, absl::string_view matcher, bool case_sensitive);
  StringMatcher(std::unique_ptr<RE2> regex_matcher, bool case_sensitive);

  Type type_ = Type::kExact;
  std::string string_matcher_;
  std::unique_ptr<RE2> regex_matcher_;
  bool case_sensitive_ = true;
};

class HeaderMatcher {
 public:
  enum class Type {
    kExact,      // value stored in StringMatcher field
    kPrefix,     // value stored in StringMatcher field
    kSuffix,     // value stored in StringMatcher field
    kSafeRegex,  // value stored in StringMatcher field
    kContains,   // value stored in StringMatcher field
    kRange,      // uses range_start and range_end fields
    kPresent,    // uses present_match field
  };

  // Make sure that the first five HeaderMatcher::Type enum values match up to
  // the corresponding StringMatcher::Type enum values, so that it's safe to
  // convert by casting when delegating to StringMatcher.
  static_assert(static_cast<StringMatcher::Type>(Type::kExact) ==
                    StringMatcher::Type::kExact,
                "");
  static_assert(static_cast<StringMatcher::Type>(Type::kPrefix) ==
                    StringMatcher::Type::kPrefix,
                "");
  static_assert(static_cast<StringMatcher::Type>(Type::kSuffix) ==
                    StringMatcher::Type::kSuffix,
                "");
  static_assert(static_cast<StringMatcher::Type>(Type::kSafeRegex) ==
                    StringMatcher::Type::kSafeRegex,
                "");
  static_assert(static_cast<StringMatcher::Type>(Type::kContains) ==
                    StringMatcher::Type::kContains,
                "");

  // Creates HeaderMatcher instance. Returns error status on failure.
  static absl::StatusOr<HeaderMatcher> Create(absl::string_view name, Type type,
                                              absl::string_view matcher,
                                              int64_t range_start = 0,
                                              int64_t range_end = 0,
                                              bool present_match = false,
                                              bool invert_match = false);

  HeaderMatcher() = default;
  HeaderMatcher(const HeaderMatcher& other);
  HeaderMatcher& operator=(const HeaderMatcher& other);
  HeaderMatcher(HeaderMatcher&& other) noexcept;
  HeaderMatcher& operator=(HeaderMatcher&& other) noexcept;
  bool operator==(const HeaderMatcher& other) const;

  const std::string& name() const { return name_; }

  Type type() const { return type_; }

  // Valid for kExact, kPrefix, kSuffix and kContains.
  const std::string& string_matcher() const {
    return matcher_.string_matcher();
  }

  // Valid for kSafeRegex.
  RE2* regex_matcher() const { return matcher_.regex_matcher(); }

  bool Match(const absl::optional<absl::string_view>& value) const;

  std::string ToString() const;

 private:
  // For StringMatcher.
  HeaderMatcher(absl::string_view name, Type type, StringMatcher matcher,
                bool invert_match);
  // For RangeMatcher.
  HeaderMatcher(absl::string_view name, int64_t range_start, int64_t range_end,
                bool invert_match);
  // For PresentMatcher.
  HeaderMatcher(absl::string_view name, bool present_match, bool invert_match);

  std::string name_;
  Type type_ = Type::kExact;
  StringMatcher matcher_;
  int64_t range_start_;
  int64_t range_end_;
  bool present_match_;
  bool invert_match_ = false;
};

}  // namespace grpc_core

#endif /* GRPC_CORE_LIB_MATCHERS_MATCHERS_H */