From cd73f2aa1783cfce1cefd056ac459d0b20db5913 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Tue, 29 Nov 2022 17:19:09 +1100 Subject: [PATCH] Use some template magic to automatically deserialize UI messages We always deserialize arguments in order, and we can extract argument types from the type of the pointer to method. --- src/remote.cc | 64 ++++++++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/src/remote.cc b/src/remote.cc index 63a7fecf..99fda3e1 100644 --- a/src/remote.cc +++ b/src/remote.cc @@ -183,6 +183,9 @@ private: } }; + template + struct Reader> : Reader, MemoryDomain::Undefined>> {}; + template struct Reader> { static HashMap read(MsgReader& reader) @@ -256,7 +259,7 @@ public: } template - T read() + auto read() { return Reader::read(*this); } @@ -664,6 +667,17 @@ RemoteClient::RemoteClient(StringView session, StringView name, std::unique_ptr< if (events & FdEvents::Write and send_data(sock, m_send_buffer)) watcher.events() &= ~FdEvents::Write; + auto exec = [&](void (UserInterface::*method)(Args...)) { + struct Impl // Use a constructor to ensure left-to-right parameter evaluation + { + Impl(UserInterface& ui, void (UserInterface::*method)(Args...), Args... args) + { + (ui.*method)(std::forward(args)...); + } + }; + Impl{*m_ui, method, reader.read>()...}; + }; + while (events & FdEvents::Read and not reader.ready() and fd_readable(sock)) { @@ -676,62 +690,34 @@ RemoteClient::RemoteClient(StringView session, StringView name, std::unique_ptr< switch (reader.type()) { case MessageType::MenuShow: - { - auto choices = reader.read>(); - auto anchor = reader.read(); - auto fg = reader.read(); - auto bg = reader.read(); - auto style = reader.read(); - m_ui->menu_show(choices, anchor, fg, bg, style); + exec(&UserInterface::menu_show); break; - } case MessageType::MenuSelect: - m_ui->menu_select(reader.read()); + exec(&UserInterface::menu_select); break; case MessageType::MenuHide: - m_ui->menu_hide(); + exec(&UserInterface::menu_hide); break; case MessageType::InfoShow: - { - auto title = reader.read(); - auto content = reader.read(); - auto anchor = reader.read(); - auto face = reader.read(); - auto style = reader.read(); - m_ui->info_show(title, content, anchor, face, style); + exec(&UserInterface::info_show); break; - } case MessageType::InfoHide: - m_ui->info_hide(); + exec(&UserInterface::info_hide); break; case MessageType::Draw: - { - auto display_buffer = reader.read(); - auto default_face = reader.read(); - auto padding_face = reader.read(); - m_ui->draw(display_buffer, default_face, padding_face); + exec(&UserInterface::draw); break; - } case MessageType::DrawStatus: - { - auto status_line = reader.read(); - auto mode_line = reader.read(); - auto default_face = reader.read(); - m_ui->draw_status(status_line, mode_line, default_face); + exec(&UserInterface::draw_status); break; - } case MessageType::SetCursor: - { - auto mode = reader.read(); - auto coord = reader.read(); - m_ui->set_cursor(mode, coord); + exec(&UserInterface::set_cursor); break; - } case MessageType::Refresh: - m_ui->refresh(reader.read()); + exec(&UserInterface::refresh); break; case MessageType::SetOptions: - m_ui->set_ui_options(reader.read>()); + exec(&UserInterface::set_ui_options); break; case MessageType::Exit: m_exit_status = reader.read();