/**
 * @file IOStream.h
 * @brief 面向内存缓冲区的二进制流读写工具。
 * @details
 * 定义 reader/writer 两个轻量类，用于在连续内存上顺序序列化：
 * - 支持算术类型按字节写入与读取；
 * - 支持原始块拷贝与位置跳过；
 * - 通过边界断言降低越界读写风险。
 */
#pragma once
#include "CommonHeader.h"

namespace XEngine::utl {

/**
 * @brief 只读内存二进制流。
 */
class blob_stream_reader
{
public:
	DISABLE_COPY_AND_MOVE(blob_stream_reader);
	/**
	 * @brief 绑定外部只读缓冲区。
	 * @param buffer 缓冲区首地址。
	 */
	explicit blob_stream_reader(const u8* buffer)
		:_buffer{buffer}, _position{buffer}
	{
		assert(buffer);
	}


	/**
	 * @brief 按类型读取一个值并推进游标。
	 * @tparam T 算术类型。
	 * @return 读取到的值。
	 */
	template<typename T>
	[[nodiscard]] T reader()
	{
		static_assert(std::is_arithmetic_v<T>, "Template argument should be a primitive type.");
		T value{ *((T*)_position) };
		_position += sizeof(T);
		return value;
	}

	/**
	 * @brief 读取原始字节块并推进游标。
	 * @param buffer 输出缓冲区。
	 * @param length 读取字节数。
	 */
	void read(u8* buffer, size_t length)
	{
		memcpy(buffer, _position, length);
		_position += length;
	}

	/**
	 * @brief 跳过指定字节数。
	 * @param offset 偏移字节数。
	 */
	void skip(size_t offset)
	{
		_position += offset;
	}

	[[nodiscard]] constexpr const u8 *const buffer_start() const { return _buffer; }
	[[nodiscard]] constexpr const u8 *const position() const { return _position; }
	[[nodiscard]] constexpr size_t offset() const { return _position - _buffer; }

private:
	const u8 *const  _buffer;
	const u8*		 _position;
};


/**
 * @brief 可写内存二进制流。
 */
class blob_stream_writer
{
public:
	DISABLE_COPY_AND_MOVE(blob_stream_writer);
	/**
	 * @brief 绑定外部可写缓冲区。
	 * @param buffer 缓冲区首地址。
	 * @param buffer_size 缓冲区大小。
	 */
	explicit blob_stream_writer(u8* buffer, size_t buffer_size)
		:_buffer{ buffer }, _position{ buffer }, _buffer_size(buffer_size)
	{
		assert(buffer && buffer_size);
	}


	/**
	 * @brief 写入一个算术类型值并推进游标。
	 * @tparam T 算术类型。
	 * @param value 待写入值。
	 */
	template<typename T>
	void write(T value)
	{
		static_assert(std::is_arithmetic_v<T>, "Template argument should be a primitive type.");
		assert(&_position[sizeof(T)] <= &_buffer[_buffer_size]);
		*((T*)_position) = value;
		_position += sizeof(T);
	}

	/**
	 * @brief 写入字符缓冲区。
	 * @param buffer 输入缓冲区。
	 * @param length 写入字节数。
	 */
	void write(const char* buffer, size_t length)
	{
		assert(&_position[length] <= &_buffer[_buffer_size]);
		memcpy(_position, buffer, length);
		_position += length;
	}

	/**
	 * @brief 写入字节缓冲区。
	 * @param buffer 输入缓冲区。
	 * @param length 写入字节数。
	 */
	void write(const u8* buffer, size_t length)
	{
		assert(&_position[length] <= &_buffer[_buffer_size]);
		memcpy(_position, buffer, length);
		_position += length;
	}

	/**
	 * @brief 跳过指定字节数。
	 * @param offset 偏移字节数。
	 */
	void skip(size_t offset)
	{
		assert(&_position[offset] <= &_buffer[_buffer_size]);
		_position += offset;
	}

	[[nodiscard]] constexpr const u8 *const buffer_start() const { return _buffer; }
	[[nodiscard]] constexpr const u8 *const buffer_end() const { return &_buffer[_buffer_size]; }
	[[nodiscard]] constexpr const u8 *const position() const { return _position; }
	[[nodiscard]] constexpr size_t offset() const { return _position - _buffer; }

private:
	u8 *const		_buffer;
	u8*				_position;
	size_t			_buffer_size;
};
}
