rpcs3/rpcs3/util/serialization_ext.hpp
2024-03-25 12:05:24 +02:00

139 lines
4.5 KiB
C++

#pragma once
#include "util/serialization.hpp"
#include "Utilities/Thread.h"
namespace fs
{
class file;
}
// Uncompressed file serialization handler
struct uncompressed_serialization_file_handler : utils::serialization_file_handler
{
const std::unique_ptr<fs::file> m_file_storage;
const std::add_pointer_t<const fs::file> m_file;
explicit uncompressed_serialization_file_handler(fs::file&& file) noexcept
: utils::serialization_file_handler()
, m_file_storage(std::make_unique<fs::file>(std::move(file)))
, m_file(m_file_storage.get())
{
}
explicit uncompressed_serialization_file_handler(const fs::file& file) noexcept
: utils::serialization_file_handler()
, m_file_storage(nullptr)
, m_file(std::addressof(file))
{
}
uncompressed_serialization_file_handler(const uncompressed_serialization_file_handler&) = delete;
uncompressed_serialization_file_handler& operator=(const uncompressed_serialization_file_handler&) = delete;
// Handle file read and write requests
bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override;
// Get available memory or file size
// Preferably memory size if is already greater/equal to recommended to avoid additional file ops
usz get_size(const utils::serial& ar, usz recommended) const override;
void finalize(utils::serial& ar) override;
};
template <typename File> requires (std::is_same_v<std::remove_cvref_t<File>, fs::file>)
inline std::unique_ptr<uncompressed_serialization_file_handler> make_uncompressed_serialization_file_handler(File&& file)
{
ensure(file);
return std::make_unique<uncompressed_serialization_file_handler>(std::forward<File>(file));
}
struct compressed_stream_data;
// Compressed file serialization handler
struct compressed_serialization_file_handler : utils::serialization_file_handler
{
explicit compressed_serialization_file_handler(fs::file&& file) noexcept
: utils::serialization_file_handler()
, m_file_storage(std::make_unique<fs::file>(std::move(file)))
, m_file(m_file_storage.get())
{
}
explicit compressed_serialization_file_handler(const fs::file& file) noexcept
: utils::serialization_file_handler()
, m_file_storage(nullptr)
, m_file(std::addressof(file))
{
}
compressed_serialization_file_handler(const compressed_serialization_file_handler&) = delete;
compressed_serialization_file_handler& operator=(const compressed_serialization_file_handler&) = delete;
// Handle file read and write requests
bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override;
// Get available memory or file size
// Preferably memory size if is already greater/equal to recommended to avoid additional file ops
usz get_size(const utils::serial& ar, usz recommended) const override;
void skip_until(utils::serial& ar) override;
bool is_valid() const override
{
return !m_errored;
}
void finalize(utils::serial& ar) override;
private:
const std::unique_ptr<fs::file> m_file_storage;
const std::add_pointer_t<const fs::file> m_file;
std::vector<u8> m_stream_data;
usz m_stream_data_index = 0;
usz m_file_read_index = 0;
atomic_t<usz> m_pending_bytes = 0;
atomic_t<bool> m_pending_signal = false;
bool m_write_inited = false;
bool m_read_inited = false;
bool m_errored = false;
std::shared_ptr<compressed_stream_data> m_stream;
std::unique_ptr<named_thread<std::function<void()>>> m_stream_data_prepare_thread;
std::unique_ptr<named_thread<std::function<void()>>> m_file_writer_thread;
usz read_at(utils::serial& ar, usz read_pos, void* data, usz size);
void initialize(utils::serial& ar);
void stream_data_prepare_thread_op();
void file_writer_thread_op();
void blocked_compressed_write(const std::vector<u8>& data);
};
template <typename File> requires (std::is_same_v<std::remove_cvref_t<File>, fs::file>)
inline std::unique_ptr<compressed_serialization_file_handler> make_compressed_serialization_file_handler(File&& file)
{
ensure(file);
return std::make_unique<compressed_serialization_file_handler>(std::forward<File>(file));
}
// Null file serialization handler
struct null_serialization_file_handler : utils::serialization_file_handler
{
explicit null_serialization_file_handler() noexcept
{
}
// Handle file read and write requests
bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override;
void finalize(utils::serial& ar) override;
bool is_null() const override
{
return true;
}
};
inline std::unique_ptr<null_serialization_file_handler> make_null_serialization_file_handler()
{
return std::make_unique<null_serialization_file_handler>();
}