xref: /aosp_15_r20/external/cronet/third_party/protobuf/objectivec/GPBExtensionInternals.m (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker// Protocol Buffers - Google's data interchange format
2*6777b538SAndroid Build Coastguard Worker// Copyright 2008 Google Inc.  All rights reserved.
3*6777b538SAndroid Build Coastguard Worker// https://developers.google.com/protocol-buffers/
4*6777b538SAndroid Build Coastguard Worker//
5*6777b538SAndroid Build Coastguard Worker// Redistribution and use in source and binary forms, with or without
6*6777b538SAndroid Build Coastguard Worker// modification, are permitted provided that the following conditions are
7*6777b538SAndroid Build Coastguard Worker// met:
8*6777b538SAndroid Build Coastguard Worker//
9*6777b538SAndroid Build Coastguard Worker//     * Redistributions of source code must retain the above copyright
10*6777b538SAndroid Build Coastguard Worker// notice, this list of conditions and the following disclaimer.
11*6777b538SAndroid Build Coastguard Worker//     * Redistributions in binary form must reproduce the above
12*6777b538SAndroid Build Coastguard Worker// copyright notice, this list of conditions and the following disclaimer
13*6777b538SAndroid Build Coastguard Worker// in the documentation and/or other materials provided with the
14*6777b538SAndroid Build Coastguard Worker// distribution.
15*6777b538SAndroid Build Coastguard Worker//     * Neither the name of Google Inc. nor the names of its
16*6777b538SAndroid Build Coastguard Worker// contributors may be used to endorse or promote products derived from
17*6777b538SAndroid Build Coastguard Worker// this software without specific prior written permission.
18*6777b538SAndroid Build Coastguard Worker//
19*6777b538SAndroid Build Coastguard Worker// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20*6777b538SAndroid Build Coastguard Worker// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21*6777b538SAndroid Build Coastguard Worker// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22*6777b538SAndroid Build Coastguard Worker// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23*6777b538SAndroid Build Coastguard Worker// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24*6777b538SAndroid Build Coastguard Worker// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25*6777b538SAndroid Build Coastguard Worker// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26*6777b538SAndroid Build Coastguard Worker// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27*6777b538SAndroid Build Coastguard Worker// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28*6777b538SAndroid Build Coastguard Worker// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29*6777b538SAndroid Build Coastguard Worker// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker#import "GPBExtensionInternals.h"
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker#import <objc/runtime.h>
34*6777b538SAndroid Build Coastguard Worker
35*6777b538SAndroid Build Coastguard Worker#import "GPBCodedInputStream_PackagePrivate.h"
36*6777b538SAndroid Build Coastguard Worker#import "GPBCodedOutputStream_PackagePrivate.h"
37*6777b538SAndroid Build Coastguard Worker#import "GPBDescriptor_PackagePrivate.h"
38*6777b538SAndroid Build Coastguard Worker#import "GPBMessage_PackagePrivate.h"
39*6777b538SAndroid Build Coastguard Worker#import "GPBUtilities_PackagePrivate.h"
40*6777b538SAndroid Build Coastguard Worker
41*6777b538SAndroid Build Coastguard Workerstatic id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension,
42*6777b538SAndroid Build Coastguard Worker                                        GPBCodedInputStream *input,
43*6777b538SAndroid Build Coastguard Worker                                        GPBExtensionRegistry *extensionRegistry,
44*6777b538SAndroid Build Coastguard Worker                                        GPBMessage *existingValue)
45*6777b538SAndroid Build Coastguard Worker    __attribute__((ns_returns_retained));
46*6777b538SAndroid Build Coastguard Worker
47*6777b538SAndroid Build Coastguard WorkerGPB_INLINE size_t DataTypeSize(GPBDataType dataType) {
48*6777b538SAndroid Build Coastguard Worker#pragma clang diagnostic push
49*6777b538SAndroid Build Coastguard Worker#pragma clang diagnostic ignored "-Wswitch-enum"
50*6777b538SAndroid Build Coastguard Worker  switch (dataType) {
51*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeBool:
52*6777b538SAndroid Build Coastguard Worker      return 1;
53*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeFixed32:
54*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeSFixed32:
55*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeFloat:
56*6777b538SAndroid Build Coastguard Worker      return 4;
57*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeFixed64:
58*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeSFixed64:
59*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeDouble:
60*6777b538SAndroid Build Coastguard Worker      return 8;
61*6777b538SAndroid Build Coastguard Worker    default:
62*6777b538SAndroid Build Coastguard Worker      return 0;
63*6777b538SAndroid Build Coastguard Worker  }
64*6777b538SAndroid Build Coastguard Worker#pragma clang diagnostic pop
65*6777b538SAndroid Build Coastguard Worker}
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Workerstatic size_t ComputePBSerializedSizeNoTagOfObject(GPBDataType dataType, id object) {
68*6777b538SAndroid Build Coastguard Worker#define FIELD_CASE(TYPE, ACCESSOR)                                     \
69*6777b538SAndroid Build Coastguard Worker  case GPBDataType##TYPE:                                              \
70*6777b538SAndroid Build Coastguard Worker    return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]);
71*6777b538SAndroid Build Coastguard Worker#define FIELD_CASE2(TYPE)                                              \
72*6777b538SAndroid Build Coastguard Worker  case GPBDataType##TYPE:                                              \
73*6777b538SAndroid Build Coastguard Worker    return GPBCompute##TYPE##SizeNoTag(object);
74*6777b538SAndroid Build Coastguard Worker  switch (dataType) {
75*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Bool, boolValue)
76*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Float, floatValue)
77*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Double, doubleValue)
78*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Int32, intValue)
79*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SFixed32, intValue)
80*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SInt32, intValue)
81*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Enum, intValue)
82*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Int64, longLongValue)
83*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SInt64, longLongValue)
84*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SFixed64, longLongValue)
85*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(UInt32, unsignedIntValue)
86*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Fixed32, unsignedIntValue)
87*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(UInt64, unsignedLongLongValue)
88*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Fixed64, unsignedLongLongValue)
89*6777b538SAndroid Build Coastguard Worker    FIELD_CASE2(Bytes)
90*6777b538SAndroid Build Coastguard Worker    FIELD_CASE2(String)
91*6777b538SAndroid Build Coastguard Worker    FIELD_CASE2(Message)
92*6777b538SAndroid Build Coastguard Worker    FIELD_CASE2(Group)
93*6777b538SAndroid Build Coastguard Worker  }
94*6777b538SAndroid Build Coastguard Worker#undef FIELD_CASE
95*6777b538SAndroid Build Coastguard Worker#undef FIELD_CASE2
96*6777b538SAndroid Build Coastguard Worker}
97*6777b538SAndroid Build Coastguard Worker
98*6777b538SAndroid Build Coastguard Workerstatic size_t ComputeSerializedSizeIncludingTagOfObject(
99*6777b538SAndroid Build Coastguard Worker    GPBExtensionDescription *description, id object) {
100*6777b538SAndroid Build Coastguard Worker#define FIELD_CASE(TYPE, ACCESSOR)                                   \
101*6777b538SAndroid Build Coastguard Worker  case GPBDataType##TYPE:                                            \
102*6777b538SAndroid Build Coastguard Worker    return GPBCompute##TYPE##Size(description->fieldNumber,          \
103*6777b538SAndroid Build Coastguard Worker                                  [(NSNumber *)object ACCESSOR]);
104*6777b538SAndroid Build Coastguard Worker#define FIELD_CASE2(TYPE)                                            \
105*6777b538SAndroid Build Coastguard Worker  case GPBDataType##TYPE:                                            \
106*6777b538SAndroid Build Coastguard Worker    return GPBCompute##TYPE##Size(description->fieldNumber, object);
107*6777b538SAndroid Build Coastguard Worker  switch (description->dataType) {
108*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Bool, boolValue)
109*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Float, floatValue)
110*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Double, doubleValue)
111*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Int32, intValue)
112*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SFixed32, intValue)
113*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SInt32, intValue)
114*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Enum, intValue)
115*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Int64, longLongValue)
116*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SInt64, longLongValue)
117*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SFixed64, longLongValue)
118*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(UInt32, unsignedIntValue)
119*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Fixed32, unsignedIntValue)
120*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(UInt64, unsignedLongLongValue)
121*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Fixed64, unsignedLongLongValue)
122*6777b538SAndroid Build Coastguard Worker    FIELD_CASE2(Bytes)
123*6777b538SAndroid Build Coastguard Worker    FIELD_CASE2(String)
124*6777b538SAndroid Build Coastguard Worker    FIELD_CASE2(Group)
125*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeMessage:
126*6777b538SAndroid Build Coastguard Worker      if (GPBExtensionIsWireFormat(description)) {
127*6777b538SAndroid Build Coastguard Worker        return GPBComputeMessageSetExtensionSize(description->fieldNumber,
128*6777b538SAndroid Build Coastguard Worker                                                 object);
129*6777b538SAndroid Build Coastguard Worker      } else {
130*6777b538SAndroid Build Coastguard Worker        return GPBComputeMessageSize(description->fieldNumber, object);
131*6777b538SAndroid Build Coastguard Worker      }
132*6777b538SAndroid Build Coastguard Worker  }
133*6777b538SAndroid Build Coastguard Worker#undef FIELD_CASE
134*6777b538SAndroid Build Coastguard Worker#undef FIELD_CASE2
135*6777b538SAndroid Build Coastguard Worker}
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Workerstatic size_t ComputeSerializedSizeIncludingTagOfArray(
138*6777b538SAndroid Build Coastguard Worker    GPBExtensionDescription *description, NSArray *values) {
139*6777b538SAndroid Build Coastguard Worker  if (GPBExtensionIsPacked(description)) {
140*6777b538SAndroid Build Coastguard Worker    size_t size = 0;
141*6777b538SAndroid Build Coastguard Worker    size_t typeSize = DataTypeSize(description->dataType);
142*6777b538SAndroid Build Coastguard Worker    if (typeSize != 0) {
143*6777b538SAndroid Build Coastguard Worker      size = values.count * typeSize;
144*6777b538SAndroid Build Coastguard Worker    } else {
145*6777b538SAndroid Build Coastguard Worker      for (id value in values) {
146*6777b538SAndroid Build Coastguard Worker        size +=
147*6777b538SAndroid Build Coastguard Worker            ComputePBSerializedSizeNoTagOfObject(description->dataType, value);
148*6777b538SAndroid Build Coastguard Worker      }
149*6777b538SAndroid Build Coastguard Worker    }
150*6777b538SAndroid Build Coastguard Worker    return size + GPBComputeTagSize(description->fieldNumber) +
151*6777b538SAndroid Build Coastguard Worker           GPBComputeRawVarint32SizeForInteger(size);
152*6777b538SAndroid Build Coastguard Worker  } else {
153*6777b538SAndroid Build Coastguard Worker    size_t size = 0;
154*6777b538SAndroid Build Coastguard Worker    for (id value in values) {
155*6777b538SAndroid Build Coastguard Worker      size += ComputeSerializedSizeIncludingTagOfObject(description, value);
156*6777b538SAndroid Build Coastguard Worker    }
157*6777b538SAndroid Build Coastguard Worker    return size;
158*6777b538SAndroid Build Coastguard Worker  }
159*6777b538SAndroid Build Coastguard Worker}
160*6777b538SAndroid Build Coastguard Worker
161*6777b538SAndroid Build Coastguard Workerstatic void WriteObjectIncludingTagToCodedOutputStream(
162*6777b538SAndroid Build Coastguard Worker    id object, GPBExtensionDescription *description,
163*6777b538SAndroid Build Coastguard Worker    GPBCodedOutputStream *output) {
164*6777b538SAndroid Build Coastguard Worker#define FIELD_CASE(TYPE, ACCESSOR)                      \
165*6777b538SAndroid Build Coastguard Worker  case GPBDataType##TYPE:                               \
166*6777b538SAndroid Build Coastguard Worker    [output write##TYPE:description->fieldNumber        \
167*6777b538SAndroid Build Coastguard Worker                  value:[(NSNumber *)object ACCESSOR]]; \
168*6777b538SAndroid Build Coastguard Worker    return;
169*6777b538SAndroid Build Coastguard Worker#define FIELD_CASE2(TYPE)                                       \
170*6777b538SAndroid Build Coastguard Worker  case GPBDataType##TYPE:                                       \
171*6777b538SAndroid Build Coastguard Worker    [output write##TYPE:description->fieldNumber value:object]; \
172*6777b538SAndroid Build Coastguard Worker    return;
173*6777b538SAndroid Build Coastguard Worker  switch (description->dataType) {
174*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Bool, boolValue)
175*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Float, floatValue)
176*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Double, doubleValue)
177*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Int32, intValue)
178*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SFixed32, intValue)
179*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SInt32, intValue)
180*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Enum, intValue)
181*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Int64, longLongValue)
182*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SInt64, longLongValue)
183*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SFixed64, longLongValue)
184*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(UInt32, unsignedIntValue)
185*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Fixed32, unsignedIntValue)
186*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(UInt64, unsignedLongLongValue)
187*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Fixed64, unsignedLongLongValue)
188*6777b538SAndroid Build Coastguard Worker    FIELD_CASE2(Bytes)
189*6777b538SAndroid Build Coastguard Worker    FIELD_CASE2(String)
190*6777b538SAndroid Build Coastguard Worker    FIELD_CASE2(Group)
191*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeMessage:
192*6777b538SAndroid Build Coastguard Worker      if (GPBExtensionIsWireFormat(description)) {
193*6777b538SAndroid Build Coastguard Worker        [output writeMessageSetExtension:description->fieldNumber value:object];
194*6777b538SAndroid Build Coastguard Worker      } else {
195*6777b538SAndroid Build Coastguard Worker        [output writeMessage:description->fieldNumber value:object];
196*6777b538SAndroid Build Coastguard Worker      }
197*6777b538SAndroid Build Coastguard Worker      return;
198*6777b538SAndroid Build Coastguard Worker  }
199*6777b538SAndroid Build Coastguard Worker#undef FIELD_CASE
200*6777b538SAndroid Build Coastguard Worker#undef FIELD_CASE2
201*6777b538SAndroid Build Coastguard Worker}
202*6777b538SAndroid Build Coastguard Worker
203*6777b538SAndroid Build Coastguard Workerstatic void WriteObjectNoTagToCodedOutputStream(
204*6777b538SAndroid Build Coastguard Worker    id object, GPBExtensionDescription *description,
205*6777b538SAndroid Build Coastguard Worker    GPBCodedOutputStream *output) {
206*6777b538SAndroid Build Coastguard Worker#define FIELD_CASE(TYPE, ACCESSOR)                             \
207*6777b538SAndroid Build Coastguard Worker  case GPBDataType##TYPE:                                      \
208*6777b538SAndroid Build Coastguard Worker    [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \
209*6777b538SAndroid Build Coastguard Worker    return;
210*6777b538SAndroid Build Coastguard Worker#define FIELD_CASE2(TYPE)               \
211*6777b538SAndroid Build Coastguard Worker  case GPBDataType##TYPE:               \
212*6777b538SAndroid Build Coastguard Worker    [output write##TYPE##NoTag:object]; \
213*6777b538SAndroid Build Coastguard Worker    return;
214*6777b538SAndroid Build Coastguard Worker  switch (description->dataType) {
215*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Bool, boolValue)
216*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Float, floatValue)
217*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Double, doubleValue)
218*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Int32, intValue)
219*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SFixed32, intValue)
220*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SInt32, intValue)
221*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Enum, intValue)
222*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Int64, longLongValue)
223*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SInt64, longLongValue)
224*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(SFixed64, longLongValue)
225*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(UInt32, unsignedIntValue)
226*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Fixed32, unsignedIntValue)
227*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(UInt64, unsignedLongLongValue)
228*6777b538SAndroid Build Coastguard Worker    FIELD_CASE(Fixed64, unsignedLongLongValue)
229*6777b538SAndroid Build Coastguard Worker    FIELD_CASE2(Bytes)
230*6777b538SAndroid Build Coastguard Worker    FIELD_CASE2(String)
231*6777b538SAndroid Build Coastguard Worker    FIELD_CASE2(Message)
232*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeGroup:
233*6777b538SAndroid Build Coastguard Worker      [output writeGroupNoTag:description->fieldNumber value:object];
234*6777b538SAndroid Build Coastguard Worker      return;
235*6777b538SAndroid Build Coastguard Worker  }
236*6777b538SAndroid Build Coastguard Worker#undef FIELD_CASE
237*6777b538SAndroid Build Coastguard Worker#undef FIELD_CASE2
238*6777b538SAndroid Build Coastguard Worker}
239*6777b538SAndroid Build Coastguard Worker
240*6777b538SAndroid Build Coastguard Workerstatic void WriteArrayIncludingTagsToCodedOutputStream(
241*6777b538SAndroid Build Coastguard Worker    NSArray *values, GPBExtensionDescription *description,
242*6777b538SAndroid Build Coastguard Worker    GPBCodedOutputStream *output) {
243*6777b538SAndroid Build Coastguard Worker  if (GPBExtensionIsPacked(description)) {
244*6777b538SAndroid Build Coastguard Worker    [output writeTag:description->fieldNumber
245*6777b538SAndroid Build Coastguard Worker              format:GPBWireFormatLengthDelimited];
246*6777b538SAndroid Build Coastguard Worker    size_t dataSize = 0;
247*6777b538SAndroid Build Coastguard Worker    size_t typeSize = DataTypeSize(description->dataType);
248*6777b538SAndroid Build Coastguard Worker    if (typeSize != 0) {
249*6777b538SAndroid Build Coastguard Worker      dataSize = values.count * typeSize;
250*6777b538SAndroid Build Coastguard Worker    } else {
251*6777b538SAndroid Build Coastguard Worker      for (id value in values) {
252*6777b538SAndroid Build Coastguard Worker        dataSize +=
253*6777b538SAndroid Build Coastguard Worker            ComputePBSerializedSizeNoTagOfObject(description->dataType, value);
254*6777b538SAndroid Build Coastguard Worker      }
255*6777b538SAndroid Build Coastguard Worker    }
256*6777b538SAndroid Build Coastguard Worker    [output writeRawVarintSizeTAs32:dataSize];
257*6777b538SAndroid Build Coastguard Worker    for (id value in values) {
258*6777b538SAndroid Build Coastguard Worker      WriteObjectNoTagToCodedOutputStream(value, description, output);
259*6777b538SAndroid Build Coastguard Worker    }
260*6777b538SAndroid Build Coastguard Worker  } else {
261*6777b538SAndroid Build Coastguard Worker    for (id value in values) {
262*6777b538SAndroid Build Coastguard Worker      WriteObjectIncludingTagToCodedOutputStream(value, description, output);
263*6777b538SAndroid Build Coastguard Worker    }
264*6777b538SAndroid Build Coastguard Worker  }
265*6777b538SAndroid Build Coastguard Worker}
266*6777b538SAndroid Build Coastguard Worker
267*6777b538SAndroid Build Coastguard Worker// Direct access is use for speed, to avoid even internally declaring things
268*6777b538SAndroid Build Coastguard Worker// read/write, etc. The warning is enabled in the project to ensure code calling
269*6777b538SAndroid Build Coastguard Worker// protos can turn on -Wdirect-ivar-access without issues.
270*6777b538SAndroid Build Coastguard Worker#pragma clang diagnostic push
271*6777b538SAndroid Build Coastguard Worker#pragma clang diagnostic ignored "-Wdirect-ivar-access"
272*6777b538SAndroid Build Coastguard Worker
273*6777b538SAndroid Build Coastguard Workervoid GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension,
274*6777b538SAndroid Build Coastguard Worker                                      BOOL isPackedOnStream,
275*6777b538SAndroid Build Coastguard Worker                                      GPBCodedInputStream *input,
276*6777b538SAndroid Build Coastguard Worker                                      GPBExtensionRegistry *extensionRegistry,
277*6777b538SAndroid Build Coastguard Worker                                      GPBMessage *message) {
278*6777b538SAndroid Build Coastguard Worker  GPBExtensionDescription *description = extension->description_;
279*6777b538SAndroid Build Coastguard Worker  GPBCodedInputStreamState *state = &input->state_;
280*6777b538SAndroid Build Coastguard Worker  if (isPackedOnStream) {
281*6777b538SAndroid Build Coastguard Worker    NSCAssert(GPBExtensionIsRepeated(description),
282*6777b538SAndroid Build Coastguard Worker              @"How was it packed if it isn't repeated?");
283*6777b538SAndroid Build Coastguard Worker    int32_t length = GPBCodedInputStreamReadInt32(state);
284*6777b538SAndroid Build Coastguard Worker    size_t limit = GPBCodedInputStreamPushLimit(state, length);
285*6777b538SAndroid Build Coastguard Worker    while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
286*6777b538SAndroid Build Coastguard Worker      id value = NewSingleValueFromInputStream(extension,
287*6777b538SAndroid Build Coastguard Worker                                               input,
288*6777b538SAndroid Build Coastguard Worker                                               extensionRegistry,
289*6777b538SAndroid Build Coastguard Worker                                               nil);
290*6777b538SAndroid Build Coastguard Worker      [message addExtension:extension value:value];
291*6777b538SAndroid Build Coastguard Worker      [value release];
292*6777b538SAndroid Build Coastguard Worker    }
293*6777b538SAndroid Build Coastguard Worker    GPBCodedInputStreamPopLimit(state, limit);
294*6777b538SAndroid Build Coastguard Worker  } else {
295*6777b538SAndroid Build Coastguard Worker    id existingValue = nil;
296*6777b538SAndroid Build Coastguard Worker    BOOL isRepeated = GPBExtensionIsRepeated(description);
297*6777b538SAndroid Build Coastguard Worker    if (!isRepeated && GPBDataTypeIsMessage(description->dataType)) {
298*6777b538SAndroid Build Coastguard Worker      existingValue = [message getExistingExtension:extension];
299*6777b538SAndroid Build Coastguard Worker    }
300*6777b538SAndroid Build Coastguard Worker    id value = NewSingleValueFromInputStream(extension,
301*6777b538SAndroid Build Coastguard Worker                                             input,
302*6777b538SAndroid Build Coastguard Worker                                             extensionRegistry,
303*6777b538SAndroid Build Coastguard Worker                                             existingValue);
304*6777b538SAndroid Build Coastguard Worker    if (isRepeated) {
305*6777b538SAndroid Build Coastguard Worker      [message addExtension:extension value:value];
306*6777b538SAndroid Build Coastguard Worker    } else {
307*6777b538SAndroid Build Coastguard Worker      [message setExtension:extension value:value];
308*6777b538SAndroid Build Coastguard Worker    }
309*6777b538SAndroid Build Coastguard Worker    [value release];
310*6777b538SAndroid Build Coastguard Worker  }
311*6777b538SAndroid Build Coastguard Worker}
312*6777b538SAndroid Build Coastguard Worker
313*6777b538SAndroid Build Coastguard Workervoid GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension,
314*6777b538SAndroid Build Coastguard Worker                                          id value,
315*6777b538SAndroid Build Coastguard Worker                                          GPBCodedOutputStream *output) {
316*6777b538SAndroid Build Coastguard Worker  GPBExtensionDescription *description = extension->description_;
317*6777b538SAndroid Build Coastguard Worker  if (GPBExtensionIsRepeated(description)) {
318*6777b538SAndroid Build Coastguard Worker    WriteArrayIncludingTagsToCodedOutputStream(value, description, output);
319*6777b538SAndroid Build Coastguard Worker  } else {
320*6777b538SAndroid Build Coastguard Worker    WriteObjectIncludingTagToCodedOutputStream(value, description, output);
321*6777b538SAndroid Build Coastguard Worker  }
322*6777b538SAndroid Build Coastguard Worker}
323*6777b538SAndroid Build Coastguard Worker
324*6777b538SAndroid Build Coastguard Workersize_t GPBComputeExtensionSerializedSizeIncludingTag(
325*6777b538SAndroid Build Coastguard Worker    GPBExtensionDescriptor *extension, id value) {
326*6777b538SAndroid Build Coastguard Worker  GPBExtensionDescription *description = extension->description_;
327*6777b538SAndroid Build Coastguard Worker  if (GPBExtensionIsRepeated(description)) {
328*6777b538SAndroid Build Coastguard Worker    return ComputeSerializedSizeIncludingTagOfArray(description, value);
329*6777b538SAndroid Build Coastguard Worker  } else {
330*6777b538SAndroid Build Coastguard Worker    return ComputeSerializedSizeIncludingTagOfObject(description, value);
331*6777b538SAndroid Build Coastguard Worker  }
332*6777b538SAndroid Build Coastguard Worker}
333*6777b538SAndroid Build Coastguard Worker
334*6777b538SAndroid Build Coastguard Worker// Note that this returns a retained value intentionally.
335*6777b538SAndroid Build Coastguard Workerstatic id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension,
336*6777b538SAndroid Build Coastguard Worker                                        GPBCodedInputStream *input,
337*6777b538SAndroid Build Coastguard Worker                                        GPBExtensionRegistry *extensionRegistry,
338*6777b538SAndroid Build Coastguard Worker                                        GPBMessage *existingValue) {
339*6777b538SAndroid Build Coastguard Worker  GPBExtensionDescription *description = extension->description_;
340*6777b538SAndroid Build Coastguard Worker  GPBCodedInputStreamState *state = &input->state_;
341*6777b538SAndroid Build Coastguard Worker  switch (description->dataType) {
342*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeBool:     return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)];
343*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeFixed32:  return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)];
344*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)];
345*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeFloat:    return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)];
346*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeFixed64:  return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)];
347*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)];
348*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeDouble:   return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)];
349*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeInt32:    return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)];
350*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeInt64:    return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)];
351*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeSInt32:   return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)];
352*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeSInt64:   return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)];
353*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeUInt32:   return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)];
354*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeUInt64:   return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)];
355*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeBytes:    return GPBCodedInputStreamReadRetainedBytes(state);
356*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeString:   return GPBCodedInputStreamReadRetainedString(state);
357*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeEnum:     return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)];
358*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeGroup:
359*6777b538SAndroid Build Coastguard Worker    case GPBDataTypeMessage: {
360*6777b538SAndroid Build Coastguard Worker      GPBMessage *message;
361*6777b538SAndroid Build Coastguard Worker      if (existingValue) {
362*6777b538SAndroid Build Coastguard Worker        message = [existingValue retain];
363*6777b538SAndroid Build Coastguard Worker      } else {
364*6777b538SAndroid Build Coastguard Worker        GPBDescriptor *descriptor = [extension.msgClass descriptor];
365*6777b538SAndroid Build Coastguard Worker        message = [[descriptor.messageClass alloc] init];
366*6777b538SAndroid Build Coastguard Worker      }
367*6777b538SAndroid Build Coastguard Worker
368*6777b538SAndroid Build Coastguard Worker      if (description->dataType == GPBDataTypeGroup) {
369*6777b538SAndroid Build Coastguard Worker        [input readGroup:description->fieldNumber
370*6777b538SAndroid Build Coastguard Worker                 message:message
371*6777b538SAndroid Build Coastguard Worker            extensionRegistry:extensionRegistry];
372*6777b538SAndroid Build Coastguard Worker      } else {
373*6777b538SAndroid Build Coastguard Worker        // description->dataType == GPBDataTypeMessage
374*6777b538SAndroid Build Coastguard Worker        if (GPBExtensionIsWireFormat(description)) {
375*6777b538SAndroid Build Coastguard Worker          // For MessageSet fields the message length will have already been
376*6777b538SAndroid Build Coastguard Worker          // read.
377*6777b538SAndroid Build Coastguard Worker          [message mergeFromCodedInputStream:input
378*6777b538SAndroid Build Coastguard Worker                           extensionRegistry:extensionRegistry];
379*6777b538SAndroid Build Coastguard Worker        } else {
380*6777b538SAndroid Build Coastguard Worker          [input readMessage:message extensionRegistry:extensionRegistry];
381*6777b538SAndroid Build Coastguard Worker        }
382*6777b538SAndroid Build Coastguard Worker      }
383*6777b538SAndroid Build Coastguard Worker
384*6777b538SAndroid Build Coastguard Worker      return message;
385*6777b538SAndroid Build Coastguard Worker    }
386*6777b538SAndroid Build Coastguard Worker  }
387*6777b538SAndroid Build Coastguard Worker
388*6777b538SAndroid Build Coastguard Worker  return nil;
389*6777b538SAndroid Build Coastguard Worker}
390*6777b538SAndroid Build Coastguard Worker
391*6777b538SAndroid Build Coastguard Worker#pragma clang diagnostic pop
392