From 99be3ff5e2a9e2e74fe23537647631a1aa87783d Mon Sep 17 00:00:00 2001 From: Jason Felice Date: Sat, 20 Apr 2019 12:43:52 -0400 Subject: [PATCH] Use helper template struct in MsgReader This makes reads for all types, including String, Vector, and Optional, use the same interface in MsgReader. --- src/remote.cc | 177 ++++++++++++++++++++++++++++---------------------- 1 file changed, 101 insertions(+), 76 deletions(-) diff --git a/src/remote.cc b/src/remote.cc index d00a81a4..5490a7b6 100644 --- a/src/remote.cc +++ b/src/remote.cc @@ -150,6 +150,58 @@ private: class MsgReader { +private: + template + struct Reader { + static T read(MsgReader& reader) + { + static_assert(std::is_trivially_copyable::value, ""); + T res; + reader.read(reinterpret_cast(&res), sizeof(T)); + return res; + } + }; + + template + struct Reader> { + static Vector read(MsgReader& reader) + { + uint32_t size = Reader::read(reader); + Vector res; + res.reserve(size); + while (size--) + res.push_back(std::move(Reader::read(reader))); + return res; + } + }; + + template + struct Reader> { + static HashMap read(MsgReader& reader) + { + uint32_t size = Reader::read(reader); + HashMap res; + res.reserve(size); + while (size--) + { + auto key = Reader::read(reader); + auto val = Reader::read(reader); + res.insert({std::move(key), std::move(val)}); + } + return res; + } + }; + + template + struct Reader> { + static Optional read(MsgReader& reader) + { + if (not Reader::read(reader)) + return {}; + return Reader::read(reader); + } + }; + public: void read_available(int sock) { @@ -198,44 +250,7 @@ public: template T read() { - static_assert(std::is_trivially_copyable::value, ""); - T res; - read(reinterpret_cast(&res), sizeof(T)); - return res; - } - - template - Vector read_vector() - { - uint32_t size = read(); - Vector res; - res.reserve(size); - while (size--) - res.push_back(read()); - return res; - } - - template - HashMap read_hash_map() - { - uint32_t size = read(); - HashMap res; - res.reserve(size); - while (size--) - { - auto key = read(); - auto val = read(); - res.insert({std::move(key), std::move(val)}); - } - return res; - } - - template - Optional read_optional() - { - if (not read()) - return {}; - return read(); + return Reader::read(*this); } void reset() @@ -262,52 +277,62 @@ private: }; template<> -String MsgReader::read() -{ - ByteCount length = read(); - String res; - if (length > 0) +struct MsgReader::Reader { + static String read(MsgReader& reader) { - res.force_size((int)length); - read(&res[0_byte], (int)length); + ByteCount length = Reader::read(reader); + String res; + if (length > 0) + { + res.force_size((int)length); + reader.read(&res[0_byte], (int)length); + } + return res; } - return res; -} +}; template<> -Color MsgReader::read() -{ - Color res; - res.color = read(); - if (res.color == Color::RGB) +struct MsgReader::Reader { + static Color read(MsgReader& reader) { - res.r = read(); - res.g = read(); - res.b = read(); + Color res; + res.color = Reader::read(reader); + if (res.color == Color::RGB) + { + res.r = Reader::read(reader); + res.g = Reader::read(reader); + res.b = Reader::read(reader); + } + return res; } - return res; -} +}; template<> -DisplayAtom MsgReader::read() -{ - String content = read(); - return {std::move(content), read()}; -} +struct MsgReader::Reader { + static DisplayAtom read(MsgReader& reader) + { + String content = Reader::read(reader); + return {std::move(content), Reader::read(reader)}; + } +}; template<> -DisplayLine MsgReader::read() -{ - return {read_vector()}; -} +struct MsgReader::Reader { + static DisplayLine read(MsgReader& reader) + { + return {Reader>::read(reader)}; + } +}; template<> -DisplayBuffer MsgReader::read() -{ - DisplayBuffer db; - db.lines() = read_vector(); - return db; -} +struct MsgReader::Reader { + static DisplayBuffer read(MsgReader& reader) + { + DisplayBuffer db; + db.lines() = Reader>::read(reader); + return db; + } +}; class RemoteUI : public UserInterface @@ -603,7 +628,7 @@ RemoteClient::RemoteClient(StringView session, StringView name, std::unique_ptr< { case MessageType::MenuShow: { - auto choices = reader.read_vector(); + auto choices = reader.read>(); auto anchor = reader.read(); auto fg = reader.read(); auto bg = reader.read(); @@ -657,7 +682,7 @@ RemoteClient::RemoteClient(StringView session, StringView name, std::unique_ptr< m_ui->refresh(reader.read()); break; case MessageType::SetOptions: - m_ui->set_ui_options(reader.read_hash_map()); + m_ui->set_ui_options(reader.read>()); break; case MessageType::Exit: m_exit_status = reader.read(); @@ -723,9 +748,9 @@ private: auto pid = m_reader.read(); auto name = m_reader.read(); auto init_cmds = m_reader.read(); - auto init_coord = m_reader.read_optional(); + auto init_coord = m_reader.read>(); auto dimensions = m_reader.read(); - auto env_vars = m_reader.read_hash_map(); + auto env_vars = m_reader.read>(); auto* ui = new RemoteUI{sock, dimensions}; ClientManager::instance().create_client( std::unique_ptr(ui), pid, std::move(name),