xref: /aosp_15_r20/external/pigweed/pw_protobuf/public/pw_protobuf/wire_format.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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 
21 namespace pw::protobuf {
22 
23 // Per the protobuf specification, valid field numbers range between 1 and
24 // 2**29 - 1, inclusive. The numbers 19000-19999 are reserved for internal
25 // use.
26 constexpr static uint32_t kMaxFieldNumber = (1u << 29) - 1;
27 constexpr static uint32_t kFirstReservedNumber = 19000;
28 constexpr static uint32_t kLastReservedNumber = 19999;
29 
ValidFieldNumber(uint32_t field_number)30 constexpr bool ValidFieldNumber(uint32_t field_number) {
31   return field_number != 0 && field_number <= kMaxFieldNumber &&
32          !(field_number >= kFirstReservedNumber &&
33            field_number <= kLastReservedNumber);
34 }
35 
ValidFieldNumber(uint64_t field_number)36 constexpr bool ValidFieldNumber(uint64_t field_number) {
37   if (field_number > std::numeric_limits<uint32_t>::max()) {
38     return false;
39   }
40   return ValidFieldNumber(static_cast<uint32_t>(field_number));
41 }
42 
43 enum class WireType {
44   kVarint = 0,
45   kFixed64 = 1,
46   kDelimited = 2,
47   // Wire types 3 and 4 are deprecated per the protobuf specification.
48   kFixed32 = 5,
49 };
50 
51 // Represents a protobuf field key, storing a field number and wire type.
52 class FieldKey {
53  public:
54   // Checks if the given encoded protobuf key is valid. Must be called before
55   // instantiating a FieldKey object with it.
IsValidKey(uint64_t key)56   static constexpr bool IsValidKey(uint64_t key) {
57     uint64_t field_number = key >> kFieldNumberShift;
58     uint32_t wire_type = key & kWireTypeMask;
59 
60     return ValidFieldNumber(field_number) && (wire_type <= 2 || wire_type == 5);
61   }
62 
63   // Creates a field key with the given field number and type.
64   //
65   // Precondition: The field number is valid.
FieldKey(uint32_t field_number,WireType wire_type)66   constexpr FieldKey(uint32_t field_number, WireType wire_type)
67       : key_(field_number << kFieldNumberShift |
68              static_cast<uint32_t>(wire_type)) {
69     PW_DASSERT(ValidFieldNumber(field_number));
70   }
71 
72   // Parses a field key from its encoded representation.
73   //
74   // Precondition: The field number is valid. Call IsValidKey(key) first.
FieldKey(uint32_t key)75   constexpr FieldKey(uint32_t key) : key_(key) {
76     PW_DASSERT(ValidFieldNumber(field_number()));
77   }
78 
uint32_t()79   constexpr operator uint32_t() { return key_; }
80 
field_number()81   constexpr uint32_t field_number() const { return key_ >> kFieldNumberShift; }
wire_type()82   constexpr WireType wire_type() const {
83     return static_cast<WireType>(key_ & kWireTypeMask);
84   }
85 
86  private:
87   static constexpr unsigned int kFieldNumberShift = 3u;
88   static constexpr unsigned int kWireTypeMask = (1u << kFieldNumberShift) - 1u;
89 
90   uint32_t key_;
91 };
92 
MakeKey(uint32_t field_number,WireType wire_type)93 [[deprecated("Use the FieldKey class")]] constexpr uint32_t MakeKey(
94     uint32_t field_number, WireType wire_type) {
95   return FieldKey(field_number, wire_type);
96 }
97 
98 }  // namespace pw::protobuf
99