C/C++ API Reference
Loading...
Searching...
No Matches
wire_format.h
1// Copyright 2020 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// 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, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include <cstdint>
17#include <limits>
18
19#include "pw_assert/assert.h"
20
21namespace pw::protobuf {
22
24
25// Per the protobuf specification, valid field numbers range between 1 and
26// 2**29 - 1, inclusive. The numbers 19000-19999 are reserved for internal
27// use.
28inline constexpr static uint32_t kMaxFieldNumber = (1u << 29) - 1;
29inline constexpr static uint32_t kFirstReservedNumber = 19000;
30inline constexpr static uint32_t kLastReservedNumber = 19999;
31
32constexpr bool ValidFieldNumber(uint32_t field_number) {
33 return field_number != 0 && field_number <= kMaxFieldNumber &&
34 !(field_number >= kFirstReservedNumber &&
35 field_number <= kLastReservedNumber);
36}
37
38constexpr bool ValidFieldNumber(uint64_t field_number) {
39 if (field_number > std::numeric_limits<uint32_t>::max()) {
40 return false;
41 }
42 return ValidFieldNumber(static_cast<uint32_t>(field_number));
43}
44
45enum class WireType {
46 kVarint = 0,
47 kFixed64 = 1,
48 kDelimited = 2,
49 // Wire types 3 and 4 are deprecated per the protobuf specification.
50 kFixed32 = 5,
51};
52
53// Represents a protobuf field key, storing a field number and wire type.
54class FieldKey {
55 public:
56 // Checks if the given encoded protobuf key is valid. Must be called before
57 // instantiating a FieldKey object with it.
58 static constexpr bool IsValidKey(uint64_t key) {
59 uint64_t field_number = key >> kFieldNumberShift;
60 uint32_t wire_type = key & kWireTypeMask;
61
62 return ValidFieldNumber(field_number) && (wire_type <= 2 || wire_type == 5);
63 }
64
65 // Creates a field key with the given field number and type.
66 //
67 // Precondition: The field number is valid.
68 constexpr FieldKey(uint32_t field_number, WireType wire_type)
69 : key_(field_number << kFieldNumberShift |
70 static_cast<uint32_t>(wire_type)) {
71 PW_DASSERT(ValidFieldNumber(field_number));
72 }
73
74 // Parses a field key from its encoded representation.
75 //
76 // Precondition: The field number is valid. Call IsValidKey(key) first.
77 constexpr FieldKey(uint32_t key) : key_(key) {
78 PW_DASSERT(ValidFieldNumber(field_number()));
79 }
80
81 constexpr operator uint32_t() { return key_; }
82
83 constexpr uint32_t field_number() const { return key_ >> kFieldNumberShift; }
84 constexpr WireType wire_type() const {
85 return static_cast<WireType>(key_ & kWireTypeMask);
86 }
87
88 private:
89 static constexpr unsigned int kFieldNumberShift = 3u;
90 static constexpr unsigned int kWireTypeMask = (1u << kFieldNumberShift) - 1u;
91
92 uint32_t key_;
93};
94
95[[deprecated("Use the FieldKey class")]] constexpr uint32_t MakeKey(
96 uint32_t field_number, WireType wire_type) {
97 return FieldKey(field_number, wire_type);
98}
99
101
102} // namespace pw::protobuf
Definition: wire_format.h:54