From 3d0a0ccc0b9cddb48059b4dc020cd7cac0aca0ac Mon Sep 17 00:00:00 2001
From: Wunkolo <Wunkolo@gmail.com>
Date: Mon, 11 Mar 2024 09:55:00 -0700
Subject: [PATCH] Refactor `Rust::Result` into `std::expected`

The standard library already has support for this type as of C++23:
https://en.cppreference.com/w/cpp/header/expected

[This is also supported by all major compilers](https://en.cppreference.com/w/cpp/compiler_support#:~:text=Yes-,%3Cexpected%3E,-P0323R12%0AP2549R1)
---
 CMakeLists.txt                           |   3 +-
 include/fs/archive_base.hpp              | 285 ++++---
 include/fs/archive_ext_save_data.hpp     |  20 +-
 include/fs/archive_ncch.hpp              |   9 +-
 include/fs/archive_save_data.hpp         |  14 +-
 include/fs/archive_sdmc.hpp              |   4 +-
 include/fs/archive_self_ncch.hpp         |   4 +-
 include/fs/archive_system_save_data.hpp  |   4 +-
 include/fs/archive_user_save_data.hpp    |   7 +-
 include/services/fs.hpp                  |   6 +-
 src/core/fs/archive_ext_save_data.cpp    |  42 +-
 src/core/fs/archive_ncch.cpp             |  60 +-
 src/core/fs/archive_save_data.cpp        |  38 +-
 src/core/fs/archive_sdmc.cpp             |  17 +-
 src/core/fs/archive_self_ncch.cpp        |  11 +-
 src/core/fs/archive_system_save_data.cpp |  20 +-
 src/core/fs/archive_user_save_data.cpp   |  30 +-
 src/core/services/fs.cpp                 | 153 ++--
 third_party/result/LICENSE               | 201 -----
 third_party/result/README.md             | 132 ----
 third_party/result/include/result.hpp    | 910 -----------------------
 21 files changed, 349 insertions(+), 1621 deletions(-)
 delete mode 100644 third_party/result/LICENSE
 delete mode 100644 third_party/result/README.md
 delete mode 100644 third_party/result/include/result.hpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4dbe438f..5c9dd83b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,7 +6,7 @@ else()
     cmake_minimum_required(VERSION 3.10)
 endif()
 
-set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD 23)
 set(CMAKE_CXX_STANDARD_REQUIRED True)
 
 if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 12)
@@ -49,7 +49,6 @@ include_directories(third_party/imgui/)
 include_directories(third_party/dynarmic/src)
 include_directories(third_party/cryptopp/)
 include_directories(third_party/cityhash/include)
-include_directories(third_party/result/include)
 include_directories(third_party/xxhash/include)
 include_directories(third_party/httplib)
 include_directories(third_party/stb)
diff --git a/include/fs/archive_base.hpp b/include/fs/archive_base.hpp
index 2843be68..b613a11d 100644
--- a/include/fs/archive_base.hpp
+++ b/include/fs/archive_base.hpp
@@ -2,26 +2,27 @@
 #include <cassert>
 #include <cstdio>
 #include <cstring>
+#include <expected>
 #include <filesystem>
 #include <optional>
 #include <string>
 #include <type_traits>
 #include <vector>
+
 #include "helpers.hpp"
 #include "memory.hpp"
-#include "result.hpp"
 #include "result/result.hpp"
 
 using Result::HorizonResult;
 
 namespace PathType {
-    enum : u32 {
-        Invalid = 0,
-        Empty = 1,
-        Binary = 2,
-        ASCII = 3,
-        UTF16 = 4,
-    };
+	enum : u32 {
+		Invalid = 0,
+		Empty = 1,
+		Binary = 2,
+		ASCII = 3,
+		UTF16 = 4,
+	};
 }
 
 namespace ArchiveID {
@@ -42,83 +43,81 @@ namespace ArchiveID {
 		UserSaveData2 = 0x567890B4,
 	};
 
-    static std::string toString(u32 id) {
-        switch (id) {
-            case SelfNCCH: return "SelfNCCH";
-            case SaveData: return "SaveData";
-            case ExtSaveData: return "ExtSaveData";
-            case SharedExtSaveData: return "SharedExtSaveData";
-            case SystemSaveData: return "SystemSaveData";
-            case SDMC: return "SDMC";
-            case SDMCWriteOnly: return "SDMC (Write-only)";
-            case SavedataAndNcch: return "Savedata & NCCH (archive 0x2345678A)";
-            default: return "Unknown archive";
-        }
-    }
-}
+	static std::string toString(u32 id) {
+		switch (id) {
+			case SelfNCCH: return "SelfNCCH";
+			case SaveData: return "SaveData";
+			case ExtSaveData: return "ExtSaveData";
+			case SharedExtSaveData: return "SharedExtSaveData";
+			case SystemSaveData: return "SystemSaveData";
+			case SDMC: return "SDMC";
+			case SDMCWriteOnly: return "SDMC (Write-only)";
+			case SavedataAndNcch: return "Savedata & NCCH (archive 0x2345678A)";
+			default: return "Unknown archive";
+		}
+	}
+}  // namespace ArchiveID
 
 struct FSPath {
-    u32 type = PathType::Invalid;
+	u32 type = PathType::Invalid;
 
-    std::vector<u8> binary; // Path data for binary paths
-    std::string string; // Path data for ASCII paths
-    std::u16string utf16_string;
+	std::vector<u8> binary;  // Path data for binary paths
+	std::string string;      // Path data for ASCII paths
+	std::u16string utf16_string;
 
-    FSPath() {}
+	FSPath() {}
 
-    FSPath(u32 type, const std::vector<u8>& vec) : type(type) {
-        switch (type) {
-            case PathType::Binary:
-                binary = std::move(vec);
-                break;
+	FSPath(u32 type, const std::vector<u8>& vec) : type(type) {
+		switch (type) {
+			case PathType::Binary: binary = std::move(vec); break;
 
-            case PathType::ASCII:
-                string.resize(vec.size() - 1); // -1 because of the null terminator
-                std::memcpy(string.data(), vec.data(), vec.size() - 1); // Copy string data
-                break;
+			case PathType::ASCII:
+				string.resize(vec.size() - 1);                           // -1 because of the null terminator
+				std::memcpy(string.data(), vec.data(), vec.size() - 1);  // Copy string data
+				break;
 
-            case PathType::UTF16: {
-                const size_t size = vec.size() / sizeof(u16) - 1; // Character count. -1 because null terminator here too
-                utf16_string.resize(size);
-                std::memcpy(utf16_string.data(), vec.data(), size * sizeof(u16));
-                break;
-            }
-;        }
-    }
+			case PathType::UTF16: {
+				const size_t size = vec.size() / sizeof(u16) - 1;  // Character count. -1 because null terminator here too
+				utf16_string.resize(size);
+				std::memcpy(utf16_string.data(), vec.data(), size * sizeof(u16));
+				break;
+			};
+		}
+	}
 };
 
 struct FilePerms {
-    u32 raw;
+	u32 raw;
 
-    FilePerms(u32 val) : raw(val) {}
-    bool read() const { return (raw & 1) != 0; }
-    bool write() const { return (raw & 2) != 0; }
-    bool create() const { return (raw & 4) != 0; }
+	FilePerms(u32 val) : raw(val) {}
+	bool read() const { return (raw & 1) != 0; }
+	bool write() const { return (raw & 2) != 0; }
+	bool create() const { return (raw & 4) != 0; }
 };
 
 class ArchiveBase;
 struct FileSession {
-    ArchiveBase* archive = nullptr;
-    FILE* fd = nullptr; // File descriptor for file sessions that require them.
-    FSPath path;
-    FSPath archivePath;
-    u32 priority = 0; // TODO: What does this even do
-    bool isOpen;
+	ArchiveBase* archive = nullptr;
+	FILE* fd = nullptr;  // File descriptor for file sessions that require them.
+	FSPath path;
+	FSPath archivePath;
+	u32 priority = 0;  // TODO: What does this even do
+	bool isOpen;
 
-    FileSession(ArchiveBase* archive, const FSPath& filePath, const FSPath& archivePath, FILE* fd, bool isOpen = true) :
-        archive(archive), path(filePath), archivePath(archivePath), fd(fd), isOpen(isOpen), priority(0) {}
+	FileSession(ArchiveBase* archive, const FSPath& filePath, const FSPath& archivePath, FILE* fd, bool isOpen = true)
+		: archive(archive), path(filePath), archivePath(archivePath), fd(fd), isOpen(isOpen), priority(0) {}
 
-    // For cloning a file session
-    FileSession(const FileSession& other) : archive(other.archive), path(other.path),
-        archivePath(other.archivePath), fd(other.fd), isOpen(other.isOpen), priority(other.priority) {}
+	// For cloning a file session
+	FileSession(const FileSession& other)
+		: archive(other.archive), path(other.path), archivePath(other.archivePath), fd(other.fd), isOpen(other.isOpen), priority(other.priority) {}
 };
 
 struct ArchiveSession {
-    ArchiveBase* archive = nullptr;
-    FSPath path;
-    bool isOpen;
+	ArchiveBase* archive = nullptr;
+	FSPath path;
+	bool isOpen;
 
-    ArchiveSession(ArchiveBase* archive, const FSPath& filePath, bool isOpen = true) : archive(archive), path(filePath), isOpen(isOpen) {}
+	ArchiveSession(ArchiveBase* archive, const FSPath& filePath, bool isOpen = true) : archive(archive), path(filePath), isOpen(isOpen) {}
 };
 
 struct DirectoryEntry {
@@ -156,106 +155,104 @@ struct DirectorySession {
 using FileDescriptor = std::optional<FILE*>;
 
 class ArchiveBase {
-public:
-    struct FormatInfo {
-        u32 size; // Archive size
-        u32 numOfDirectories; // Number of directories
-        u32 numOfFiles;       // Number of files
-        bool duplicateData;   // Whether to duplicate data or not
-    };
+  public:
+	struct FormatInfo {
+		u32 size;              // Archive size
+		u32 numOfDirectories;  // Number of directories
+		u32 numOfFiles;        // Number of files
+		bool duplicateData;    // Whether to duplicate data or not
+	};
 
-protected:
-    using Handle = u32;
+  protected:
+	using Handle = u32;
 
-    static constexpr FileDescriptor NoFile = nullptr;
-    static constexpr FileDescriptor FileError = std::nullopt;
-    Memory& mem;
+	static constexpr FileDescriptor NoFile = nullptr;
+	static constexpr FileDescriptor FileError = std::nullopt;
+	Memory& mem;
 
-    // Returns if a specified 3DS path in UTF16 or ASCII format is safe or not
-    // A 3DS path is considered safe if its first character is '/' which means we're not trying to access anything outside the root of the fs
-    // And if it doesn't contain enough instances of ".." (Indicating "climb up a folder" in filesystems) to let the software climb up the directory tree
-    // And access files outside of the emulator's app data folder
-    template <u32 format>
-    bool isPathSafe(const FSPath& path) {
-        static_assert(format == PathType::ASCII || format == PathType::UTF16);
-        using String = typename std::conditional<format == PathType::UTF16, std::u16string, std::string>::type; // String type for the path
-        using Char = typename String::value_type; // Char type for the path
+	// Returns if a specified 3DS path in UTF16 or ASCII format is safe or not
+	// A 3DS path is considered safe if its first character is '/' which means we're not trying to access anything outside the root of the fs
+	// And if it doesn't contain enough instances of ".." (Indicating "climb up a folder" in filesystems) to let the software climb up the directory
+	// tree And access files outside of the emulator's app data folder
+	template <u32 format>
+	bool isPathSafe(const FSPath& path) {
+		static_assert(format == PathType::ASCII || format == PathType::UTF16);
+		using String = typename std::conditional<format == PathType::UTF16, std::u16string, std::string>::type;  // String type for the path
+		using Char = typename String::value_type;                                                                // Char type for the path
 
-        String pathString, dots;
-        if constexpr (std::is_same<String, std::u16string>()) {
-            pathString = path.utf16_string;
-            dots = u"..";
-        } else {
-            pathString = path.string;
-            dots = "..";
-        }
+		String pathString, dots;
+		if constexpr (std::is_same<String, std::u16string>()) {
+			pathString = path.utf16_string;
+			dots = u"..";
+		} else {
+			pathString = path.string;
+			dots = "..";
+		}
 
-        // If the path string doesn't begin with / then that means it's accessing outside the FS root, which is invalid & unsafe
-        if (pathString[0] != Char('/')) return false;
+		// If the path string doesn't begin with / then that means it's accessing outside the FS root, which is invalid & unsafe
+		if (pathString[0] != Char('/')) return false;
 
-        // Counts how many folders sans the root our file is nested under.
-        // If it's < 0 at any point of parsing, then the path is unsafe and tries to crawl outside our file sandbox.
-        // If it's 0 then this is the FS root.
-        // If it's > 0 then we're in a subdirectory of the root.
-        int level = 0;
+		// Counts how many folders sans the root our file is nested under.
+		// If it's < 0 at any point of parsing, then the path is unsafe and tries to crawl outside our file sandbox.
+		// If it's 0 then this is the FS root.
+		// If it's > 0 then we're in a subdirectory of the root.
+		int level = 0;
 
-        // Split the string on / characters and see how many of the substrings are ".."
-        size_t pos = 0;
-        while ((pos = pathString.find(Char('/'))) != String::npos) {
-            String token = pathString.substr(0, pos);
-            pathString.erase(0, pos + 1);
+		// Split the string on / characters and see how many of the substrings are ".."
+		size_t pos = 0;
+		while ((pos = pathString.find(Char('/'))) != String::npos) {
+			String token = pathString.substr(0, pos);
+			pathString.erase(0, pos + 1);
 
-            if (token == dots) {
-                level--;
-                if (level < 0) return false;
-            } else {
-                level++;
-            }
-        }
+			if (token == dots) {
+				level--;
+				if (level < 0) return false;
+			} else {
+				level++;
+			}
+		}
 
-        return true;
-    }
+		return true;
+	}
 
-public:
-    virtual std::string name() = 0;
-    virtual u64 getFreeBytes() = 0;
-    virtual HorizonResult createFile(const FSPath& path, u64 size) = 0;
-    virtual HorizonResult deleteFile(const FSPath& path) = 0;
+  public:
+	virtual std::string name() = 0;
+	virtual u64 getFreeBytes() = 0;
+	virtual HorizonResult createFile(const FSPath& path, u64 size) = 0;
+	virtual HorizonResult deleteFile(const FSPath& path) = 0;
 
-    virtual Rust::Result<FormatInfo, HorizonResult> getFormatInfo(const FSPath& path) {
-        Helpers::panic("Unimplemented GetFormatInfo for %s archive", name().c_str());
-        // Return a dummy struct just to avoid the UB of not returning anything, even if we panic
-        return Ok(FormatInfo{ .size = 0, .numOfDirectories = 0, .numOfFiles = 0, .duplicateData = false });
-    }
+	virtual std::expected<FormatInfo, HorizonResult> getFormatInfo(const FSPath& path) {
+		Helpers::panic("Unimplemented GetFormatInfo for %s archive", name().c_str());
+		// Return a dummy struct just to avoid the UB of not returning anything, even if we panic
+		return FormatInfo{.size = 0, .numOfDirectories = 0, .numOfFiles = 0, .duplicateData = false};
+	}
 
-    virtual HorizonResult createDirectory(const FSPath& path) {
-        Helpers::panic("Unimplemented CreateDirectory for %s archive", name().c_str());
-        return Result::FS::AlreadyExists;
-    }
+	virtual HorizonResult createDirectory(const FSPath& path) {
+		Helpers::panic("Unimplemented CreateDirectory for %s archive", name().c_str());
+		return Result::FS::AlreadyExists;
+	}
 
-    // Returns nullopt if opening the file failed, otherwise returns a file descriptor to it (nullptr if none is needed)
-    virtual FileDescriptor openFile(const FSPath& path, const FilePerms& perms) = 0;
-    virtual Rust::Result<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) = 0;
+	// Returns nullopt if opening the file failed, otherwise returns a file descriptor to it (nullptr if none is needed)
+	virtual FileDescriptor openFile(const FSPath& path, const FilePerms& perms) = 0;
+	virtual std::expected<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) = 0;
 
-    virtual Rust::Result<DirectorySession, HorizonResult> openDirectory(const FSPath& path) {
-        Helpers::panic("Unimplemented OpenDirectory for %s archive", name().c_str());
-        return Err(Result::FS::FileNotFoundAlt);
-    }
+	virtual std::expected<DirectorySession, HorizonResult> openDirectory(const FSPath& path) {
+		Helpers::panic("Unimplemented OpenDirectory for %s archive", name().c_str());
+		return std::unexpected(Result::FS::FileNotFoundAlt);
+	}
 
-    virtual void format(const FSPath& path, const FormatInfo& info) {
-        Helpers::panic("Unimplemented Format for %s archive", name().c_str());
-    }
+	virtual void format(const FSPath& path, const FormatInfo& info) { Helpers::panic("Unimplemented Format for %s archive", name().c_str()); }
 
-    virtual HorizonResult renameFile(const FSPath& oldPath, const FSPath& newPath) {
+	virtual HorizonResult renameFile(const FSPath& oldPath, const FSPath& newPath) {
 		Helpers::panic("Unimplemented RenameFile for %s archive", name().c_str());
 		return Result::Success;
-    }
+	}
 
-    // Read size bytes from a file starting at offset "offset" into a certain buffer in memory
-    // Returns the number of bytes read, or nullopt if the read failed
-    virtual std::optional<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) = 0;
+	// Read size bytes from a file starting at offset "offset" into a certain buffer in memory
+	// Returns the number of bytes read, or nullopt if the read failed
+	virtual std::optional<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) = 0;
 
-    ArchiveBase(Memory& mem) : mem(mem) {}
+	ArchiveBase(Memory& mem) : mem(mem) {}
 };
 
 struct ArchiveResource {
diff --git a/include/fs/archive_ext_save_data.hpp b/include/fs/archive_ext_save_data.hpp
index 7c8c7503..5c150d9b 100644
--- a/include/fs/archive_ext_save_data.hpp
+++ b/include/fs/archive_ext_save_data.hpp
@@ -2,11 +2,13 @@
 #include "archive_base.hpp"
 
 class ExtSaveDataArchive : public ArchiveBase {
-public:
-	ExtSaveDataArchive(Memory& mem, const std::string& folder, bool isShared = false) : ArchiveBase(mem),
-		isShared(isShared), backingFolder(folder) {}
+  public:
+	ExtSaveDataArchive(Memory& mem, const std::string& folder, bool isShared = false) : ArchiveBase(mem), isShared(isShared), backingFolder(folder) {}
 
-	u64 getFreeBytes() override { Helpers::panic("ExtSaveData::GetFreeBytes unimplemented"); return 0;  }
+	u64 getFreeBytes() override {
+		Helpers::panic("ExtSaveData::GetFreeBytes unimplemented");
+		return 0;
+	}
 	std::string name() override { return "ExtSaveData::" + backingFolder; }
 
 	HorizonResult createDirectory(const FSPath& path) override;
@@ -14,14 +16,14 @@ public:
 	HorizonResult deleteFile(const FSPath& path) override;
 	HorizonResult renameFile(const FSPath& oldPath, const FSPath& newPath) override;
 
-	Rust::Result<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
-	Rust::Result<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;
+	std::expected<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
+	std::expected<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;
 	FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;
 	std::optional<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override;
 
-	Rust::Result<FormatInfo, HorizonResult> getFormatInfo(const FSPath& path) override {
+	std::expected<FormatInfo, HorizonResult> getFormatInfo(const FSPath& path) override {
 		Helpers::warn("Stubbed ExtSaveData::GetFormatInfo");
-		return Ok(FormatInfo{.size = 1_GB, .numOfDirectories = 255, .numOfFiles = 255, .duplicateData = false});
+		return FormatInfo{.size = 1_GB, .numOfDirectories = 255, .numOfFiles = 255, .duplicateData = false};
 	}
 
 	// Takes in a binary ExtSaveData path, outputs a combination of the backing folder with the low and high save entries of the path
@@ -29,5 +31,5 @@ public:
 	std::string getExtSaveDataPathFromBinary(const FSPath& path);
 
 	bool isShared = false;
-	std::string backingFolder; // Backing folder for the archive. Can be NAND, Gamecard or SD depending on the archive path.
+	std::string backingFolder;  // Backing folder for the archive. Can be NAND, Gamecard or SD depending on the archive path.
 };
\ No newline at end of file
diff --git a/include/fs/archive_ncch.hpp b/include/fs/archive_ncch.hpp
index 275bcd20..ebe42c8b 100644
--- a/include/fs/archive_ncch.hpp
+++ b/include/fs/archive_ncch.hpp
@@ -2,16 +2,19 @@
 #include "archive_base.hpp"
 
 class NCCHArchive : public ArchiveBase {
-public:
+  public:
 	NCCHArchive(Memory& mem) : ArchiveBase(mem) {}
 
-	u64 getFreeBytes() override { Helpers::panic("NCCH::GetFreeBytes unimplemented"); return 0;  }
+	u64 getFreeBytes() override {
+		Helpers::panic("NCCH::GetFreeBytes unimplemented");
+		return 0;
+	}
 	std::string name() override { return "NCCH"; }
 
 	HorizonResult createFile(const FSPath& path, u64 size) override;
 	HorizonResult deleteFile(const FSPath& path) override;
 
-	Rust::Result<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
+	std::expected<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
 	FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;
 	std::optional<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override;
 
diff --git a/include/fs/archive_save_data.hpp b/include/fs/archive_save_data.hpp
index 5b1ba489..50b604c8 100644
--- a/include/fs/archive_save_data.hpp
+++ b/include/fs/archive_save_data.hpp
@@ -2,7 +2,7 @@
 #include "archive_base.hpp"
 
 class SaveDataArchive : public ArchiveBase {
-public:
+  public:
 	SaveDataArchive(Memory& mem) : ArchiveBase(mem) {}
 
 	u64 getFreeBytes() override { return 32_MB; }
@@ -12,21 +12,19 @@ public:
 	HorizonResult createFile(const FSPath& path, u64 size) override;
 	HorizonResult deleteFile(const FSPath& path) override;
 
-	Rust::Result<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
-	Rust::Result<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;
+	std::expected<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
+	std::expected<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;
 	FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;
 	std::optional<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override;
 
 	void format(const FSPath& path, const FormatInfo& info) override;
-	Rust::Result<FormatInfo, HorizonResult> getFormatInfo(const FSPath& path) override;
+	std::expected<FormatInfo, HorizonResult> getFormatInfo(const FSPath& path) override;
 
-	std::filesystem::path getFormatInfoPath() {
-		return IOFile::getAppData() / "FormatInfo" / "SaveData.format";
-	}
+	std::filesystem::path getFormatInfoPath() { return IOFile::getAppData() / "FormatInfo" / "SaveData.format"; }
 
 	// Returns whether the cart has save data or not
 	bool cartHasSaveData() {
 		auto cxi = mem.getCXI();
-		return (cxi != nullptr && cxi->hasSaveData()); // We need to have a CXI file with more than 0 bytes of save data
+		return (cxi != nullptr && cxi->hasSaveData());  // We need to have a CXI file with more than 0 bytes of save data
 	}
 };
\ No newline at end of file
diff --git a/include/fs/archive_sdmc.hpp b/include/fs/archive_sdmc.hpp
index f63731c4..f0a13889 100644
--- a/include/fs/archive_sdmc.hpp
+++ b/include/fs/archive_sdmc.hpp
@@ -17,8 +17,8 @@ class SDMCArchive : public ArchiveBase {
 	HorizonResult deleteFile(const FSPath& path) override;
 	HorizonResult createDirectory(const FSPath& path) override;
 
-	Rust::Result<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
-	Rust::Result<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;
+	std::expected<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
+	std::expected<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;
 
 	FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;
 	std::optional<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override;
diff --git a/include/fs/archive_self_ncch.hpp b/include/fs/archive_self_ncch.hpp
index ed882a7d..053ee4a5 100644
--- a/include/fs/archive_self_ncch.hpp
+++ b/include/fs/archive_self_ncch.hpp
@@ -2,7 +2,7 @@
 #include "archive_base.hpp"
 
 class SelfNCCHArchive : public ArchiveBase {
-public:
+  public:
 	SelfNCCHArchive(Memory& mem) : ArchiveBase(mem) {}
 
 	u64 getFreeBytes() override { return 0; }
@@ -11,7 +11,7 @@ public:
 	HorizonResult createFile(const FSPath& path, u64 size) override;
 	HorizonResult deleteFile(const FSPath& path) override;
 
-	Rust::Result<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
+	std::expected<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
 	FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;
 	std::optional<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override;
 
diff --git a/include/fs/archive_system_save_data.hpp b/include/fs/archive_system_save_data.hpp
index c4526bec..0d374238 100644
--- a/include/fs/archive_system_save_data.hpp
+++ b/include/fs/archive_system_save_data.hpp
@@ -16,8 +16,8 @@ class SystemSaveDataArchive : public ArchiveBase {
 	HorizonResult createFile(const FSPath& path, u64 size) override;
 	HorizonResult deleteFile(const FSPath& path) override;
 
-	Rust::Result<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
-	Rust::Result<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;
+	std::expected<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
+	std::expected<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;
 
 	FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;
 
diff --git a/include/fs/archive_user_save_data.hpp b/include/fs/archive_user_save_data.hpp
index 56e2c0f6..58db296d 100644
--- a/include/fs/archive_user_save_data.hpp
+++ b/include/fs/archive_user_save_data.hpp
@@ -3,6 +3,7 @@
 
 class UserSaveDataArchive : public ArchiveBase {
 	u32 archiveID;
+
   public:
 	UserSaveDataArchive(Memory& mem, u32 archiveID) : ArchiveBase(mem), archiveID(archiveID) {}
 
@@ -13,13 +14,13 @@ class UserSaveDataArchive : public ArchiveBase {
 	HorizonResult createFile(const FSPath& path, u64 size) override;
 	HorizonResult deleteFile(const FSPath& path) override;
 
-	Rust::Result<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
-	Rust::Result<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;
+	std::expected<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
+	std::expected<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;
 	FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;
 	std::optional<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override;
 
 	void format(const FSPath& path, const FormatInfo& info) override;
-	Rust::Result<FormatInfo, HorizonResult> getFormatInfo(const FSPath& path) override;
+	std::expected<FormatInfo, HorizonResult> getFormatInfo(const FSPath& path) override;
 
 	std::filesystem::path getFormatInfoPath() { return IOFile::getAppData() / "FormatInfo" / "SaveData.format"; }
 
diff --git a/include/services/fs.hpp b/include/services/fs.hpp
index 4a613121..2f721f9d 100644
--- a/include/services/fs.hpp
+++ b/include/services/fs.hpp
@@ -38,8 +38,8 @@ class FSService {
 	SystemSaveDataArchive systemSaveData;
 
 	ArchiveBase* getArchiveFromID(u32 id, const FSPath& archivePath);
-	Rust::Result<Handle, HorizonResult> openArchiveHandle(u32 archiveID, const FSPath& path);
-	Rust::Result<Handle, HorizonResult> openDirectoryHandle(ArchiveBase* archive, const FSPath& path);
+	std::expected<Handle, HorizonResult> openArchiveHandle(u32 archiveID, const FSPath& path);
+	std::expected<Handle, HorizonResult> openDirectoryHandle(ArchiveBase* archive, const FSPath& path);
 	std::optional<Handle> openFileHandle(ArchiveBase* archive, const FSPath& path, const FSPath& archivePath, const FilePerms& perms);
 	FSPath readPath(u32 type, u32 pointer, u32 size);
 
@@ -81,7 +81,7 @@ class FSService {
 	// Used for set/get priority: Not sure what sort of priority this is referring to
 	u32 priority;
 
-public:
+  public:
 	FSService(Memory& mem, Kernel& kernel, const EmulatorConfig& config)
 		: mem(mem), saveData(mem), sharedExtSaveData_nand(mem, "../SharedFiles/NAND", true), extSaveData_sdmc(mem, "SDMC"), sdmc(mem),
 		  sdmcWriteOnly(mem, true), selfNcch(mem), ncch(mem), userSaveData1(mem, ArchiveID::UserSaveData1),
diff --git a/src/core/fs/archive_ext_save_data.cpp b/src/core/fs/archive_ext_save_data.cpp
index 4b57f245..b84242d7 100644
--- a/src/core/fs/archive_ext_save_data.cpp
+++ b/src/core/fs/archive_ext_save_data.cpp
@@ -1,21 +1,19 @@
 #include "fs/archive_ext_save_data.hpp"
+
 #include <memory>
 
 namespace fs = std::filesystem;
 
 HorizonResult ExtSaveDataArchive::createFile(const FSPath& path, u64 size) {
-	if (size == 0)
-		Helpers::panic("ExtSaveData file does not support size == 0");
+	if (size == 0) Helpers::panic("ExtSaveData file does not support size == 0");
 
 	if (path.type == PathType::UTF16) {
-		if (!isPathSafe<PathType::UTF16>(path))
-			Helpers::panic("Unsafe path in ExtSaveData::CreateFile");
+		if (!isPathSafe<PathType::UTF16>(path)) Helpers::panic("Unsafe path in ExtSaveData::CreateFile");
 
 		fs::path p = IOFile::getAppData() / backingFolder;
 		p += fs::path(path.utf16_string).make_preferred();
 
-		if (fs::exists(p))
-			return Result::FS::AlreadyExists;
+		if (fs::exists(p)) return Result::FS::AlreadyExists;
 
 		// Create a file of size "size" by creating an empty one, seeking to size - 1 and just writing a 0 there
 		IOFile file(p.string().c_str(), "wb");
@@ -34,8 +32,7 @@ HorizonResult ExtSaveDataArchive::createFile(const FSPath& path, u64 size) {
 
 HorizonResult ExtSaveDataArchive::deleteFile(const FSPath& path) {
 	if (path.type == PathType::UTF16) {
-		if (!isPathSafe<PathType::UTF16>(path))
-			Helpers::panic("Unsafe path in ExtSaveData::DeleteFile");
+		if (!isPathSafe<PathType::UTF16>(path)) Helpers::panic("Unsafe path in ExtSaveData::DeleteFile");
 
 		fs::path p = IOFile::getAppData() / backingFolder;
 		p += fs::path(path.utf16_string).make_preferred();
@@ -66,17 +63,15 @@ HorizonResult ExtSaveDataArchive::deleteFile(const FSPath& path) {
 
 FileDescriptor ExtSaveDataArchive::openFile(const FSPath& path, const FilePerms& perms) {
 	if (path.type == PathType::UTF16) {
-		if (!isPathSafe<PathType::UTF16>(path))
-			Helpers::panic("Unsafe path in ExtSaveData::OpenFile");
+		if (!isPathSafe<PathType::UTF16>(path)) Helpers::panic("Unsafe path in ExtSaveData::OpenFile");
 
-		if (perms.create())
-			Helpers::panic("[ExtSaveData] Can't open file with create flag");
+		if (perms.create()) Helpers::panic("[ExtSaveData] Can't open file with create flag");
 
 		fs::path p = IOFile::getAppData() / backingFolder;
 		p += fs::path(path.utf16_string).make_preferred();
 
-		if (fs::exists(p)) { // Return file descriptor if the file exists
-			IOFile file(p.string().c_str(), "r+b"); // According to Citra, this ignores the OpenFlags field and always opens as r+b? TODO: Check
+		if (fs::exists(p)) {                         // Return file descriptor if the file exists
+			IOFile file(p.string().c_str(), "r+b");  // According to Citra, this ignores the OpenFlags field and always opens as r+b? TODO: Check
 			return file.isOpen() ? file.getHandle() : FileError;
 		} else {
 			return FileError;
@@ -155,7 +150,7 @@ std::string ExtSaveDataArchive::getExtSaveDataPathFromBinary(const FSPath& path)
 	return backingFolder + std::to_string(saveLow) + std::to_string(saveHigh);
 }
 
-Rust::Result<ArchiveBase*, HorizonResult> ExtSaveDataArchive::openArchive(const FSPath& path) {
+std::expected<ArchiveBase*, HorizonResult> ExtSaveDataArchive::openArchive(const FSPath& path) {
 	if (path.type != PathType::Binary || path.binary.size() != 12) {
 		Helpers::panic("ExtSaveData accessed with an invalid path in OpenArchive");
 	}
@@ -165,34 +160,33 @@ Rust::Result<ArchiveBase*, HorizonResult> ExtSaveDataArchive::openArchive(const
 	// fs::path formatInfopath = IOFile::getAppData() / "FormatInfo" / (getExtSaveDataPathFromBinary(path) + ".format");
 	// Format info not found so the archive is not formatted
 	// if (!fs::is_regular_file(formatInfopath)) {
-	//	return isShared ? Err(Result::FS::NotFormatted) : Err(Result::FS::NotFoundInvalid);
+	//	return isShared ? std::unexpected(Result::FS::NotFormatted) : std::unexpected(Result::FS::NotFoundInvalid);
 	//}
 
-	return Ok((ArchiveBase*)this);
+	return (ArchiveBase*)this;
 }
 
-Rust::Result<DirectorySession, HorizonResult> ExtSaveDataArchive::openDirectory(const FSPath& path) {
+std::expected<DirectorySession, HorizonResult> ExtSaveDataArchive::openDirectory(const FSPath& path) {
 	if (path.type == PathType::UTF16) {
-		if (!isPathSafe<PathType::UTF16>(path))
-			Helpers::panic("Unsafe path in ExtSaveData::OpenDirectory");
+		if (!isPathSafe<PathType::UTF16>(path)) Helpers::panic("Unsafe path in ExtSaveData::OpenDirectory");
 
 		fs::path p = IOFile::getAppData() / backingFolder;
 		p += fs::path(path.utf16_string).make_preferred();
 
 		if (fs::is_regular_file(p)) {
 			printf("ExtSaveData: OpenArchive used with a file path");
-			return Err(Result::FS::UnexpectedFileOrDir);
+			return std::unexpected(Result::FS::UnexpectedFileOrDir);
 		}
 
 		if (fs::is_directory(p)) {
-			return Ok(DirectorySession(this, p));
+			return DirectorySession(this, p);
 		} else {
-			return Err(Result::FS::FileNotFoundAlt);
+			return std::unexpected(Result::FS::FileNotFoundAlt);
 		}
 	}
 
 	Helpers::panic("ExtSaveDataArchive::OpenDirectory: Unimplemented path type");
-	return Err(Result::Success);
+	return std::unexpected(Result::Success);
 }
 
 std::optional<u32> ExtSaveDataArchive::readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) {
diff --git a/src/core/fs/archive_ncch.cpp b/src/core/fs/archive_ncch.cpp
index d5a4bab5..d6a165fe 100644
--- a/src/core/fs/archive_ncch.cpp
+++ b/src/core/fs/archive_ncch.cpp
@@ -1,9 +1,11 @@
 #include "fs/archive_ncch.hpp"
+
+#include <algorithm>
+#include <memory>
+
 #include "fs/bad_word_list.hpp"
 #include "fs/country_list.hpp"
 #include "fs/mii_data.hpp"
-#include <algorithm>
-#include <memory>
 
 namespace PathType {
 	enum : u32 {
@@ -14,11 +16,7 @@ namespace PathType {
 };
 
 namespace MediaType {
-	enum : u8 {
-		NAND = 0,
-		SD = 1,
-		Gamecard = 2
-	};
+	enum : u8 { NAND = 0, SD = 1, Gamecard = 2 };
 };
 
 HorizonResult NCCHArchive::createFile(const FSPath& path, u64 size) {
@@ -36,39 +34,36 @@ FileDescriptor NCCHArchive::openFile(const FSPath& path, const FilePerms& perms)
 		Helpers::panic("NCCHArchive::OpenFile: Invalid path");
 	}
 
-	const u32 media = *(u32*)&path.binary[0]; // 0 for NCCH, 1 for SaveData
-	if (media != 0)
-		Helpers::panic("NCCHArchive::OpenFile: Tried to read non-NCCH file");
+	const u32 media = *(u32*)&path.binary[0];  // 0 for NCCH, 1 for SaveData
+	if (media != 0) Helpers::panic("NCCHArchive::OpenFile: Tried to read non-NCCH file");
 
 	// Third word of the binary path indicates what we're reading from.
 	const u32 type = *(u32*)&path.binary[8];
-	if (media == 0 && type > 2)
-		Helpers::panic("NCCHArchive::OpenFile: Invalid file path type");
+	if (media == 0 && type > 2) Helpers::panic("NCCHArchive::OpenFile: Invalid file path type");
 
 	return NoFile;
 }
 
-Rust::Result<ArchiveBase*, HorizonResult> NCCHArchive::openArchive(const FSPath& path) {
+std::expected<ArchiveBase*, HorizonResult> NCCHArchive::openArchive(const FSPath& path) {
 	if (path.type != PathType::Binary || path.binary.size() != 16) {
 		Helpers::panic("NCCHArchive::OpenArchive: Invalid path");
 	}
 
 	const u32 mediaType = path.binary[8];
-	if (mediaType != 0)
-		Helpers::panic("NCCH archive. Tried to access a mediatype other than the NAND. Type: %d", mediaType);
+	if (mediaType != 0) Helpers::panic("NCCH archive. Tried to access a mediatype other than the NAND. Type: %d", mediaType);
 
-	return Ok((ArchiveBase*)this);
+	return (ArchiveBase*)this;
 }
 
 std::optional<u32> NCCHArchive::readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) {
-	const auto& path = file->path.binary; // Path of the file
-	const auto& archivePath = file->archivePath.binary; // Path of the archive
+	const auto& path = file->path.binary;                // Path of the file
+	const auto& archivePath = file->archivePath.binary;  // Path of the archive
 
 	const auto mediaType = archivePath[8];
 
-	const auto media = *(u32*)&path[0]; // 0 for NCCH, 1 for savedata
+	const auto media = *(u32*)&path[0];  // 0 for NCCH, 1 for savedata
 	const auto partition = *(u32*)&path[4];
-	const auto type = *(u32*)&path[8]; // Type of the path
+	const auto type = *(u32*)&path[8];  // Type of the path
 
 	if (mediaType == MediaType::NAND) {
 		const u32 lowProgramID = *(u32*)&archivePath[0];
@@ -87,26 +82,29 @@ std::optional<u32> NCCHArchive::readFile(FileSession* file, u64 offset, u32 size
 		std::vector<u8> fileData;
 
 		if (highProgramID == sharedDataArchive) {
-			if (lowProgramID == miiData) fileData = std::vector<u8>(std::begin(MII_DATA), std::end(MII_DATA));
-			else if (lowProgramID == regionManifest) fileData = std::vector<u8>(std::begin(COUNTRY_LIST_DATA), std::end(COUNTRY_LIST_DATA));
+			if (lowProgramID == miiData)
+				fileData = std::vector<u8>(std::begin(MII_DATA), std::end(MII_DATA));
+			else if (lowProgramID == regionManifest)
+				fileData = std::vector<u8>(std::begin(COUNTRY_LIST_DATA), std::end(COUNTRY_LIST_DATA));
 			else if (lowProgramID == tlsRootCertificates) {
 				Helpers::warn("Read from Shared Data archive 00010602");
 				return 0;
-			}
-			else Helpers::panic("[NCCH archive] Read unimplemented NAND file. ID: %08X", lowProgramID);
+			} else
+				Helpers::panic("[NCCH archive] Read unimplemented NAND file. ID: %08X", lowProgramID);
 		} else if (highProgramID == systemDataArchive && lowProgramID == badWordList) {
 			fileData = std::vector<u8>(std::begin(BAD_WORD_LIST_DATA), std::end(BAD_WORD_LIST_DATA));
 		} else {
-			Helpers::panic("[NCCH archive] Read from unimplemented NCCH archive file. High program ID: %08X, low ID: %08X",
-				highProgramID, lowProgramID);
+			Helpers::panic(
+				"[NCCH archive] Read from unimplemented NCCH archive file. High program ID: %08X, low ID: %08X", highProgramID, lowProgramID
+			);
 		}
 
 		if (offset >= fileData.size()) {
 			Helpers::panic("[NCCH archive] Out of bounds read from NAND file");
 		}
 
-		u32 availableBytes = u32(fileData.size() - offset); // How many bytes we can read from the file
-		u32 bytesRead = std::min<u32>(size, availableBytes); // Cap the amount of bytes to read if we're going to go out of bounds
+		u32 availableBytes = u32(fileData.size() - offset);   // How many bytes we can read from the file
+		u32 bytesRead = std::min<u32>(size, availableBytes);  // Cap the amount of bytes to read if we're going to go out of bounds
 		for (u32 i = 0; i < bytesRead; i++) {
 			mem.write8(dataPointer + i, fileData[offset + i]);
 		}
@@ -117,8 +115,7 @@ std::optional<u32> NCCHArchive::readFile(FileSession* file, u64 offset, u32 size
 	}
 
 	// Code below is for mediaType == 2 (gamecard). Currently unused
-	if (partition != 0)
-		Helpers::panic("[NCCH] Tried to read from non-zero partition");
+	if (partition != 0) Helpers::panic("[NCCH] Tried to read from non-zero partition");
 
 	if (type == PathType::RomFS && !hasRomFS()) {
 		Helpers::panic("Tried to read file from non-existent RomFS");
@@ -150,8 +147,7 @@ std::optional<u32> NCCHArchive::readFile(FileSession* file, u64 offset, u32 size
 			break;
 		}
 
-		default:
-			Helpers::panic("Unimplemented file path type for NCCH archive");
+		default: Helpers::panic("Unimplemented file path type for NCCH archive");
 	}
 
 	std::unique_ptr<u8[]> data(new u8[size]);
diff --git a/src/core/fs/archive_save_data.cpp b/src/core/fs/archive_save_data.cpp
index 0bdb9e01..0f287480 100644
--- a/src/core/fs/archive_save_data.cpp
+++ b/src/core/fs/archive_save_data.cpp
@@ -1,4 +1,5 @@
 #include "fs/archive_save_data.hpp"
+
 #include <algorithm>
 #include <memory>
 
@@ -6,8 +7,7 @@ namespace fs = std::filesystem;
 
 HorizonResult SaveDataArchive::createFile(const FSPath& path, u64 size) {
 	if (path.type == PathType::UTF16) {
-		if (!isPathSafe<PathType::UTF16>(path))
-			Helpers::panic("Unsafe path in SaveData::CreateFile");
+		if (!isPathSafe<PathType::UTF16>(path)) Helpers::panic("Unsafe path in SaveData::CreateFile");
 
 		fs::path p = IOFile::getAppData() / "SaveData";
 		p += fs::path(path.utf16_string).make_preferred();
@@ -110,16 +110,16 @@ FileDescriptor SaveDataArchive::openFile(const FSPath& path, const FilePerms& pe
 
 		const char* permString = perms.write() ? "r+b" : "rb";
 
-		if (fs::exists(p)) { // Return file descriptor if the file exists
+		if (fs::exists(p)) {  // Return file descriptor if the file exists
 			IOFile file(p.string().c_str(), permString);
 			return file.isOpen() ? file.getHandle() : FileError;
 		} else {
 			// If the file is not found, create it if the create flag is on
 			if (perms.create()) {
-				IOFile file(p.string().c_str(), "wb"); // Create file
-				file.close(); // Close it
+				IOFile file(p.string().c_str(), "wb");  // Create file
+				file.close();                           // Close it
 
-				file.open(p.string().c_str(), permString); // Reopen with proper perms
+				file.open(p.string().c_str(), permString);  // Reopen with proper perms
 				return file.isOpen() ? file.getHandle() : FileError;
 			} else {
 				return FileError;
@@ -131,7 +131,7 @@ FileDescriptor SaveDataArchive::openFile(const FSPath& path, const FilePerms& pe
 	return FileError;
 }
 
-Rust::Result<DirectorySession, HorizonResult> SaveDataArchive::openDirectory(const FSPath& path) {
+std::expected<DirectorySession, HorizonResult> SaveDataArchive::openDirectory(const FSPath& path) {
 	if (path.type == PathType::UTF16) {
 		if (!isPathSafe<PathType::UTF16>(path)) {
 			Helpers::panic("Unsafe path in SaveData::OpenDirectory");
@@ -142,27 +142,27 @@ Rust::Result<DirectorySession, HorizonResult> SaveDataArchive::openDirectory(con
 
 		if (fs::is_regular_file(p)) {
 			printf("SaveData: OpenDirectory used with a file path");
-			return Err(Result::FS::UnexpectedFileOrDir);
+			return std::unexpected(Result::FS::UnexpectedFileOrDir);
 		}
 
 		if (fs::is_directory(p)) {
-			return Ok(DirectorySession(this, p));
+			return DirectorySession(this, p);
 		} else {
-			return Err(Result::FS::FileNotFoundAlt);
+			return std::unexpected(Result::FS::FileNotFoundAlt);
 		}
 	}
 
 	Helpers::panic("SaveDataArchive::OpenDirectory: Unimplemented path type");
-	return Err(Result::Success);
+	return std::unexpected(Result::Success);
 }
 
-Rust::Result<ArchiveBase::FormatInfo, HorizonResult> SaveDataArchive::getFormatInfo(const FSPath& path) {
+std::expected<ArchiveBase::FormatInfo, HorizonResult> SaveDataArchive::getFormatInfo(const FSPath& path) {
 	const fs::path formatInfoPath = getFormatInfoPath();
 	IOFile file(formatInfoPath, "rb");
 
 	// If the file failed to open somehow, we return that the archive is not formatted
 	if (!file.isOpen()) {
-		return Err(Result::FS::NotFormatted);
+		return std::unexpected(Result::FS::NotFormatted);
 	}
 
 	FormatInfo ret;
@@ -171,10 +171,10 @@ Rust::Result<ArchiveBase::FormatInfo, HorizonResult> SaveDataArchive::getFormatI
 
 	if (!success || bytesRead != sizeof(FormatInfo)) {
 		Helpers::warn("SaveData::GetFormatInfo: Format file exists but was not properly read into the FormatInfo struct");
-		return Err(Result::FS::NotFormatted);
+		return std::unexpected(Result::FS::NotFormatted);
 	}
 
-	return Ok(ret);
+	return ret;
 }
 
 void SaveDataArchive::format(const FSPath& path, const ArchiveBase::FormatInfo& info) {
@@ -192,19 +192,19 @@ void SaveDataArchive::format(const FSPath& path, const ArchiveBase::FormatInfo&
 	file.close();
 }
 
-Rust::Result<ArchiveBase*, HorizonResult> SaveDataArchive::openArchive(const FSPath& path) {
+std::expected<ArchiveBase*, HorizonResult> SaveDataArchive::openArchive(const FSPath& path) {
 	if (path.type != PathType::Empty) {
 		Helpers::panic("Unimplemented path type for SaveData archive: %d\n", path.type);
-		return Err(Result::FS::NotFoundInvalid);
+		return std::unexpected(Result::FS::NotFoundInvalid);
 	}
 
 	const fs::path formatInfoPath = getFormatInfoPath();
 	// Format info not found so the archive is not formatted
 	if (!fs::is_regular_file(formatInfoPath)) {
-		return Err(Result::FS::NotFormatted);
+		return std::unexpected(Result::FS::NotFormatted);
 	}
 
-	return Ok((ArchiveBase*)this);
+	return (ArchiveBase*)this;
 }
 
 std::optional<u32> SaveDataArchive::readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) {
diff --git a/src/core/fs/archive_sdmc.cpp b/src/core/fs/archive_sdmc.cpp
index 6c34de7a..b6c75b67 100644
--- a/src/core/fs/archive_sdmc.cpp
+++ b/src/core/fs/archive_sdmc.cpp
@@ -1,4 +1,5 @@
 #include "fs/archive_sdmc.hpp"
+
 #include <memory>
 
 namespace fs = std::filesystem;
@@ -137,10 +138,10 @@ HorizonResult SDMCArchive::createDirectory(const FSPath& path) {
 	return success ? Result::Success : Result::FS::UnexpectedFileOrDir;
 }
 
-Rust::Result<DirectorySession, HorizonResult> SDMCArchive::openDirectory(const FSPath& path) {
+std::expected<DirectorySession, HorizonResult> SDMCArchive::openDirectory(const FSPath& path) {
 	if (isWriteOnly) {
 		Helpers::warn("SDMC: OpenDirectory is not allowed in SDMC Write-Only archive");
-		return Err(Result::FS::UnexpectedFileOrDir);
+		return std::unexpected(Result::FS::UnexpectedFileOrDir);
 	}
 
 	if (path.type == PathType::UTF16) {
@@ -153,27 +154,27 @@ Rust::Result<DirectorySession, HorizonResult> SDMCArchive::openDirectory(const F
 
 		if (fs::is_regular_file(p)) {
 			printf("SDMC: OpenDirectory used with a file path");
-			return Err(Result::FS::UnexpectedFileOrDir);
+			return std::unexpected(Result::FS::UnexpectedFileOrDir);
 		}
 
 		if (fs::is_directory(p)) {
-			return Ok(DirectorySession(this, p));
+			return DirectorySession(this, p);
 		} else {
-			return Err(Result::FS::FileNotFoundAlt);
+			return std::unexpected(Result::FS::FileNotFoundAlt);
 		}
 	}
 
 	Helpers::panic("SDMCArchive::OpenDirectory: Unimplemented path type");
-	return Err(Result::Success);
+	return std::unexpected(Result::Success);
 }
 
-Rust::Result<ArchiveBase*, HorizonResult> SDMCArchive::openArchive(const FSPath& path) {
+std::expected<ArchiveBase*, HorizonResult> SDMCArchive::openArchive(const FSPath& path) {
 	// TODO: Fail here if the SD is disabled in the connfig.
 	if (path.type != PathType::Empty) {
 		Helpers::panic("Unimplemented path type for SDMC::OpenArchive");
 	}
 
-	return Ok((ArchiveBase*)this);
+	return (ArchiveBase*)this;
 }
 
 std::optional<u32> SDMCArchive::readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) {
diff --git a/src/core/fs/archive_self_ncch.cpp b/src/core/fs/archive_self_ncch.cpp
index 9369152d..70bba828 100644
--- a/src/core/fs/archive_self_ncch.cpp
+++ b/src/core/fs/archive_self_ncch.cpp
@@ -1,4 +1,5 @@
 #include "fs/archive_self_ncch.hpp"
+
 #include <memory>
 
 // The part of the NCCH archive we're trying to access. Depends on the first 4 bytes of the binary file path
@@ -33,21 +34,21 @@ FileDescriptor SelfNCCHArchive::openFile(const FSPath& path, const FilePerms& pe
 
 	// Where to read the file from. (https://www.3dbrew.org/wiki/Filesystem_services#SelfNCCH_File_Path_Data_Format)
 	// We currently only know how to read from an NCCH's RomFS, ie type = 0
-	const u32 type = *(u32*)&path.binary[0]; // TODO: Get rid of UB here
+	const u32 type = *(u32*)&path.binary[0];  // TODO: Get rid of UB here
 	if (type != PathType::RomFS && type != PathType::ExeFS && type != PathType::UpdateRomFS) {
 		Helpers::panic("Read from NCCH's non-RomFS & non-exeFS section! Path type: %d", type);
 	}
 
-	return NoFile; // No file descriptor needed for RomFS
+	return NoFile;  // No file descriptor needed for RomFS
 }
 
-Rust::Result<ArchiveBase*, HorizonResult> SelfNCCHArchive::openArchive(const FSPath& path) {
+std::expected<ArchiveBase*, HorizonResult> SelfNCCHArchive::openArchive(const FSPath& path) {
 	if (path.type != PathType::Empty) {
 		Helpers::panic("Invalid path type for SelfNCCH archive: %d\n", path.type);
-		return Err(Result::FS::NotFoundInvalid);
+		return std::unexpected(Result::FS::NotFoundInvalid);
 	}
 
-	return Ok((ArchiveBase*)this);
+	return (ArchiveBase*)this;
 }
 
 std::optional<u32> SelfNCCHArchive::readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) {
diff --git a/src/core/fs/archive_system_save_data.cpp b/src/core/fs/archive_system_save_data.cpp
index 37afb431..5264cd3f 100644
--- a/src/core/fs/archive_system_save_data.cpp
+++ b/src/core/fs/archive_system_save_data.cpp
@@ -1,14 +1,15 @@
-#include <algorithm>
 #include "fs/archive_system_save_data.hpp"
 
+#include <algorithm>
+
 namespace fs = std::filesystem;
 
-Rust::Result<ArchiveBase*, HorizonResult> SystemSaveDataArchive::openArchive(const FSPath& path) {
+std::expected<ArchiveBase*, HorizonResult> SystemSaveDataArchive::openArchive(const FSPath& path) {
 	if (path.type != PathType::Binary) {
 		Helpers::panic("Unimplemented path type for SystemSaveData::OpenArchive");
 	}
 
-	return Ok((ArchiveBase*)this);
+	return (ArchiveBase*)this;
 }
 
 FileDescriptor SystemSaveDataArchive::openFile(const FSPath& path, const FilePerms& perms) {
@@ -108,7 +109,6 @@ HorizonResult SystemSaveDataArchive::createDirectory(const FSPath& path) {
 	}
 }
 
-
 HorizonResult SystemSaveDataArchive::deleteFile(const FSPath& path) {
 	if (path.type == PathType::UTF16) {
 		if (!isPathSafe<PathType::UTF16>(path)) {
@@ -142,11 +142,11 @@ HorizonResult SystemSaveDataArchive::deleteFile(const FSPath& path) {
 	return Result::Success;
 }
 
-Rust::Result<DirectorySession, HorizonResult> SystemSaveDataArchive::openDirectory(const FSPath& path) {
+std::expected<DirectorySession, HorizonResult> SystemSaveDataArchive::openDirectory(const FSPath& path) {
 	if (path.type == PathType::UTF16) {
 		if (!isPathSafe<PathType::UTF16>(path)) {
 			Helpers::warn("Unsafe path in SystemSaveData::OpenDirectory");
-			return Err(Result::FS::FileNotFoundAlt);
+			return std::unexpected(Result::FS::FileNotFoundAlt);
 		}
 
 		fs::path p = IOFile::getAppData() / ".." / "SharedFiles" / "SystemSaveData";
@@ -154,16 +154,16 @@ Rust::Result<DirectorySession, HorizonResult> SystemSaveDataArchive::openDirecto
 
 		if (fs::is_regular_file(p)) {
 			printf("SystemSaveData: OpenDirectory used with a file path");
-			return Err(Result::FS::UnexpectedFileOrDir);
+			return std::unexpected(Result::FS::UnexpectedFileOrDir);
 		}
 
 		if (fs::is_directory(p)) {
-			return Ok(DirectorySession(this, p));
+			return DirectorySession(this, p);
 		} else {
-			return Err(Result::FS::FileNotFoundAlt);
+			return std::unexpected(Result::FS::FileNotFoundAlt);
 		}
 	}
 
 	Helpers::panic("SystemSaveData::OpenDirectory: Unimplemented path type");
-	return Err(Result::Success);
+	return std::unexpected(Result::Success);
 }
\ No newline at end of file
diff --git a/src/core/fs/archive_user_save_data.cpp b/src/core/fs/archive_user_save_data.cpp
index cba9bff8..20c75145 100644
--- a/src/core/fs/archive_user_save_data.cpp
+++ b/src/core/fs/archive_user_save_data.cpp
@@ -1,8 +1,8 @@
+#include "fs/archive_user_save_data.hpp"
+
 #include <algorithm>
 #include <memory>
 
-#include "fs/archive_user_save_data.hpp"
-
 namespace fs = std::filesystem;
 
 HorizonResult UserSaveDataArchive::createFile(const FSPath& path, u64 size) {
@@ -118,7 +118,7 @@ FileDescriptor UserSaveDataArchive::openFile(const FSPath& path, const FilePerms
 	return FileError;
 }
 
-Rust::Result<DirectorySession, HorizonResult> UserSaveDataArchive::openDirectory(const FSPath& path) {
+std::expected<DirectorySession, HorizonResult> UserSaveDataArchive::openDirectory(const FSPath& path) {
 	if (path.type == PathType::UTF16) {
 		if (!isPathSafe<PathType::UTF16>(path)) Helpers::panic("Unsafe path in UserSaveData::OpenDirectory");
 
@@ -127,27 +127,27 @@ Rust::Result<DirectorySession, HorizonResult> UserSaveDataArchive::openDirectory
 
 		if (fs::is_regular_file(p)) {
 			printf("SaveData: OpenDirectory used with a file path");
-			return Err(Result::FS::UnexpectedFileOrDir);
+			return std::unexpected(Result::FS::UnexpectedFileOrDir);
 		}
 
 		if (fs::is_directory(p)) {
-			return Ok(DirectorySession(this, p));
+			return DirectorySession(this, p);
 		} else {
-			return Err(Result::FS::FileNotFoundAlt);
+			return std::unexpected(Result::FS::FileNotFoundAlt);
 		}
 	}
 
 	Helpers::panic("UserSaveDataArchive::OpenDirectory: Unimplemented path type");
-	return Err(Result::Success);
+	return std::unexpected(Result::Success);
 }
 
-Rust::Result<ArchiveBase::FormatInfo, HorizonResult> UserSaveDataArchive::getFormatInfo(const FSPath& path) {
+std::expected<ArchiveBase::FormatInfo, HorizonResult> UserSaveDataArchive::getFormatInfo(const FSPath& path) {
 	const fs::path formatInfoPath = getFormatInfoPath();
 	IOFile file(formatInfoPath, "rb");
 
 	// If the file failed to open somehow, we return that the archive is not formatted
 	if (!file.isOpen()) {
-		return Err(Result::FS::NotFormatted);
+		return std::unexpected(Result::FS::NotFormatted);
 	}
 
 	FormatInfo ret;
@@ -156,10 +156,10 @@ Rust::Result<ArchiveBase::FormatInfo, HorizonResult> UserSaveDataArchive::getFor
 
 	if (!success || bytesRead != sizeof(FormatInfo)) {
 		Helpers::warn("UserSaveData::GetFormatInfo: Format file exists but was not properly read into the FormatInfo struct");
-		return Err(Result::FS::NotFormatted);
+		return std::unexpected(Result::FS::NotFormatted);
 	}
 
-	return Ok(ret);
+	return ret;
 }
 
 void UserSaveDataArchive::format(const FSPath& path, const ArchiveBase::FormatInfo& info) {
@@ -177,19 +177,19 @@ void UserSaveDataArchive::format(const FSPath& path, const ArchiveBase::FormatIn
 	file.close();
 }
 
-Rust::Result<ArchiveBase*, HorizonResult> UserSaveDataArchive::openArchive(const FSPath& path) {
+std::expected<ArchiveBase*, HorizonResult> UserSaveDataArchive::openArchive(const FSPath& path) {
 	if (path.type != PathType::Binary) {
 		Helpers::panic("Unimplemented path type for UserSaveData archive: %d\n", path.type);
-		return Err(Result::FS::NotFoundInvalid);
+		return std::unexpected(Result::FS::NotFoundInvalid);
 	}
 
 	const fs::path formatInfoPath = getFormatInfoPath();
 	// Format info not found so the archive is not formatted
 	if (!fs::is_regular_file(formatInfoPath)) {
-		return Err(Result::FS::NotFormatted);
+		return std::unexpected(Result::FS::NotFormatted);
 	}
 
-	return Ok((ArchiveBase*)this);
+	return (ArchiveBase*)this;
 }
 
 std::optional<u32> UserSaveDataArchive::readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) {
diff --git a/src/core/services/fs.cpp b/src/core/services/fs.cpp
index 2e102958..aa044a53 100644
--- a/src/core/services/fs.cpp
+++ b/src/core/services/fs.cpp
@@ -1,10 +1,11 @@
 #include "services/fs.hpp"
-#include "kernel/kernel.hpp"
+
 #include "io_file.hpp"
 #include "ipc.hpp"
+#include "kernel/kernel.hpp"
 #include "result/result.hpp"
 
-#ifdef CreateFile // windows.h defines CreateFile & DeleteFile because of course it does.
+#ifdef CreateFile  // windows.h defines CreateFile & DeleteFile because of course it does.
 #undef CreateDirectory
 #undef CreateFile
 #undef DeleteFile
@@ -47,21 +48,18 @@ namespace FSCommands {
 	};
 }
 
-void FSService::reset() {
-	priority = 0;
-}
+void FSService::reset() { priority = 0; }
 
 // Creates directories for NAND, ExtSaveData, etc if they don't already exist. Should be executed after loading a new ROM.
 void FSService::initializeFilesystem() {
-	const auto sdmcPath = IOFile::getAppData() / "SDMC"; // Create SDMC directory
+	const auto sdmcPath = IOFile::getAppData() / "SDMC";  // Create SDMC directory
 	const auto nandSharedpath = IOFile::getAppData() / ".." / "SharedFiles" / "NAND";
 
-	const auto savePath = IOFile::getAppData() / "SaveData"; // Create SaveData
-	const auto formatPath = IOFile::getAppData() / "FormatInfo"; // Create folder for storing archive formatting info
+	const auto savePath = IOFile::getAppData() / "SaveData";      // Create SaveData
+	const auto formatPath = IOFile::getAppData() / "FormatInfo";  // Create folder for storing archive formatting info
 	const auto systemSaveDataPath = IOFile::getAppData() / ".." / "SharedFiles" / "SystemSaveData";
 	namespace fs = std::filesystem;
 
-
 	if (!fs::is_directory(nandSharedpath)) {
 		fs::create_directories(nandSharedpath);
 	}
@@ -89,25 +87,21 @@ ArchiveBase* FSService::getArchiveFromID(u32 id, const FSPath& archivePath) {
 		case ArchiveID::SaveData: return &saveData;
 		case ArchiveID::UserSaveData2: return &userSaveData2;
 
-		case ArchiveID::ExtSaveData:
-			return &extSaveData_sdmc;
+		case ArchiveID::ExtSaveData: return &extSaveData_sdmc;
 
-		case ArchiveID::SharedExtSaveData:
-			return &sharedExtSaveData_nand;
+		case ArchiveID::SharedExtSaveData: return &sharedExtSaveData_nand;
 
 		case ArchiveID::SystemSaveData: return &systemSaveData;
 		case ArchiveID::SDMC: return &sdmc;
 		case ArchiveID::SDMCWriteOnly: return &sdmcWriteOnly;
-		case ArchiveID::SavedataAndNcch: return &ncch; // This can only access NCCH outside of FSPXI
-		default:
-			Helpers::panic("Unknown archive. ID: %d\n", id);
-			return nullptr;
+		case ArchiveID::SavedataAndNcch: return &ncch;  // This can only access NCCH outside of FSPXI
+		default: Helpers::panic("Unknown archive. ID: %d\n", id); return nullptr;
 	}
 }
 
 std::optional<Handle> FSService::openFileHandle(ArchiveBase* archive, const FSPath& path, const FSPath& archivePath, const FilePerms& perms) {
 	FileDescriptor opened = archive->openFile(path, perms);
-	if (opened.has_value()) { // If opened doesn't have a value, we failed to open the file
+	if (opened.has_value()) {  // If opened doesn't have a value, we failed to open the file
 		auto handle = kernel.makeObject(KernelObjectType::File);
 
 		auto& file = kernel.getObjects()[handle];
@@ -119,37 +113,36 @@ std::optional<Handle> FSService::openFileHandle(ArchiveBase* archive, const FSPa
 	}
 }
 
-Rust::Result<Handle, Result::HorizonResult> FSService::openDirectoryHandle(ArchiveBase* archive, const FSPath& path) {
-	Rust::Result<DirectorySession, Result::HorizonResult> opened = archive->openDirectory(path);
-	if (opened.isOk()) { // If opened doesn't have a value, we failed to open the directory
+std::expected<Handle, Result::HorizonResult> FSService::openDirectoryHandle(ArchiveBase* archive, const FSPath& path) {
+	std::expected<DirectorySession, Result::HorizonResult> opened = archive->openDirectory(path);
+	if (opened) {  // If opened doesn't have a value, we failed to open the directory
 		auto handle = kernel.makeObject(KernelObjectType::Directory);
 		auto& object = kernel.getObjects()[handle];
-		object.data = new DirectorySession(opened.unwrap());
+		object.data = new DirectorySession(opened.value());
 
-		return Ok(handle);
+		return handle;
 	} else {
-		return Err(opened.unwrapErr());
+		return std::unexpected(opened.error());
 	}
 }
 
-Rust::Result<Handle, Result::HorizonResult> FSService::openArchiveHandle(u32 archiveID, const FSPath& path) {
+std::expected<Handle, Result::HorizonResult> FSService::openArchiveHandle(u32 archiveID, const FSPath& path) {
 	ArchiveBase* archive = getArchiveFromID(archiveID, path);
 
 	if (archive == nullptr) [[unlikely]] {
 		Helpers::panic("OpenArchive: Tried to open unknown archive %d.", archiveID);
-		return Err(Result::FS::NotFormatted);
+		return std::unexpected(Result::FS::NotFormatted);
 	}
 
-	Rust::Result<ArchiveBase*, Result::HorizonResult> res = archive->openArchive(path);
-	if (res.isOk()) {
+	std::expected<ArchiveBase*, Result::HorizonResult> res = archive->openArchive(path);
+	if (res.has_value()) {
 		auto handle = kernel.makeObject(KernelObjectType::Archive);
 		auto& archiveObject = kernel.getObjects()[handle];
-		archiveObject.data = new ArchiveSession(res.unwrap(), path);
+		archiveObject.data = new ArchiveSession(res.value(), path);
 
-		return Ok(handle);
-	}
-	else {
-		return Err(res.unwrapErr());
+		return handle;
+	} else {
+		return std::unexpected(res.error());
 	}
 }
 
@@ -157,8 +150,7 @@ FSPath FSService::readPath(u32 type, u32 pointer, u32 size) {
 	std::vector<u8> data;
 	data.resize(size);
 
-	for (u32 i = 0; i < size; i++)
-		data[i] = mem.read8(pointer + i);
+	for (u32 i = 0; i < size; i++) data[i] = mem.read8(pointer + i);
 
 	return FSPath(type, data);
 }
@@ -217,7 +209,7 @@ void FSService::initializeWithSdkVersion(u32 messagePointer) {
 }
 
 void FSService::closeArchive(u32 messagePointer) {
-	const Handle handle = static_cast<u32>(mem.read64(messagePointer + 4)); // TODO: archive handles should be 64-bit
+	const Handle handle = static_cast<u32>(mem.read64(messagePointer + 4));  // TODO: archive handles should be 64-bit
 	const auto object = kernel.getObject(handle, KernelObjectType::Archive);
 	log("FSService::CloseArchive(handle = %X)\n", handle);
 
@@ -241,14 +233,14 @@ void FSService::openArchive(u32 messagePointer) {
 	auto archivePath = readPath(archivePathType, archivePathPointer, archivePathSize);
 	log("FS::OpenArchive(archive ID = %d, archive path type = %d)\n", archiveID, archivePathType);
 
-	Rust::Result<Handle, Result::HorizonResult> res = openArchiveHandle(archiveID, archivePath);
+	std::expected<Handle, Result::HorizonResult> res = openArchiveHandle(archiveID, archivePath);
 	mem.write32(messagePointer, IPC::responseHeader(0x80C, 3, 0));
-	if (res.isOk()) {
+	if (res.has_value()) {
 		mem.write32(messagePointer + 4, Result::Success);
-		mem.write64(messagePointer + 8, res.unwrap());
+		mem.write64(messagePointer + 8, res.value());
 	} else {
-		log("FS::OpenArchive: Failed to open archive with id = %d. Error %08X\n", archiveID, (u32)res.unwrapErr());
-		mem.write32(messagePointer + 4, res.unwrapErr());
+		log("FS::OpenArchive: Failed to open archive with id = %d. Error %08X\n", archiveID, (u32)res.error());
+		mem.write32(messagePointer + 4, res.error());
 		mem.write64(messagePointer + 8, 0);
 	}
 }
@@ -283,7 +275,7 @@ void FSService::openFile(u32 messagePointer) {
 		mem.write32(messagePointer + 4, Result::FS::FileNotFound);
 	} else {
 		mem.write32(messagePointer + 4, Result::Success);
-		mem.write32(messagePointer + 8, 0x10); // "Move handle descriptor"
+		mem.write32(messagePointer + 8, 0x10);  // "Move handle descriptor"
 		mem.write32(messagePointer + 12, handle.value());
 	}
 }
@@ -330,12 +322,12 @@ void FSService::openDirectory(u32 messagePointer) {
 	auto dir = openDirectoryHandle(archive, dirPath);
 
 	mem.write32(messagePointer, IPC::responseHeader(0x80B, 1, 2));
-	if (dir.isOk()) {
+	if (dir.has_value()) {
 		mem.write32(messagePointer + 4, Result::Success);
-		mem.write32(messagePointer + 12, dir.unwrap());
+		mem.write32(messagePointer + 12, dir.value());
 	} else {
 		printf("FS::OpenDirectory failed\n");
-		mem.write32(messagePointer + 4, static_cast<u32>(dir.unwrapErr()));
+		mem.write32(messagePointer + 4, static_cast<u32>(dir.error()));
 	}
 }
 
@@ -360,11 +352,11 @@ void FSService::openFileDirectly(u32 messagePointer) {
 	auto filePath = readPath(filePathType, filePathPointer, filePathSize);
 	const FilePerms perms(openFlags);
 
-	Rust::Result<ArchiveBase*, Result::HorizonResult> res = archive->openArchive(archivePath);
-	if (res.isErr()) [[unlikely]] {
+	std::expected<ArchiveBase*, Result::HorizonResult> res = archive->openArchive(archivePath);
+	if (!res.has_value()) [[unlikely]] {
 		Helpers::panic("OpenFileDirectly: Failed to open archive with given path");
 	}
-	archive = res.unwrap();
+	archive = res.value();
 
 	std::optional<Handle> handle = openFileHandle(archive, filePath, archivePath, perms);
 	mem.write32(messagePointer, IPC::responseHeader(0x803, 1, 2));
@@ -451,18 +443,18 @@ void FSService::getFormatInfo(u32 messagePointer) {
 	}
 
 	mem.write32(messagePointer, IPC::responseHeader(0x845, 5, 0));
-	Rust::Result<ArchiveBase::FormatInfo, Result::HorizonResult> res = archive->getFormatInfo(path);
+	std::expected<ArchiveBase::FormatInfo, Result::HorizonResult> res = archive->getFormatInfo(path);
 
 	// If the FormatInfo was returned, write them to the output buffer. Otherwise, write an error code.
-	if (res.isOk()) {
-		ArchiveBase::FormatInfo info = res.unwrap();
+	if (res.has_value()) {
+		ArchiveBase::FormatInfo info = res.value();
 		mem.write32(messagePointer + 4, Result::Success);
 		mem.write32(messagePointer + 8, info.size);
 		mem.write32(messagePointer + 12, info.numOfDirectories);
 		mem.write32(messagePointer + 16, info.numOfFiles);
 		mem.write8(messagePointer + 20, info.duplicateData ? 1 : 0);
 	} else {
-		mem.write32(messagePointer + 4, static_cast<u32>(res.unwrapErr()));
+		mem.write32(messagePointer + 4, static_cast<u32>(res.error()));
 	}
 }
 
@@ -470,8 +462,7 @@ void FSService::formatSaveData(u32 messagePointer) {
 	log("FS::FormatSaveData\n");
 
 	const u32 archiveID = mem.read32(messagePointer + 4);
-	if (archiveID != ArchiveID::SaveData)
-		Helpers::panic("FS::FormatSaveData: Archive is not SaveData");
+	if (archiveID != ArchiveID::SaveData) Helpers::panic("FS::FormatSaveData: Archive is not SaveData");
 
 	// Read path and path info
 	const u32 pathType = mem.read32(messagePointer + 8);
@@ -481,21 +472,15 @@ void FSService::formatSaveData(u32 messagePointer) {
 	// Size of a block. Seems to always be 0x200
 	const u32 blockSize = mem.read32(messagePointer + 16);
 
-	if (blockSize != 0x200 && blockSize != 0x1000)
-		Helpers::panic("FS::FormatSaveData: Invalid SaveData block size");
+	if (blockSize != 0x200 && blockSize != 0x1000) Helpers::panic("FS::FormatSaveData: Invalid SaveData block size");
 
-	const u32 directoryNum = mem.read32(messagePointer + 20); // Max number of directories
-	const u32 fileNum = mem.read32(messagePointer + 24); // Max number of files
-	const u32 directoryBucketNum = mem.read32(messagePointer + 28); // Not sure what a directory bucket is...?
-	const u32 fileBucketNum = mem.read32(messagePointer + 32); // Same here
+	const u32 directoryNum = mem.read32(messagePointer + 20);        // Max number of directories
+	const u32 fileNum = mem.read32(messagePointer + 24);             // Max number of files
+	const u32 directoryBucketNum = mem.read32(messagePointer + 28);  // Not sure what a directory bucket is...?
+	const u32 fileBucketNum = mem.read32(messagePointer + 32);       // Same here
 	const bool duplicateData = mem.read8(messagePointer + 36) != 0;
 
-	ArchiveBase::FormatInfo info {
-		.size = blockSize * 0x200,
-		.numOfDirectories = directoryNum,
-		.numOfFiles = fileNum,
-		.duplicateData = duplicateData
-	};
+	ArchiveBase::FormatInfo info{.size = blockSize * 0x200, .numOfDirectories = directoryNum, .numOfFiles = fileNum, .duplicateData = duplicateData};
 
 	saveData.format(path, info);
 
@@ -512,8 +497,8 @@ void FSService::deleteExtSaveData(u32 messagePointer) {
 	log("FS::DeleteExtSaveData (media type = %d, saveID = %llx) (stubbed)\n", mediaType, saveID);
 
 	mem.write32(messagePointer, IPC::responseHeader(0x0852, 1, 0));
-	// TODO: We can't properly implement this yet until we properly support title/save IDs. We will stub this and insert a warning for now. Required for Planet Robobot
-	// When we properly implement it, it will just be a recursive directory deletion
+	// TODO: We can't properly implement this yet until we properly support title/save IDs. We will stub this and insert a warning for now. Required
+	// for Planet Robobot When we properly implement it, it will just be a recursive directory deletion
 	mem.write32(messagePointer + 4, Result::Success);
 }
 
@@ -521,7 +506,8 @@ void FSService::createExtSaveData(u32 messagePointer) {
 	Helpers::warn("Stubbed call to FS::CreateExtSaveData!");
 	// First 4 words of parameters are the ExtSaveData info
 	// https://www.3dbrew.org/wiki/Filesystem_services#ExtSaveDataInfo
-	// This creates the ExtSaveData with the specified saveid in the specified media type. It stores the SMDH as "icon" in the root of the created directory. 
+	// This creates the ExtSaveData with the specified saveid in the specified media type. It stores the SMDH as "icon" in the root of the created
+	// directory.
 	const u8 mediaType = mem.read8(messagePointer + 4);
 	const u64 saveID = mem.read64(messagePointer + 8);
 	const u32 numOfDirectories = mem.read32(messagePointer + 20);
@@ -541,18 +527,13 @@ void FSService::formatThisUserSaveData(u32 messagePointer) {
 	log("FS::FormatThisUserSaveData\n");
 
 	const u32 blockSize = mem.read32(messagePointer + 4);
-	const u32 directoryNum = mem.read32(messagePointer + 8); // Max number of directories
-	const u32 fileNum = mem.read32(messagePointer + 12); // Max number of files
-	const u32 directoryBucketNum = mem.read32(messagePointer + 16); // Not sure what a directory bucket is...?
-	const u32 fileBucketNum = mem.read32(messagePointer + 20); // Same here
+	const u32 directoryNum = mem.read32(messagePointer + 8);         // Max number of directories
+	const u32 fileNum = mem.read32(messagePointer + 12);             // Max number of files
+	const u32 directoryBucketNum = mem.read32(messagePointer + 16);  // Not sure what a directory bucket is...?
+	const u32 fileBucketNum = mem.read32(messagePointer + 20);       // Same here
 	const bool duplicateData = mem.read8(messagePointer + 24) != 0;
 
-	ArchiveBase::FormatInfo info {
-		.size = blockSize * 0x200,
-		.numOfDirectories = directoryNum,
-		.numOfFiles = fileNum,
-		.duplicateData = duplicateData
-	};
+	ArchiveBase::FormatInfo info{.size = blockSize * 0x200, .numOfDirectories = directoryNum, .numOfFiles = fileNum, .duplicateData = duplicateData};
 	FSPath emptyPath;
 
 	mem.write32(messagePointer, IPC::responseHeader(0x080F, 1, 0));
@@ -578,18 +559,16 @@ void FSService::controlArchive(u32 messagePointer) {
 	}
 
 	switch (action) {
-		case 0: // Commit save data changes. Shouldn't need us to do anything
+		case 0:  // Commit save data changes. Shouldn't need us to do anything
 			mem.write32(messagePointer + 4, Result::Success);
 			break;
 
-		case 1: // Retrieves a file's last-modified timestamp. Seen in DDLC, stubbed for the moment
+		case 1:  // Retrieves a file's last-modified timestamp. Seen in DDLC, stubbed for the moment
 			Helpers::warn("FS::ControlArchive: Tried to retrieve a file's last-modified timestamp");
 			mem.write32(messagePointer + 4, Result::Success);
 			break;
 
-		default:
-			Helpers::panic("Unimplemented action for ControlArchive (action = %X)\n", action);
-			break;
+		default: Helpers::panic("Unimplemented action for ControlArchive (action = %X)\n", action); break;
 	}
 }
 
@@ -673,9 +652,9 @@ void FSService::getThisSaveDataSecureValue(u32 messagePointer) {
 
 	mem.write32(messagePointer, IPC::responseHeader(0x86F, 1, 0));
 	mem.write32(messagePointer + 4, Result::Success);
-	mem.write8(messagePointer + 8, 0); // Secure value does not exist
-	mem.write8(messagePointer + 12, 1); // TODO: What is this?
-	mem.write64(messagePointer + 16, 0); // Secure value
+	mem.write8(messagePointer + 8, 0);    // Secure value does not exist
+	mem.write8(messagePointer + 12, 1);   // TODO: What is this?
+	mem.write64(messagePointer + 16, 0);  // Secure value
 }
 
 void FSService::setThisSaveDataSecureValue(u32 messagePointer) {
diff --git a/third_party/result/LICENSE b/third_party/result/LICENSE
deleted file mode 100644
index 6f4e91e3..00000000
--- a/third_party/result/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "{}"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright {2016} {Mathieu Stefani}
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/third_party/result/README.md b/third_party/result/README.md
deleted file mode 100644
index 7f588045..00000000
--- a/third_party/result/README.md
+++ /dev/null
@@ -1,132 +0,0 @@
-# Result
-This is an adaption of [https://github.com/oktal/result](https://github.com/oktal/result). Make sure to support the original library!
-
-## Overview
-
-`Result<T, E>` is a template type that can be used to return and propage errors. It can be used to replace
-exceptions in context where they are not allowed or too slow to be used. `Result<T, E>` is an algebraic data
-type of `Ok(T)` that represents success and `Err(E)` representing an error.
-
-Design of this class has been mainly inspired by Rust's [std::result](https://doc.rust-lang.org/std/result/)
-
-```
-
-struct Request {
-};
-
-struct Error {
-
-    enum class Kind {
-        Timeout,
-        Invalid,
-        TooLong
-    }
-
-    Error(Kind kind, std::string text);
-
-    Kind kind;
-    std::string text;
-};
-
-Result<Request, Error> parseRequest(const std::string& payload) {
-    if (payload.size() > 512) return Err(Error(Kind::TooLong, "Request exceeded maximum allowed size (512 bytes)"));
-
-    Request request;
-    return Ok(request);
-}
-
-std::string payload = receivePayload();
-auto request = parseRequest(payload).expect("Failed to parse request");
-```
-
-To return a successfull `Result`, use the `Ok()` function. To return an error one, use the `Err()` function.
-
-## Extract and unwrap
-
-To extract the value from a `Result<T, E>` type, you can use the `expect()` function that will yield the value
-of an `Ok(T)` or terminate the program with an error message passed as a parameter.
-
-```
-Result<uint32_t, uint32_t> r1 = Ok(3u);
-
-auto val = r1.expect("Failed to retrieve the value");
-assert(val == 3);
-```
-
-`unwrap()` can also be used to extract the value of a `Result`, yielding the value of an `Ok(T)` value or terminating
-the program otherwise:
-
-```
-Result<uint32_t, uint32_t> r1 = Ok(3u);
-
-auto val = r1.unwrap();
-assert(val == 3);
-```
-
-Instead a terminating the program, `unwrapOr` can be used to return a default value for an `Err(E)` Result:
-
-```
-Result<uint32_t, uint32_t> r1 = Err(9u);
-
-auto val = r1.unwrapOr(0);
-assert(val == 0);
-```
-
-## Map and bind
-
-To transform (or map) a `Result<T, E>` to a `Result<U, E>`, `Result` provides a `map` member function.
-`map` will apply a function to a contained `Ok(T)` value and will return the result of the transformation,
-and will leave an `Err(E)` untouched:
-
-```
-std::string stringify(int val) { return std::to_string(val); }
-
-Result<uint32_t, uint32_t> r1 = Ok(2u);
-auto r2 = r1.map(stringify); // Maps a Result<uint32_t, uint32_t> to Result<std::string, uint32_t>
-
-assert(r2.unwrap(), "2");
-```
-
-Note that `map` should return a simple value and not a `Result<U, E>`. A function returning nothing (`void`)
-applied to a `Result<T, E>` will yield a `Result<void, E>`.
-
-To map a function to a contained `Err(E)` value, use the `mapError` function.
-
-To *bind* a `Result<T, E>` to a `Result<U, E>`, you can use the `andThen` member function:
-
-```
-Result<uint32_t, uint32_t> square(uint32_t val) { return Ok(val * val); }
-
-Result<uint32_t, uint32_t> r1 = Ok(3u);
-auto r2 = r1.andThen(square);
-
-assert(r2.unwrap(), 9);
-```
-
-Use `orElse` to apply a function to a contained `Err(E)` value:
-
-```
-Result<uint32_t, uint32_t> identity(uint32_t val) { return Ok(val); }
-
-Result<uint32_t, uint32_t> r1 = Err(3u);
-assert(r1.andThen(identity).orElse(square).unwrap(), 9);
-```
-
-## The TRY macro
-
-Like Rust, a `TRY` macro is also provided that comes in handy when writing code that calls a lot of functions returning a `Result`.
-
-the `TRY` macro will simply call its argument and short-cirtcuit the function returning an `Err(E)` if the operation returned an error `Result`:
-
-```
-Result<void, IoError> copy(int srcFd, const char* dstFile) {
-
-    auto fd = TRY(open(dstFile));
-    auto data = TRY(read(srcFd));
-    TRY(write(fd, data));
-
-    return Ok();
-}
-```
-
-Note that this macro uses a special extension called *compound statement* only supported by gcc and clang
diff --git a/third_party/result/include/result.hpp b/third_party/result/include/result.hpp
deleted file mode 100644
index b75dee90..00000000
--- a/third_party/result/include/result.hpp
+++ /dev/null
@@ -1,910 +0,0 @@
-/* 
-   Mathieu Stefani, 03 mai 2016
-   
-   This header provides a Result type that can be used to replace exceptions in code
-   that has to handle error.
-
-   Result<T, E> can be used to return and propagate an error to the caller. Result<T, E> is an algebraic
-   data type that can either Ok(T) to represent success or Err(E) to represent an error.
-*/
-
-#pragma once
-
-#include <iostream>
-#include <functional>
-#include <type_traits>
-
-namespace types {
-    template<typename T>
-    struct Ok {
-        Ok(const T& val) : val(val) { }
-        Ok(T&& val) : val(std::move(val)) { }
-
-        T val;
-    };
-
-    template<>
-    struct Ok<void> { };
-
-    template<typename E>
-    struct Err {
-        Err(const E& val) : val(val) { }
-        Err(E&& val) : val(std::move(val)) { }
-
-        E val;
-    };
-}
-
-template<typename T, typename CleanT = typename std::decay<T>::type>
-types::Ok<CleanT> Ok(T&& val) {
-    return types::Ok<CleanT>(std::forward<T>(val));
-}
-
-inline types::Ok<void> Ok() {
-    return types::Ok<void>();
-}
-
-template<typename E, typename CleanE = typename std::decay<E>::type>
-types::Err<CleanE> Err(E&& val) {
-    return types::Err<CleanE>(std::forward<E>(val));
-}
-
-namespace Rust {
-template<typename T, typename E> struct Result;
-}
-
-namespace details {
-
-template<typename ...> struct void_t { typedef void type; };
-
-namespace impl {
-    template<typename Func> struct result_of;
-
-    template<typename Ret, typename Cls, typename... Args>
-    struct result_of<Ret (Cls::*)(Args...)> : public result_of<Ret (Args...)> { };
-
-    template<typename Ret, typename... Args>
-    struct result_of<Ret (Args...)> {
-        typedef Ret type;
-    };
-}
-
-template<typename Func>
-struct result_of : public impl::result_of<decltype(&Func::operator())> { };
-
-template<typename Ret, typename Cls, typename... Args>
-struct result_of<Ret (Cls::*) (Args...) const> {
-    typedef Ret type;
-};
-
-template<typename Ret, typename... Args>
-struct result_of<Ret (*)(Args...)> {
-    typedef Ret type;
-};
-
-template<typename R>
-struct ResultOkType { typedef typename std::decay<R>::type type; };
-
-template<typename T, typename E>
-struct ResultOkType<Rust::Result<T, E>> {
-    typedef T type;
-};
-
-template<typename R>
-struct ResultErrType { typedef R type; };
-
-template<typename T, typename E>
-struct ResultErrType<Rust::Result<T, E>> {
-    typedef typename std::remove_reference<E>::type type;
-};
-
-template<typename R> struct IsResult : public std::false_type { };
-template<typename T, typename E>
-struct IsResult<Rust::Result<T, E>> : public std::true_type { };
-
-namespace ok {
-
-namespace impl {
-
-template<typename T> struct Map;
-
-template<typename Ret, typename Cls, typename Arg>
-struct Map<Ret (Cls::*)(Arg) const> : public Map<Ret (Arg)> { };
-
-template<typename Ret, typename Cls, typename Arg>
-struct Map<Ret (Cls::*)(Arg)> : public Map<Ret (Arg)> { };
-
-// General implementation
-template<typename Ret, typename Arg>
-struct Map<Ret (Arg)> {
-
-    static_assert(!IsResult<Ret>::value,
-            "Can not map a callback returning a Result, use andThen instead");
-
-    template<typename T, typename E, typename Func>
-    static Rust::Result<Ret, E> map(const Rust::Result<T, E>& result, Func func) {
-
-        static_assert(
-                std::is_same<T, Arg>::value ||
-                std::is_convertible<T, Arg>::value,
-                "Incompatible types detected");
-
-        if (result.isOk()) {
-            auto res = func(result.storage().template get<T>());
-            return types::Ok<Ret>(std::move(res));
-        }
-
-        return types::Err<E>(result.storage().template get<E>());
-    }
-};
-
-// Specialization for callback returning void
-template<typename Arg>
-struct Map<void (Arg)> {
-
-    template<typename T, typename E, typename Func>
-    static Rust::Result<void, E> map(const Rust::Result<T, E>& result, Func func) {
-
-        if (result.isOk()) {
-            func(result.storage().template get<T>());
-            return types::Ok<void>();
-        }
-
-        return types::Err<E>(result.storage().template get<E>());
-    }
-};
-
-// Specialization for a void Result
-template<typename Ret>
-struct Map<Ret (void)> {
-
-    template<typename T, typename E, typename Func>
-    static Rust::Result<Ret, E> map(const Rust::Result<T, E>& result, Func func) {
-        static_assert(std::is_same<T, void>::value,
-                "Can not map a void callback on a non-void Result");
-
-        if (result.isOk()) {
-            auto ret = func();
-            return types::Ok<Ret>(std::move(ret));
-        }
-
-        return types::Err<E>(result.storage().template get<E>());
-    }
-};
-
-// Specialization for callback returning void on a void Result
-template<>
-struct Map<void (void)> {
-
-    template<typename T, typename E, typename Func>
-    static Rust::Result<void, E> map(const Rust::Result<T, E>& result, Func func) {
-        static_assert(std::is_same<T, void>::value,
-                "Can not map a void callback on a non-void Result");
-
-        if (result.isOk()) {
-            func();
-            return types::Ok<void>();
-        }
-
-        return types::Err<E>(result.storage().template get<E>());
-    }
-};
-
-// General specialization for a callback returning a Result
-template<typename U, typename E, typename Arg>
-struct Map<Rust::Result<U, E> (Arg)> {
-
-    template<typename T, typename Func>
-    static Rust::Result<U, E> map(const Rust::Result<T, E>& result, Func func) {
-        static_assert(
-                std::is_same<T, Arg>::value ||
-                std::is_convertible<T, Arg>::value,
-                "Incompatible types detected");
-
-        if (result.isOk()) {
-            auto res = func(result.storage().template get<T>());
-            return res;
-        }
-
-        return types::Err<E>(result.storage().template get<E>());
-    }
-};
-
-// Specialization for a void callback returning a Result
-template<typename U, typename E>
-struct Map<Rust::Result<U, E> (void)> {
-
-    template<typename T, typename Func>
-    static Rust::Result<U, E> map(const Rust::Result<T, E>& result, Func func) {
-        static_assert(std::is_same<T, void>::value, "Can not call a void-callback on a non-void Result");
-
-        if (result.isOk()) {
-            auto res = func();
-            return res;
-        }
-
-        return types::Err<E>(result.storage().template get<E>());
-    }
-
-};
-
-} // namespace impl
-
-template<typename Func> struct Map : public impl::Map<decltype(&Func::operator())> { };
-
-template<typename Ret, typename... Args>
-struct Map<Ret (*) (Args...)> : public impl::Map<Ret (Args...)> { };
-
-template<typename Ret, typename Cls, typename... Args>
-struct Map<Ret (Cls::*) (Args...)> : public impl::Map<Ret (Args...)> { };
-
-template<typename Ret, typename Cls, typename... Args>
-struct Map<Ret (Cls::*) (Args...) const> : public impl::Map<Ret (Args...)> { };
-
-template<typename Ret, typename... Args>
-struct Map<std::function<Ret (Args...)>> : public impl::Map<Ret (Args...)> { };
-
-} // namespace ok
-
-
-namespace err {
-
-namespace impl {
-
-template<typename T> struct Map;
-
-template<typename Ret, typename Cls, typename Arg>
-struct Map<Ret (Cls::*)(Arg) const> {
-
-    static_assert(!IsResult<Ret>::value,
-            "Can not map a callback returning a Result, use orElse instead");
-
-    template<typename T, typename E, typename Func>
-    static Rust::Result<T, Ret> map(const Rust::Result<T, E>& result, Func func) {
-        if (result.isErr()) {
-            auto res = func(result.storage().template get<E>());
-            return types::Err<Ret>(res);
-        }
-
-        return types::Ok<T>(result.storage().template get<T>());
-    }
-
-    template<typename E, typename Func>
-    static Rust::Result<void, Ret> map(const Rust::Result<void, E>& result, Func func) {
-        if (result.isErr()) {
-            auto res = func(result.storage().template get<E>());
-            return types::Err<Ret>(res);
-        }
-
-        return types::Ok<void>();
-    }
-
-
-};
-
-} // namespace impl
-
-template<typename Func> struct Map : public impl::Map<decltype(&Func::operator())> { };
-
-} // namespace err;
-
-namespace And {
-
-namespace impl {
-
-    template<typename Func> struct Then;
-
-    template<typename Ret, typename... Args>
-    struct Then<Ret (*)(Args...)> : public Then<Ret (Args...)> { };
-
-    template<typename Ret, typename Cls, typename... Args>
-    struct Then<Ret (Cls::*)(Args...)> : public Then<Ret (Args...)> { };
-
-    template<typename Ret, typename Cls, typename... Args>
-    struct Then<Ret (Cls::*)(Args...) const> : public Then<Ret (Args...)> { };
-
-    template<typename Ret, typename Arg>
-    struct Then<Ret (Arg)> {
-        static_assert(std::is_same<Ret, void>::value,
-                "then() should not return anything, use map() instead");
-
-        template<typename T, typename E, typename Func>
-        static Rust::Result<T, E> then(const Rust::Result<T, E>& result, Func func) {
-            if (result.isOk()) {
-                func(result.storage().template get<T>());
-            }
-            return result;
-        }
-    };
-
-    template<typename Ret>
-    struct Then<Ret (void)> {
-        static_assert(std::is_same<Ret, void>::value,
-                "then() should not return anything, use map() instead");
-
-        template<typename T, typename E, typename Func>
-        static Rust::Result<T, E> then(const Rust::Result<T, E>& result, Func func) {
-            static_assert(std::is_same<T, void>::value, "Can not call a void-callback on a non-void Result");
-
-            if (result.isOk()) {
-                func();
-            }
-
-            return result;
-        }
-    };
-
-
-} // namespace impl
-
-template<typename Func>
-struct Then : public impl::Then<decltype(&Func::operator())> { };
-
-template<typename Ret, typename... Args>
-struct Then<Ret (*) (Args...)> : public impl::Then<Ret (Args...)> { };
-
-template<typename Ret, typename Cls, typename... Args>
-struct Then<Ret (Cls::*)(Args...)> : public impl::Then<Ret (Args...)> { };
-
-template<typename Ret, typename Cls, typename... Args>
-struct Then<Ret (Cls::*)(Args...) const> : public impl::Then<Ret (Args...)> { };
-
-} // namespace And
-
-namespace Or {
-
-namespace impl {
-
-    template<typename Func> struct Else;
-
-    template<typename Ret, typename... Args>
-    struct Else<Ret (*)(Args...)> : public Else<Ret (Args...)> { };
-
-    template<typename Ret, typename Cls, typename... Args>
-    struct Else<Ret (Cls::*)(Args...)> : public Else<Ret (Args...)> { };
-
-    template<typename Ret, typename Cls, typename... Args>
-    struct Else<Ret (Cls::*)(Args...) const> : public Else<Ret (Args...)> { };
-
-    template<typename T, typename F, typename Arg>
-    struct Else<Rust::Result<T, F> (Arg)> {
-
-        template<typename E, typename Func>
-        static Rust::Result<T, F> orElse(const Rust::Result<T, E>& result, Func func) {
-            static_assert(
-                    std::is_same<E, Arg>::value ||
-                    std::is_convertible<E, Arg>::value,
-                    "Incompatible types detected");
-
-            if (result.isErr()) {
-                auto res = func(result.storage().template get<E>());
-                return res;
-            }
-
-            return types::Ok<T>(result.storage().template get<T>());
-        }
-
-        template<typename E, typename Func>
-        static Rust::Result<void, F> orElse(const Rust::Result<void, E>& result, Func func) {
-            if (result.isErr()) {
-                auto res = func(result.storage().template get<E>());
-                return res;
-            }
-
-            return types::Ok<void>();
-        }
-
-    };
-
-    template<typename T, typename F>
-    struct Else<Rust::Result<T, F> (void)> {
-
-        template<typename E, typename Func>
-        static Rust::Result<T, F> orElse(const Rust::Result<T, E>& result, Func func) {
-            static_assert(std::is_same<T, void>::value,
-                    "Can not call a void-callback on a non-void Result");
-
-            if (result.isErr()) {
-                auto res = func();
-                return res;
-            }
-
-            return types::Ok<T>(result.storage().template get<T>());
-        }
-
-        template<typename E, typename Func>
-        static Rust::Result<void, F> orElse(const Rust::Result<void, E>& result, Func func) {
-            if (result.isErr()) {
-                auto res = func();
-                return res;
-            }
-
-            return types::Ok<void>();
-        }
-
-    };
-
-} // namespace impl
-
-template<typename Func>
-struct Else : public impl::Else<decltype(&Func::operator())> { };
-
-template<typename Ret, typename... Args>
-struct Else<Ret (*) (Args...)> : public impl::Else<Ret (Args...)> { };
-
-template<typename Ret, typename Cls, typename... Args>
-struct Else<Ret (Cls::*)(Args...)> : public impl::Else<Ret (Args...)> { };
-
-template<typename Ret, typename Cls, typename... Args>
-struct Else<Ret (Cls::*)(Args...) const> : public impl::Else<Ret (Args...)> { };
-
-} // namespace Or
-
-namespace Other {
-
-namespace impl {
-
-    template<typename Func> struct Wise;
-
-    template<typename Ret, typename... Args>
-    struct Wise<Ret (*)(Args...)> : public Wise<Ret (Args...)> { };
-
-    template<typename Ret, typename Cls, typename... Args>
-    struct Wise<Ret (Cls::*)(Args...)> : public Wise<Ret (Args...)> { };
-
-    template<typename Ret, typename Cls, typename... Args>
-    struct Wise<Ret (Cls::*)(Args...) const> : public Wise<Ret (Args...)> { };
-
-    template<typename Ret, typename Arg>
-    struct Wise<Ret (Arg)> {
-
-        template<typename T, typename E, typename Func>
-        static Rust::Result<T, E> otherwise(const Rust::Result<T, E>& result, Func func) {
-            static_assert(
-                    std::is_same<E, Arg>::value ||
-                    std::is_convertible<E, Arg>::value,
-                    "Incompatible types detected");
-
-            static_assert(std::is_same<Ret, void>::value,
-                    "callback should not return anything, use mapError() for that");
-
-            if (result.isErr()) {
-                func(result.storage().template get<E>());
-            }
-            return result;
-        }
-
-    };
-
-} // namespace impl
-
-template<typename Func>
-struct Wise : public impl::Wise<decltype(&Func::operator())> { };
-
-template<typename Ret, typename... Args>
-struct Wise<Ret (*) (Args...)> : public impl::Wise<Ret (Args...)> { };
-
-template<typename Ret, typename Cls, typename... Args>
-struct Wise<Ret (Cls::*)(Args...)> : public impl::Wise<Ret (Args...)> { };
-
-template<typename Ret, typename Cls, typename... Args>
-struct Wise<Ret (Cls::*)(Args...) const> : public impl::Wise<Ret (Args...)> { };
-
-} // namespace Other
-
-template<typename T, typename E, typename Func,
-         typename Ret =
-            Rust::Result<
-                typename details::ResultOkType<
-                    typename details::result_of<Func>::type
-                >::type,
-            E>
-        >
-Ret map(const Rust::Result<T, E>& result, Func func) {
-    return ok::Map<Func>::map(result, func);
-}
-
-template<typename T, typename E, typename Func,
-         typename Ret =
-            Rust::Result<T,
-                typename details::ResultErrType<
-                    typename details::result_of<Func>::type
-                >::type
-            >
-        >
-Ret mapError(const Rust::Result<T, E>& result, Func func) {
-    return err::Map<Func>::map(result, func);
-}
-
-template<typename T, typename E, typename Func>
-Rust::Result<T, E> then(const Rust::Result<T, E>& result, Func func) {
-    return And::Then<Func>::then(result, func);
-}
-
-template<typename T, typename E, typename Func>
-Rust::Result<T, E> otherwise(const Rust::Result<T, E>& result, Func func) {
-    return Other::Wise<Func>::otherwise(result, func);
-}
-
-template<typename T, typename E, typename Func,
-    typename Ret =
-        Rust::Result<T,
-            typename details::ResultErrType<
-                typename details::result_of<Func>::type
-            >::type
-       >
->
-Ret orElse(const Rust::Result<T, E>& result, Func func) {
-    return Or::Else<Func>::orElse(result, func);
-}
-
-struct ok_tag { };
-struct err_tag { };
-
-template<typename T, typename E>
-struct Storage {
-    static constexpr size_t Size = sizeof(T) > sizeof(E) ? sizeof(T) : sizeof(E);
-    static constexpr size_t Align = sizeof(T) > sizeof(E) ? alignof(T) : alignof(E);
-
-    typedef typename std::aligned_storage<Size, Align>::type type;
-
-    Storage()
-        : initialized_(false)
-    { }
-
-    void construct(types::Ok<T> ok)
-    {
-        new (&storage_) T(ok.val);
-        initialized_ = true;
-    }
-    void construct(types::Err<E> err)
-    {
-        new (&storage_) E(err.val);
-        initialized_ = true;
-    }
-
-    template<typename U>
-    void rawConstruct(U&& val) {
-        typedef typename std::decay<U>::type CleanU;
-
-        new (&storage_) CleanU(std::forward<U>(val));
-        initialized_ = true;
-    }
-
-    template<typename U>
-    const U& get() const {
-        return *reinterpret_cast<const U *>(&storage_);
-    }
-
-    template<typename U>
-    U& get() {
-        return *reinterpret_cast<U *>(&storage_);
-    }
-
-    void destroy(ok_tag) {
-        if (initialized_) {
-            get<T>().~T();
-            initialized_ = false;
-        }
-    }
-
-    void destroy(err_tag) {
-        if (initialized_) {
-            get<E>().~E();
-            initialized_ = false;
-        }
-    }
-
-    type storage_;
-    bool initialized_;
-};
-
-template<typename E>
-struct Storage<void, E> {
-    typedef typename std::aligned_storage<sizeof(E), alignof(E)>::type type;
-
-    void construct(types::Ok<void>)
-    {
-        initialized_ = true;
-    }
-
-    void construct(types::Err<E> err)
-    {
-        new (&storage_) E(err.val);
-        initialized_ = true;
-    }
-
-    template<typename U>
-    void rawConstruct(U&& val) {
-        typedef typename std::decay<U>::type CleanU;
-
-        new (&storage_) CleanU(std::forward<U>(val));
-        initialized_ = true;
-    }
-
-    void destroy(ok_tag) { initialized_ = false; }
-    void destroy(err_tag) {
-        if (initialized_) {
-            get<E>().~E(); initialized_ = false;
-        }
-    }
-
-    template<typename U>
-    const U& get() const {
-        return *reinterpret_cast<const U *>(&storage_);
-    }
-
-    template<typename U>
-    U& get() {
-        return *reinterpret_cast<U *>(&storage_);
-    }
-
-    type storage_;
-    bool initialized_;
-};
-
-template<typename T, typename E>
-struct Constructor {
-
-    static void move(Storage<T, E>&& src, Storage<T, E>& dst, ok_tag) {
-        dst.rawConstruct(std::move(src.template get<T>()));
-        src.destroy(ok_tag());
-    }
-
-    static void copy(const Storage<T, E>& src, Storage<T, E>& dst, ok_tag) {
-        dst.rawConstruct(src.template get<T>());
-    }
-
-    static void move(Storage<T, E>&& src, Storage<T, E>& dst, err_tag) {
-        dst.rawConstruct(std::move(src.template get<E>()));
-        src.destroy(err_tag());
-    }
-
-    static void copy(const Storage<T, E>& src, Storage<T, E>& dst, err_tag) {
-        dst.rawConstruct(src.template get<E>());
-    }
-};
-
-template<typename E>
-struct Constructor<void, E> {
-    static void move(Storage<void, E>&& src, Storage<void, E>& dst, ok_tag) {
-    }
-
-    static void copy(const Storage<void, E>& src, Storage<void, E>& dst, ok_tag) {
-    }
-
-    static void move(Storage<void, E>&& src, Storage<void, E>& dst, err_tag) {
-        dst.rawConstruct(std::move(src.template get<E>()));
-        src.destroy(err_tag());
-    }
-
-    static void copy(const Storage<void, E>& src, Storage<void, E>& dst, err_tag) {
-        dst.rawConstruct(src.template get<E>());
-    }
-};
-
-} // namespace details
-
-namespace rpog {
-
-template<typename T, typename = void> struct EqualityComparable : std::false_type { };
-
-template<typename T>
-struct EqualityComparable<T,
-typename std::enable_if<
-    true,
-    typename details::void_t<decltype(std::declval<T>() == std::declval<T>())>::type
-    >::type
-> : std::true_type
-{
-};
-
-
-} // namespace rpog
-
-namespace Rust {
-template<typename T, typename E>
-struct Result {
-
-    static_assert(!std::is_same<E, void>::value, "void error type is not allowed");
-
-    typedef details::Storage<T, E> storage_type;
-
-    Result(types::Ok<T> ok)
-        : ok_(true)
-    {
-        storage_.construct(std::move(ok));
-    }
-
-    Result(types::Err<E> err)
-        : ok_(false)
-    {
-        storage_.construct(std::move(err));
-    }
-
-    Result(Result&& other) {
-        if (other.isOk()) {
-            details::Constructor<T, E>::move(std::move(other.storage_), storage_, details::ok_tag());
-            ok_ = true;
-        } else {
-            details::Constructor<T, E>::move(std::move(other.storage_), storage_, details::err_tag());
-            ok_ = false;
-        }
-    }
-
-    Result(const Result& other) {
-        if (other.isOk()) {
-            details::Constructor<T, E>::copy(other.storage_, storage_, details::ok_tag());
-            ok_ = true;
-        } else {
-            details::Constructor<T, E>::copy(other.storage_, storage_, details::err_tag());
-            ok_ = false;
-        }
-    }
-
-    ~Result() {
-        if (ok_)
-            storage_.destroy(details::ok_tag());
-        else
-            storage_.destroy(details::err_tag());
-    }
-
-    bool isOk() const {
-        return ok_;
-    }
-
-    bool isErr() const {
-        return !ok_;
-    }
-
-    T expect(const char* str) const {
-        if (!isOk()) {
-            std::fprintf(stderr, "%s\n", str);
-            std::terminate(); 
-        }
-        return expect_impl(std::is_same<T, void>());
-    }
-
-    template<typename Func,
-             typename Ret =
-                Result<
-                    typename details::ResultOkType<
-                        typename details::result_of<Func>::type
-                    >::type,
-                E>
-            >
-    Ret map(Func func) const {
-        return details::map(*this, func);
-    }
-
-    template<typename Func,
-         typename Ret =
-             Result<T,
-                typename details::ResultErrType<
-                    typename details::result_of<Func>::type
-                >::type
-            >
-    >
-    Ret mapError(Func func) const {
-        return details::mapError(*this, func);
-    }
-
-    template<typename Func>
-    Result<T, E> then(Func func) const {
-        return details::then(*this, func);
-    }
-
-    template<typename Func>
-    Result<T, E> otherwise(Func func) const {
-        return details::otherwise(*this, func);
-    }
-
-    template<typename Func,
-        typename Ret =
-            Result<T,
-                typename details::ResultErrType<
-                    typename details::result_of<Func>::type
-                >::type
-           >
-    >
-    Ret orElse(Func func) const {
-        return details::orElse(*this, func);
-    }
-
-    storage_type& storage() {
-        return storage_;
-    }
-
-    const storage_type& storage() const {
-        return storage_;
-    }
-
-    template<typename U = T>
-    typename std::enable_if<
-        !std::is_same<U, void>::value,
-        U
-    >::type
-    unwrapOr(const U& defaultValue) const {
-        if (isOk()) {
-            return storage().template get<U>();
-        }
-        return defaultValue;
-    }
-
-    template<typename U = T>
-    typename std::enable_if<
-        !std::is_same<U, void>::value,
-        U
-    >::type
-    unwrap() const {
-        if (isOk()) {
-            return storage().template get<U>();
-        }
-
-        std::fprintf(stderr, "Attempting to unwrap an error Result\n");
-        std::terminate();
-    }
-
-    E unwrapErr() const {
-        if (isErr()) {
-            return storage().template get<E>();
-        }
-
-        std::fprintf(stderr, "Attempting to unwrapErr an ok Result\n");
-        std::terminate();
-    }
-
-private:
-    T expect_impl(std::true_type) const { }
-    T expect_impl(std::false_type) const { return storage_.template get<T>(); }
-
-    bool ok_;
-    storage_type storage_;
-};
-
-template<typename T, typename E>
-bool operator==(const Rust::Result<T, E>& lhs, const Rust::Result<T, E>& rhs) {
-    static_assert(rpog::EqualityComparable<T>::value, "T must be EqualityComparable for Result to be comparable");
-    static_assert(rpog::EqualityComparable<E>::value, "E must be EqualityComparable for Result to be comparable");
-
-    if (lhs.isOk() && rhs.isOk()) {
-        return lhs.storage().template get<T>() == rhs.storage().template get<T>();
-    }
-    if (lhs.isErr() && rhs.isErr()) {
-        return lhs.storage().template get<E>() == rhs.storage().template get<E>();
-    }
-}
-
-template<typename T, typename E>
-bool operator==(const Rust::Result<T, E>& lhs, types::Ok<T> ok) {
-    static_assert(rpog::EqualityComparable<T>::value, "T must be EqualityComparable for Result to be comparable");
-
-    if (!lhs.isOk()) return false;
-
-    return lhs.storage().template get<T>() == ok.val;
-}
-
-template<typename E>
-bool operator==(const Rust::Result<void, E>& lhs, types::Ok<void>) {
-    return lhs.isOk();
-}
-
-template<typename T, typename E>
-bool operator==(const Rust::Result<T, E>& lhs, types::Err<E> err) {
-    static_assert(rpog::EqualityComparable<E>::value, "E must be EqualityComparable for Result to be comparable");
-    if (!lhs.isErr()) return false;
-
-    return lhs.storage().template get<E>() == err.val;
-}
-} // end namespace Rust
-
-#define TRY(...)                                                   \
-    ({                                                             \
-        auto res = __VA_ARGS__;                                    \
-        if (!res.isOk()) {                                         \
-            typedef details::ResultErrType<decltype(res)>::type E; \
-            return types::Err<E>(res.storage().get<E>());          \
-        }                                                          \
-        typedef details::ResultOkType<decltype(res)>::type T;      \
-        res.storage().get<T>();                                    \
-    })