aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/serialise.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/serialise.hh')
-rw-r--r--src/libutil/serialise.hh85
1 files changed, 67 insertions, 18 deletions
diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh
index 491b1987d..2651ec979 100644
--- a/src/libutil/serialise.hh
+++ b/src/libutil/serialise.hh
@@ -350,33 +350,82 @@ inline Sink & operator<<(Sink & sink, Generator<Bytes> && g)
return sink;
}
+struct SerializingTransform;
+using WireFormatGenerator = Generator<Bytes, SerializingTransform>;
+
+struct SerializingTransform
+{
+ std::array<unsigned char, 8> buf;
+
+ Bytes operator()(uint64_t n)
+ {
+ buf[0] = n & 0xff;
+ buf[1] = (n >> 8) & 0xff;
+ buf[2] = (n >> 16) & 0xff;
+ buf[3] = (n >> 24) & 0xff;
+ buf[4] = (n >> 32) & 0xff;
+ buf[5] = (n >> 40) & 0xff;
+ buf[6] = (n >> 48) & 0xff;
+ buf[7] = (unsigned char) (n >> 56) & 0xff;
+ return {reinterpret_cast<const char *>(buf.begin()), 8};
+ }
+
+ static Bytes padding(size_t unpadded)
+ {
+ return Bytes("\0\0\0\0\0\0\0", unpadded % 8 ? 8 - unpadded % 8 : 0);
+ }
+
+ // opt in to generator chaining. without this co_yielding
+ // another generator of any type will cause a type error.
+ auto operator()(Generator<Bytes> && g)
+ {
+ return std::move(g);
+ }
+
+ // only choose this for *exactly* char spans, do not allow implicit
+ // conversions. this would cause ambiguities with strings literals,
+ // and resolving those with more string-like overloads needs a lot.
+ template<typename Span>
+ requires std::same_as<Span, std::span<char>> || std::same_as<Span, std::span<const char>>
+ Bytes operator()(Span s)
+ {
+ return s;
+ }
+ WireFormatGenerator operator()(std::string_view s);
+ WireFormatGenerator operator()(const Strings & s);
+ WireFormatGenerator operator()(const StringSet & s);
+ WireFormatGenerator operator()(const Error & s);
+};
+
void writePadding(size_t len, Sink & sink);
-void writeString(std::string_view s, Sink & sink);
-inline Sink & operator << (Sink & sink, uint64_t n)
+inline Sink & operator<<(Sink & sink, uint64_t u)
{
- unsigned char buf[8];
- buf[0] = n & 0xff;
- buf[1] = (n >> 8) & 0xff;
- buf[2] = (n >> 16) & 0xff;
- buf[3] = (n >> 24) & 0xff;
- buf[4] = (n >> 32) & 0xff;
- buf[5] = (n >> 40) & 0xff;
- buf[6] = (n >> 48) & 0xff;
- buf[7] = (unsigned char) (n >> 56) & 0xff;
- sink({(char *) buf, sizeof(buf)});
- return sink;
+ return sink << [&]() -> WireFormatGenerator { co_yield u; }();
+}
+
+inline Sink & operator<<(Sink & sink, std::string_view s)
+{
+ return sink << [&]() -> WireFormatGenerator { co_yield s; }();
+}
+
+inline Sink & operator<<(Sink & sink, const Strings & s)
+{
+ return sink << [&]() -> WireFormatGenerator { co_yield s; }();
}
-Sink & operator << (Sink & in, const Error & ex);
-Sink & operator << (Sink & sink, std::string_view s);
-Sink & operator << (Sink & sink, const Strings & s);
-Sink & operator << (Sink & sink, const StringSet & s);
+inline Sink & operator<<(Sink & sink, const StringSet & s)
+{
+ return sink << [&]() -> WireFormatGenerator { co_yield s; }();
+}
+inline Sink & operator<<(Sink & sink, const Error & ex)
+{
+ return sink << [&]() -> WireFormatGenerator { co_yield ex; }();
+}
MakeError(SerialisationError, Error);
-
template<typename T>
T readNum(Source & source)
{