• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
BufferSizeForStructuredProtoField(StructuredProtoField field)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_
108