/* * Copyright 2016 ScylaDB */ /* * SPDX-License-Identifier: AGPL-3.0-or-later */ #pragma once #include "bytes_ostream.hh" #include "serializer.hh" namespace ser { // frame represents a place holder for object size which will be known later template struct place_holder { }; template struct frame { }; template<> struct place_holder { bytes_ostream::place_holder ph; place_holder(bytes_ostream::place_holder ph) : ph(ph) { } void set(bytes_ostream& out, size_type v) { auto stream = ph.get_stream(); serialize(stream, v); } }; template<> struct frame : public place_holder { bytes_ostream::size_type offset; frame(bytes_ostream::place_holder ph, bytes_ostream::size_type offset) : place_holder(ph), offset(offset) { } void end(bytes_ostream& out) { set(out, out.size() - offset); } }; struct vector_position { bytes_ostream::position pos; size_type count; }; //empty frame, behave like a place holder, but is used when no place holder is needed template struct empty_frame { void end(Output&) {} empty_frame() = default; empty_frame(const frame&){} }; inline place_holder start_place_holder(bytes_ostream& out) { auto size_ph = out.write_place_holder(); return { size_ph}; } inline frame start_frame(bytes_ostream& out) { auto offset = out.size(); auto size_ph = out.write_place_holder(); { auto out = size_ph.get_stream(); serialize(out, (size_type)0); } return frame { size_ph, offset }; } template size_type read_frame_size(Input& in) { auto sz = deserialize(in, boost::type()); if (sz < sizeof(size_type)) { throw std::runtime_error(fmt::format("IDL frame truncated: expected to have at least {} bytes, got {}", sizeof(size_type), sz)); } return sz - sizeof(size_type); } template<> struct place_holder { void set(seastar::measuring_output_stream&, size_type) { } }; template<> struct frame : public place_holder { void end(seastar::measuring_output_stream& out) { } }; inline place_holder start_place_holder(seastar::measuring_output_stream& out) { serialize(out, size_type()); return { }; } inline frame start_frame(seastar::measuring_output_stream& out) { serialize(out, size_type()); return { }; } template<> class place_holder { seastar::simple_output_stream _substream; public: place_holder(seastar::simple_output_stream substream) : _substream(substream) { } void set(seastar::simple_output_stream& out, size_type v) { serialize(_substream, v); } }; template<> class frame : public place_holder { char* _start; public: frame(seastar::simple_output_stream ph, char* start) : place_holder(ph), _start(start) { } void end(seastar::simple_output_stream& out) { set(out, out.begin() - _start); } }; inline place_holder start_place_holder(seastar::simple_output_stream& out) { return { out.write_substream(sizeof(size_type)) }; } inline frame start_frame(seastar::simple_output_stream& out) { auto start = out.begin(); auto substream = out.write_substream(sizeof(size_type)); { auto sstr = substream; serialize(sstr, size_type(0)); } return frame(substream, start); } template class place_holder> { seastar::memory_output_stream _substream; public: place_holder(seastar::memory_output_stream substream) : _substream(substream) { } void set(seastar::memory_output_stream& out, size_type v) { serialize(_substream, v); } }; template class frame> : public place_holder> { size_t _start_left; public: frame(seastar::memory_output_stream ph, size_t start_left) : place_holder>(ph), _start_left(start_left) { } void end(seastar::memory_output_stream& out) { this->set(out, _start_left - out.size()); } }; template inline place_holder> start_place_holder(seastar::memory_output_stream& out) { return { out.write_substream(sizeof(size_type)) }; } template inline frame> start_frame(seastar::memory_output_stream& out) { auto start_left = out.size(); auto substream = out.write_substream(sizeof(size_type)); { auto sstr = substream; serialize(sstr, size_type(0)); } return frame>(substream, start_left); } }