xref: /aosp_15_r20/external/angle/third_party/abseil-cpp/absl/log/internal/proto.cc (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 {
EncodeRawVarint(uint64_t value,size_t size,absl::Span<char> * buf)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 
EncodeVarint(uint64_t tag,uint64_t value,absl::Span<char> * buf)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 
Encode64Bit(uint64_t tag,uint64_t value,absl::Span<char> * buf)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 
Encode32Bit(uint64_t tag,uint32_t value,absl::Span<char> * buf)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 
EncodeBytes(uint64_t tag,absl::Span<const char> value,absl::Span<char> * buf)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 
EncodeBytesTruncate(uint64_t tag,absl::Span<const char> value,absl::Span<char> * buf)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 
EncodeMessageStart(uint64_t tag,uint64_t max_size,absl::Span<char> * buf)126 ABSL_MUST_USE_RESULT absl::Span<char> EncodeMessageStart(
127     uint64_t tag, uint64_t max_size, absl::Span<char> *buf) {
128   const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
129   const size_t tag_type_size = VarintSize(tag_type);
130   max_size = std::min<uint64_t>(max_size, buf->size());
131   const size_t length_size = VarintSize(max_size);
132   if (tag_type_size + length_size > buf->size()) {
133     buf->remove_suffix(buf->size());
134     return absl::Span<char>();
135   }
136   EncodeRawVarint(tag_type, tag_type_size, buf);
137   const absl::Span<char> ret = buf->subspan(0, length_size);
138   EncodeRawVarint(0, length_size, buf);
139   return ret;
140 }
141 
EncodeMessageLength(absl::Span<char> msg,const absl::Span<char> * buf)142 void EncodeMessageLength(absl::Span<char> msg, const absl::Span<char> *buf) {
143   if (!msg.data()) return;
144   assert(buf->data() >= msg.data());
145   if (buf->data() < msg.data()) return;
146   EncodeRawVarint(
147       static_cast<uint64_t>(buf->data() - (msg.data() + msg.size())),
148       msg.size(), &msg);
149 }
150 
151 namespace {
DecodeVarint(absl::Span<const char> * buf)152 uint64_t DecodeVarint(absl::Span<const char> *buf) {
153   uint64_t value = 0;
154   size_t s = 0;
155   while (s < buf->size()) {
156     value |= static_cast<uint64_t>(static_cast<unsigned char>((*buf)[s]) & 0x7f)
157              << 7 * s;
158     if (!((*buf)[s++] & 0x80)) break;
159   }
160   buf->remove_prefix(s);
161   return value;
162 }
163 
Decode64Bit(absl::Span<const char> * buf)164 uint64_t Decode64Bit(absl::Span<const char> *buf) {
165   uint64_t value = 0;
166   size_t s = 0;
167   while (s < buf->size()) {
168     value |= static_cast<uint64_t>(static_cast<unsigned char>((*buf)[s]))
169              << 8 * s;
170     if (++s == sizeof(value)) break;
171   }
172   buf->remove_prefix(s);
173   return value;
174 }
175 
Decode32Bit(absl::Span<const char> * buf)176 uint32_t Decode32Bit(absl::Span<const char> *buf) {
177   uint32_t value = 0;
178   size_t s = 0;
179   while (s < buf->size()) {
180     value |= static_cast<uint32_t>(static_cast<unsigned char>((*buf)[s]))
181              << 8 * s;
182     if (++s == sizeof(value)) break;
183   }
184   buf->remove_prefix(s);
185   return value;
186 }
187 }  // namespace
188 
DecodeFrom(absl::Span<const char> * data)189 bool ProtoField::DecodeFrom(absl::Span<const char> *data) {
190   if (data->empty()) return false;
191   const uint64_t tag_type = DecodeVarint(data);
192   tag_ = tag_type >> 3;
193   type_ = static_cast<WireType>(tag_type & 0x07);
194   switch (type_) {
195     case WireType::kVarint:
196       value_ = DecodeVarint(data);
197       break;
198     case WireType::k64Bit:
199       value_ = Decode64Bit(data);
200       break;
201     case WireType::kLengthDelimited: {
202       value_ = DecodeVarint(data);
203       data_ = data->subspan(
204           0, static_cast<size_t>(std::min<uint64_t>(value_, data->size())));
205       data->remove_prefix(data_.size());
206       break;
207     }
208     case WireType::k32Bit:
209       value_ = Decode32Bit(data);
210       break;
211   }
212   return true;
213 }
214 
215 }  // namespace log_internal
216 ABSL_NAMESPACE_END
217 }  // namespace absl
218