Coverage Report

Created: 2026-05-27 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/common/values/parsed_message_value.h
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
// IWYU pragma: private, include "common/value.h"
16
// IWYU pragma: friend "common/value.h"
17
18
#ifndef THIRD_PARTY_CEL_CPP_COMMON_VALUES_PARSED_MESSAGE_VALUE_H_
19
#define THIRD_PARTY_CEL_CPP_COMMON_VALUES_PARSED_MESSAGE_VALUE_H_
20
21
#include <cstddef>
22
#include <cstdint>
23
#include <memory>
24
#include <ostream>
25
#include <string>
26
#include <utility>
27
28
#include "google/protobuf/any.pb.h"
29
#include "google/protobuf/struct.pb.h"
30
#include "absl/base/attributes.h"
31
#include "absl/base/nullability.h"
32
#include "absl/log/absl_check.h"
33
#include "absl/status/status.h"
34
#include "absl/status/statusor.h"
35
#include "absl/strings/string_view.h"
36
#include "absl/types/span.h"
37
#include "base/attribute.h"
38
#include "common/memory.h"
39
#include "common/type.h"
40
#include "common/value_kind.h"
41
#include "common/values/custom_struct_value.h"
42
#include "common/values/values.h"
43
#include "runtime/runtime_options.h"
44
#include "google/protobuf/arena.h"
45
#include "google/protobuf/descriptor.h"
46
#include "google/protobuf/io/zero_copy_stream.h"
47
#include "google/protobuf/message.h"
48
49
namespace cel {
50
51
class MessageValue;
52
class StructValue;
53
class Value;
54
55
class ParsedMessageValue final
56
    : private common_internal::StructValueMixin<ParsedMessageValue> {
57
 public:
58
  static constexpr ValueKind kKind = ValueKind::kStruct;
59
60
  using element_type = const google::protobuf::Message;
61
62
  ParsedMessageValue(
63
      const google::protobuf::Message* absl_nonnull value ABSL_ATTRIBUTE_LIFETIME_BOUND,
64
      google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND)
65
0
      : value_(value), arena_(arena) {
66
0
    ABSL_DCHECK(value != nullptr);
67
0
    ABSL_DCHECK(arena != nullptr);
68
0
    ABSL_DCHECK(!value_ || !IsWellKnownMessageType(value_->GetDescriptor()))
69
0
        << value_->GetTypeName() << " is a well known type";
70
0
    ABSL_DCHECK(!value_ || value_->GetReflection() != nullptr)
71
0
        << value_->GetTypeName() << " is missing reflection";
72
0
    ABSL_DCHECK_OK(CheckArena(value_, arena_));
73
0
  }
74
75
  // Places the `ParsedMessageValue` into a special state where it is logically
76
  // equivalent to the default instance of `google.protobuf.Empty`, however
77
  // dereferencing via `operator*` or `operator->` is not allowed.
78
  ParsedMessageValue();
79
  ParsedMessageValue(const ParsedMessageValue&) = default;
80
  ParsedMessageValue(ParsedMessageValue&&) = default;
81
  ParsedMessageValue& operator=(const ParsedMessageValue&) = default;
82
  ParsedMessageValue& operator=(ParsedMessageValue&&) = default;
83
84
0
  static constexpr ValueKind kind() { return kKind; }
85
86
0
  absl::string_view GetTypeName() const { return GetDescriptor()->full_name(); }
87
88
0
  MessageType GetRuntimeType() const { return MessageType(GetDescriptor()); }
89
90
0
  const google::protobuf::Descriptor* absl_nonnull GetDescriptor() const {
91
0
    return (*this)->GetDescriptor();
92
0
  }
93
94
0
  const google::protobuf::Reflection* absl_nonnull GetReflection() const {
95
0
    return (*this)->GetReflection();
96
0
  }
97
98
0
  const google::protobuf::Message& operator*() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
99
0
    return *value_;
100
0
  }
101
102
  const google::protobuf::Message* absl_nonnull operator->() const
103
0
      ABSL_ATTRIBUTE_LIFETIME_BOUND {
104
0
    return value_;
105
0
  }
106
107
  bool IsZeroValue() const;
108
109
  std::string DebugString() const;
110
111
  // See Value::SerializeTo().
112
  absl::Status SerializeTo(
113
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
114
      google::protobuf::MessageFactory* absl_nonnull message_factory,
115
      google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const;
116
117
  // See Value::ConvertToJson().
118
  absl::Status ConvertToJson(
119
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
120
      google::protobuf::MessageFactory* absl_nonnull message_factory,
121
      google::protobuf::Message* absl_nonnull json) const;
122
123
  // See Value::ConvertToJsonObject().
124
  absl::Status ConvertToJsonObject(
125
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
126
      google::protobuf::MessageFactory* absl_nonnull message_factory,
127
      google::protobuf::Message* absl_nonnull json) const;
128
129
  absl::Status Equal(const Value& other,
130
                     const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
131
                     google::protobuf::MessageFactory* absl_nonnull message_factory,
132
                     google::protobuf::Arena* absl_nonnull arena,
133
                     Value* absl_nonnull result) const;
134
  using StructValueMixin::Equal;
135
136
  ParsedMessageValue Clone(google::protobuf::Arena* absl_nonnull arena) const;
137
138
  absl::Status GetFieldByName(
139
      absl::string_view name, ProtoWrapperTypeOptions unboxing_options,
140
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
141
      google::protobuf::MessageFactory* absl_nonnull message_factory,
142
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const;
143
  using StructValueMixin::GetFieldByName;
144
145
  absl::Status GetFieldByNumber(
146
      int64_t number, ProtoWrapperTypeOptions unboxing_options,
147
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
148
      google::protobuf::MessageFactory* absl_nonnull message_factory,
149
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const;
150
  using StructValueMixin::GetFieldByNumber;
151
152
  absl::StatusOr<bool> HasFieldByName(absl::string_view name) const;
153
154
  absl::StatusOr<bool> HasFieldByNumber(int64_t number) const;
155
156
  using ForEachFieldCallback = CustomStructValueInterface::ForEachFieldCallback;
157
158
  absl::Status ForEachField(
159
      ForEachFieldCallback callback,
160
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
161
      google::protobuf::MessageFactory* absl_nonnull message_factory,
162
      google::protobuf::Arena* absl_nonnull arena) const;
163
164
  absl::Status Qualify(
165
      absl::Span<const SelectQualifier> qualifiers, bool presence_test,
166
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
167
      google::protobuf::MessageFactory* absl_nonnull message_factory,
168
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result,
169
      int* absl_nonnull count) const;
170
  using StructValueMixin::Qualify;
171
172
0
  friend void swap(ParsedMessageValue& lhs, ParsedMessageValue& rhs) noexcept {
173
0
    using std::swap;
174
0
    swap(lhs.value_, rhs.value_);
175
0
    swap(lhs.arena_, rhs.arena_);
176
0
  }
177
178
 private:
179
  friend std::pointer_traits<ParsedMessageValue>;
180
  friend class StructValue;
181
  friend class common_internal::ValueMixin<ParsedMessageValue>;
182
  friend class common_internal::StructValueMixin<ParsedMessageValue>;
183
  friend ParsedMessageValue UnsafeParsedMessageValue(
184
      const google::protobuf::Message* absl_nonnull value);
185
186
  explicit ParsedMessageValue(
187
      const google::protobuf::Message* absl_nonnull value ABSL_ATTRIBUTE_LIFETIME_BOUND)
188
0
      : value_(value), arena_(value->GetArena()) {
189
0
    ABSL_DCHECK(value != nullptr);
190
0
    ABSL_DCHECK(!value_ || !IsWellKnownMessageType(value_->GetDescriptor()))
191
0
        << value_->GetTypeName() << " is a well known type";
192
0
    ABSL_DCHECK(!value_ || value_->GetReflection() != nullptr)
193
0
        << value_->GetTypeName() << " is missing reflection";
194
0
  }
195
196
  static absl::Status CheckArena(const google::protobuf::Message* absl_nullable message,
197
0
                                 google::protobuf::Arena* absl_nonnull arena) {
198
0
    if (message != nullptr && message->GetArena() != nullptr &&
199
0
        message->GetArena() != arena) {
200
0
      return absl::InvalidArgumentError(
201
0
          "message arena must be the same as arena");
202
0
    }
203
0
    return absl::OkStatus();
204
0
  }
205
206
  absl::Status GetField(
207
      const google::protobuf::FieldDescriptor* absl_nonnull field,
208
      ProtoWrapperTypeOptions unboxing_options,
209
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
210
      google::protobuf::MessageFactory* absl_nonnull message_factory,
211
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const;
212
213
  bool HasField(const google::protobuf::FieldDescriptor* absl_nonnull field) const;
214
215
  const google::protobuf::Message* absl_nonnull value_;
216
  // Arena that is attributed as owning the value. May be null to indicate that
217
  // the value is managed externally.
218
  google::protobuf::Arena* absl_nullable arena_;
219
};
220
221
inline std::ostream& operator<<(std::ostream& out,
222
0
                                const ParsedMessageValue& value) {
223
0
  return out << value.DebugString();
224
0
}
225
226
// Creates a `ParsedMessageValue` without specifying a managing arena.
227
// The message must outlive the `ParsedMessageValue` or any value that might
228
// be derived from it. Prefer to use `cel::Value::WrapMessageUnsafe()`.
229
inline ParsedMessageValue UnsafeParsedMessageValue(
230
0
    const google::protobuf::Message* absl_nonnull value) {
231
0
  return ParsedMessageValue(value);
232
0
}
233
234
}  // namespace cel
235
236
namespace std {
237
238
template <>
239
struct pointer_traits<cel::ParsedMessageValue> {
240
  using pointer = cel::ParsedMessageValue;
241
  using element_type = typename cel::ParsedMessageValue::element_type;
242
  using difference_type = ptrdiff_t;
243
244
0
  static element_type* to_address(const pointer& p) noexcept {
245
0
    return cel::to_address(p.value_);
246
0
  }
247
};
248
249
}  // namespace std
250
251
#endif  // THIRD_PARTY_CEL_CPP_COMMON_VALUES_PARSED_MESSAGE_VALUE_H_