diff options
author | Robert Hensing <robert@roberthensing.nl> | 2020-09-17 17:36:16 +0200 |
---|---|---|
committer | Robert Hensing <robert@roberthensing.nl> | 2020-09-17 20:21:04 +0200 |
commit | 14b30b3f3d5af75c210a15cb128e67c0eff66149 (patch) | |
tree | 81db6f5789083371286a1efa1bd347066c058e43 /src/libutil/serialise.hh | |
parent | dfa547c6a81d6fb7ef3d3f69a98ebe969df42828 (diff) |
Move FramedSource and FramedSink, extract withFramedSink
Diffstat (limited to 'src/libutil/serialise.hh')
-rw-r--r-- | src/libutil/serialise.hh | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index 2fd06bb4d..6027d5961 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -406,4 +406,51 @@ struct StreamToSourceAdapter : Source }; +/* Like SizedSource, but guarantees that the whole frame is consumed after + destruction. This ensures that the original stream is in a known state. */ +struct FramedSource : Source +{ + Source & from; + bool eof = false; + std::vector<unsigned char> pending; + size_t pos = 0; + + FramedSource(Source & from) : from(from) + { } + + ~FramedSource() + { + if (!eof) { + while (true) { + auto n = readInt(from); + if (!n) break; + std::vector<unsigned char> data(n); + from(data.data(), n); + } + } + } + + size_t read(unsigned char * data, size_t len) override + { + if (eof) throw EndOfFile("reached end of FramedSource"); + + if (pos >= pending.size()) { + size_t len = readInt(from); + if (!len) { + eof = true; + return 0; + } + pending = std::vector<unsigned char>(len); + pos = 0; + from(pending.data(), len); + } + + auto n = std::min(len, pending.size() - pos); + memcpy(data, pending.data() + pos, n); + pos += n; + return n; + } +}; + + } |