Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <warpcoil/cpp/helpers.hpp>
- #include <silicium/source/source.hpp>
- #include <silicium/sink/iterator_sink.hpp>
- #include <silicium/sink/append.hpp>
- #include <silicium/variant.hpp>
- #include <boost/asio/write.hpp>
- #include <boost/range/algorithm/equal.hpp>
- #include <cstdint>
- #include <tuple>
- struct async_hello_as_a_service
- {
- virtual ~async_hello_as_a_service()
- {
- }
- virtual void hello(std::string name, std::function<void(boost::system::error_code, std::string)> on_result) = 0;
- };
- template <class Client>
- struct async_type_erased_hello_as_a_service : async_hello_as_a_service
- {
- Client &client;
- explicit async_type_erased_hello_as_a_service(Client &client)
- : client(client)
- {
- }
- virtual ~async_type_erased_hello_as_a_service()
- {
- }
- void hello(std::string name, std::function<void(boost::system::error_code, std::string)> on_result) override
- {
- return client.hello(std::move(name), std::move(on_result));
- }
- };
- template <class AsyncWriteStream, class AsyncReadStream>
- struct async_hello_as_a_service_client
- {
- explicit async_hello_as_a_service_client(AsyncWriteStream &requests, AsyncReadStream &responses)
- : requests(requests)
- , responses(responses)
- , response_buffer_used(0)
- {
- }
- template <class CompletionToken>
- auto hello(std::string name, CompletionToken &&token)
- {
- using handler_type =
- typename boost::asio::handler_type<decltype(token), void(boost::system::error_code, std::string)>::type;
- handler_type handler(std::forward<CompletionToken>(token));
- boost::asio::async_result<handler_type> result(handler);
- request_buffer.clear();
- auto request_writer = Si::Sink<std::uint8_t, Si::success>::erase(Si::make_container_sink(request_buffer));
- append(request_writer, 5u);
- append(request_writer, Si::make_c_str_range(reinterpret_cast<std::uint8_t const *>("hello")));
- if (!utf8::is_valid(name.begin(), name.end()))
- {
- handler(warpcoil::cpp::make_invalid_input_error(), {});
- return result.get();
- }
- if ((name.size()) > 255u)
- {
- handler(warpcoil::cpp::make_invalid_input_error(), {});
- return result.get();
- }
- warpcoil::cpp::write_integer(request_writer, static_cast<std::uint8_t>(name.size()));
- Si::append(request_writer,
- Si::make_iterator_range(reinterpret_cast<std::uint8_t const *>(name.data()),
- reinterpret_cast<std::uint8_t const *>(name.data() + name.size())));
- boost::asio::async_write(
- requests, boost::asio::buffer(request_buffer),
- [ this, handler = std::move(handler) ](boost::system::error_code ec, std::size_t) mutable
- {
- if (!!ec)
- {
- std::move(handler)(ec, {});
- return;
- }
- begin_parse_value(responses, boost::asio::buffer(response_buffer), response_buffer_used,
- warpcoil::cpp::utf8_parser<warpcoil::cpp::integer_parser<std::uint8_t>>{},
- std::move(handler));
- });
- return result.get();
- }
- private:
- std::vector<std::uint8_t> request_buffer;
- AsyncWriteStream &requests;
- std::array<std::uint8_t, 512> response_buffer;
- AsyncReadStream &responses;
- std::size_t response_buffer_used;
- };
- template <class AsyncReadStream, class AsyncWriteStream>
- struct async_hello_as_a_service_server
- {
- explicit async_hello_as_a_service_server(async_hello_as_a_service &implementation, AsyncReadStream &requests,
- AsyncWriteStream &responses)
- : implementation(implementation)
- , requests(requests)
- , request_buffer_used(0)
- , responses(responses)
- {
- }
- template <class CompletionToken>
- auto serve_one_request(CompletionToken &&token)
- {
- using handler_type = typename boost::asio::handler_type<decltype(token), void(boost::system::error_code)>::type;
- handler_type handler(std::forward<CompletionToken>(token));
- boost::asio::async_result<handler_type> result(handler);
- begin_receive_method_name(std::move(handler));
- return result.get();
- }
- private:
- async_hello_as_a_service &implementation;
- AsyncReadStream &requests;
- std::array<std::uint8_t, 512> request_buffer;
- std::size_t request_buffer_used;
- std::vector<std::uint8_t> response_buffer;
- AsyncWriteStream &responses;
- typedef warpcoil::cpp::utf8_parser<warpcoil::cpp::integer_parser<std::uint8_t>> method_name_parser;
- template <class Handler>
- void begin_receive_method_name(Handler &&handle_result)
- {
- begin_parse_value(requests, boost::asio::buffer(request_buffer), request_buffer_used, method_name_parser(),
- [ this, handle_result = std::forward<Handler>(handle_result) ](boost::system::error_code ec,
- std::string name) mutable
- {
- if (!!ec)
- {
- std::forward<Handler>(handle_result)(ec);
- return;
- }
- if (boost::range::equal(name, Si::make_c_str_range("hello")))
- {
- begin_receive_method_argument_of_hello(std::forward<Handler>(handle_result));
- }
- else
- {
- throw std::logic_error("to do: handle unknown method name");
- }
- });
- }
- template <class Handler>
- void begin_receive_method_argument_of_hello(Handler &&handle_result)
- {
- begin_parse_value(
- requests, boost::asio::buffer(request_buffer), request_buffer_used,
- warpcoil::cpp::tuple_parser<warpcoil::cpp::utf8_parser<warpcoil::cpp::integer_parser<std::uint8_t>>>{},
- [ this, handle_result = std::forward<Handler>(handle_result) ](boost::system::error_code ec,
- std::tuple<std::string> argument) mutable
- {
- if (!!ec)
- {
- std::forward<Handler>(handle_result)(ec);
- return;
- }
- implementation.hello(
- std::get<0>(std::move(argument)), [ this, handle_result = std::forward<Handler>(handle_result) ](
- boost::system::error_code ec, std::string result) mutable
- {
- if (!!ec)
- {
- std::forward<Handler>(handle_result)(ec);
- return;
- }
- response_buffer.clear();
- auto response_writer =
- Si::Sink<std::uint8_t, Si::success>::erase(Si::make_container_sink(response_buffer));
- if (!utf8::is_valid(result.begin(), result.end()))
- {
- return std::forward<Handler>(handle_result)(warpcoil::cpp::make_invalid_input_error());
- }
- if ((result.size()) > 255u)
- {
- return std::forward<Handler>(handle_result)(warpcoil::cpp::make_invalid_input_error());
- }
- warpcoil::cpp::write_integer(response_writer, static_cast<std::uint8_t>(result.size()));
- Si::append(response_writer,
- Si::make_iterator_range(
- reinterpret_cast<std::uint8_t const *>(result.data()),
- reinterpret_cast<std::uint8_t const *>(result.data() + result.size())));
- boost::asio::async_write(responses, boost::asio::buffer(response_buffer),
- [handle_result = std::forward<Handler>(handle_result)](
- boost::system::error_code ec, std::size_t) mutable
- {
- std::forward<Handler>(handle_result)(ec);
- });
- });
- });
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement