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