ams: support building unit test programs on windows/linux/macos

This commit is contained in:
Michael Scire
2022-03-06 12:08:20 -08:00
committed by SciresM
parent 9a38be201a
commit 64a97576d0
756 changed files with 33359 additions and 9372 deletions

View File

@@ -38,23 +38,4 @@ namespace ams::fs::impl {
}
};
class RemoteEventNotifierObjectAdapter final : public ::ams::fs::IEventNotifier, public ::ams::fs::impl::Newable {
private:
::FsEventNotifier m_notifier;
public:
RemoteEventNotifierObjectAdapter(::FsEventNotifier &n) : m_notifier(n) { /* ... */ }
virtual ~RemoteEventNotifierObjectAdapter() { fsEventNotifierClose(std::addressof(m_notifier)); }
private:
virtual Result DoBindEvent(os::SystemEventType *out, os::EventClearMode clear_mode) override {
/* Get the handle. */
::Event e;
R_TRY(fsEventNotifierGetEventHandle(std::addressof(m_notifier), std::addressof(e), false));
/* Create the system event. */
os::AttachReadableHandleToSystemEvent(out, e.revent, true, clear_mode);
return ResultSuccess();
}
};
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::fs::impl {
sf::SharedPointer<fssrv::sf::IFileSystemProxy> GetFileSystemProxyServiceObject();
sf::SharedPointer<fssrv::sf::IFileSystemProxyForLoader> GetFileSystemProxyForLoaderServiceObject();
}

View File

@@ -0,0 +1,263 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::fs::impl {
class FileServiceObjectAdapter : public ::ams::fs::impl::Newable, public ::ams::fs::fsa::IFile {
NON_COPYABLE(FileServiceObjectAdapter);
NON_MOVEABLE(FileServiceObjectAdapter);
private:
sf::SharedPointer<fssrv::sf::IFile> m_x;
public:
explicit FileServiceObjectAdapter(sf::SharedPointer<fssrv::sf::IFile> &&o) : m_x(o) { /* ... */}
virtual ~FileServiceObjectAdapter() { /* ... */ }
public:
virtual Result DoRead(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) override final {
s64 read_size = 0;
R_TRY(m_x->Read(std::addressof(read_size), offset, sf::OutNonSecureBuffer(buffer, size), static_cast<s64>(size), option));
*out = static_cast<size_t>(read_size);
R_SUCCEED();
}
virtual Result DoGetSize(s64 *out) override final {
R_RETURN(m_x->GetSize(out));
}
virtual Result DoFlush() override final {
R_RETURN(m_x->Flush());
}
virtual Result DoWrite(s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) override final {
R_RETURN(m_x->Write(offset, sf::InNonSecureBuffer(buffer, size), static_cast<s64>(size), option));
}
virtual Result DoSetSize(s64 size) override final {
R_RETURN(m_x->SetSize(size));
}
virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final {
switch (op_id) {
case OperationId::Invalidate:
{
fs::QueryRangeInfo dummy_range_info;
R_RETURN(m_x->OperateRange(std::addressof(dummy_range_info), static_cast<s32>(op_id), offset, size));
}
case OperationId::QueryRange:
{
R_UNLESS(dst != nullptr, fs::ResultNullptrArgument());
R_UNLESS(dst_size == sizeof(fs::QueryRangeInfo), fs::ResultInvalidSize());
R_RETURN(m_x->OperateRange(reinterpret_cast<fs::QueryRangeInfo *>(dst), static_cast<s32>(op_id), offset, size));
}
default:
{
R_RETURN(m_x->OperateRangeWithBuffer(sf::OutNonSecureBuffer(dst, dst_size), sf::InNonSecureBuffer(src, src_size), static_cast<s32>(op_id), offset, size));
}
}
}
public:
virtual sf::cmif::DomainObjectId GetDomainObjectId() const override final {
AMS_ABORT("Invalid GetDomainObjectId call");
}
};
class DirectoryServiceObjectAdapter : public ::ams::fs::impl::Newable, public ::ams::fs::fsa::IDirectory {
NON_COPYABLE(DirectoryServiceObjectAdapter);
NON_MOVEABLE(DirectoryServiceObjectAdapter);
private:
sf::SharedPointer<fssrv::sf::IDirectory> m_x;
public:
explicit DirectoryServiceObjectAdapter(sf::SharedPointer<fssrv::sf::IDirectory> &&o) : m_x(o) { /* ... */}
virtual ~DirectoryServiceObjectAdapter() { /* ... */ }
public:
virtual Result DoRead(s64 *out_count, DirectoryEntry *out_entries, s64 max_entries) override final {
R_RETURN(m_x->Read(out_count, sf::OutBuffer(out_entries, max_entries * sizeof(*out_entries))));
}
virtual Result DoGetEntryCount(s64 *out) override final {
R_RETURN(m_x->GetEntryCount(out));
}
public:
virtual sf::cmif::DomainObjectId GetDomainObjectId() const override final {
AMS_ABORT("Invalid GetDomainObjectId call");
}
};
class FileSystemServiceObjectAdapter : public ::ams::fs::impl::Newable, public ::ams::fs::fsa::IFileSystem {
NON_COPYABLE(FileSystemServiceObjectAdapter);
NON_MOVEABLE(FileSystemServiceObjectAdapter);
private:
sf::SharedPointer<fssrv::sf::IFileSystem> m_x;
public:
explicit FileSystemServiceObjectAdapter(sf::SharedPointer<fssrv::sf::IFileSystem> &&o) : m_x(o) { /* ... */}
virtual ~FileSystemServiceObjectAdapter() { /* ... */ }
sf::SharedPointer<fssrv::sf::IFileSystem> GetFileSystem() const { return m_x; }
private:
static Result GetPathForServiceObject(fssrv::sf::Path *out, const fs::Path &path) {
const size_t len = util::Strlcpy<char>(out->str, path.GetString(), sizeof(out->str));
R_UNLESS(len < sizeof(out->str), fs::ResultTooLongPath());
R_SUCCEED();
}
private:
virtual Result DoOpenFile(std::unique_ptr<fsa::IFile> *out_file, const fs::Path &path, OpenMode mode) override final {
/* Convert the path. */
fssrv::sf::Path fsp_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_path), path));
/* Open the file. */
sf::SharedPointer<fssrv::sf::IFile> file;
R_TRY(m_x->OpenFile(std::addressof(file), fsp_path, mode));
/* Create the output fsa file. */
out_file->reset(new FileServiceObjectAdapter(std::move(file)));
R_UNLESS(out_file != nullptr, fs::ResultAllocationFailureInNew());
R_SUCCEED();
}
virtual Result DoOpenDirectory(std::unique_ptr<fsa::IDirectory> *out_dir, const fs::Path &path, OpenDirectoryMode mode) override final {
/* Convert the path. */
fssrv::sf::Path fsp_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_path), path));
/* Open the directory. */
sf::SharedPointer<fssrv::sf::IDirectory> dir;
R_TRY(m_x->OpenDirectory(std::addressof(dir), fsp_path, mode));
/* Create the output fsa directory. */
out_dir->reset(new DirectoryServiceObjectAdapter(std::move(dir)));
R_UNLESS(out_dir != nullptr, fs::ResultAllocationFailureInNew());
R_SUCCEED();
}
virtual Result DoGetEntryType(DirectoryEntryType *out, const fs::Path &path) override final {
/* Convert the path. */
fssrv::sf::Path fsp_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_path), path));
R_RETURN(m_x->GetEntryType(out, fsp_path));
}
virtual Result DoCommit() override final {
R_RETURN(m_x->Commit());
}
virtual Result DoCreateFile(const fs::Path &path, s64 size, int flags) override final {
/* Convert the path. */
fssrv::sf::Path fsp_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_path), path));
R_RETURN(m_x->CreateFile(fsp_path, size, flags));
}
virtual Result DoDeleteFile(const fs::Path &path) override final {
/* Convert the path. */
fssrv::sf::Path fsp_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_path), path));
R_RETURN(m_x->DeleteFile(fsp_path));
}
virtual Result DoCreateDirectory(const fs::Path &path) override final {
/* Convert the path. */
fssrv::sf::Path fsp_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_path), path));
R_RETURN(m_x->CreateDirectory(fsp_path));
}
virtual Result DoDeleteDirectory(const fs::Path &path) override final {
/* Convert the path. */
fssrv::sf::Path fsp_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_path), path));
R_RETURN(m_x->DeleteDirectory(fsp_path));
}
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override final {
/* Convert the path. */
fssrv::sf::Path fsp_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_path), path));
R_RETURN(m_x->DeleteDirectoryRecursively(fsp_path));
}
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override final {
/* Convert the path. */
fssrv::sf::Path fsp_old_path;
fssrv::sf::Path fsp_new_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_old_path), old_path));
R_TRY(GetPathForServiceObject(std::addressof(fsp_new_path), new_path));
R_RETURN(m_x->RenameFile(fsp_old_path, fsp_new_path));
}
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override final {
/* Convert the path. */
fssrv::sf::Path fsp_old_path;
fssrv::sf::Path fsp_new_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_old_path), old_path));
R_TRY(GetPathForServiceObject(std::addressof(fsp_new_path), new_path));
R_RETURN(m_x->RenameDirectory(fsp_old_path, fsp_new_path));
}
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) override final {
/* Convert the path. */
fssrv::sf::Path fsp_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_path), path));
R_RETURN(m_x->CleanDirectoryRecursively(fsp_path));
}
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) override final {
/* Convert the path. */
fssrv::sf::Path fsp_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_path), path));
R_RETURN(m_x->GetFreeSpaceSize(out, fsp_path));
}
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) override final {
/* Convert the path. */
fssrv::sf::Path fsp_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_path), path));
R_RETURN(m_x->GetTotalSpaceSize(out, fsp_path));
}
virtual Result DoGetFileTimeStampRaw(fs::FileTimeStampRaw *out, const fs::Path &path) override final {
/* Convert the path. */
fssrv::sf::Path fsp_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_path), path));
R_RETURN(m_x->GetFileTimeStampRaw(out, fsp_path));
}
virtual Result DoQueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fs::fsa::QueryId query, const fs::Path &path) override {
fssrv::sf::Path fsp_path;
R_TRY(GetPathForServiceObject(std::addressof(fsp_path), path));
R_RETURN(m_x->QueryEntry(sf::OutBuffer(dst, dst_size), sf::InBuffer(src, src_size), static_cast<s32>(query), fsp_path));
}
};
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include <stratosphere/fssrv/fssrv_interface_adapters.hpp>
#include "fs_library.hpp"
#include "fs_file_system_service_object_adapter.hpp"
#include "../../fssrv/impl/fssrv_allocator_for_service_framework.hpp"
namespace ams::fs::impl {
#if !defined(ATMOSPHERE_OS_HORIZON)
namespace {
constexpr size_t SystemHeapSize = 8_MB;
alignas(os::MemoryPageSize) constinit u8 g_system_heap[SystemHeapSize];
ALWAYS_INLINE auto &GetSystemHeapAllocator() {
AMS_FUNCTION_LOCAL_STATIC(mem::StandardAllocator, s_system_heap_allocator, g_system_heap, sizeof(g_system_heap));
return s_system_heap_allocator;
}
constinit util::optional<fssrv::MemoryResourceFromStandardAllocator> g_system_heap_memory_resource;
void *AllocateForSystem(size_t size) { return g_system_heap_memory_resource->Allocate(size); }
void DeallocateForSystem(void *p, size_t size) { return g_system_heap_memory_resource->Deallocate(p, size); }
[[maybe_unused]] constexpr size_t BufferPoolSize = 6_MB;
[[maybe_unused]] constexpr size_t DeviceBufferSize = 8_MB;
[[maybe_unused]] constexpr size_t BufferManagerHeapSize = 14_MB;
static_assert(util::IsAligned(BufferManagerHeapSize, os::MemoryBlockUnitSize));
//alignas(os::MemoryPageSize) u8 g_buffer_pool[BufferPoolSize];
//alignas(os::MemoryPageSize) u8 g_device_buffer[DeviceBufferSize];
//alignas(os::MemoryPageSize) u8 g_buffer_manager_heap[BufferManagerHeapSize];
//
//alignas(os::MemoryPageSize) u8 g_buffer_manager_work_buffer[64_KB];
/* TODO: Other work buffers. */
/* TODO: Implement pooled threads. */
// constexpr int PooledThreadCount = 12;
// constexpr size_t PooledThreadStackSize = 32_KB;
// fssystem::PooledThread g_pooled_threads[PooledThreadCount];
/* FileSystem creators. */
constinit util::optional<fssrv::fscreator::LocalFileSystemCreator> g_local_fs_creator;
constinit util::optional<fssrv::fscreator::SubDirectoryFileSystemCreator> g_subdir_fs_creator;
constinit fssrv::fscreator::FileSystemCreatorInterfaces g_fs_creator_interfaces = {};
Result InitializeFileSystemLibraryImpl() {
/* Set system allocator. */
fssystem::InitializeAllocator(::ams::fs::impl::Allocate, ::ams::fs::impl::Deallocate);
fssystem::InitializeAllocatorForSystem(::ams::fs::impl::AllocateForSystem, ::ams::fs::impl::DeallocateForSystem);
/* TODO: Many things. */
g_system_heap_memory_resource.emplace(std::addressof(GetSystemHeapAllocator()));
/* Setup fscreators/interfaces. */
g_local_fs_creator.emplace(true);
g_subdir_fs_creator.emplace();
g_fs_creator_interfaces.local_fs_creator = std::addressof(*g_local_fs_creator);
g_fs_creator_interfaces.subdir_fs_creator = std::addressof(*g_subdir_fs_creator);
/* Initialize fssrv. */
const fssrv::FileSystemProxyConfiguration config = {
.m_fs_creator_interfaces = std::addressof(g_fs_creator_interfaces),
.m_base_storage_service_impl = nullptr /* TODO */,
.m_base_file_system_service_impl = nullptr /* TODO */,
.m_nca_file_system_service_impl = nullptr /* TODO */,
.m_save_data_file_system_service_impl = nullptr /* TODO */,
.m_access_failure_management_service_impl = nullptr /* TODO */,
.m_time_service_impl = nullptr /* TODO */,
.m_status_report_service_impl = nullptr /* TODO */,
.m_program_registry_service_impl = nullptr /* TODO */,
.m_access_log_service_impl = nullptr /* TODO */,
.m_debug_configuration_service_impl = nullptr /* TODO */,
};
fssrv::InitializeForFileSystemProxy(config);
R_SUCCEED();
}
class FileSystemLibraryInitializer {
public:
FileSystemLibraryInitializer() {
R_ABORT_UNLESS(InitializeFileSystemLibraryImpl());
}
};
}
#endif
void InitializeFileSystemLibrary() {
#if !defined(ATMOSPHERE_OS_HORIZON)
AMS_FUNCTION_LOCAL_STATIC(FileSystemLibraryInitializer, s_library_initializer);
AMS_UNUSED(s_library_initializer);
#endif
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::fs::impl {
void InitializeFileSystemLibrary();
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::fs::impl {
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteDeviceOperator {
private:
::FsDeviceOperator m_operator;
public:
RemoteDeviceOperator(::FsDeviceOperator &o) : m_operator(o) { /* ... */ }
virtual ~RemoteDeviceOperator() {
fsDeviceOperatorClose(std::addressof(m_operator));
}
public:
Result IsSdCardInserted(ams::sf::Out<bool> out) {
R_RETURN(fsDeviceOperatorIsSdCardInserted(std::addressof(m_operator), out.GetPointer()));
}
Result IsGameCardInserted(ams::sf::Out<bool> out) {
R_RETURN(fsDeviceOperatorIsGameCardInserted(std::addressof(m_operator), out.GetPointer()));
}
Result GetGameCardHandle(ams::sf::Out<u32> out) {
static_assert(sizeof(::FsGameCardHandle) == sizeof(u32));
R_RETURN(fsDeviceOperatorGetGameCardHandle(std::addressof(m_operator), reinterpret_cast<::FsGameCardHandle *>(out.GetPointer())));
}
};
static_assert(fssrv::sf::IsIDeviceOperator<RemoteDeviceOperator>);
#endif
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::fs::impl {
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteEventNotifier {
private:
::FsEventNotifier m_notifier;
public:
RemoteEventNotifier(::FsEventNotifier &n) : m_notifier(n) { /* ... */ }
virtual ~RemoteEventNotifier() {
fsEventNotifierClose(std::addressof(m_notifier));
}
public:
Result GetEventHandle(ams::sf::OutCopyHandle out) {
::Event e;
R_TRY(fsEventNotifierGetEventHandle(std::addressof(m_notifier), std::addressof(e), false));
out.SetValue(e.revent, true);
R_SUCCEED();
}
};
static_assert(fssrv::sf::IsIEventNotifier<RemoteEventNotifier>);
#endif
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::fs::impl {
class StorageServiceObjectAdapter : public ::ams::fs::impl::Newable, public ::ams::fs::IStorage {
NON_COPYABLE(StorageServiceObjectAdapter);
NON_MOVEABLE(StorageServiceObjectAdapter);
private:
sf::SharedPointer<fssrv::sf::IStorage> m_x;
public:
explicit StorageServiceObjectAdapter(sf::SharedPointer<fssrv::sf::IStorage> &&o) : m_x(o) { /* ... */}
virtual ~StorageServiceObjectAdapter() { /* ... */ }
public:
virtual Result Read(s64 offset, void *buffer, size_t size) override final {
R_RETURN(m_x->Read(offset, sf::OutNonSecureBuffer(buffer, size), static_cast<s64>(size)));
}
virtual Result GetSize(s64 *out) override final {
R_RETURN(m_x->GetSize(out));
}
virtual Result Flush() override final {
R_RETURN(m_x->Flush());
}
virtual Result Write(s64 offset, const void *buffer, size_t size) override final {
R_RETURN(m_x->Write(offset, sf::InNonSecureBuffer(buffer, size), static_cast<s64>(size)));
}
virtual Result SetSize(s64 size) override final {
R_RETURN(m_x->SetSize(size));
}
virtual Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final {
AMS_UNUSED(src, src_size);
switch (op_id) {
case OperationId::Invalidate:
{
fs::QueryRangeInfo dummy_range_info;
R_RETURN(m_x->OperateRange(std::addressof(dummy_range_info), static_cast<s32>(op_id), offset, size));
}
case OperationId::QueryRange:
{
R_UNLESS(dst != nullptr, fs::ResultNullptrArgument());
R_UNLESS(dst_size == sizeof(fs::QueryRangeInfo), fs::ResultInvalidSize());
R_RETURN(m_x->OperateRange(reinterpret_cast<fs::QueryRangeInfo *>(dst), static_cast<s32>(op_id), offset, size));
}
default:
{
R_THROW(fs::ResultUnsupportedOperationInStorageServiceObjectAdapterA());
}
}
}
};
}