structured_proto.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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. #ifndef ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_
  19. #define ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_
  20. #include <cstddef>
  21. #include <cstdint>
  22. #include "absl/base/config.h"
  23. #include "absl/log/internal/proto.h"
  24. #include "absl/types/span.h"
  25. #include "absl/types/variant.h"
  26. namespace absl {
  27. ABSL_NAMESPACE_BEGIN
  28. namespace log_internal {
  29. // Sum type holding a single valid protobuf field suitable for encoding.
  30. struct StructuredProtoField final {
  31. // Numeric type encoded with varint encoding:
  32. // https://protobuf.dev/programming-guides/encoding/#varints
  33. using Varint = absl::variant<uint64_t, int64_t, uint32_t, int32_t, bool>;
  34. // Fixed-length 64-bit integer encoding:
  35. // https://protobuf.dev/programming-guides/encoding/#non-varints
  36. using I64 = absl::variant<uint64_t, int64_t, double>;
  37. // Length-delimited record type (string, sub-message):
  38. // https://protobuf.dev/programming-guides/encoding/#length-types
  39. using LengthDelimited = absl::Span<const char>;
  40. // Fixed-length 32-bit integer encoding:
  41. // https://protobuf.dev/programming-guides/encoding/#non-varints
  42. using I32 = absl::variant<uint32_t, int32_t, float>;
  43. // Valid record type:
  44. // https://protobuf.dev/programming-guides/encoding/#structure
  45. using Value = absl::variant<Varint, I64, LengthDelimited, I32>;
  46. // Field number for the protobuf value.
  47. uint64_t field_number;
  48. // Value to encode.
  49. Value value;
  50. };
  51. // Estimates the number of bytes needed to encode `field` using
  52. // protobuf encoding.
  53. //
  54. // The returned value might be larger than the actual number of bytes needed.
  55. inline size_t BufferSizeForStructuredProtoField(StructuredProtoField field) {
  56. // Visitor to estimate the number of bytes of one of the types contained
  57. // inside `StructuredProtoField`.
  58. struct BufferSizeVisitor final {
  59. size_t operator()(StructuredProtoField::Varint /*unused*/) {
  60. return BufferSizeFor(field_number, WireType::kVarint);
  61. }
  62. size_t operator()(StructuredProtoField::I64 /*unused*/) {
  63. return BufferSizeFor(field_number, WireType::k64Bit);
  64. }
  65. size_t operator()(StructuredProtoField::LengthDelimited length_delimited) {
  66. return BufferSizeFor(field_number, WireType::kLengthDelimited) +
  67. length_delimited.size();
  68. }
  69. size_t operator()(StructuredProtoField::I32 /*unused*/) {
  70. return BufferSizeFor(field_number, WireType::k32Bit);
  71. }
  72. uint64_t field_number;
  73. };
  74. return absl::visit(BufferSizeVisitor{field.field_number}, field.value);
  75. }
  76. // Encodes `field` into `buf` using protobuf encoding.
  77. //
  78. // On success, returns `true` and advances `buf` to the end of
  79. // the bytes consumed.
  80. //
  81. // On failure (if `buf` was too small), returns `false`.
  82. bool EncodeStructuredProtoField(StructuredProtoField field,
  83. absl::Span<char>& buf);
  84. } // namespace log_internal
  85. ABSL_NAMESPACE_END
  86. } // namespace absl
  87. #endif // ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_