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