proto.cc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Copyright 2020 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. #include "absl/log/internal/proto.h"
  15. #include <algorithm>
  16. #include <cassert>
  17. #include <cstddef>
  18. #include <cstdint>
  19. #include <cstring>
  20. #include "absl/base/attributes.h"
  21. #include "absl/base/config.h"
  22. #include "absl/types/span.h"
  23. namespace absl {
  24. ABSL_NAMESPACE_BEGIN
  25. namespace log_internal {
  26. namespace {
  27. void EncodeRawVarint(uint64_t value, size_t size, absl::Span<char> *buf) {
  28. for (size_t s = 0; s < size; s++) {
  29. (*buf)[s] = static_cast<char>((value & 0x7f) | (s + 1 == size ? 0 : 0x80));
  30. value >>= 7;
  31. }
  32. buf->remove_prefix(size);
  33. }
  34. } // namespace
  35. bool EncodeVarint(uint64_t tag, uint64_t value, absl::Span<char> *buf) {
  36. const uint64_t tag_type = MakeTagType(tag, WireType::kVarint);
  37. const size_t tag_type_size = VarintSize(tag_type);
  38. const size_t value_size = VarintSize(value);
  39. if (tag_type_size + value_size > buf->size()) {
  40. buf->remove_suffix(buf->size());
  41. return false;
  42. }
  43. EncodeRawVarint(tag_type, tag_type_size, buf);
  44. EncodeRawVarint(value, value_size, buf);
  45. return true;
  46. }
  47. bool Encode64Bit(uint64_t tag, uint64_t value, absl::Span<char> *buf) {
  48. const uint64_t tag_type = MakeTagType(tag, WireType::k64Bit);
  49. const size_t tag_type_size = VarintSize(tag_type);
  50. if (tag_type_size + sizeof(value) > buf->size()) {
  51. buf->remove_suffix(buf->size());
  52. return false;
  53. }
  54. EncodeRawVarint(tag_type, tag_type_size, buf);
  55. for (size_t s = 0; s < sizeof(value); s++) {
  56. (*buf)[s] = static_cast<char>(value & 0xff);
  57. value >>= 8;
  58. }
  59. buf->remove_prefix(sizeof(value));
  60. return true;
  61. }
  62. bool Encode32Bit(uint64_t tag, uint32_t value, absl::Span<char> *buf) {
  63. const uint64_t tag_type = MakeTagType(tag, WireType::k32Bit);
  64. const size_t tag_type_size = VarintSize(tag_type);
  65. if (tag_type_size + sizeof(value) > buf->size()) {
  66. buf->remove_suffix(buf->size());
  67. return false;
  68. }
  69. EncodeRawVarint(tag_type, tag_type_size, buf);
  70. for (size_t s = 0; s < sizeof(value); s++) {
  71. (*buf)[s] = static_cast<char>(value & 0xff);
  72. value >>= 8;
  73. }
  74. buf->remove_prefix(sizeof(value));
  75. return true;
  76. }
  77. bool EncodeBytes(uint64_t tag, absl::Span<const char> value,
  78. absl::Span<char> *buf) {
  79. const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
  80. const size_t tag_type_size = VarintSize(tag_type);
  81. uint64_t length = value.size();
  82. const size_t length_size = VarintSize(length);
  83. if (tag_type_size + length_size + value.size() > buf->size()) {
  84. buf->remove_suffix(buf->size());
  85. return false;
  86. }
  87. EncodeRawVarint(tag_type, tag_type_size, buf);
  88. EncodeRawVarint(length, length_size, buf);
  89. memcpy(buf->data(), value.data(), value.size());
  90. buf->remove_prefix(value.size());
  91. return true;
  92. }
  93. bool EncodeBytesTruncate(uint64_t tag, absl::Span<const char> value,
  94. absl::Span<char> *buf) {
  95. const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
  96. const size_t tag_type_size = VarintSize(tag_type);
  97. uint64_t length = value.size();
  98. const size_t length_size =
  99. VarintSize(std::min<uint64_t>(length, buf->size()));
  100. if (tag_type_size + length_size <= buf->size() &&
  101. tag_type_size + length_size + value.size() > buf->size()) {
  102. value.remove_suffix(tag_type_size + length_size + value.size() -
  103. buf->size());
  104. length = value.size();
  105. }
  106. if (tag_type_size + length_size + value.size() > buf->size()) {
  107. buf->remove_suffix(buf->size());
  108. return false;
  109. }
  110. EncodeRawVarint(tag_type, tag_type_size, buf);
  111. EncodeRawVarint(length, length_size, buf);
  112. memcpy(buf->data(), value.data(), value.size());
  113. buf->remove_prefix(value.size());
  114. return true;
  115. }
  116. ABSL_MUST_USE_RESULT absl::Span<char> EncodeMessageStart(
  117. uint64_t tag, uint64_t max_size, absl::Span<char> *buf) {
  118. const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
  119. const size_t tag_type_size = VarintSize(tag_type);
  120. max_size = std::min<uint64_t>(max_size, buf->size());
  121. const size_t length_size = VarintSize(max_size);
  122. if (tag_type_size + length_size > buf->size()) {
  123. buf->remove_suffix(buf->size());
  124. return absl::Span<char>();
  125. }
  126. EncodeRawVarint(tag_type, tag_type_size, buf);
  127. const absl::Span<char> ret = buf->subspan(0, length_size);
  128. EncodeRawVarint(0, length_size, buf);
  129. return ret;
  130. }
  131. void EncodeMessageLength(absl::Span<char> msg, const absl::Span<char> *buf) {
  132. if (!msg.data()) return;
  133. assert(buf->data() >= msg.data());
  134. if (buf->data() < msg.data()) return;
  135. EncodeRawVarint(
  136. static_cast<uint64_t>(buf->data() - (msg.data() + msg.size())),
  137. msg.size(), &msg);
  138. }
  139. namespace {
  140. uint64_t DecodeVarint(absl::Span<const char> *buf) {
  141. uint64_t value = 0;
  142. size_t s = 0;
  143. while (s < buf->size()) {
  144. value |= static_cast<uint64_t>(static_cast<unsigned char>((*buf)[s]) & 0x7f)
  145. << 7 * s;
  146. if (!((*buf)[s++] & 0x80)) break;
  147. }
  148. buf->remove_prefix(s);
  149. return value;
  150. }
  151. uint64_t Decode64Bit(absl::Span<const char> *buf) {
  152. uint64_t value = 0;
  153. size_t s = 0;
  154. while (s < buf->size()) {
  155. value |= static_cast<uint64_t>(static_cast<unsigned char>((*buf)[s]))
  156. << 8 * s;
  157. if (++s == sizeof(value)) break;
  158. }
  159. buf->remove_prefix(s);
  160. return value;
  161. }
  162. uint32_t Decode32Bit(absl::Span<const char> *buf) {
  163. uint32_t value = 0;
  164. size_t s = 0;
  165. while (s < buf->size()) {
  166. value |= static_cast<uint32_t>(static_cast<unsigned char>((*buf)[s]))
  167. << 8 * s;
  168. if (++s == sizeof(value)) break;
  169. }
  170. buf->remove_prefix(s);
  171. return value;
  172. }
  173. } // namespace
  174. bool ProtoField::DecodeFrom(absl::Span<const char> *data) {
  175. if (data->empty()) return false;
  176. const uint64_t tag_type = DecodeVarint(data);
  177. tag_ = tag_type >> 3;
  178. type_ = static_cast<WireType>(tag_type & 0x07);
  179. switch (type_) {
  180. case WireType::kVarint:
  181. value_ = DecodeVarint(data);
  182. break;
  183. case WireType::k64Bit:
  184. value_ = Decode64Bit(data);
  185. break;
  186. case WireType::kLengthDelimited: {
  187. value_ = DecodeVarint(data);
  188. data_ = data->subspan(
  189. 0, static_cast<size_t>(std::min<uint64_t>(value_, data->size())));
  190. data->remove_prefix(data_.size());
  191. break;
  192. }
  193. case WireType::k32Bit:
  194. value_ = Decode32Bit(data);
  195. break;
  196. }
  197. return true;
  198. }
  199. } // namespace log_internal
  200. ABSL_NAMESPACE_END
  201. } // namespace absl