diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 14a21b867..5162dea9b 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -73,6 +73,7 @@ add_library(citra_common STATIC dynamic_library/ffmpeg.h error.cpp error.h + expected.h file_util.cpp file_util.h hash.h diff --git a/src/common/expected.h b/src/common/expected.h new file mode 100644 index 000000000..c8d8579c1 --- /dev/null +++ b/src/common/expected.h @@ -0,0 +1,987 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +// This is based on the proposed implementation of std::expected (P0323) +// https://github.com/TartanLlama/expected/blob/master/include/tl/expected.hpp + +#pragma once + +#include +#include + +namespace Common { + +template +class Expected; + +template +class Unexpected { +public: + Unexpected() = delete; + + constexpr explicit Unexpected(const E& e) : m_val{e} {} + + constexpr explicit Unexpected(E&& e) : m_val{std::move(e)} {} + + constexpr E& value() & { + return m_val; + } + + constexpr const E& value() const& { + return m_val; + } + + constexpr E&& value() && { + return std::move(m_val); + } + + constexpr const E&& value() const&& { + return std::move(m_val); + } + +private: + E m_val; +}; + +template +constexpr auto operator<=>(const Unexpected& lhs, const Unexpected& rhs) { + return lhs.value() <=> rhs.value(); +} + +struct unexpect_t { + constexpr explicit unexpect_t() = default; +}; + +namespace detail { + +struct no_init_t { + constexpr explicit no_init_t() = default; +}; + +/** + * This specialization is for when T is not trivially destructible, + * so the destructor must be called on destruction of `expected' + * Additionally, this requires E to be trivially destructible + */ +template > +requires std::is_trivially_destructible_v +struct expected_storage_base { + constexpr expected_storage_base() : m_val{T{}}, m_has_val{true} {} + + constexpr expected_storage_base(no_init_t) : m_has_val{false} {} + + template >* = nullptr> + constexpr expected_storage_base(std::in_place_t, Args&&... args) + : m_val{std::forward(args)...}, m_has_val{true} {} + + template &, Args&&...>>* = + nullptr> + constexpr expected_storage_base(std::in_place_t, std::initializer_list il, Args&&... args) + : m_val{il, std::forward(args)...}, m_has_val{true} {} + + template >* = nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args&&... args) + : m_unexpect{std::forward(args)...}, m_has_val{false} {} + + template &, Args&&...>>* = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, + Args&&... args) + : m_unexpect{il, std::forward(args)...}, m_has_val{false} {} + + ~expected_storage_base() { + if (m_has_val) { + m_val.~T(); + } + } + + union { + T m_val; + Unexpected m_unexpect; + }; + + bool m_has_val; +}; + +/** + * This specialization is for when T is trivially destructible, + * so the destructor of `expected` can be trivial + * Additionally, this requires E to be trivially destructible + */ +template +requires std::is_trivially_destructible_v +struct expected_storage_base { + constexpr expected_storage_base() : m_val{T{}}, m_has_val{true} {} + + constexpr expected_storage_base(no_init_t) : m_has_val{false} {} + + template >* = nullptr> + constexpr expected_storage_base(std::in_place_t, Args&&... args) + : m_val{std::forward(args)...}, m_has_val{true} {} + + template &, Args&&...>>* = + nullptr> + constexpr expected_storage_base(std::in_place_t, std::initializer_list il, Args&&... args) + : m_val{il, std::forward(args)...}, m_has_val{true} {} + + template >* = nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args&&... args) + : m_unexpect{std::forward(args)...}, m_has_val{false} {} + + template &, Args&&...>>* = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, + Args&&... args) + : m_unexpect{il, std::forward(args)...}, m_has_val{false} {} + + ~expected_storage_base() = default; + + union { + T m_val; + Unexpected m_unexpect; + }; + + bool m_has_val; +}; + +template +struct expected_operations_base : expected_storage_base { + using expected_storage_base::expected_storage_base; + + template + void construct(Args&&... args) noexcept { + new (std::addressof(this->m_val)) T{std::forward(args)...}; + this->m_has_val = true; + } + + template + void construct_with(Rhs&& rhs) noexcept { + new (std::addressof(this->m_val)) T{std::forward(rhs).get()}; + this->m_has_val = true; + } + + template + void construct_error(Args&&... args) noexcept { + new (std::addressof(this->m_unexpect)) Unexpected{std::forward(args)...}; + this->m_has_val = false; + } + + void assign(const expected_operations_base& rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~Unexpected(); + construct(rhs.get()); + } else { + assign_common(rhs); + } + } + + void assign(expected_operations_base&& rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~Unexpected(); + construct(std::move(rhs).get()); + } else { + assign_common(rhs); + } + } + + template + void assign_common(Rhs&& rhs) { + if (this->m_has_val) { + if (rhs.m_has_val) { + get() = std::forward(rhs).get(); + } else { + destroy_val(); + construct_error(std::forward(rhs).geterr()); + } + } else { + if (!rhs.m_has_val) { + geterr() = std::forward(rhs).geterr(); + } + } + } + + bool has_value() const { + return this->m_has_val; + } + + constexpr T& get() & { + return this->m_val; + } + + constexpr const T& get() const& { + return this->m_val; + } + + constexpr T&& get() && { + return std::move(this->m_val); + } + + constexpr const T&& get() const&& { + return std::move(this->m_val); + } + + constexpr Unexpected& geterr() & { + return this->m_unexpect; + } + + constexpr const Unexpected& geterr() const& { + return this->m_unexpect; + } + + constexpr Unexpected&& geterr() && { + return std::move(this->m_unexpect); + } + + constexpr const Unexpected&& geterr() const&& { + return std::move(this->m_unexpect); + } + + constexpr void destroy_val() { + get().~T(); + } +}; + +/** + * This manages conditionally having a trivial copy constructor + * This specialization is for when T is trivially copy constructible + * Additionally, this requires E to be trivially copy constructible + */ +template > +requires std::is_trivially_copy_constructible_v +struct expected_copy_base : expected_operations_base { + using expected_operations_base::expected_operations_base; +}; + +/** + * This specialization is for when T is not trivially copy constructible + * Additionally, this requires E to be trivially copy constructible + */ +template +requires std::is_trivially_copy_constructible_v +struct expected_copy_base : expected_operations_base { + using expected_operations_base::expected_operations_base; + + expected_copy_base() = default; + + expected_copy_base(const expected_copy_base& rhs) + : expected_operations_base{no_init_t{}} { + if (rhs.has_value()) { + this->construct_with(rhs); + } else { + this->construct_error(rhs.geterr()); + } + } + + expected_copy_base(expected_copy_base&&) = default; + + expected_copy_base& operator=(const expected_copy_base&) = default; + + expected_copy_base& operator=(expected_copy_base&&) = default; +}; + +/** + * This manages conditionally having a trivial move constructor + * This specialization is for when T is trivially move constructible + * Additionally, this requires E to be trivially move constructible + */ +template > +requires std::is_trivially_move_constructible_v +struct expected_move_base : expected_copy_base { + using expected_copy_base::expected_copy_base; +}; + +/** + * This specialization is for when T is not trivially move constructible + * Additionally, this requires E to be trivially move constructible + */ +template +requires std::is_trivially_move_constructible_v +struct expected_move_base : expected_copy_base { + using expected_copy_base::expected_copy_base; + + expected_move_base() = default; + + expected_move_base(const expected_move_base&) = default; + + expected_move_base(expected_move_base&& rhs) noexcept(std::is_nothrow_move_constructible_v) + : expected_copy_base{no_init_t{}} { + if (rhs.has_value()) { + this->construct_with(std::move(rhs)); + } else { + this->construct_error(std::move(rhs.geterr())); + } + } + + expected_move_base& operator=(const expected_move_base&) = default; + + expected_move_base& operator=(expected_move_base&&) = default; +}; + +/** + * This manages conditionally having a trivial copy assignment operator + * This specialization is for when T is trivially copy assignable + * Additionally, this requires E to be trivially copy assignable + */ +template , + std::is_trivially_copy_constructible, + std::is_trivially_destructible>> +requires std::conjunction_v, + std::is_trivially_copy_constructible, + std::is_trivially_destructible> +struct expected_copy_assign_base : expected_move_base { + using expected_move_base::expected_move_base; +}; + +/** + * This specialization is for when T is not trivially copy assignable + * Additionally, this requires E to be trivially copy assignable + */ +template +requires std::conjunction_v, + std::is_trivially_copy_constructible, + std::is_trivially_destructible> +struct expected_copy_assign_base : expected_move_base { + using expected_move_base::expected_move_base; + + expected_copy_assign_base() = default; + + expected_copy_assign_base(const expected_copy_assign_base&) = default; + + expected_copy_assign_base(expected_copy_assign_base&&) = default; + + expected_copy_assign_base& operator=(const expected_copy_assign_base& rhs) { + this->assign(rhs); + return *this; + } + + expected_copy_assign_base& operator=(expected_copy_assign_base&&) = default; +}; + +/** + * This manages conditionally having a trivial move assignment operator + * This specialization is for when T is trivially move assignable + * Additionally, this requires E to be trivially move assignable + */ +template , + std::is_trivially_move_constructible, + std::is_trivially_destructible>> +requires std::conjunction_v, + std::is_trivially_move_constructible, + std::is_trivially_destructible> +struct expected_move_assign_base : expected_copy_assign_base { + using expected_copy_assign_base::expected_copy_assign_base; +}; + +/** + * This specialization is for when T is not trivially move assignable + * Additionally, this requires E to be trivially move assignable + */ +template +requires std::conjunction_v, + std::is_trivially_move_constructible, + std::is_trivially_destructible> +struct expected_move_assign_base : expected_copy_assign_base { + using expected_copy_assign_base::expected_copy_assign_base; + + expected_move_assign_base() = default; + + expected_move_assign_base(const expected_move_assign_base&) = default; + + expected_move_assign_base(expected_move_assign_base&&) = default; + + expected_move_assign_base& operator=(const expected_move_assign_base&) = default; + + expected_move_assign_base& operator=(expected_move_assign_base&& rhs) noexcept( + std::conjunction_v, + std::is_nothrow_move_assignable>) { + this->assign(std::move(rhs)); + return *this; + } +}; + +/** + * expected_delete_ctor_base will conditionally delete copy and move constructors + * depending on whether T is copy/move constructible + * Additionally, this requires E to be copy/move constructible + */ +template , + bool EnableMove = std::is_move_constructible_v> +requires std::conjunction_v, std::is_move_constructible> +struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + expected_delete_ctor_base(const expected_delete_ctor_base&) = default; + expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = default; + expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = default; + expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = default; +}; + +template +requires std::conjunction_v, std::is_move_constructible> +struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + expected_delete_ctor_base(const expected_delete_ctor_base&) = default; + expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = delete; + expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = default; + expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = default; +}; + +template +requires std::conjunction_v, std::is_move_constructible> +struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + expected_delete_ctor_base(const expected_delete_ctor_base&) = delete; + expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = default; + expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = default; + expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = default; +}; + +template +requires std::conjunction_v, std::is_move_constructible> +struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + expected_delete_ctor_base(const expected_delete_ctor_base&) = delete; + expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = delete; + expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = default; + expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = default; +}; + +/** + * expected_delete_assign_base will conditionally delete copy and move assignment operators + * depending on whether T is copy/move constructible + assignable + * Additionally, this requires E to be copy/move constructible + assignable + */ +template < + typename T, typename E, + bool EnableCopy = std::conjunction_v, std::is_copy_assignable>, + bool EnableMove = std::conjunction_v, std::is_move_assignable>> +requires std::conjunction_v, std::is_move_constructible, + std::is_copy_assignable, std::is_move_assignable> +struct expected_delete_assign_base { + expected_delete_assign_base() = default; + expected_delete_assign_base(const expected_delete_assign_base&) = default; + expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default; + expected_delete_assign_base& operator=(const expected_delete_assign_base&) = default; + expected_delete_assign_base& operator=(expected_delete_assign_base&&) noexcept = default; +}; + +template +requires std::conjunction_v, std::is_move_constructible, + std::is_copy_assignable, std::is_move_assignable> +struct expected_delete_assign_base { + expected_delete_assign_base() = default; + expected_delete_assign_base(const expected_delete_assign_base&) = default; + expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default; + expected_delete_assign_base& operator=(const expected_delete_assign_base&) = default; + expected_delete_assign_base& operator=(expected_delete_assign_base&&) noexcept = delete; +}; + +template +requires std::conjunction_v, std::is_move_constructible, + std::is_copy_assignable, std::is_move_assignable> +struct expected_delete_assign_base { + expected_delete_assign_base() = default; + expected_delete_assign_base(const expected_delete_assign_base&) = default; + expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default; + expected_delete_assign_base& operator=(const expected_delete_assign_base&) = delete; + expected_delete_assign_base& operator=(expected_delete_assign_base&&) noexcept = default; +}; + +template +requires std::conjunction_v, std::is_move_constructible, + std::is_copy_assignable, std::is_move_assignable> +struct expected_delete_assign_base { + expected_delete_assign_base() = default; + expected_delete_assign_base(const expected_delete_assign_base&) = default; + expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default; + expected_delete_assign_base& operator=(const expected_delete_assign_base&) = delete; + expected_delete_assign_base& operator=(expected_delete_assign_base&&) noexcept = delete; +}; + +/** + * This is needed to be able to construct the expected_default_ctor_base which follows, + * while still conditionally deleting the default constructor. + */ +struct default_constructor_tag { + constexpr explicit default_constructor_tag() = default; +}; + +/** + * expected_default_ctor_base will ensure that expected + * has a deleted default constructor if T is not default constructible + * This specialization is for when T is default constructible + */ +template > +struct expected_default_ctor_base { + constexpr expected_default_ctor_base() noexcept = default; + constexpr expected_default_ctor_base(expected_default_ctor_base const&) noexcept = default; + constexpr expected_default_ctor_base(expected_default_ctor_base&&) noexcept = default; + expected_default_ctor_base& operator=(expected_default_ctor_base const&) noexcept = default; + expected_default_ctor_base& operator=(expected_default_ctor_base&&) noexcept = default; + + constexpr explicit expected_default_ctor_base(default_constructor_tag) {} +}; + +template +struct expected_default_ctor_base { + constexpr expected_default_ctor_base() noexcept = delete; + constexpr expected_default_ctor_base(expected_default_ctor_base const&) noexcept = default; + constexpr expected_default_ctor_base(expected_default_ctor_base&&) noexcept = default; + expected_default_ctor_base& operator=(expected_default_ctor_base const&) noexcept = default; + expected_default_ctor_base& operator=(expected_default_ctor_base&&) noexcept = default; + + constexpr explicit expected_default_ctor_base(default_constructor_tag) {} +}; + +template +using expected_enable_forward_value = + std::enable_if_t && + !std::is_same_v, std::in_place_t> && + !std::is_same_v, std::remove_cvref_t> && + !std::is_same_v, std::remove_cvref_t>>; + +template +using expected_enable_from_other = std::enable_if_t< + std::is_constructible_v && std::is_constructible_v && + !std::is_constructible_v&> && !std::is_constructible_v&&> && + !std::is_constructible_v&> && + !std::is_constructible_v&&> && + !std::is_convertible_v&, T> && !std::is_convertible_v&&, T> && + !std::is_convertible_v&, T> && + !std::is_convertible_v&&, T>>; + +} // namespace detail + +template +class Expected : private detail::expected_move_assign_base, + private detail::expected_delete_ctor_base, + private detail::expected_delete_assign_base, + private detail::expected_default_ctor_base { +public: + using value_type = T; + using error_type = E; + using unexpected_type = Unexpected; + + constexpr Expected() = default; + constexpr Expected(const Expected&) = default; + constexpr Expected(Expected&&) = default; + Expected& operator=(const Expected&) = default; + Expected& operator=(Expected&&) = default; + + template >* = nullptr> + constexpr Expected(std::in_place_t, Args&&... args) + : impl_base{std::in_place, std::forward(args)...}, + ctor_base{detail::default_constructor_tag{}} {} + + template &, Args&&...>>* = + nullptr> + constexpr Expected(std::in_place_t, std::initializer_list il, Args&&... args) + : impl_base{std::in_place, il, std::forward(args)...}, + ctor_base{detail::default_constructor_tag{}} {} + + template >* = nullptr, + std::enable_if_t>* = nullptr> + constexpr explicit Expected(const Unexpected& e) + : impl_base{unexpect_t{}, e.value()}, ctor_base{detail::default_constructor_tag{}} {} + + template >* = nullptr, + std::enable_if_t>* = nullptr> + constexpr Expected(Unexpected const& e) + : impl_base{unexpect_t{}, e.value()}, ctor_base{detail::default_constructor_tag{}} {} + + template >* = nullptr, + std::enable_if_t>* = nullptr> + constexpr explicit Expected(Unexpected&& e) noexcept(std::is_nothrow_constructible_v) + : impl_base{unexpect_t{}, std::move(e.value())}, ctor_base{ + detail::default_constructor_tag{}} {} + + template >* = nullptr, + std::enable_if_t>* = nullptr> + constexpr Expected(Unexpected&& e) noexcept(std::is_nothrow_constructible_v) + : impl_base{unexpect_t{}, std::move(e.value())}, ctor_base{ + detail::default_constructor_tag{}} {} + + template >* = nullptr> + constexpr explicit Expected(unexpect_t, Args&&... args) + : impl_base{unexpect_t{}, std::forward(args)...}, + ctor_base{detail::default_constructor_tag{}} {} + + template &, Args&&...>>* = + nullptr> + constexpr explicit Expected(unexpect_t, std::initializer_list il, Args&&... args) + : impl_base{unexpect_t{}, il, std::forward(args)...}, + ctor_base{detail::default_constructor_tag{}} {} + + template && + std::is_convertible_v)>* = nullptr, + detail::expected_enable_from_other* = nullptr> + constexpr explicit Expected(const Expected& rhs) + : ctor_base{detail::default_constructor_tag{}} { + if (rhs.has_value()) { + this->construct(*rhs); + } else { + this->construct_error(rhs.error()); + } + } + + template && + std::is_convertible_v)>* = nullptr, + detail::expected_enable_from_other* = nullptr> + constexpr Expected(const Expected& rhs) : ctor_base{detail::default_constructor_tag{}} { + if (rhs.has_value()) { + this->construct(*rhs); + } else { + this->construct_error(rhs.error()); + } + } + + template && std::is_convertible_v)>* = + nullptr, + detail::expected_enable_from_other* = nullptr> + constexpr explicit Expected(Expected&& rhs) + : ctor_base{detail::default_constructor_tag{}} { + if (rhs.has_value()) { + this->construct(std::move(*rhs)); + } else { + this->construct_error(std::move(rhs.error())); + } + } + + template && std::is_convertible_v)>* = + nullptr, + detail::expected_enable_from_other* = nullptr> + constexpr Expected(Expected&& rhs) : ctor_base{detail::default_constructor_tag{}} { + if (rhs.has_value()) { + this->construct(std::move(*rhs)); + } else { + this->construct_error(std::move(rhs.error())); + } + } + + template >* = nullptr, + detail::expected_enable_forward_value* = nullptr> + constexpr explicit Expected(U&& v) : Expected{std::in_place, std::forward(v)} {} + + template >* = nullptr, + detail::expected_enable_forward_value* = nullptr> + constexpr Expected(U&& v) : Expected{std::in_place, std::forward(v)} {} + + template >* = nullptr, + std::enable_if_t<( + !std::is_same_v, std::remove_cvref_t> && + !std::conjunction_v, std::is_same>> && + std::is_constructible_v && std::is_assignable_v && + std::is_nothrow_move_constructible_v)>* = nullptr> + Expected& operator=(U&& v) { + if (has_value()) { + val() = std::forward(v); + } else { + err().~Unexpected(); + new (valptr()) T{std::forward(v)}; + this->m_has_val = true; + } + + return *this; + } + + template >* = nullptr, + std::enable_if_t<( + !std::is_same_v, std::remove_cvref_t> && + !std::conjunction_v, std::is_same>> && + std::is_constructible_v && std::is_assignable_v && + std::is_nothrow_move_constructible_v)>* = nullptr> + Expected& operator=(U&& v) { + if (has_value()) { + val() = std::forward(v); + } else { + auto tmp = std::move(err()); + err().~Unexpected(); + new (valptr()) T{std::forward(v)}; + this->m_has_val = true; + } + + return *this; + } + + template && + std::is_assignable_v>* = nullptr> + Expected& operator=(const Unexpected& rhs) { + if (!has_value()) { + err() = rhs; + } else { + this->destroy_val(); + new (errptr()) Unexpected{rhs}; + this->m_has_val = false; + } + + return *this; + } + + template && + std::is_move_assignable_v>* = nullptr> + Expected& operator=(Unexpected&& rhs) noexcept { + if (!has_value()) { + err() = std::move(rhs); + } else { + this->destroy_val(); + new (errptr()) Unexpected{std::move(rhs)}; + this->m_has_val = false; + } + + return *this; + } + + template >* = nullptr> + void emplace(Args&&... args) { + if (has_value()) { + val() = T{std::forward(args)...}; + } else { + err().~Unexpected(); + new (valptr()) T{std::forward(args)...}; + this->m_has_val = true; + } + } + + template >* = nullptr> + void emplace(Args&&... args) { + if (has_value()) { + val() = T{std::forward(args)...}; + } else { + auto tmp = std::move(err()); + err().~Unexpected(); + new (valptr()) T{std::forward(args)...}; + this->m_has_val = true; + } + } + + template &, + Args&&...>>* = nullptr> + void emplace(std::initializer_list il, Args&&... args) { + if (has_value()) { + T t{il, std::forward(args)...}; + val() = std::move(t); + } else { + err().~Unexpected(); + new (valptr()) T{il, std::forward(args)...}; + this->m_has_val = true; + } + } + + template &, + Args&&...>>* = nullptr> + void emplace(std::initializer_list il, Args&&... args) { + if (has_value()) { + T t{il, std::forward(args)...}; + val() = std::move(t); + } else { + auto tmp = std::move(err()); + err().~Unexpected(); + new (valptr()) T{il, std::forward(args)...}; + this->m_has_val = true; + } + } + + constexpr T* operator->() { + return valptr(); + } + + constexpr const T* operator->() const { + return valptr(); + } + + template + constexpr U& operator*() & { + return val(); + } + + template + constexpr const U& operator*() const& { + return val(); + } + + template + constexpr U&& operator*() && { + return std::move(val()); + } + + template + constexpr const U&& operator*() const&& { + return std::move(val()); + } + + constexpr bool has_value() const noexcept { + return this->m_has_val; + } + + constexpr explicit operator bool() const noexcept { + return this->m_has_val; + } + + template + constexpr U& value() & { + return val(); + } + + template + constexpr const U& value() const& { + return val(); + } + + template + constexpr U&& value() && { + return std::move(val()); + } + + template + constexpr const U&& value() const&& { + return std::move(val()); + } + + constexpr E& error() & { + return err().value(); + } + + constexpr const E& error() const& { + return err().value(); + } + + constexpr E&& error() && { + return std::move(err().value()); + } + + constexpr const E&& error() const&& { + return std::move(err().value()); + } + + template + constexpr T value_or(U&& v) const& { + static_assert(std::is_copy_constructible_v && std::is_convertible_v, + "T must be copy-constructible and convertible from U&&"); + return bool(*this) ? **this : static_cast(std::forward(v)); + } + + template + constexpr T value_or(U&& v) && { + static_assert(std::is_move_constructible_v && std::is_convertible_v, + "T must be move-constructible and convertible from U&&"); + return bool(*this) ? std::move(**this) : static_cast(std::forward(v)); + } + +private: + static_assert(!std::is_reference_v, "T must not be a reference"); + static_assert(!std::is_same_v>, + "T must not be std::in_place_t"); + static_assert(!std::is_same_v>, "T must not be unexpect_t"); + static_assert(!std::is_same_v>>, + "T must not be Unexpected"); + static_assert(!std::is_reference_v, "E must not be a reference"); + + T* valptr() { + return std::addressof(this->m_val); + } + + const T* valptr() const { + return std::addressof(this->m_val); + } + + Unexpected* errptr() { + return std::addressof(this->m_unexpect); + } + + const Unexpected* errptr() const { + return std::addressof(this->m_unexpect); + } + + template + constexpr U& val() { + return this->m_val; + } + + template + constexpr const U& val() const { + return this->m_val; + } + + constexpr Unexpected& err() { + return this->m_unexpect; + } + + constexpr const Unexpected& err() const { + return this->m_unexpect; + } + + using impl_base = detail::expected_move_assign_base; + using ctor_base = detail::expected_default_ctor_base; +}; + +template +constexpr bool operator==(const Expected& lhs, const Expected& rhs) { + return (lhs.has_value() != rhs.has_value()) + ? false + : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs); +} + +template +constexpr bool operator!=(const Expected& lhs, const Expected& rhs) { + return !operator==(lhs, rhs); +} + +template +constexpr bool operator==(const Expected& x, const U& v) { + return x.has_value() ? *x == v : false; +} + +template +constexpr bool operator==(const U& v, const Expected& x) { + return x.has_value() ? *x == v : false; +} + +template +constexpr bool operator!=(const Expected& x, const U& v) { + return !operator==(x, v); +} + +template +constexpr bool operator!=(const U& v, const Expected& x) { + return !operator==(v, x); +} + +template +constexpr bool operator==(const Expected& x, const Unexpected& e) { + return x.has_value() ? false : x.error() == e.value(); +} + +template +constexpr bool operator==(const Unexpected& e, const Expected& x) { + return x.has_value() ? false : x.error() == e.value(); +} + +template +constexpr bool operator!=(const Expected& x, const Unexpected& e) { + return !operator==(x, e); +} + +template +constexpr bool operator!=(const Unexpected& e, const Expected& x) { + return !operator==(e, x); +} + +} // namespace Common diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp index cde5811fe..7ace09a58 100644 --- a/src/core/file_sys/archive_extsavedata.cpp +++ b/src/core/file_sys/archive_extsavedata.cpp @@ -42,7 +42,7 @@ public: if (offset > size) { return ERR_WRITE_BEYOND_END; } else if (offset == size) { - return MakeResult(0); + return 0ULL; } if (offset + length > size) { @@ -150,11 +150,9 @@ public: Mode rwmode; rwmode.write_flag.Assign(1); rwmode.read_flag.Assign(1); - std::unique_ptr delay_generator = - std::make_unique(); - auto disk_file = - std::make_unique(std::move(file), rwmode, std::move(delay_generator)); - return MakeResult>(std::move(disk_file)); + auto delay_generator = std::make_unique(); + return std::make_unique(std::move(file), rwmode, + std::move(delay_generator)); } ResultCode CreateFile(const Path& path, u64 size) const override { @@ -255,8 +253,7 @@ ResultVal> ArchiveFactory_ExtSaveData::Open(cons } } std::unique_ptr delay_generator = std::make_unique(); - auto archive = std::make_unique(fullpath, std::move(delay_generator)); - return MakeResult>(std::move(archive)); + return std::make_unique(fullpath, std::move(delay_generator)); } ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path, @@ -276,7 +273,7 @@ ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path, if (!file.IsOpen()) { // TODO(Subv): Find the correct error code - return ResultCode(-1); + return RESULT_UNKNOWN; } file.WriteBytes(&format_info, sizeof(format_info)); @@ -296,7 +293,7 @@ ResultVal ArchiveFactory_ExtSaveData::GetFormatInfo(const Pat ArchiveFormatInfo info = {}; file.ReadBytes(&info, sizeof(info)); - return MakeResult(info); + return info; } void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, const u8* icon_data, diff --git a/src/core/file_sys/archive_ncch.cpp b/src/core/file_sys/archive_ncch.cpp index 551998576..7b0e4de58 100644 --- a/src/core/file_sys/archive_ncch.cpp +++ b/src/core/file_sys/archive_ncch.cpp @@ -170,16 +170,14 @@ ResultVal> NCCHArchive::OpenFile(const Path& path, if (!archive_data.empty()) { u64 romfs_offset = 0; u64 romfs_size = archive_data.size(); - std::unique_ptr delay_generator = - std::make_unique(); - file = std::make_unique(std::move(archive_data), romfs_offset, + auto delay_generator = std::make_unique(); + return std::make_unique(std::move(archive_data), romfs_offset, romfs_size, std::move(delay_generator)); - return MakeResult>(std::move(file)); } return ERROR_NOT_FOUND; } - return MakeResult>(std::move(file)); + return file; } ResultCode NCCHArchive::DeleteFile(const Path& path) const { @@ -192,21 +190,21 @@ ResultCode NCCHArchive::DeleteFile(const Path& path) const { ResultCode NCCHArchive::RenameFile(const Path& src_path, const Path& dest_path) const { LOG_CRITICAL(Service_FS, "Attempted to rename a file within an NCCH archive ({}).", GetName()); // TODO(wwylele): Use correct error code - return ResultCode(-1); + return RESULT_UNKNOWN; } ResultCode NCCHArchive::DeleteDirectory(const Path& path) const { LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an NCCH archive ({}).", GetName()); // TODO(wwylele): Use correct error code - return ResultCode(-1); + return RESULT_UNKNOWN; } ResultCode NCCHArchive::DeleteDirectoryRecursively(const Path& path) const { LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an NCCH archive ({}).", GetName()); // TODO(wwylele): Use correct error code - return ResultCode(-1); + return RESULT_UNKNOWN; } ResultCode NCCHArchive::CreateFile(const Path& path, u64 size) const { @@ -219,20 +217,20 @@ ResultCode NCCHArchive::CreateFile(const Path& path, u64 size) const { ResultCode NCCHArchive::CreateDirectory(const Path& path) const { LOG_CRITICAL(Service_FS, "Attempted to create a directory in an NCCH archive ({}).", GetName()); // TODO(wwylele): Use correct error code - return ResultCode(-1); + return RESULT_UNKNOWN; } ResultCode NCCHArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { LOG_CRITICAL(Service_FS, "Attempted to rename a file within an NCCH archive ({}).", GetName()); // TODO(wwylele): Use correct error code - return ResultCode(-1); + return RESULT_UNKNOWN; } ResultVal> NCCHArchive::OpenDirectory(const Path& path) const { LOG_CRITICAL(Service_FS, "Attempted to open a directory within an NCCH archive ({}).", GetName().c_str()); // TODO(shinyquagsire23): Use correct error code - return ResultCode(-1); + return RESULT_UNKNOWN; } u64 NCCHArchive::GetFreeBytes() const { @@ -253,14 +251,14 @@ ResultVal NCCHFile::Read(const u64 offset, const std::size_t length std::size_t copy_size = std::min(length, available_size); memcpy(buffer, file_buffer.data() + offset, copy_size); - return MakeResult(copy_size); + return copy_size; } ResultVal NCCHFile::Write(const u64 offset, const std::size_t length, const bool flush, const u8* buffer) { LOG_ERROR(Service_FS, "Attempted to write to NCCH file"); // TODO(shinyquagsire23): Find error code - return MakeResult(0); + return 0ULL; } u64 NCCHFile::GetSize() const { @@ -290,9 +288,8 @@ ResultVal> ArchiveFactory_NCCH::Open(const Path& NCCHArchivePath open_path; std::memcpy(&open_path, binary.data(), sizeof(NCCHArchivePath)); - auto archive = std::make_unique( + return std::make_unique( open_path.tid, static_cast(open_path.media_type & 0xFF)); - return MakeResult>(std::move(archive)); } ResultCode ArchiveFactory_NCCH::Format(const Path& path, @@ -308,7 +305,7 @@ ResultVal ArchiveFactory_NCCH::GetFormatInfo(const Path& path u64 program_id) const { // TODO(Subv): Implement LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName()); - return ResultCode(-1); + return RESULT_UNKNOWN; } } // namespace FileSys diff --git a/src/core/file_sys/archive_other_savedata.cpp b/src/core/file_sys/archive_other_savedata.cpp index 8f6d9ca24..319415f55 100644 --- a/src/core/file_sys/archive_other_savedata.cpp +++ b/src/core/file_sys/archive_other_savedata.cpp @@ -45,7 +45,7 @@ ResultVal> ParsePath(const Path& path, T program_id_r return ERROR_UNSUPPORTED_OPEN_FLAGS; } - return MakeResult>(media_type, program_id_reader(data)); + return std::make_tuple(media_type, program_id_reader(data)); } ResultVal> ParsePathPermitted(const Path& path) { diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index 0e6947493..ce69cf0ce 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp @@ -108,8 +108,7 @@ ResultVal> SDMCArchive::OpenFileBase(const Path& pa } std::unique_ptr delay_generator = std::make_unique(); - auto disk_file = std::make_unique(std::move(file), mode, std::move(delay_generator)); - return MakeResult>(std::move(disk_file)); + return std::make_unique(std::move(file), mode, std::move(delay_generator)); } ResultCode SDMCArchive::DeleteFile(const Path& path) const { @@ -358,8 +357,7 @@ ResultVal> SDMCArchive::OpenDirectory(const Pa break; // Expected 'success' case } - auto directory = std::make_unique(full_path); - return MakeResult>(std::move(directory)); + return std::make_unique(full_path); } u64 SDMCArchive::GetFreeBytes() const { @@ -390,8 +388,7 @@ bool ArchiveFactory_SDMC::Initialize() { ResultVal> ArchiveFactory_SDMC::Open(const Path& path, u64 program_id) { std::unique_ptr delay_generator = std::make_unique(); - auto archive = std::make_unique(sdmc_directory, std::move(delay_generator)); - return MakeResult>(std::move(archive)); + return std::make_unique(sdmc_directory, std::move(delay_generator)); } ResultCode ArchiveFactory_SDMC::Format(const Path& path, @@ -405,7 +402,7 @@ ResultVal ArchiveFactory_SDMC::GetFormatInfo(const Path& path u64 program_id) const { // TODO(Subv): Implement LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName()); - return ResultCode(-1); + return RESULT_UNKNOWN; } } // namespace FileSys diff --git a/src/core/file_sys/archive_sdmcwriteonly.cpp b/src/core/file_sys/archive_sdmcwriteonly.cpp index e0053404d..102279d68 100644 --- a/src/core/file_sys/archive_sdmcwriteonly.cpp +++ b/src/core/file_sys/archive_sdmcwriteonly.cpp @@ -78,9 +78,7 @@ ResultVal> ArchiveFactory_SDMCWriteOnly::Open(co u64 program_id) { std::unique_ptr delay_generator = std::make_unique(); - auto archive = - std::make_unique(sdmc_directory, std::move(delay_generator)); - return MakeResult>(std::move(archive)); + return std::make_unique(sdmc_directory, std::move(delay_generator)); } ResultCode ArchiveFactory_SDMCWriteOnly::Format(const Path& path, @@ -88,14 +86,14 @@ ResultCode ArchiveFactory_SDMCWriteOnly::Format(const Path& path, u64 program_id) { // TODO(wwylele): hwtest this LOG_ERROR(Service_FS, "Attempted to format a SDMC write-only archive."); - return ResultCode(-1); + return RESULT_UNKNOWN; } ResultVal ArchiveFactory_SDMCWriteOnly::GetFormatInfo(const Path& path, u64 program_id) const { // TODO(Subv): Implement LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName()); - return ResultCode(-1); + return RESULT_UNKNOWN; } } // namespace FileSys diff --git a/src/core/file_sys/archive_selfncch.cpp b/src/core/file_sys/archive_selfncch.cpp index e707f64a4..b0955f1e7 100644 --- a/src/core/file_sys/archive_selfncch.cpp +++ b/src/core/file_sys/archive_selfncch.cpp @@ -48,7 +48,7 @@ public: } std::memcpy(buffer, data->data(), data->size()); - return MakeResult(data->size()); + return data->size(); } ResultVal Write(u64 offset, std::size_t length, bool flush, @@ -183,8 +183,7 @@ private: if (ncch_data.romfs_file) { std::unique_ptr delay_generator = std::make_unique(); - return MakeResult>( - std::make_unique(ncch_data.romfs_file, std::move(delay_generator))); + return std::make_unique(ncch_data.romfs_file, std::move(delay_generator)); } else { LOG_INFO(Service_FS, "Unable to read RomFS"); return ERROR_ROMFS_NOT_FOUND; @@ -195,8 +194,8 @@ private: if (ncch_data.update_romfs_file) { std::unique_ptr delay_generator = std::make_unique(); - return MakeResult>(std::make_unique( - ncch_data.update_romfs_file, std::move(delay_generator))); + return std::make_unique(ncch_data.update_romfs_file, + std::move(delay_generator)); } else { LOG_INFO(Service_FS, "Unable to read update RomFS"); return ERROR_ROMFS_NOT_FOUND; @@ -206,8 +205,7 @@ private: ResultVal> OpenExeFS(const std::string& filename) const { if (filename == "icon") { if (ncch_data.icon) { - return MakeResult>( - std::make_unique(ncch_data.icon)); + return std::make_unique(ncch_data.icon); } LOG_WARNING(Service_FS, "Unable to read icon"); @@ -216,8 +214,7 @@ private: if (filename == "logo") { if (ncch_data.logo) { - return MakeResult>( - std::make_unique(ncch_data.logo)); + return std::make_unique(ncch_data.logo); } LOG_WARNING(Service_FS, "Unable to read logo"); @@ -226,8 +223,7 @@ private: if (filename == "banner") { if (ncch_data.banner) { - return MakeResult>( - std::make_unique(ncch_data.banner)); + return std::make_unique(ncch_data.banner); } LOG_WARNING(Service_FS, "Unable to read banner"); @@ -297,8 +293,7 @@ void ArchiveFactory_SelfNCCH::Register(Loader::AppLoader& app_loader) { ResultVal> ArchiveFactory_SelfNCCH::Open(const Path& path, u64 program_id) { - auto archive = std::make_unique(ncch_data[program_id]); - return MakeResult>(std::move(archive)); + return std::make_unique(ncch_data[program_id]); } ResultCode ArchiveFactory_SelfNCCH::Format(const Path&, const FileSys::ArchiveFormatInfo&, diff --git a/src/core/file_sys/archive_source_sd_savedata.cpp b/src/core/file_sys/archive_source_sd_savedata.cpp index bb3c586d4..de2a06cbb 100644 --- a/src/core/file_sys/archive_source_sd_savedata.cpp +++ b/src/core/file_sys/archive_source_sd_savedata.cpp @@ -50,8 +50,7 @@ ResultVal> ArchiveSource_SDSaveData::Open(u64 pr return ERR_NOT_FORMATTED; } - auto archive = std::make_unique(std::move(concrete_mount_point)); - return MakeResult>(std::move(archive)); + return std::make_unique(std::move(concrete_mount_point)); } ResultCode ArchiveSource_SDSaveData::Format(u64 program_id, @@ -83,7 +82,7 @@ ResultVal ArchiveSource_SDSaveData::GetFormatInfo(u64 program ArchiveFormatInfo info = {}; file.ReadBytes(&info, sizeof(info)); - return MakeResult(info); + return info; } std::string ArchiveSource_SDSaveData::GetSaveDataPathFor(const std::string& mount_point, diff --git a/src/core/file_sys/archive_systemsavedata.cpp b/src/core/file_sys/archive_systemsavedata.cpp index 3d6b7f34d..d1e285571 100644 --- a/src/core/file_sys/archive_systemsavedata.cpp +++ b/src/core/file_sys/archive_systemsavedata.cpp @@ -59,8 +59,7 @@ ResultVal> ArchiveFactory_SystemSaveData::Open(c // TODO(Subv): Check error code, this one is probably wrong return ERROR_NOT_FOUND; } - auto archive = std::make_unique(fullpath); - return MakeResult>(std::move(archive)); + return std::make_unique(fullpath); } ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path, @@ -76,7 +75,7 @@ ResultVal ArchiveFactory_SystemSaveData::GetFormatInfo(const u64 program_id) const { // TODO(Subv): Implement LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName()); - return ResultCode(-1); + return RESULT_UNKNOWN; } } // namespace FileSys diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp index ca5e49e86..1b9717387 100644 --- a/src/core/file_sys/disk_archive.cpp +++ b/src/core/file_sys/disk_archive.cpp @@ -22,7 +22,7 @@ ResultVal DiskFile::Read(const u64 offset, const std::size_t length return ERROR_INVALID_OPEN_FLAGS; file->Seek(offset, SEEK_SET); - return MakeResult(file->ReadBytes(buffer, length)); + return file->ReadBytes(buffer, length); } ResultVal DiskFile::Write(const u64 offset, const std::size_t length, const bool flush, @@ -34,7 +34,7 @@ ResultVal DiskFile::Write(const u64 offset, const std::size_t lengt std::size_t written = file->WriteBytes(buffer, length); if (flush) file->Flush(); - return MakeResult(written); + return written; } u64 DiskFile::GetSize() const { diff --git a/src/core/file_sys/ivfc_archive.cpp b/src/core/file_sys/ivfc_archive.cpp index 010a4d42b..d5d46e0ef 100644 --- a/src/core/file_sys/ivfc_archive.cpp +++ b/src/core/file_sys/ivfc_archive.cpp @@ -31,8 +31,7 @@ std::string IVFCArchive::GetName() const { ResultVal> IVFCArchive::OpenFile(const Path& path, const Mode& mode) const { std::unique_ptr delay_generator = std::make_unique(); - return MakeResult>( - std::make_unique(romfs_file, std::move(delay_generator))); + return std::make_unique(romfs_file, std::move(delay_generator)); } ResultCode IVFCArchive::DeleteFile(const Path& path) const { @@ -45,21 +44,21 @@ ResultCode IVFCArchive::DeleteFile(const Path& path) const { ResultCode IVFCArchive::RenameFile(const Path& src_path, const Path& dest_path) const { LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive ({}).", GetName()); // TODO(wwylele): Use correct error code - return ResultCode(-1); + return RESULT_UNKNOWN; } ResultCode IVFCArchive::DeleteDirectory(const Path& path) const { LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an IVFC archive ({}).", GetName()); // TODO(wwylele): Use correct error code - return ResultCode(-1); + return RESULT_UNKNOWN; } ResultCode IVFCArchive::DeleteDirectoryRecursively(const Path& path) const { LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an IVFC archive ({}).", GetName()); // TODO(wwylele): Use correct error code - return ResultCode(-1); + return RESULT_UNKNOWN; } ResultCode IVFCArchive::CreateFile(const Path& path, u64 size) const { @@ -72,17 +71,17 @@ ResultCode IVFCArchive::CreateFile(const Path& path, u64 size) const { ResultCode IVFCArchive::CreateDirectory(const Path& path) const { LOG_CRITICAL(Service_FS, "Attempted to create a directory in an IVFC archive ({}).", GetName()); // TODO(wwylele): Use correct error code - return ResultCode(-1); + return RESULT_UNKNOWN; } ResultCode IVFCArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive ({}).", GetName()); // TODO(wwylele): Use correct error code - return ResultCode(-1); + return RESULT_UNKNOWN; } ResultVal> IVFCArchive::OpenDirectory(const Path& path) const { - return MakeResult>(std::make_unique()); + return std::make_unique(); } u64 IVFCArchive::GetFreeBytes() const { @@ -99,14 +98,14 @@ IVFCFile::IVFCFile(std::shared_ptr file, ResultVal IVFCFile::Read(const u64 offset, const std::size_t length, u8* buffer) const { LOG_TRACE(Service_FS, "called offset={}, length={}", offset, length); - return MakeResult(romfs_file->ReadFile(offset, length, buffer)); + return romfs_file->ReadFile(offset, length, buffer); } ResultVal IVFCFile::Write(const u64 offset, const std::size_t length, const bool flush, const u8* buffer) { LOG_ERROR(Service_FS, "Attempted to write to IVFC file"); // TODO(Subv): Find error code - return MakeResult(0); + return 0ULL; } u64 IVFCFile::GetSize() const { @@ -130,14 +129,14 @@ ResultVal IVFCFileInMemory::Read(const u64 offset, const std::size_ std::size_t read_length = (std::size_t)std::min((u64)length, data_size - offset); std::memcpy(buffer, romfs_file.data() + data_offset + offset, read_length); - return MakeResult(read_length); + return read_length; } ResultVal IVFCFileInMemory::Write(const u64 offset, const std::size_t length, const bool flush, const u8* buffer) { LOG_ERROR(Service_FS, "Attempted to write to IVFC file"); // TODO(Subv): Find error code - return MakeResult(0); + return 0ULL; } u64 IVFCFileInMemory::GetSize() const { diff --git a/src/core/file_sys/savedata_archive.cpp b/src/core/file_sys/savedata_archive.cpp index bec9eb650..63a905560 100644 --- a/src/core/file_sys/savedata_archive.cpp +++ b/src/core/file_sys/savedata_archive.cpp @@ -90,8 +90,7 @@ ResultVal> SaveDataArchive::OpenFile(const Path& pa } std::unique_ptr delay_generator = std::make_unique(); - auto disk_file = std::make_unique(std::move(file), mode, std::move(delay_generator)); - return MakeResult>(std::move(disk_file)); + return std::make_unique(std::move(file), mode, std::move(delay_generator)); } ResultCode SaveDataArchive::DeleteFile(const Path& path) const { @@ -343,8 +342,7 @@ ResultVal> SaveDataArchive::OpenDirectory( break; // Expected 'success' case } - auto directory = std::make_unique(full_path); - return MakeResult>(std::move(directory)); + return std::make_unique(full_path); } u64 SaveDataArchive::GetFreeBytes() const { diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index e7e8a8014..d12078ce3 100644 --- a/src/core/hle/kernel/client_port.cpp +++ b/src/core/hle/kernel/client_port.cpp @@ -40,7 +40,7 @@ ResultVal> ClientPort::Connect() { // Wake the threads waiting on the ServerPort server_port->WakeupAllWaitingThreads(); - return MakeResult(client); + return client; } void ClientPort::ConnectionClosed() { diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index d717c8399..8c7b95f26 100644 --- a/src/core/hle/kernel/handle_table.cpp +++ b/src/core/hle/kernel/handle_table.cpp @@ -49,7 +49,7 @@ ResultVal HandleTable::Create(std::shared_ptr obj) { objects[slot] = std::move(obj); Handle handle = generation | (slot << 15); - return MakeResult(handle); + return handle; } ResultVal HandleTable::Duplicate(Handle handle) { diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index f10baa064..9b59f9775 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -271,7 +271,7 @@ ResultVal Process::HeapAllocate(VAddr target, u32 size, VMAPermission per memory_used += size; resource_limit->current_commit += size; - return MakeResult(target); + return target; } ResultCode Process::HeapFree(VAddr target, u32 size) { @@ -344,7 +344,7 @@ ResultVal Process::LinearAllocate(VAddr target, u32 size, VMAPermission p resource_limit->current_commit += size; LOG_DEBUG(Kernel, "Allocated at target={:08X}", target); - return MakeResult(target); + return target; } ResultCode Process::LinearFree(VAddr target, u32 size) { diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index 7aefc8605..cbc6beea1 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp @@ -31,7 +31,7 @@ ResultVal> KernelSystem::CreateSemaphore(s32 initial_ semaphore->available_count = initial_count; semaphore->name = std::move(name); - return MakeResult>(std::move(semaphore)); + return semaphore; } bool Semaphore::ShouldWait(const Thread* thread) const { @@ -53,7 +53,7 @@ ResultVal Semaphore::Release(s32 release_count) { WakeupAllWaitingThreads(); - return MakeResult(previous_count); + return previous_count; } } // namespace Kernel diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp index 006403925..721a029d8 100644 --- a/src/core/hle/kernel/server_port.cpp +++ b/src/core/hle/kernel/server_port.cpp @@ -31,7 +31,7 @@ ResultVal> ServerPort::Accept() { auto session = std::move(pending_sessions.back()); pending_sessions.pop_back(); - return MakeResult(std::move(session)); + return session; } bool ServerPort::ShouldWait(const Thread* thread) const { diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index edd8be1a3..2e0c647e4 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -52,7 +52,7 @@ ResultVal> ServerSession::Create(KernelSystem& ke server_session->name = std::move(name); server_session->parent = nullptr; - return MakeResult(std::move(server_session)); + return server_session; } bool ServerSession::ShouldWait(const Thread* thread) const { diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index 48fcab17a..73a795982 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -69,7 +69,7 @@ ResultVal> KernelSystem::CreateSharedMemory( } shared_memory->base_address = address; - return MakeResult(shared_memory); + return shared_memory; } std::shared_ptr KernelSystem::CreateSharedMemoryForApplet( diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 4c075b541..faa173f76 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -674,7 +674,7 @@ ResultCode SVC::OpenProcess(Handle* out_handle, u32 process_id) { return ResultCode(24, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); } auto result_handle = kernel.GetCurrentProcess()->handle_table.Create(process); - if (result_handle.empty()) { + if (!result_handle) { return result_handle.Code(); } *out_handle = result_handle.Unwrap(); @@ -699,7 +699,7 @@ ResultCode SVC::OpenThread(Handle* out_handle, Handle process_handle, u32 thread for (auto& thread : thread_list) { if (thread->owner_process.lock() == process && thread.get()->thread_id == thread_id) { auto result_handle = kernel.GetCurrentProcess()->handle_table.Create(thread); - if (result_handle.empty()) { + if (!result_handle) { return result_handle.Code(); } *out_handle = result_handle.Unwrap(); diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index a6ccf9525..2e6aebe21 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -423,7 +423,7 @@ ResultVal> KernelSystem::CreateThread( thread_managers[processor_id]->ready_queue.push_back(thread->current_priority, thread.get()); thread->status = ThreadStatus::Ready; - return MakeResult>(std::move(thread)); + return thread; } void Thread::SetPriority(u32 priority) { diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 49533bb7e..944c9a5b1 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -96,7 +96,7 @@ ResultVal VMManager::MapBackingMemoryToBase(VAddr base, u32 region_size, if (result.Failed()) return result.Code(); - return MakeResult(target); + return target; } ResultVal VMManager::MapBackingMemory(VAddr target, MemoryRef memory, @@ -115,7 +115,7 @@ ResultVal VMManager::MapBackingMemory(VAddr target, Memory final_vma.backing_memory = memory; UpdatePageTableForVMA(final_vma); - return MakeResult(MergeAdjacent(vma_handle)); + return MergeAdjacent(vma_handle); } ResultVal VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, @@ -135,7 +135,7 @@ ResultVal VMManager::MapMMIO(VAddr target, PAddr paddr, u3 final_vma.mmio_handler = mmio_handler; UpdatePageTableForVMA(final_vma); - return MakeResult(MergeAdjacent(vma_handle)); + return MergeAdjacent(vma_handle); } ResultCode VMManager::ChangeMemoryState(VAddr target, u32 size, MemoryState expected_state, @@ -294,7 +294,7 @@ ResultVal VMManager::CarveVMA(VAddr base, u32 size) { vma_handle = SplitVMA(vma_handle, start_in_vma); } - return MakeResult(vma_handle); + return vma_handle; } ResultVal VMManager::CarveVMARange(VAddr target, u32 size) { @@ -322,7 +322,7 @@ ResultVal VMManager::CarveVMARange(VAddr target, u32 size) { end_vma = SplitVMA(end_vma, target_end - end_vma->second.base); } - return MakeResult(begin_vma); + return begin_vma; } VMManager::VMAIter VMManager::SplitVMA(VMAIter vma_handle, u32 offset_in_vma) { @@ -409,6 +409,6 @@ ResultVal>> VMManager::GetBackingBlocksFor interval_target += interval_size; } - return MakeResult(backing_blocks); + return backing_blocks; } } // namespace Kernel diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 40a71e369..a1adaeeaa 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -4,13 +4,12 @@ #pragma once -#include -#include #include #include "common/assert.h" #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" +#include "common/expected.h" // All the constants in this file come from http://3dbrew.org/wiki/Error_codes @@ -255,12 +254,19 @@ constexpr ResultCode UnimplementedFunction(ErrorModule module) { } /** - * This is an optional value type. It holds a `ResultCode` and, if that code is a success code, - * also holds a result of type `T`. If the code is an error code then trying to access the inner - * value fails, thus ensuring that the ResultCode of functions is always checked properly before - * their return value is used. It is similar in concept to the `std::optional` type - * (http://en.cppreference.com/w/cpp/experimental/optional) originally proposed for inclusion in - * C++14, or the `Result` type in Rust (http://doc.rust-lang.org/std/result/index.html). + * Placeholder result code used for unknown error codes. + * + * @note This should only be used when a particular error code + * is not known yet. + */ +constexpr ResultCode RESULT_UNKNOWN(UINT32_MAX); + +/** + * This is an optional value type. It holds a `ResultCode` and, if that code is ResultSuccess, it + * also holds a result of type `T`. If the code is an error code (not ResultSuccess), then trying + * to access the inner value with operator* is undefined behavior and will assert with Unwrap(). + * Users of this class must be cognizant to check the status of the ResultVal with operator bool(), + * Code(), Succeeded() or Failed() prior to accessing the inner value. * * An example of how it could be used: * \code @@ -271,166 +277,117 @@ constexpr ResultCode UnimplementedFunction(ErrorModule module) { * ErrorSummary::InvalidArgument, ErrorLevel::Permanent); * } else { * // Frobnicated! Give caller a cookie - * return MakeResult(42); + * return 42; * } * } * \endcode * * \code - * ResultVal frob_result = Frobnicate(0.75f); + * auto frob_result = Frobnicate(0.75f); * if (frob_result) { * // Frobbed ok * printf("My cookie is %d\n", *frob_result); * } else { - * printf("Guess I overdid it. :( Error code: %ux\n", frob_result.code().hex); + * printf("Guess I overdid it. :( Error code: %ux\n", frob_result.Code().raw); * } * \endcode */ template class ResultVal { public: - /// Constructs an empty `ResultVal` with the given error code. The code must not be a success - /// code. - ResultVal(ResultCode error_code = ResultCode(-1)) : result_code(error_code) { - ASSERT(error_code.IsError()); - } + constexpr ResultVal() : expected{} {} - /** - * Similar to the non-member function `MakeResult`, with the exception that you can manually - * specify the success code. `success_code` must not be an error code. - */ - template - static ResultVal WithCode(ResultCode success_code, Args&&... args) { - ResultVal result; - result.emplace(success_code, std::forward(args)...); - return result; - } + constexpr ResultVal(ResultCode code) : expected{Common::Unexpected(code)} {} - ResultVal(const ResultVal& o) : result_code(o.result_code) { - if (!o.empty()) { - new (&object) T(o.object); - } - } - - ResultVal(ResultVal&& o) : result_code(o.result_code) { - if (!o.empty()) { - new (&object) T(std::move(o.object)); - } - } - - ~ResultVal() { - if (!empty()) { - object.~T(); - } - } - - ResultVal& operator=(const ResultVal& o) { - if (!empty()) { - if (!o.empty()) { - object = o.object; - } else { - object.~T(); - } - } else { - if (!o.empty()) { - new (&object) T(o.object); - } - } - result_code = o.result_code; - - return *this; - } - - /** - * Replaces the current result with a new constructed result value in-place. The code must not - * be an error code. - */ - template - void emplace(ResultCode success_code, Args&&... args) { - ASSERT(success_code.IsSuccess()); - if (!empty()) { - object.~T(); - } - new (&object) T(std::forward(args)...); - result_code = success_code; - } - - /// Returns true if the `ResultVal` contains an error code and no value. - bool empty() const { - return result_code.IsError(); - } - - /// Returns true if the `ResultVal` contains a return value. - bool Succeeded() const { - return result_code.IsSuccess(); - } - /// Returns true if the `ResultVal` contains an error code and no value. - bool Failed() const { - return empty(); - } - - ResultCode Code() const { - return result_code; - } - - const T& operator*() const { - return object; - } - T& operator*() { - return object; - } - const T* operator->() const { - return &object; - } - T* operator->() { - return &object; - } - - /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing. template - T ValueOr(U&& value) const { - return !empty() ? object : std::move(value); + constexpr ResultVal(U&& val) : expected{std::forward(val)} {} + + template + constexpr ResultVal(Args&&... args) : expected{std::in_place, std::forward(args)...} {} + + ~ResultVal() = default; + + constexpr ResultVal(const ResultVal&) = default; + constexpr ResultVal(ResultVal&&) = default; + + ResultVal& operator=(const ResultVal&) = default; + ResultVal& operator=(ResultVal&&) = default; + + [[nodiscard]] constexpr explicit operator bool() const noexcept { + return expected.has_value(); } - /// Asserts that the result succeeded and returns a reference to it. - T& Unwrap() & { - ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); - return **this; + [[nodiscard]] constexpr ResultCode Code() const { + return expected.has_value() ? RESULT_SUCCESS : expected.error(); } - T&& Unwrap() && { + [[nodiscard]] constexpr bool Succeeded() const { + return expected.has_value(); + } + + [[nodiscard]] constexpr bool Failed() const { + return !expected.has_value(); + } + + [[nodiscard]] constexpr T* operator->() { + return std::addressof(expected.value()); + } + + [[nodiscard]] constexpr const T* operator->() const { + return std::addressof(expected.value()); + } + + [[nodiscard]] constexpr T& operator*() & { + return *expected; + } + + [[nodiscard]] constexpr const T& operator*() const& { + return *expected; + } + + [[nodiscard]] constexpr T&& operator*() && { + return *expected; + } + + [[nodiscard]] constexpr const T&& operator*() const&& { + return *expected; + } + + [[nodiscard]] constexpr T& Unwrap() & { ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); - return std::move(**this); + return expected.value(); + } + + [[nodiscard]] constexpr const T& Unwrap() const& { + ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); + return expected.value(); + } + + [[nodiscard]] constexpr T&& Unwrap() && { + ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); + return std::move(expected.value()); + } + + [[nodiscard]] constexpr const T&& Unwrap() const&& { + ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); + return std::move(expected.value()); + } + + template + [[nodiscard]] constexpr T ValueOr(U&& v) const& { + return expected.value_or(v); + } + + template + [[nodiscard]] constexpr T ValueOr(U&& v) && { + return expected.value_or(v); } private: - // A union is used to allocate the storage for the value, while allowing us to construct and - // destruct it at will. - union { - T object; - }; - ResultCode result_code; + // TODO: Replace this with std::expected once it is standardized in the STL. + Common::Expected expected; }; -/** - * This function is a helper used to construct `ResultVal`s. It receives the arguments to construct - * `T` with and creates a success `ResultVal` contained the constructed value. - */ -template -ResultVal MakeResult(Args&&... args) { - return ResultVal::WithCode(RESULT_SUCCESS, std::forward(args)...); -} - -/** - * Deducible overload of MakeResult, allowing the template parameter to be ommited if you're just - * copy or move constructing. - */ -template -ResultVal> MakeResult(Arg&& arg) { - return ResultVal>::WithCode(RESULT_SUCCESS, - std::forward(arg)); -} - /** * Check for the success of `source` (which must evaluate to a ResultVal). If it succeeds, unwraps * the contained value and assigns it to `target`, which can be either an l-value expression or a diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 439574be2..b1e111f91 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -92,7 +92,7 @@ CIAFile::~CIAFile() { ResultVal CIAFile::Read(u64 offset, std::size_t length, u8* buffer) const { UNIMPLEMENTED(); - return MakeResult(length); + return length; } ResultCode CIAFile::WriteTicket() { @@ -203,7 +203,7 @@ ResultVal CIAFile::WriteContentData(u64 offset, std::size_t length, } } - return MakeResult(length); + return length; } ResultVal CIAFile::Write(u64 offset, std::size_t length, bool flush, @@ -235,7 +235,7 @@ ResultVal CIAFile::Write(u64 offset, std::size_t length, bool flush // If we don't have a header yet, we can't pull offsets of other sections if (install_state == CIAInstallState::InstallStarted) - return MakeResult(length); + return length; // If we have been given data before (or including) .app content, pull it into // our buffer, but only pull *up to* the content offset, no further. @@ -267,14 +267,14 @@ ResultVal CIAFile::Write(u64 offset, std::size_t length, bool flush // Content data sizes can only be retrieved from TMD data if (install_state != CIAInstallState::TMDLoaded) - return MakeResult(length); + return length; // From this point forward, data will no longer be buffered in data auto result = WriteContentData(offset, length, buffer); if (result.Failed()) return result; - return MakeResult(length); + return length; } u64 CIAFile::GetSize() const { @@ -1316,7 +1316,7 @@ ResultVal> GetFileFromSession( // File::OpenSubFile std::size_t offset = file->GetSessionFileOffset(server); std::size_t size = file->GetSessionFileSize(server); - return MakeResult(std::make_unique(file, offset, size)); + return std::make_unique(file, offset, size); } LOG_ERROR(Service_AM, "Failed to cast handle to FSFile!"); diff --git a/src/core/hle/service/apt/applet_manager.cpp b/src/core/hle/service/apt/applet_manager.cpp index d52d1e5c9..6a10d7016 100644 --- a/src/core/hle/service/apt/applet_manager.cpp +++ b/src/core/hle/service/apt/applet_manager.cpp @@ -291,7 +291,7 @@ ResultVal AppletManager::GlanceParameter(AppletId app_id) { next_parameter = {}; } - return MakeResult(std::move(parameter)); + return parameter; } ResultVal AppletManager::ReceiveParameter(AppletId app_id) { @@ -333,7 +333,7 @@ ResultVal AppletManager::GetLockHandle( corrected_attributes.raw); } - return MakeResult({corrected_attributes, 0, lock}); + return GetLockHandleResult{corrected_attributes, 0, lock}; } ResultVal AppletManager::Initialize(AppletId app_id, @@ -372,8 +372,7 @@ ResultVal AppletManager::Initialize(AppletId ap }); } - return MakeResult( - {slot_data->notification_event, slot_data->parameter_event}); + return InitializeResult{slot_data->notification_event, slot_data->parameter_event}; } ResultCode AppletManager::Enable(AppletAttributes attributes) { @@ -420,7 +419,7 @@ ResultVal AppletManager::InquireNotification(AppletId app_id) { if (slot_data->registered) { auto notification = slot_data->notification; slot_data->notification = Notification::None; - return MakeResult(notification); + return notification; } } @@ -943,12 +942,12 @@ ResultVal AppletManager::GetAppletManInfo( } } - return MakeResult({ + return AppletManInfo{ .active_applet_pos = active_applet_pos, .requested_applet_id = requested_applet_id, .home_menu_applet_id = AppletId::HomeMenu, .active_applet_id = active_applet_id, - }); + }; } ResultVal AppletManager::GetAppletInfo(AppletId app_id) { @@ -968,8 +967,13 @@ ResultVal AppletManager::GetAppletInfo(AppletId app_i auto media_type = ((slot_data->title_id >> 32) & 0xFFFFFFFF) == 0x00040000 ? Service::FS::MediaType::SDMC : Service::FS::MediaType::NAND; - return MakeResult({slot_data->title_id, media_type, slot_data->registered, - slot_data->loaded, slot_data->attributes.raw}); + return AppletInfo{ + .title_id = slot_data->title_id, + .media_type = media_type, + .registered = slot_data->registered, + .loaded = slot_data->loaded, + .attributes = slot_data->attributes.raw, + }; } ResultCode AppletManager::PrepareToDoApplicationJump(u64 title_id, FS::MediaType media_type, diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp index 94a46be4b..f6b27e122 100644 --- a/src/core/hle/service/cecd/cecd.cpp +++ b/src/core/hle/service/cecd/cecd.cpp @@ -1239,7 +1239,7 @@ void Module::CheckAndUpdateFile(const CecDataPathType path_type, const u32 ncch_ const u32 message_size = static_cast(message->GetSize()); std::vector buffer(message_size); - message->Read(0, message_size, buffer.data()).Unwrap(); + void(message->Read(0, message_size, buffer.data()).Unwrap()); message->Close(); std::memcpy(&message_headers[outbox_info_header.message_num++], buffer.data(), @@ -1329,7 +1329,7 @@ void Module::CheckAndUpdateFile(const CecDataPathType path_type, const u32 ncch_ const u32 message_size = static_cast(message->GetSize()); std::vector buffer(message_size); - message->Read(0, message_size, buffer.data()).Unwrap(); + void(message->Read(0, message_size, buffer.data()).Unwrap()); message->Close(); // Message id is at offset 0x20, and is 8 bytes diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index 3b2c6e113..0f00ddc0f 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -432,7 +432,7 @@ ResultVal Module::GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 f else pointer = &cfg_config_file_buffer[itr->offset_or_data]; - return MakeResult(pointer); + return pointer; } ResultCode Module::GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output) { diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 65e145344..3e58133ed 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -63,7 +63,7 @@ ResultVal ArchiveManager::OpenArchive(ArchiveIdCode id_code, ++next_handle; } handle_map.emplace(next_handle, std::move(res)); - return MakeResult(next_handle++); + return next_handle++; } ResultCode ArchiveManager::CloseArchive(ArchiveHandle handle) { @@ -103,7 +103,7 @@ ArchiveManager::OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys: } auto file = std::make_shared(system.Kernel(), std::move(backend).Unwrap(), path); - return std::make_pair(MakeResult(std::move(file)), open_timeout_ns); + return std::make_pair(std::move(file), open_timeout_ns); } ResultCode ArchiveManager::DeleteFileFromArchive(ArchiveHandle archive_handle, @@ -197,8 +197,7 @@ ResultVal> ArchiveManager::OpenDirectoryFromArchive( return backend.Code(); } - auto directory = std::make_shared(std::move(backend).Unwrap(), path); - return MakeResult(std::move(directory)); + return std::make_shared(std::move(backend).Unwrap(), path); } ResultVal ArchiveManager::GetFreeBytesInArchive(ArchiveHandle archive_handle) { @@ -206,7 +205,7 @@ ResultVal ArchiveManager::GetFreeBytesInArchive(ArchiveHandle archive_handl if (archive == nullptr) { return FileSys::ERR_INVALID_ARCHIVE_HANDLE; } - return MakeResult(archive->GetFreeBytes()); + return archive->GetFreeBytes(); } ResultCode ArchiveManager::FormatArchive(ArchiveIdCode id_code, @@ -314,7 +313,7 @@ ResultVal ArchiveManager::GetArchiveResource(MediaType media_ty resource.cluster_size_in_bytes = 16384; resource.partition_capacity_in_clusters = 0x80000; // 8GiB capacity resource.free_space_in_clusters = 0x80000; // 8GiB free - return MakeResult(resource); + return resource; } void ArchiveManager::RegisterArchiveTypes() { diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 0a6c3c887..54db4e5bd 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -845,11 +845,11 @@ ResultVal FS_USER::GetSpecialContentIndexFromGameCard(u64 title_id, Special switch (type) { case SpecialContentType::Update: - return MakeResult(static_cast(NCSDContentIndex::Update)); + return static_cast(NCSDContentIndex::Update); case SpecialContentType::Manual: - return MakeResult(static_cast(NCSDContentIndex::Manual)); + return static_cast(NCSDContentIndex::Manual); case SpecialContentType::DLPChild: - return MakeResult(static_cast(NCSDContentIndex::DLP)); + return static_cast(NCSDContentIndex::DLP); default: UNREACHABLE(); } @@ -874,9 +874,9 @@ ResultVal FS_USER::GetSpecialContentIndexFromTMD(MediaType media_type, u64 switch (type) { case SpecialContentType::Manual: - return MakeResult(static_cast(FileSys::TMDContentIndex::Manual)); + return static_cast(FileSys::TMDContentIndex::Manual); case SpecialContentType::DLPChild: - return MakeResult(static_cast(FileSys::TMDContentIndex::DLP)); + return static_cast(FileSys::TMDContentIndex::DLP); default: ASSERT(false); } diff --git a/src/core/hle/service/ldr_ro/cro_helper.cpp b/src/core/hle/service/ldr_ro/cro_helper.cpp index 73713a3b6..bdeb89d30 100644 --- a/src/core/hle/service/ldr_ro/cro_helper.cpp +++ b/src/core/hle/service/ldr_ro/cro_helper.cpp @@ -301,7 +301,7 @@ ResultVal CROHelper::RebaseSegmentTable(u32 cro_size, VAddr data_segment_ } SetEntry(system.Memory(), i, segment); } - return MakeResult(prev_data_segment + module_address); + return prev_data_segment + module_address; } ResultCode CROHelper::RebaseExportNamedSymbolTable() { @@ -776,10 +776,10 @@ ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) { return result; } - return MakeResult(false); + return false; } - return MakeResult(true); + return true; }); if (result.IsError()) { return result; @@ -897,9 +897,9 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) { return result; } } - return MakeResult(false); + return false; } - return MakeResult(true); + return true; }); if (result.IsError()) { return result; @@ -1090,10 +1090,10 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) { return result; } - return MakeResult(false); + return false; } - return MakeResult(true); + return true; }); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error applying exit relocation {:08X}", result.raw); @@ -1317,7 +1317,7 @@ ResultCode CROHelper::Link(VAddr crs_address, bool link_on_load_bug_fix) { if (result.IsError()) return result; - return MakeResult(true); + return true; }); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error applying export {:08X}", result.raw); @@ -1362,7 +1362,7 @@ ResultCode CROHelper::Unlink(VAddr crs_address) { if (result.IsError()) return result; - return MakeResult(true); + return true; }); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error resetting export {:08X}", result.raw); diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp index 311dfd72b..857a6ba79 100644 --- a/src/core/hle/service/nwm/nwm_uds.cpp +++ b/src/core/hle/service/nwm/nwm_uds.cpp @@ -673,7 +673,7 @@ ResultVal> NWM_UDS::Initialize( channel_data.clear(); } - return MakeResult(connection_status_event); + return connection_status_event; } void NWM_UDS::InitializeWithVersion(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/plgldr/plgldr.cpp b/src/core/hle/service/plgldr/plgldr.cpp index 00c5cb01a..62379dd8b 100644 --- a/src/core/hle/service/plgldr/plgldr.cpp +++ b/src/core/hle/service/plgldr/plgldr.cpp @@ -131,7 +131,7 @@ void PLG_LDR::OnProcessExit(Kernel::Process& process, Kernel::KernelSystem& kern ResultVal PLG_LDR::GetMemoryChangedHandle(Kernel::KernelSystem& kernel) { if (plgldr_context.memory_changed_handle) - return MakeResult(plgldr_context.memory_changed_handle); + return plgldr_context.memory_changed_handle; std::shared_ptr evt = kernel.CreateEvent( Kernel::ResetType::OneShot, @@ -139,7 +139,7 @@ ResultVal PLG_LDR::GetMemoryChangedHandle(Kernel::KernelSystem& CASCADE_RESULT(plgldr_context.memory_changed_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(evt))); - return MakeResult(plgldr_context.memory_changed_handle); + return plgldr_context.memory_changed_handle; } void PLG_LDR::OnMemoryChanged(Kernel::Process& process, Kernel::KernelSystem& kernel) { diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 3caca2f93..25ca1d248 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -44,7 +44,7 @@ ResultVal> ServiceManager::RegisterService( registered_services_inverse.emplace(client_port->GetObjectId(), name); registered_services.emplace(std::move(name), std::move(client_port)); - return MakeResult(std::move(server_port)); + return server_port; } ResultVal> ServiceManager::GetServicePort( @@ -56,7 +56,7 @@ ResultVal> ServiceManager::GetServicePort( return ERR_SERVICE_NOT_REGISTERED; } - return MakeResult(it->second); + return it->second; } ResultVal> ServiceManager::ConnectToService(