diff --git a/wpiutil/src/main/native/include/wpi/util/protobuf/ProtobufCallbacks.hpp b/wpiutil/src/main/native/include/wpi/util/protobuf/ProtobufCallbacks.hpp index d700c567d9..00763da8c0 100644 --- a/wpiutil/src/main/native/include/wpi/util/protobuf/ProtobufCallbacks.hpp +++ b/wpiutil/src/main/native/include/wpi/util/protobuf/ProtobufCallbacks.hpp @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include @@ -482,15 +483,31 @@ struct WpiArrayUnpackCallback * A callback method that will pack elements when called. * * @tparam T object type + * @tparam R range type (defaults to std::span) */ -template +template > + requires std::same_as>, T> class PackCallback { public: + /** + * Constructs a pack callback from a range of elements. The range + * _MUST_ stay alive throughout the entire encode call. + */ + explicit PackCallback(const R& range) + requires(!std::same_as>) + : m_range{&range} { + m_callback.funcs.encode = CallbackFunc; + m_callback.arg = this; + } + /** * Constructs a pack callback from a span of elements. The elements in the * buffer _MUST_ stay alive throughout the entire encode call. */ - explicit PackCallback(std::span buffer) : m_buffer{buffer} { + explicit PackCallback(std::span buffer) + requires std::same_as> + : m_storedSpan{buffer}, m_range{&m_storedSpan} { m_callback.funcs.encode = CallbackFunc; m_callback.arg = this; } @@ -502,10 +519,9 @@ class PackCallback { * reference) */ explicit PackCallback(const T* element) - : m_buffer{std::span{element, 1}} { - m_callback.funcs.encode = CallbackFunc; - m_callback.arg = this; - } + requires std::same_as> + : PackCallback(std::span{element, 1}) {} + PackCallback(const PackCallback&) = delete; PackCallback(PackCallback&&) = delete; PackCallback& operator=(const PackCallback&) = delete; @@ -518,13 +534,6 @@ class PackCallback { */ pb_callback_t Callback() const { return m_callback; } - /** - * Gets a span pointing to the items - * - * @return span - */ - std::span Bufs() const { return m_buffer; } - private: static auto EncodeStreamTypeFinder() { if constexpr (ProtobufSerializable) { @@ -588,9 +597,10 @@ class PackCallback { bool EncodeLoop(pb_ostream_t* stream, const pb_field_t* field, bool writeTag) const { + const R& range = *m_range; if constexpr (ProtobufSerializable) { ProtoOutputStream ostream{stream}; - for (auto&& i : m_buffer) { + for (const auto& i : range) { if (writeTag) { if (!pb_encode_tag_for_field(stream, field)) { return false; @@ -601,7 +611,7 @@ class PackCallback { } } } else { - for (auto&& i : m_buffer) { + for (const auto& i : range) { if (writeTag) { if (!pb_encode_tag_for_field(stream, field)) { return false; @@ -612,7 +622,6 @@ class PackCallback { } } } - return true; } @@ -641,7 +650,7 @@ class PackCallback { bool CallbackFunc(pb_ostream_t* stream, const pb_field_t* field) const { // First off, if we're empty, do nothing, but say we were successful - if (m_buffer.empty()) { + if (std::ranges::empty(*m_range)) { return true; } @@ -664,8 +673,16 @@ class PackCallback { field); } - std::span m_buffer; + std::span m_storedSpan; + const R* m_range{nullptr}; pb_callback_t m_callback; }; +template +PackCallback(const R&) + -> PackCallback>, R>; + +template +PackCallback(const T*) -> PackCallback; + } // namespace wpi::util