summaryrefslogtreecommitdiff
path: root/src/state.cpp
blob: 8790dfc158bbddc25ccf076baa30c8d672e3b693 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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)));
}