module; #include #include #include #include export module ttwhy:io; import :event; import :scanner; namespace ttwhy::io { export template auto handle_signals(Stream & stream) -> asio::awaitable { auto executor = co_await asio::this_coro::executor; auto signals = asio::signal_set{executor, SIGINT, SIGTERM}; auto [error, signal] = co_await signals.async_wait(asio::as_tuple(asio::use_awaitable)); if (!error) { auto message = std::format("Received signal {}, exiting ...\n", signal); co_await asio::async_write(stream, asio::buffer(message), asio::use_awaitable); } co_return error; } export template auto read_events(InputStream & stream, AppRouter & router) -> asio::awaitable { auto queue = std::vector{}; queue.reserve(16); auto scanner = ansi_scanner{queue}; auto raw_buffer = std::array{}; while (true) { auto [error, bytes_read] = co_await stream.async_read_some(asio::buffer(raw_buffer), asio::as_tuple(asio::use_awaitable)); if (error) { co_return; } auto const byte_span = std::span{raw_buffer.data(), bytes_read}; scanner.process(byte_span); for (auto const & event : queue) { co_await router.process(event); } queue.clear(); } } } // namespace ttwhy::io