diff --git a/include/parselink/msgpack/core/detail/packable_ranges.h b/include/parselink/msgpack/core/detail/packable_ranges.h index 8e1ef3c..cef11ac 100644 --- a/include/parselink/msgpack/core/detail/packable_ranges.h +++ b/include/parselink/msgpack/core/detail/packable_ranges.h @@ -23,29 +23,78 @@ #include "builtin_packable_types.h" #include +#include namespace msgpack { -namespace detail {} // namespace detail +namespace detail { + +// +template +concept packable_array = std::ranges::input_range + && builtin_packable>; template -concept packable_range = std::ranges::input_range - && builtin_packable>; +concept tuple_like = requires(T t) { typename std::tuple_size::type; }; + +template +concept key_value_pairlike = requires(T t) { + typename std::tuple_size::type; +} && std::tuple_size_v == 2; + +template +concept packable_map = + std::ranges::input_range + && key_value_pairlike> + && builtin_packable< + std::tuple_element_t<0, std::ranges::range_value_t>> + && builtin_packable< + std::tuple_element_t<1, std::ranges::range_value_t>>; + +template +struct desc_traits; + +template +struct desc_traits { + using type = map_desc; +}; + +template +struct desc_traits { + using type = array_desc; +}; + +} // namespace detail + +template +concept packable_range = detail::packable_array || detail::packable_map; template struct builtin_packer : builtin_packer_base { + using desc_type = detail::desc_traits::type; + static constexpr std::size_t rep_size(T const& value) { return std::ranges::size(value); } + static constexpr auto desc(T const& value) { + return desc_type(rep_size(value)); + } + static constexpr auto marker(T const& value) { - array_desc desc(rep_size(value)); - return builtin_packer::marker(desc); + return builtin_packer::marker(desc(value)); } static constexpr void pack(T const& value, auto& packer) noexcept { - packer.pack(array_desc(rep_size(value))); - for (auto const& element : value) { - packer.pack(element); + packer.pack(desc(value)); + if constexpr (detail::packable_map) { + for (auto const& [key, value] : value) { + packer.pack(key); + packer.pack(value); + } + } else { + for (auto const& element : value) { + packer.pack(element); + } } } }; diff --git a/tests/msgpack/BUILD b/tests/msgpack/BUILD index fae7cc2..179dfbb 100644 --- a/tests/msgpack/BUILD +++ b/tests/msgpack/BUILD @@ -76,3 +76,11 @@ cc_binary( ], deps = ["test_deps"], ) + +cc_binary( + name = "code", + srcs = [ + "test_code.cpp", + ], + deps = ["test_deps"], +) diff --git a/tests/msgpack/test_code.cpp b/tests/msgpack/test_code.cpp new file mode 100644 index 0000000..f8697f6 --- /dev/null +++ b/tests/msgpack/test_code.cpp @@ -0,0 +1,17 @@ +#include +#include +#include + +int main(int argc, char** argv) { + std::map args{}; + for (int i = 0; i < argc; ++i) { + args.emplace(i, argv[i]); + } + std::array buff; + msgpack::packer packer(buff); + packer.pack(args); + for (auto b : packer.subspan()) { + printf("%c", char(b)); + } + return 0; +}