// Protocol Buffers - Google's data interchange format // Copyright 2023 Google LLC. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd #ifndef UPB_PROTOS_REPEATED_FIELD_ITERATOR_H_ #define UPB_PROTOS_REPEATED_FIELD_ITERATOR_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "protos/protos.h" #include "upb/base/string_view.h" #include "upb/mem/arena.h" #include "upb/message/array.h" #include "upb/message/message.h" namespace protos { namespace internal { // TODO: Implement std iterator for messages template class RepeatedFieldScalarProxy; template class RepeatedFieldStringProxy; struct IteratorTestPeer; template class Iterator; template class ReferenceProxy; template class InjectedRelationalsImpl { using RP = ReferenceProxy; using V = typename PolicyT::value_type; friend bool operator==(RP a, V b) { return static_cast(a) == b; } friend bool operator==(V a, RP b) { return a == static_cast(b); } friend bool operator==(RP a, RP b) { return static_cast(a) == static_cast(b); } friend bool operator!=(RP a, V b) { return static_cast(a) != b; } friend bool operator!=(V a, RP b) { return a != static_cast(b); } friend bool operator!=(RP a, RP b) { return static_cast(a) != static_cast(b); } friend bool operator<(RP a, V b) { return static_cast(a) < b; } friend bool operator<(V a, RP b) { return a < static_cast(b); } friend bool operator<(RP a, RP b) { return static_cast(a) < static_cast(b); } friend bool operator<=(RP a, V b) { return static_cast(a) <= b; } friend bool operator<=(V a, RP b) { return a <= static_cast(b); } friend bool operator<=(RP a, RP b) { return static_cast(a) <= static_cast(b); } friend bool operator>(RP a, V b) { return static_cast(a) > b; } friend bool operator>(V a, RP b) { return a > static_cast(b); } friend bool operator>(RP a, RP b) { return static_cast(a) > static_cast(b); } friend bool operator>=(RP a, V b) { return static_cast(a) >= b; } friend bool operator>=(V a, RP b) { return a >= static_cast(b); } friend bool operator>=(RP a, RP b) { return static_cast(a) >= static_cast(b); } }; class NoInjectedRelationalsImpl {}; // We need to inject relationals for the string references because the // relationals for string_view are templates and won't allow for implicit // conversions from ReferenceProxy to string_view before deduction. template using InjectedRelationals = std::conditional_t< std::is_same_v, absl::string_view>, InjectedRelationalsImpl, NoInjectedRelationalsImpl>; template class ReferenceProxy : InjectedRelationals { using value_type = typename PolicyT::value_type; public: ReferenceProxy(const ReferenceProxy&) = default; ReferenceProxy& operator=(const ReferenceProxy& other) { // Assign through the references // TODO: Make this better for strings to avoid the copy. it_.Set(other.it_.Get()); return *this; } friend void swap(ReferenceProxy a, ReferenceProxy b) { a.it_.swap(b.it_); } operator value_type() const { return it_.Get(); } void operator=(const value_type& value) const { it_.Set(value); } void operator=(value_type&& value) const { it_.Set(std::move(value)); } Iterator operator&() const { return Iterator(it_); } private: friend IteratorTestPeer; friend ReferenceProxy; friend Iterator; explicit ReferenceProxy(typename PolicyT::Payload elem) : it_(elem) {} typename PolicyT::Payload it_; }; template