Added 'connection refused' stream error.
This commit is contained in:
parent
713d5ca02d
commit
41618310e4
160
source/mijin/io/archive.hpp
Normal file
160
source/mijin/io/archive.hpp
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(MIJIN_IO_ARCHIVE_HPP_INCLUDED)
|
||||||
|
#define MIJIN_IO_ARCHIVE_HPP_INCLUDED 1
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
#include "mijin/container/optional.hpp"
|
||||||
|
#include "mijin/io/stream.hpp"
|
||||||
|
|
||||||
|
namespace mijin
|
||||||
|
{
|
||||||
|
enum class ArchiveMode : std::uint8_t
|
||||||
|
{
|
||||||
|
READ,
|
||||||
|
WRITE
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TPointer>
|
||||||
|
class ArchiveBase
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ArchiveMode mode_ = ArchiveMode::READ;
|
||||||
|
StreamError error_ = StreamError::SUCCESS;
|
||||||
|
TPointer stream_ = nullptr;
|
||||||
|
public:
|
||||||
|
ArchiveBase() MIJIN_NOEXCEPT = default;
|
||||||
|
ArchiveBase(const ArchiveBase&) MIJIN_NOEXCEPT = default;
|
||||||
|
ArchiveBase(ArchiveBase&&) noexcept = default;
|
||||||
|
ArchiveBase(ArchiveMode mode, TPointer stream) MIJIN_NOEXCEPT : mode_(mode), stream_(std::move(stream)) {}
|
||||||
|
|
||||||
|
ArchiveBase& operator=(const ArchiveBase&) MIJIN_NOEXCEPT = default;
|
||||||
|
ArchiveBase& operator=(ArchiveBase&&) noexcept = default;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
ArchiveMode getMode() const MIJIN_NOEXCEPT { return mode_; }
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
StreamError getError() const MIJIN_NOEXCEPT { return error_; }
|
||||||
|
|
||||||
|
void setError(StreamError value) MIJIN_NOEXCEPT { error_ = value; }
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Stream& getStream() MIJIN_NOEXCEPT { return *stream_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
using Archive = ArchiveBase<Stream*>;
|
||||||
|
using OwningArchive = ArchiveBase<std::unique_ptr<Stream>>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename TPointer, typename TValue> requires (std::is_const_v<TValue>)
|
||||||
|
Task<> c_serialize(ArchiveBase<TPointer>& archive, TValue& value) noexcept
|
||||||
|
{
|
||||||
|
if (archive.getMode() != ArchiveMode::WRITE)
|
||||||
|
{
|
||||||
|
MIJIN_ERROR("Attempt to write to a const object.");
|
||||||
|
archive.setError(StreamError::IO_ERROR);
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
co_await c_serialize(archive, const_cast<std::remove_const_t<TValue>&>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TPointer>
|
||||||
|
Task<> c_serialize(ArchiveBase<TPointer>& archive, std::string& value) noexcept
|
||||||
|
{
|
||||||
|
if (archive.getError() != StreamError::SUCCESS)
|
||||||
|
{
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
if (archive.getMode() == ArchiveMode::READ)
|
||||||
|
{
|
||||||
|
archive.setError(co_await archive.getStream().c_readBinaryString(value));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
archive.setError(co_await archive.getStream().c_writeBinaryString(value));
|
||||||
|
}
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TPointer, typename TValue> requires (!std::is_const_v<TValue> && (std::is_arithmetic_v<TValue> || std::is_enum_v<TValue>))
|
||||||
|
Task<> c_serialize(ArchiveBase<TPointer>& archive, TValue& value) noexcept
|
||||||
|
{
|
||||||
|
if (archive.getError() != StreamError::SUCCESS)
|
||||||
|
{
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
if (archive.getMode() == ArchiveMode::READ)
|
||||||
|
{
|
||||||
|
archive.setError(co_await archive.getStream().c_read(value));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
archive.setError(co_await archive.getStream().c_write(value));
|
||||||
|
}
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TPointer, typename TElement, typename TAllocator>
|
||||||
|
Task<> c_serialize(ArchiveBase<TPointer>& archive, std::vector<TElement, TAllocator>& value) noexcept
|
||||||
|
{
|
||||||
|
if (archive.getError() != StreamError::SUCCESS)
|
||||||
|
{
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
std::uint64_t size = value.size();
|
||||||
|
co_await c_serialize(archive, size);
|
||||||
|
|
||||||
|
if (archive.getError() != StreamError::SUCCESS)
|
||||||
|
{
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archive.getMode() == ArchiveMode::READ)
|
||||||
|
{
|
||||||
|
value.resize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TElement& element : value)
|
||||||
|
{
|
||||||
|
co_await c_serialize(archive, element);
|
||||||
|
if (archive.getError() != StreamError::SUCCESS)
|
||||||
|
{
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TPointer, typename TContent>
|
||||||
|
Task<> c_serialize(ArchiveBase<TPointer> archive, Optional<TContent>& value) noexcept
|
||||||
|
{
|
||||||
|
if (archive.getError() != StreamError::SUCCESS)
|
||||||
|
{
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
std::uint8_t exists = !value.empty();
|
||||||
|
co_await c_serialize(archive, exists);
|
||||||
|
if (exists)
|
||||||
|
{
|
||||||
|
if (archive.getMode() == ArchiveMode::READ)
|
||||||
|
{
|
||||||
|
TContent content;
|
||||||
|
co_await c_serialize(archive, content);
|
||||||
|
if (archive.getError() != StreamError::SUCCESS)
|
||||||
|
{
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
value.emplace(std::move(content));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
co_await c_serialize(archive, *value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace mijin
|
||||||
|
|
||||||
|
#endif // !defined(MIJIN_IO_ARCHIVE_HPP_INCLUDED)
|
@ -72,6 +72,7 @@ enum class [[nodiscard]] StreamError
|
|||||||
CONNECTION_CLOSED = 3,
|
CONNECTION_CLOSED = 3,
|
||||||
PROTOCOL_ERROR = 4,
|
PROTOCOL_ERROR = 4,
|
||||||
WOULD_BLOCK = 5,
|
WOULD_BLOCK = 5,
|
||||||
|
CONNECTION_REFUSED = 6,
|
||||||
UNKNOWN_ERROR = -1
|
UNKNOWN_ERROR = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -450,6 +451,8 @@ inline const char* errorName(StreamError error) MIJIN_NOEXCEPT
|
|||||||
return "would block";
|
return "would block";
|
||||||
case StreamError::UNKNOWN_ERROR:
|
case StreamError::UNKNOWN_ERROR:
|
||||||
return "unknown error";
|
return "unknown error";
|
||||||
|
case StreamError::CONNECTION_REFUSED:
|
||||||
|
return "connection refused";
|
||||||
}
|
}
|
||||||
return "<invalid error>";
|
return "<invalid error>";
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user