Coverage Report

Created: 2024-09-23 06:29

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