2 * Copyright 2017 Google
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #import "FIRMessagingCodedInputStream.h"
18 #import "FIRMessagingDefines.h"
26 static BOOL CheckSize(BufferState *state, size_t size) {
27 size_t newSize = state->bufferPos + size;
28 if (newSize > state->bufferSize) {
34 static BOOL ReadRawByte(BufferState *state, int8_t *output) {
35 _FIRMessagingDevAssert(output != NULL && state != NULL, @"Invalid parameters");
37 if (CheckSize(state, sizeof(int8_t))) {
38 *output = ((int8_t *)state->bytes)[state->bufferPos++];
44 static BOOL ReadRawVarInt32(BufferState *state, int32_t *output) {
45 _FIRMessagingDevAssert(output != NULL && state != NULL, @"Invalid parameters");
48 if (!ReadRawByte(state, &tmp)) {
55 int32_t result = tmp & 0x7f;
56 if (!ReadRawByte(state, &tmp)) {
62 result |= (tmp & 0x7f) << 7;
63 if (!ReadRawByte(state, &tmp)) {
69 result |= (tmp & 0x7f) << 14;
70 if (!ReadRawByte(state, &tmp)) {
76 result |= (tmp & 0x7f) << 21;
77 if (!ReadRawByte(state, &tmp)) {
82 // Discard upper 32 bits.
83 for (int i = 0; i < 5; ++i) {
84 if (!ReadRawByte(state, &tmp)) {
101 @interface FIRMessagingCodedInputStream()
103 @property(nonatomic, readwrite, strong) NSData *buffer;
104 @property(nonatomic, readwrite, assign) BufferState state;
108 @implementation FIRMessagingCodedInputStream;
110 - (instancetype)initWithData:(NSData *)data {
114 _state.bytes = _buffer.bytes;
115 _state.bufferSize = _buffer.length;
121 return _state.bufferPos;
124 - (BOOL)readTag:(int8_t *)tag {
125 return ReadRawByte(&_state, tag);
128 - (BOOL)readLength:(int32_t *)length {
129 return ReadRawVarInt32(&_state, length);
132 - (NSData *)readDataWithLength:(uint32_t)length {
133 if (!CheckSize(&_state, length)) {
136 const void *bytesToRead = _state.bytes + _state.bufferPos;
137 NSData *result = [NSData dataWithBytes:bytesToRead length:length];
138 _state.bufferPos += length;