diff options
author | Roman Smrž <roman.smrz@seznam.cz> | 2019-12-11 22:14:12 +0100 |
---|---|---|
committer | Roman Smrž <roman.smrz@seznam.cz> | 2019-12-18 22:26:28 +0100 |
commit | d084c069be38b6f3ad74912ca629403d9fdaec58 (patch) | |
tree | 957e9e2340b291cdff6dac60480d1f4060c106a3 /include/erebos/storage.h | |
parent | 361891f25ca735fd85db64a14823cc55b8a0619a (diff) |
Identity loading and validation
Diffstat (limited to 'include/erebos/storage.h')
-rw-r--r-- | include/erebos/storage.h | 98 |
1 files changed, 96 insertions, 2 deletions
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<typename T> class Stored; class Storage { @@ -45,6 +46,8 @@ public: explicit Digest(const std::string &); explicit operator std::string() const; + const std::array<uint8_t, size> & 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<uint8_t>, 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<int> asInteger() const; std::optional<std::string> asText() const; std::optional<std::vector<uint8_t>> asBinary() const; std::optional<Ref> asRef() const; + template<typename T> std::optional<Stored<T>> as() const; + private: friend class Record; std::string name; @@ -111,8 +121,8 @@ public: std::vector<uint8_t> encode() const; const std::vector<Item> & items() const; - std::optional<Item> item(const std::string & name) const; - std::optional<Item> operator[](const std::string & name) const; + Item item(const std::string & name) const; + Item operator[](const std::string & name) const; std::vector<Item> items(const std::string & name) const; private: @@ -158,6 +168,7 @@ public: static std::optional<Object> decode(Storage, const std::vector<uint8_t> &); std::vector<uint8_t> encode() const; + static std::optional<Object> load(const Ref &); std::optional<Record> asRecord() const; std::optional<Blob> asBlob() const; @@ -169,4 +180,87 @@ private: Variants content; }; +template<typename T> +std::optional<Stored<T>> Record::Item::as() const +{ + if (auto ref = asRef()) + return Stored<T>::load(ref.value()); + return std::nullopt; +} + +template<typename T> +class Stored +{ + Stored(Ref ref, std::shared_ptr<T> val): ref(ref), val(val) {} +public: + static std::optional<Stored<T>> load(const Ref &); + + bool operator==(const Stored<T> & other) const + { return ref.digest() == other.ref.digest(); } + bool operator!=(const Stored<T> & other) const + { return ref.digest() != other.ref.digest(); } + bool operator<(const Stored<T> & other) const + { return ref.digest() < other.ref.digest(); } + bool operator<=(const Stored<T> & other) const + { return ref.digest() <= other.ref.digest(); } + bool operator>(const Stored<T> & other) const + { return ref.digest() > other.ref.digest(); } + bool operator>=(const Stored<T> & other) const + { return ref.digest() >= other.ref.digest(); } + + const T & operator*() const { return *val; } + const T * operator->() const { return val.get(); } + + std::vector<Stored<T>> previous() const; + bool precedes(const Stored<T> &) const; + + const Ref ref; + const std::shared_ptr<T> val; +}; + +template<typename T> +std::optional<Stored<T>> Stored<T>::load(const Ref & ref) +{ + if (auto val = T::load(ref)) + return Stored(ref, std::make_shared<T>(val.value())); + return std::nullopt; +} + +template<typename T> +std::vector<Stored<T>> Stored<T>::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<Stored<T>> res; + for (const auto & i : drec->items("SPREV")) + if (auto x = i.as<T>()) + res.push_back(*x); + return res; + } + + std::vector<Stored<T>> res; + for (auto & i : rec->items("PREV")) + if (auto x = i.as<T>()) + res.push_back(*x); + return res; +} + +template<typename T> +bool Stored<T>::precedes(const Stored<T> & other) const +{ + for (const auto & x : other.previous()) { + if (*this == x || precedes(x)) + return true; + } + return false; +} + } |