annotate osx/include/capnp/message.h @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 0994c39f1e94
children
rev   line source
cannam@62 1 // Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
cannam@62 2 // Licensed under the MIT License:
cannam@62 3 //
cannam@62 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@62 5 // of this software and associated documentation files (the "Software"), to deal
cannam@62 6 // in the Software without restriction, including without limitation the rights
cannam@62 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@62 8 // copies of the Software, and to permit persons to whom the Software is
cannam@62 9 // furnished to do so, subject to the following conditions:
cannam@62 10 //
cannam@62 11 // The above copyright notice and this permission notice shall be included in
cannam@62 12 // all copies or substantial portions of the Software.
cannam@62 13 //
cannam@62 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@62 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@62 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@62 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@62 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@62 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@62 20 // THE SOFTWARE.
cannam@62 21
cannam@62 22 #include <kj/common.h>
cannam@62 23 #include <kj/memory.h>
cannam@62 24 #include <kj/mutex.h>
cannam@62 25 #include <kj/debug.h>
cannam@62 26 #include "common.h"
cannam@62 27 #include "layout.h"
cannam@62 28 #include "any.h"
cannam@62 29
cannam@62 30 #ifndef CAPNP_MESSAGE_H_
cannam@62 31 #define CAPNP_MESSAGE_H_
cannam@62 32
cannam@62 33 #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
cannam@62 34 #pragma GCC system_header
cannam@62 35 #endif
cannam@62 36
cannam@62 37 namespace capnp {
cannam@62 38
cannam@62 39 namespace _ { // private
cannam@62 40 class ReaderArena;
cannam@62 41 class BuilderArena;
cannam@62 42 }
cannam@62 43
cannam@62 44 class StructSchema;
cannam@62 45 class Orphanage;
cannam@62 46 template <typename T>
cannam@62 47 class Orphan;
cannam@62 48
cannam@62 49 // =======================================================================================
cannam@62 50
cannam@62 51 struct ReaderOptions {
cannam@62 52 // Options controlling how data is read.
cannam@62 53
cannam@62 54 uint64_t traversalLimitInWords = 8 * 1024 * 1024;
cannam@62 55 // Limits how many total words of data are allowed to be traversed. Traversal is counted when
cannam@62 56 // a new struct or list builder is obtained, e.g. from a get() accessor. This means that calling
cannam@62 57 // the getter for the same sub-struct multiple times will cause it to be double-counted. Once
cannam@62 58 // the traversal limit is reached, an error will be reported.
cannam@62 59 //
cannam@62 60 // This limit exists for security reasons. It is possible for an attacker to construct a message
cannam@62 61 // in which multiple pointers point at the same location. This is technically invalid, but hard
cannam@62 62 // to detect. Using such a message, an attacker could cause a message which is small on the wire
cannam@62 63 // to appear much larger when actually traversed, possibly exhausting server resources leading to
cannam@62 64 // denial-of-service.
cannam@62 65 //
cannam@62 66 // It makes sense to set a traversal limit that is much larger than the underlying message.
cannam@62 67 // Together with sensible coding practices (e.g. trying to avoid calling sub-object getters
cannam@62 68 // multiple times, which is expensive anyway), this should provide adequate protection without
cannam@62 69 // inconvenience.
cannam@62 70 //
cannam@62 71 // The default limit is 64 MiB. This may or may not be a sensible number for any given use case,
cannam@62 72 // but probably at least prevents easy exploitation while also avoiding causing problems in most
cannam@62 73 // typical cases.
cannam@62 74
cannam@62 75 int nestingLimit = 64;
cannam@62 76 // Limits how deeply-nested a message structure can be, e.g. structs containing other structs or
cannam@62 77 // lists of structs.
cannam@62 78 //
cannam@62 79 // Like the traversal limit, this limit exists for security reasons. Since it is common to use
cannam@62 80 // recursive code to traverse recursive data structures, an attacker could easily cause a stack
cannam@62 81 // overflow by sending a very-deeply-nested (or even cyclic) message, without the message even
cannam@62 82 // being very large. The default limit of 64 is probably low enough to prevent any chance of
cannam@62 83 // stack overflow, yet high enough that it is never a problem in practice.
cannam@62 84 };
cannam@62 85
cannam@62 86 class MessageReader {
cannam@62 87 // Abstract interface for an object used to read a Cap'n Proto message. Subclasses of
cannam@62 88 // MessageReader are responsible for reading the raw, flat message content. Callers should
cannam@62 89 // usually call `messageReader.getRoot<MyStructType>()` to get a `MyStructType::Reader`
cannam@62 90 // representing the root of the message, then use that to traverse the message content.
cannam@62 91 //
cannam@62 92 // Some common subclasses of `MessageReader` include `SegmentArrayMessageReader`, whose
cannam@62 93 // constructor accepts pointers to the raw data, and `StreamFdMessageReader` (from
cannam@62 94 // `serialize.h`), which reads the message from a file descriptor. One might implement other
cannam@62 95 // subclasses to handle things like reading from shared memory segments, mmap()ed files, etc.
cannam@62 96
cannam@62 97 public:
cannam@62 98 MessageReader(ReaderOptions options);
cannam@62 99 // It is suggested that subclasses take ReaderOptions as a constructor parameter, but give it a
cannam@62 100 // default value of "ReaderOptions()". The base class constructor doesn't have a default value
cannam@62 101 // in order to remind subclasses that they really need to give the user a way to provide this.
cannam@62 102
cannam@62 103 virtual ~MessageReader() noexcept(false);
cannam@62 104
cannam@62 105 virtual kj::ArrayPtr<const word> getSegment(uint id) = 0;
cannam@62 106 // Gets the segment with the given ID, or returns null if no such segment exists. This method
cannam@62 107 // will be called at most once for each segment ID.
cannam@62 108
cannam@62 109 inline const ReaderOptions& getOptions();
cannam@62 110 // Get the options passed to the constructor.
cannam@62 111
cannam@62 112 template <typename RootType>
cannam@62 113 typename RootType::Reader getRoot();
cannam@62 114 // Get the root struct of the message, interpreting it as the given struct type.
cannam@62 115
cannam@62 116 template <typename RootType, typename SchemaType>
cannam@62 117 typename RootType::Reader getRoot(SchemaType schema);
cannam@62 118 // Dynamically interpret the root struct of the message using the given schema (a StructSchema).
cannam@62 119 // RootType in this case must be DynamicStruct, and you must #include <capnp/dynamic.h> to
cannam@62 120 // use this.
cannam@62 121
cannam@62 122 bool isCanonical();
cannam@62 123 // Returns whether the message encoded in the reader is in canonical form.
cannam@62 124
cannam@62 125 private:
cannam@62 126 ReaderOptions options;
cannam@62 127
cannam@62 128 // Space in which we can construct a ReaderArena. We don't use ReaderArena directly here
cannam@62 129 // because we don't want clients to have to #include arena.h, which itself includes a bunch of
cannam@62 130 // big STL headers. We don't use a pointer to a ReaderArena because that would require an
cannam@62 131 // extra malloc on every message which could be expensive when processing small messages.
cannam@62 132 void* arenaSpace[15 + sizeof(kj::MutexGuarded<void*>) / sizeof(void*)];
cannam@62 133 bool allocatedArena;
cannam@62 134
cannam@62 135 _::ReaderArena* arena() { return reinterpret_cast<_::ReaderArena*>(arenaSpace); }
cannam@62 136 AnyPointer::Reader getRootInternal();
cannam@62 137 };
cannam@62 138
cannam@62 139 class MessageBuilder {
cannam@62 140 // Abstract interface for an object used to allocate and build a message. Subclasses of
cannam@62 141 // MessageBuilder are responsible for allocating the space in which the message will be written.
cannam@62 142 // The most common subclass is `MallocMessageBuilder`, but other subclasses may be used to do
cannam@62 143 // tricky things like allocate messages in shared memory or mmap()ed files.
cannam@62 144 //
cannam@62 145 // Creating a new message ususually means allocating a new MessageBuilder (ideally on the stack)
cannam@62 146 // and then calling `messageBuilder.initRoot<MyStructType>()` to get a `MyStructType::Builder`.
cannam@62 147 // That, in turn, can be used to fill in the message content. When done, you can call
cannam@62 148 // `messageBuilder.getSegmentsForOutput()` to get a list of flat data arrays containing the
cannam@62 149 // message.
cannam@62 150
cannam@62 151 public:
cannam@62 152 MessageBuilder();
cannam@62 153 virtual ~MessageBuilder() noexcept(false);
cannam@62 154 KJ_DISALLOW_COPY(MessageBuilder);
cannam@62 155
cannam@62 156 struct SegmentInit {
cannam@62 157 kj::ArrayPtr<word> space;
cannam@62 158
cannam@62 159 size_t wordsUsed;
cannam@62 160 // Number of words in `space` which are used; the rest are free space in which additional
cannam@62 161 // objects may be allocated.
cannam@62 162 };
cannam@62 163
cannam@62 164 explicit MessageBuilder(kj::ArrayPtr<SegmentInit> segments);
cannam@62 165 // Create a MessageBuilder backed by existing memory. This is an advanced interface that most
cannam@62 166 // people should not use. THIS METHOD IS INSECURE; see below.
cannam@62 167 //
cannam@62 168 // This allows a MessageBuilder to be constructed to modify an in-memory message without first
cannam@62 169 // making a copy of the content. This is especially useful in conjunction with mmap().
cannam@62 170 //
cannam@62 171 // The contents of each segment must outlive the MessageBuilder, but the SegmentInit array itself
cannam@62 172 // only need outlive the constructor.
cannam@62 173 //
cannam@62 174 // SECURITY: Do not use this in conjunction with untrusted data. This constructor assumes that
cannam@62 175 // the input message is valid. This constructor is designed to be used with data you control,
cannam@62 176 // e.g. an mmap'd file which is owned and accessed by only one program. When reading data you
cannam@62 177 // do not trust, you *must* load it into a Reader and then copy into a Builder as a means of
cannam@62 178 // validating the content.
cannam@62 179 //
cannam@62 180 // WARNING: It is NOT safe to initialize a MessageBuilder in this way from memory that is
cannam@62 181 // currently in use by another MessageBuilder or MessageReader. Other readers/builders will
cannam@62 182 // not observe changes to the segment sizes nor newly-allocated segments caused by allocating
cannam@62 183 // new objects in this message.
cannam@62 184
cannam@62 185 virtual kj::ArrayPtr<word> allocateSegment(uint minimumSize) = 0;
cannam@62 186 // Allocates an array of at least the given number of words, throwing an exception or crashing if
cannam@62 187 // this is not possible. It is expected that this method will usually return more space than
cannam@62 188 // requested, and the caller should use that extra space as much as possible before allocating
cannam@62 189 // more. The returned space remains valid at least until the MessageBuilder is destroyed.
cannam@62 190 //
cannam@62 191 // Cap'n Proto will only call this once at a time, so the subclass need not worry about
cannam@62 192 // thread-safety.
cannam@62 193
cannam@62 194 template <typename RootType>
cannam@62 195 typename RootType::Builder initRoot();
cannam@62 196 // Initialize the root struct of the message as the given struct type.
cannam@62 197
cannam@62 198 template <typename Reader>
cannam@62 199 void setRoot(Reader&& value);
cannam@62 200 // Set the root struct to a deep copy of the given struct.
cannam@62 201
cannam@62 202 template <typename RootType>
cannam@62 203 typename RootType::Builder getRoot();
cannam@62 204 // Get the root struct of the message, interpreting it as the given struct type.
cannam@62 205
cannam@62 206 template <typename RootType, typename SchemaType>
cannam@62 207 typename RootType::Builder getRoot(SchemaType schema);
cannam@62 208 // Dynamically interpret the root struct of the message using the given schema (a StructSchema).
cannam@62 209 // RootType in this case must be DynamicStruct, and you must #include <capnp/dynamic.h> to
cannam@62 210 // use this.
cannam@62 211
cannam@62 212 template <typename RootType, typename SchemaType>
cannam@62 213 typename RootType::Builder initRoot(SchemaType schema);
cannam@62 214 // Dynamically init the root struct of the message using the given schema (a StructSchema).
cannam@62 215 // RootType in this case must be DynamicStruct, and you must #include <capnp/dynamic.h> to
cannam@62 216 // use this.
cannam@62 217
cannam@62 218 template <typename T>
cannam@62 219 void adoptRoot(Orphan<T>&& orphan);
cannam@62 220 // Like setRoot() but adopts the orphan without copying.
cannam@62 221
cannam@62 222 kj::ArrayPtr<const kj::ArrayPtr<const word>> getSegmentsForOutput();
cannam@62 223 // Get the raw data that makes up the message.
cannam@62 224
cannam@62 225 Orphanage getOrphanage();
cannam@62 226
cannam@62 227 bool isCanonical();
cannam@62 228 // Check whether the message builder is in canonical form
cannam@62 229
cannam@62 230 private:
cannam@62 231 void* arenaSpace[22];
cannam@62 232 // Space in which we can construct a BuilderArena. We don't use BuilderArena directly here
cannam@62 233 // because we don't want clients to have to #include arena.h, which itself includes a bunch of
cannam@62 234 // big STL headers. We don't use a pointer to a BuilderArena because that would require an
cannam@62 235 // extra malloc on every message which could be expensive when processing small messages.
cannam@62 236
cannam@62 237 bool allocatedArena = false;
cannam@62 238 // We have to initialize the arena lazily because when we do so we want to allocate the root
cannam@62 239 // pointer immediately, and this will allocate a segment, which requires a virtual function
cannam@62 240 // call on the MessageBuilder. We can't do such a call in the constructor since the subclass
cannam@62 241 // isn't constructed yet. This is kind of annoying because it means that getOrphanage() is
cannam@62 242 // not thread-safe, but that shouldn't be a huge deal...
cannam@62 243
cannam@62 244 _::BuilderArena* arena() { return reinterpret_cast<_::BuilderArena*>(arenaSpace); }
cannam@62 245 _::SegmentBuilder* getRootSegment();
cannam@62 246 AnyPointer::Builder getRootInternal();
cannam@62 247 };
cannam@62 248
cannam@62 249 template <typename RootType>
cannam@62 250 typename RootType::Reader readMessageUnchecked(const word* data);
cannam@62 251 // IF THE INPUT IS INVALID, THIS MAY CRASH, CORRUPT MEMORY, CREATE A SECURITY HOLE IN YOUR APP,
cannam@62 252 // MURDER YOUR FIRST-BORN CHILD, AND/OR BRING ABOUT ETERNAL DAMNATION ON ALL OF HUMANITY. DO NOT
cannam@62 253 // USE UNLESS YOU UNDERSTAND THE CONSEQUENCES.
cannam@62 254 //
cannam@62 255 // Given a pointer to a known-valid message located in a single contiguous memory segment,
cannam@62 256 // returns a reader for that message. No bounds-checking will be done while traversing this
cannam@62 257 // message. Use this only if you have already verified that all pointers are valid and in-bounds,
cannam@62 258 // and there are no far pointers in the message.
cannam@62 259 //
cannam@62 260 // To create a message that can be passed to this function, build a message using a MallocAllocator
cannam@62 261 // whose preferred segment size is larger than the message size. This guarantees that the message
cannam@62 262 // will be allocated as a single segment, meaning getSegmentsForOutput() returns a single word
cannam@62 263 // array. That word array is your message; you may pass a pointer to its first word into
cannam@62 264 // readMessageUnchecked() to read the message.
cannam@62 265 //
cannam@62 266 // This can be particularly handy for embedding messages in generated code: you can
cannam@62 267 // embed the raw bytes (using AlignedData) then make a Reader for it using this. This is the way
cannam@62 268 // default values are embedded in code generated by the Cap'n Proto compiler. E.g., if you have
cannam@62 269 // a message MyMessage, you can read its default value like so:
cannam@62 270 // MyMessage::Reader reader = Message<MyMessage>::readMessageUnchecked(MyMessage::DEFAULT.words);
cannam@62 271 //
cannam@62 272 // To sanitize a message from an untrusted source such that it can be safely passed to
cannam@62 273 // readMessageUnchecked(), use copyToUnchecked().
cannam@62 274
cannam@62 275 template <typename Reader>
cannam@62 276 void copyToUnchecked(Reader&& reader, kj::ArrayPtr<word> uncheckedBuffer);
cannam@62 277 // Copy the content of the given reader into the given buffer, such that it can safely be passed to
cannam@62 278 // readMessageUnchecked(). The buffer's size must be exactly reader.totalSizeInWords() + 1,
cannam@62 279 // otherwise an exception will be thrown. The buffer must be zero'd before calling.
cannam@62 280
cannam@62 281 template <typename RootType>
cannam@62 282 typename RootType::Reader readDataStruct(kj::ArrayPtr<const word> data);
cannam@62 283 // Interprets the given data as a single, data-only struct. Only primitive fields (booleans,
cannam@62 284 // numbers, and enums) will be readable; all pointers will be null. This is useful if you want
cannam@62 285 // to use Cap'n Proto as a language/platform-neutral way to pack some bits.
cannam@62 286 //
cannam@62 287 // The input is a word array rather than a byte array to enforce alignment. If you have a byte
cannam@62 288 // array which you know is word-aligned (or if your platform supports unaligned reads and you don't
cannam@62 289 // mind the performance penalty), then you can use `reinterpret_cast` to convert a byte array into
cannam@62 290 // a word array:
cannam@62 291 //
cannam@62 292 // kj::arrayPtr(reinterpret_cast<const word*>(bytes.begin()),
cannam@62 293 // reinterpret_cast<const word*>(bytes.end()))
cannam@62 294
cannam@62 295 template <typename BuilderType>
cannam@62 296 typename kj::ArrayPtr<const word> writeDataStruct(BuilderType builder);
cannam@62 297 // Given a struct builder, get the underlying data section as a word array, suitable for passing
cannam@62 298 // to `readDataStruct()`.
cannam@62 299 //
cannam@62 300 // Note that you may call `.toBytes()` on the returned value to convert to `ArrayPtr<const byte>`.
cannam@62 301
cannam@62 302 template <typename Type>
cannam@62 303 static typename Type::Reader defaultValue();
cannam@62 304 // Get a default instance of the given struct or list type.
cannam@62 305 //
cannam@62 306 // TODO(cleanup): Find a better home for this function?
cannam@62 307
cannam@62 308 // =======================================================================================
cannam@62 309
cannam@62 310 class SegmentArrayMessageReader: public MessageReader {
cannam@62 311 // A simple MessageReader that reads from an array of word arrays representing all segments.
cannam@62 312 // In particular you can read directly from the output of MessageBuilder::getSegmentsForOutput()
cannam@62 313 // (although it would probably make more sense to call builder.getRoot().asReader() in that case).
cannam@62 314
cannam@62 315 public:
cannam@62 316 SegmentArrayMessageReader(kj::ArrayPtr<const kj::ArrayPtr<const word>> segments,
cannam@62 317 ReaderOptions options = ReaderOptions());
cannam@62 318 // Creates a message pointing at the given segment array, without taking ownership of the
cannam@62 319 // segments. All arrays passed in must remain valid until the MessageReader is destroyed.
cannam@62 320
cannam@62 321 KJ_DISALLOW_COPY(SegmentArrayMessageReader);
cannam@62 322 ~SegmentArrayMessageReader() noexcept(false);
cannam@62 323
cannam@62 324 virtual kj::ArrayPtr<const word> getSegment(uint id) override;
cannam@62 325
cannam@62 326 private:
cannam@62 327 kj::ArrayPtr<const kj::ArrayPtr<const word>> segments;
cannam@62 328 };
cannam@62 329
cannam@62 330 enum class AllocationStrategy: uint8_t {
cannam@62 331 FIXED_SIZE,
cannam@62 332 // The builder will prefer to allocate the same amount of space for each segment with no
cannam@62 333 // heuristic growth. It will still allocate larger segments when the preferred size is too small
cannam@62 334 // for some single object. This mode is generally not recommended, but can be particularly useful
cannam@62 335 // for testing in order to force a message to allocate a predictable number of segments. Note
cannam@62 336 // that you can force every single object in the message to be located in a separate segment by
cannam@62 337 // using this mode with firstSegmentWords = 0.
cannam@62 338
cannam@62 339 GROW_HEURISTICALLY
cannam@62 340 // The builder will heuristically decide how much space to allocate for each segment. Each
cannam@62 341 // allocated segment will be progressively larger than the previous segments on the assumption
cannam@62 342 // that message sizes are exponentially distributed. The total number of segments that will be
cannam@62 343 // allocated for a message of size n is O(log n).
cannam@62 344 };
cannam@62 345
cannam@62 346 constexpr uint SUGGESTED_FIRST_SEGMENT_WORDS = 1024;
cannam@62 347 constexpr AllocationStrategy SUGGESTED_ALLOCATION_STRATEGY = AllocationStrategy::GROW_HEURISTICALLY;
cannam@62 348
cannam@62 349 class MallocMessageBuilder: public MessageBuilder {
cannam@62 350 // A simple MessageBuilder that uses malloc() (actually, calloc()) to allocate segments. This
cannam@62 351 // implementation should be reasonable for any case that doesn't require writing the message to
cannam@62 352 // a specific location in memory.
cannam@62 353
cannam@62 354 public:
cannam@62 355 explicit MallocMessageBuilder(uint firstSegmentWords = SUGGESTED_FIRST_SEGMENT_WORDS,
cannam@62 356 AllocationStrategy allocationStrategy = SUGGESTED_ALLOCATION_STRATEGY);
cannam@62 357 // Creates a BuilderContext which allocates at least the given number of words for the first
cannam@62 358 // segment, and then uses the given strategy to decide how much to allocate for subsequent
cannam@62 359 // segments. When choosing a value for firstSegmentWords, consider that:
cannam@62 360 // 1) Reading and writing messages gets slower when multiple segments are involved, so it's good
cannam@62 361 // if most messages fit in a single segment.
cannam@62 362 // 2) Unused bytes will not be written to the wire, so generally it is not a big deal to allocate
cannam@62 363 // more space than you need. It only becomes problematic if you are allocating many messages
cannam@62 364 // in parallel and thus use lots of memory, or if you allocate so much extra space that just
cannam@62 365 // zeroing it out becomes a bottleneck.
cannam@62 366 // The defaults have been chosen to be reasonable for most people, so don't change them unless you
cannam@62 367 // have reason to believe you need to.
cannam@62 368
cannam@62 369 explicit MallocMessageBuilder(kj::ArrayPtr<word> firstSegment,
cannam@62 370 AllocationStrategy allocationStrategy = SUGGESTED_ALLOCATION_STRATEGY);
cannam@62 371 // This version always returns the given array for the first segment, and then proceeds with the
cannam@62 372 // allocation strategy. This is useful for optimization when building lots of small messages in
cannam@62 373 // a tight loop: you can reuse the space for the first segment.
cannam@62 374 //
cannam@62 375 // firstSegment MUST be zero-initialized. MallocMessageBuilder's destructor will write new zeros
cannam@62 376 // over any space that was used so that it can be reused.
cannam@62 377
cannam@62 378 KJ_DISALLOW_COPY(MallocMessageBuilder);
cannam@62 379 virtual ~MallocMessageBuilder() noexcept(false);
cannam@62 380
cannam@62 381 virtual kj::ArrayPtr<word> allocateSegment(uint minimumSize) override;
cannam@62 382
cannam@62 383 private:
cannam@62 384 uint nextSize;
cannam@62 385 AllocationStrategy allocationStrategy;
cannam@62 386
cannam@62 387 bool ownFirstSegment;
cannam@62 388 bool returnedFirstSegment;
cannam@62 389
cannam@62 390 void* firstSegment;
cannam@62 391
cannam@62 392 struct MoreSegments;
cannam@62 393 kj::Maybe<kj::Own<MoreSegments>> moreSegments;
cannam@62 394 };
cannam@62 395
cannam@62 396 class FlatMessageBuilder: public MessageBuilder {
cannam@62 397 // THIS IS NOT THE CLASS YOU'RE LOOKING FOR.
cannam@62 398 //
cannam@62 399 // If you want to write a message into already-existing scratch space, use `MallocMessageBuilder`
cannam@62 400 // and pass the scratch space to its constructor. It will then only fall back to malloc() if
cannam@62 401 // the scratch space is not large enough.
cannam@62 402 //
cannam@62 403 // Do NOT use this class unless you really know what you're doing. This class is problematic
cannam@62 404 // because it requires advance knowledge of the size of your message, which is usually impossible
cannam@62 405 // to determine without actually building the message. The class was created primarily to
cannam@62 406 // implement `copyToUnchecked()`, which itself exists only to support other internal parts of
cannam@62 407 // the Cap'n Proto implementation.
cannam@62 408
cannam@62 409 public:
cannam@62 410 explicit FlatMessageBuilder(kj::ArrayPtr<word> array);
cannam@62 411 KJ_DISALLOW_COPY(FlatMessageBuilder);
cannam@62 412 virtual ~FlatMessageBuilder() noexcept(false);
cannam@62 413
cannam@62 414 void requireFilled();
cannam@62 415 // Throws an exception if the flat array is not exactly full.
cannam@62 416
cannam@62 417 virtual kj::ArrayPtr<word> allocateSegment(uint minimumSize) override;
cannam@62 418
cannam@62 419 private:
cannam@62 420 kj::ArrayPtr<word> array;
cannam@62 421 bool allocated;
cannam@62 422 };
cannam@62 423
cannam@62 424 // =======================================================================================
cannam@62 425 // implementation details
cannam@62 426
cannam@62 427 inline const ReaderOptions& MessageReader::getOptions() {
cannam@62 428 return options;
cannam@62 429 }
cannam@62 430
cannam@62 431 template <typename RootType>
cannam@62 432 inline typename RootType::Reader MessageReader::getRoot() {
cannam@62 433 return getRootInternal().getAs<RootType>();
cannam@62 434 }
cannam@62 435
cannam@62 436 template <typename RootType>
cannam@62 437 inline typename RootType::Builder MessageBuilder::initRoot() {
cannam@62 438 return getRootInternal().initAs<RootType>();
cannam@62 439 }
cannam@62 440
cannam@62 441 template <typename Reader>
cannam@62 442 inline void MessageBuilder::setRoot(Reader&& value) {
cannam@62 443 getRootInternal().setAs<FromReader<Reader>>(value);
cannam@62 444 }
cannam@62 445
cannam@62 446 template <typename RootType>
cannam@62 447 inline typename RootType::Builder MessageBuilder::getRoot() {
cannam@62 448 return getRootInternal().getAs<RootType>();
cannam@62 449 }
cannam@62 450
cannam@62 451 template <typename T>
cannam@62 452 void MessageBuilder::adoptRoot(Orphan<T>&& orphan) {
cannam@62 453 return getRootInternal().adopt(kj::mv(orphan));
cannam@62 454 }
cannam@62 455
cannam@62 456 template <typename RootType, typename SchemaType>
cannam@62 457 typename RootType::Reader MessageReader::getRoot(SchemaType schema) {
cannam@62 458 return getRootInternal().getAs<RootType>(schema);
cannam@62 459 }
cannam@62 460
cannam@62 461 template <typename RootType, typename SchemaType>
cannam@62 462 typename RootType::Builder MessageBuilder::getRoot(SchemaType schema) {
cannam@62 463 return getRootInternal().getAs<RootType>(schema);
cannam@62 464 }
cannam@62 465
cannam@62 466 template <typename RootType, typename SchemaType>
cannam@62 467 typename RootType::Builder MessageBuilder::initRoot(SchemaType schema) {
cannam@62 468 return getRootInternal().initAs<RootType>(schema);
cannam@62 469 }
cannam@62 470
cannam@62 471 template <typename RootType>
cannam@62 472 typename RootType::Reader readMessageUnchecked(const word* data) {
cannam@62 473 return AnyPointer::Reader(_::PointerReader::getRootUnchecked(data)).getAs<RootType>();
cannam@62 474 }
cannam@62 475
cannam@62 476 template <typename Reader>
cannam@62 477 void copyToUnchecked(Reader&& reader, kj::ArrayPtr<word> uncheckedBuffer) {
cannam@62 478 FlatMessageBuilder builder(uncheckedBuffer);
cannam@62 479 builder.setRoot(kj::fwd<Reader>(reader));
cannam@62 480 builder.requireFilled();
cannam@62 481 }
cannam@62 482
cannam@62 483 template <typename RootType>
cannam@62 484 typename RootType::Reader readDataStruct(kj::ArrayPtr<const word> data) {
cannam@62 485 return typename RootType::Reader(_::StructReader(data));
cannam@62 486 }
cannam@62 487
cannam@62 488 template <typename BuilderType>
cannam@62 489 typename kj::ArrayPtr<const word> writeDataStruct(BuilderType builder) {
cannam@62 490 auto bytes = _::PointerHelpers<FromBuilder<BuilderType>>::getInternalBuilder(kj::mv(builder))
cannam@62 491 .getDataSectionAsBlob();
cannam@62 492 return kj::arrayPtr(reinterpret_cast<word*>(bytes.begin()),
cannam@62 493 reinterpret_cast<word*>(bytes.end()));
cannam@62 494 }
cannam@62 495
cannam@62 496 template <typename Type>
cannam@62 497 static typename Type::Reader defaultValue() {
cannam@62 498 return typename Type::Reader(_::StructReader());
cannam@62 499 }
cannam@62 500
cannam@62 501 template <typename T>
cannam@62 502 kj::Array<word> canonicalize(T&& reader) {
cannam@62 503 return _::PointerHelpers<FromReader<T>>::getInternalReader(reader).canonicalize();
cannam@62 504 }
cannam@62 505
cannam@62 506 } // namespace capnp
cannam@62 507
cannam@62 508 #endif // CAPNP_MESSAGE_H_