#pragma once #include #include #include #include #include #include #include namespace erebos { class Storage; class Digest; class Ref; class Object; class Storage { public: Storage(const Storage &) = default; Storage & operator=(const Storage &) = delete; static std::optional open(std::filesystem::path path); std::optional ref(const Digest &) const; std::optional load(const Digest &) const; Ref store(const Object &) const; private: friend class Ref; struct Priv; const std::shared_ptr p; Storage(const std::shared_ptr p): p(p) {} }; class Digest { public: static constexpr size_t size = 32; Digest(const Digest &) = default; Digest & operator=(const Digest &) = delete; explicit Digest(std::array value): value(value) {} explicit Digest(const std::string &); explicit operator std::string() const; 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; } 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; } private: std::array value; }; class Ref { public: Ref(const Ref &) = default; Ref & operator=(const Ref &) = delete; static std::optional create(Storage, const Digest &); const Digest & digest() const; const Object & operator*() const; const Object * operator->() const; private: friend class Storage; struct Priv; const std::shared_ptr p; Ref(const std::shared_ptr p): p(p) {} }; class Record { public: class Item { public: typedef std::variant< int, std::string, std::vector, Ref> Variant; Item(const std::string & name, Variant value): name(name), value(value) {} Item(const Item &) = default; Item & operator=(const Item &) = delete; std::optional asInteger() const; std::optional asText() const; std::optional> asBinary() const; std::optional asRef() const; private: friend class Record; std::string name; Variant value; }; private: Record(const std::shared_ptr> & ptr): ptr(ptr) {} public: Record(const std::vector &); 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; std::vector items(const std::string & name) const; private: friend class Object; std::vector encodeInner() const; static Record decode(Storage, std::vector::const_iterator, std::vector::const_iterator); const std::shared_ptr> ptr; }; class Blob { public: Blob(const std::vector &); const std::vector & data() const { return *ptr; } std::vector encode() const; private: friend class Object; std::vector encodeInner() const; static Blob decode(Storage, std::vector::const_iterator, std::vector::const_iterator); Blob(std::shared_ptr> ptr): ptr(ptr) {} const std::shared_ptr> ptr; }; class Object { public: typedef std::variant< Record, Blob> Variants; Object(const Object &) = default; Object(Variants content): content(content) {} Object & operator=(const Object &) = delete; static std::optional decode(Storage, const std::vector &); std::vector encode() const; std::optional asRecord() const; std::optional asBlob() const; private: friend class Record; friend class Blob; Variants content; }; }