support result<T, Error>

This commit is contained in:
ouczbs 2024-06-17 00:25:00 +08:00
parent 1348dda9eb
commit 1c8b6c1b7c
15 changed files with 172 additions and 58 deletions

View File

@ -0,0 +1,45 @@
#pragma once
#include <utility>
#include <variant>
namespace meta
{
// a struct stolen from rust
// lets us define a result, or return an error otherwise
template<typename Result, typename Error>
class result
: protected std::variant<Result, Error>
{
protected:
using Base = std::variant<Result, Error>;
private:
static constexpr auto Success = 0;
static constexpr auto Failure = 1;
static_assert(std::is_default_constructible_v<Error>, "Error must be default constructible");
public:
using value_type = Result;
using Base::Base;
using Base::operator=;
// accessors
Result& value();
template<typename U, typename = std::enable_if_t<std::is_constructible_v<Result, U>>>
Result value_or(U&& result) const;
Error& error();
const Result& value() const;
const Error& error() const;
// monadic operators
template<class Fn> auto map(Fn&& visitor) const;
template<class Fn> auto and_then(Fn&& visitor) const;
template<class Fn, class ErrFn> auto and_then(Fn&& visitor, ErrFn&& err_visitor) const;
template<class ErrFunc> auto or_else(ErrFunc&& err_visitor) const;
// operator overloads
explicit operator bool() const;
Result& operator*();
Result* operator->();
const Result& operator*() const;
const Result* operator->() const;
};
}

View File

@ -0,0 +1,57 @@
#include "result.h"
#pragma once
namespace meta
{
template<typename Result, typename Error>
inline Result& result<Result, Error>::value()
{
return std::get<Success>(*this);
}
template<typename Result, typename Error>
template<typename U, typename>
Result result<Result, Error>::value_or(U&& result) const
{
return bool(*this) ? **this : static_cast<Result>(std::forward<U>(result));
}
template<typename Result, typename Error>
inline Error& result<Result, Error>::error()
{
return std::get<Failure>(*this);
}
template<typename Result, typename Error>
inline const Result& result<Result, Error>::value() const
{
return std::get<Success>(*this);
}
template<typename Result, typename Error>
inline const Error& result<Result, Error>::error() const
{
return std::get<Failure>(*this);
}
template<typename Result, typename Error>
inline result<Result, Error>::operator bool() const
{
return Base::index() == Success;
}
template<typename Result, typename Error>
inline Result& result<Result, Error>::operator*()
{
return value();
}
template<typename Result, typename Error>
inline Result* result<Result, Error>::operator->()
{
return &operator*();
}
template<typename Result, typename Error>
const Result& result<Result, Error>::operator*() const
{
return value();
}
template<typename Result, typename Error>
const Result* result<Result, Error>::operator->() const
{
return &operator*();
}
}

View File

@ -1,16 +1,28 @@
#pragma once
#include "serialize/binary.inl"
#include "serialize/text.inl"
#include "meta/result.inl"
namespace YAML
{
using meta::result;
enum class SerializeError : char
{
TEXT_EMPTY,
TYPE_ERROR,
};
string Text_Serialize(const Any& any) {
return Dump(TextArchive::Serialize(any));
}
template<typename T>
T Text_Unserialize(const string& text) {
result<T, SerializeError> Text_Unserialize(const string& text) {
if (text.empty()) {
return SerializeError::TEXT_EMPTY;
}
char data[sizeof(T)];
Any any(&data, &TypeInfo<T>::StaticClass);
TextArchive::Unserialize(Load(text), any);
if (!TextArchive::Unserialize(Load(text), any)) {
return SerializeError::TYPE_ERROR;
}
return *any.CastTo<T*>();
}
}

View File

@ -1,5 +1,9 @@
#include "refl/refl.h"
#include <objbase.h>
#include <string>
#include <vector>
using std::string;
using std::vector;
struct Guid
{
using MyMeta = class Guid_Meta;
@ -61,4 +65,19 @@ struct Guid
return guid;
}
};
struct SerializedMeta
{
Guid guid;
string name;
string t_hash{};
string metadata;
};
struct ResourceBundle;
struct MetaBundle
{
vector<SerializedMeta> metadatas;
MetaBundle() = default;
};
#include "guid_gen.inl"

View File

@ -11,8 +11,13 @@ int main() {
string rx = YAML::Text_Serialize(x);
string rg1 = YAML::Text_Serialize(g1);
YAML::Node rg2 = YAML::Load(rg1);
Guid g2 = YAML::Text_Unserialize<Guid>(rg1);
auto res1 = YAML::Text_Unserialize<Guid>(rg1);
Guid g2 = res1.value();
assert(g1 == g2);
auto res2 = YAML::Text_Unserialize<MetaBundle>(rg1);
if (res2) {
MetaBundle aa = res2.value();
}
std::cout << rg1 << std::endl;
YAML::Node primes = YAML::Load("[2, 3, 5, 7, 11]");
for (std::size_t i = 0; i < primes.size(); i++) {

View File

@ -1,12 +1,8 @@
#include <iostream>
#include "zlog.h"
#include "singleton.h"
#include "assetmanager.h"
int main() {
zlog::info("hello info");
zlog::warn("hello {}", "warn");
zlog::error("hello {}", "error");
AssetManager re;
AssetManager::GetSingleton().GetSingleton();
return 0;
}

View File

@ -1 +0,0 @@
#include "assetmanager.h"

View File

@ -1,5 +0,0 @@
#pragma once
#include "singleton.h"
class AssetManager :public ISingleton<AssetManager> {
};

View File

@ -1,20 +0,0 @@
#pragma once
template <typename T>
class Singleton {
protected:
static T* ms_Singleton;
public:
explicit Singleton() {
ms_Singleton = static_cast<T*>(this);
}
~Singleton() {
ms_Singleton = nullptr;
}
static T& GetSingleton(void) {
return *ms_Singleton;
}
static T* GetSingletonPtr(void) {
return ms_Singleton;
}
};

View File

@ -6,9 +6,8 @@ target("zlog")
add_files("src/*.cpp")
add_headerfiles("include/*.h")
target("zlog_test01_file")
set_languages("cxx20")
set_kind("binary")
add_deps("zlog")
add_files("test/*.cpp")
add_headerfiles("test/*.h")
-- target("zlog_test01_file")
-- set_languages("cxx20")
-- set_kind("binary")
-- add_deps("zlog")
-- add_files("test/*.cpp")

View File

@ -1,6 +1,5 @@
#include "resource_manager.inl"
#include "file_manager.h"
#include "yaml/yaml.h"
namespace engineapi {
void ResourceManager::Init()
{
@ -19,7 +18,7 @@ namespace engineapi {
return nullptr;
return itr->second;
}
ResourceBundle ResourceManager::Load(PackagePath path, bool reload_resource)
LoadResult<ResourceBundle> ResourceManager::Load(PackagePath path, bool reload_resource)
{
auto ext = path.GetExtension();
auto* loader = GetLoader(ext);
@ -30,9 +29,7 @@ namespace engineapi {
MetaBundle ResourceManager::GetMeta(PackagePath path)
{
auto bundlestream = FileManager::LoadTextFile(path.AbsolutePath() + ".meta");
auto meta = YAML::Text_Unserialize<MetaBundle>(bundlestream);
return meta;
return {};
}
}

View File

@ -4,14 +4,32 @@
#include "res/resource_bundle.h"
#include "res/package_path.h"
#include "res/meta_bundle.h"
#include "meta/result.inl"
#include <memory>
#include <optional>
namespace engineapi {
using std::array;
using std::shared_ptr;
class IFileLoader;
enum class ResourceLoadError : char
{
ExtensionNotRegistered,
FileDoesNotExist,
FailedToLoadResource,
};
template<typename Res>
using LoadResult = result<Res, ResourceLoadError>;
class ResourceManager : public ISingleton<ResourceManager>
{
public:
template<typename R>
struct ResourceControlBlock;
template<typename R>
using ResourceStorage = hash_table<Guid, ResourceControlBlock<R>>;
using GenericPtr = shared_ptr<void>;
private:
array<GenericPtr, ResourceCount> mResourceTable;
hash_table<Name, IFileLoader*> mFileLoader;
public:
void Init() override;
void Shutdown() override;
@ -26,18 +44,9 @@ namespace engineapi {
FLoader& RegisterLoader(Name ext, Args&& ... args);
template<typename Res>
Res* Load(PackagePath path, bool reload_resource = true);
ResourceBundle Load(PackagePath path, bool reload_resource = true);
LoadResult<Res> Load(PackagePath path, bool reload_resource = true);
LoadResult<ResourceBundle> Load(PackagePath path, bool reload_resource = true);
MetaBundle GetMeta(PackagePath path);
template<typename R>
struct ResourceControlBlock;
template<typename R>
using ResourceStorage = hash_table<Guid, ResourceControlBlock<R>>;
using GenericPtr = shared_ptr<void>;
private:
array<GenericPtr, ResourceCount> mResourceTable;
hash_table<Name, IFileLoader*> mFileLoader;
};
template<typename R>
struct ResourceManager::ResourceControlBlock

View File

@ -42,7 +42,7 @@ namespace engineapi {
return *ptr;
}
template<typename Res>
inline Res* ResourceManager::Load(PackagePath path, bool reload_resource)
inline LoadResult<Res> ResourceManager::Load(PackagePath path, bool reload_resource)
{
auto res = Load(path, reload_resource);
if (!res)

View File

@ -4,6 +4,7 @@
#include "asset/resource_manager.h"
#include "vulkanapi/loader/vulkan_glsl_loader.h"
#include "zlog.h"
#include "yaml/yaml.h"
using namespace engineapi;
int main(int argc, char** argv)
{

View File

@ -9,7 +9,7 @@ target("zengine")
add_rules("c++.codegen",{
files = {"src/engine/render/meta/*.h", "src/engine/asset/res/guid.h"}
})
add_deps("zlib","zlog")
add_deps("zlog","zlib")
add_defines("VULKAN_API")
add_packages("vulkansdk","tinyobjloader","assimp","nlohmann_json")
add_includedirs("src/engine")