summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2020-07-22 22:13:33 +0200
committerRoman Smrž <roman.smrz@seznam.cz>2020-07-22 22:40:34 +0200
commit90021e1d335efac1017562c1d5dee43e99580319 (patch)
tree2a6c70ab6664085f5a86f210ac63cb064c9cb5c8 /src
parent8ac21c24e49bc3702c55d1c796f969f1d1f6128b (diff)
Local and shared state
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/identity.cpp11
-rw-r--r--src/state.cpp127
-rw-r--r--src/state.h32
4 files changed, 171 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 64c14b5..b97293c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -9,6 +9,7 @@ add_library(erebos
network
pubkey
service
+ state
storage
time
uuid
diff --git a/src/identity.cpp b/src/identity.cpp
index 2396b9f..7364a8b 100644
--- a/src/identity.cpp
+++ b/src/identity.cpp
@@ -11,6 +11,8 @@ using std::nullopt;
using std::runtime_error;
using std::set;
+const UUID Identity::sharedTypeId { "0c6c1fe0-f2d7-4891-926b-c332449f7871" };
+
Identity::Identity(const Priv * p): p(p) {}
Identity::Identity(shared_ptr<const Priv> && p): p(std::move(p)) {}
@@ -32,6 +34,15 @@ optional<Identity> Identity::load(const vector<Ref> & refs)
return nullopt;
}
+vector<Ref> Identity::store(const Storage & st) const
+{
+ vector<Ref> res;
+ res.reserve(p->data.size());
+ for (const auto & x : p->data)
+ res.push_back(x.store(st));
+ return res;
+}
+
optional<string> Identity::name() const
{
return p->name.get();
diff --git a/src/state.cpp b/src/state.cpp
new file mode 100644
index 0000000..8790dfc
--- /dev/null
+++ b/src/state.cpp
@@ -0,0 +1,127 @@
+#include "state.h"
+
+#include "identity.h"
+
+using namespace erebos;
+
+using std::make_shared;
+
+const UUID LocalState::headTypeId { "1d7491a9-7bcb-4eaa-8f13-c8c4c4087e4e" };
+
+LocalState::LocalState():
+ p(make_shared<Priv>())
+{}
+
+LocalState::LocalState(const Ref & ref):
+ LocalState()
+{
+ auto rec = ref->asRecord();
+ if (!rec)
+ return;
+
+ if (auto x = rec->item("id").asRef())
+ p->identity = Identity::load(*x);
+
+ for (auto i : rec->items("shared"))
+ if (const auto & x = i.as<SharedState>())
+ p->shared.push_back(*x);
+}
+
+Ref LocalState::store(const Storage & st) const
+{
+ vector<Record::Item> items;
+
+ if (p->identity)
+ items.emplace_back("id", *p->identity->ref());
+ for (const auto & x : p->shared)
+ items.emplace_back("shared", x);
+
+ return st.storeObject(Record(std::move(items)));
+}
+
+const optional<Identity> & LocalState::identity() const
+{
+ return p->identity;
+}
+
+LocalState LocalState::identity(const Identity & id) const
+{
+ LocalState ret;
+ ret.p->identity = id;
+ ret.p->shared = p->shared;
+ return ret;
+}
+
+vector<Ref> LocalState::lookupShared(UUID type) const
+{
+ vector<Stored<SharedState>> found;
+ vector<Stored<SharedState>> process = p->shared;
+
+ while (!process.empty()) {
+ auto cur = std::move(process.back());
+ process.pop_back();
+
+ if (cur->type == type) {
+ found.push_back(std::move(cur));
+ continue;
+ }
+
+ for (const auto & x : cur->prev)
+ process.push_back(x);
+ }
+
+ filterAncestors(found);
+ vector<Ref> res;
+ for (const auto & s : found)
+ for (const auto & v : s->value)
+ res.push_back(v);
+ return res;
+}
+
+LocalState LocalState::updateShared(UUID type, const vector<Ref> & xs) const
+{
+ const Storage * st;
+ if (xs.size() > 0)
+ st = &xs[0].storage();
+ else if (p->shared.size() > 0)
+ st = &p->shared[0].ref().storage();
+ else
+ return *this;
+
+ LocalState ret;
+ ret.p->identity = p->identity;
+ ret.p->shared.push_back(SharedState(p->shared, type, xs).store(*st));
+ return ret;
+}
+
+
+SharedState::SharedState(const Ref & ref)
+{
+ auto rec = ref->asRecord();
+ if (!rec)
+ return;
+
+ for (auto i : rec->items("PREV"))
+ if (const auto & x = i.as<SharedState>())
+ prev.push_back(*x);
+
+ if (auto x = rec->item("type").asUUID())
+ type = *x;
+
+ for (auto i : rec->items("value"))
+ if (const auto & x = i.asRef())
+ value.push_back(*x);
+}
+
+Ref SharedState::store(const Storage & st) const
+{
+ vector<Record::Item> items;
+
+ for (const auto & x : prev)
+ items.emplace_back("PREV", x);
+ items.emplace_back("type", type);
+ for (const auto & x : value)
+ items.emplace_back("value", x);
+
+ return st.storeObject(Record(std::move(items)));
+}
diff --git a/src/state.h b/src/state.h
new file mode 100644
index 0000000..d2c89fc
--- /dev/null
+++ b/src/state.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <erebos/state.h>
+
+#include "pubkey.h"
+
+using std::optional;
+using std::vector;
+
+namespace erebos {
+
+struct LocalState::Priv
+{
+ optional<Identity> identity;
+ vector<Stored<struct SharedState>> shared;
+};
+
+struct SharedState
+{
+ explicit SharedState(vector<Stored<SharedState>> prev,
+ UUID type, vector<Ref> value):
+ prev(prev), type(type), value(value) {}
+ explicit SharedState(const Ref &);
+ static SharedState load(const Ref & ref) { return SharedState(ref); }
+ Ref store(const Storage &) const;
+
+ vector<Stored<SharedState>> prev;
+ UUID type;
+ vector<Ref> value;
+};
+
+}