Coverage Report

Created: 2026-09-14 06:52

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
namespace interop_internal {
52
bool IsUnsafeParsedMessageValue(const ParsedMessageValue& value);
53
}
54
55
class MessageValue;
56
class StructValue;
57
class Value;
58
59
class ParsedMessageValue final
60
    : private common_internal::StructValueMixin<ParsedMessageValue> {
61
 public:
62
  static constexpr ValueKind kKind = ValueKind::kStruct;
63
64
  using element_type = const google::protobuf::Message;
65
66
  ParsedMessageValue(
67
      const google::protobuf::Message* absl_nonnull value ABSL_ATTRIBUTE_LIFETIME_BOUND,
68
      google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND)
69
245k
      : value_(value), arena_(arena) {
70
245k
    ABSL_DCHECK(value != nullptr);
71
245k
    ABSL_DCHECK(arena != nullptr);
72
491k
    ABSL_DCHECK(!value_ || !IsWellKnownMessageType(value_->GetDescriptor()))
73
491k
        << value_->GetTypeName() << " is a well known type";
74
491k
    ABSL_DCHECK(!value_ || value_->GetReflection() != nullptr)
75
491k
        << value_->GetTypeName() << " is missing reflection";
76
245k
    ABSL_DCHECK_OK(CheckArena(value_, arena_));
77
245k
  }
78
79
  // Places the `ParsedMessageValue` into a special state where it is logically
80
  // equivalent to the default instance of `google.protobuf.Empty`, however
81
  // dereferencing via `operator*` or `operator->` is not allowed.
82
  ParsedMessageValue();
83
  ParsedMessageValue(const ParsedMessageValue&) = default;
84
  ParsedMessageValue(ParsedMessageValue&&) = default;
85
  ParsedMessageValue& operator=(const ParsedMessageValue&) = default;
86
  ParsedMessageValue& operator=(ParsedMessageValue&&) = default;
87
88
0
  static constexpr ValueKind kind() { return kKind; }
89
90
0
  absl::string_view GetTypeName() const { return GetDescriptor()->full_name(); }
91
92
0
  MessageType GetRuntimeType() const { return MessageType(GetDescriptor()); }
93
94
195k
  const google::protobuf::Descriptor* absl_nonnull GetDescriptor() const {
95
195k
    return (*this)->GetDescriptor();
96
195k
  }
97
98
0
  const google::protobuf::Reflection* absl_nonnull GetReflection() const {
99
0
    return (*this)->GetReflection();
100
0
  }
101
102
20.1k
  const google::protobuf::Message& operator*() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
103
20.1k
    return *value_;
104
20.1k
  }
105
106
195k
  const google::protobuf::Message* absl_nonnull operator->() const { return value_; }
107
0
  const google::protobuf::Message* absl_nonnull message() const { return value_; }
108
109
  bool IsZeroValue() const;
110
111
  std::string DebugString() const;
112
113
  // See Value::SerializeTo().
114
  absl::Status SerializeTo(
115
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
116
      google::protobuf::MessageFactory* absl_nonnull message_factory,
117
      google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const;
118
119
  // See Value::ConvertToJson().
120
  absl::Status ConvertToJson(
121
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
122
      google::protobuf::MessageFactory* absl_nonnull message_factory,
123
      google::protobuf::Message* absl_nonnull json) const;
124
125
  // See Value::ConvertToJsonObject().
126
  absl::Status ConvertToJsonObject(
127
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
128
      google::protobuf::MessageFactory* absl_nonnull message_factory,
129
      google::protobuf::Message* absl_nonnull json) const;
130
131
  absl::Status Equal(const Value& other,
132
                     const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
133
                     google::protobuf::MessageFactory* absl_nonnull message_factory,
134
                     google::protobuf::Arena* absl_nonnull arena,
135
                     Value* absl_nonnull result) const;
136
  using StructValueMixin::Equal;
137
138
  ParsedMessageValue Clone(google::protobuf::Arena* absl_nonnull arena) const;
139
140
  absl::Status GetFieldByName(
141
      absl::string_view name, ProtoWrapperTypeOptions unboxing_options,
142
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
143
      google::protobuf::MessageFactory* absl_nonnull message_factory,
144
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const;
145
  using StructValueMixin::GetFieldByName;
146
147
  absl::Status GetFieldByNumber(
148
      int64_t number, ProtoWrapperTypeOptions unboxing_options,
149
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
150
      google::protobuf::MessageFactory* absl_nonnull message_factory,
151
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const;
152
  using StructValueMixin::GetFieldByNumber;
153
154
  absl::StatusOr<bool> HasFieldByName(absl::string_view name) const;
155
156
  absl::StatusOr<bool> HasFieldByNumber(int64_t number) const;
157
158
  using ForEachFieldCallback = CustomStructValueInterface::ForEachFieldCallback;
159
160
  absl::Status ForEachField(
161
      ForEachFieldCallback callback,
162
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
163
      google::protobuf::MessageFactory* absl_nonnull message_factory,
164
      google::protobuf::Arena* absl_nonnull arena) const;
165
166
  absl::Status Qualify(
167
      absl::Span<const SelectQualifier> qualifiers, bool presence_test,
168
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
169
      google::protobuf::MessageFactory* absl_nonnull message_factory,
170
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result,
171
      int* absl_nonnull count) const;
172
  using StructValueMixin::Qualify;
173
174
0
  friend void swap(ParsedMessageValue& lhs, ParsedMessageValue& rhs) noexcept {
175
0
    using std::swap;
176
0
    swap(lhs.value_, rhs.value_);
177
0
    swap(lhs.arena_, rhs.arena_);
178
0
  }
179
180
  absl::Status GetField(
181
      const google::protobuf::FieldDescriptor* absl_nonnull field,
182
      ProtoWrapperTypeOptions unboxing_options,
183
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
184
      google::protobuf::MessageFactory* absl_nonnull message_factory,
185
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const;
186
187
  bool HasField(const google::protobuf::FieldDescriptor* absl_nonnull field) const;
188
189
 private:
190
  friend std::pointer_traits<ParsedMessageValue>;
191
  friend class StructValue;
192
  friend class common_internal::ValueMixin<ParsedMessageValue>;
193
  friend class common_internal::StructValueMixin<ParsedMessageValue>;
194
  friend ParsedMessageValue UnsafeParsedMessageValue(
195
      const google::protobuf::Message* absl_nonnull value);
196
  friend bool interop_internal::IsUnsafeParsedMessageValue(
197
      const ParsedMessageValue& value);
198
199
  explicit ParsedMessageValue(
200
      const google::protobuf::Message* absl_nonnull value ABSL_ATTRIBUTE_LIFETIME_BOUND)
201
235k
      : value_(value), arena_(nullptr) {
202
235k
    ABSL_DCHECK(value != nullptr);
203
471k
    ABSL_DCHECK(!value_ || !IsWellKnownMessageType(value_->GetDescriptor()))
204
471k
        << value_->GetTypeName() << " is a well known type";
205
471k
    ABSL_DCHECK(!value_ || value_->GetReflection() != nullptr)
206
471k
        << value_->GetTypeName() << " is missing reflection";
207
235k
  }
208
209
  static absl::Status CheckArena(const google::protobuf::Message* absl_nullable message,
210
0
                                 google::protobuf::Arena* absl_nonnull arena) {
211
0
    if (message != nullptr && message->GetArena() != nullptr &&
212
0
        message->GetArena() != arena) {
213
0
      return absl::InvalidArgumentError(
214
0
          "message arena must be the same as arena");
215
0
    }
216
0
    return absl::OkStatus();
217
0
  }
218
219
245k
  bool is_unsafe() const { return arena_ == nullptr; }
220
221
  const google::protobuf::Message* absl_nonnull value_;
222
223
  // The arena attributed as Owning this value. Null if the value is created by
224
  // UnsafeParsedMessageValue() or derived from such a value. This is used to
225
  // identify externally managed messages and propagating the unsafe field
226
  // access behavior.
227
  google::protobuf::Arena* absl_nullable arena_;
228
};
229
230
inline std::ostream& operator<<(std::ostream& out,
231
0
                                const ParsedMessageValue& value) {
232
0
  return out << value.DebugString();
233
0
}
234
235
// Creates a `ParsedMessageValue` without specifying a managing arena.
236
// The message must outlive the `ParsedMessageValue` or any value that might
237
// be derived from it. Prefer to use `cel::Value::WrapMessageUnsafe()`.
238
inline ParsedMessageValue UnsafeParsedMessageValue(
239
235k
    const google::protobuf::Message* absl_nonnull value) {
240
235k
  return ParsedMessageValue(value);
241
235k
}
242
243
}  // namespace cel
244
245
namespace std {
246
247
template <>
248
struct pointer_traits<cel::ParsedMessageValue> {
249
  using pointer = cel::ParsedMessageValue;
250
  using element_type = typename cel::ParsedMessageValue::element_type;
251
  using difference_type = ptrdiff_t;
252
253
245k
  static element_type* to_address(const pointer& p) noexcept {
254
245k
    return cel::to_address(p.value_);
255
245k
  }
256
};
257
258
}  // namespace std
259
260
#endif  // THIRD_PARTY_CEL_CPP_COMMON_VALUES_PARSED_MESSAGE_VALUE_H_