22 { t.write(s, count) };
67 template <writable_stream TStream>
88 void write(std::span<const std::uint8_t> span);
97 void write(uint8_t value, std::
size_t count = 1);
116 void reserve(const std::function<std::
size_t()>& calculate_reserve_size);
123 [[nodiscard]]
size_t size() const;
132 template <typename TStream>
142 template <typename TStream>
143 const TStream&
get() const;
150 struct stream_concept
152 virtual ~stream_concept() =
default;
153 virtual void write(
const char* s, std::streamsize count) = 0;
154 virtual void write(std::span<const std::uint8_t> span) = 0;
155 virtual void write(uint8_t value, std::size_t count) = 0;
156 virtual void put(uint8_t value) = 0;
159 virtual void reserve(
const std::function<std::size_t()>& calculate_reserve_size) = 0;
160 [[nodiscard]]
virtual size_t size()
const = 0;
168 template <
typename TStream>
169 class stream_model :
public stream_concept
173 stream_model(TStream& stream);
175 void write(
const char* s, std::streamsize count)
final;
177 void write(std::span<const std::uint8_t> span)
final;
179 void write(uint8_t value, std::size_t count)
final;
181 void put(uint8_t value)
final;
183 void add_padding() final;
185 void reserve(std::
size_t size) final;
187 void reserve(const std::function<std::
size_t()>& calculate_reserve_size) final;
189 [[nodiscard]]
size_t size() const final;
191 TStream& get_stream();
193 const TStream& get_stream() const;
201 std::unique_ptr<stream_concept> m_impl;
208 : m_impl(std::make_unique<stream_model<TStream>>(stream))
212 template <
typename TStream>
215 auto* model =
dynamic_cast<stream_model<TStream>*
>(m_impl.get());
218 throw std::bad_cast();
220 return model->get_stream();
223 template <
typename TStream>
226 const auto* model =
dynamic_cast<const stream_model<TStream>*
>(m_impl.get());
229 throw std::bad_cast();
231 return model->get_stream();
236 template <
typename TStream>
237 any_output_stream::stream_model<TStream>::stream_model(TStream& stream)
242 template <
typename TStream>
243 void any_output_stream::stream_model<TStream>::write(
const char* s, std::streamsize count)
245 m_stream->write(s, count);
246 m_size +=
static_cast<size_t>(count);
249 template <
typename TStream>
250 void any_output_stream::stream_model<TStream>::write(std::span<const std::uint8_t> span)
252 m_stream->write(
reinterpret_cast<const char*
>(span.data()),
static_cast<std::streamsize
>(span.size()));
253 m_size += span.size();
256 template <
typename TStream>
257 void any_output_stream::stream_model<TStream>::write(uint8_t value, std::size_t count)
259 if constexpr (
requires(TStream& t, uint8_t v, std::size_t c) { t.write(v, c); })
261 m_stream->write(value, count);
266 for (std::size_t i = 0; i < count; ++i)
268 m_stream->put(value);
274 template <
typename TStream>
275 void any_output_stream::stream_model<TStream>::put(uint8_t value)
277 m_stream->put(value);
281 template <
typename TStream>
282 void any_output_stream::stream_model<TStream>::add_padding()
284 const size_t current_size = size();
285 const size_t padding_needed = (8 - (current_size % 8)) % 8;
286 if (padding_needed > 0)
288 static constexpr char padding_value = 0;
289 for (
size_t i = 0; i < padding_needed; ++i)
291 m_stream->write(&padding_value, 1);
293 m_size += padding_needed;
297 template <
typename TStream>
298 void any_output_stream::stream_model<TStream>::reserve(std::size_t size)
300 if constexpr (
requires(TStream& t, std::size_t s) { t.reserve(s); })
302 m_stream->reserve(size);
307 template <
typename TStream>
308 void any_output_stream::stream_model<TStream>::reserve(
const std::function<std::size_t()>& calculate_reserve_size)
310 if constexpr (
requires(TStream& t,
const std::function<std::size_t()>& func) {
314 m_stream->reserve(calculate_reserve_size);
316 else if constexpr (
requires(TStream& t, std::size_t s) { t.reserve(s); })
318 m_stream->reserve(calculate_reserve_size());
323 template <
typename TStream>
324 size_t any_output_stream::stream_model<TStream>::size()
const
326 if constexpr (
requires(
const TStream& t) {
327 { t.size() } -> std::convertible_to<size_t>;
330 return m_stream->size();
338 template <
typename TStream>
339 TStream& any_output_stream::stream_model<TStream>::get_stream()
344 template <
typename TStream>
345 const TStream& any_output_stream::stream_model<TStream>::get_stream()
const