#pragma once #include #include #include namespace erebos { using std::optional; using std::shared_ptr; using std::vector; class LocalState { public: LocalState(); explicit LocalState(const Ref &); static LocalState load(const Ref & ref) { return LocalState(ref); } Ref store(const Storage &) const; static const UUID headTypeId; const optional & identity() const; LocalState identity(const Identity &) const; template optional shared() const; template LocalState shared(const vector> &) const; template LocalState shared(const Stored & x) const { return shared({ x }); }; template LocalState shared(const Storage & st, const T & x) { return updateShared(T::sharedTypeId, x.store(st)); } vector sharedRefs() const; LocalState sharedRefAdd(const Ref &) const; template static T lens(const LocalState &); private: vector lookupShared(UUID) const; LocalState updateShared(UUID, const vector &) const; struct Priv; std::shared_ptr p; }; class SharedState { public: template optional get() const; template static T lens(const SharedState &); bool operator==(const SharedState &) const; bool operator!=(const SharedState &) const; private: vector lookup(UUID) const; struct Priv; SharedState(shared_ptr && p): p(std::move(p)) {} shared_ptr p; friend class LocalState; }; template optional LocalState::shared() const { return T::load(lookupShared(T::sharedTypeId)); } template LocalState LocalState::shared(const vector> & v) const { vector refs; for (const auto & x : v) refs.push_back(x.ref()); return updateShared(T::sharedTypeId, refs); } template optional SharedState::get() const { return T::load(lookup(T::sharedTypeId)); } template T SharedState::lens(const SharedState & x) { return T::value_type::load(x.lookup(T::value_type::sharedTypeId)); } }