serialize-packed.h (5347B)
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors 2 // Licensed under the MIT License: 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 22 #pragma once 23 24 #include "serialize.h" 25 26 CAPNP_BEGIN_HEADER 27 28 namespace capnp { 29 30 namespace _ { // private 31 32 class PackedInputStream: public kj::InputStream { 33 // An input stream that unpacks packed data with a picky constraint: The caller must read data 34 // in the exact same size and sequence as the data was written to PackedOutputStream. 35 36 public: 37 explicit PackedInputStream(kj::BufferedInputStream& inner); 38 KJ_DISALLOW_COPY(PackedInputStream); 39 ~PackedInputStream() noexcept(false); 40 41 // implements InputStream ------------------------------------------ 42 size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override; 43 void skip(size_t bytes) override; 44 45 private: 46 kj::BufferedInputStream& inner; 47 }; 48 49 class PackedOutputStream: public kj::OutputStream { 50 // An output stream that packs data. Buffers passed to `write()` must be word-aligned. 51 public: 52 explicit PackedOutputStream(kj::BufferedOutputStream& inner); 53 KJ_DISALLOW_COPY(PackedOutputStream); 54 ~PackedOutputStream() noexcept(false); 55 56 // implements OutputStream ----------------------------------------- 57 void write(const void* buffer, size_t bytes) override; 58 59 private: 60 kj::BufferedOutputStream& inner; 61 }; 62 63 } // namespace _ (private) 64 65 class PackedMessageReader: private _::PackedInputStream, public InputStreamMessageReader { 66 public: 67 PackedMessageReader(kj::BufferedInputStream& inputStream, ReaderOptions options = ReaderOptions(), 68 kj::ArrayPtr<word> scratchSpace = nullptr); 69 KJ_DISALLOW_COPY(PackedMessageReader); 70 ~PackedMessageReader() noexcept(false); 71 }; 72 73 class PackedFdMessageReader: private kj::FdInputStream, private kj::BufferedInputStreamWrapper, 74 public PackedMessageReader { 75 public: 76 PackedFdMessageReader(int fd, ReaderOptions options = ReaderOptions(), 77 kj::ArrayPtr<word> scratchSpace = nullptr); 78 // Read message from a file descriptor, without taking ownership of the descriptor. 79 // Note that if you want to reuse the descriptor after the reader is destroyed, you'll need to 80 // seek it, since otherwise the position is unspecified. 81 82 PackedFdMessageReader(kj::AutoCloseFd fd, ReaderOptions options = ReaderOptions(), 83 kj::ArrayPtr<word> scratchSpace = nullptr); 84 // Read a message from a file descriptor, taking ownership of the descriptor. 85 86 KJ_DISALLOW_COPY(PackedFdMessageReader); 87 88 ~PackedFdMessageReader() noexcept(false); 89 }; 90 91 void writePackedMessage(kj::BufferedOutputStream& output, MessageBuilder& builder); 92 void writePackedMessage(kj::BufferedOutputStream& output, 93 kj::ArrayPtr<const kj::ArrayPtr<const word>> segments); 94 // Write a packed message to a buffered output stream. 95 96 void writePackedMessage(kj::OutputStream& output, MessageBuilder& builder); 97 void writePackedMessage(kj::OutputStream& output, 98 kj::ArrayPtr<const kj::ArrayPtr<const word>> segments); 99 // Write a packed message to an unbuffered output stream. If you intend to write multiple messages 100 // in succession, consider wrapping your output in a buffered stream in order to reduce system 101 // call overhead. 102 103 void writePackedMessageToFd(int fd, MessageBuilder& builder); 104 void writePackedMessageToFd(int fd, kj::ArrayPtr<const kj::ArrayPtr<const word>> segments); 105 // Write a single packed message to the file descriptor. 106 107 size_t computeUnpackedSizeInWords(kj::ArrayPtr<const byte> packedBytes); 108 // Computes the number of words to which the given packed bytes will unpack. Not intended for use 109 // in performance-sensitive situations. 110 111 // ======================================================================================= 112 // inline stuff 113 114 inline void writePackedMessage(kj::BufferedOutputStream& output, MessageBuilder& builder) { 115 writePackedMessage(output, builder.getSegmentsForOutput()); 116 } 117 118 inline void writePackedMessage(kj::OutputStream& output, MessageBuilder& builder) { 119 writePackedMessage(output, builder.getSegmentsForOutput()); 120 } 121 122 inline void writePackedMessageToFd(int fd, MessageBuilder& builder) { 123 writePackedMessageToFd(fd, builder.getSegmentsForOutput()); 124 } 125 126 } // namespace capnp 127 128 CAPNP_END_HEADER