123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- /* Copyright (c) 2018-2023 Marcelo Zimbres Silva ([email protected])
- *
- * Distributed under the Boost Software License, Version 1.0. (See
- * accompanying file LICENSE.txt)
- */
- #ifndef BOOST_REDIS_RESP3_SERIALIZATION_HPP
- #define BOOST_REDIS_RESP3_SERIALIZATION_HPP
- #include <boost/redis/resp3/type.hpp>
- #include <boost/system/system_error.hpp>
- #include <boost/throw_exception.hpp>
- #include <boost/redis/resp3/parser.hpp>
- #include <string>
- #include <tuple>
- // NOTE: Consider detecting tuples in the type in the parameter pack
- // to calculate the header size correctly.
- namespace boost::redis::resp3 {
- /** @brief Adds a bulk to the request.
- * @relates boost::redis::request
- *
- * This function is useful in serialization of your own data
- * structures in a request. For example
- *
- * @code
- * void boost_redis_to_bulk(std::string& payload, mystruct const& obj)
- * {
- * auto const str = // Convert obj to a string.
- * boost_redis_to_bulk(payload, str);
- * }
- * @endcode
- *
- * @param payload Storage on which data will be copied into.
- * @param data Data that will be serialized and stored in `payload`.
- *
- * See more in @ref serialization.
- */
- void boost_redis_to_bulk(std::string& payload, std::string_view data);
- template <class T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
- void boost_redis_to_bulk(std::string& payload, T n)
- {
- auto const s = std::to_string(n);
- boost::redis::resp3::boost_redis_to_bulk(payload, std::string_view{s});
- }
- template <class T>
- struct add_bulk_impl {
- static void add(std::string& payload, T const& from)
- {
- using namespace boost::redis::resp3;
- boost_redis_to_bulk(payload, from);
- }
- };
- template <class ...Ts>
- struct add_bulk_impl<std::tuple<Ts...>> {
- static void add(std::string& payload, std::tuple<Ts...> const& t)
- {
- auto f = [&](auto const&... vs)
- {
- using namespace boost::redis::resp3;
- (boost_redis_to_bulk(payload, vs), ...);
- };
- std::apply(f, t);
- }
- };
- template <class U, class V>
- struct add_bulk_impl<std::pair<U, V>> {
- static void add(std::string& payload, std::pair<U, V> const& from)
- {
- using namespace boost::redis::resp3;
- boost_redis_to_bulk(payload, from.first);
- boost_redis_to_bulk(payload, from.second);
- }
- };
- void add_header(std::string& payload, type t, std::size_t size);
- template <class T>
- void add_bulk(std::string& payload, T const& data)
- {
- add_bulk_impl<T>::add(payload, data);
- }
- template <class>
- struct bulk_counter;
- template <class>
- struct bulk_counter {
- static constexpr auto size = 1U;
- };
- template <class T, class U>
- struct bulk_counter<std::pair<T, U>> {
- static constexpr auto size = 2U;
- };
- void add_blob(std::string& payload, std::string_view blob);
- void add_separator(std::string& payload);
- namespace detail
- {
- template <class Adapter>
- void deserialize(std::string_view const& data, Adapter adapter, system::error_code& ec)
- {
- parser parser;
- while (!parser.done()) {
- auto const res = parser.consume(data, ec);
- if (ec)
- return;
- BOOST_ASSERT(res.has_value());
- adapter(res.value(), ec);
- if (ec)
- return;
- }
- BOOST_ASSERT(parser.get_consumed() == std::size(data));
- }
- template <class Adapter>
- void deserialize(std::string_view const& data, Adapter adapter)
- {
- system::error_code ec;
- deserialize(data, adapter, ec);
- if (ec)
- BOOST_THROW_EXCEPTION(system::system_error{ec});
- }
- }
- } // boost::redis::resp3
- #endif // BOOST_REDIS_RESP3_SERIALIZATION_HPP
|