Coverage Report

Created: 2026-05-27 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/internal/message_equality.cc
Line
Count
Source
1
// Copyright 2024 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include "internal/message_equality.h"
16
17
#include <cstddef>
18
#include <cstdint>
19
#include <functional>
20
#include <limits>
21
#include <memory>
22
#include <string>
23
#include <type_traits>
24
25
#include "absl/base/attributes.h"
26
#include "absl/base/nullability.h"
27
#include "absl/base/optimization.h"
28
#include "absl/functional/overload.h"
29
#include "absl/log/absl_check.h"
30
#include "absl/status/status.h"
31
#include "absl/status/statusor.h"
32
#include "absl/strings/str_cat.h"
33
#include "absl/strings/string_view.h"
34
#include "absl/time/time.h"
35
#include "absl/types/variant.h"
36
#include "common/memory.h"
37
#include "extensions/protobuf/internal/map_reflection.h"
38
#include "internal/json.h"
39
#include "internal/number.h"
40
#include "internal/status_macros.h"
41
#include "internal/well_known_types.h"
42
#include "google/protobuf/arena.h"
43
#include "google/protobuf/descriptor.h"
44
#include "google/protobuf/message.h"
45
#include "google/protobuf/util/message_differencer.h"
46
47
#undef GetMessage
48
49
namespace cel::internal {
50
51
namespace {
52
53
using ::cel::extensions::protobuf_internal::ConstMapBegin;
54
using ::cel::extensions::protobuf_internal::ConstMapEnd;
55
using ::cel::extensions::protobuf_internal::LookupMapValue;
56
using ::cel::extensions::protobuf_internal::MapSize;
57
using ::google::protobuf::Descriptor;
58
using ::google::protobuf::DescriptorPool;
59
using ::google::protobuf::FieldDescriptor;
60
using ::google::protobuf::Message;
61
using ::google::protobuf::MessageFactory;
62
using ::google::protobuf::util::MessageDifferencer;
63
64
class EquatableListValue final
65
    : public std::reference_wrapper<const google::protobuf::Message> {
66
 public:
67
  using std::reference_wrapper<const google::protobuf::Message>::reference_wrapper;
68
};
69
70
class EquatableStruct final
71
    : public std::reference_wrapper<const google::protobuf::Message> {
72
 public:
73
  using std::reference_wrapper<const google::protobuf::Message>::reference_wrapper;
74
};
75
76
class EquatableAny final
77
    : public std::reference_wrapper<const google::protobuf::Message> {
78
 public:
79
  using std::reference_wrapper<const google::protobuf::Message>::reference_wrapper;
80
};
81
82
class EquatableMessage final
83
    : public std::reference_wrapper<const google::protobuf::Message> {
84
 public:
85
  using std::reference_wrapper<const google::protobuf::Message>::reference_wrapper;
86
};
87
88
using EquatableValue =
89
    std::variant<std::nullptr_t, bool, int64_t, uint64_t, double,
90
                 well_known_types::BytesValue, well_known_types::StringValue,
91
                 absl::Duration, absl::Time, EquatableListValue,
92
                 EquatableStruct, EquatableAny, EquatableMessage>;
93
94
struct NullValueEqualer {
95
0
  bool operator()(std::nullptr_t, std::nullptr_t) const { return true; }
96
97
  template <typename T>
98
  std::enable_if_t<std::negation_v<std::is_same<std::nullptr_t, T>>, bool>
99
0
  operator()(std::nullptr_t, const T&) const {
100
0
    return false;
101
0
  }
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116NullValueEqualerclIbEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIDnT_EEEEbE4typeEDnRKS7_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116NullValueEqualerclIlEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIDnT_EEEEbE4typeEDnRKS7_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116NullValueEqualerclImEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIDnT_EEEEbE4typeEDnRKS7_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116NullValueEqualerclIdEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIDnT_EEEEbE4typeEDnRKS7_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116NullValueEqualerclINS_16well_known_types10BytesValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameIDnT_EEEEbE4typeEDnRKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116NullValueEqualerclINS_16well_known_types11StringValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameIDnT_EEEEbE4typeEDnRKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116NullValueEqualerclIN4absl12lts_202601078DurationEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameIDnT_EEEEbE4typeEDnRKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116NullValueEqualerclIN4absl12lts_202601074TimeEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameIDnT_EEEEbE4typeEDnRKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116NullValueEqualerclINS1_18EquatableListValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIDnT_EEEEbE4typeEDnRKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116NullValueEqualerclINS1_15EquatableStructEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIDnT_EEEEbE4typeEDnRKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116NullValueEqualerclINS1_12EquatableAnyEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIDnT_EEEEbE4typeEDnRKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116NullValueEqualerclINS1_16EquatableMessageEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIDnT_EEEEbE4typeEDnRKS8_
102
};
103
104
struct BoolValueEqualer {
105
0
  bool operator()(bool lhs, bool rhs) const { return lhs == rhs; }
106
107
  template <typename T>
108
  std::enable_if_t<std::negation_v<std::is_same<bool, T>>, bool> operator()(
109
0
      bool, const T&) const {
110
0
    return false;
111
0
  }
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116BoolValueEqualerclIDnEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIbT_EEEEbE4typeEbRKS7_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116BoolValueEqualerclIlEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIbT_EEEEbE4typeEbRKS7_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116BoolValueEqualerclImEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIbT_EEEEbE4typeEbRKS7_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116BoolValueEqualerclIdEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIbT_EEEEbE4typeEbRKS7_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116BoolValueEqualerclINS_16well_known_types10BytesValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameIbT_EEEEbE4typeEbRKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116BoolValueEqualerclINS_16well_known_types11StringValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameIbT_EEEEbE4typeEbRKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116BoolValueEqualerclIN4absl12lts_202601078DurationEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameIbT_EEEEbE4typeEbRKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116BoolValueEqualerclIN4absl12lts_202601074TimeEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameIbT_EEEEbE4typeEbRKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116BoolValueEqualerclINS1_18EquatableListValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIbT_EEEEbE4typeEbRKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116BoolValueEqualerclINS1_15EquatableStructEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIbT_EEEEbE4typeEbRKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116BoolValueEqualerclINS1_12EquatableAnyEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIbT_EEEEbE4typeEbRKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116BoolValueEqualerclINS1_16EquatableMessageEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIbT_EEEEbE4typeEbRKS8_
112
};
113
114
struct BytesValueEqualer {
115
  bool operator()(const well_known_types::BytesValue& lhs,
116
0
                  const well_known_types::BytesValue& rhs) const {
117
0
    return lhs == rhs;
118
0
  }
119
120
  template <typename T>
121
  std::enable_if_t<
122
      std::negation_v<std::is_same<well_known_types::BytesValue, T>>, bool>
123
0
  operator()(const well_known_types::BytesValue&, const T&) const {
124
0
    return false;
125
0
  }
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_117BytesValueEqualerclIDnEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS_16well_known_types10BytesValueET_EEEEbE4typeERKS8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_117BytesValueEqualerclIbEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS_16well_known_types10BytesValueET_EEEEbE4typeERKS8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_117BytesValueEqualerclIlEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS_16well_known_types10BytesValueET_EEEEbE4typeERKS8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_117BytesValueEqualerclImEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS_16well_known_types10BytesValueET_EEEEbE4typeERKS8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_117BytesValueEqualerclIdEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS_16well_known_types10BytesValueET_EEEEbE4typeERKS8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_117BytesValueEqualerclINS_16well_known_types11StringValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameINS4_10BytesValueET_EEEEbE4typeERKS9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_117BytesValueEqualerclIN4absl12lts_202601078DurationEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS_16well_known_types10BytesValueET_EEEEbE4typeERKSB_RKSC_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_117BytesValueEqualerclIN4absl12lts_202601074TimeEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS_16well_known_types10BytesValueET_EEEEbE4typeERKSB_RKSC_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_117BytesValueEqualerclINS1_18EquatableListValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS_16well_known_types10BytesValueET_EEEEbE4typeERKS9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_117BytesValueEqualerclINS1_15EquatableStructEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS_16well_known_types10BytesValueET_EEEEbE4typeERKS9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_117BytesValueEqualerclINS1_12EquatableAnyEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS_16well_known_types10BytesValueET_EEEEbE4typeERKS9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_117BytesValueEqualerclINS1_16EquatableMessageEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS_16well_known_types10BytesValueET_EEEEbE4typeERKS9_RKSA_
126
};
127
128
struct IntValueEqualer {
129
0
  bool operator()(int64_t lhs, int64_t rhs) const { return lhs == rhs; }
130
131
0
  bool operator()(int64_t lhs, uint64_t rhs) const {
132
0
    return Number::FromInt64(lhs) == Number::FromUint64(rhs);
133
0
  }
134
135
0
  bool operator()(int64_t lhs, double rhs) const {
136
0
    return Number::FromInt64(lhs) == Number::FromDouble(rhs);
137
0
  }
138
139
  template <typename T>
140
  std::enable_if_t<std::conjunction_v<std::negation<std::is_same<int64_t, T>>,
141
                                      std::negation<std::is_same<uint64_t, T>>,
142
                                      std::negation<std::is_same<double, T>>>,
143
                   bool>
144
0
  operator()(int64_t, const T&) const {
145
0
    return false;
146
0
  }
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115IntValueEqualerclIDnEENSt3__19enable_ifIXsr3stdE13conjunction_vINS4_8negationINS4_7is_sameIlT_EEEENS6_INS7_ImS8_EEEENS6_INS7_IdS8_EEEEEEbE4typeElRKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115IntValueEqualerclIbEENSt3__19enable_ifIXsr3stdE13conjunction_vINS4_8negationINS4_7is_sameIlT_EEEENS6_INS7_ImS8_EEEENS6_INS7_IdS8_EEEEEEbE4typeElRKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115IntValueEqualerclINS_16well_known_types10BytesValueEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS6_8negationINS6_7is_sameIlT_EEEENS8_INS9_ImSA_EEEENS8_INS9_IdSA_EEEEEEbE4typeElRKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115IntValueEqualerclINS_16well_known_types11StringValueEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS6_8negationINS6_7is_sameIlT_EEEENS8_INS9_ImSA_EEEENS8_INS9_IdSA_EEEEEEbE4typeElRKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115IntValueEqualerclIN4absl12lts_202601078DurationEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS7_8negationINS7_7is_sameIlT_EEEENS9_INSA_ImSB_EEEENS9_INSA_IdSB_EEEEEEbE4typeElRKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115IntValueEqualerclIN4absl12lts_202601074TimeEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS7_8negationINS7_7is_sameIlT_EEEENS9_INSA_ImSB_EEEENS9_INSA_IdSB_EEEEEEbE4typeElRKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115IntValueEqualerclINS1_18EquatableListValueEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS5_8negationINS5_7is_sameIlT_EEEENS7_INS8_ImS9_EEEENS7_INS8_IdS9_EEEEEEbE4typeElRKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115IntValueEqualerclINS1_15EquatableStructEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS5_8negationINS5_7is_sameIlT_EEEENS7_INS8_ImS9_EEEENS7_INS8_IdS9_EEEEEEbE4typeElRKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115IntValueEqualerclINS1_12EquatableAnyEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS5_8negationINS5_7is_sameIlT_EEEENS7_INS8_ImS9_EEEENS7_INS8_IdS9_EEEEEEbE4typeElRKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115IntValueEqualerclINS1_16EquatableMessageEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS5_8negationINS5_7is_sameIlT_EEEENS7_INS8_ImS9_EEEENS7_INS8_IdS9_EEEEEEbE4typeElRKS9_
147
};
148
149
struct UintValueEqualer {
150
0
  bool operator()(uint64_t lhs, int64_t rhs) const {
151
0
    return Number::FromUint64(lhs) == Number::FromInt64(rhs);
152
0
  }
153
154
0
  bool operator()(uint64_t lhs, uint64_t rhs) const { return lhs == rhs; }
155
156
0
  bool operator()(uint64_t lhs, double rhs) const {
157
0
    return Number::FromUint64(lhs) == Number::FromDouble(rhs);
158
0
  }
159
160
  template <typename T>
161
  std::enable_if_t<std::conjunction_v<std::negation<std::is_same<int64_t, T>>,
162
                                      std::negation<std::is_same<uint64_t, T>>,
163
                                      std::negation<std::is_same<double, T>>>,
164
                   bool>
165
0
  operator()(uint64_t, const T&) const {
166
0
    return false;
167
0
  }
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116UintValueEqualerclIDnEENSt3__19enable_ifIXsr3stdE13conjunction_vINS4_8negationINS4_7is_sameIlT_EEEENS6_INS7_ImS8_EEEENS6_INS7_IdS8_EEEEEEbE4typeEmRKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116UintValueEqualerclIbEENSt3__19enable_ifIXsr3stdE13conjunction_vINS4_8negationINS4_7is_sameIlT_EEEENS6_INS7_ImS8_EEEENS6_INS7_IdS8_EEEEEEbE4typeEmRKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116UintValueEqualerclINS_16well_known_types10BytesValueEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS6_8negationINS6_7is_sameIlT_EEEENS8_INS9_ImSA_EEEENS8_INS9_IdSA_EEEEEEbE4typeEmRKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116UintValueEqualerclINS_16well_known_types11StringValueEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS6_8negationINS6_7is_sameIlT_EEEENS8_INS9_ImSA_EEEENS8_INS9_IdSA_EEEEEEbE4typeEmRKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116UintValueEqualerclIN4absl12lts_202601078DurationEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS7_8negationINS7_7is_sameIlT_EEEENS9_INSA_ImSB_EEEENS9_INSA_IdSB_EEEEEEbE4typeEmRKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116UintValueEqualerclIN4absl12lts_202601074TimeEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS7_8negationINS7_7is_sameIlT_EEEENS9_INSA_ImSB_EEEENS9_INSA_IdSB_EEEEEEbE4typeEmRKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116UintValueEqualerclINS1_18EquatableListValueEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS5_8negationINS5_7is_sameIlT_EEEENS7_INS8_ImS9_EEEENS7_INS8_IdS9_EEEEEEbE4typeEmRKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116UintValueEqualerclINS1_15EquatableStructEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS5_8negationINS5_7is_sameIlT_EEEENS7_INS8_ImS9_EEEENS7_INS8_IdS9_EEEEEEbE4typeEmRKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116UintValueEqualerclINS1_12EquatableAnyEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS5_8negationINS5_7is_sameIlT_EEEENS7_INS8_ImS9_EEEENS7_INS8_IdS9_EEEEEEbE4typeEmRKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116UintValueEqualerclINS1_16EquatableMessageEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS5_8negationINS5_7is_sameIlT_EEEENS7_INS8_ImS9_EEEENS7_INS8_IdS9_EEEEEEbE4typeEmRKS9_
168
};
169
170
struct DoubleValueEqualer {
171
0
  bool operator()(double lhs, int64_t rhs) const {
172
0
    return Number::FromDouble(lhs) == Number::FromInt64(rhs);
173
0
  }
174
175
0
  bool operator()(double lhs, uint64_t rhs) const {
176
0
    return Number::FromDouble(lhs) == Number::FromUint64(rhs);
177
0
  }
178
179
0
  bool operator()(double lhs, double rhs) const { return lhs == rhs; }
180
181
  template <typename T>
182
  std::enable_if_t<std::conjunction_v<std::negation<std::is_same<int64_t, T>>,
183
                                      std::negation<std::is_same<uint64_t, T>>,
184
                                      std::negation<std::is_same<double, T>>>,
185
                   bool>
186
0
  operator()(double, const T&) const {
187
0
    return false;
188
0
  }
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118DoubleValueEqualerclIDnEENSt3__19enable_ifIXsr3stdE13conjunction_vINS4_8negationINS4_7is_sameIlT_EEEENS6_INS7_ImS8_EEEENS6_INS7_IdS8_EEEEEEbE4typeEdRKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118DoubleValueEqualerclIbEENSt3__19enable_ifIXsr3stdE13conjunction_vINS4_8negationINS4_7is_sameIlT_EEEENS6_INS7_ImS8_EEEENS6_INS7_IdS8_EEEEEEbE4typeEdRKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118DoubleValueEqualerclINS_16well_known_types10BytesValueEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS6_8negationINS6_7is_sameIlT_EEEENS8_INS9_ImSA_EEEENS8_INS9_IdSA_EEEEEEbE4typeEdRKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118DoubleValueEqualerclINS_16well_known_types11StringValueEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS6_8negationINS6_7is_sameIlT_EEEENS8_INS9_ImSA_EEEENS8_INS9_IdSA_EEEEEEbE4typeEdRKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118DoubleValueEqualerclIN4absl12lts_202601078DurationEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS7_8negationINS7_7is_sameIlT_EEEENS9_INSA_ImSB_EEEENS9_INSA_IdSB_EEEEEEbE4typeEdRKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118DoubleValueEqualerclIN4absl12lts_202601074TimeEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS7_8negationINS7_7is_sameIlT_EEEENS9_INSA_ImSB_EEEENS9_INSA_IdSB_EEEEEEbE4typeEdRKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118DoubleValueEqualerclINS1_18EquatableListValueEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS5_8negationINS5_7is_sameIlT_EEEENS7_INS8_ImS9_EEEENS7_INS8_IdS9_EEEEEEbE4typeEdRKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118DoubleValueEqualerclINS1_15EquatableStructEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS5_8negationINS5_7is_sameIlT_EEEENS7_INS8_ImS9_EEEENS7_INS8_IdS9_EEEEEEbE4typeEdRKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118DoubleValueEqualerclINS1_12EquatableAnyEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS5_8negationINS5_7is_sameIlT_EEEENS7_INS8_ImS9_EEEENS7_INS8_IdS9_EEEEEEbE4typeEdRKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118DoubleValueEqualerclINS1_16EquatableMessageEEENSt3__19enable_ifIXsr3stdE13conjunction_vINS5_8negationINS5_7is_sameIlT_EEEENS7_INS8_ImS9_EEEENS7_INS8_IdS9_EEEEEEbE4typeEdRKS9_
189
};
190
191
struct StringValueEqualer {
192
  bool operator()(const well_known_types::StringValue& lhs,
193
0
                  const well_known_types::StringValue& rhs) const {
194
0
    return lhs == rhs;
195
0
  }
196
197
  template <typename T>
198
  std::enable_if_t<
199
      std::negation_v<std::is_same<well_known_types::StringValue, T>>, bool>
200
0
  operator()(const well_known_types::StringValue&, const T&) const {
201
0
    return false;
202
0
  }
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118StringValueEqualerclIDnEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS_16well_known_types11StringValueET_EEEEbE4typeERKS8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118StringValueEqualerclIbEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS_16well_known_types11StringValueET_EEEEbE4typeERKS8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118StringValueEqualerclIlEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS_16well_known_types11StringValueET_EEEEbE4typeERKS8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118StringValueEqualerclImEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS_16well_known_types11StringValueET_EEEEbE4typeERKS8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118StringValueEqualerclIdEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS_16well_known_types11StringValueET_EEEEbE4typeERKS8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118StringValueEqualerclINS_16well_known_types10BytesValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameINS4_11StringValueET_EEEEbE4typeERKS9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118StringValueEqualerclIN4absl12lts_202601078DurationEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS_16well_known_types11StringValueET_EEEEbE4typeERKSB_RKSC_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118StringValueEqualerclIN4absl12lts_202601074TimeEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS_16well_known_types11StringValueET_EEEEbE4typeERKSB_RKSC_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118StringValueEqualerclINS1_18EquatableListValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS_16well_known_types11StringValueET_EEEEbE4typeERKS9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118StringValueEqualerclINS1_15EquatableStructEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS_16well_known_types11StringValueET_EEEEbE4typeERKS9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118StringValueEqualerclINS1_12EquatableAnyEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS_16well_known_types11StringValueET_EEEEbE4typeERKS9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_118StringValueEqualerclINS1_16EquatableMessageEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS_16well_known_types11StringValueET_EEEEbE4typeERKS9_RKSA_
203
};
204
205
struct DurationEqualer {
206
0
  bool operator()(absl::Duration lhs, absl::Duration rhs) const {
207
0
    return lhs == rhs;
208
0
  }
209
210
  template <typename T>
211
  std::enable_if_t<std::negation_v<std::is_same<absl::Duration, T>>, bool>
212
0
  operator()(absl::Duration, const T&) const {
213
0
    return false;
214
0
  }
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115DurationEqualerclIDnEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIN4absl12lts_202601078DurationET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115DurationEqualerclIbEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIN4absl12lts_202601078DurationET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115DurationEqualerclIlEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIN4absl12lts_202601078DurationET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115DurationEqualerclImEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIN4absl12lts_202601078DurationET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115DurationEqualerclIdEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIN4absl12lts_202601078DurationET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115DurationEqualerclINS_16well_known_types10BytesValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameIN4absl12lts_202601078DurationET_EEEEbE4typeESB_RKSC_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115DurationEqualerclINS_16well_known_types11StringValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameIN4absl12lts_202601078DurationET_EEEEbE4typeESB_RKSC_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115DurationEqualerclIN4absl12lts_202601074TimeEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS5_8DurationET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115DurationEqualerclINS1_18EquatableListValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIN4absl12lts_202601078DurationET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115DurationEqualerclINS1_15EquatableStructEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIN4absl12lts_202601078DurationET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115DurationEqualerclINS1_12EquatableAnyEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIN4absl12lts_202601078DurationET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_115DurationEqualerclINS1_16EquatableMessageEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIN4absl12lts_202601078DurationET_EEEEbE4typeESA_RKSB_
215
};
216
217
struct TimestampEqualer {
218
0
  bool operator()(absl::Time lhs, absl::Time rhs) const { return lhs == rhs; }
219
220
  template <typename T>
221
  std::enable_if_t<std::negation_v<std::is_same<absl::Time, T>>, bool>
222
0
  operator()(absl::Time, const T&) const {
223
0
    return false;
224
0
  }
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116TimestampEqualerclIDnEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIN4absl12lts_202601074TimeET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116TimestampEqualerclIbEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIN4absl12lts_202601074TimeET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116TimestampEqualerclIlEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIN4absl12lts_202601074TimeET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116TimestampEqualerclImEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIN4absl12lts_202601074TimeET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116TimestampEqualerclIdEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameIN4absl12lts_202601074TimeET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116TimestampEqualerclINS_16well_known_types10BytesValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameIN4absl12lts_202601074TimeET_EEEEbE4typeESB_RKSC_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116TimestampEqualerclINS_16well_known_types11StringValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameIN4absl12lts_202601074TimeET_EEEEbE4typeESB_RKSC_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116TimestampEqualerclIN4absl12lts_202601078DurationEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS5_4TimeET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116TimestampEqualerclINS1_18EquatableListValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIN4absl12lts_202601074TimeET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116TimestampEqualerclINS1_15EquatableStructEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIN4absl12lts_202601074TimeET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116TimestampEqualerclINS1_12EquatableAnyEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIN4absl12lts_202601074TimeET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116TimestampEqualerclINS1_16EquatableMessageEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameIN4absl12lts_202601074TimeET_EEEEbE4typeESA_RKSB_
225
};
226
227
struct ListValueEqualer {
228
0
  bool operator()(EquatableListValue lhs, EquatableListValue rhs) const {
229
0
    return JsonListEquals(lhs, rhs);
230
0
  }
231
232
  template <typename T>
233
  std::enable_if_t<std::negation_v<std::is_same<EquatableListValue, T>>, bool>
234
0
  operator()(EquatableListValue, const T&) const {
235
0
    return false;
236
0
  }
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116ListValueEqualerclIDnEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_18EquatableListValueET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116ListValueEqualerclIbEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_18EquatableListValueET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116ListValueEqualerclIlEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_18EquatableListValueET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116ListValueEqualerclImEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_18EquatableListValueET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116ListValueEqualerclIdEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_18EquatableListValueET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116ListValueEqualerclINS_16well_known_types10BytesValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameINS1_18EquatableListValueET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116ListValueEqualerclINS_16well_known_types11StringValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameINS1_18EquatableListValueET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116ListValueEqualerclIN4absl12lts_202601078DurationEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS1_18EquatableListValueET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116ListValueEqualerclIN4absl12lts_202601074TimeEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS1_18EquatableListValueET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116ListValueEqualerclINS1_15EquatableStructEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS1_18EquatableListValueET_EEEEbE4typeES8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116ListValueEqualerclINS1_12EquatableAnyEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS1_18EquatableListValueET_EEEEbE4typeES8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_116ListValueEqualerclINS1_16EquatableMessageEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS1_18EquatableListValueET_EEEEbE4typeES8_RKS9_
237
};
238
239
struct StructEqualer {
240
0
  bool operator()(EquatableStruct lhs, EquatableStruct rhs) const {
241
0
    return JsonMapEquals(lhs, rhs);
242
0
  }
243
244
  template <typename T>
245
  std::enable_if_t<std::negation_v<std::is_same<EquatableStruct, T>>, bool>
246
0
  operator()(EquatableStruct, const T&) const {
247
0
    return false;
248
0
  }
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_113StructEqualerclIDnEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_15EquatableStructET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_113StructEqualerclIbEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_15EquatableStructET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_113StructEqualerclIlEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_15EquatableStructET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_113StructEqualerclImEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_15EquatableStructET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_113StructEqualerclIdEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_15EquatableStructET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_113StructEqualerclINS_16well_known_types10BytesValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameINS1_15EquatableStructET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_113StructEqualerclINS_16well_known_types11StringValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameINS1_15EquatableStructET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_113StructEqualerclIN4absl12lts_202601078DurationEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS1_15EquatableStructET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_113StructEqualerclIN4absl12lts_202601074TimeEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS1_15EquatableStructET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_113StructEqualerclINS1_18EquatableListValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS1_15EquatableStructET_EEEEbE4typeES8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_113StructEqualerclINS1_12EquatableAnyEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS1_15EquatableStructET_EEEEbE4typeES8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_113StructEqualerclINS1_16EquatableMessageEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS1_15EquatableStructET_EEEEbE4typeES8_RKS9_
249
};
250
251
struct AnyEqualer {
252
0
  bool operator()(EquatableAny lhs, EquatableAny rhs) const {
253
0
    auto lhs_reflection =
254
0
        well_known_types::GetAnyReflectionOrDie(lhs.get().GetDescriptor());
255
0
    std::string lhs_type_url_scratch;
256
0
    std::string lhs_value_scratch;
257
0
    auto rhs_reflection =
258
0
        well_known_types::GetAnyReflectionOrDie(rhs.get().GetDescriptor());
259
0
    std::string rhs_type_url_scratch;
260
0
    std::string rhs_value_scratch;
261
0
    return lhs_reflection.GetTypeUrl(lhs.get(), lhs_type_url_scratch) ==
262
0
               rhs_reflection.GetTypeUrl(rhs.get(), rhs_type_url_scratch) &&
263
0
           lhs_reflection.GetValue(lhs.get(), lhs_value_scratch) ==
264
0
               rhs_reflection.GetValue(rhs.get(), rhs_value_scratch);
265
0
  }
266
267
  template <typename T>
268
  std::enable_if_t<std::negation_v<std::is_same<EquatableAny, T>>, bool>
269
0
  operator()(EquatableAny, const T&) const {
270
0
    return false;
271
0
  }
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_110AnyEqualerclIDnEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_12EquatableAnyET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_110AnyEqualerclIbEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_12EquatableAnyET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_110AnyEqualerclIlEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_12EquatableAnyET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_110AnyEqualerclImEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_12EquatableAnyET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_110AnyEqualerclIdEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_12EquatableAnyET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_110AnyEqualerclINS_16well_known_types10BytesValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameINS1_12EquatableAnyET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_110AnyEqualerclINS_16well_known_types11StringValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameINS1_12EquatableAnyET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_110AnyEqualerclIN4absl12lts_202601078DurationEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS1_12EquatableAnyET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_110AnyEqualerclIN4absl12lts_202601074TimeEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS1_12EquatableAnyET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_110AnyEqualerclINS1_18EquatableListValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS1_12EquatableAnyET_EEEEbE4typeES8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_110AnyEqualerclINS1_15EquatableStructEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS1_12EquatableAnyET_EEEEbE4typeES8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_110AnyEqualerclINS1_16EquatableMessageEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS1_12EquatableAnyET_EEEEbE4typeES8_RKS9_
272
};
273
274
struct MessageEqualer {
275
0
  bool operator()(EquatableMessage lhs, EquatableMessage rhs) const {
276
0
    return lhs.get().GetDescriptor() == rhs.get().GetDescriptor() &&
277
0
           MessageDifferencer::Equals(lhs.get(), rhs.get());
278
0
  }
279
280
  template <typename T>
281
  std::enable_if_t<std::negation_v<std::is_same<EquatableMessage, T>>, bool>
282
0
  operator()(EquatableMessage, const T&) const {
283
0
    return false;
284
0
  }
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_114MessageEqualerclIDnEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_16EquatableMessageET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_114MessageEqualerclIbEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_16EquatableMessageET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_114MessageEqualerclIlEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_16EquatableMessageET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_114MessageEqualerclImEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_16EquatableMessageET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_114MessageEqualerclIdEENSt3__19enable_ifIXsr3stdE10negation_vINS4_7is_sameINS1_16EquatableMessageET_EEEEbE4typeES7_RKS8_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_114MessageEqualerclINS_16well_known_types10BytesValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameINS1_16EquatableMessageET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_114MessageEqualerclINS_16well_known_types11StringValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS6_7is_sameINS1_16EquatableMessageET_EEEEbE4typeES9_RKSA_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_114MessageEqualerclIN4absl12lts_202601078DurationEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS1_16EquatableMessageET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_114MessageEqualerclIN4absl12lts_202601074TimeEEENSt3__19enable_ifIXsr3stdE10negation_vINS7_7is_sameINS1_16EquatableMessageET_EEEEbE4typeESA_RKSB_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_114MessageEqualerclINS1_18EquatableListValueEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS1_16EquatableMessageET_EEEEbE4typeES8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_114MessageEqualerclINS1_15EquatableStructEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS1_16EquatableMessageET_EEEEbE4typeES8_RKS9_
Unexecuted instantiation: message_equality.cc:_ZNK3cel8internal12_GLOBAL__N_114MessageEqualerclINS1_12EquatableAnyEEENSt3__19enable_ifIXsr3stdE10negation_vINS5_7is_sameINS1_16EquatableMessageET_EEEEbE4typeES8_RKS9_
285
};
286
287
struct EquatableValueReflection final {
288
  well_known_types::DoubleValueReflection double_value_reflection;
289
  well_known_types::FloatValueReflection float_value_reflection;
290
  well_known_types::Int64ValueReflection int64_value_reflection;
291
  well_known_types::UInt64ValueReflection uint64_value_reflection;
292
  well_known_types::Int32ValueReflection int32_value_reflection;
293
  well_known_types::UInt32ValueReflection uint32_value_reflection;
294
  well_known_types::StringValueReflection string_value_reflection;
295
  well_known_types::BytesValueReflection bytes_value_reflection;
296
  well_known_types::BoolValueReflection bool_value_reflection;
297
  well_known_types::AnyReflection any_reflection;
298
  well_known_types::DurationReflection duration_reflection;
299
  well_known_types::TimestampReflection timestamp_reflection;
300
  well_known_types::ValueReflection value_reflection;
301
  well_known_types::ListValueReflection list_value_reflection;
302
  well_known_types::StructReflection struct_reflection;
303
};
304
305
absl::StatusOr<EquatableValue> AsEquatableValue(
306
    EquatableValueReflection& reflection,
307
    const Message& message ABSL_ATTRIBUTE_LIFETIME_BOUND,
308
    const Descriptor* absl_nonnull descriptor,
309
    Descriptor::WellKnownType well_known_type,
310
0
    std::string& scratch ABSL_ATTRIBUTE_LIFETIME_BOUND) {
311
0
  switch (well_known_type) {
312
0
    case Descriptor::WELLKNOWNTYPE_DOUBLEVALUE:
313
0
      CEL_RETURN_IF_ERROR(
314
0
          reflection.double_value_reflection.Initialize(descriptor));
315
0
      return reflection.double_value_reflection.GetValue(message);
316
0
    case Descriptor::WELLKNOWNTYPE_FLOATVALUE:
317
0
      CEL_RETURN_IF_ERROR(
318
0
          reflection.float_value_reflection.Initialize(descriptor));
319
0
      return static_cast<double>(
320
0
          reflection.float_value_reflection.GetValue(message));
321
0
    case Descriptor::WELLKNOWNTYPE_INT64VALUE:
322
0
      CEL_RETURN_IF_ERROR(
323
0
          reflection.int64_value_reflection.Initialize(descriptor));
324
0
      return reflection.int64_value_reflection.GetValue(message);
325
0
    case Descriptor::WELLKNOWNTYPE_UINT64VALUE:
326
0
      CEL_RETURN_IF_ERROR(
327
0
          reflection.uint64_value_reflection.Initialize(descriptor));
328
0
      return reflection.uint64_value_reflection.GetValue(message);
329
0
    case Descriptor::WELLKNOWNTYPE_INT32VALUE:
330
0
      CEL_RETURN_IF_ERROR(
331
0
          reflection.int32_value_reflection.Initialize(descriptor));
332
0
      return static_cast<int64_t>(
333
0
          reflection.int32_value_reflection.GetValue(message));
334
0
    case Descriptor::WELLKNOWNTYPE_UINT32VALUE:
335
0
      CEL_RETURN_IF_ERROR(
336
0
          reflection.uint32_value_reflection.Initialize(descriptor));
337
0
      return static_cast<uint64_t>(
338
0
          reflection.uint32_value_reflection.GetValue(message));
339
0
    case Descriptor::WELLKNOWNTYPE_STRINGVALUE:
340
0
      CEL_RETURN_IF_ERROR(
341
0
          reflection.string_value_reflection.Initialize(descriptor));
342
0
      return reflection.string_value_reflection.GetValue(message, scratch);
343
0
    case Descriptor::WELLKNOWNTYPE_BYTESVALUE:
344
0
      CEL_RETURN_IF_ERROR(
345
0
          reflection.bytes_value_reflection.Initialize(descriptor));
346
0
      return reflection.bytes_value_reflection.GetValue(message, scratch);
347
0
    case Descriptor::WELLKNOWNTYPE_BOOLVALUE:
348
0
      CEL_RETURN_IF_ERROR(
349
0
          reflection.bool_value_reflection.Initialize(descriptor));
350
0
      return reflection.bool_value_reflection.GetValue(message);
351
0
    case Descriptor::WELLKNOWNTYPE_VALUE: {
352
0
      CEL_RETURN_IF_ERROR(reflection.value_reflection.Initialize(descriptor));
353
0
      const auto kind_case = reflection.value_reflection.GetKindCase(message);
354
0
      switch (kind_case) {
355
0
        case google::protobuf::Value::KIND_NOT_SET:
356
0
          ABSL_FALLTHROUGH_INTENDED;
357
0
        case google::protobuf::Value::kNullValue:
358
0
          return nullptr;
359
0
        case google::protobuf::Value::kBoolValue:
360
0
          return reflection.value_reflection.GetBoolValue(message);
361
0
        case google::protobuf::Value::kNumberValue:
362
0
          return reflection.value_reflection.GetNumberValue(message);
363
0
        case google::protobuf::Value::kStringValue:
364
0
          return reflection.value_reflection.GetStringValue(message, scratch);
365
0
        case google::protobuf::Value::kListValue:
366
0
          return EquatableListValue(
367
0
              reflection.value_reflection.GetListValue(message));
368
0
        case google::protobuf::Value::kStructValue:
369
0
          return EquatableStruct(
370
0
              reflection.value_reflection.GetStructValue(message));
371
0
        default:
372
0
          return absl::InternalError(
373
0
              absl::StrCat("unexpected value kind case: ", kind_case));
374
0
      }
375
0
    }
376
0
    case Descriptor::WELLKNOWNTYPE_LISTVALUE:
377
0
      return EquatableListValue(message);
378
0
    case Descriptor::WELLKNOWNTYPE_STRUCT:
379
0
      return EquatableStruct(message);
380
0
    case Descriptor::WELLKNOWNTYPE_DURATION:
381
0
      CEL_RETURN_IF_ERROR(
382
0
          reflection.duration_reflection.Initialize(descriptor));
383
0
      return reflection.duration_reflection.ToAbslDuration(message);
384
0
    case Descriptor::WELLKNOWNTYPE_TIMESTAMP:
385
0
      CEL_RETURN_IF_ERROR(
386
0
          reflection.timestamp_reflection.Initialize(descriptor));
387
0
      return reflection.timestamp_reflection.ToAbslTime(message);
388
0
    case Descriptor::WELLKNOWNTYPE_ANY:
389
0
      return EquatableAny(message);
390
0
    default:
391
0
      return EquatableMessage(message);
392
0
  }
393
0
}
394
395
absl::StatusOr<EquatableValue> AsEquatableValue(
396
    EquatableValueReflection& reflection,
397
    const Message& message ABSL_ATTRIBUTE_LIFETIME_BOUND,
398
    const Descriptor* absl_nonnull descriptor,
399
0
    std::string& scratch ABSL_ATTRIBUTE_LIFETIME_BOUND) {
400
0
  return AsEquatableValue(reflection, message, descriptor,
401
0
                          descriptor->well_known_type(), scratch);
402
0
}
403
404
absl::StatusOr<EquatableValue> AsEquatableValue(
405
    EquatableValueReflection& reflection,
406
    const Message& message ABSL_ATTRIBUTE_LIFETIME_BOUND,
407
    const FieldDescriptor* absl_nonnull field,
408
0
    std::string& scratch ABSL_ATTRIBUTE_LIFETIME_BOUND) {
409
0
  ABSL_DCHECK(!field->is_repeated() && !field->is_map());
410
0
  switch (field->cpp_type()) {
411
0
    case FieldDescriptor::CPPTYPE_INT32:
412
0
      return static_cast<int64_t>(
413
0
          message.GetReflection()->GetInt32(message, field));
414
0
    case FieldDescriptor::CPPTYPE_INT64:
415
0
      return message.GetReflection()->GetInt64(message, field);
416
0
    case FieldDescriptor::CPPTYPE_UINT32:
417
0
      return static_cast<uint64_t>(
418
0
          message.GetReflection()->GetUInt32(message, field));
419
0
    case FieldDescriptor::CPPTYPE_UINT64:
420
0
      return message.GetReflection()->GetUInt64(message, field);
421
0
    case FieldDescriptor::CPPTYPE_DOUBLE:
422
0
      return message.GetReflection()->GetDouble(message, field);
423
0
    case FieldDescriptor::CPPTYPE_FLOAT:
424
0
      return static_cast<double>(
425
0
          message.GetReflection()->GetFloat(message, field));
426
0
    case FieldDescriptor::CPPTYPE_BOOL:
427
0
      return message.GetReflection()->GetBool(message, field);
428
0
    case FieldDescriptor::CPPTYPE_ENUM:
429
0
      if (field->enum_type()->full_name() == "google.protobuf.NullValue") {
430
0
        return nullptr;
431
0
      }
432
0
      return static_cast<int64_t>(
433
0
          message.GetReflection()->GetEnumValue(message, field));
434
0
    case FieldDescriptor::CPPTYPE_STRING:
435
0
      if (field->type() == FieldDescriptor::TYPE_BYTES) {
436
0
        return well_known_types::GetBytesField(message, field, scratch);
437
0
      }
438
0
      return well_known_types::GetStringField(message, field, scratch);
439
0
    case FieldDescriptor::CPPTYPE_MESSAGE:
440
0
      return AsEquatableValue(
441
0
          reflection, message.GetReflection()->GetMessage(message, field),
442
0
          field->message_type(), scratch);
443
0
    default:
444
0
      return absl::InternalError(
445
0
          absl::StrCat("unexpected field type: ", field->cpp_type_name()));
446
0
  }
447
0
}
448
449
0
bool IsAny(const Message& message) {
450
0
  return message.GetDescriptor()->well_known_type() ==
451
0
         Descriptor::WELLKNOWNTYPE_ANY;
452
0
}
453
454
0
bool IsAnyField(const FieldDescriptor* absl_nonnull field) {
455
0
  return field->type() == FieldDescriptor::TYPE_MESSAGE &&
456
0
         field->message_type()->well_known_type() ==
457
0
             Descriptor::WELLKNOWNTYPE_ANY;
458
0
}
459
460
absl::StatusOr<EquatableValue> MapValueAsEquatableValue(
461
    google::protobuf::Arena* absl_nonnull arena, const DescriptorPool* absl_nonnull pool,
462
    MessageFactory* absl_nonnull factory, EquatableValueReflection& reflection,
463
    const google::protobuf::MapValueConstRef& value,
464
    const FieldDescriptor* absl_nonnull field, std::string& scratch,
465
0
    Unique<Message>& unpacked) {
466
0
  if (IsAnyField(field)) {
467
0
    CEL_ASSIGN_OR_RETURN(unpacked, well_known_types::UnpackAnyIfResolveable(
468
0
                                       arena, reflection.any_reflection,
469
0
                                       value.GetMessageValue(), pool, factory));
470
0
    if (unpacked) {
471
0
      return AsEquatableValue(reflection, *unpacked, unpacked->GetDescriptor(),
472
0
                              scratch);
473
0
    }
474
0
    return AsEquatableValue(reflection, value.GetMessageValue(),
475
0
                            value.GetMessageValue().GetDescriptor(), scratch);
476
0
  }
477
0
  switch (field->cpp_type()) {
478
0
    case FieldDescriptor::CPPTYPE_INT32:
479
0
      return static_cast<int64_t>(value.GetInt32Value());
480
0
    case FieldDescriptor::CPPTYPE_INT64:
481
0
      return value.GetInt64Value();
482
0
    case FieldDescriptor::CPPTYPE_UINT32:
483
0
      return static_cast<uint64_t>(value.GetUInt32Value());
484
0
    case FieldDescriptor::CPPTYPE_UINT64:
485
0
      return value.GetUInt64Value();
486
0
    case FieldDescriptor::CPPTYPE_DOUBLE:
487
0
      return value.GetDoubleValue();
488
0
    case FieldDescriptor::CPPTYPE_FLOAT:
489
0
      return static_cast<double>(value.GetFloatValue());
490
0
    case FieldDescriptor::CPPTYPE_BOOL:
491
0
      return value.GetBoolValue();
492
0
    case FieldDescriptor::CPPTYPE_ENUM:
493
0
      if (field->enum_type()->full_name() == "google.protobuf.NullValue") {
494
0
        return nullptr;
495
0
      }
496
0
      return static_cast<int64_t>(value.GetEnumValue());
497
0
    case FieldDescriptor::CPPTYPE_STRING:
498
0
      if (field->type() == FieldDescriptor::TYPE_BYTES) {
499
0
        return well_known_types::BytesValue(
500
0
            absl::string_view(value.GetStringValue()));
501
0
      }
502
0
      return well_known_types::StringValue(
503
0
          absl::string_view(value.GetStringValue()));
504
0
    case FieldDescriptor::CPPTYPE_MESSAGE: {
505
0
      const auto& message = value.GetMessageValue();
506
0
      return AsEquatableValue(reflection, message, message.GetDescriptor(),
507
0
                              scratch);
508
0
    }
509
0
    default:
510
0
      return absl::InternalError(
511
0
          absl::StrCat("unexpected field type: ", field->cpp_type_name()));
512
0
  }
513
0
}
514
515
absl::StatusOr<EquatableValue> RepeatedFieldAsEquatableValue(
516
    google::protobuf::Arena* absl_nonnull arena, const DescriptorPool* absl_nonnull pool,
517
    MessageFactory* absl_nonnull factory, EquatableValueReflection& reflection,
518
    const Message& message, const FieldDescriptor* absl_nonnull field,
519
0
    int index, std::string& scratch, Unique<Message>& unpacked) {
520
0
  if (IsAnyField(field)) {
521
0
    const auto& field_value =
522
0
        message.GetReflection()->GetRepeatedMessage(message, field, index);
523
0
    CEL_ASSIGN_OR_RETURN(unpacked, well_known_types::UnpackAnyIfResolveable(
524
0
                                       arena, reflection.any_reflection,
525
0
                                       field_value, pool, factory));
526
0
    if (unpacked) {
527
0
      return AsEquatableValue(reflection, *unpacked, unpacked->GetDescriptor(),
528
0
                              scratch);
529
0
    }
530
0
    return AsEquatableValue(reflection, field_value,
531
0
                            field_value.GetDescriptor(), scratch);
532
0
  }
533
0
  switch (field->cpp_type()) {
534
0
    case FieldDescriptor::CPPTYPE_INT32:
535
0
      return static_cast<int64_t>(
536
0
          message.GetReflection()->GetRepeatedInt32(message, field, index));
537
0
    case FieldDescriptor::CPPTYPE_INT64:
538
0
      return message.GetReflection()->GetRepeatedInt64(message, field, index);
539
0
    case FieldDescriptor::CPPTYPE_UINT32:
540
0
      return static_cast<uint64_t>(
541
0
          message.GetReflection()->GetRepeatedUInt32(message, field, index));
542
0
    case FieldDescriptor::CPPTYPE_UINT64:
543
0
      return message.GetReflection()->GetRepeatedUInt64(message, field, index);
544
0
    case FieldDescriptor::CPPTYPE_DOUBLE:
545
0
      return message.GetReflection()->GetRepeatedDouble(message, field, index);
546
0
    case FieldDescriptor::CPPTYPE_FLOAT:
547
0
      return static_cast<double>(
548
0
          message.GetReflection()->GetRepeatedFloat(message, field, index));
549
0
    case FieldDescriptor::CPPTYPE_BOOL:
550
0
      return message.GetReflection()->GetRepeatedBool(message, field, index);
551
0
    case FieldDescriptor::CPPTYPE_ENUM:
552
0
      if (field->enum_type()->full_name() == "google.protobuf.NullValue") {
553
0
        return nullptr;
554
0
      }
555
0
      return static_cast<int64_t>(
556
0
          message.GetReflection()->GetRepeatedEnumValue(message, field, index));
557
0
    case FieldDescriptor::CPPTYPE_STRING:
558
0
      if (field->type() == FieldDescriptor::TYPE_BYTES) {
559
0
        return well_known_types::GetRepeatedBytesField(message, field, index,
560
0
                                                       scratch);
561
0
      }
562
0
      return well_known_types::GetRepeatedStringField(message, field, index,
563
0
                                                      scratch);
564
0
    case FieldDescriptor::CPPTYPE_MESSAGE: {
565
0
      const auto& submessage =
566
0
          message.GetReflection()->GetRepeatedMessage(message, field, index);
567
0
      return AsEquatableValue(reflection, submessage,
568
0
                              submessage.GetDescriptor(), scratch);
569
0
    }
570
0
    default:
571
0
      return absl::InternalError(
572
0
          absl::StrCat("unexpected field type: ", field->cpp_type_name()));
573
0
  }
574
0
}
575
576
// Compare two `EquatableValue` for equality.
577
bool EquatableValueEquals(const EquatableValue& lhs,
578
0
                          const EquatableValue& rhs) {
579
0
  return absl::visit(
580
0
      absl::Overload(NullValueEqualer{}, BoolValueEqualer{},
581
0
                     BytesValueEqualer{}, IntValueEqualer{}, UintValueEqualer{},
582
0
                     DoubleValueEqualer{}, StringValueEqualer{},
583
0
                     DurationEqualer{}, TimestampEqualer{}, ListValueEqualer{},
584
0
                     StructEqualer{}, AnyEqualer{}, MessageEqualer{}),
585
0
      lhs, rhs);
586
0
}
587
588
// Attempts to coalesce one map key to another. Returns true if it was possible,
589
// false otherwise.
590
bool CoalesceMapKey(const google::protobuf::MapKey& src,
591
                    FieldDescriptor::CppType dest_type,
592
0
                    google::protobuf::MapKey* absl_nonnull dest) {
593
0
  switch (src.type()) {
594
0
    case FieldDescriptor::CPPTYPE_BOOL:
595
0
      if (dest_type != FieldDescriptor::CPPTYPE_BOOL) {
596
0
        return false;
597
0
      }
598
0
      dest->SetBoolValue(src.GetBoolValue());
599
0
      return true;
600
0
    case FieldDescriptor::CPPTYPE_INT32: {
601
0
      const auto src_value = src.GetInt32Value();
602
0
      switch (dest_type) {
603
0
        case FieldDescriptor::CPPTYPE_INT32:
604
0
          dest->SetInt32Value(src_value);
605
0
          return true;
606
0
        case FieldDescriptor::CPPTYPE_INT64:
607
0
          dest->SetInt64Value(src_value);
608
0
          return true;
609
0
        case FieldDescriptor::CPPTYPE_UINT32:
610
0
          if (src_value < 0) {
611
0
            return false;
612
0
          }
613
0
          dest->SetUInt32Value(static_cast<uint32_t>(src_value));
614
0
          return true;
615
0
        case FieldDescriptor::CPPTYPE_UINT64:
616
0
          if (src_value < 0) {
617
0
            return false;
618
0
          }
619
0
          dest->SetUInt64Value(static_cast<uint64_t>(src_value));
620
0
          return true;
621
0
        default:
622
0
          return false;
623
0
      }
624
0
    }
625
0
    case FieldDescriptor::CPPTYPE_INT64: {
626
0
      const auto src_value = src.GetInt64Value();
627
0
      switch (dest_type) {
628
0
        case FieldDescriptor::CPPTYPE_INT32:
629
0
          if (src_value < std::numeric_limits<int32_t>::min() ||
630
0
              src_value > std::numeric_limits<int32_t>::max()) {
631
0
            return false;
632
0
          }
633
0
          dest->SetInt32Value(static_cast<int32_t>(src_value));
634
0
          return true;
635
0
        case FieldDescriptor::CPPTYPE_INT64:
636
0
          dest->SetInt64Value(src_value);
637
0
          return true;
638
0
        case FieldDescriptor::CPPTYPE_UINT32:
639
0
          if (src_value < 0 ||
640
0
              src_value > std::numeric_limits<uint32_t>::max()) {
641
0
            return false;
642
0
          }
643
0
          dest->SetUInt32Value(static_cast<uint32_t>(src_value));
644
0
          return true;
645
0
        case FieldDescriptor::CPPTYPE_UINT64:
646
0
          if (src_value < 0) {
647
0
            return false;
648
0
          }
649
0
          dest->SetUInt64Value(static_cast<uint64_t>(src_value));
650
0
          return true;
651
0
        default:
652
0
          return false;
653
0
      }
654
0
    }
655
0
    case FieldDescriptor::CPPTYPE_UINT32: {
656
0
      const auto src_value = src.GetUInt32Value();
657
0
      switch (dest_type) {
658
0
        case FieldDescriptor::CPPTYPE_INT32:
659
0
          if (src_value > std::numeric_limits<int32_t>::max()) {
660
0
            return false;
661
0
          }
662
0
          dest->SetInt32Value(static_cast<int32_t>(src_value));
663
0
          return true;
664
0
        case FieldDescriptor::CPPTYPE_INT64:
665
0
          dest->SetInt64Value(static_cast<int64_t>(src_value));
666
0
          return true;
667
0
        case FieldDescriptor::CPPTYPE_UINT32:
668
0
          dest->SetUInt32Value(src_value);
669
0
          return true;
670
0
        case FieldDescriptor::CPPTYPE_UINT64:
671
0
          dest->SetUInt64Value(static_cast<uint64_t>(src_value));
672
0
          return true;
673
0
        default:
674
0
          return false;
675
0
      }
676
0
    }
677
0
    case FieldDescriptor::CPPTYPE_UINT64: {
678
0
      const auto src_value = src.GetUInt64Value();
679
0
      switch (dest_type) {
680
0
        case FieldDescriptor::CPPTYPE_INT32:
681
0
          if (src_value > std::numeric_limits<int32_t>::max()) {
682
0
            return false;
683
0
          }
684
0
          dest->SetInt32Value(static_cast<int32_t>(src_value));
685
0
          return true;
686
0
        case FieldDescriptor::CPPTYPE_INT64:
687
0
          if (src_value > std::numeric_limits<int64_t>::max()) {
688
0
            return false;
689
0
          }
690
0
          dest->SetInt64Value(static_cast<int64_t>(src_value));
691
0
          return true;
692
0
        case FieldDescriptor::CPPTYPE_UINT32:
693
0
          if (src_value > std::numeric_limits<uint32_t>::max()) {
694
0
            return false;
695
0
          }
696
0
          dest->SetUInt32Value(src_value);
697
0
          return true;
698
0
        case FieldDescriptor::CPPTYPE_UINT64:
699
0
          dest->SetUInt64Value(src_value);
700
0
          return true;
701
0
        default:
702
0
          return false;
703
0
      }
704
0
    }
705
0
    case FieldDescriptor::CPPTYPE_STRING:
706
0
      if (dest_type != FieldDescriptor::CPPTYPE_STRING) {
707
0
        return false;
708
0
      }
709
0
      dest->SetStringValue(src.GetStringValue());
710
0
      return true;
711
0
    default:
712
      // Only bool, integrals, and string may be map keys.
713
0
      ABSL_UNREACHABLE();
714
0
  }
715
0
}
716
717
// Bits used for categorizing equality. Can be used to cheaply check whether two
718
// categories are comparable for equality by performing an AND and checking if
719
// the result against `kNone`.
720
enum class EquatableCategory {
721
  kNone = 0,
722
723
  kNullLike = 1 << 0,
724
  kBoolLike = 1 << 1,
725
  kNumericLike = 1 << 2,
726
  kBytesLike = 1 << 3,
727
  kStringLike = 1 << 4,
728
  kList = 1 << 5,
729
  kMap = 1 << 6,
730
  kMessage = 1 << 7,
731
  kDuration = 1 << 8,
732
  kTimestamp = 1 << 9,
733
734
  kAny = kNullLike | kBoolLike | kNumericLike | kBytesLike | kStringLike |
735
         kList | kMap | kMessage | kDuration | kTimestamp,
736
  kValue = kNullLike | kBoolLike | kNumericLike | kStringLike | kList | kMap,
737
};
738
739
constexpr EquatableCategory operator&(EquatableCategory lhs,
740
0
                                      EquatableCategory rhs) {
741
0
  return static_cast<EquatableCategory>(
742
0
      static_cast<std::underlying_type_t<EquatableCategory>>(lhs) &
743
0
      static_cast<std::underlying_type_t<EquatableCategory>>(rhs));
744
0
}
745
746
0
constexpr bool operator==(EquatableCategory lhs, EquatableCategory rhs) {
747
0
  return static_cast<std::underlying_type_t<EquatableCategory>>(lhs) ==
748
0
         static_cast<std::underlying_type_t<EquatableCategory>>(rhs);
749
0
}
750
751
EquatableCategory GetEquatableCategory(
752
0
    const Descriptor* absl_nonnull descriptor) {
753
0
  switch (descriptor->well_known_type()) {
754
0
    case Descriptor::WELLKNOWNTYPE_BOOLVALUE:
755
0
      return EquatableCategory::kBoolLike;
756
0
    case Descriptor::WELLKNOWNTYPE_FLOATVALUE:
757
0
      ABSL_FALLTHROUGH_INTENDED;
758
0
    case Descriptor::WELLKNOWNTYPE_DOUBLEVALUE:
759
0
      ABSL_FALLTHROUGH_INTENDED;
760
0
    case Descriptor::WELLKNOWNTYPE_INT32VALUE:
761
0
      ABSL_FALLTHROUGH_INTENDED;
762
0
    case Descriptor::WELLKNOWNTYPE_UINT32VALUE:
763
0
      ABSL_FALLTHROUGH_INTENDED;
764
0
    case Descriptor::WELLKNOWNTYPE_INT64VALUE:
765
0
      ABSL_FALLTHROUGH_INTENDED;
766
0
    case Descriptor::WELLKNOWNTYPE_UINT64VALUE:
767
0
      return EquatableCategory::kNumericLike;
768
0
    case Descriptor::WELLKNOWNTYPE_BYTESVALUE:
769
0
      return EquatableCategory::kBytesLike;
770
0
    case Descriptor::WELLKNOWNTYPE_STRINGVALUE:
771
0
      return EquatableCategory::kStringLike;
772
0
    case Descriptor::WELLKNOWNTYPE_VALUE:
773
0
      return EquatableCategory::kValue;
774
0
    case Descriptor::WELLKNOWNTYPE_LISTVALUE:
775
0
      return EquatableCategory::kList;
776
0
    case Descriptor::WELLKNOWNTYPE_STRUCT:
777
0
      return EquatableCategory::kMap;
778
0
    case Descriptor::WELLKNOWNTYPE_ANY:
779
0
      return EquatableCategory::kAny;
780
0
    case Descriptor::WELLKNOWNTYPE_DURATION:
781
0
      return EquatableCategory::kDuration;
782
0
    case Descriptor::WELLKNOWNTYPE_TIMESTAMP:
783
0
      return EquatableCategory::kTimestamp;
784
0
    default:
785
0
      return EquatableCategory::kAny;
786
0
  }
787
0
}
788
789
EquatableCategory GetEquatableFieldCategory(
790
0
    const FieldDescriptor* absl_nonnull field) {
791
0
  switch (field->cpp_type()) {
792
0
    case FieldDescriptor::CPPTYPE_ENUM:
793
0
      return field->enum_type()->full_name() == "google.protobuf.NullValue"
794
0
                 ? EquatableCategory::kNullLike
795
0
                 : EquatableCategory::kNumericLike;
796
0
    case FieldDescriptor::CPPTYPE_BOOL:
797
0
      return EquatableCategory::kBoolLike;
798
0
    case FieldDescriptor::CPPTYPE_FLOAT:
799
0
      ABSL_FALLTHROUGH_INTENDED;
800
0
    case FieldDescriptor::CPPTYPE_DOUBLE:
801
0
      ABSL_FALLTHROUGH_INTENDED;
802
0
    case FieldDescriptor::CPPTYPE_INT32:
803
0
      ABSL_FALLTHROUGH_INTENDED;
804
0
    case FieldDescriptor::CPPTYPE_UINT32:
805
0
      ABSL_FALLTHROUGH_INTENDED;
806
0
    case FieldDescriptor::CPPTYPE_INT64:
807
0
      ABSL_FALLTHROUGH_INTENDED;
808
0
    case FieldDescriptor::CPPTYPE_UINT64:
809
0
      return EquatableCategory::kNumericLike;
810
0
    case FieldDescriptor::CPPTYPE_STRING:
811
0
      return field->type() == FieldDescriptor::TYPE_BYTES
812
0
                 ? EquatableCategory::kBytesLike
813
0
                 : EquatableCategory::kStringLike;
814
0
    case FieldDescriptor::CPPTYPE_MESSAGE:
815
0
      return GetEquatableCategory(field->message_type());
816
0
    default:
817
      // Ugh. Force any future additions to compare instead of short circuiting.
818
0
      return EquatableCategory::kAny;
819
0
  }
820
0
}
821
822
class MessageEqualsState final {
823
 public:
824
  MessageEqualsState(const DescriptorPool* absl_nonnull pool,
825
                     MessageFactory* absl_nonnull factory)
826
0
      : pool_(pool), factory_(factory) {}
827
828
  // Equality between messages.
829
0
  absl::StatusOr<bool> Equals(const Message& lhs, const Message& rhs) {
830
0
    const auto* lhs_descriptor = lhs.GetDescriptor();
831
0
    const auto* rhs_descriptor = rhs.GetDescriptor();
832
    // Deal with well known types, starting with any.
833
0
    auto lhs_well_known_type = lhs_descriptor->well_known_type();
834
0
    auto rhs_well_known_type = rhs_descriptor->well_known_type();
835
0
    const Message* absl_nonnull lhs_ptr = &lhs;
836
0
    const Message* absl_nonnull rhs_ptr = &rhs;
837
0
    Unique<Message> lhs_unpacked;
838
0
    Unique<Message> rhs_unpacked;
839
    // Deal with any first. We could in theory check if we should bother
840
    // unpacking, but that is more complicated. We can always implement it
841
    // later.
842
0
    if (lhs_well_known_type == Descriptor::WELLKNOWNTYPE_ANY) {
843
0
      CEL_ASSIGN_OR_RETURN(
844
0
          lhs_unpacked,
845
0
          well_known_types::UnpackAnyIfResolveable(
846
0
              &arena_, lhs_reflection_.any_reflection, lhs, pool_, factory_));
847
0
      if (lhs_unpacked) {
848
0
        lhs_ptr = cel::to_address(lhs_unpacked);
849
0
        lhs_descriptor = lhs_ptr->GetDescriptor();
850
0
        lhs_well_known_type = lhs_descriptor->well_known_type();
851
0
      }
852
0
    }
853
0
    if (rhs_well_known_type == Descriptor::WELLKNOWNTYPE_ANY) {
854
0
      CEL_ASSIGN_OR_RETURN(
855
0
          rhs_unpacked,
856
0
          well_known_types::UnpackAnyIfResolveable(
857
0
              &arena_, rhs_reflection_.any_reflection, rhs, pool_, factory_));
858
0
      if (rhs_unpacked) {
859
0
        rhs_ptr = cel::to_address(rhs_unpacked);
860
0
        rhs_descriptor = rhs_ptr->GetDescriptor();
861
0
        rhs_well_known_type = rhs_descriptor->well_known_type();
862
0
      }
863
0
    }
864
0
    CEL_ASSIGN_OR_RETURN(
865
0
        auto lhs_value,
866
0
        AsEquatableValue(lhs_reflection_, *lhs_ptr, lhs_descriptor,
867
0
                         lhs_well_known_type, lhs_scratch_));
868
0
    CEL_ASSIGN_OR_RETURN(
869
0
        auto rhs_value,
870
0
        AsEquatableValue(rhs_reflection_, *rhs_ptr, rhs_descriptor,
871
0
                         rhs_well_known_type, rhs_scratch_));
872
0
    return EquatableValueEquals(lhs_value, rhs_value);
873
0
  }
874
875
  // Equality between map message fields.
876
  absl::StatusOr<bool> MapFieldEquals(
877
      const Message& lhs, const FieldDescriptor* absl_nonnull lhs_field,
878
0
      const Message& rhs, const FieldDescriptor* absl_nonnull rhs_field) {
879
0
    ABSL_DCHECK(lhs_field->is_map());
880
0
    ABSL_DCHECK_EQ(lhs_field->containing_type(), lhs.GetDescriptor());
881
0
    ABSL_DCHECK(rhs_field->is_map());
882
0
    ABSL_DCHECK_EQ(rhs_field->containing_type(), rhs.GetDescriptor());
883
0
    const auto* lhs_entry = lhs_field->message_type();
884
0
    const auto* lhs_entry_key_field = lhs_entry->map_key();
885
0
    const auto* lhs_entry_value_field = lhs_entry->map_value();
886
0
    const auto* rhs_entry = rhs_field->message_type();
887
0
    const auto* rhs_entry_key_field = rhs_entry->map_key();
888
0
    const auto* rhs_entry_value_field = rhs_entry->map_value();
889
    // Perform cheap test which checks whether the left and right can even be
890
    // compared for equality.
891
0
    if (lhs_field != rhs_field &&
892
0
        ((GetEquatableFieldCategory(lhs_entry_key_field) &
893
0
          GetEquatableFieldCategory(rhs_entry_key_field)) ==
894
0
             EquatableCategory::kNone ||
895
0
         (GetEquatableFieldCategory(lhs_entry_value_field) &
896
0
          GetEquatableFieldCategory(rhs_entry_value_field)) ==
897
0
             EquatableCategory::kNone)) {
898
      // Short-circuit.
899
0
      return false;
900
0
    }
901
0
    const auto* lhs_reflection = lhs.GetReflection();
902
0
    const auto* rhs_reflection = rhs.GetReflection();
903
0
    if (MapSize(*lhs_reflection, lhs, *lhs_field) !=
904
0
        MapSize(*rhs_reflection, rhs, *rhs_field)) {
905
0
      return false;
906
0
    }
907
0
    auto lhs_begin = ConstMapBegin(*lhs_reflection, lhs, *lhs_field);
908
0
    const auto lhs_end = ConstMapEnd(*lhs_reflection, lhs, *lhs_field);
909
0
    Unique<Message> lhs_unpacked;
910
0
    EquatableValue lhs_value;
911
0
    Unique<Message> rhs_unpacked;
912
0
    EquatableValue rhs_value;
913
0
    google::protobuf::MapKey rhs_map_key;
914
0
    google::protobuf::MapValueConstRef rhs_map_value;
915
0
    for (; lhs_begin != lhs_end; ++lhs_begin) {
916
0
      if (!CoalesceMapKey(lhs_begin.GetKey(), rhs_entry_key_field->cpp_type(),
917
0
                          &rhs_map_key)) {
918
0
        return false;
919
0
      }
920
0
      if (!LookupMapValue(*rhs_reflection, rhs, *rhs_field, rhs_map_key,
921
0
                          &rhs_map_value)) {
922
0
        return false;
923
0
      }
924
0
      CEL_ASSIGN_OR_RETURN(lhs_value,
925
0
                           MapValueAsEquatableValue(
926
0
                               &arena_, pool_, factory_, lhs_reflection_,
927
0
                               lhs_begin.GetValueRef(), lhs_entry_value_field,
928
0
                               lhs_scratch_, lhs_unpacked));
929
0
      CEL_ASSIGN_OR_RETURN(
930
0
          rhs_value,
931
0
          MapValueAsEquatableValue(&arena_, pool_, factory_, rhs_reflection_,
932
0
                                   rhs_map_value, rhs_entry_value_field,
933
0
                                   rhs_scratch_, rhs_unpacked));
934
0
      if (!EquatableValueEquals(lhs_value, rhs_value)) {
935
0
        return false;
936
0
      }
937
0
    }
938
0
    return true;
939
0
  }
940
941
  // Equality between repeated message fields.
942
  absl::StatusOr<bool> RepeatedFieldEquals(
943
      const Message& lhs, const FieldDescriptor* absl_nonnull lhs_field,
944
0
      const Message& rhs, const FieldDescriptor* absl_nonnull rhs_field) {
945
0
    ABSL_DCHECK(lhs_field->is_repeated() && !lhs_field->is_map());
946
0
    ABSL_DCHECK_EQ(lhs_field->containing_type(), lhs.GetDescriptor());
947
0
    ABSL_DCHECK(rhs_field->is_repeated() && !rhs_field->is_map());
948
0
    ABSL_DCHECK_EQ(rhs_field->containing_type(), rhs.GetDescriptor());
949
    // Perform cheap test which checks whether the left and right can even be
950
    // compared for equality.
951
0
    if (lhs_field != rhs_field &&
952
0
        (GetEquatableFieldCategory(lhs_field) &
953
0
         GetEquatableFieldCategory(rhs_field)) == EquatableCategory::kNone) {
954
      // Short-circuit.
955
0
      return false;
956
0
    }
957
0
    const auto* lhs_reflection = lhs.GetReflection();
958
0
    const auto* rhs_reflection = rhs.GetReflection();
959
0
    const auto size = lhs_reflection->FieldSize(lhs, lhs_field);
960
0
    if (size != rhs_reflection->FieldSize(rhs, rhs_field)) {
961
0
      return false;
962
0
    }
963
0
    Unique<Message> lhs_unpacked;
964
0
    EquatableValue lhs_value;
965
0
    Unique<Message> rhs_unpacked;
966
0
    EquatableValue rhs_value;
967
0
    for (int i = 0; i < size; ++i) {
968
0
      CEL_ASSIGN_OR_RETURN(lhs_value,
969
0
                           RepeatedFieldAsEquatableValue(
970
0
                               &arena_, pool_, factory_, lhs_reflection_, lhs,
971
0
                               lhs_field, i, lhs_scratch_, lhs_unpacked));
972
0
      CEL_ASSIGN_OR_RETURN(rhs_value,
973
0
                           RepeatedFieldAsEquatableValue(
974
0
                               &arena_, pool_, factory_, rhs_reflection_, rhs,
975
0
                               rhs_field, i, rhs_scratch_, rhs_unpacked));
976
0
      if (!EquatableValueEquals(lhs_value, rhs_value)) {
977
0
        return false;
978
0
      }
979
0
    }
980
0
    return true;
981
0
  }
982
983
  // Equality between singular message fields and/or messages. If the field is
984
  // `nullptr`, we are performing equality on the message itself rather than the
985
  // corresponding field.
986
  absl::StatusOr<bool> SingularFieldEquals(
987
      const Message& lhs, const FieldDescriptor* absl_nullable lhs_field,
988
0
      const Message& rhs, const FieldDescriptor* absl_nullable rhs_field) {
989
0
    ABSL_DCHECK(lhs_field == nullptr ||
990
0
                (!lhs_field->is_repeated() && !lhs_field->is_map()));
991
0
    ABSL_DCHECK(lhs_field == nullptr ||
992
0
                lhs_field->containing_type() == lhs.GetDescriptor());
993
0
    ABSL_DCHECK(rhs_field == nullptr ||
994
0
                (!rhs_field->is_repeated() && !rhs_field->is_map()));
995
0
    ABSL_DCHECK(rhs_field == nullptr ||
996
0
                rhs_field->containing_type() == rhs.GetDescriptor());
997
    // Perform cheap test which checks whether the left and right can even be
998
    // compared for equality.
999
0
    if (lhs_field != rhs_field &&
1000
0
        ((lhs_field != nullptr ? GetEquatableFieldCategory(lhs_field)
1001
0
                               : GetEquatableCategory(lhs.GetDescriptor())) &
1002
0
         (rhs_field != nullptr ? GetEquatableFieldCategory(rhs_field)
1003
0
                               : GetEquatableCategory(rhs.GetDescriptor()))) ==
1004
0
            EquatableCategory::kNone) {
1005
      // Short-circuit.
1006
0
      return false;
1007
0
    }
1008
0
    const Message* absl_nonnull lhs_ptr = &lhs;
1009
0
    const Message* absl_nonnull rhs_ptr = &rhs;
1010
0
    Unique<Message> lhs_unpacked;
1011
0
    Unique<Message> rhs_unpacked;
1012
0
    if (lhs_field != nullptr && IsAnyField(lhs_field)) {
1013
0
      CEL_ASSIGN_OR_RETURN(lhs_unpacked,
1014
0
                           well_known_types::UnpackAnyIfResolveable(
1015
0
                               &arena_, lhs_reflection_.any_reflection,
1016
0
                               lhs.GetReflection()->GetMessage(lhs, lhs_field),
1017
0
                               pool_, factory_));
1018
0
      if (lhs_unpacked) {
1019
0
        lhs_ptr = cel::to_address(lhs_unpacked);
1020
0
        lhs_field = nullptr;
1021
0
      }
1022
0
    } else if (lhs_field == nullptr && IsAny(lhs)) {
1023
0
      CEL_ASSIGN_OR_RETURN(
1024
0
          lhs_unpacked,
1025
0
          well_known_types::UnpackAnyIfResolveable(
1026
0
              &arena_, lhs_reflection_.any_reflection, lhs, pool_, factory_));
1027
0
      if (lhs_unpacked) {
1028
0
        lhs_ptr = cel::to_address(lhs_unpacked);
1029
0
      }
1030
0
    }
1031
0
    if (rhs_field != nullptr && IsAnyField(rhs_field)) {
1032
0
      CEL_ASSIGN_OR_RETURN(rhs_unpacked,
1033
0
                           well_known_types::UnpackAnyIfResolveable(
1034
0
                               &arena_, rhs_reflection_.any_reflection,
1035
0
                               rhs.GetReflection()->GetMessage(rhs, rhs_field),
1036
0
                               pool_, factory_));
1037
0
      if (rhs_unpacked) {
1038
0
        rhs_ptr = cel::to_address(rhs_unpacked);
1039
0
        rhs_field = nullptr;
1040
0
      }
1041
0
    } else if (rhs_field == nullptr && IsAny(rhs)) {
1042
0
      CEL_ASSIGN_OR_RETURN(
1043
0
          rhs_unpacked,
1044
0
          well_known_types::UnpackAnyIfResolveable(
1045
0
              &arena_, rhs_reflection_.any_reflection, rhs, pool_, factory_));
1046
0
      if (rhs_unpacked) {
1047
0
        rhs_ptr = cel::to_address(rhs_unpacked);
1048
0
      }
1049
0
    }
1050
0
    EquatableValue lhs_value;
1051
0
    if (lhs_field != nullptr) {
1052
0
      CEL_ASSIGN_OR_RETURN(
1053
0
          lhs_value,
1054
0
          AsEquatableValue(lhs_reflection_, *lhs_ptr, lhs_field, lhs_scratch_));
1055
0
    } else {
1056
0
      CEL_ASSIGN_OR_RETURN(
1057
0
          lhs_value, AsEquatableValue(lhs_reflection_, *lhs_ptr,
1058
0
                                      lhs_ptr->GetDescriptor(), lhs_scratch_));
1059
0
    }
1060
0
    EquatableValue rhs_value;
1061
0
    if (rhs_field != nullptr) {
1062
0
      CEL_ASSIGN_OR_RETURN(
1063
0
          rhs_value,
1064
0
          AsEquatableValue(rhs_reflection_, *rhs_ptr, rhs_field, rhs_scratch_));
1065
0
    } else {
1066
0
      CEL_ASSIGN_OR_RETURN(
1067
0
          rhs_value, AsEquatableValue(rhs_reflection_, *rhs_ptr,
1068
0
                                      rhs_ptr->GetDescriptor(), rhs_scratch_));
1069
0
    }
1070
0
    return EquatableValueEquals(lhs_value, rhs_value);
1071
0
  }
1072
1073
  absl::StatusOr<bool> FieldEquals(
1074
      const Message& lhs, const FieldDescriptor* absl_nullable lhs_field,
1075
0
      const Message& rhs, const FieldDescriptor* absl_nullable rhs_field) {
1076
0
    ABSL_DCHECK(lhs_field != nullptr ||
1077
0
                rhs_field != nullptr);  // Both cannot be null.
1078
0
    if (lhs_field != nullptr && lhs_field->is_map()) {
1079
      // map<?, ?> == map<?, ?>
1080
      // map<?, ?> == google.protobuf.Value
1081
      // map<?, ?> == google.protobuf.Struct
1082
      // map<?, ?> == google.protobuf.Any
1083
1084
      // Right hand side should be a map, `google.protobuf.Value`,
1085
      // `google.protobuf.Struct`, or `google.protobuf.Any`.
1086
0
      if (rhs_field != nullptr && rhs_field->is_map()) {
1087
        // map<?, ?> == map<?, ?>
1088
0
        return MapFieldEquals(lhs, lhs_field, rhs, rhs_field);
1089
0
      }
1090
0
      if (rhs_field != nullptr &&
1091
0
          (rhs_field->is_repeated() ||
1092
0
           rhs_field->type() != FieldDescriptor::TYPE_MESSAGE)) {
1093
0
        return false;
1094
0
      }
1095
0
      const Message* absl_nullable rhs_packed = nullptr;
1096
0
      Unique<Message> rhs_unpacked;
1097
0
      if (rhs_field != nullptr && IsAnyField(rhs_field)) {
1098
0
        rhs_packed = &rhs.GetReflection()->GetMessage(rhs, rhs_field);
1099
0
      } else if (rhs_field == nullptr && IsAny(rhs)) {
1100
0
        rhs_packed = &rhs;
1101
0
      }
1102
0
      if (rhs_packed != nullptr) {
1103
0
        CEL_RETURN_IF_ERROR(rhs_reflection_.any_reflection.Initialize(
1104
0
            rhs_packed->GetDescriptor()));
1105
0
        auto rhs_type_url = rhs_reflection_.any_reflection.GetTypeUrl(
1106
0
            *rhs_packed, rhs_scratch_);
1107
0
        if (!rhs_type_url.ConsumePrefix("type.googleapis.com/") &&
1108
0
            !rhs_type_url.ConsumePrefix("type.googleprod.com/")) {
1109
0
          return false;
1110
0
        }
1111
0
        if (rhs_type_url != "google.protobuf.Value" &&
1112
0
            rhs_type_url != "google.protobuf.Struct" &&
1113
0
            rhs_type_url != "google.protobuf.Any") {
1114
0
          return false;
1115
0
        }
1116
0
        CEL_ASSIGN_OR_RETURN(rhs_unpacked,
1117
0
                             well_known_types::UnpackAnyIfResolveable(
1118
0
                                 &arena_, rhs_reflection_.any_reflection,
1119
0
                                 *rhs_packed, pool_, factory_));
1120
0
        if (rhs_unpacked) {
1121
0
          rhs_field = nullptr;
1122
0
        }
1123
0
      }
1124
0
      const Message* absl_nonnull rhs_message =
1125
0
          rhs_field != nullptr
1126
0
              ? &rhs.GetReflection()->GetMessage(rhs, rhs_field)
1127
0
          : rhs_unpacked != nullptr ? cel::to_address(rhs_unpacked)
1128
0
                                    : &rhs;
1129
0
      const auto* rhs_descriptor = rhs_message->GetDescriptor();
1130
0
      const auto rhs_well_known_type = rhs_descriptor->well_known_type();
1131
0
      switch (rhs_well_known_type) {
1132
0
        case Descriptor::WELLKNOWNTYPE_VALUE: {
1133
          // map<?, ?> == google.protobuf.Value
1134
0
          CEL_RETURN_IF_ERROR(
1135
0
              rhs_reflection_.value_reflection.Initialize(rhs_descriptor));
1136
0
          if (rhs_reflection_.value_reflection.GetKindCase(*rhs_message) !=
1137
0
              google::protobuf::Value::kStructValue) {
1138
0
            return false;
1139
0
          }
1140
0
          CEL_RETURN_IF_ERROR(rhs_reflection_.struct_reflection.Initialize(
1141
0
              rhs_reflection_.value_reflection.GetStructDescriptor()));
1142
0
          return MapFieldEquals(
1143
0
              lhs, lhs_field,
1144
0
              rhs_reflection_.value_reflection.GetStructValue(*rhs_message),
1145
0
              rhs_reflection_.struct_reflection.GetFieldsDescriptor());
1146
0
        }
1147
0
        case Descriptor::WELLKNOWNTYPE_STRUCT: {
1148
          // map<?, ?> == google.protobuf.Struct
1149
0
          CEL_RETURN_IF_ERROR(
1150
0
              rhs_reflection_.struct_reflection.Initialize(rhs_descriptor));
1151
0
          return MapFieldEquals(
1152
0
              lhs, lhs_field, *rhs_message,
1153
0
              rhs_reflection_.struct_reflection.GetFieldsDescriptor());
1154
0
        }
1155
0
        default:
1156
0
          return false;
1157
0
      }
1158
      // Explicitly unreachable, for ease of reading. Control never leaves this
1159
      // if statement.
1160
0
      ABSL_UNREACHABLE();
1161
0
    }
1162
0
    if (rhs_field != nullptr && rhs_field->is_map()) {
1163
      // google.protobuf.Value == map<?, ?>
1164
      // google.protobuf.Struct == map<?, ?>
1165
      // google.protobuf.Any == map<?, ?>
1166
1167
      // Left hand side should be singular `google.protobuf.Value`
1168
      // `google.protobuf.Struct`, or `google.protobuf.Any`.
1169
0
      ABSL_DCHECK(lhs_field == nullptr ||
1170
0
                  !lhs_field->is_map());  // Handled above.
1171
0
      if (lhs_field != nullptr &&
1172
0
          (lhs_field->is_repeated() ||
1173
0
           lhs_field->type() != FieldDescriptor::TYPE_MESSAGE)) {
1174
0
        return false;
1175
0
      }
1176
0
      const Message* absl_nullable lhs_packed = nullptr;
1177
0
      Unique<Message> lhs_unpacked;
1178
0
      if (lhs_field != nullptr && IsAnyField(lhs_field)) {
1179
0
        lhs_packed = &lhs.GetReflection()->GetMessage(lhs, lhs_field);
1180
0
      } else if (lhs_field == nullptr && IsAny(lhs)) {
1181
0
        lhs_packed = &lhs;
1182
0
      }
1183
0
      if (lhs_packed != nullptr) {
1184
0
        CEL_RETURN_IF_ERROR(lhs_reflection_.any_reflection.Initialize(
1185
0
            lhs_packed->GetDescriptor()));
1186
0
        auto lhs_type_url = lhs_reflection_.any_reflection.GetTypeUrl(
1187
0
            *lhs_packed, lhs_scratch_);
1188
0
        if (!lhs_type_url.ConsumePrefix("type.googleapis.com/") &&
1189
0
            !lhs_type_url.ConsumePrefix("type.googleprod.com/")) {
1190
0
          return false;
1191
0
        }
1192
0
        if (lhs_type_url != "google.protobuf.Value" &&
1193
0
            lhs_type_url != "google.protobuf.Struct" &&
1194
0
            lhs_type_url != "google.protobuf.Any") {
1195
0
          return false;
1196
0
        }
1197
0
        CEL_ASSIGN_OR_RETURN(lhs_unpacked,
1198
0
                             well_known_types::UnpackAnyIfResolveable(
1199
0
                                 &arena_, lhs_reflection_.any_reflection,
1200
0
                                 *lhs_packed, pool_, factory_));
1201
0
        if (lhs_unpacked) {
1202
0
          lhs_field = nullptr;
1203
0
        }
1204
0
      }
1205
0
      const Message* absl_nonnull lhs_message =
1206
0
          lhs_field != nullptr
1207
0
              ? &lhs.GetReflection()->GetMessage(lhs, lhs_field)
1208
0
          : lhs_unpacked != nullptr ? cel::to_address(lhs_unpacked)
1209
0
                                    : &lhs;
1210
0
      const auto* lhs_descriptor = lhs_message->GetDescriptor();
1211
0
      const auto lhs_well_known_type = lhs_descriptor->well_known_type();
1212
0
      switch (lhs_well_known_type) {
1213
0
        case Descriptor::WELLKNOWNTYPE_VALUE: {
1214
          // map<?, ?> == google.protobuf.Value
1215
0
          CEL_RETURN_IF_ERROR(
1216
0
              lhs_reflection_.value_reflection.Initialize(lhs_descriptor));
1217
0
          if (lhs_reflection_.value_reflection.GetKindCase(*lhs_message) !=
1218
0
              google::protobuf::Value::kStructValue) {
1219
0
            return false;
1220
0
          }
1221
0
          CEL_RETURN_IF_ERROR(lhs_reflection_.struct_reflection.Initialize(
1222
0
              lhs_reflection_.value_reflection.GetStructDescriptor()));
1223
0
          return MapFieldEquals(
1224
0
              lhs_reflection_.value_reflection.GetStructValue(*lhs_message),
1225
0
              lhs_reflection_.struct_reflection.GetFieldsDescriptor(), rhs,
1226
0
              rhs_field);
1227
0
        }
1228
0
        case Descriptor::WELLKNOWNTYPE_STRUCT: {
1229
          // map<?, ?> == google.protobuf.Struct
1230
0
          CEL_RETURN_IF_ERROR(
1231
0
              lhs_reflection_.struct_reflection.Initialize(lhs_descriptor));
1232
0
          return MapFieldEquals(
1233
0
              *lhs_message,
1234
0
              lhs_reflection_.struct_reflection.GetFieldsDescriptor(), rhs,
1235
0
              rhs_field);
1236
0
        }
1237
0
        default:
1238
0
          return false;
1239
0
      }
1240
      // Explicitly unreachable, for ease of reading. Control never leaves this
1241
      // if statement.
1242
0
      ABSL_UNREACHABLE();
1243
0
    }
1244
0
    ABSL_DCHECK(lhs_field == nullptr ||
1245
0
                !lhs_field->is_map());  // Handled above.
1246
0
    ABSL_DCHECK(rhs_field == nullptr ||
1247
0
                !rhs_field->is_map());  // Handled above.
1248
0
    if (lhs_field != nullptr && lhs_field->is_repeated()) {
1249
      // repeated<?> == repeated<?>
1250
      // repeated<?> == google.protobuf.Value
1251
      // repeated<?> == google.protobuf.ListValue
1252
      // repeated<?> == google.protobuf.Any
1253
1254
      // Right hand side should be a repeated, `google.protobuf.Value`,
1255
      // `google.protobuf.ListValue`, or `google.protobuf.Any`.
1256
0
      if (rhs_field != nullptr && rhs_field->is_repeated()) {
1257
        // map<?, ?> == map<?, ?>
1258
0
        return RepeatedFieldEquals(lhs, lhs_field, rhs, rhs_field);
1259
0
      }
1260
0
      if (rhs_field != nullptr &&
1261
0
          rhs_field->type() != FieldDescriptor::TYPE_MESSAGE) {
1262
0
        return false;
1263
0
      }
1264
0
      const Message* absl_nullable rhs_packed = nullptr;
1265
0
      Unique<Message> rhs_unpacked;
1266
0
      if (rhs_field != nullptr && IsAnyField(rhs_field)) {
1267
0
        rhs_packed = &rhs.GetReflection()->GetMessage(rhs, rhs_field);
1268
0
      } else if (rhs_field == nullptr && IsAny(rhs)) {
1269
0
        rhs_packed = &rhs;
1270
0
      }
1271
0
      if (rhs_packed != nullptr) {
1272
0
        CEL_RETURN_IF_ERROR(rhs_reflection_.any_reflection.Initialize(
1273
0
            rhs_packed->GetDescriptor()));
1274
0
        auto rhs_type_url = rhs_reflection_.any_reflection.GetTypeUrl(
1275
0
            *rhs_packed, rhs_scratch_);
1276
0
        if (!rhs_type_url.ConsumePrefix("type.googleapis.com/") &&
1277
0
            !rhs_type_url.ConsumePrefix("type.googleprod.com/")) {
1278
0
          return false;
1279
0
        }
1280
0
        if (rhs_type_url != "google.protobuf.Value" &&
1281
0
            rhs_type_url != "google.protobuf.ListValue" &&
1282
0
            rhs_type_url != "google.protobuf.Any") {
1283
0
          return false;
1284
0
        }
1285
0
        CEL_ASSIGN_OR_RETURN(rhs_unpacked,
1286
0
                             well_known_types::UnpackAnyIfResolveable(
1287
0
                                 &arena_, rhs_reflection_.any_reflection,
1288
0
                                 *rhs_packed, pool_, factory_));
1289
0
        if (rhs_unpacked) {
1290
0
          rhs_field = nullptr;
1291
0
        }
1292
0
      }
1293
0
      const Message* absl_nonnull rhs_message =
1294
0
          rhs_field != nullptr
1295
0
              ? &rhs.GetReflection()->GetMessage(rhs, rhs_field)
1296
0
          : rhs_unpacked != nullptr ? cel::to_address(rhs_unpacked)
1297
0
                                    : &rhs;
1298
0
      const auto* rhs_descriptor = rhs_message->GetDescriptor();
1299
0
      const auto rhs_well_known_type = rhs_descriptor->well_known_type();
1300
0
      switch (rhs_well_known_type) {
1301
0
        case Descriptor::WELLKNOWNTYPE_VALUE: {
1302
          // map<?, ?> == google.protobuf.Value
1303
0
          CEL_RETURN_IF_ERROR(
1304
0
              rhs_reflection_.value_reflection.Initialize(rhs_descriptor));
1305
0
          if (rhs_reflection_.value_reflection.GetKindCase(*rhs_message) !=
1306
0
              google::protobuf::Value::kListValue) {
1307
0
            return false;
1308
0
          }
1309
0
          CEL_RETURN_IF_ERROR(rhs_reflection_.list_value_reflection.Initialize(
1310
0
              rhs_reflection_.value_reflection.GetListValueDescriptor()));
1311
0
          return RepeatedFieldEquals(
1312
0
              lhs, lhs_field,
1313
0
              rhs_reflection_.value_reflection.GetListValue(*rhs_message),
1314
0
              rhs_reflection_.list_value_reflection.GetValuesDescriptor());
1315
0
        }
1316
0
        case Descriptor::WELLKNOWNTYPE_LISTVALUE: {
1317
          // map<?, ?> == google.protobuf.ListValue
1318
0
          CEL_RETURN_IF_ERROR(
1319
0
              rhs_reflection_.list_value_reflection.Initialize(rhs_descriptor));
1320
0
          return RepeatedFieldEquals(
1321
0
              lhs, lhs_field, *rhs_message,
1322
0
              rhs_reflection_.list_value_reflection.GetValuesDescriptor());
1323
0
        }
1324
0
        default:
1325
0
          return false;
1326
0
      }
1327
      // Explicitly unreachable, for ease of reading. Control never leaves this
1328
      // if statement.
1329
0
      ABSL_UNREACHABLE();
1330
0
    }
1331
0
    if (rhs_field != nullptr && rhs_field->is_repeated()) {
1332
      // google.protobuf.Value == repeated<?>
1333
      // google.protobuf.ListValue == repeated<?>
1334
      // google.protobuf.Any == repeated<?>
1335
1336
      // Left hand side should be singular `google.protobuf.Value`
1337
      // `google.protobuf.ListValue`, or `google.protobuf.Any`.
1338
0
      ABSL_DCHECK(lhs_field == nullptr ||
1339
0
                  !lhs_field->is_repeated());  // Handled above.
1340
0
      if (lhs_field != nullptr &&
1341
0
          lhs_field->type() != FieldDescriptor::TYPE_MESSAGE) {
1342
0
        return false;
1343
0
      }
1344
0
      const Message* absl_nullable lhs_packed = nullptr;
1345
0
      Unique<Message> lhs_unpacked;
1346
0
      if (lhs_field != nullptr && IsAnyField(lhs_field)) {
1347
0
        lhs_packed = &lhs.GetReflection()->GetMessage(lhs, lhs_field);
1348
0
      } else if (lhs_field == nullptr && IsAny(lhs)) {
1349
0
        lhs_packed = &lhs;
1350
0
      }
1351
0
      if (lhs_packed != nullptr) {
1352
0
        CEL_RETURN_IF_ERROR(lhs_reflection_.any_reflection.Initialize(
1353
0
            lhs_packed->GetDescriptor()));
1354
0
        auto lhs_type_url = lhs_reflection_.any_reflection.GetTypeUrl(
1355
0
            *lhs_packed, lhs_scratch_);
1356
0
        if (!lhs_type_url.ConsumePrefix("type.googleapis.com/") &&
1357
0
            !lhs_type_url.ConsumePrefix("type.googleprod.com/")) {
1358
0
          return false;
1359
0
        }
1360
0
        if (lhs_type_url != "google.protobuf.Value" &&
1361
0
            lhs_type_url != "google.protobuf.ListValue" &&
1362
0
            lhs_type_url != "google.protobuf.Any") {
1363
0
          return false;
1364
0
        }
1365
0
        CEL_ASSIGN_OR_RETURN(lhs_unpacked,
1366
0
                             well_known_types::UnpackAnyIfResolveable(
1367
0
                                 &arena_, lhs_reflection_.any_reflection,
1368
0
                                 *lhs_packed, pool_, factory_));
1369
0
        if (lhs_unpacked) {
1370
0
          lhs_field = nullptr;
1371
0
        }
1372
0
      }
1373
0
      const Message* absl_nonnull lhs_message =
1374
0
          lhs_field != nullptr
1375
0
              ? &lhs.GetReflection()->GetMessage(lhs, lhs_field)
1376
0
          : lhs_unpacked != nullptr ? cel::to_address(lhs_unpacked)
1377
0
                                    : &lhs;
1378
0
      const auto* lhs_descriptor = lhs_message->GetDescriptor();
1379
0
      const auto lhs_well_known_type = lhs_descriptor->well_known_type();
1380
0
      switch (lhs_well_known_type) {
1381
0
        case Descriptor::WELLKNOWNTYPE_VALUE: {
1382
          // map<?, ?> == google.protobuf.Value
1383
0
          CEL_RETURN_IF_ERROR(
1384
0
              lhs_reflection_.value_reflection.Initialize(lhs_descriptor));
1385
0
          if (lhs_reflection_.value_reflection.GetKindCase(*lhs_message) !=
1386
0
              google::protobuf::Value::kListValue) {
1387
0
            return false;
1388
0
          }
1389
0
          CEL_RETURN_IF_ERROR(lhs_reflection_.list_value_reflection.Initialize(
1390
0
              lhs_reflection_.value_reflection.GetListValueDescriptor()));
1391
0
          return RepeatedFieldEquals(
1392
0
              lhs_reflection_.value_reflection.GetListValue(*lhs_message),
1393
0
              lhs_reflection_.list_value_reflection.GetValuesDescriptor(), rhs,
1394
0
              rhs_field);
1395
0
        }
1396
0
        case Descriptor::WELLKNOWNTYPE_LISTVALUE: {
1397
          // map<?, ?> == google.protobuf.ListValue
1398
0
          CEL_RETURN_IF_ERROR(
1399
0
              lhs_reflection_.list_value_reflection.Initialize(lhs_descriptor));
1400
0
          return RepeatedFieldEquals(
1401
0
              *lhs_message,
1402
0
              lhs_reflection_.list_value_reflection.GetValuesDescriptor(), rhs,
1403
0
              rhs_field);
1404
0
        }
1405
0
        default:
1406
0
          return false;
1407
0
      }
1408
      // Explicitly unreachable, for ease of reading. Control never leaves this
1409
      // if statement.
1410
0
      ABSL_UNREACHABLE();
1411
0
    }
1412
0
    return SingularFieldEquals(lhs, lhs_field, rhs, rhs_field);
1413
0
  }
1414
1415
 private:
1416
  const DescriptorPool* absl_nonnull const pool_;
1417
  MessageFactory* absl_nonnull const factory_;
1418
  google::protobuf::Arena arena_;
1419
  EquatableValueReflection lhs_reflection_;
1420
  EquatableValueReflection rhs_reflection_;
1421
  std::string lhs_scratch_;
1422
  std::string rhs_scratch_;
1423
};
1424
1425
}  // namespace
1426
1427
absl::StatusOr<bool> MessageEquals(const Message& lhs, const Message& rhs,
1428
                                   const DescriptorPool* absl_nonnull pool,
1429
0
                                   MessageFactory* absl_nonnull factory) {
1430
0
  ABSL_DCHECK(pool != nullptr);
1431
0
  ABSL_DCHECK(factory != nullptr);
1432
0
  if (&lhs == &rhs) {
1433
0
    return true;
1434
0
  }
1435
  // MessageEqualsState has quite a large size, so we allocate it on the heap.
1436
  // Ideally we should just hold most of the state at runtime in something like
1437
  // `FlatExpressionEvaluatorState`, so we can avoid allocating this repeatedly.
1438
0
  return std::make_unique<MessageEqualsState>(pool, factory)->Equals(lhs, rhs);
1439
0
}
1440
1441
absl::StatusOr<bool> MessageFieldEquals(
1442
    const Message& lhs, const FieldDescriptor* absl_nonnull lhs_field,
1443
    const Message& rhs, const FieldDescriptor* absl_nonnull rhs_field,
1444
    const DescriptorPool* absl_nonnull pool,
1445
0
    MessageFactory* absl_nonnull factory) {
1446
0
  ABSL_DCHECK(lhs_field != nullptr);
1447
0
  ABSL_DCHECK(rhs_field != nullptr);
1448
0
  ABSL_DCHECK(pool != nullptr);
1449
0
  ABSL_DCHECK(factory != nullptr);
1450
0
  if (&lhs == &rhs && lhs_field == rhs_field) {
1451
0
    return true;
1452
0
  }
1453
  // MessageEqualsState has quite a large size, so we allocate it on the heap.
1454
  // Ideally we should just hold most of the state at runtime in something like
1455
  // `FlatExpressionEvaluatorState`, so we can avoid allocating this repeatedly.
1456
0
  return std::make_unique<MessageEqualsState>(pool, factory)
1457
0
      ->FieldEquals(lhs, lhs_field, rhs, rhs_field);
1458
0
}
1459
1460
absl::StatusOr<bool> MessageFieldEquals(
1461
    const google::protobuf::Message& lhs, const google::protobuf::Message& rhs,
1462
    const google::protobuf::FieldDescriptor* absl_nonnull rhs_field,
1463
    const google::protobuf::DescriptorPool* absl_nonnull pool,
1464
0
    google::protobuf::MessageFactory* absl_nonnull factory) {
1465
0
  ABSL_DCHECK(rhs_field != nullptr);
1466
0
  ABSL_DCHECK(pool != nullptr);
1467
0
  ABSL_DCHECK(factory != nullptr);
1468
  // MessageEqualsState has quite a large size, so we allocate it on the heap.
1469
  // Ideally we should just hold most of the state at runtime in something like
1470
  // `FlatExpressionEvaluatorState`, so we can avoid allocating this repeatedly.
1471
0
  return std::make_unique<MessageEqualsState>(pool, factory)
1472
0
      ->FieldEquals(lhs, nullptr, rhs, rhs_field);
1473
0
}
1474
1475
absl::StatusOr<bool> MessageFieldEquals(
1476
    const google::protobuf::Message& lhs,
1477
    const google::protobuf::FieldDescriptor* absl_nonnull lhs_field,
1478
    const google::protobuf::Message& rhs, const google::protobuf::DescriptorPool* absl_nonnull pool,
1479
0
    google::protobuf::MessageFactory* absl_nonnull factory) {
1480
0
  ABSL_DCHECK(lhs_field != nullptr);
1481
0
  ABSL_DCHECK(pool != nullptr);
1482
0
  ABSL_DCHECK(factory != nullptr);
1483
  // MessageEqualsState has quite a large size, so we allocate it on the heap.
1484
  // Ideally we should just hold most of the state at runtime in something like
1485
  // `FlatExpressionEvaluatorState`, so we can avoid allocating this repeatedly.
1486
0
  return std::make_unique<MessageEqualsState>(pool, factory)
1487
0
      ->FieldEquals(lhs, lhs_field, rhs, nullptr);
1488
0
}
1489
1490
}  // namespace cel::internal