@@ -144,11 +144,27 @@ concept supports_expandable_buffer =
144144 { ctr.data () } -> std::same_as<std::byte*>;
145145 }
146146
147+ template <typename Ctr>
148+ concept supports_endian_expandable_buffer =
149+ supports_expandable_buffer<Ctr> &&
150+ requires (Ctr ctr) {
151+ typename Ctr::endian_type;
152+ }
153+
147154template <supports_expandable_buffer Ctr = chops::mutable_shared_buffer,
148155 std::endian Endian = std::endian::little>
149- struct expandable_buffer : Ctr {
150- using Endian;
151- }
156+ class expandable_buffer {
157+ private:
158+ Ctr m_ctr;
159+ public:
160+ using endian_type = Endian;
161+ using value_type = std::byte;
162+ Ctr& get_buf () noexcept { return m_ctr; }
163+ std::size_t size () noexcept { return m_ctr.size (); }
164+ std::byte* data () noexcept { return m_ctr.data (); }
165+ void resize (std::size_t sz) noexcept m_ctr.resize(sz); }
166+ };
167+
152168/* *
153169
154170 * @brief Extract a sequence in network byte order from a @c std::byte buffer into the
@@ -286,29 +302,55 @@ class fixed_size_byte_array {
286302// similar can be used for the Buf template parameter
287303struct adl_tag { };
288304
289- // lower-level function template that performs the actual buffer manipulation and
290- // marshalling of a single value, with an ADL tag for full namespace inclusion in the
291- // overload set; this function template is not called directly by application code, and
292- // is only used with arithmetic values or a std::byte
293- template <typename CastValType, typename T, typename Buf = chops::mutable_shared_buffer>
294- Buf& marshall (Buf& buf, const T& val, adl_tag) {
295- auto old_sz = buf.size ();
296- buf.resize (old_sz + sizeof (CastValType));
297- append_val (buf.data ()+old_sz, static_cast <CastValType>(val));
298- return buf;
299- }
300305
301306namespace detail {
302307
303- template <typename CastValType, typename T, typename Buf = expandable_buffer>
308+ template <integral_or_byte CastTypeVal, integral_or_byte T,
309+ supports_endian_expandable_buf Buf = expandable_buffer>
304310constexpr Buf& serialize_val (Buf& buf, const T& val) {
305311 auto old_sz = buf.size ();
306- buf.resize (old_sz + sizeof (CastValType));
307- append_val (buf.data ()+old_sz, static_cast <CastValType>(val));
312+ buf.resize (old_sz + sizeof (CastTypeVal));
313+ append_val<Buf::endian_type>(buf.data ()+old_sz, static_cast <CastTypeVal>(val));
314+ return buf;
315+ }
316+
317+ template <integral_or_byte CastTypeVal, integral_or_byte T,
318+ supports_endian_expandable Buf = chops::mutable_shared_buffer>
319+ constexpr Buf& serialize (Buf& buf, const T& val) {
320+ return serialize_val<CastTypeVal> (buf, val);
321+ }
322+
323+ template <integral_or_byte CastTypeSz, integral_or_byte CastTypeVal,
324+ integral_or_byte T,
325+ supports_endian_expandable Buf = chops::mutable_shared_buffer>
326+ constexpr Buf& serialize (Buf& buf, const T* seq, std::size_t sz) {
327+ serialize_val<CastTypeSz> (buf, sz);
328+ for (int i {0 }; i < sz; ++i) {
329+ serialize_val<CastTypeVal>(buf, seq[i]);
330+ }
308331 return buf;
309332}
310333
334+ template <integral_or_byte CastTypeSz,
335+ supports_endian_expandable Buf = chops::mutable_shared_buffer>
336+ constexpr Buf& serialize (Buf& buf, const std::string& str) {
337+ return serialize<CastTypeSz, std::byte> (buf, str.data (), std.size ());
338+ }
339+
340+ template <integral_or_byte CastTypeBool, integral_or_byte CastTypeVal,
341+ integral_or_byte T,
342+ supports_endian_expandable Buf = chops::mutable_shared_buffer>
343+ constexpr Buf& serialize (Buf& buf, const std::optional<T>& val) {
344+ if (val)
345+ serialize_val<CastTypeBool> (buf, 1 );
346+ return serialize_val<CastTypeVal> (buf, *val);
347+ }
348+ serialize_val<CastTypeBool> (buf, 0 );
349+ }
350+
311351}
352+
353+
312354/* *
313355 * @brief Marshall a single arithmetic value or a @c std::byte into a buffer of bytes.
314356 *
0 commit comments