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