From d084c069be38b6f3ad74912ca629403d9fdaec58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Smr=C5=BE?= Date: Wed, 11 Dec 2019 22:14:12 +0100 Subject: Identity loading and validation --- include/erebos/identity.h | 23 +++++++++++ include/erebos/storage.h | 98 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 include/erebos/identity.h (limited to 'include/erebos') diff --git a/include/erebos/identity.h b/include/erebos/identity.h new file mode 100644 index 0000000..7b66d82 --- /dev/null +++ b/include/erebos/identity.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +namespace erebos { + +class Identity +{ +public: + static std::optional load(const Ref &); + static std::optional load(const std::vector &); + + std::optional name() const; + std::optional owner() const; + +private: + struct Priv; + const std::shared_ptr p; + Identity(const Priv * p): p(p) {} + Identity(std::shared_ptr && p): p(std::move(p)) {} +}; + +} diff --git a/include/erebos/storage.h b/include/erebos/storage.h index ae899f5..ea0e894 100644 --- a/include/erebos/storage.h +++ b/include/erebos/storage.h @@ -14,6 +14,7 @@ class Storage; class Digest; class Ref; class Object; +template class Stored; class Storage { @@ -45,6 +46,8 @@ public: explicit Digest(const std::string &); explicit operator std::string() const; + const std::array & arr() const { return value; } + bool operator==(const Digest & other) const { return value == other.value; } bool operator!=(const Digest & other) const { return value != other.value; } bool operator<(const Digest & other) const { return value < other.value; } @@ -81,21 +84,28 @@ public: class Item { public: typedef std::variant< + std::monostate, int, std::string, std::vector, Ref> Variant; + Item(const std::string & name): + Item(name, std::monostate()) {} Item(const std::string & name, Variant value): name(name), value(value) {} Item(const Item &) = default; Item & operator=(const Item &) = delete; + operator bool() const; + std::optional asInteger() const; std::optional asText() const; std::optional> asBinary() const; std::optional asRef() const; + template std::optional> as() const; + private: friend class Record; std::string name; @@ -111,8 +121,8 @@ public: std::vector encode() const; const std::vector & items() const; - std::optional item(const std::string & name) const; - std::optional operator[](const std::string & name) const; + Item item(const std::string & name) const; + Item operator[](const std::string & name) const; std::vector items(const std::string & name) const; private: @@ -158,6 +168,7 @@ public: static std::optional decode(Storage, const std::vector &); std::vector encode() const; + static std::optional load(const Ref &); std::optional asRecord() const; std::optional asBlob() const; @@ -169,4 +180,87 @@ private: Variants content; }; +template +std::optional> Record::Item::as() const +{ + if (auto ref = asRef()) + return Stored::load(ref.value()); + return std::nullopt; +} + +template +class Stored +{ + Stored(Ref ref, std::shared_ptr val): ref(ref), val(val) {} +public: + static std::optional> load(const Ref &); + + bool operator==(const Stored & other) const + { return ref.digest() == other.ref.digest(); } + bool operator!=(const Stored & other) const + { return ref.digest() != other.ref.digest(); } + bool operator<(const Stored & other) const + { return ref.digest() < other.ref.digest(); } + bool operator<=(const Stored & other) const + { return ref.digest() <= other.ref.digest(); } + bool operator>(const Stored & other) const + { return ref.digest() > other.ref.digest(); } + bool operator>=(const Stored & other) const + { return ref.digest() >= other.ref.digest(); } + + const T & operator*() const { return *val; } + const T * operator->() const { return val.get(); } + + std::vector> previous() const; + bool precedes(const Stored &) const; + + const Ref ref; + const std::shared_ptr val; +}; + +template +std::optional> Stored::load(const Ref & ref) +{ + if (auto val = T::load(ref)) + return Stored(ref, std::make_shared(val.value())); + return std::nullopt; +} + +template +std::vector> Stored::previous() const +{ + auto rec = ref->asRecord(); + if (!rec) + return {}; + + auto sdata = rec->item("SDATA").asRef(); + if (sdata) { + auto drec = sdata.value()->asRecord(); + if (!drec) + return {}; + + std::vector> res; + for (const auto & i : drec->items("SPREV")) + if (auto x = i.as()) + res.push_back(*x); + return res; + } + + std::vector> res; + for (auto & i : rec->items("PREV")) + if (auto x = i.as()) + res.push_back(*x); + return res; +} + +template +bool Stored::precedes(const Stored & other) const +{ + for (const auto & x : other.previous()) { + if (*this == x || precedes(x)) + return true; + } + return false; +} + } -- cgit v1.2.3