All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.opentelemetry.exporter.internal.marshal.CodedInputStream Maven / Gradle / Ivy

/*
 * Copyright The OpenTelemetry Authors
 * SPDX-License-Identifier: Apache-2.0
 */

// Includes work from:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package io.opentelemetry.exporter.internal.marshal;

import static io.opentelemetry.exporter.internal.marshal.WireFormat.FIXED32_SIZE;
import static io.opentelemetry.exporter.internal.marshal.WireFormat.FIXED64_SIZE;
import static io.opentelemetry.exporter.internal.marshal.WireFormat.MAX_VARINT_SIZE;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * Minimal copy of protobuf-java's CodedInputStream, currently only used in GrpcStatusUtil.
 *
 * 

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ @SuppressWarnings("UnnecessaryFinal") public final class CodedInputStream { private final byte[] buffer; private final int limit; private int pos; private int lastTag; /** Returns a new {@link CodedInputStream}. */ public static CodedInputStream newInstance(byte[] serialized) { return new CodedInputStream(serialized); } private CodedInputStream(byte[] buffer) { this.buffer = buffer; limit = buffer.length; pos = 0; } /** Reads the next tag. */ public int readTag() throws IOException { if (isAtEnd()) { lastTag = 0; return 0; } lastTag = readRawVarint32(); if (WireFormat.getTagFieldNumber(lastTag) == 0) { // If we actually read zero (or any tag number corresponding to field // number zero), that's not a valid tag. throw new IOException("Invalid tag: " + lastTag); } return lastTag; } /** Reads a string field. */ public String readStringRequireUtf8() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= (limit - pos)) { String result = new String(buffer, pos, size, StandardCharsets.UTF_8); pos += size; return result; } if (size == 0) { return ""; } if (size <= 0) { throw newNegativeException(); } throw newTruncatedException(); } /** Skips a field. */ public boolean skipField(final int tag) throws IOException { switch (WireFormat.getTagWireType(tag)) { case WireFormat.WIRETYPE_VARINT: skipRawVarint(); return true; case WireFormat.WIRETYPE_FIXED64: skipRawBytes(FIXED64_SIZE); return true; case WireFormat.WIRETYPE_LENGTH_DELIMITED: skipRawBytes(readRawVarint32()); return true; case WireFormat.WIRETYPE_FIXED32: skipRawBytes(FIXED32_SIZE); return true; default: throw new IOException("Invalid wire type: " + tag); } } private boolean isAtEnd() { return pos == limit; } /** Read varint32. */ @SuppressWarnings("LabelledBreakTarget") public int readRawVarint32() throws IOException { // See implementation notes for readRawVarint64 fastpath: { int tempPos = pos; if (limit == tempPos) { break fastpath; } final byte[] buffer = this.buffer; int x; if ((x = buffer[tempPos++]) >= 0) { pos = tempPos; return x; } else if (limit - tempPos < 9) { break fastpath; } else if ((x ^= (buffer[tempPos++] << 7)) < 0) { x ^= (~0 << 7); } else if ((x ^= (buffer[tempPos++] << 14)) >= 0) { x ^= (~0 << 7) ^ (~0 << 14); } else if ((x ^= (buffer[tempPos++] << 21)) < 0) { x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21); } else { int y = buffer[tempPos++]; x ^= y << 28; x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28); if (y < 0 && buffer[tempPos++] < 0 && buffer[tempPos++] < 0 && buffer[tempPos++] < 0 && buffer[tempPos++] < 0 && buffer[tempPos++] < 0) { break fastpath; // Will throw malformedVarint() } } pos = tempPos; return x; } return (int) readRawVarint64SlowPath(); } private long readRawVarint64SlowPath() throws IOException { long result = 0; for (int shift = 0; shift < 64; shift += 7) { final byte b = readRawByte(); result |= (long) (b & 0x7F) << shift; if ((b & 0x80) == 0) { return result; } } throw newMalformedVarintException(); } private byte readRawByte() throws IOException { if (pos == limit) { throw newTruncatedException(); } return buffer[pos++]; } private void skipRawVarint() throws IOException { if (limit - pos >= MAX_VARINT_SIZE) { skipRawVarintFastPath(); } else { skipRawVarintSlowPath(); } } public double readDouble() throws IOException { return Double.longBitsToDouble(readRawLittleEndian64()); } private long readRawLittleEndian64() throws IOException { int tempPos = pos; if (limit - tempPos < FIXED64_SIZE) { throw newTruncatedException(); } final byte[] buffer = this.buffer; pos = tempPos + FIXED64_SIZE; return ((buffer[tempPos] & 0xffL) | ((buffer[tempPos + 1] & 0xffL) << 8) | ((buffer[tempPos + 2] & 0xffL) << 16) | ((buffer[tempPos + 3] & 0xffL) << 24) | ((buffer[tempPos + 4] & 0xffL) << 32) | ((buffer[tempPos + 5] & 0xffL) << 40) | ((buffer[tempPos + 6] & 0xffL) << 48) | ((buffer[tempPos + 7] & 0xffL) << 56)); } private void skipRawVarintFastPath() throws IOException { for (int i = 0; i < MAX_VARINT_SIZE; i++) { if (buffer[pos++] >= 0) { return; } } throw newMalformedVarintException(); } private void skipRawVarintSlowPath() throws IOException { for (int i = 0; i < MAX_VARINT_SIZE; i++) { if (readRawByte() >= 0) { return; } } throw newMalformedVarintException(); } private void skipRawBytes(final int length) throws IOException { if (length >= 0 && length <= (limit - pos)) { // We have all the bytes we need already. pos += length; return; } if (length < 0) { throw newNegativeException(); } throw newTruncatedException(); } private static IOException newNegativeException() { return new IOException( "CodedInputStream encountered an embedded string or message " + "which claimed to have negative size."); } private static IOException newTruncatedException() { return new IOException( "While parsing a protocol message, the input ended unexpectedly " + "in the middle of a field. This could mean either that the " + "input has been truncated or that an embedded message " + "misreported its own length."); } private static IOException newMalformedVarintException() { return new IOException("CodedInputStream encountered a malformed varint."); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy