Google OR-Tools v9.12
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
proto_enum_utils.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#ifndef OR_TOOLS_BASE_PROTO_ENUM_UTILS_H_
15#define OR_TOOLS_BASE_PROTO_ENUM_UTILS_H_
16
17// Provides utility functions that help with handling Protocol Buffer enums.
18//
19// Examples:
20//
21// A function to easily iterate over all defined values of an enum known at
22// compile-time:
23//
24// for (Proto::Enum e : EnumerateEnumValues<Proto::Enum>()) {
25// ...
26// }
27//
28
29#include <iterator>
30#include <type_traits>
31
32#include "absl/types/span.h"
33#include "google/protobuf/descriptor.pb.h"
34
36
37using google::protobuf::GetEnumDescriptor;
38using google::protobuf::RepeatedField;
39
40template <typename E>
42
43template <typename E>
45
46template <typename E>
48
49template <typename E>
51
52// Generic Proto enum iterator.
53template <typename E>
55 public:
56 typedef E value_type;
57 typedef std::forward_iterator_tag iterator_category;
58 typedef int difference_type;
59 typedef E* pointer;
60 typedef E& reference;
61
62 ProtoEnumIterator() : current_(0) {}
63
65 : current_(other.current_) {}
66
68 current_ = other.current_;
69 return *this;
70 }
71
73 ProtoEnumIterator other(*this);
74 ++(*this);
75 return other;
76 }
77
79 ++current_;
80 return *this;
81 }
82
83 E operator*() const {
84 return static_cast<E>(GetEnumDescriptor<E>()->value(current_)->number());
85 }
86
87 private:
88 explicit ProtoEnumIterator(int current) : current_(current) {}
89
90 int current_;
91
92 // Only EnumeratedProtoEnumView can instantiate ProtoEnumIterator.
93 friend class EnumeratedProtoEnumView<E>;
94 friend bool operator==
95 <>(const ProtoEnumIterator<E>& a, const ProtoEnumIterator<E>& b);
96 friend bool operator!=
97 <>(const ProtoEnumIterator<E>& a, const ProtoEnumIterator<E>& b);
98};
99
100template <typename E>
102 return a.current_ == b.current_;
103}
104
105template <typename E>
107 return a.current_ != b.current_;
108}
109
110template <typename E>
112 public:
113 typedef E value_type;
115 iterator begin() const { return iterator(0); }
116 iterator end() const {
117 return iterator(GetEnumDescriptor<E>()->value_count());
118 }
119};
120
121// Returns an EnumeratedProtoEnumView that can be iterated over:
122// for (Proto::Enum e : EnumerateEnumValues<Proto::Enum>()) {
123// ...
124// }
125template <typename E>
129
130// Returns a view that allows to iterate directly over the enum values
131// in an enum repeated field, wrapping the repeated field with a type-safe
132// iterator that provides access to the enum values.
133//
134// for (Enum enum :
135// REPEATED_ENUM_ADAPTER(message, repeated_enum_field)) {
136// ...
137// }
138//
139// It provides greater safety than iterating over the enum directly, as the
140// following will fail to type-check:
141//
142// .proto
143// RightEnum enum = 5;
144//
145// client .cc
146// for (WrongEnum e : REPEATED_ENUM_ADAPTER(proto, enum)) { <- Error: Cannot
147// cast from
148// RightEnum to
149// WrongEnum
150// }
151//
152// NOTE: As per http://shortn/_CYfjpruK6N, unrecognized enum values are treated
153// differently between proto2 and proto3.
154//
155// For proto2, they are stripped out from the message when read, so all
156// unrecognized enum values from the wire format will be skipped when iterating
157// over the wrapper (this is the same behavior as iterating over the
158// RepeatedField<int> directly).
159//
160// For proto3, they are left as-is, so unrecognized enum values from the wire
161// format will still be returned when iterating over the wrapper (this is the
162// same behavior as iterating over the RepeatedField<int> directly).
163//
164#define REPEATED_ENUM_ADAPTER(var, field) \
165 google::protobuf::contrib::utils::internal::RepeatedEnumView< \
166 decltype(var.field(0))>(var.field())
167
168// ==== WARNING TO USERS ====
169// Below are internal implementations, not public API, and may change without
170// notice. Do NOT use directly.
171
172namespace internal {
173
174// Implementation for REPEATED_ENUM_ADAPTER. This does not provide type safety
175// thus should be used through REPEATED_ENUM_ADAPTER only. See cr/246914845 for
176// context.
177template <typename E>
179 public:
180 class Iterator : public std::iterator<std::input_iterator_tag, E> {
181 public:
182 explicit Iterator(RepeatedField<int>::const_iterator ptr) : ptr_(ptr) {}
183 bool operator==(const Iterator& it) const { return ptr_ == it.ptr_; }
184 bool operator!=(const Iterator& it) const { return ptr_ != it.ptr_; }
186 ++ptr_;
187 return *this;
188 }
189 E operator*() const { return static_cast<E>(*ptr_); }
190
191 private:
192 RepeatedField<int>::const_iterator ptr_;
193 };
194
195 explicit RepeatedEnumView(const RepeatedField<int>& repeated_field)
196 : repeated_field_(repeated_field) {}
197
198 Iterator begin() const { return Iterator(repeated_field_.begin()); }
199 Iterator end() const { return Iterator(repeated_field_.end()); }
200
201 private:
202 const RepeatedField<int>& repeated_field_;
203};
204
205} // namespace internal
206
207} // namespace google::protobuf::contrib::utils
208
209#endif // OR_TOOLS_BASE_PROTO_ENUM_UTILS_H_
ProtoEnumIterator & operator=(const ProtoEnumIterator &other)
RepeatedEnumView(const RepeatedField< int > &repeated_field)
EnumeratedProtoEnumView< E > EnumerateEnumValues()
bool operator!=(const ProtoEnumIterator< E > &a, const ProtoEnumIterator< E > &b)
bool operator==(const ProtoEnumIterator< E > &a, const ProtoEnumIterator< E > &b)