xref: /aosp_15_r20/external/libprotobuf-mutator/src/field_instance.h (revision fd525a9c096e28cf6f8d8719388df0568a611e7b)
1*fd525a9cSAndroid Build Coastguard Worker // Copyright 2016 Google Inc. All rights reserved.
2*fd525a9cSAndroid Build Coastguard Worker //
3*fd525a9cSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*fd525a9cSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*fd525a9cSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*fd525a9cSAndroid Build Coastguard Worker //
7*fd525a9cSAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*fd525a9cSAndroid Build Coastguard Worker //
9*fd525a9cSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*fd525a9cSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*fd525a9cSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*fd525a9cSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*fd525a9cSAndroid Build Coastguard Worker // limitations under the License.
14*fd525a9cSAndroid Build Coastguard Worker 
15*fd525a9cSAndroid Build Coastguard Worker #ifndef SRC_FIELD_INSTANCE_H_
16*fd525a9cSAndroid Build Coastguard Worker #define SRC_FIELD_INSTANCE_H_
17*fd525a9cSAndroid Build Coastguard Worker 
18*fd525a9cSAndroid Build Coastguard Worker #include <memory>
19*fd525a9cSAndroid Build Coastguard Worker #include <string>
20*fd525a9cSAndroid Build Coastguard Worker 
21*fd525a9cSAndroid Build Coastguard Worker #include "port/protobuf.h"
22*fd525a9cSAndroid Build Coastguard Worker 
23*fd525a9cSAndroid Build Coastguard Worker namespace protobuf_mutator {
24*fd525a9cSAndroid Build Coastguard Worker 
25*fd525a9cSAndroid Build Coastguard Worker // Helper class for common protobuf fields operations.
26*fd525a9cSAndroid Build Coastguard Worker class ConstFieldInstance {
27*fd525a9cSAndroid Build Coastguard Worker  public:
28*fd525a9cSAndroid Build Coastguard Worker   static const size_t kInvalidIndex = -1;
29*fd525a9cSAndroid Build Coastguard Worker 
30*fd525a9cSAndroid Build Coastguard Worker   struct Enum {
31*fd525a9cSAndroid Build Coastguard Worker     size_t index;
32*fd525a9cSAndroid Build Coastguard Worker     size_t count;
33*fd525a9cSAndroid Build Coastguard Worker   };
34*fd525a9cSAndroid Build Coastguard Worker 
ConstFieldInstance()35*fd525a9cSAndroid Build Coastguard Worker   ConstFieldInstance()
36*fd525a9cSAndroid Build Coastguard Worker       : message_(nullptr), descriptor_(nullptr), index_(kInvalidIndex) {}
37*fd525a9cSAndroid Build Coastguard Worker 
ConstFieldInstance(const protobuf::Message * message,const protobuf::FieldDescriptor * field,size_t index)38*fd525a9cSAndroid Build Coastguard Worker   ConstFieldInstance(const protobuf::Message* message,
39*fd525a9cSAndroid Build Coastguard Worker                      const protobuf::FieldDescriptor* field, size_t index)
40*fd525a9cSAndroid Build Coastguard Worker       : message_(message), descriptor_(field), index_(index) {
41*fd525a9cSAndroid Build Coastguard Worker     assert(message_);
42*fd525a9cSAndroid Build Coastguard Worker     assert(descriptor_);
43*fd525a9cSAndroid Build Coastguard Worker     assert(index_ != kInvalidIndex);
44*fd525a9cSAndroid Build Coastguard Worker     assert(descriptor_->is_repeated());
45*fd525a9cSAndroid Build Coastguard Worker   }
46*fd525a9cSAndroid Build Coastguard Worker 
ConstFieldInstance(const protobuf::Message * message,const protobuf::FieldDescriptor * field)47*fd525a9cSAndroid Build Coastguard Worker   ConstFieldInstance(const protobuf::Message* message,
48*fd525a9cSAndroid Build Coastguard Worker                      const protobuf::FieldDescriptor* field)
49*fd525a9cSAndroid Build Coastguard Worker       : message_(message), descriptor_(field), index_(kInvalidIndex) {
50*fd525a9cSAndroid Build Coastguard Worker     assert(message_);
51*fd525a9cSAndroid Build Coastguard Worker     assert(descriptor_);
52*fd525a9cSAndroid Build Coastguard Worker     assert(!descriptor_->is_repeated());
53*fd525a9cSAndroid Build Coastguard Worker   }
54*fd525a9cSAndroid Build Coastguard Worker 
GetDefault(int32_t * out)55*fd525a9cSAndroid Build Coastguard Worker   void GetDefault(int32_t* out) const {
56*fd525a9cSAndroid Build Coastguard Worker     *out = descriptor_->default_value_int32();
57*fd525a9cSAndroid Build Coastguard Worker   }
58*fd525a9cSAndroid Build Coastguard Worker 
GetDefault(int64_t * out)59*fd525a9cSAndroid Build Coastguard Worker   void GetDefault(int64_t* out) const {
60*fd525a9cSAndroid Build Coastguard Worker     *out = descriptor_->default_value_int64();
61*fd525a9cSAndroid Build Coastguard Worker   }
62*fd525a9cSAndroid Build Coastguard Worker 
GetDefault(uint32_t * out)63*fd525a9cSAndroid Build Coastguard Worker   void GetDefault(uint32_t* out) const {
64*fd525a9cSAndroid Build Coastguard Worker     *out = descriptor_->default_value_uint32();
65*fd525a9cSAndroid Build Coastguard Worker   }
66*fd525a9cSAndroid Build Coastguard Worker 
GetDefault(uint64_t * out)67*fd525a9cSAndroid Build Coastguard Worker   void GetDefault(uint64_t* out) const {
68*fd525a9cSAndroid Build Coastguard Worker     *out = descriptor_->default_value_uint64();
69*fd525a9cSAndroid Build Coastguard Worker   }
70*fd525a9cSAndroid Build Coastguard Worker 
GetDefault(double * out)71*fd525a9cSAndroid Build Coastguard Worker   void GetDefault(double* out) const {
72*fd525a9cSAndroid Build Coastguard Worker     *out = descriptor_->default_value_double();
73*fd525a9cSAndroid Build Coastguard Worker   }
74*fd525a9cSAndroid Build Coastguard Worker 
GetDefault(float * out)75*fd525a9cSAndroid Build Coastguard Worker   void GetDefault(float* out) const {
76*fd525a9cSAndroid Build Coastguard Worker     *out = descriptor_->default_value_float();
77*fd525a9cSAndroid Build Coastguard Worker   }
78*fd525a9cSAndroid Build Coastguard Worker 
GetDefault(bool * out)79*fd525a9cSAndroid Build Coastguard Worker   void GetDefault(bool* out) const { *out = descriptor_->default_value_bool(); }
80*fd525a9cSAndroid Build Coastguard Worker 
GetDefault(Enum * out)81*fd525a9cSAndroid Build Coastguard Worker   void GetDefault(Enum* out) const {
82*fd525a9cSAndroid Build Coastguard Worker     const protobuf::EnumValueDescriptor* value =
83*fd525a9cSAndroid Build Coastguard Worker         descriptor_->default_value_enum();
84*fd525a9cSAndroid Build Coastguard Worker     const protobuf::EnumDescriptor* type = value->type();
85*fd525a9cSAndroid Build Coastguard Worker     *out = {static_cast<size_t>(value->index()),
86*fd525a9cSAndroid Build Coastguard Worker             static_cast<size_t>(type->value_count())};
87*fd525a9cSAndroid Build Coastguard Worker   }
88*fd525a9cSAndroid Build Coastguard Worker 
GetDefault(std::string * out)89*fd525a9cSAndroid Build Coastguard Worker   void GetDefault(std::string* out) const {
90*fd525a9cSAndroid Build Coastguard Worker     *out = descriptor_->default_value_string();
91*fd525a9cSAndroid Build Coastguard Worker   }
92*fd525a9cSAndroid Build Coastguard Worker 
GetDefault(std::unique_ptr<protobuf::Message> * out)93*fd525a9cSAndroid Build Coastguard Worker   void GetDefault(std::unique_ptr<protobuf::Message>* out) const {
94*fd525a9cSAndroid Build Coastguard Worker     out->reset(reflection()
95*fd525a9cSAndroid Build Coastguard Worker                    .GetMessageFactory()
96*fd525a9cSAndroid Build Coastguard Worker                    ->GetPrototype(descriptor_->message_type())
97*fd525a9cSAndroid Build Coastguard Worker                    ->New());
98*fd525a9cSAndroid Build Coastguard Worker   }
99*fd525a9cSAndroid Build Coastguard Worker 
Load(int32_t * value)100*fd525a9cSAndroid Build Coastguard Worker   void Load(int32_t* value) const {
101*fd525a9cSAndroid Build Coastguard Worker     *value = is_repeated()
102*fd525a9cSAndroid Build Coastguard Worker                  ? reflection().GetRepeatedInt32(*message_, descriptor_, index_)
103*fd525a9cSAndroid Build Coastguard Worker                  : reflection().GetInt32(*message_, descriptor_);
104*fd525a9cSAndroid Build Coastguard Worker   }
105*fd525a9cSAndroid Build Coastguard Worker 
Load(int64_t * value)106*fd525a9cSAndroid Build Coastguard Worker   void Load(int64_t* value) const {
107*fd525a9cSAndroid Build Coastguard Worker     *value = is_repeated()
108*fd525a9cSAndroid Build Coastguard Worker                  ? reflection().GetRepeatedInt64(*message_, descriptor_, index_)
109*fd525a9cSAndroid Build Coastguard Worker                  : reflection().GetInt64(*message_, descriptor_);
110*fd525a9cSAndroid Build Coastguard Worker   }
111*fd525a9cSAndroid Build Coastguard Worker 
Load(uint32_t * value)112*fd525a9cSAndroid Build Coastguard Worker   void Load(uint32_t* value) const {
113*fd525a9cSAndroid Build Coastguard Worker     *value = is_repeated() ? reflection().GetRepeatedUInt32(*message_,
114*fd525a9cSAndroid Build Coastguard Worker                                                             descriptor_, index_)
115*fd525a9cSAndroid Build Coastguard Worker                            : reflection().GetUInt32(*message_, descriptor_);
116*fd525a9cSAndroid Build Coastguard Worker   }
117*fd525a9cSAndroid Build Coastguard Worker 
Load(uint64_t * value)118*fd525a9cSAndroid Build Coastguard Worker   void Load(uint64_t* value) const {
119*fd525a9cSAndroid Build Coastguard Worker     *value = is_repeated() ? reflection().GetRepeatedUInt64(*message_,
120*fd525a9cSAndroid Build Coastguard Worker                                                             descriptor_, index_)
121*fd525a9cSAndroid Build Coastguard Worker                            : reflection().GetUInt64(*message_, descriptor_);
122*fd525a9cSAndroid Build Coastguard Worker   }
123*fd525a9cSAndroid Build Coastguard Worker 
Load(double * value)124*fd525a9cSAndroid Build Coastguard Worker   void Load(double* value) const {
125*fd525a9cSAndroid Build Coastguard Worker     *value = is_repeated() ? reflection().GetRepeatedDouble(*message_,
126*fd525a9cSAndroid Build Coastguard Worker                                                             descriptor_, index_)
127*fd525a9cSAndroid Build Coastguard Worker                            : reflection().GetDouble(*message_, descriptor_);
128*fd525a9cSAndroid Build Coastguard Worker   }
129*fd525a9cSAndroid Build Coastguard Worker 
Load(float * value)130*fd525a9cSAndroid Build Coastguard Worker   void Load(float* value) const {
131*fd525a9cSAndroid Build Coastguard Worker     *value = is_repeated()
132*fd525a9cSAndroid Build Coastguard Worker                  ? reflection().GetRepeatedFloat(*message_, descriptor_, index_)
133*fd525a9cSAndroid Build Coastguard Worker                  : reflection().GetFloat(*message_, descriptor_);
134*fd525a9cSAndroid Build Coastguard Worker   }
135*fd525a9cSAndroid Build Coastguard Worker 
Load(bool * value)136*fd525a9cSAndroid Build Coastguard Worker   void Load(bool* value) const {
137*fd525a9cSAndroid Build Coastguard Worker     *value = is_repeated()
138*fd525a9cSAndroid Build Coastguard Worker                  ? reflection().GetRepeatedBool(*message_, descriptor_, index_)
139*fd525a9cSAndroid Build Coastguard Worker                  : reflection().GetBool(*message_, descriptor_);
140*fd525a9cSAndroid Build Coastguard Worker   }
141*fd525a9cSAndroid Build Coastguard Worker 
Load(Enum * value)142*fd525a9cSAndroid Build Coastguard Worker   void Load(Enum* value) const {
143*fd525a9cSAndroid Build Coastguard Worker     const protobuf::EnumValueDescriptor* value_descriptor =
144*fd525a9cSAndroid Build Coastguard Worker         is_repeated()
145*fd525a9cSAndroid Build Coastguard Worker             ? reflection().GetRepeatedEnum(*message_, descriptor_, index_)
146*fd525a9cSAndroid Build Coastguard Worker             : reflection().GetEnum(*message_, descriptor_);
147*fd525a9cSAndroid Build Coastguard Worker     *value = {static_cast<size_t>(value_descriptor->index()),
148*fd525a9cSAndroid Build Coastguard Worker               static_cast<size_t>(value_descriptor->type()->value_count())};
149*fd525a9cSAndroid Build Coastguard Worker     if (value->index >= value->count) GetDefault(value);
150*fd525a9cSAndroid Build Coastguard Worker   }
151*fd525a9cSAndroid Build Coastguard Worker 
Load(std::string * value)152*fd525a9cSAndroid Build Coastguard Worker   void Load(std::string* value) const {
153*fd525a9cSAndroid Build Coastguard Worker     *value = is_repeated() ? reflection().GetRepeatedString(*message_,
154*fd525a9cSAndroid Build Coastguard Worker                                                             descriptor_, index_)
155*fd525a9cSAndroid Build Coastguard Worker                            : reflection().GetString(*message_, descriptor_);
156*fd525a9cSAndroid Build Coastguard Worker   }
157*fd525a9cSAndroid Build Coastguard Worker 
Load(std::unique_ptr<protobuf::Message> * value)158*fd525a9cSAndroid Build Coastguard Worker   void Load(std::unique_ptr<protobuf::Message>* value) const {
159*fd525a9cSAndroid Build Coastguard Worker     const protobuf::Message& source =
160*fd525a9cSAndroid Build Coastguard Worker         is_repeated()
161*fd525a9cSAndroid Build Coastguard Worker             ? reflection().GetRepeatedMessage(*message_, descriptor_, index_)
162*fd525a9cSAndroid Build Coastguard Worker             : reflection().GetMessage(*message_, descriptor_);
163*fd525a9cSAndroid Build Coastguard Worker     value->reset(source.New());
164*fd525a9cSAndroid Build Coastguard Worker     (*value)->CopyFrom(source);
165*fd525a9cSAndroid Build Coastguard Worker   }
166*fd525a9cSAndroid Build Coastguard Worker 
167*fd525a9cSAndroid Build Coastguard Worker   template <class T>
CanStore(const T & value)168*fd525a9cSAndroid Build Coastguard Worker   bool CanStore(const T& value) const {
169*fd525a9cSAndroid Build Coastguard Worker     return true;
170*fd525a9cSAndroid Build Coastguard Worker   }
171*fd525a9cSAndroid Build Coastguard Worker 
CanStore(const std::string & value)172*fd525a9cSAndroid Build Coastguard Worker   bool CanStore(const std::string& value) const {
173*fd525a9cSAndroid Build Coastguard Worker     if (!EnforceUtf8()) return true;
174*fd525a9cSAndroid Build Coastguard Worker     using protobuf::internal::WireFormatLite;
175*fd525a9cSAndroid Build Coastguard Worker     return WireFormatLite::VerifyUtf8String(value.data(), value.length(),
176*fd525a9cSAndroid Build Coastguard Worker                                             WireFormatLite::PARSE, "");
177*fd525a9cSAndroid Build Coastguard Worker   }
178*fd525a9cSAndroid Build Coastguard Worker 
name()179*fd525a9cSAndroid Build Coastguard Worker   std::string name() const { return descriptor_->name(); }
180*fd525a9cSAndroid Build Coastguard Worker 
cpp_type()181*fd525a9cSAndroid Build Coastguard Worker   protobuf::FieldDescriptor::CppType cpp_type() const {
182*fd525a9cSAndroid Build Coastguard Worker     return descriptor_->cpp_type();
183*fd525a9cSAndroid Build Coastguard Worker   }
184*fd525a9cSAndroid Build Coastguard Worker 
enum_type()185*fd525a9cSAndroid Build Coastguard Worker   const protobuf::EnumDescriptor* enum_type() const {
186*fd525a9cSAndroid Build Coastguard Worker     return descriptor_->enum_type();
187*fd525a9cSAndroid Build Coastguard Worker   }
188*fd525a9cSAndroid Build Coastguard Worker 
message_type()189*fd525a9cSAndroid Build Coastguard Worker   const protobuf::Descriptor* message_type() const {
190*fd525a9cSAndroid Build Coastguard Worker     return descriptor_->message_type();
191*fd525a9cSAndroid Build Coastguard Worker   }
192*fd525a9cSAndroid Build Coastguard Worker 
EnforceUtf8()193*fd525a9cSAndroid Build Coastguard Worker   bool EnforceUtf8() const {
194*fd525a9cSAndroid Build Coastguard Worker     return descriptor_->type() == protobuf::FieldDescriptor::TYPE_STRING &&
195*fd525a9cSAndroid Build Coastguard Worker            descriptor()->file()->syntax() ==
196*fd525a9cSAndroid Build Coastguard Worker                protobuf::FileDescriptor::SYNTAX_PROTO3;
197*fd525a9cSAndroid Build Coastguard Worker   }
198*fd525a9cSAndroid Build Coastguard Worker 
descriptor()199*fd525a9cSAndroid Build Coastguard Worker   const protobuf::FieldDescriptor* descriptor() const { return descriptor_; }
200*fd525a9cSAndroid Build Coastguard Worker 
DebugString()201*fd525a9cSAndroid Build Coastguard Worker   std::string DebugString() const {
202*fd525a9cSAndroid Build Coastguard Worker     std::string s = descriptor_->DebugString();
203*fd525a9cSAndroid Build Coastguard Worker     if (is_repeated()) s += "[" + std::to_string(index_) + "]";
204*fd525a9cSAndroid Build Coastguard Worker     return s + " of\n" + message_->DebugString();
205*fd525a9cSAndroid Build Coastguard Worker   }
206*fd525a9cSAndroid Build Coastguard Worker 
207*fd525a9cSAndroid Build Coastguard Worker  protected:
is_repeated()208*fd525a9cSAndroid Build Coastguard Worker   bool is_repeated() const { return descriptor_->is_repeated(); }
209*fd525a9cSAndroid Build Coastguard Worker 
reflection()210*fd525a9cSAndroid Build Coastguard Worker   const protobuf::Reflection& reflection() const {
211*fd525a9cSAndroid Build Coastguard Worker     return *message_->GetReflection();
212*fd525a9cSAndroid Build Coastguard Worker   }
213*fd525a9cSAndroid Build Coastguard Worker 
index()214*fd525a9cSAndroid Build Coastguard Worker   size_t index() const { return index_; }
215*fd525a9cSAndroid Build Coastguard Worker 
216*fd525a9cSAndroid Build Coastguard Worker  private:
217*fd525a9cSAndroid Build Coastguard Worker   template <class Fn, class T>
218*fd525a9cSAndroid Build Coastguard Worker   friend struct FieldFunction;
219*fd525a9cSAndroid Build Coastguard Worker 
220*fd525a9cSAndroid Build Coastguard Worker   const protobuf::Message* message_;
221*fd525a9cSAndroid Build Coastguard Worker   const protobuf::FieldDescriptor* descriptor_;
222*fd525a9cSAndroid Build Coastguard Worker   size_t index_;
223*fd525a9cSAndroid Build Coastguard Worker };
224*fd525a9cSAndroid Build Coastguard Worker 
225*fd525a9cSAndroid Build Coastguard Worker class FieldInstance : public ConstFieldInstance {
226*fd525a9cSAndroid Build Coastguard Worker  public:
227*fd525a9cSAndroid Build Coastguard Worker   static const size_t kInvalidIndex = -1;
228*fd525a9cSAndroid Build Coastguard Worker 
FieldInstance()229*fd525a9cSAndroid Build Coastguard Worker   FieldInstance() : ConstFieldInstance(), message_(nullptr) {}
230*fd525a9cSAndroid Build Coastguard Worker 
FieldInstance(protobuf::Message * message,const protobuf::FieldDescriptor * field,size_t index)231*fd525a9cSAndroid Build Coastguard Worker   FieldInstance(protobuf::Message* message,
232*fd525a9cSAndroid Build Coastguard Worker                 const protobuf::FieldDescriptor* field, size_t index)
233*fd525a9cSAndroid Build Coastguard Worker       : ConstFieldInstance(message, field, index), message_(message) {}
234*fd525a9cSAndroid Build Coastguard Worker 
FieldInstance(protobuf::Message * message,const protobuf::FieldDescriptor * field)235*fd525a9cSAndroid Build Coastguard Worker   FieldInstance(protobuf::Message* message,
236*fd525a9cSAndroid Build Coastguard Worker                 const protobuf::FieldDescriptor* field)
237*fd525a9cSAndroid Build Coastguard Worker       : ConstFieldInstance(message, field), message_(message) {}
238*fd525a9cSAndroid Build Coastguard Worker 
Delete()239*fd525a9cSAndroid Build Coastguard Worker   void Delete() const {
240*fd525a9cSAndroid Build Coastguard Worker     if (!is_repeated()) return reflection().ClearField(message_, descriptor());
241*fd525a9cSAndroid Build Coastguard Worker     int field_size = reflection().FieldSize(*message_, descriptor());
242*fd525a9cSAndroid Build Coastguard Worker     // API has only method to delete the last message, so we move method from
243*fd525a9cSAndroid Build Coastguard Worker     // the
244*fd525a9cSAndroid Build Coastguard Worker     // middle to the end.
245*fd525a9cSAndroid Build Coastguard Worker     for (int i = index() + 1; i < field_size; ++i)
246*fd525a9cSAndroid Build Coastguard Worker       reflection().SwapElements(message_, descriptor(), i, i - 1);
247*fd525a9cSAndroid Build Coastguard Worker     reflection().RemoveLast(message_, descriptor());
248*fd525a9cSAndroid Build Coastguard Worker   }
249*fd525a9cSAndroid Build Coastguard Worker 
250*fd525a9cSAndroid Build Coastguard Worker   template <class T>
Create(const T & value)251*fd525a9cSAndroid Build Coastguard Worker   void Create(const T& value) const {
252*fd525a9cSAndroid Build Coastguard Worker     if (!is_repeated()) return Store(value);
253*fd525a9cSAndroid Build Coastguard Worker     InsertRepeated(value);
254*fd525a9cSAndroid Build Coastguard Worker   }
255*fd525a9cSAndroid Build Coastguard Worker 
Store(int32_t value)256*fd525a9cSAndroid Build Coastguard Worker   void Store(int32_t value) const {
257*fd525a9cSAndroid Build Coastguard Worker     if (is_repeated())
258*fd525a9cSAndroid Build Coastguard Worker       reflection().SetRepeatedInt32(message_, descriptor(), index(), value);
259*fd525a9cSAndroid Build Coastguard Worker     else
260*fd525a9cSAndroid Build Coastguard Worker       reflection().SetInt32(message_, descriptor(), value);
261*fd525a9cSAndroid Build Coastguard Worker   }
262*fd525a9cSAndroid Build Coastguard Worker 
Store(int64_t value)263*fd525a9cSAndroid Build Coastguard Worker   void Store(int64_t value) const {
264*fd525a9cSAndroid Build Coastguard Worker     if (is_repeated())
265*fd525a9cSAndroid Build Coastguard Worker       reflection().SetRepeatedInt64(message_, descriptor(), index(), value);
266*fd525a9cSAndroid Build Coastguard Worker     else
267*fd525a9cSAndroid Build Coastguard Worker       reflection().SetInt64(message_, descriptor(), value);
268*fd525a9cSAndroid Build Coastguard Worker   }
269*fd525a9cSAndroid Build Coastguard Worker 
Store(uint32_t value)270*fd525a9cSAndroid Build Coastguard Worker   void Store(uint32_t value) const {
271*fd525a9cSAndroid Build Coastguard Worker     if (is_repeated())
272*fd525a9cSAndroid Build Coastguard Worker       reflection().SetRepeatedUInt32(message_, descriptor(), index(), value);
273*fd525a9cSAndroid Build Coastguard Worker     else
274*fd525a9cSAndroid Build Coastguard Worker       reflection().SetUInt32(message_, descriptor(), value);
275*fd525a9cSAndroid Build Coastguard Worker   }
276*fd525a9cSAndroid Build Coastguard Worker 
Store(uint64_t value)277*fd525a9cSAndroid Build Coastguard Worker   void Store(uint64_t value) const {
278*fd525a9cSAndroid Build Coastguard Worker     if (is_repeated())
279*fd525a9cSAndroid Build Coastguard Worker       reflection().SetRepeatedUInt64(message_, descriptor(), index(), value);
280*fd525a9cSAndroid Build Coastguard Worker     else
281*fd525a9cSAndroid Build Coastguard Worker       reflection().SetUInt64(message_, descriptor(), value);
282*fd525a9cSAndroid Build Coastguard Worker   }
283*fd525a9cSAndroid Build Coastguard Worker 
Store(double value)284*fd525a9cSAndroid Build Coastguard Worker   void Store(double value) const {
285*fd525a9cSAndroid Build Coastguard Worker     if (is_repeated())
286*fd525a9cSAndroid Build Coastguard Worker       reflection().SetRepeatedDouble(message_, descriptor(), index(), value);
287*fd525a9cSAndroid Build Coastguard Worker     else
288*fd525a9cSAndroid Build Coastguard Worker       reflection().SetDouble(message_, descriptor(), value);
289*fd525a9cSAndroid Build Coastguard Worker   }
290*fd525a9cSAndroid Build Coastguard Worker 
Store(float value)291*fd525a9cSAndroid Build Coastguard Worker   void Store(float value) const {
292*fd525a9cSAndroid Build Coastguard Worker     if (is_repeated())
293*fd525a9cSAndroid Build Coastguard Worker       reflection().SetRepeatedFloat(message_, descriptor(), index(), value);
294*fd525a9cSAndroid Build Coastguard Worker     else
295*fd525a9cSAndroid Build Coastguard Worker       reflection().SetFloat(message_, descriptor(), value);
296*fd525a9cSAndroid Build Coastguard Worker   }
297*fd525a9cSAndroid Build Coastguard Worker 
Store(bool value)298*fd525a9cSAndroid Build Coastguard Worker   void Store(bool value) const {
299*fd525a9cSAndroid Build Coastguard Worker     if (is_repeated())
300*fd525a9cSAndroid Build Coastguard Worker       reflection().SetRepeatedBool(message_, descriptor(), index(), value);
301*fd525a9cSAndroid Build Coastguard Worker     else
302*fd525a9cSAndroid Build Coastguard Worker       reflection().SetBool(message_, descriptor(), value);
303*fd525a9cSAndroid Build Coastguard Worker   }
304*fd525a9cSAndroid Build Coastguard Worker 
Store(const Enum & value)305*fd525a9cSAndroid Build Coastguard Worker   void Store(const Enum& value) const {
306*fd525a9cSAndroid Build Coastguard Worker     assert(value.index < value.count);
307*fd525a9cSAndroid Build Coastguard Worker     const protobuf::EnumValueDescriptor* enum_value =
308*fd525a9cSAndroid Build Coastguard Worker         descriptor()->enum_type()->value(value.index);
309*fd525a9cSAndroid Build Coastguard Worker     if (is_repeated())
310*fd525a9cSAndroid Build Coastguard Worker       reflection().SetRepeatedEnum(message_, descriptor(), index(), enum_value);
311*fd525a9cSAndroid Build Coastguard Worker     else
312*fd525a9cSAndroid Build Coastguard Worker       reflection().SetEnum(message_, descriptor(), enum_value);
313*fd525a9cSAndroid Build Coastguard Worker   }
314*fd525a9cSAndroid Build Coastguard Worker 
Store(const std::string & value)315*fd525a9cSAndroid Build Coastguard Worker   void Store(const std::string& value) const {
316*fd525a9cSAndroid Build Coastguard Worker     if (is_repeated())
317*fd525a9cSAndroid Build Coastguard Worker       reflection().SetRepeatedString(message_, descriptor(), index(), value);
318*fd525a9cSAndroid Build Coastguard Worker     else
319*fd525a9cSAndroid Build Coastguard Worker       reflection().SetString(message_, descriptor(), value);
320*fd525a9cSAndroid Build Coastguard Worker   }
321*fd525a9cSAndroid Build Coastguard Worker 
Store(const std::unique_ptr<protobuf::Message> & value)322*fd525a9cSAndroid Build Coastguard Worker   void Store(const std::unique_ptr<protobuf::Message>& value) const {
323*fd525a9cSAndroid Build Coastguard Worker     protobuf::Message* mutable_message =
324*fd525a9cSAndroid Build Coastguard Worker         is_repeated() ? reflection().MutableRepeatedMessage(
325*fd525a9cSAndroid Build Coastguard Worker                             message_, descriptor(), index())
326*fd525a9cSAndroid Build Coastguard Worker                       : reflection().MutableMessage(message_, descriptor());
327*fd525a9cSAndroid Build Coastguard Worker     mutable_message->Clear();
328*fd525a9cSAndroid Build Coastguard Worker     if (value) mutable_message->CopyFrom(*value);
329*fd525a9cSAndroid Build Coastguard Worker   }
330*fd525a9cSAndroid Build Coastguard Worker 
331*fd525a9cSAndroid Build Coastguard Worker  private:
332*fd525a9cSAndroid Build Coastguard Worker   template <class T>
InsertRepeated(const T & value)333*fd525a9cSAndroid Build Coastguard Worker   void InsertRepeated(const T& value) const {
334*fd525a9cSAndroid Build Coastguard Worker     PushBackRepeated(value);
335*fd525a9cSAndroid Build Coastguard Worker     size_t field_size = reflection().FieldSize(*message_, descriptor());
336*fd525a9cSAndroid Build Coastguard Worker     if (field_size == 1) return;
337*fd525a9cSAndroid Build Coastguard Worker     // API has only method to add field to the end of the list. So we add
338*fd525a9cSAndroid Build Coastguard Worker     // descriptor()
339*fd525a9cSAndroid Build Coastguard Worker     // and move it into the middle.
340*fd525a9cSAndroid Build Coastguard Worker     for (size_t i = field_size - 1; i > index(); --i)
341*fd525a9cSAndroid Build Coastguard Worker       reflection().SwapElements(message_, descriptor(), i, i - 1);
342*fd525a9cSAndroid Build Coastguard Worker   }
343*fd525a9cSAndroid Build Coastguard Worker 
PushBackRepeated(int32_t value)344*fd525a9cSAndroid Build Coastguard Worker   void PushBackRepeated(int32_t value) const {
345*fd525a9cSAndroid Build Coastguard Worker     assert(is_repeated());
346*fd525a9cSAndroid Build Coastguard Worker     reflection().AddInt32(message_, descriptor(), value);
347*fd525a9cSAndroid Build Coastguard Worker   }
348*fd525a9cSAndroid Build Coastguard Worker 
PushBackRepeated(int64_t value)349*fd525a9cSAndroid Build Coastguard Worker   void PushBackRepeated(int64_t value) const {
350*fd525a9cSAndroid Build Coastguard Worker     assert(is_repeated());
351*fd525a9cSAndroid Build Coastguard Worker     reflection().AddInt64(message_, descriptor(), value);
352*fd525a9cSAndroid Build Coastguard Worker   }
353*fd525a9cSAndroid Build Coastguard Worker 
PushBackRepeated(uint32_t value)354*fd525a9cSAndroid Build Coastguard Worker   void PushBackRepeated(uint32_t value) const {
355*fd525a9cSAndroid Build Coastguard Worker     assert(is_repeated());
356*fd525a9cSAndroid Build Coastguard Worker     reflection().AddUInt32(message_, descriptor(), value);
357*fd525a9cSAndroid Build Coastguard Worker   }
358*fd525a9cSAndroid Build Coastguard Worker 
PushBackRepeated(uint64_t value)359*fd525a9cSAndroid Build Coastguard Worker   void PushBackRepeated(uint64_t value) const {
360*fd525a9cSAndroid Build Coastguard Worker     assert(is_repeated());
361*fd525a9cSAndroid Build Coastguard Worker     reflection().AddUInt64(message_, descriptor(), value);
362*fd525a9cSAndroid Build Coastguard Worker   }
363*fd525a9cSAndroid Build Coastguard Worker 
PushBackRepeated(double value)364*fd525a9cSAndroid Build Coastguard Worker   void PushBackRepeated(double value) const {
365*fd525a9cSAndroid Build Coastguard Worker     assert(is_repeated());
366*fd525a9cSAndroid Build Coastguard Worker     reflection().AddDouble(message_, descriptor(), value);
367*fd525a9cSAndroid Build Coastguard Worker   }
368*fd525a9cSAndroid Build Coastguard Worker 
PushBackRepeated(float value)369*fd525a9cSAndroid Build Coastguard Worker   void PushBackRepeated(float value) const {
370*fd525a9cSAndroid Build Coastguard Worker     assert(is_repeated());
371*fd525a9cSAndroid Build Coastguard Worker     reflection().AddFloat(message_, descriptor(), value);
372*fd525a9cSAndroid Build Coastguard Worker   }
373*fd525a9cSAndroid Build Coastguard Worker 
PushBackRepeated(bool value)374*fd525a9cSAndroid Build Coastguard Worker   void PushBackRepeated(bool value) const {
375*fd525a9cSAndroid Build Coastguard Worker     assert(is_repeated());
376*fd525a9cSAndroid Build Coastguard Worker     reflection().AddBool(message_, descriptor(), value);
377*fd525a9cSAndroid Build Coastguard Worker   }
378*fd525a9cSAndroid Build Coastguard Worker 
PushBackRepeated(const Enum & value)379*fd525a9cSAndroid Build Coastguard Worker   void PushBackRepeated(const Enum& value) const {
380*fd525a9cSAndroid Build Coastguard Worker     assert(value.index < value.count);
381*fd525a9cSAndroid Build Coastguard Worker     const protobuf::EnumValueDescriptor* enum_value =
382*fd525a9cSAndroid Build Coastguard Worker         descriptor()->enum_type()->value(value.index);
383*fd525a9cSAndroid Build Coastguard Worker     assert(is_repeated());
384*fd525a9cSAndroid Build Coastguard Worker     reflection().AddEnum(message_, descriptor(), enum_value);
385*fd525a9cSAndroid Build Coastguard Worker   }
386*fd525a9cSAndroid Build Coastguard Worker 
PushBackRepeated(const std::string & value)387*fd525a9cSAndroid Build Coastguard Worker   void PushBackRepeated(const std::string& value) const {
388*fd525a9cSAndroid Build Coastguard Worker     assert(is_repeated());
389*fd525a9cSAndroid Build Coastguard Worker     reflection().AddString(message_, descriptor(), value);
390*fd525a9cSAndroid Build Coastguard Worker   }
391*fd525a9cSAndroid Build Coastguard Worker 
PushBackRepeated(const std::unique_ptr<protobuf::Message> & value)392*fd525a9cSAndroid Build Coastguard Worker   void PushBackRepeated(const std::unique_ptr<protobuf::Message>& value) const {
393*fd525a9cSAndroid Build Coastguard Worker     assert(is_repeated());
394*fd525a9cSAndroid Build Coastguard Worker     protobuf::Message* mutable_message =
395*fd525a9cSAndroid Build Coastguard Worker         reflection().AddMessage(message_, descriptor());
396*fd525a9cSAndroid Build Coastguard Worker     mutable_message->Clear();
397*fd525a9cSAndroid Build Coastguard Worker     if (value) mutable_message->CopyFrom(*value);
398*fd525a9cSAndroid Build Coastguard Worker   }
399*fd525a9cSAndroid Build Coastguard Worker 
400*fd525a9cSAndroid Build Coastguard Worker   protobuf::Message* message_;
401*fd525a9cSAndroid Build Coastguard Worker };
402*fd525a9cSAndroid Build Coastguard Worker 
403*fd525a9cSAndroid Build Coastguard Worker template <class Fn, class R = void>
404*fd525a9cSAndroid Build Coastguard Worker struct FieldFunction {
405*fd525a9cSAndroid Build Coastguard Worker   template <class Field, class... Args>
operatorFieldFunction406*fd525a9cSAndroid Build Coastguard Worker   R operator()(const Field& field, const Args&... args) const {
407*fd525a9cSAndroid Build Coastguard Worker     assert(field.descriptor());
408*fd525a9cSAndroid Build Coastguard Worker     using protobuf::FieldDescriptor;
409*fd525a9cSAndroid Build Coastguard Worker     switch (field.cpp_type()) {
410*fd525a9cSAndroid Build Coastguard Worker       case FieldDescriptor::CPPTYPE_INT32:
411*fd525a9cSAndroid Build Coastguard Worker         return static_cast<const Fn*>(this)->template ForType<int32_t>(field,
412*fd525a9cSAndroid Build Coastguard Worker                                                                        args...);
413*fd525a9cSAndroid Build Coastguard Worker       case FieldDescriptor::CPPTYPE_INT64:
414*fd525a9cSAndroid Build Coastguard Worker         return static_cast<const Fn*>(this)->template ForType<int64_t>(field,
415*fd525a9cSAndroid Build Coastguard Worker                                                                        args...);
416*fd525a9cSAndroid Build Coastguard Worker       case FieldDescriptor::CPPTYPE_UINT32:
417*fd525a9cSAndroid Build Coastguard Worker         return static_cast<const Fn*>(this)->template ForType<uint32_t>(
418*fd525a9cSAndroid Build Coastguard Worker             field, args...);
419*fd525a9cSAndroid Build Coastguard Worker       case FieldDescriptor::CPPTYPE_UINT64:
420*fd525a9cSAndroid Build Coastguard Worker         return static_cast<const Fn*>(this)->template ForType<uint64_t>(
421*fd525a9cSAndroid Build Coastguard Worker             field, args...);
422*fd525a9cSAndroid Build Coastguard Worker       case FieldDescriptor::CPPTYPE_DOUBLE:
423*fd525a9cSAndroid Build Coastguard Worker         return static_cast<const Fn*>(this)->template ForType<double>(field,
424*fd525a9cSAndroid Build Coastguard Worker                                                                       args...);
425*fd525a9cSAndroid Build Coastguard Worker       case FieldDescriptor::CPPTYPE_FLOAT:
426*fd525a9cSAndroid Build Coastguard Worker         return static_cast<const Fn*>(this)->template ForType<float>(field,
427*fd525a9cSAndroid Build Coastguard Worker                                                                      args...);
428*fd525a9cSAndroid Build Coastguard Worker       case FieldDescriptor::CPPTYPE_BOOL:
429*fd525a9cSAndroid Build Coastguard Worker         return static_cast<const Fn*>(this)->template ForType<bool>(field,
430*fd525a9cSAndroid Build Coastguard Worker                                                                     args...);
431*fd525a9cSAndroid Build Coastguard Worker       case FieldDescriptor::CPPTYPE_ENUM:
432*fd525a9cSAndroid Build Coastguard Worker         return static_cast<const Fn*>(this)
433*fd525a9cSAndroid Build Coastguard Worker             ->template ForType<ConstFieldInstance::Enum>(field, args...);
434*fd525a9cSAndroid Build Coastguard Worker       case FieldDescriptor::CPPTYPE_STRING:
435*fd525a9cSAndroid Build Coastguard Worker         return static_cast<const Fn*>(this)->template ForType<std::string>(
436*fd525a9cSAndroid Build Coastguard Worker             field, args...);
437*fd525a9cSAndroid Build Coastguard Worker       case FieldDescriptor::CPPTYPE_MESSAGE:
438*fd525a9cSAndroid Build Coastguard Worker         return static_cast<const Fn*>(this)
439*fd525a9cSAndroid Build Coastguard Worker             ->template ForType<std::unique_ptr<protobuf::Message>>(field,
440*fd525a9cSAndroid Build Coastguard Worker                                                                    args...);
441*fd525a9cSAndroid Build Coastguard Worker     }
442*fd525a9cSAndroid Build Coastguard Worker     assert(false && "Unknown type");
443*fd525a9cSAndroid Build Coastguard Worker     abort();
444*fd525a9cSAndroid Build Coastguard Worker   }
445*fd525a9cSAndroid Build Coastguard Worker };
446*fd525a9cSAndroid Build Coastguard Worker 
447*fd525a9cSAndroid Build Coastguard Worker }  // namespace protobuf_mutator
448*fd525a9cSAndroid Build Coastguard Worker 
449*fd525a9cSAndroid Build Coastguard Worker #endif  // SRC_FIELD_INSTANCE_H_
450