Skip to content

Commit

Permalink
OrcLib: add Orc::Result based on Rust's Result type
Browse files Browse the repository at this point in the history
  • Loading branch information
jgautier-anssi authored and fabienfl-orc committed Jul 31, 2020
1 parent 11bdcb8 commit d317f08
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/OrcLib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ set(SRC_UTILITIES
"LogFileWriter.h"
"OrcException.cpp"
"OrcException.h"
"OrcResult.h"
)

source_group(Utilities FILES ${SRC_UTILITIES})
Expand Down
115 changes: 115 additions & 0 deletions src/OrcLib/OrcResult.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//
// SPDX-License-Identifier: LGPL-2.1-or-later
//
// Copyright © 2011-2019 ANSSI. All Rights Reserved.
//
// Author(s): Jean Gautier (ANSSI)
//
#pragma once

#include "OrcLib.h"

#include "OrcException.h"

#include <optional>
#include <variant>
#include <filesystem>

namespace Orc {

template <typename _ResultT, typename _ErrorT = HRESULT> class Result
{
public:
Result() = default;
Result(const _ResultT& result)
: m_result(result)
{
}
Result(_ResultT&& result) noexcept
: m_result(std::move(result))
{
}
Result(const _ErrorT& err)
: m_result(err)
{
}
Result(_ErrorT&& err) noexcept
: m_result(std::move(err))
{
}

bool is_ok() const {
return std::holds_alternative<_ResultT>(m_result);
}
bool is_err() const { return !std::holds_alternative<_ResultT>(m_result);
}

_ResultT unwrap()
{
return std::visit([](auto&& arg) -> _ResultT {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, _ResultT>)
return std::move(arg);
else if constexpr (std::is_same_v<T, HRESULT>)
throw Orc::Exception(ExceptionSeverity::Continue, arg, L"unwrap called with error result");
else if constexpr (std::is_same_v<T, _ErrorT>)
throw Orc::Exception(ExceptionSeverity::Continue, E_FAIL, L"unwrap called with error result");
else if constexpr (std::is_same_v<T, std::monostate>)
throw Orc::Exception(ExceptionSeverity::Continue, E_FAIL, L"unwrap called with invalid result state");
else
throw Orc::Exception(
ExceptionSeverity::Fatal, E_FAIL, L"unwrap called with state");

},
m_result);
}
_ResultT unwrap_or(_ResultT or_value)
{
std::visit(
[](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, _T>)
return std::move(arg);
else
return std::move(or_value);
},
m_result);
}
_ResultT unwrap_or_default()
{
std::visit(
[](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, _T>)
return std::move(arg);
else
return _ResultT();
},
m_result);
}

_ErrorT err()
{
return std::visit(
[](auto&& arg) -> _ErrorT {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, _ErrorT>)
return std::move(arg);
else
throw Orc::Exception(ExceptionSeverity::Fatal, E_FAIL, L"err() called with successful result");
},
m_result);
}

private:

std::variant<std::monostate, _ResultT, _ErrorT> m_result;

};

using StringResult = Result<std::wstring>;
using PathResult = Result<std::filesystem::path>;

}

#pragma managed(push, off)

0 comments on commit d317f08

Please sign in to comment.