6#include <steamclient/utilities/err.h>
14using byte =
unsigned char;
16namespace Steam::Utils {
20 explicit Stream() : readBuffer(nullptr), position(0) {}
23 explicit Stream(
const std::vector<byte>& input)
24 : readBuffer(&input), buffer(), position(0) {}
27 explicit Stream(
const std::vector<byte>& input,
size_t offset)
28 : readBuffer(&input), buffer(), position(offset) {}
30 size_t Position()
const {
return position; }
32 size_t Length()
const {
33 return readBuffer ? readBuffer->size() : buffer.size();
36 const std::vector<byte>& GetBuffer()
const {
return buffer; }
38 std::vector<byte> MoveBuffer() {
return std::move(buffer); }
42 static_assert(std::is_integral_v<T>,
"Integral required");
44 if (readBuffer)
throw std::runtime_error(
"Stream is in read mode");
46 for (
size_t i = 0; i <
sizeof(T); ++i)
47 buffer.push_back(
static_cast<byte>((value >> (8 * i)) & 0xFF));
50 void Write(
const std::vector<byte>& data) {
51 if (readBuffer)
throw std::runtime_error(
"Stream is in read mode");
53 buffer.insert(buffer.end(), data.begin(), data.end());
56 void Write(
const byte* data,
size_t size) {
57 if (readBuffer)
throw std::runtime_error(
"Stream is in read mode");
59 buffer.insert(buffer.end(), data, data + size);
62 void Write(
const void* data,
size_t size) {
63 const uint8_t* ptr =
static_cast<const uint8_t*
>(data);
64 buffer.insert(buffer.end(), ptr, ptr + size);
69 static_assert(std::is_integral_v<T>,
"Integral required");
71 if (!readBuffer)
throw std::runtime_error(
"Stream is in write mode");
73 if (position +
sizeof(T) > readBuffer->size())
74 throw std::runtime_error(
"Stream underflow");
77 for (
size_t i = 0; i <
sizeof(T); ++i)
78 value |=
static_cast<T
>((*readBuffer)[position + i]) << (8 * i);
80 position +=
sizeof(T);
84 void Read(
byte* out,
size_t size) {
85 if (!readBuffer)
throw std::runtime_error(
"Stream is in write mode");
87 if (position + size > readBuffer->size())
88 throw std::runtime_error(
"Stream underflow");
90 std::memcpy(out, readBuffer->data() + position, size);
94 std::vector<byte> ReadBytes(
size_t size) {
95 if (!readBuffer)
throw std::runtime_error(
"Stream is in write mode");
97 if (position + size > readBuffer->size())
98 throw std::runtime_error(
"Stream underflow");
100 std::vector<byte> out(readBuffer->begin() + position,
101 readBuffer->begin() + position + size);
107 template <
typename T>
108 std::vector<T> ReadArray(
size_t count) {
109 static_assert(std::is_integral_v<T>,
"Integral required");
111 if (!readBuffer)
throw std::runtime_error(
"Stream is in write mode");
113 if (position +
sizeof(T) * count > readBuffer->size())
114 throw std::runtime_error(
"Stream underflow");
116 std::vector<T> result;
117 result.reserve(count);
119 for (
size_t i = 0; i < count; ++i) result.push_back(Read<T>());
125 const std::vector<byte>* readBuffer;
126 std::vector<byte> buffer;