197440f459544938f019c5ea15893b0416e46ded6Primiano Tucci/* 297440f459544938f019c5ea15893b0416e46ded6Primiano Tucci * Copyright (C) 2017 The Android Open Source Project 397440f459544938f019c5ea15893b0416e46ded6Primiano Tucci * 497440f459544938f019c5ea15893b0416e46ded6Primiano Tucci * Licensed under the Apache License, Version 2.0 (the "License"); 597440f459544938f019c5ea15893b0416e46ded6Primiano Tucci * you may not use this file except in compliance with the License. 697440f459544938f019c5ea15893b0416e46ded6Primiano Tucci * You may obtain a copy of the License at 797440f459544938f019c5ea15893b0416e46ded6Primiano Tucci * 897440f459544938f019c5ea15893b0416e46ded6Primiano Tucci * http://www.apache.org/licenses/LICENSE-2.0 997440f459544938f019c5ea15893b0416e46ded6Primiano Tucci * 1097440f459544938f019c5ea15893b0416e46ded6Primiano Tucci * Unless required by applicable law or agreed to in writing, software 1197440f459544938f019c5ea15893b0416e46ded6Primiano Tucci * distributed under the License is distributed on an "AS IS" BASIS, 1297440f459544938f019c5ea15893b0416e46ded6Primiano Tucci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1397440f459544938f019c5ea15893b0416e46ded6Primiano Tucci * See the License for the specific language governing permissions and 1497440f459544938f019c5ea15893b0416e46ded6Primiano Tucci * limitations under the License. 1597440f459544938f019c5ea15893b0416e46ded6Primiano Tucci */ 1697440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 174f9b6d7b7b2ad7b86e1577a18dc6e2df91b98164Primiano Tucci#ifndef INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_ 184f9b6d7b7b2ad7b86e1577a18dc6e2df91b98164Primiano Tucci#define INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_ 1997440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 2097440f459544938f019c5ea15893b0416e46ded6Primiano Tucci#include <inttypes.h> 2197440f459544938f019c5ea15893b0416e46ded6Primiano Tucci#include <stddef.h> 2297440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 2397440f459544938f019c5ea15893b0416e46ded6Primiano Tucci#include <type_traits> 2497440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 2597440f459544938f019c5ea15893b0416e46ded6Primiano Tuccinamespace protozero { 2697440f459544938f019c5ea15893b0416e46ded6Primiano Tuccinamespace proto_utils { 2797440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 2897440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// See https://developers.google.com/protocol-buffers/docs/encoding wire types. 2997440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 3097440f459544938f019c5ea15893b0416e46ded6Primiano Tuccienum FieldType : uint32_t { 3197440f459544938f019c5ea15893b0416e46ded6Primiano Tucci kFieldTypeVarInt = 0, 3297440f459544938f019c5ea15893b0416e46ded6Primiano Tucci kFieldTypeFixed64 = 1, 3397440f459544938f019c5ea15893b0416e46ded6Primiano Tucci kFieldTypeLengthDelimited = 2, 3497440f459544938f019c5ea15893b0416e46ded6Primiano Tucci kFieldTypeFixed32 = 5, 3597440f459544938f019c5ea15893b0416e46ded6Primiano Tucci}; 3697440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 3797440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// Maximum message size supported: 256 MiB (4 x 7-bit due to varint encoding). 3897440f459544938f019c5ea15893b0416e46ded6Primiano Tucciconstexpr size_t kMessageLengthFieldSize = 4; 3997440f459544938f019c5ea15893b0416e46ded6Primiano Tucciconstexpr size_t kMaxMessageLength = (1u << (kMessageLengthFieldSize * 7)) - 1; 4097440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 4197440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// Field tag is encoded as 32-bit varint (5 bytes at most). 4297440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// Largest value of simple (not length-delimited) field is 64-bit varint 4397440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// (10 bytes at most). 15 bytes buffer is enough to store a simple field. 4497440f459544938f019c5ea15893b0416e46ded6Primiano Tucciconstexpr size_t kMaxTagEncodedSize = 5; 4597440f459544938f019c5ea15893b0416e46ded6Primiano Tucciconstexpr size_t kMaxSimpleFieldEncodedSize = kMaxTagEncodedSize + 10; 4697440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 4797440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// Proto types: (int|uint|sint)(32|64), bool, enum. 4897440f459544938f019c5ea15893b0416e46ded6Primiano Tucciconstexpr uint32_t MakeTagVarInt(uint32_t field_id) { 4997440f459544938f019c5ea15893b0416e46ded6Primiano Tucci return (field_id << 3) | kFieldTypeVarInt; 5097440f459544938f019c5ea15893b0416e46ded6Primiano Tucci} 5197440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 5297440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// Proto types: fixed64, sfixed64, fixed32, sfixed32, double, float. 5397440f459544938f019c5ea15893b0416e46ded6Primiano Tuccitemplate <typename T> 5497440f459544938f019c5ea15893b0416e46ded6Primiano Tucciconstexpr uint32_t MakeTagFixed(uint32_t field_id) { 5597440f459544938f019c5ea15893b0416e46ded6Primiano Tucci static_assert(sizeof(T) == 8 || sizeof(T) == 4, "Value must be 4 or 8 bytes"); 5697440f459544938f019c5ea15893b0416e46ded6Primiano Tucci return (field_id << 3) | 5797440f459544938f019c5ea15893b0416e46ded6Primiano Tucci (sizeof(T) == 8 ? kFieldTypeFixed64 : kFieldTypeFixed32); 5897440f459544938f019c5ea15893b0416e46ded6Primiano Tucci} 5997440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 6097440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// Proto types: string, bytes, embedded messages. 6197440f459544938f019c5ea15893b0416e46ded6Primiano Tucciconstexpr uint32_t MakeTagLengthDelimited(uint32_t field_id) { 6297440f459544938f019c5ea15893b0416e46ded6Primiano Tucci return (field_id << 3) | kFieldTypeLengthDelimited; 6397440f459544938f019c5ea15893b0416e46ded6Primiano Tucci} 6497440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 6597440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// Proto types: sint64, sint32. 6697440f459544938f019c5ea15893b0416e46ded6Primiano Tuccitemplate <typename T> 6797440f459544938f019c5ea15893b0416e46ded6Primiano Tucciinline typename std::make_unsigned<T>::type ZigZagEncode(T value) { 6897440f459544938f019c5ea15893b0416e46ded6Primiano Tucci return static_cast<typename std::make_unsigned<T>::type>( 6997440f459544938f019c5ea15893b0416e46ded6Primiano Tucci (value << 1) ^ (value >> (sizeof(T) * 8 - 1))); 7097440f459544938f019c5ea15893b0416e46ded6Primiano Tucci} 7197440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 7297440f459544938f019c5ea15893b0416e46ded6Primiano Tuccitemplate <typename T> 7397440f459544938f019c5ea15893b0416e46ded6Primiano Tucciinline uint8_t* WriteVarInt(T value, uint8_t* target) { 7497440f459544938f019c5ea15893b0416e46ded6Primiano Tucci // Avoid arithmetic (sign expanding) shifts. 7597440f459544938f019c5ea15893b0416e46ded6Primiano Tucci using UnsignedType = typename std::make_unsigned<T>::type; 7697440f459544938f019c5ea15893b0416e46ded6Primiano Tucci UnsignedType unsigned_value = static_cast<UnsignedType>(value); 7797440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 7897440f459544938f019c5ea15893b0416e46ded6Primiano Tucci while (unsigned_value >= 0x80) { 7997440f459544938f019c5ea15893b0416e46ded6Primiano Tucci *target++ = static_cast<uint8_t>(unsigned_value) | 0x80; 8097440f459544938f019c5ea15893b0416e46ded6Primiano Tucci unsigned_value >>= 7; 8197440f459544938f019c5ea15893b0416e46ded6Primiano Tucci } 8297440f459544938f019c5ea15893b0416e46ded6Primiano Tucci *target = static_cast<uint8_t>(unsigned_value); 8397440f459544938f019c5ea15893b0416e46ded6Primiano Tucci return target + 1; 8497440f459544938f019c5ea15893b0416e46ded6Primiano Tucci} 8597440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 8697440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// Writes a fixed-size redundant encoding of the given |value|. This is 8797440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// used to backfill fixed-size reservations for the length field using a 8897440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// non-canonical varint encoding (e.g. \x81\x80\x80\x00 instead of \x01). 8997440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// See https://github.com/google/protobuf/issues/1530. 9097440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// In particular, this is used for nested messages. The size of a nested message 9197440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// is not known until all its field have been written. |kMessageLengthFieldSize| 9297440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// bytes are reserved to encode the size field and backfilled at the end. 9397440f459544938f019c5ea15893b0416e46ded6Primiano Tucciinline void WriteRedundantVarInt(uint32_t value, uint8_t* buf) { 9497440f459544938f019c5ea15893b0416e46ded6Primiano Tucci for (size_t i = 0; i < kMessageLengthFieldSize; ++i) { 9597440f459544938f019c5ea15893b0416e46ded6Primiano Tucci const uint8_t msb = (i < kMessageLengthFieldSize - 1) ? 0x80 : 0; 9697440f459544938f019c5ea15893b0416e46ded6Primiano Tucci buf[i] = static_cast<uint8_t>(value) | msb; 9797440f459544938f019c5ea15893b0416e46ded6Primiano Tucci value >>= 7; 9897440f459544938f019c5ea15893b0416e46ded6Primiano Tucci } 9997440f459544938f019c5ea15893b0416e46ded6Primiano Tucci} 10097440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 10197440f459544938f019c5ea15893b0416e46ded6Primiano Tuccitemplate <uint32_t field_id> 10297440f459544938f019c5ea15893b0416e46ded6Primiano Tuccivoid StaticAssertSingleBytePreamble() { 10397440f459544938f019c5ea15893b0416e46ded6Primiano Tucci static_assert(field_id < 16, 10497440f459544938f019c5ea15893b0416e46ded6Primiano Tucci "Proto field id too big to fit in a single byte preamble"); 10597440f459544938f019c5ea15893b0416e46ded6Primiano Tucci}; 10697440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 10797440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// Parses a VarInt from the encoded buffer [start, end). |end| is STL-style and 10897440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// points one byte past the end of buffer. 10997440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// The parsed int value is stored in the output arg |value|. Returns a pointer 11097440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// to the next unconsumed byte (so start < retval <= end). 11197440f459544938f019c5ea15893b0416e46ded6Primiano Tucciconst uint8_t* ParseVarInt(const uint8_t* start, 11297440f459544938f019c5ea15893b0416e46ded6Primiano Tucci const uint8_t* end, 11397440f459544938f019c5ea15893b0416e46ded6Primiano Tucci uint64_t* value); 11497440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 11597440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// Parses a protobuf field and computes its id, type and value. 11697440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// Returns a pointer to the next unconsumed byte (|start| < retval <= end) that 11797440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// is either the beginning of the next field or the end of the parent message. 11897440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// In the case of a kFieldTypeLengthDelimited field, |field_intvalue| will 11997440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// store the length of the payload (either a string or a nested message). In 12097440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// this case, the start of the payload will be at (return value) - 12197440f459544938f019c5ea15893b0416e46ded6Primiano Tucci// |field_intvalue|. 12297440f459544938f019c5ea15893b0416e46ded6Primiano Tucciconst uint8_t* ParseField(const uint8_t* start, 12397440f459544938f019c5ea15893b0416e46ded6Primiano Tucci const uint8_t* end, 12497440f459544938f019c5ea15893b0416e46ded6Primiano Tucci uint32_t* field_id, 12597440f459544938f019c5ea15893b0416e46ded6Primiano Tucci FieldType* field_type, 12697440f459544938f019c5ea15893b0416e46ded6Primiano Tucci uint64_t* field_intvalue); 12797440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 12897440f459544938f019c5ea15893b0416e46ded6Primiano Tucci} // namespace proto_utils 12997440f459544938f019c5ea15893b0416e46ded6Primiano Tucci} // namespace protozero 13097440f459544938f019c5ea15893b0416e46ded6Primiano Tucci 1314f9b6d7b7b2ad7b86e1577a18dc6e2df91b98164Primiano Tucci#endif // INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_ 132