.. _program_listing_file_eshet_data.hpp: Program Listing for File data.hpp ================================= |exhale_lsh| :ref:`Return to documentation for file ` (``eshet/data.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #pragma once #include "actorpp/actor.hpp" #include "eshet/msgpack_to_string.hpp" #include "msgpack.hpp" #include #include namespace eshet { using namespace actorpp; using Time = std::chrono::duration; template msgpack::object_handle oh_with_zone(const T &value) { std::unique_ptr z = std::make_unique(); return msgpack::object_handle(msgpack::object(value, *z), std::move(z)); } template struct HasMsgpackObject { msgpack::object_handle value; explicit HasMsgpackObject(msgpack::object_handle value) : value(std::move(value)) {} explicit HasMsgpackObject() {} template explicit HasMsgpackObject(T t) { value.set(msgpack::object(std::move(t))); } template T as() const { T v; value.get().convert(v); return v; } template void convert(T &v) const { value.get().convert(v); } template void convert(std::tuple v) const { value.get().convert(v); } bool operator==(const HasMsgpackObject &other) const { return value.get() == other.value.get(); } bool operator!=(const HasMsgpackObject &other) const { return !(*this == other); } }; struct Success : public HasMsgpackObject { using HasMsgpackObject::HasMsgpackObject; static constexpr const char *name = "Success"; }; // Error is usable as an exception, so needs to be copyable struct Error : public HasMsgpackObject, public std::exception { using HasMsgpackObject::HasMsgpackObject; static constexpr const char *name = "Error"; Error(const Error &other) : HasMsgpackObject(msgpack::clone(other.value.get())) {} Error(Error &&) = default; Error &operator=(Error &&) = default; const char *what() const throw() { if (!error_str.size()) { error_str += "Error("; append_msgpack(error_str, value.get()); error_str += ")"; } return error_str.c_str(); } private: mutable std::string error_str; }; using Result = std::variant; struct Known : public HasMsgpackObject { explicit Known() : HasMsgpackObject(), t_since_change(0) {} template explicit Known(T &&v, Time t = Time{0}) : HasMsgpackObject(std::forward(v)), t_since_change(t) {} static constexpr const char *name = "Known"; Time t_since_change; }; struct Unknown { explicit Unknown(Time t = Time{0}) : t_since_change(t) {} bool operator==(const Unknown &other) const { return true; } bool operator!=(const Unknown &other) const { return !(*this == other); } Time t_since_change; }; using StateResult = std::variant; using StateUpdate = std::variant; using AnyResult = std::variant; struct Call : public HasMsgpackObject { static constexpr const char *name = "Call"; uint16_t connection_id; uint16_t id; explicit Call(uint16_t connection_id, uint16_t id, msgpack::object_handle args, Channel> reply_chan) : HasMsgpackObject(std::move(args)), connection_id(connection_id), id(id), reply_chan(reply_chan) {} void reply(Result r) { reply_chan.emplace(connection_id, id, std::move(r)); } Channel> reply_chan; }; // make these printable template std::ostream &operator<<(std::ostream &stream, const HasMsgpackObject &value) { return stream << Base::name << "(" << value.value.get() << ")"; } std::ostream &operator<<(std::ostream &stream, const Unknown &unknown) { return stream << "unknown"; } template ::value || std::is_same::value || std::is_same::value || std::is_same::value>> std::ostream &operator<<(std::ostream &stream, const T &result) { std::visit([&](const auto &v) { stream << v; }, result); return stream; } struct Disconnected : public std::exception { const char *what() const throw() { return "Disconnected"; } }; struct ProtocolError : public std::exception { const char *what() const throw() { return "ProtocolError"; } }; } // namespace eshet