structured_proto.h (3729B)
1 // Copyright 2024 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // ----------------------------------------------------------------------------- 16 // File: log/internal/structured_proto.h 17 // ----------------------------------------------------------------------------- 18 19 #ifndef ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_ 20 #define ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_ 21 22 #include <cstddef> 23 #include <cstdint> 24 25 #include "absl/base/config.h" 26 #include "absl/log/internal/proto.h" 27 #include "absl/types/span.h" 28 #include "absl/types/variant.h" 29 30 namespace absl { 31 ABSL_NAMESPACE_BEGIN 32 namespace log_internal { 33 34 // Sum type holding a single valid protobuf field suitable for encoding. 35 struct StructuredProtoField final { 36 // Numeric type encoded with varint encoding: 37 // https://protobuf.dev/programming-guides/encoding/#varints 38 using Varint = absl::variant<uint64_t, int64_t, uint32_t, int32_t, bool>; 39 40 // Fixed-length 64-bit integer encoding: 41 // https://protobuf.dev/programming-guides/encoding/#non-varints 42 using I64 = absl::variant<uint64_t, int64_t, double>; 43 44 // Length-delimited record type (string, sub-message): 45 // https://protobuf.dev/programming-guides/encoding/#length-types 46 using LengthDelimited = absl::Span<const char>; 47 48 // Fixed-length 32-bit integer encoding: 49 // https://protobuf.dev/programming-guides/encoding/#non-varints 50 using I32 = absl::variant<uint32_t, int32_t, float>; 51 52 // Valid record type: 53 // https://protobuf.dev/programming-guides/encoding/#structure 54 using Value = absl::variant<Varint, I64, LengthDelimited, I32>; 55 56 // Field number for the protobuf value. 57 uint64_t field_number; 58 59 // Value to encode. 60 Value value; 61 }; 62 63 // Estimates the number of bytes needed to encode `field` using 64 // protobuf encoding. 65 // 66 // The returned value might be larger than the actual number of bytes needed. 67 inline size_t BufferSizeForStructuredProtoField(StructuredProtoField field) { 68 // Visitor to estimate the number of bytes of one of the types contained 69 // inside `StructuredProtoField`. 70 struct BufferSizeVisitor final { 71 size_t operator()(StructuredProtoField::Varint /*unused*/) { 72 return BufferSizeFor(field_number, WireType::kVarint); 73 } 74 75 size_t operator()(StructuredProtoField::I64 /*unused*/) { 76 return BufferSizeFor(field_number, WireType::k64Bit); 77 } 78 79 size_t operator()(StructuredProtoField::LengthDelimited length_delimited) { 80 return BufferSizeFor(field_number, WireType::kLengthDelimited) + 81 length_delimited.size(); 82 } 83 84 size_t operator()(StructuredProtoField::I32 /*unused*/) { 85 return BufferSizeFor(field_number, WireType::k32Bit); 86 } 87 88 uint64_t field_number; 89 }; 90 91 return absl::visit(BufferSizeVisitor{field.field_number}, field.value); 92 } 93 94 // Encodes `field` into `buf` using protobuf encoding. 95 // 96 // On success, returns `true` and advances `buf` to the end of 97 // the bytes consumed. 98 // 99 // On failure (if `buf` was too small), returns `false`. 100 bool EncodeStructuredProtoField(StructuredProtoField field, 101 absl::Span<char>& buf); 102 103 } // namespace log_internal 104 ABSL_NAMESPACE_END 105 } // namespace absl 106 107 #endif // ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_