Files
UnrealEngineUWP/Engine/Source/Programs/Unsync/Private/UnsyncError.h
Yuriy ODonnell b5709042fb Import Unsync into the main source tree
This is a binary patching and incremental downloading tool, similar to rsync or zsync. It aims to improve the large binary download processes that previously were served by robocopy (i.e. full packages produced by the build farm).

The original code can be found in `//depot/usr/yuriy.odonnell/unsync`. This commit is a branch from the original location to preserve history.

While the codebase is designed to be self-contained and does not depend on any engine libraries, it mostly follows the UE coding guidelines and can be built with UBT.

Currently only Windows is supported, however the tool is expected to also work on Mac and Linux in the future.

#rb Martin.Ridgers
#preflight skip

[CL 18993571 by Yuriy ODonnell in ue5-main branch]
2022-02-15 04:30:27 -05:00

139 lines
2.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "UnsyncCommon.h"
#include "UnsyncLog.h"
#include <string>
#include <type_traits>
#include <variant>
namespace unsync {
enum class EErrorKind
{
Unknown,
App,
System,
Http,
};
struct FError
{
int32 Code = 0;
EErrorKind Kind = EErrorKind::Unknown;
std::wstring Context;
// TODO: add support for chained errors for rich error context reporting
};
inline FError
SystemError(std::wstring&& Context, int32 Code = -1)
{
return FError{.Code = Code, .Kind = EErrorKind::System, .Context = Context};
}
inline FError
AppError(std::wstring&& Context, int32 Code = -1)
{
return FError{.Code = Code, .Kind = EErrorKind::App, .Context = Context};
}
inline FError
AppError(std::string&& Context, int32 Code = -1)
{
extern std::wstring ConvertUtf8ToWide(std::string_view StringUtf8);
return FError{.Code = Code, .Kind = EErrorKind::App, .Context = ConvertUtf8ToWide(Context)};
}
inline FError
HttpError(std::wstring&& Context, int32 Code)
{
return FError{.Code = Code, .Kind = EErrorKind::Http, .Context = Context};
}
inline FError
HttpError(int32 Code)
{
return FError{.Code = Code, .Kind = EErrorKind::Http};
}
struct FEmpty
{
};
template<typename T = FEmpty, typename Et = FError>
struct [[nodiscard]] TResult
{
// Implicit construction from Error type for convenience
TResult(Et&& E) : DataOrError(std::forward<Et>(E)) {}
explicit TResult(T&& Ok) : DataOrError(std::forward<T>(Ok)) {}
bool IsOk() const { return std::holds_alternative<T>(DataOrError); }
bool IsError() const { return std::holds_alternative<Et>(DataOrError); }
const T* TryData() const { return std::get_if<T>(&DataOrError); }
const Et* TryError() const { return std::get_if<Et>(&DataOrError); }
T* TryData() { return std::get_if<T>(&DataOrError); }
Et* TryError() { return std::get_if<Et>(&DataOrError); }
const T& GetData() const
{
UNSYNC_ASSERT(IsOk());
return *TryData();
}
const Et& GetError() const
{
UNSYNC_ASSERT(IsError());
return *TryError();
}
T& GetData()
{
UNSYNC_ASSERT(IsOk());
return *TryData();
}
Et& GetError()
{
UNSYNC_ASSERT(IsError());
return *TryError();
}
const T* operator->() const
{
UNSYNC_ASSERT(IsOk());
return TryData();
}
const T& operator*() const
{
UNSYNC_ASSERT(IsOk());
return *TryData();
}
private:
std::variant<T, Et> DataOrError;
};
template<typename Tx, typename E = FError>
static TResult<Tx, E>
ResultOk(Tx Ok)
{
return TResult<Tx, E>(std::forward<Tx>(Ok));
}
template<typename E = FError>
static TResult<FEmpty, E>
ResultOk()
{
return TResult<FEmpty, E>(FEmpty());
}
} // namespace unsync