From fdd4b2b5a345f1aadfe50f042ad58f562b194233 Mon Sep 17 00:00:00 2001 From: Jake Tuero Date: Fri, 11 Aug 2023 17:14:47 -0600 Subject: [PATCH] set, unordered_set, and deque support --- docs/getting-started.md | 3 +- include/nop/base/deque.h | 101 ++++++++++++++++++++++++ include/nop/base/set.h | 162 +++++++++++++++++++++++++++++++++++++++ include/nop/serializer.h | 2 + 4 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 include/nop/base/deque.h create mode 100644 include/nop/base/set.h diff --git a/docs/getting-started.md b/docs/getting-started.md index 1c4c1d1..e28e5d7 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -56,9 +56,10 @@ This interface supports the following types: * enum and enum classes. * std::string. * C-style arrays with elements of any supported type. - * std::array, std::pair, std::tuple, and std::vector with elements of any + * std::array, std::pair, std::tuple, std::vector, and std::deque with elements of any supported type. * std::map and std::unordered_map with keys and values of any supported type. + * std::set and std::unordered_set with keys of any supported type. * std::reference_wrapper with T of any supported type. * nop::Optional with T of any supported type. * nop::Result with T of any supported type. diff --git a/include/nop/base/deque.h b/include/nop/base/deque.h new file mode 100644 index 0000000..aa2de83 --- /dev/null +++ b/include/nop/base/deque.h @@ -0,0 +1,101 @@ +/* + * Copyright 2017 The Native Object Protocols Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBNOP_INCLUDE_NOP_BASE_DEQUE_H_ +#define LIBNOP_INCLUDE_NOP_BASE_DEQUE_H_ + +#include +#include + +#include +#include + +namespace nop { + +// +// std::deque encoding format: +// +// +-------+---------+-----//-----+ +// | DEQUE | INT64:N | N ELEMENTS | +// +-------+---------+-----//-----+ +// +// Elements must be valid encodings of type T. +// + +template +struct Encoding> + : EncodingIO> { + using Type = std::deque; + + static constexpr EncodingByte Prefix(const Type& /*value*/) { + return EncodingByte::Array; + } + + static constexpr std::size_t Size(const Type& value) { + return BaseEncodingSize(Prefix(value)) + + Encoding::Size(value.size()) + + std::accumulate(value.cbegin(), value.cend(), 0U, + [](const std::size_t& sum, const T& element) { + return sum + Encoding::Size(element); + }); + } + + static constexpr bool Match(EncodingByte prefix) { + return prefix == EncodingByte::Array; + } + + template + static constexpr Status WritePayload(EncodingByte /*prefix*/, + const Type& value, + Writer* writer) { + auto status = Encoding::Write(value.size(), writer); + if (!status) + return status; + + for (const T& element : value) { + status = Encoding::Write(element, writer); + if (!status) + return status; + } + + return {}; + } + + template + static constexpr Status ReadPayload(EncodingByte /*prefix*/, + Type* value, Reader* reader) { + SizeType size = 0; + auto status = Encoding::Read(&size, reader); + if (!status) + return status; + + value->clear(); + for (SizeType i = 0; i < size; i++) { + T element; + status = Encoding::Read(&element, reader); + if (!status) + return status; + + value->push_back(std::move(element)); + } + + return {}; + } +}; + +} // namespace nop + +#endif // LIBNOP_INCLUDE_NOP_BASE_DEQUE_H_ diff --git a/include/nop/base/set.h b/include/nop/base/set.h new file mode 100644 index 0000000..7afe5ba --- /dev/null +++ b/include/nop/base/set.h @@ -0,0 +1,162 @@ +/* + * Copyright 2017 The Native Object Protocols Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBNOP_INCLUDE_NOP_BASE_SET_H_ +#define LIBNOP_INCLUDE_NOP_BASE_SET_H_ + +#include + +#include +#include +#include + +namespace nop { + +// +// std::set and std::unordered_set encoding format: +// +// +-----+---------+---//---+ +// | SET | INT64:N | N KEYS | +// +-----+---------+---//---+ +// +// Elements must be valid encodings of type T. +// + +template +struct Encoding> + : EncodingIO> { + using Type = std::set; + + static constexpr EncodingByte Prefix(const Type& /*value*/) { + return EncodingByte::Array; + } + + static constexpr std::size_t Size(const Type& value) { + return BaseEncodingSize(Prefix(value)) + + Encoding::Size(value.size()) + + std::accumulate(value.cbegin(), value.cend(), 0U, + [](const std::size_t& sum, const Key& element) { + return sum + Encoding::Size(element); + }); + } + + static constexpr bool Match(EncodingByte prefix) { + return prefix == EncodingByte::Array; + } + + template + static constexpr Status WritePayload(EncodingByte /*prefix*/, + const Type& value, + Writer* writer) { + auto status = Encoding::Write(value.size(), writer); + if (!status) + return status; + + for (const Key& element : value) { + status = Encoding::Write(element, writer); + if (!status) + return status; + } + + return {}; + } + + template + static constexpr Status ReadPayload(EncodingByte /*prefix*/, + Type* value, Reader* reader) { + SizeType size = 0; + auto status = Encoding::Read(&size, reader); + if (!status) + return status; + + value->clear(); + for (SizeType i = 0; i < size; i++) { + Key element; + status = Encoding::Read(&element, reader); + if (!status) + return status; + + value->insert(std::move(element)); + } + + return {}; + } +}; + +template +struct Encoding> + : EncodingIO> { + using Type = std::unordered_set; + + static constexpr EncodingByte Prefix(const Type& /*value*/) { + return EncodingByte::Array; + } + + static constexpr std::size_t Size(const Type& value) { + return BaseEncodingSize(Prefix(value)) + + Encoding::Size(value.size()) + + std::accumulate(value.cbegin(), value.cend(), 0U, + [](const std::size_t& sum, const Key& element) { + return sum + Encoding::Size(element); + }); + } + + static constexpr bool Match(EncodingByte prefix) { + return prefix == EncodingByte::Array; + } + + template + static constexpr Status WritePayload(EncodingByte /*prefix*/, + const Type& value, + Writer* writer) { + auto status = Encoding::Write(value.size(), writer); + if (!status) + return status; + + for (const Key& element : value) { + status = Encoding::Write(element, writer); + if (!status) + return status; + } + + return {}; + } + + template + static constexpr Status ReadPayload(EncodingByte /*prefix*/, + Type* value, Reader* reader) { + SizeType size = 0; + auto status = Encoding::Read(&size, reader); + if (!status) + return status; + + value->clear(); + for (SizeType i = 0; i < size; i++) { + Key element; + status = Encoding::Read(&element, reader); + if (!status) + return status; + + value->insert(std::move(element)); + } + + return {}; + } +}; + +} // namespace nop + +#endif // LIBNOP_INCLUDE_NOP_BASE_SET_H_ diff --git a/include/nop/serializer.h b/include/nop/serializer.h index a908cfc..220d92d 100644 --- a/include/nop/serializer.h +++ b/include/nop/serializer.h @@ -18,6 +18,7 @@ #define LIBNOP_INCLUDE_NOP_SERIALIZER_H_ #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include #include