From 567156b05183cc63aedbf57c03f26e0eaf43a39e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Smr=C5=BE?= Date: Tue, 27 Apr 2021 22:59:52 +0200 Subject: SharedState type and lens --- include/erebos/state.h | 31 ++++++++++++++++++++++++++ src/state.cpp | 59 ++++++++++++++++++++++++++++++++++++-------------- src/state.h | 20 ++++++++++++----- 3 files changed, 88 insertions(+), 22 deletions(-) diff --git a/include/erebos/state.h b/include/erebos/state.h index 7060f22..cfa9532 100644 --- a/include/erebos/state.h +++ b/include/erebos/state.h @@ -8,6 +8,7 @@ namespace erebos { using std::optional; +using std::shared_ptr; using std::vector; class LocalState @@ -42,6 +43,24 @@ private: 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 { @@ -57,4 +76,16 @@ LocalState LocalState::shared(const vector> & v) const 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)); +} + } diff --git a/src/state.cpp b/src/state.cpp index 1a3381a..82fe907 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -23,8 +23,8 @@ LocalState::LocalState(const Ref & ref): p->identity = Identity::load(*x); for (auto i : rec->items("shared")) - if (const auto & x = i.as()) - p->shared.push_back(*x); + if (const auto & x = i.as()) + p->shared.tip.push_back(*x); } Ref LocalState::store(const Storage & st) const @@ -33,7 +33,7 @@ Ref LocalState::store(const Storage & st) const if (p->identity) items.emplace_back("id", *p->identity->ref()); - for (const auto & x : p->shared) + for (const auto & x : p->shared.tip) items.emplace_back("shared", x); return st.storeObject(Record(std::move(items))); @@ -54,8 +54,18 @@ LocalState LocalState::identity(const Identity & id) const vector LocalState::lookupShared(UUID type) const { - vector> found; - vector> process = p->shared; + return p->shared.lookup(type); +} + +vector SharedState::lookup(UUID type) const +{ + return p->lookup(type); +} + +vector SharedState::Priv::lookup(UUID type) const +{ + vector> found; + vector> process = tip; while (!process.empty()) { auto cur = std::move(process.back()); @@ -81,7 +91,7 @@ vector LocalState::lookupShared(UUID type) const vector LocalState::sharedRefs() const { vector refs; - for (const auto & x : p->shared) + for (const auto & x : p->shared.tip) refs.push_back(x.ref()); return refs; } @@ -89,8 +99,8 @@ vector LocalState::sharedRefs() const LocalState LocalState::sharedRefAdd(const Ref & ref) const { const Storage * st; - if (p->shared.size() > 0) - st = &p->shared[0].ref().storage(); + if (p->shared.tip.size() > 0) + st = &p->shared.tip[0].ref().storage(); else if (p->identity) st = &p->identity->ref()->storage(); else @@ -99,16 +109,16 @@ LocalState LocalState::sharedRefAdd(const Ref & ref) const LocalState ret; ret.p->identity = p->identity; ret.p->shared = p->shared; - ret.p->shared.push_back(SharedState(ref).store(*st)); - filterAncestors(ret.p->shared); + ret.p->shared.tip.push_back(SharedData(ref).store(*st)); + filterAncestors(ret.p->shared.tip); return ret; } LocalState LocalState::updateShared(UUID type, const vector & xs) const { const Storage * st; - if (p->shared.size() > 0) - st = &p->shared[0].ref().storage(); + if (p->shared.tip.size() > 0) + st = &p->shared.tip[0].ref().storage(); else if (p->identity) st = &p->identity->ref()->storage(); else if (xs.size() > 0) @@ -118,19 +128,30 @@ LocalState LocalState::updateShared(UUID type, const vector & xs) const LocalState ret; ret.p->identity = p->identity; - ret.p->shared.push_back(SharedState(p->shared, type, xs).store(*st)); + ret.p->shared.tip.push_back(SharedData(p->shared.tip, type, xs).store(*st)); return ret; } -SharedState::SharedState(const Ref & ref) +bool SharedState::operator==(const SharedState & other) const +{ + return p->tip == other.p->tip; +} + +bool SharedState::operator!=(const SharedState & other) const +{ + return p->tip != other.p->tip; +} + + +SharedData::SharedData(const Ref & ref) { auto rec = ref->asRecord(); if (!rec) return; for (auto i : rec->items("PREV")) - if (const auto & x = i.as()) + if (const auto & x = i.as()) prev.push_back(*x); if (auto x = rec->item("type").asUUID()) @@ -141,7 +162,7 @@ SharedState::SharedState(const Ref & ref) value.push_back(*x); } -Ref SharedState::store(const Storage & st) const +Ref SharedData::store(const Storage & st) const { vector items; @@ -165,3 +186,9 @@ vector LocalState::lens>(const LocalState & x) { return x.sharedRefs(); } + +template<> +SharedState LocalState::lens(const LocalState & x) +{ + return SharedState(shared_ptr(x.p, &x.p->shared)); +} diff --git a/src/state.h b/src/state.h index d2c89fc..91dea94 100644 --- a/src/state.h +++ b/src/state.h @@ -5,26 +5,34 @@ #include "pubkey.h" using std::optional; +using std::shared_ptr; using std::vector; namespace erebos { +struct SharedState::Priv +{ + vector lookup(UUID) const; + + vector> tip; +}; + struct LocalState::Priv { optional identity; - vector> shared; + SharedState::Priv shared; }; -struct SharedState +struct SharedData { - explicit SharedState(vector> prev, + explicit SharedData(vector> prev, UUID type, vector value): prev(prev), type(type), value(value) {} - explicit SharedState(const Ref &); - static SharedState load(const Ref & ref) { return SharedState(ref); } + explicit SharedData(const Ref &); + static SharedData load(const Ref & ref) { return SharedData(ref); } Ref store(const Storage &) const; - vector> prev; + vector> prev; UUID type; vector value; }; -- cgit v1.2.3