parent
							
								
									660a156557
								
							
						
					
					
						commit
						e10f330290
					
				
				 93 changed files with 44625 additions and 13 deletions
			
			
		
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -0,0 +1,220 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_BLOB_H_ | ||||
| #define CAPNP_BLOB_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include <kj/common.h> | ||||
| #include <kj/string.h> | ||||
| #include "common.h" | ||||
| #include <string.h> | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| struct Data { | ||||
|   Data() = delete; | ||||
|   class Reader; | ||||
|   class Builder; | ||||
|   class Pipeline {}; | ||||
| }; | ||||
| 
 | ||||
| struct Text { | ||||
|   Text() = delete; | ||||
|   class Reader; | ||||
|   class Builder; | ||||
|   class Pipeline {}; | ||||
| }; | ||||
| 
 | ||||
| class Data::Reader: public kj::ArrayPtr<const byte> { | ||||
|   // Points to a blob of bytes.  The usual Reader rules apply -- Data::Reader behaves like a simple
 | ||||
|   // pointer which does not own its target, can be passed by value, etc.
 | ||||
| 
 | ||||
| public: | ||||
|   typedef Data Reads; | ||||
| 
 | ||||
|   Reader() = default; | ||||
|   inline Reader(decltype(nullptr)): ArrayPtr<const byte>(nullptr) {} | ||||
|   inline Reader(const byte* value, size_t size): ArrayPtr<const byte>(value, size) {} | ||||
|   inline Reader(const kj::Array<const byte>& value): ArrayPtr<const byte>(value) {} | ||||
|   inline Reader(const ArrayPtr<const byte>& value): ArrayPtr<const byte>(value) {} | ||||
|   inline Reader(const kj::Array<byte>& value): ArrayPtr<const byte>(value) {} | ||||
|   inline Reader(const ArrayPtr<byte>& value): ArrayPtr<const byte>(value) {} | ||||
| }; | ||||
| 
 | ||||
| class Text::Reader: public kj::StringPtr { | ||||
|   // Like Data::Reader, but points at NUL-terminated UTF-8 text.  The NUL terminator is not counted
 | ||||
|   // in the size but must be present immediately after the last byte.
 | ||||
|   //
 | ||||
|   // Text::Reader's interface contract is that its data MUST be NUL-terminated.  The producer of
 | ||||
|   // the Text::Reader must guarantee this, so that the consumer need not check.  The data SHOULD
 | ||||
|   // also be valid UTF-8, but this is NOT guaranteed -- the consumer must verify if it cares.
 | ||||
| 
 | ||||
| public: | ||||
|   typedef Text Reads; | ||||
| 
 | ||||
|   Reader() = default; | ||||
|   inline Reader(decltype(nullptr)): StringPtr(nullptr) {} | ||||
|   inline Reader(const char* value): StringPtr(value) {} | ||||
|   inline Reader(const char* value, size_t size): StringPtr(value, size) {} | ||||
|   inline Reader(const kj::String& value): StringPtr(value) {} | ||||
|   inline Reader(const StringPtr& value): StringPtr(value) {} | ||||
| 
 | ||||
| #if KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP | ||||
|   template <typename T, typename = decltype(kj::instance<T>().c_str())> | ||||
|   inline Reader(const T& t): StringPtr(t) {} | ||||
|   // Allow implicit conversion from any class that has a c_str() method (namely, std::string).
 | ||||
|   // We use a template trick to detect std::string in order to avoid including the header for
 | ||||
|   // those who don't want it.
 | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| class Data::Builder: public kj::ArrayPtr<byte> { | ||||
|   // Like Data::Reader except the pointers aren't const.
 | ||||
| 
 | ||||
| public: | ||||
|   typedef Data Builds; | ||||
| 
 | ||||
|   Builder() = default; | ||||
|   inline Builder(decltype(nullptr)): ArrayPtr<byte>(nullptr) {} | ||||
|   inline Builder(byte* value, size_t size): ArrayPtr<byte>(value, size) {} | ||||
|   inline Builder(kj::Array<byte>& value): ArrayPtr<byte>(value) {} | ||||
|   inline Builder(ArrayPtr<byte> value): ArrayPtr<byte>(value) {} | ||||
| 
 | ||||
|   inline Data::Reader asReader() const { return Data::Reader(*this); } | ||||
|   inline operator Reader() const { return asReader(); } | ||||
| }; | ||||
| 
 | ||||
| class Text::Builder: public kj::DisallowConstCopy { | ||||
|   // Basically identical to kj::StringPtr, except that the contents are non-const.
 | ||||
| 
 | ||||
| public: | ||||
|   inline Builder(): content(nulstr, 1) {} | ||||
|   inline Builder(decltype(nullptr)): content(nulstr, 1) {} | ||||
|   inline Builder(char* value): content(value, strlen(value) + 1) {} | ||||
|   inline Builder(char* value, size_t size): content(value, size + 1) { | ||||
|     KJ_IREQUIRE(value[size] == '\0', "StringPtr must be NUL-terminated."); | ||||
|   } | ||||
| 
 | ||||
|   inline Reader asReader() const { return Reader(content.begin(), content.size() - 1); } | ||||
|   inline operator Reader() const { return asReader(); } | ||||
| 
 | ||||
|   inline operator kj::ArrayPtr<char>(); | ||||
|   inline kj::ArrayPtr<char> asArray(); | ||||
|   inline operator kj::ArrayPtr<const char>() const; | ||||
|   inline kj::ArrayPtr<const char> asArray() const; | ||||
|   inline kj::ArrayPtr<byte> asBytes() { return asArray().asBytes(); } | ||||
|   inline kj::ArrayPtr<const byte> asBytes() const { return asArray().asBytes(); } | ||||
|   // Result does not include NUL terminator.
 | ||||
| 
 | ||||
|   inline operator kj::StringPtr() const; | ||||
|   inline kj::StringPtr asString() const; | ||||
| 
 | ||||
|   inline const char* cStr() const { return content.begin(); } | ||||
|   // Returns NUL-terminated string.
 | ||||
| 
 | ||||
|   inline size_t size() const { return content.size() - 1; } | ||||
|   // Result does not include NUL terminator.
 | ||||
| 
 | ||||
|   inline char operator[](size_t index) const { return content[index]; } | ||||
|   inline char& operator[](size_t index) { return content[index]; } | ||||
| 
 | ||||
|   inline char* begin() { return content.begin(); } | ||||
|   inline char* end() { return content.end() - 1; } | ||||
|   inline const char* begin() const { return content.begin(); } | ||||
|   inline const char* end() const { return content.end() - 1; } | ||||
| 
 | ||||
|   inline bool operator==(decltype(nullptr)) const { return content.size() <= 1; } | ||||
|   inline bool operator!=(decltype(nullptr)) const { return content.size() > 1; } | ||||
| 
 | ||||
|   inline bool operator==(Builder other) const { return asString() == other.asString(); } | ||||
|   inline bool operator!=(Builder other) const { return asString() != other.asString(); } | ||||
|   inline bool operator< (Builder other) const { return asString() <  other.asString(); } | ||||
|   inline bool operator> (Builder other) const { return asString() >  other.asString(); } | ||||
|   inline bool operator<=(Builder other) const { return asString() <= other.asString(); } | ||||
|   inline bool operator>=(Builder other) const { return asString() >= other.asString(); } | ||||
| 
 | ||||
|   inline kj::StringPtr slice(size_t start) const; | ||||
|   inline kj::ArrayPtr<const char> slice(size_t start, size_t end) const; | ||||
|   inline Builder slice(size_t start); | ||||
|   inline kj::ArrayPtr<char> slice(size_t start, size_t end); | ||||
|   // A string slice is only NUL-terminated if it is a suffix, so slice() has a one-parameter
 | ||||
|   // version that assumes end = size().
 | ||||
| 
 | ||||
| private: | ||||
|   inline explicit Builder(kj::ArrayPtr<char> content): content(content) {} | ||||
| 
 | ||||
|   kj::ArrayPtr<char> content; | ||||
| 
 | ||||
|   static char nulstr[1]; | ||||
| }; | ||||
| 
 | ||||
| inline kj::StringPtr KJ_STRINGIFY(Text::Builder builder) { | ||||
|   return builder.asString(); | ||||
| } | ||||
| 
 | ||||
| inline bool operator==(const char* a, const Text::Builder& b) { return a == b.asString(); } | ||||
| inline bool operator!=(const char* a, const Text::Builder& b) { return a != b.asString(); } | ||||
| 
 | ||||
| inline Text::Builder::operator kj::StringPtr() const { | ||||
|   return kj::StringPtr(content.begin(), content.size() - 1); | ||||
| } | ||||
| 
 | ||||
| inline kj::StringPtr Text::Builder::asString() const { | ||||
|   return kj::StringPtr(content.begin(), content.size() - 1); | ||||
| } | ||||
| 
 | ||||
| inline Text::Builder::operator kj::ArrayPtr<char>() { | ||||
|   return content.slice(0, content.size() - 1); | ||||
| } | ||||
| 
 | ||||
| inline kj::ArrayPtr<char> Text::Builder::asArray() { | ||||
|   return content.slice(0, content.size() - 1); | ||||
| } | ||||
| 
 | ||||
| inline Text::Builder::operator kj::ArrayPtr<const char>() const { | ||||
|   return content.slice(0, content.size() - 1); | ||||
| } | ||||
| 
 | ||||
| inline kj::ArrayPtr<const char> Text::Builder::asArray() const { | ||||
|   return content.slice(0, content.size() - 1); | ||||
| } | ||||
| 
 | ||||
| inline kj::StringPtr Text::Builder::slice(size_t start) const { | ||||
|   return asReader().slice(start); | ||||
| } | ||||
| inline kj::ArrayPtr<const char> Text::Builder::slice(size_t start, size_t end) const { | ||||
|   return content.slice(start, end); | ||||
| } | ||||
| 
 | ||||
| inline Text::Builder Text::Builder::slice(size_t start) { | ||||
|   return Text::Builder(content.slice(start, content.size())); | ||||
| } | ||||
| inline kj::ArrayPtr<char> Text::Builder::slice(size_t start, size_t end) { | ||||
|   return content.slice(start, end); | ||||
| } | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_BLOB_H_
 | ||||
| @ -0,0 +1,26 @@ | ||||
| # Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors | ||||
| # Licensed under the MIT License: | ||||
| # | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| # of this software and associated documentation files (the "Software"), to deal | ||||
| # in the Software without restriction, including without limitation the rights | ||||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| # copies of the Software, and to permit persons to whom the Software is | ||||
| # furnished to do so, subject to the following conditions: | ||||
| # | ||||
| # The above copyright notice and this permission notice shall be included in | ||||
| # all copies or substantial portions of the Software. | ||||
| # | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| # THE SOFTWARE. | ||||
| 
 | ||||
| @0xbdf87d7bb8304e81; | ||||
| $namespace("capnp::annotations"); | ||||
| 
 | ||||
| annotation namespace(file): Text; | ||||
| annotation name(field, enumerant, struct, enum, interface, method, param, group, union): Text; | ||||
| @ -0,0 +1,33 @@ | ||||
| // Generated by Cap'n Proto compiler, DO NOT EDIT
 | ||||
| // source: c++.capnp
 | ||||
| 
 | ||||
| #ifndef CAPNP_INCLUDED_bdf87d7bb8304e81_ | ||||
| #define CAPNP_INCLUDED_bdf87d7bb8304e81_ | ||||
| 
 | ||||
| #include <capnp/generated-header-support.h> | ||||
| 
 | ||||
| #if CAPNP_VERSION != 6001 | ||||
| #error "Version mismatch between generated code and library headers.  You must use the same version of the Cap'n Proto compiler and library." | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| namespace capnp { | ||||
| namespace schemas { | ||||
| 
 | ||||
| CAPNP_DECLARE_SCHEMA(b9c6f99ebf805f2c); | ||||
| CAPNP_DECLARE_SCHEMA(f264a779fef191ce); | ||||
| 
 | ||||
| }  // namespace schemas
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| namespace capnp { | ||||
| namespace annotations { | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| }  // namespace
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| #endif  // CAPNP_INCLUDED_bdf87d7bb8304e81_
 | ||||
| @ -0,0 +1,37 @@ | ||||
| # Copyright (c) 2016 NetDEF, Inc. and contributors | ||||
| # Licensed under the MIT License: | ||||
| # | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| # of this software and associated documentation files (the "Software"), to deal | ||||
| # in the Software without restriction, including without limitation the rights | ||||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| # copies of the Software, and to permit persons to whom the Software is | ||||
| # furnished to do so, subject to the following conditions: | ||||
| # | ||||
| # The above copyright notice and this permission notice shall be included in | ||||
| # all copies or substantial portions of the Software. | ||||
| # | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| # THE SOFTWARE. | ||||
| 
 | ||||
| @0xc0183dd65ffef0f3; | ||||
| 
 | ||||
| annotation nameinfix @0x85a8d86d736ba637 (file): Text; | ||||
| # add an infix (middle insert) for output file names | ||||
| # | ||||
| # "make" generally has implicit rules for compiling "foo.c" => "foo".  This | ||||
| # is very annoying with capnp since the rule will be "foo" => "foo.c", leading | ||||
| # to a loop.  $nameinfix (recommended parameter: "-gen") inserts its parameter | ||||
| # before the ".c", so the filename becomes "foo-gen.c" | ||||
| # | ||||
| # ("foo" is really "foo.capnp", so it's foo.capnp-gen.c) | ||||
| 
 | ||||
| annotation fieldgetset @0xf72bc690355d66de (file): Void; | ||||
| # generate getter & setter functions for accessing fields | ||||
| # | ||||
| # allows grabbing/putting values without de-/encoding the entire struct. | ||||
| @ -0,0 +1,884 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_CAPABILITY_H_ | ||||
| #define CAPNP_CAPABILITY_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #if CAPNP_LITE | ||||
| #error "RPC APIs, including this header, are not available in lite mode." | ||||
| #endif | ||||
| 
 | ||||
| #include <kj/async.h> | ||||
| #include <kj/vector.h> | ||||
| #include "raw-schema.h" | ||||
| #include "any.h" | ||||
| #include "pointer-helpers.h" | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| template <typename Results> | ||||
| class Response; | ||||
| 
 | ||||
| template <typename T> | ||||
| class RemotePromise: public kj::Promise<Response<T>>, public T::Pipeline { | ||||
|   // A Promise which supports pipelined calls.  T is typically a struct type.  T must declare
 | ||||
|   // an inner "mix-in" type "Pipeline" which implements pipelining; RemotePromise simply
 | ||||
|   // multiply-inherits that type along with Promise<Response<T>>.  T::Pipeline must be movable,
 | ||||
|   // but does not need to be copyable (i.e. just like Promise<T>).
 | ||||
|   //
 | ||||
|   // The promise is for an owned pointer so that the RPC system can allocate the MessageReader
 | ||||
|   // itself.
 | ||||
| 
 | ||||
| public: | ||||
|   inline RemotePromise(kj::Promise<Response<T>>&& promise, typename T::Pipeline&& pipeline) | ||||
|       : kj::Promise<Response<T>>(kj::mv(promise)), | ||||
|         T::Pipeline(kj::mv(pipeline)) {} | ||||
|   inline RemotePromise(decltype(nullptr)) | ||||
|       : kj::Promise<Response<T>>(nullptr), | ||||
|         T::Pipeline(nullptr) {} | ||||
|   KJ_DISALLOW_COPY(RemotePromise); | ||||
|   RemotePromise(RemotePromise&& other) = default; | ||||
|   RemotePromise& operator=(RemotePromise&& other) = default; | ||||
| }; | ||||
| 
 | ||||
| class LocalClient; | ||||
| namespace _ { // private
 | ||||
| extern const RawSchema NULL_INTERFACE_SCHEMA;  // defined in schema.c++
 | ||||
| class CapabilityServerSetBase; | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| struct Capability { | ||||
|   // A capability without type-safe methods.  Typed capability clients wrap `Client` and typed
 | ||||
|   // capability servers subclass `Server` to dispatch to the regular, typed methods.
 | ||||
| 
 | ||||
|   class Client; | ||||
|   class Server; | ||||
| 
 | ||||
|   struct _capnpPrivate { | ||||
|     struct IsInterface; | ||||
|     static constexpr uint64_t typeId = 0x3; | ||||
|     static constexpr Kind kind = Kind::INTERFACE; | ||||
|     static constexpr _::RawSchema const* schema = &_::NULL_INTERFACE_SCHEMA; | ||||
| 
 | ||||
|     static const _::RawBrandedSchema* brand() { | ||||
|       return &_::NULL_INTERFACE_SCHEMA.defaultBrand; | ||||
|     } | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Capability clients
 | ||||
| 
 | ||||
| class RequestHook; | ||||
| class ResponseHook; | ||||
| class PipelineHook; | ||||
| class ClientHook; | ||||
| 
 | ||||
| template <typename Params, typename Results> | ||||
| class Request: public Params::Builder { | ||||
|   // A call that hasn't been sent yet.  This class extends a Builder for the call's "Params"
 | ||||
|   // structure with a method send() that actually sends it.
 | ||||
|   //
 | ||||
|   // Given a Cap'n Proto method `foo(a :A, b :B): C`, the generated client interface will have
 | ||||
|   // a method `Request<FooParams, C> fooRequest()` (as well as a convenience method
 | ||||
|   // `RemotePromise<C> foo(A::Reader a, B::Reader b)`).
 | ||||
| 
 | ||||
| public: | ||||
|   inline Request(typename Params::Builder builder, kj::Own<RequestHook>&& hook) | ||||
|       : Params::Builder(builder), hook(kj::mv(hook)) {} | ||||
|   inline Request(decltype(nullptr)): Params::Builder(nullptr) {} | ||||
| 
 | ||||
|   RemotePromise<Results> send() KJ_WARN_UNUSED_RESULT; | ||||
|   // Send the call and return a promise for the results.
 | ||||
| 
 | ||||
| private: | ||||
|   kj::Own<RequestHook> hook; | ||||
| 
 | ||||
|   friend class Capability::Client; | ||||
|   friend struct DynamicCapability; | ||||
|   template <typename, typename> | ||||
|   friend class CallContext; | ||||
|   friend class RequestHook; | ||||
| }; | ||||
| 
 | ||||
| template <typename Results> | ||||
| class Response: public Results::Reader { | ||||
|   // A completed call.  This class extends a Reader for the call's answer structure.  The Response
 | ||||
|   // is move-only -- once it goes out-of-scope, the underlying message will be freed.
 | ||||
| 
 | ||||
| public: | ||||
|   inline Response(typename Results::Reader reader, kj::Own<ResponseHook>&& hook) | ||||
|       : Results::Reader(reader), hook(kj::mv(hook)) {} | ||||
| 
 | ||||
| private: | ||||
|   kj::Own<ResponseHook> hook; | ||||
| 
 | ||||
|   template <typename, typename> | ||||
|   friend class Request; | ||||
|   friend class ResponseHook; | ||||
| }; | ||||
| 
 | ||||
| class Capability::Client { | ||||
|   // Base type for capability clients.
 | ||||
| 
 | ||||
| public: | ||||
|   typedef Capability Reads; | ||||
|   typedef Capability Calls; | ||||
| 
 | ||||
|   Client(decltype(nullptr)); | ||||
|   // If you need to declare a Client before you have anything to assign to it (perhaps because
 | ||||
|   // the assignment is going to occur in an if/else scope), you can start by initializing it to
 | ||||
|   // `nullptr`.  The resulting client is not meant to be called and throws exceptions from all
 | ||||
|   // methods.
 | ||||
| 
 | ||||
|   template <typename T, typename = kj::EnableIf<kj::canConvert<T*, Capability::Server*>()>> | ||||
|   Client(kj::Own<T>&& server); | ||||
|   // Make a client capability that wraps the given server capability.  The server's methods will
 | ||||
|   // only be executed in the given EventLoop, regardless of what thread calls the client's methods.
 | ||||
| 
 | ||||
|   template <typename T, typename = kj::EnableIf<kj::canConvert<T*, Client*>()>> | ||||
|   Client(kj::Promise<T>&& promise); | ||||
|   // Make a client from a promise for a future client.  The resulting client queues calls until the
 | ||||
|   // promise resolves.
 | ||||
| 
 | ||||
|   Client(kj::Exception&& exception); | ||||
|   // Make a broken client that throws the given exception from all calls.
 | ||||
| 
 | ||||
|   Client(Client& other); | ||||
|   Client& operator=(Client& other); | ||||
|   // Copies by reference counting.  Warning:  This refcounting is not thread-safe.  All copies of
 | ||||
|   // the client must remain in one thread.
 | ||||
| 
 | ||||
|   Client(Client&&) = default; | ||||
|   Client& operator=(Client&&) = default; | ||||
|   // Move constructor avoids reference counting.
 | ||||
| 
 | ||||
|   explicit Client(kj::Own<ClientHook>&& hook); | ||||
|   // For use by the RPC implementation:  Wrap a ClientHook.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   typename T::Client castAs(); | ||||
|   // Reinterpret the capability as implementing the given interface.  Note that no error will occur
 | ||||
|   // here if the capability does not actually implement this interface, but later method calls will
 | ||||
|   // fail.  It's up to the application to decide how indicate that additional interfaces are
 | ||||
|   // supported.
 | ||||
|   //
 | ||||
|   // TODO(perf):  GCC 4.8 / Clang 3.3:  rvalue-qualified version for better performance.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   typename T::Client castAs(InterfaceSchema schema); | ||||
|   // Dynamic version.  `T` must be `DynamicCapability`, and you must `#include <capnp/dynamic.h>`.
 | ||||
| 
 | ||||
|   kj::Promise<void> whenResolved(); | ||||
|   // If the capability is actually only a promise, the returned promise resolves once the
 | ||||
|   // capability itself has resolved to its final destination (or propagates the exception if
 | ||||
|   // the capability promise is rejected).  This is mainly useful for error-checking in the case
 | ||||
|   // where no calls are being made.  There is no reason to wait for this before making calls; if
 | ||||
|   // the capability does not resolve, the call results will propagate the error.
 | ||||
| 
 | ||||
|   Request<AnyPointer, AnyPointer> typelessRequest( | ||||
|       uint64_t interfaceId, uint16_t methodId, | ||||
|       kj::Maybe<MessageSize> sizeHint); | ||||
|   // Make a request without knowing the types of the params or results. You specify the type ID
 | ||||
|   // and method number manually.
 | ||||
| 
 | ||||
|   // TODO(someday):  method(s) for Join
 | ||||
| 
 | ||||
| protected: | ||||
|   Client() = default; | ||||
| 
 | ||||
|   template <typename Params, typename Results> | ||||
|   Request<Params, Results> newCall(uint64_t interfaceId, uint16_t methodId, | ||||
|                                    kj::Maybe<MessageSize> sizeHint); | ||||
| 
 | ||||
| private: | ||||
|   kj::Own<ClientHook> hook; | ||||
| 
 | ||||
|   static kj::Own<ClientHook> makeLocalClient(kj::Own<Capability::Server>&& server); | ||||
| 
 | ||||
|   template <typename, Kind> | ||||
|   friend struct _::PointerHelpers; | ||||
|   friend struct DynamicCapability; | ||||
|   friend class Orphanage; | ||||
|   friend struct DynamicStruct; | ||||
|   friend struct DynamicList; | ||||
|   template <typename, Kind> | ||||
|   friend struct List; | ||||
|   friend class _::CapabilityServerSetBase; | ||||
|   friend class ClientHook; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Capability servers
 | ||||
| 
 | ||||
| class CallContextHook; | ||||
| 
 | ||||
| template <typename Params, typename Results> | ||||
| class CallContext: public kj::DisallowConstCopy { | ||||
|   // Wrapper around CallContextHook with a specific return type.
 | ||||
|   //
 | ||||
|   // Methods of this class may only be called from within the server's event loop, not from other
 | ||||
|   // threads.
 | ||||
|   //
 | ||||
|   // The CallContext becomes invalid as soon as the call reports completion.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit CallContext(CallContextHook& hook); | ||||
| 
 | ||||
|   typename Params::Reader getParams(); | ||||
|   // Get the params payload.
 | ||||
| 
 | ||||
|   void releaseParams(); | ||||
|   // Release the params payload.  getParams() will throw an exception after this is called.
 | ||||
|   // Releasing the params may allow the RPC system to free up buffer space to handle other
 | ||||
|   // requests.  Long-running asynchronous methods should try to call this as early as is
 | ||||
|   // convenient.
 | ||||
| 
 | ||||
|   typename Results::Builder getResults(kj::Maybe<MessageSize> sizeHint = nullptr); | ||||
|   typename Results::Builder initResults(kj::Maybe<MessageSize> sizeHint = nullptr); | ||||
|   void setResults(typename Results::Reader value); | ||||
|   void adoptResults(Orphan<Results>&& value); | ||||
|   Orphanage getResultsOrphanage(kj::Maybe<MessageSize> sizeHint = nullptr); | ||||
|   // Manipulate the results payload.  The "Return" message (part of the RPC protocol) will
 | ||||
|   // typically be allocated the first time one of these is called.  Some RPC systems may
 | ||||
|   // allocate these messages in a limited space (such as a shared memory segment), therefore the
 | ||||
|   // application should delay calling these as long as is convenient to do so (but don't delay
 | ||||
|   // if doing so would require extra copies later).
 | ||||
|   //
 | ||||
|   // `sizeHint` indicates a guess at the message size.  This will usually be used to decide how
 | ||||
|   // much space to allocate for the first message segment (don't worry: only space that is actually
 | ||||
|   // used will be sent on the wire).  If omitted, the system decides.  The message root pointer
 | ||||
|   // should not be included in the size.  So, if you are simply going to copy some existing message
 | ||||
|   // directly into the results, just call `.totalSize()` and pass that in.
 | ||||
| 
 | ||||
|   template <typename SubParams> | ||||
|   kj::Promise<void> tailCall(Request<SubParams, Results>&& tailRequest); | ||||
|   // Resolve the call by making a tail call.  `tailRequest` is a request that has been filled in
 | ||||
|   // but not yet sent.  The context will send the call, then fill in the results with the result
 | ||||
|   // of the call.  If tailCall() is used, {get,init,set,adopt}Results (above) *must not* be called.
 | ||||
|   //
 | ||||
|   // The RPC implementation may be able to optimize a tail call to another machine such that the
 | ||||
|   // results never actually pass through this machine.  Even if no such optimization is possible,
 | ||||
|   // `tailCall()` may allow pipelined calls to be forwarded optimistically to the new call site.
 | ||||
|   //
 | ||||
|   // In general, this should be the last thing a method implementation calls, and the promise
 | ||||
|   // returned from `tailCall()` should then be returned by the method implementation.
 | ||||
| 
 | ||||
|   void allowCancellation(); | ||||
|   // Indicate that it is OK for the RPC system to discard its Promise for this call's result if
 | ||||
|   // the caller cancels the call, thereby transitively canceling any asynchronous operations the
 | ||||
|   // call implementation was performing.  This is not done by default because it could represent a
 | ||||
|   // security risk:  applications must be carefully written to ensure that they do not end up in
 | ||||
|   // a bad state if an operation is canceled at an arbitrary point.  However, for long-running
 | ||||
|   // method calls that hold significant resources, prompt cancellation is often useful.
 | ||||
|   //
 | ||||
|   // Keep in mind that asynchronous cancellation cannot occur while the method is synchronously
 | ||||
|   // executing on a local thread.  The method must perform an asynchronous operation or call
 | ||||
|   // `EventLoop::current().evalLater()` to yield control.
 | ||||
|   //
 | ||||
|   // Note:  You might think that we should offer `onCancel()` and/or `isCanceled()` methods that
 | ||||
|   // provide notification when the caller cancels the request without forcefully killing off the
 | ||||
|   // promise chain.  Unfortunately, this composes poorly with promise forking:  the canceled
 | ||||
|   // path may be just one branch of a fork of the result promise.  The other branches still want
 | ||||
|   // the call to continue.  Promise forking is used within the Cap'n Proto implementation -- in
 | ||||
|   // particular each pipelined call forks the result promise.  So, if a caller made a pipelined
 | ||||
|   // call and then dropped the original object, the call should not be canceled, but it would be
 | ||||
|   // excessively complicated for the framework to avoid notififying of cancellation as long as
 | ||||
|   // pipelined calls still exist.
 | ||||
| 
 | ||||
| private: | ||||
|   CallContextHook* hook; | ||||
| 
 | ||||
|   friend class Capability::Server; | ||||
|   friend struct DynamicCapability; | ||||
| }; | ||||
| 
 | ||||
| class Capability::Server { | ||||
|   // Objects implementing a Cap'n Proto interface must subclass this.  Typically, such objects
 | ||||
|   // will instead subclass a typed Server interface which will take care of implementing
 | ||||
|   // dispatchCall().
 | ||||
| 
 | ||||
| public: | ||||
|   typedef Capability Serves; | ||||
| 
 | ||||
|   virtual kj::Promise<void> dispatchCall(uint64_t interfaceId, uint16_t methodId, | ||||
|                                          CallContext<AnyPointer, AnyPointer> context) = 0; | ||||
|   // Call the given method.  `params` is the input struct, and should be released as soon as it
 | ||||
|   // is no longer needed.  `context` may be used to allocate the output struct and deal with
 | ||||
|   // cancellation.
 | ||||
| 
 | ||||
|   // TODO(someday):  Method which can optionally be overridden to implement Join when the object is
 | ||||
|   //   a proxy.
 | ||||
| 
 | ||||
| protected: | ||||
|   inline Capability::Client thisCap(); | ||||
|   // Get a capability pointing to this object, much like the `this` keyword.
 | ||||
|   //
 | ||||
|   // The effect of this method is undefined if:
 | ||||
|   // - No capability client has been created pointing to this object. (This is always the case in
 | ||||
|   //   the server's constructor.)
 | ||||
|   // - The capability client pointing at this object has been destroyed. (This is always the case
 | ||||
|   //   in the server's destructor.)
 | ||||
|   // - Multiple capability clients have been created around the same server (possible if the server
 | ||||
|   //   is refcounted, which is not recommended since the client itself provides refcounting).
 | ||||
| 
 | ||||
|   template <typename Params, typename Results> | ||||
|   CallContext<Params, Results> internalGetTypedContext( | ||||
|       CallContext<AnyPointer, AnyPointer> typeless); | ||||
|   kj::Promise<void> internalUnimplemented(const char* actualInterfaceName, | ||||
|                                           uint64_t requestedTypeId); | ||||
|   kj::Promise<void> internalUnimplemented(const char* interfaceName, | ||||
|                                           uint64_t typeId, uint16_t methodId); | ||||
|   kj::Promise<void> internalUnimplemented(const char* interfaceName, const char* methodName, | ||||
|                                           uint64_t typeId, uint16_t methodId); | ||||
| 
 | ||||
| private: | ||||
|   ClientHook* thisHook = nullptr; | ||||
|   friend class LocalClient; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| class ReaderCapabilityTable: private _::CapTableReader { | ||||
|   // Class which imbues Readers with the ability to read capabilities.
 | ||||
|   //
 | ||||
|   // In Cap'n Proto format, the encoding of a capability pointer is simply an integer index into
 | ||||
|   // an external table. Since these pointers fundamentally point outside the message, a
 | ||||
|   // MessageReader by default has no idea what they point at, and therefore reading capabilities
 | ||||
|   // from such a reader will throw exceptions.
 | ||||
|   //
 | ||||
|   // In order to be able to read capabilities, you must first attach a capability table, using
 | ||||
|   // this class. By "imbuing" a Reader, you get a new Reader which will interpret capability
 | ||||
|   // pointers by treating them as indexes into the ReaderCapabilityTable.
 | ||||
|   //
 | ||||
|   // Note that when using Cap'n Proto's RPC system, this is handled automatically.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit ReaderCapabilityTable(kj::Array<kj::Maybe<kj::Own<ClientHook>>> table); | ||||
|   KJ_DISALLOW_COPY(ReaderCapabilityTable); | ||||
| 
 | ||||
|   template <typename T> | ||||
|   T imbue(T reader); | ||||
|   // Return a reader equivalent to `reader` except that when reading capability-valued fields,
 | ||||
|   // the capabilities are looked up in this table.
 | ||||
| 
 | ||||
| private: | ||||
|   kj::Array<kj::Maybe<kj::Own<ClientHook>>> table; | ||||
| 
 | ||||
|   kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override; | ||||
| }; | ||||
| 
 | ||||
| class BuilderCapabilityTable: private _::CapTableBuilder { | ||||
|   // Class which imbues Builders with the ability to read and write capabilities.
 | ||||
|   //
 | ||||
|   // This is much like ReaderCapabilityTable, except for builders. The table starts out empty,
 | ||||
|   // but capabilities can be added to it over time.
 | ||||
| 
 | ||||
| public: | ||||
|   BuilderCapabilityTable(); | ||||
|   KJ_DISALLOW_COPY(BuilderCapabilityTable); | ||||
| 
 | ||||
|   inline kj::ArrayPtr<kj::Maybe<kj::Own<ClientHook>>> getTable() { return table; } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   T imbue(T builder); | ||||
|   // Return a builder equivalent to `builder` except that when reading capability-valued fields,
 | ||||
|   // the capabilities are looked up in this table.
 | ||||
| 
 | ||||
| private: | ||||
|   kj::Vector<kj::Maybe<kj::Own<ClientHook>>> table; | ||||
| 
 | ||||
|   kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override; | ||||
|   uint injectCap(kj::Own<ClientHook>&& cap) override; | ||||
|   void dropCap(uint index) override; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| class CapabilityServerSetBase { | ||||
| public: | ||||
|   Capability::Client addInternal(kj::Own<Capability::Server>&& server, void* ptr); | ||||
|   kj::Promise<void*> getLocalServerInternal(Capability::Client& client); | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class CapabilityServerSet: private _::CapabilityServerSetBase { | ||||
|   // Allows a server to recognize its own capabilities when passed back to it, and obtain the
 | ||||
|   // underlying Server objects associated with them.
 | ||||
|   //
 | ||||
|   // All objects in the set must have the same interface type T. The objects may implement various
 | ||||
|   // interfaces derived from T (and in fact T can be `capnp::Capability` to accept all objects),
 | ||||
|   // but note that if you compile with RTTI disabled then you will not be able to down-cast through
 | ||||
|   // virtual inheritance, and all inheritance between server interfaces is virtual. So, with RTTI
 | ||||
|   // disabled, you will likely need to set T to be the most-derived Cap'n Proto interface type,
 | ||||
|   // and you server class will need to be directly derived from that, so that you can use
 | ||||
|   // static_cast (or kj::downcast) to cast to it after calling getLocalServer(). (If you compile
 | ||||
|   // with RTTI, then you can freely dynamic_cast and ignore this issue!)
 | ||||
| 
 | ||||
| public: | ||||
|   CapabilityServerSet() = default; | ||||
|   KJ_DISALLOW_COPY(CapabilityServerSet); | ||||
| 
 | ||||
|   typename T::Client add(kj::Own<typename T::Server>&& server); | ||||
|   // Create a new capability Client for the given Server and also add this server to the set.
 | ||||
| 
 | ||||
|   kj::Promise<kj::Maybe<typename T::Server&>> getLocalServer(typename T::Client& client); | ||||
|   // Given a Client pointing to a server previously passed to add(), return the corresponding
 | ||||
|   // Server. This returns a promise because if the input client is itself a promise, this must
 | ||||
|   // wait for it to resolve. Keep in mind that the server will be deleted when all clients are
 | ||||
|   // gone, so the caller should make sure to keep the client alive (hence why this method only
 | ||||
|   // accepts an lvalue input).
 | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Hook interfaces which must be implemented by the RPC system.  Applications never call these
 | ||||
| // directly; the RPC system implements them and the types defined earlier in this file wrap them.
 | ||||
| 
 | ||||
| class RequestHook { | ||||
|   // Hook interface implemented by RPC system representing a request being built.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual RemotePromise<AnyPointer> send() = 0; | ||||
|   // Send the call and return a promise for the result.
 | ||||
| 
 | ||||
|   virtual const void* getBrand() = 0; | ||||
|   // Returns a void* that identifies who made this request.  This can be used by an RPC adapter to
 | ||||
|   // discover when tail call is going to be sent over its own connection and therefore can be
 | ||||
|   // optimized into a remote tail call.
 | ||||
| 
 | ||||
|   template <typename T, typename U> | ||||
|   inline static kj::Own<RequestHook> from(Request<T, U>&& request) { | ||||
|     return kj::mv(request.hook); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| class ResponseHook { | ||||
|   // Hook interface implemented by RPC system representing a response.
 | ||||
|   //
 | ||||
|   // At present this class has no methods.  It exists only for garbage collection -- when the
 | ||||
|   // ResponseHook is destroyed, the results can be freed.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual ~ResponseHook() noexcept(false); | ||||
|   // Just here to make sure the type is dynamic.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   inline static kj::Own<ResponseHook> from(Response<T>&& response) { | ||||
|     return kj::mv(response.hook); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| // class PipelineHook is declared in any.h because it is needed there.
 | ||||
| 
 | ||||
| class ClientHook { | ||||
| public: | ||||
|   ClientHook(); | ||||
| 
 | ||||
|   virtual Request<AnyPointer, AnyPointer> newCall( | ||||
|       uint64_t interfaceId, uint16_t methodId, kj::Maybe<MessageSize> sizeHint) = 0; | ||||
|   // Start a new call, allowing the client to allocate request/response objects as it sees fit.
 | ||||
|   // This version is used when calls are made from application code in the local process.
 | ||||
| 
 | ||||
|   struct VoidPromiseAndPipeline { | ||||
|     kj::Promise<void> promise; | ||||
|     kj::Own<PipelineHook> pipeline; | ||||
|   }; | ||||
| 
 | ||||
|   virtual VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId, | ||||
|                                       kj::Own<CallContextHook>&& context) = 0; | ||||
|   // Call the object, but the caller controls allocation of the request/response objects.  If the
 | ||||
|   // callee insists on allocating these objects itself, it must make a copy.  This version is used
 | ||||
|   // when calls come in over the network via an RPC system.  Note that even if the returned
 | ||||
|   // `Promise<void>` is discarded, the call may continue executing if any pipelined calls are
 | ||||
|   // waiting for it.
 | ||||
|   //
 | ||||
|   // Since the caller of this method chooses the CallContext implementation, it is the caller's
 | ||||
|   // responsibility to ensure that the returned promise is not canceled unless allowed via
 | ||||
|   // the context's `allowCancellation()`.
 | ||||
|   //
 | ||||
|   // The call must not begin synchronously; the callee must arrange for the call to begin in a
 | ||||
|   // later turn of the event loop. Otherwise, application code may call back and affect the
 | ||||
|   // callee's state in an unexpected way.
 | ||||
| 
 | ||||
|   virtual kj::Maybe<ClientHook&> getResolved() = 0; | ||||
|   // If this ClientHook is a promise that has already resolved, returns the inner, resolved version
 | ||||
|   // of the capability.  The caller may permanently replace this client with the resolved one if
 | ||||
|   // desired.  Returns null if the client isn't a promise or hasn't resolved yet -- use
 | ||||
|   // `whenMoreResolved()` to distinguish between them.
 | ||||
| 
 | ||||
|   virtual kj::Maybe<kj::Promise<kj::Own<ClientHook>>> whenMoreResolved() = 0; | ||||
|   // If this client is a settled reference (not a promise), return nullptr.  Otherwise, return a
 | ||||
|   // promise that eventually resolves to a new client that is closer to being the final, settled
 | ||||
|   // client (i.e. the value eventually returned by `getResolved()`).  Calling this repeatedly
 | ||||
|   // should eventually produce a settled client.
 | ||||
| 
 | ||||
|   kj::Promise<void> whenResolved(); | ||||
|   // Repeatedly calls whenMoreResolved() until it returns nullptr.
 | ||||
| 
 | ||||
|   virtual kj::Own<ClientHook> addRef() = 0; | ||||
|   // Return a new reference to the same capability.
 | ||||
| 
 | ||||
|   virtual const void* getBrand() = 0; | ||||
|   // Returns a void* that identifies who made this client.  This can be used by an RPC adapter to
 | ||||
|   // discover when a capability it needs to marshal is one that it created in the first place, and
 | ||||
|   // therefore it can transfer the capability without proxying.
 | ||||
| 
 | ||||
|   static const uint NULL_CAPABILITY_BRAND; | ||||
|   // Value is irrelevant; used for pointer.
 | ||||
| 
 | ||||
|   inline bool isNull() { return getBrand() == &NULL_CAPABILITY_BRAND; } | ||||
|   // Returns true if the capability was created as a result of assigning a Client to null or by
 | ||||
|   // reading a null pointer out of a Cap'n Proto message.
 | ||||
| 
 | ||||
|   virtual void* getLocalServer(_::CapabilityServerSetBase& capServerSet); | ||||
|   // If this is a local capability created through `capServerSet`, return the underlying Server.
 | ||||
|   // Otherwise, return nullptr. Default implementation (which everyone except LocalClient should
 | ||||
|   // use) always returns nullptr.
 | ||||
| 
 | ||||
|   static kj::Own<ClientHook> from(Capability::Client client) { return kj::mv(client.hook); } | ||||
| }; | ||||
| 
 | ||||
| class CallContextHook { | ||||
|   // Hook interface implemented by RPC system to manage a call on the server side.  See
 | ||||
|   // CallContext<T>.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual AnyPointer::Reader getParams() = 0; | ||||
|   virtual void releaseParams() = 0; | ||||
|   virtual AnyPointer::Builder getResults(kj::Maybe<MessageSize> sizeHint) = 0; | ||||
|   virtual kj::Promise<void> tailCall(kj::Own<RequestHook>&& request) = 0; | ||||
|   virtual void allowCancellation() = 0; | ||||
| 
 | ||||
|   virtual kj::Promise<AnyPointer::Pipeline> onTailCall() = 0; | ||||
|   // If `tailCall()` is called, resolves to the PipelineHook from the tail call.  An
 | ||||
|   // implementation of `ClientHook::call()` is allowed to call this at most once.
 | ||||
| 
 | ||||
|   virtual ClientHook::VoidPromiseAndPipeline directTailCall(kj::Own<RequestHook>&& request) = 0; | ||||
|   // Call this when you would otherwise call onTailCall() immediately followed by tailCall().
 | ||||
|   // Implementations of tailCall() should typically call directTailCall() and then fulfill the
 | ||||
|   // promise fulfiller for onTailCall() with the returned pipeline.
 | ||||
| 
 | ||||
|   virtual kj::Own<CallContextHook> addRef() = 0; | ||||
| }; | ||||
| 
 | ||||
| kj::Own<ClientHook> newLocalPromiseClient(kj::Promise<kj::Own<ClientHook>>&& promise); | ||||
| // Returns a ClientHook that queues up calls until `promise` resolves, then forwards them to
 | ||||
| // the new client.  This hook's `getResolved()` and `whenMoreResolved()` methods will reflect the
 | ||||
| // redirection to the eventual replacement client.
 | ||||
| 
 | ||||
| kj::Own<PipelineHook> newLocalPromisePipeline(kj::Promise<kj::Own<PipelineHook>>&& promise); | ||||
| // Returns a PipelineHook that queues up calls until `promise` resolves, then forwards them to
 | ||||
| // the new pipeline.
 | ||||
| 
 | ||||
| kj::Own<ClientHook> newBrokenCap(kj::StringPtr reason); | ||||
| kj::Own<ClientHook> newBrokenCap(kj::Exception&& reason); | ||||
| // Helper function that creates a capability which simply throws exceptions when called.
 | ||||
| 
 | ||||
| kj::Own<PipelineHook> newBrokenPipeline(kj::Exception&& reason); | ||||
| // Helper function that creates a pipeline which simply throws exceptions when called.
 | ||||
| 
 | ||||
| Request<AnyPointer, AnyPointer> newBrokenRequest( | ||||
|     kj::Exception&& reason, kj::Maybe<MessageSize> sizeHint); | ||||
| // Helper function that creates a Request object that simply throws exceptions when sent.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Extend PointerHelpers for interfaces
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T> | ||||
| struct PointerHelpers<T, Kind::INTERFACE> { | ||||
|   static inline typename T::Client get(PointerReader reader) { | ||||
|     return typename T::Client(reader.getCapability()); | ||||
|   } | ||||
|   static inline typename T::Client get(PointerBuilder builder) { | ||||
|     return typename T::Client(builder.getCapability()); | ||||
|   } | ||||
|   static inline void set(PointerBuilder builder, typename T::Client&& value) { | ||||
|     builder.setCapability(kj::mv(value.Capability::Client::hook)); | ||||
|   } | ||||
|   static inline void set(PointerBuilder builder, typename T::Client& value) { | ||||
|     builder.setCapability(value.Capability::Client::hook->addRef()); | ||||
|   } | ||||
|   static inline void adopt(PointerBuilder builder, Orphan<T>&& value) { | ||||
|     builder.adopt(kj::mv(value.builder)); | ||||
|   } | ||||
|   static inline Orphan<T> disown(PointerBuilder builder) { | ||||
|     return Orphan<T>(builder.disown()); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Extend List for interfaces
 | ||||
| 
 | ||||
| template <typename T> | ||||
| struct List<T, Kind::INTERFACE> { | ||||
|   List() = delete; | ||||
| 
 | ||||
|   class Reader { | ||||
|   public: | ||||
|     typedef List<T> Reads; | ||||
| 
 | ||||
|     Reader() = default; | ||||
|     inline explicit Reader(_::ListReader reader): reader(reader) {} | ||||
| 
 | ||||
|     inline uint size() const { return unbound(reader.size() / ELEMENTS); } | ||||
|     inline typename T::Client operator[](uint index) const { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       return typename T::Client(reader.getPointerElement( | ||||
|           bounded(index) * ELEMENTS).getCapability()); | ||||
|     } | ||||
| 
 | ||||
|     typedef _::IndexingIterator<const Reader, typename T::Client> Iterator; | ||||
|     inline Iterator begin() const { return Iterator(this, 0); } | ||||
|     inline Iterator end() const { return Iterator(this, size()); } | ||||
| 
 | ||||
|   private: | ||||
|     _::ListReader reader; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct _::PointerHelpers; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct List; | ||||
|     friend class Orphanage; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct ToDynamic_; | ||||
|   }; | ||||
| 
 | ||||
|   class Builder { | ||||
|   public: | ||||
|     typedef List<T> Builds; | ||||
| 
 | ||||
|     Builder() = delete; | ||||
|     inline Builder(decltype(nullptr)) {} | ||||
|     inline explicit Builder(_::ListBuilder builder): builder(builder) {} | ||||
| 
 | ||||
|     inline operator Reader() const { return Reader(builder.asReader()); } | ||||
|     inline Reader asReader() const { return Reader(builder.asReader()); } | ||||
| 
 | ||||
|     inline uint size() const { return unbound(builder.size() / ELEMENTS); } | ||||
|     inline typename T::Client operator[](uint index) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       return typename T::Client(builder.getPointerElement( | ||||
|           bounded(index) * ELEMENTS).getCapability()); | ||||
|     } | ||||
|     inline void set(uint index, typename T::Client value) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       builder.getPointerElement(bounded(index) * ELEMENTS).setCapability(kj::mv(value.hook)); | ||||
|     } | ||||
|     inline void adopt(uint index, Orphan<T>&& value) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value)); | ||||
|     } | ||||
|     inline Orphan<T> disown(uint index) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown()); | ||||
|     } | ||||
| 
 | ||||
|     typedef _::IndexingIterator<Builder, typename T::Client> Iterator; | ||||
|     inline Iterator begin() { return Iterator(this, 0); } | ||||
|     inline Iterator end() { return Iterator(this, size()); } | ||||
| 
 | ||||
|   private: | ||||
|     _::ListBuilder builder; | ||||
|     friend class Orphanage; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct ToDynamic_; | ||||
|   }; | ||||
| 
 | ||||
| private: | ||||
|   inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) { | ||||
|     return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS); | ||||
|   } | ||||
|   inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) { | ||||
|     return builder.getList(ElementSize::POINTER, defaultValue); | ||||
|   } | ||||
|   inline static _::ListReader getFromPointer( | ||||
|       const _::PointerReader& reader, const word* defaultValue) { | ||||
|     return reader.getList(ElementSize::POINTER, defaultValue); | ||||
|   } | ||||
| 
 | ||||
|   template <typename U, Kind k> | ||||
|   friend struct List; | ||||
|   template <typename U, Kind K> | ||||
|   friend struct _::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Inline implementation details
 | ||||
| 
 | ||||
| template <typename Params, typename Results> | ||||
| RemotePromise<Results> Request<Params, Results>::send() { | ||||
|   auto typelessPromise = hook->send(); | ||||
|   hook = nullptr;  // prevent reuse
 | ||||
| 
 | ||||
|   // Convert the Promise to return the correct response type.
 | ||||
|   // Explicitly upcast to kj::Promise to make clear that calling .then() doesn't invalidate the
 | ||||
|   // Pipeline part of the RemotePromise.
 | ||||
|   auto typedPromise = kj::implicitCast<kj::Promise<Response<AnyPointer>>&>(typelessPromise) | ||||
|       .then([](Response<AnyPointer>&& response) -> Response<Results> { | ||||
|         return Response<Results>(response.getAs<Results>(), kj::mv(response.hook)); | ||||
|       }); | ||||
| 
 | ||||
|   // Wrap the typeless pipeline in a typed wrapper.
 | ||||
|   typename Results::Pipeline typedPipeline( | ||||
|       kj::mv(kj::implicitCast<AnyPointer::Pipeline&>(typelessPromise))); | ||||
| 
 | ||||
|   return RemotePromise<Results>(kj::mv(typedPromise), kj::mv(typedPipeline)); | ||||
| } | ||||
| 
 | ||||
| inline Capability::Client::Client(kj::Own<ClientHook>&& hook): hook(kj::mv(hook)) {} | ||||
| template <typename T, typename> | ||||
| inline Capability::Client::Client(kj::Own<T>&& server) | ||||
|     : hook(makeLocalClient(kj::mv(server))) {} | ||||
| template <typename T, typename> | ||||
| inline Capability::Client::Client(kj::Promise<T>&& promise) | ||||
|     : hook(newLocalPromiseClient(promise.then([](T&& t) { return kj::mv(t.hook); }))) {} | ||||
| inline Capability::Client::Client(Client& other): hook(other.hook->addRef()) {} | ||||
| inline Capability::Client& Capability::Client::operator=(Client& other) { | ||||
|   hook = other.hook->addRef(); | ||||
|   return *this; | ||||
| } | ||||
| template <typename T> | ||||
| inline typename T::Client Capability::Client::castAs() { | ||||
|   return typename T::Client(hook->addRef()); | ||||
| } | ||||
| inline kj::Promise<void> Capability::Client::whenResolved() { | ||||
|   return hook->whenResolved(); | ||||
| } | ||||
| inline Request<AnyPointer, AnyPointer> Capability::Client::typelessRequest( | ||||
|     uint64_t interfaceId, uint16_t methodId, | ||||
|     kj::Maybe<MessageSize> sizeHint) { | ||||
|   return newCall<AnyPointer, AnyPointer>(interfaceId, methodId, sizeHint); | ||||
| } | ||||
| template <typename Params, typename Results> | ||||
| inline Request<Params, Results> Capability::Client::newCall( | ||||
|     uint64_t interfaceId, uint16_t methodId, kj::Maybe<MessageSize> sizeHint) { | ||||
|   auto typeless = hook->newCall(interfaceId, methodId, sizeHint); | ||||
|   return Request<Params, Results>(typeless.template getAs<Params>(), kj::mv(typeless.hook)); | ||||
| } | ||||
| 
 | ||||
| template <typename Params, typename Results> | ||||
| inline CallContext<Params, Results>::CallContext(CallContextHook& hook): hook(&hook) {} | ||||
| template <typename Params, typename Results> | ||||
| inline typename Params::Reader CallContext<Params, Results>::getParams() { | ||||
|   return hook->getParams().template getAs<Params>(); | ||||
| } | ||||
| template <typename Params, typename Results> | ||||
| inline void CallContext<Params, Results>::releaseParams() { | ||||
|   hook->releaseParams(); | ||||
| } | ||||
| template <typename Params, typename Results> | ||||
| inline typename Results::Builder CallContext<Params, Results>::getResults( | ||||
|     kj::Maybe<MessageSize> sizeHint) { | ||||
|   // `template` keyword needed due to: http://llvm.org/bugs/show_bug.cgi?id=17401
 | ||||
|   return hook->getResults(sizeHint).template getAs<Results>(); | ||||
| } | ||||
| template <typename Params, typename Results> | ||||
| inline typename Results::Builder CallContext<Params, Results>::initResults( | ||||
|     kj::Maybe<MessageSize> sizeHint) { | ||||
|   // `template` keyword needed due to: http://llvm.org/bugs/show_bug.cgi?id=17401
 | ||||
|   return hook->getResults(sizeHint).template initAs<Results>(); | ||||
| } | ||||
| template <typename Params, typename Results> | ||||
| inline void CallContext<Params, Results>::setResults(typename Results::Reader value) { | ||||
|   hook->getResults(value.totalSize()).template setAs<Results>(value); | ||||
| } | ||||
| template <typename Params, typename Results> | ||||
| inline void CallContext<Params, Results>::adoptResults(Orphan<Results>&& value) { | ||||
|   hook->getResults(nullptr).adopt(kj::mv(value)); | ||||
| } | ||||
| template <typename Params, typename Results> | ||||
| inline Orphanage CallContext<Params, Results>::getResultsOrphanage( | ||||
|     kj::Maybe<MessageSize> sizeHint) { | ||||
|   return Orphanage::getForMessageContaining(hook->getResults(sizeHint)); | ||||
| } | ||||
| template <typename Params, typename Results> | ||||
| template <typename SubParams> | ||||
| inline kj::Promise<void> CallContext<Params, Results>::tailCall( | ||||
|     Request<SubParams, Results>&& tailRequest) { | ||||
|   return hook->tailCall(kj::mv(tailRequest.hook)); | ||||
| } | ||||
| template <typename Params, typename Results> | ||||
| inline void CallContext<Params, Results>::allowCancellation() { | ||||
|   hook->allowCancellation(); | ||||
| } | ||||
| 
 | ||||
| template <typename Params, typename Results> | ||||
| CallContext<Params, Results> Capability::Server::internalGetTypedContext( | ||||
|     CallContext<AnyPointer, AnyPointer> typeless) { | ||||
|   return CallContext<Params, Results>(*typeless.hook); | ||||
| } | ||||
| 
 | ||||
| Capability::Client Capability::Server::thisCap() { | ||||
|   return Client(thisHook->addRef()); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| T ReaderCapabilityTable::imbue(T reader) { | ||||
|   return T(_::PointerHelpers<FromReader<T>>::getInternalReader(reader).imbue(this)); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| T BuilderCapabilityTable::imbue(T builder) { | ||||
|   return T(_::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::mv(builder)).imbue(this)); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| typename T::Client CapabilityServerSet<T>::add(kj::Own<typename T::Server>&& server) { | ||||
|   void* ptr = reinterpret_cast<void*>(server.get()); | ||||
|   // Clang insists that `castAs` is a template-dependent member and therefore we need the
 | ||||
|   // `template` keyword here, but AFAICT this is wrong: addImpl() is not a template.
 | ||||
|   return addInternal(kj::mv(server), ptr).template castAs<T>(); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| kj::Promise<kj::Maybe<typename T::Server&>> CapabilityServerSet<T>::getLocalServer( | ||||
|     typename T::Client& client) { | ||||
|   return getLocalServerInternal(client) | ||||
|       .then([](void* server) -> kj::Maybe<typename T::Server&> { | ||||
|     if (server == nullptr) { | ||||
|       return nullptr; | ||||
|     } else { | ||||
|       return *reinterpret_cast<typename T::Server*>(server); | ||||
|     } | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| struct Orphanage::GetInnerReader<T, Kind::INTERFACE> { | ||||
|   static inline kj::Own<ClientHook> apply(typename T::Client t) { | ||||
|     return ClientHook::from(kj::mv(t)); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_CAPABILITY_H_
 | ||||
| @ -0,0 +1,723 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| // This file contains types which are intended to help detect incorrect usage at compile
 | ||||
| // time, but should then be optimized down to basic primitives (usually, integers) by the
 | ||||
| // compiler.
 | ||||
| 
 | ||||
| #ifndef CAPNP_COMMON_H_ | ||||
| #define CAPNP_COMMON_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include <inttypes.h> | ||||
| #include <kj/string.h> | ||||
| #include <kj/memory.h> | ||||
| 
 | ||||
| #if CAPNP_DEBUG_TYPES | ||||
| #include <kj/units.h> | ||||
| #endif | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| #define CAPNP_VERSION_MAJOR 0 | ||||
| #define CAPNP_VERSION_MINOR 6 | ||||
| #define CAPNP_VERSION_MICRO 1 | ||||
| 
 | ||||
| #define CAPNP_VERSION \ | ||||
|   (CAPNP_VERSION_MAJOR * 1000000 + CAPNP_VERSION_MINOR * 1000 + CAPNP_VERSION_MICRO) | ||||
| 
 | ||||
| #ifndef CAPNP_LITE | ||||
| #define CAPNP_LITE 0 | ||||
| #endif | ||||
| 
 | ||||
| typedef unsigned int uint; | ||||
| 
 | ||||
| struct Void { | ||||
|   // Type used for Void fields.  Using C++'s "void" type creates a bunch of issues since it behaves
 | ||||
|   // differently from other types.
 | ||||
| 
 | ||||
|   inline constexpr bool operator==(Void other) const { return true; } | ||||
|   inline constexpr bool operator!=(Void other) const { return false; } | ||||
| }; | ||||
| 
 | ||||
| static constexpr Void VOID = Void(); | ||||
| // Constant value for `Void`,  which is an empty struct.
 | ||||
| 
 | ||||
| inline kj::StringPtr KJ_STRINGIFY(Void) { return "void"; } | ||||
| 
 | ||||
| struct Text; | ||||
| struct Data; | ||||
| 
 | ||||
| enum class Kind: uint8_t { | ||||
|   PRIMITIVE, | ||||
|   BLOB, | ||||
|   ENUM, | ||||
|   STRUCT, | ||||
|   UNION, | ||||
|   INTERFACE, | ||||
|   LIST, | ||||
| 
 | ||||
|   OTHER | ||||
|   // Some other type which is often a type parameter to Cap'n Proto templates, but which needs
 | ||||
|   // special handling. This includes types like AnyPointer, Dynamic*, etc.
 | ||||
| }; | ||||
| 
 | ||||
| enum class Style: uint8_t { | ||||
|   PRIMITIVE, | ||||
|   POINTER,      // other than struct
 | ||||
|   STRUCT, | ||||
|   CAPABILITY | ||||
| }; | ||||
| 
 | ||||
| enum class ElementSize: uint8_t { | ||||
|   // Size of a list element.
 | ||||
| 
 | ||||
|   VOID = 0, | ||||
|   BIT = 1, | ||||
|   BYTE = 2, | ||||
|   TWO_BYTES = 3, | ||||
|   FOUR_BYTES = 4, | ||||
|   EIGHT_BYTES = 5, | ||||
| 
 | ||||
|   POINTER = 6, | ||||
| 
 | ||||
|   INLINE_COMPOSITE = 7 | ||||
| }; | ||||
| 
 | ||||
| enum class PointerType { | ||||
|   // Various wire types a pointer field can take
 | ||||
| 
 | ||||
|   NULL_, | ||||
|   // Should be NULL, but that's #defined in stddef.h
 | ||||
| 
 | ||||
|   STRUCT, | ||||
|   LIST, | ||||
|   CAPABILITY | ||||
| }; | ||||
| 
 | ||||
| namespace schemas { | ||||
| 
 | ||||
| template <typename T> | ||||
| struct EnumInfo; | ||||
| 
 | ||||
| }  // namespace schemas
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T, typename = void> struct Kind_; | ||||
| 
 | ||||
| template <> struct Kind_<Void> { static constexpr Kind kind = Kind::PRIMITIVE; }; | ||||
| template <> struct Kind_<bool> { static constexpr Kind kind = Kind::PRIMITIVE; }; | ||||
| template <> struct Kind_<int8_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; | ||||
| template <> struct Kind_<int16_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; | ||||
| template <> struct Kind_<int32_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; | ||||
| template <> struct Kind_<int64_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; | ||||
| template <> struct Kind_<uint8_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; | ||||
| template <> struct Kind_<uint16_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; | ||||
| template <> struct Kind_<uint32_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; | ||||
| template <> struct Kind_<uint64_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; | ||||
| template <> struct Kind_<float> { static constexpr Kind kind = Kind::PRIMITIVE; }; | ||||
| template <> struct Kind_<double> { static constexpr Kind kind = Kind::PRIMITIVE; }; | ||||
| template <> struct Kind_<Text> { static constexpr Kind kind = Kind::BLOB; }; | ||||
| template <> struct Kind_<Data> { static constexpr Kind kind = Kind::BLOB; }; | ||||
| 
 | ||||
| template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsStruct>> { | ||||
|   static constexpr Kind kind = Kind::STRUCT; | ||||
| }; | ||||
| template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsInterface>> { | ||||
|   static constexpr Kind kind = Kind::INTERFACE; | ||||
| }; | ||||
| template <typename T> struct Kind_<T, kj::VoidSfinae<typename schemas::EnumInfo<T>::IsEnum>> { | ||||
|   static constexpr Kind kind = Kind::ENUM; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename T, Kind k = _::Kind_<T>::kind> | ||||
| inline constexpr Kind kind() { | ||||
|   // This overload of kind() matches types which have a Kind_ specialization.
 | ||||
| 
 | ||||
|   return k; | ||||
| } | ||||
| 
 | ||||
| #if _MSC_VER | ||||
| 
 | ||||
| #define CAPNP_KIND(T) ::capnp::_::Kind_<T>::kind | ||||
| // Avoid constexpr methods in MSVC (it remains buggy in many situations).
 | ||||
| 
 | ||||
| #else  // _MSC_VER
 | ||||
| 
 | ||||
| #define CAPNP_KIND(T) ::capnp::kind<T>() | ||||
| // Use this macro rather than kind<T>() in any code which must work in MSVC.
 | ||||
| 
 | ||||
| #endif  // _MSC_VER, else
 | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
| 
 | ||||
| template <typename T, Kind k = kind<T>()> | ||||
| inline constexpr Style style() { | ||||
|   return k == Kind::PRIMITIVE || k == Kind::ENUM ? Style::PRIMITIVE | ||||
|        : k == Kind::STRUCT ? Style::STRUCT | ||||
|        : k == Kind::INTERFACE ? Style::CAPABILITY : Style::POINTER; | ||||
| } | ||||
| 
 | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| template <typename T, Kind k = CAPNP_KIND(T)> | ||||
| struct List; | ||||
| 
 | ||||
| #if _MSC_VER | ||||
| 
 | ||||
| template <typename T, Kind k> | ||||
| struct List {}; | ||||
| // For some reason, without this declaration, MSVC will error out on some uses of List
 | ||||
| // claiming that "T" -- as used in the default initializer for the second template param, "k" --
 | ||||
| // is not defined. I do not understand this error, but adding this empty default declaration fixes
 | ||||
| // it.
 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| template <typename T> struct ListElementType_; | ||||
| template <typename T> struct ListElementType_<List<T>> { typedef T Type; }; | ||||
| template <typename T> using ListElementType = typename ListElementType_<T>::Type; | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| template <typename T, Kind k> struct Kind_<List<T, k>> { | ||||
|   static constexpr Kind kind = Kind::LIST; | ||||
| }; | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename T, Kind k = CAPNP_KIND(T)> struct ReaderFor_ { typedef typename T::Reader Type; }; | ||||
| template <typename T> struct ReaderFor_<T, Kind::PRIMITIVE> { typedef T Type; }; | ||||
| template <typename T> struct ReaderFor_<T, Kind::ENUM> { typedef T Type; }; | ||||
| template <typename T> struct ReaderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; }; | ||||
| template <typename T> using ReaderFor = typename ReaderFor_<T>::Type; | ||||
| // The type returned by List<T>::Reader::operator[].
 | ||||
| 
 | ||||
| template <typename T, Kind k = CAPNP_KIND(T)> struct BuilderFor_ { typedef typename T::Builder Type; }; | ||||
| template <typename T> struct BuilderFor_<T, Kind::PRIMITIVE> { typedef T Type; }; | ||||
| template <typename T> struct BuilderFor_<T, Kind::ENUM> { typedef T Type; }; | ||||
| template <typename T> struct BuilderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; }; | ||||
| template <typename T> using BuilderFor = typename BuilderFor_<T>::Type; | ||||
| // The type returned by List<T>::Builder::operator[].
 | ||||
| 
 | ||||
| template <typename T, Kind k = CAPNP_KIND(T)> struct PipelineFor_ { typedef typename T::Pipeline Type;}; | ||||
| template <typename T> struct PipelineFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; }; | ||||
| template <typename T> using PipelineFor = typename PipelineFor_<T>::Type; | ||||
| 
 | ||||
| template <typename T, Kind k = CAPNP_KIND(T)> struct TypeIfEnum_; | ||||
| template <typename T> struct TypeIfEnum_<T, Kind::ENUM> { typedef T Type; }; | ||||
| 
 | ||||
| template <typename T> | ||||
| using TypeIfEnum = typename TypeIfEnum_<kj::Decay<T>>::Type; | ||||
| 
 | ||||
| template <typename T> | ||||
| using FromReader = typename kj::Decay<T>::Reads; | ||||
| // FromReader<MyType::Reader> = MyType (for any Cap'n Proto type).
 | ||||
| 
 | ||||
| template <typename T> | ||||
| using FromBuilder = typename kj::Decay<T>::Builds; | ||||
| // FromBuilder<MyType::Builder> = MyType (for any Cap'n Proto type).
 | ||||
| 
 | ||||
| template <typename T> | ||||
| using FromPipeline = typename kj::Decay<T>::Pipelines; | ||||
| // FromBuilder<MyType::Pipeline> = MyType (for any Cap'n Proto type).
 | ||||
| 
 | ||||
| template <typename T> | ||||
| using FromClient = typename kj::Decay<T>::Calls; | ||||
| // FromReader<MyType::Client> = MyType (for any Cap'n Proto interface type).
 | ||||
| 
 | ||||
| template <typename T> | ||||
| using FromServer = typename kj::Decay<T>::Serves; | ||||
| // FromBuilder<MyType::Server> = MyType (for any Cap'n Proto interface type).
 | ||||
| 
 | ||||
| template <typename T, typename = void> | ||||
| struct FromAny_; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct FromAny_<T, kj::VoidSfinae<FromReader<T>>> { | ||||
|   using Type = FromReader<T>; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct FromAny_<T, kj::VoidSfinae<FromBuilder<T>>> { | ||||
|   using Type = FromBuilder<T>; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct FromAny_<T, kj::VoidSfinae<FromPipeline<T>>> { | ||||
|   using Type = FromPipeline<T>; | ||||
| }; | ||||
| 
 | ||||
| // Note that T::Client is covered by FromReader
 | ||||
| 
 | ||||
| template <typename T> | ||||
| struct FromAny_<kj::Own<T>, kj::VoidSfinae<FromServer<T>>> { | ||||
|   using Type = FromServer<T>; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct FromAny_<T, | ||||
|     kj::EnableIf<_::Kind_<T>::kind == Kind::PRIMITIVE || _::Kind_<T>::kind == Kind::ENUM>> { | ||||
|   // TODO(msvc): Ideally the EnableIf condition would be `style<T>() == Style::PRIMITIVE`, but MSVC
 | ||||
|   // cannot yet use style<T>() in this constexpr context.
 | ||||
| 
 | ||||
|   using Type = kj::Decay<T>; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| using FromAny = typename FromAny_<T>::Type; | ||||
| // Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is:
 | ||||
| //
 | ||||
| //     Foo::Reader -> Foo
 | ||||
| //     Foo::Builder -> Foo
 | ||||
| //     Foo::Pipeline -> Foo
 | ||||
| //     Foo::Client -> Foo
 | ||||
| //     Own<Foo::Server> -> Foo
 | ||||
| //     uint32_t -> uint32_t
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T, Kind k = CAPNP_KIND(T)> | ||||
| struct PointerHelpers; | ||||
| 
 | ||||
| #if _MSC_VER | ||||
| 
 | ||||
| template <typename T, Kind k> | ||||
| struct PointerHelpers {}; | ||||
| // For some reason, without this declaration, MSVC will error out on some uses of PointerHelpers
 | ||||
| // claiming that "T" -- as used in the default initializer for the second template param, "k" --
 | ||||
| // is not defined. I do not understand this error, but adding this empty default declaration fixes
 | ||||
| // it.
 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| struct MessageSize { | ||||
|   // Size of a message.  Every struct type has a method `.totalSize()` that returns this.
 | ||||
|   uint64_t wordCount; | ||||
|   uint capCount; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Raw memory types and measures
 | ||||
| 
 | ||||
| using kj::byte; | ||||
| 
 | ||||
| class word { uint64_t content KJ_UNUSED_MEMBER; KJ_DISALLOW_COPY(word); public: word() = default; }; | ||||
| // word is an opaque type with size of 64 bits.  This type is useful only to make pointer
 | ||||
| // arithmetic clearer.  Since the contents are private, the only way to access them is to first
 | ||||
| // reinterpret_cast to some other pointer type.
 | ||||
| //
 | ||||
| // Copying is disallowed because you should always use memcpy().  Otherwise, you may run afoul of
 | ||||
| // aliasing rules.
 | ||||
| //
 | ||||
| // A pointer of type word* should always be word-aligned even if won't actually be dereferenced as
 | ||||
| // that type.
 | ||||
| 
 | ||||
| static_assert(sizeof(byte) == 1, "uint8_t is not one byte?"); | ||||
| static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?"); | ||||
| 
 | ||||
| #if CAPNP_DEBUG_TYPES | ||||
| // Set CAPNP_DEBUG_TYPES to 1 to use kj::Quantity for "count" types.  Otherwise, plain integers are
 | ||||
| // used.  All the code should still operate exactly the same, we just lose compile-time checking.
 | ||||
| // Note that this will also change symbol names, so it's important that the library and any clients
 | ||||
| // be compiled with the same setting here.
 | ||||
| //
 | ||||
| // We disable this by default to reduce symbol name size and avoid any possibility of the compiler
 | ||||
| // failing to fully-optimize the types, but anyone modifying Cap'n Proto itself should enable this
 | ||||
| // during development and testing.
 | ||||
| 
 | ||||
| namespace _ { class BitLabel; class ElementLabel; struct WirePointer; } | ||||
| 
 | ||||
| template <uint width, typename T = uint> | ||||
| using BitCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::BitLabel>; | ||||
| template <uint width, typename T = uint> | ||||
| using ByteCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, byte>; | ||||
| template <uint width, typename T = uint> | ||||
| using WordCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, word>; | ||||
| template <uint width, typename T = uint> | ||||
| using ElementCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::ElementLabel>; | ||||
| template <uint width, typename T = uint> | ||||
| using WirePointerCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::WirePointer>; | ||||
| 
 | ||||
| typedef BitCountN<8, uint8_t> BitCount8; | ||||
| typedef BitCountN<16, uint16_t> BitCount16; | ||||
| typedef BitCountN<32, uint32_t> BitCount32; | ||||
| typedef BitCountN<64, uint64_t> BitCount64; | ||||
| typedef BitCountN<sizeof(uint) * 8, uint> BitCount; | ||||
| 
 | ||||
| typedef ByteCountN<8, uint8_t> ByteCount8; | ||||
| typedef ByteCountN<16, uint16_t> ByteCount16; | ||||
| typedef ByteCountN<32, uint32_t> ByteCount32; | ||||
| typedef ByteCountN<64, uint64_t> ByteCount64; | ||||
| typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount; | ||||
| 
 | ||||
| typedef WordCountN<8, uint8_t> WordCount8; | ||||
| typedef WordCountN<16, uint16_t> WordCount16; | ||||
| typedef WordCountN<32, uint32_t> WordCount32; | ||||
| typedef WordCountN<64, uint64_t> WordCount64; | ||||
| typedef WordCountN<sizeof(uint) * 8, uint> WordCount; | ||||
| 
 | ||||
| typedef ElementCountN<8, uint8_t> ElementCount8; | ||||
| typedef ElementCountN<16, uint16_t> ElementCount16; | ||||
| typedef ElementCountN<32, uint32_t> ElementCount32; | ||||
| typedef ElementCountN<64, uint64_t> ElementCount64; | ||||
| typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount; | ||||
| 
 | ||||
| typedef WirePointerCountN<8, uint8_t> WirePointerCount8; | ||||
| typedef WirePointerCountN<16, uint16_t> WirePointerCount16; | ||||
| typedef WirePointerCountN<32, uint32_t> WirePointerCount32; | ||||
| typedef WirePointerCountN<64, uint64_t> WirePointerCount64; | ||||
| typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount; | ||||
| 
 | ||||
| template <uint width> | ||||
| using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>()); | ||||
| template <uint width> | ||||
| using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>()); | ||||
| template <uint width> | ||||
| using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>()); | ||||
| template <uint width> | ||||
| using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>()); | ||||
| 
 | ||||
| using kj::bounded; | ||||
| using kj::unbound; | ||||
| using kj::unboundAs; | ||||
| using kj::unboundMax; | ||||
| using kj::unboundMaxBits; | ||||
| using kj::assertMax; | ||||
| using kj::assertMaxBits; | ||||
| using kj::upgradeBound; | ||||
| using kj::ThrowOverflow; | ||||
| using kj::assumeBits; | ||||
| using kj::assumeMax; | ||||
| using kj::subtractChecked; | ||||
| using kj::trySubtract; | ||||
| 
 | ||||
| template <typename T, typename U> | ||||
| inline constexpr U* operator+(U* ptr, kj::Quantity<T, U> offset) { | ||||
|   return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>()); | ||||
| } | ||||
| template <typename T, typename U> | ||||
| inline constexpr const U* operator+(const U* ptr, kj::Quantity<T, U> offset) { | ||||
|   return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>()); | ||||
| } | ||||
| template <typename T, typename U> | ||||
| inline constexpr U* operator+=(U*& ptr, kj::Quantity<T, U> offset) { | ||||
|   return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>()); | ||||
| } | ||||
| template <typename T, typename U> | ||||
| inline constexpr const U* operator+=(const U*& ptr, kj::Quantity<T, U> offset) { | ||||
|   return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>()); | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename U> | ||||
| inline constexpr U* operator-(U* ptr, kj::Quantity<T, U> offset) { | ||||
|   return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>()); | ||||
| } | ||||
| template <typename T, typename U> | ||||
| inline constexpr const U* operator-(const U* ptr, kj::Quantity<T, U> offset) { | ||||
|   return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>()); | ||||
| } | ||||
| template <typename T, typename U> | ||||
| inline constexpr U* operator-=(U*& ptr, kj::Quantity<T, U> offset) { | ||||
|   return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>()); | ||||
| } | ||||
| template <typename T, typename U> | ||||
| inline constexpr const U* operator-=(const U*& ptr, kj::Quantity<T, U> offset) { | ||||
|   return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>()); | ||||
| } | ||||
| 
 | ||||
| constexpr auto BITS = kj::unit<BitCountN<1>>(); | ||||
| constexpr auto BYTES = kj::unit<ByteCountN<1>>(); | ||||
| constexpr auto WORDS = kj::unit<WordCountN<1>>(); | ||||
| constexpr auto ELEMENTS = kj::unit<ElementCountN<1>>(); | ||||
| constexpr auto POINTERS = kj::unit<WirePointerCountN<1>>(); | ||||
| 
 | ||||
| constexpr auto ZERO = kj::bounded<0>(); | ||||
| constexpr auto ONE = kj::bounded<1>(); | ||||
| 
 | ||||
| // GCC 4.7 actually gives unused warnings on these constants in opt mode...
 | ||||
| constexpr auto BITS_PER_BYTE KJ_UNUSED = bounded<8>() * BITS / BYTES; | ||||
| constexpr auto BITS_PER_WORD KJ_UNUSED = bounded<64>() * BITS / WORDS; | ||||
| constexpr auto BYTES_PER_WORD KJ_UNUSED = bounded<8>() * BYTES / WORDS; | ||||
| 
 | ||||
| constexpr auto BITS_PER_POINTER KJ_UNUSED = bounded<64>() * BITS / POINTERS; | ||||
| constexpr auto BYTES_PER_POINTER KJ_UNUSED = bounded<8>() * BYTES / POINTERS; | ||||
| constexpr auto WORDS_PER_POINTER KJ_UNUSED = ONE * WORDS / POINTERS; | ||||
| 
 | ||||
| constexpr auto POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER; | ||||
| 
 | ||||
| constexpr uint SEGMENT_WORD_COUNT_BITS = 29;      // Number of words in a segment.
 | ||||
| constexpr uint LIST_ELEMENT_COUNT_BITS = 29;      // Number of elements in a list.
 | ||||
| constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16;  // Number of words in a Struct data section.
 | ||||
| constexpr uint STRUCT_POINTER_COUNT_BITS = 16;    // Number of pointers in a Struct pointer section.
 | ||||
| constexpr uint BLOB_SIZE_BITS = 29;               // Number of bytes in a blob.
 | ||||
| 
 | ||||
| typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount; | ||||
| typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount; | ||||
| typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount; | ||||
| typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount; | ||||
| typedef ByteCountN<BLOB_SIZE_BITS> BlobSize; | ||||
| 
 | ||||
| constexpr auto MAX_SEGMENT_WORDS = | ||||
|     bounded<kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>()>() * WORDS; | ||||
| constexpr auto MAX_LIST_ELEMENTS = | ||||
|     bounded<kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>()>() * ELEMENTS; | ||||
| constexpr auto MAX_STUCT_DATA_WORDS = | ||||
|     bounded<kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>()>() * WORDS; | ||||
| constexpr auto MAX_STRUCT_POINTER_COUNT = | ||||
|     bounded<kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>()>() * POINTERS; | ||||
| 
 | ||||
| using StructDataBitCount = decltype(WordCountN<STRUCT_POINTER_COUNT_BITS>() * BITS_PER_WORD); | ||||
| // Number of bits in a Struct data segment (should come out to BitCountN<22>).
 | ||||
| 
 | ||||
| using StructDataOffset = decltype(StructDataBitCount() * (ONE * ELEMENTS / BITS)); | ||||
| using StructPointerOffset = StructPointerCount; | ||||
| // Type of a field offset.
 | ||||
| 
 | ||||
| inline StructDataOffset assumeDataOffset(uint32_t offset) { | ||||
|   return assumeMax(MAX_STUCT_DATA_WORDS * BITS_PER_WORD * (ONE * ELEMENTS / BITS), | ||||
|                    bounded(offset) * ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| inline StructPointerOffset assumePointerOffset(uint32_t offset) { | ||||
|   return assumeMax(MAX_STRUCT_POINTER_COUNT, bounded(offset) * POINTERS); | ||||
| } | ||||
| 
 | ||||
| constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1; | ||||
| typedef kj::Quantity<kj::Bounded<MAX_TEXT_SIZE, uint>, byte> TextSize; | ||||
| // Not including NUL terminator.
 | ||||
| 
 | ||||
| template <typename T> | ||||
| inline KJ_CONSTEXPR() decltype(bounded<sizeof(T)>() * BYTES / ELEMENTS) bytesPerElement() { | ||||
|   return bounded<sizeof(T)>() * BYTES / ELEMENTS; | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline KJ_CONSTEXPR() decltype(bounded<sizeof(T) * 8>() * BITS / ELEMENTS) bitsPerElement() { | ||||
|   return bounded<sizeof(T) * 8>() * BITS / ELEMENTS; | ||||
| } | ||||
| 
 | ||||
| template <typename T, uint maxN> | ||||
| inline constexpr kj::Quantity<kj::Bounded<maxN, size_t>, T> | ||||
| intervalLength(const T* a, const T* b, kj::Quantity<kj::BoundedConst<maxN>, T>) { | ||||
|   return kj::assumeMax<maxN>(b - a) * kj::unit<kj::Quantity<kj::BoundedConst<1u>, T>>(); | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename U> | ||||
| inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, kj::Quantity<T, U> size) { | ||||
|   return kj::ArrayPtr<const U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>())); | ||||
| } | ||||
| template <typename T, typename U> | ||||
| inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, kj::Quantity<T, U> size) { | ||||
|   return kj::ArrayPtr<U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>())); | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| template <uint width, typename T = uint> | ||||
| using BitCountN = T; | ||||
| template <uint width, typename T = uint> | ||||
| using ByteCountN = T; | ||||
| template <uint width, typename T = uint> | ||||
| using WordCountN = T; | ||||
| template <uint width, typename T = uint> | ||||
| using ElementCountN = T; | ||||
| template <uint width, typename T = uint> | ||||
| using WirePointerCountN = T; | ||||
| 
 | ||||
| 
 | ||||
| // XXX
 | ||||
| typedef BitCountN<8, uint8_t> BitCount8; | ||||
| typedef BitCountN<16, uint16_t> BitCount16; | ||||
| typedef BitCountN<32, uint32_t> BitCount32; | ||||
| typedef BitCountN<64, uint64_t> BitCount64; | ||||
| typedef BitCountN<sizeof(uint) * 8, uint> BitCount; | ||||
| 
 | ||||
| typedef ByteCountN<8, uint8_t> ByteCount8; | ||||
| typedef ByteCountN<16, uint16_t> ByteCount16; | ||||
| typedef ByteCountN<32, uint32_t> ByteCount32; | ||||
| typedef ByteCountN<64, uint64_t> ByteCount64; | ||||
| typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount; | ||||
| 
 | ||||
| typedef WordCountN<8, uint8_t> WordCount8; | ||||
| typedef WordCountN<16, uint16_t> WordCount16; | ||||
| typedef WordCountN<32, uint32_t> WordCount32; | ||||
| typedef WordCountN<64, uint64_t> WordCount64; | ||||
| typedef WordCountN<sizeof(uint) * 8, uint> WordCount; | ||||
| 
 | ||||
| typedef ElementCountN<8, uint8_t> ElementCount8; | ||||
| typedef ElementCountN<16, uint16_t> ElementCount16; | ||||
| typedef ElementCountN<32, uint32_t> ElementCount32; | ||||
| typedef ElementCountN<64, uint64_t> ElementCount64; | ||||
| typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount; | ||||
| 
 | ||||
| typedef WirePointerCountN<8, uint8_t> WirePointerCount8; | ||||
| typedef WirePointerCountN<16, uint16_t> WirePointerCount16; | ||||
| typedef WirePointerCountN<32, uint32_t> WirePointerCount32; | ||||
| typedef WirePointerCountN<64, uint64_t> WirePointerCount64; | ||||
| typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount; | ||||
| 
 | ||||
| template <uint width> | ||||
| using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>()); | ||||
| template <uint width> | ||||
| using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>()); | ||||
| template <uint width> | ||||
| using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>()); | ||||
| template <uint width> | ||||
| using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>()); | ||||
| 
 | ||||
| using kj::ThrowOverflow; | ||||
| // YYY
 | ||||
| 
 | ||||
| template <uint i> inline constexpr uint bounded() { return i; } | ||||
| template <typename T> inline constexpr T bounded(T i) { return i; } | ||||
| template <typename T> inline constexpr T unbound(T i) { return i; } | ||||
| 
 | ||||
| template <typename T, typename U> inline constexpr T unboundAs(U i) { return i; } | ||||
| 
 | ||||
| template <uint64_t requestedMax, typename T> inline constexpr uint unboundMax(T i) { return i; } | ||||
| template <uint bits, typename T> inline constexpr uint unboundMaxBits(T i) { return i; } | ||||
| 
 | ||||
| template <uint newMax, typename T, typename ErrorFunc> | ||||
| inline T assertMax(T value, ErrorFunc&& func) { | ||||
|   if (KJ_UNLIKELY(value > newMax)) func(); | ||||
|   return value; | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename ErrorFunc> | ||||
| inline T assertMax(uint newMax, T value, ErrorFunc&& func) { | ||||
|   if (KJ_UNLIKELY(value > newMax)) func(); | ||||
|   return value; | ||||
| } | ||||
| 
 | ||||
| template <uint bits, typename T, typename ErrorFunc = ThrowOverflow> | ||||
| inline T assertMaxBits(T value, ErrorFunc&& func = ErrorFunc()) { | ||||
|   if (KJ_UNLIKELY(value > kj::maxValueForBits<bits>())) func(); | ||||
|   return value; | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename ErrorFunc = ThrowOverflow> | ||||
| inline T assertMaxBits(uint bits, T value, ErrorFunc&& func = ErrorFunc()) { | ||||
|   if (KJ_UNLIKELY(value > (1ull << bits) - 1)) func(); | ||||
|   return value; | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename U> inline constexpr T upgradeBound(U i) { return i; } | ||||
| 
 | ||||
| template <uint bits, typename T> inline constexpr T assumeBits(T i) { return i; } | ||||
| template <uint64_t max, typename T> inline constexpr T assumeMax(T i) { return i; } | ||||
| 
 | ||||
| template <typename T, typename U, typename ErrorFunc = ThrowOverflow> | ||||
| inline auto subtractChecked(T a, U b, ErrorFunc&& errorFunc = ErrorFunc()) | ||||
|     -> decltype(a - b) { | ||||
|   if (b > a) errorFunc(); | ||||
|   return a - b; | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename U> | ||||
| inline auto trySubtract(T a, U b) -> kj::Maybe<decltype(a - b)> { | ||||
|   if (b > a) { | ||||
|     return nullptr; | ||||
|   } else { | ||||
|     return a - b; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| constexpr uint BITS = 1; | ||||
| constexpr uint BYTES = 1; | ||||
| constexpr uint WORDS = 1; | ||||
| constexpr uint ELEMENTS = 1; | ||||
| constexpr uint POINTERS = 1; | ||||
| 
 | ||||
| constexpr uint ZERO = 0; | ||||
| constexpr uint ONE = 1; | ||||
| 
 | ||||
| // GCC 4.7 actually gives unused warnings on these constants in opt mode...
 | ||||
| constexpr uint BITS_PER_BYTE KJ_UNUSED = 8; | ||||
| constexpr uint BITS_PER_WORD KJ_UNUSED = 64; | ||||
| constexpr uint BYTES_PER_WORD KJ_UNUSED = 8; | ||||
| 
 | ||||
| constexpr uint BITS_PER_POINTER KJ_UNUSED = 64; | ||||
| constexpr uint BYTES_PER_POINTER KJ_UNUSED = 8; | ||||
| constexpr uint WORDS_PER_POINTER KJ_UNUSED = 1; | ||||
| 
 | ||||
| // XXX
 | ||||
| constexpr uint POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER; | ||||
| 
 | ||||
| constexpr uint SEGMENT_WORD_COUNT_BITS = 29;      // Number of words in a segment.
 | ||||
| constexpr uint LIST_ELEMENT_COUNT_BITS = 29;      // Number of elements in a list.
 | ||||
| constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16;  // Number of words in a Struct data section.
 | ||||
| constexpr uint STRUCT_POINTER_COUNT_BITS = 16;    // Number of pointers in a Struct pointer section.
 | ||||
| constexpr uint BLOB_SIZE_BITS = 29;               // Number of bytes in a blob.
 | ||||
| 
 | ||||
| typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount; | ||||
| typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount; | ||||
| typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount; | ||||
| typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount; | ||||
| typedef ByteCountN<BLOB_SIZE_BITS> BlobSize; | ||||
| // YYY
 | ||||
| 
 | ||||
| constexpr auto MAX_SEGMENT_WORDS = kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>(); | ||||
| constexpr auto MAX_LIST_ELEMENTS = kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>(); | ||||
| constexpr auto MAX_STUCT_DATA_WORDS = kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>(); | ||||
| constexpr auto MAX_STRUCT_POINTER_COUNT = kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>(); | ||||
| 
 | ||||
| typedef uint StructDataBitCount; | ||||
| typedef uint StructDataOffset; | ||||
| typedef uint StructPointerOffset; | ||||
| 
 | ||||
| inline StructDataOffset assumeDataOffset(uint32_t offset) { return offset; } | ||||
| inline StructPointerOffset assumePointerOffset(uint32_t offset) { return offset; } | ||||
| 
 | ||||
| constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1; | ||||
| typedef uint TextSize; | ||||
| 
 | ||||
| template <typename T> | ||||
| inline KJ_CONSTEXPR() size_t bytesPerElement() { return sizeof(T); } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline KJ_CONSTEXPR() size_t bitsPerElement() { return sizeof(T) * 8; } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline constexpr ptrdiff_t intervalLength(const T* a, const T* b, uint) { | ||||
|   return b - a; | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename U> | ||||
| inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, T size) { | ||||
|   return kj::arrayPtr(ptr, size); | ||||
| } | ||||
| template <typename T, typename U> | ||||
| inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, T size) { | ||||
|   return kj::arrayPtr(ptr, size); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_COMMON_H_
 | ||||
| @ -0,0 +1,860 @@ | ||||
| // Generated by Cap'n Proto compiler, DO NOT EDIT
 | ||||
| // source: json.capnp
 | ||||
| 
 | ||||
| #ifndef CAPNP_INCLUDED_8ef99297a43a5e34_ | ||||
| #define CAPNP_INCLUDED_8ef99297a43a5e34_ | ||||
| 
 | ||||
| #include <capnp/generated-header-support.h> | ||||
| #if !CAPNP_LITE | ||||
| #include <capnp/capability.h> | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| #if CAPNP_VERSION != 6001 | ||||
| #error "Version mismatch between generated code and library headers.  You must use the same version of the Cap'n Proto compiler and library." | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| namespace capnp { | ||||
| namespace schemas { | ||||
| 
 | ||||
| CAPNP_DECLARE_SCHEMA(8825ffaa852cda72); | ||||
| CAPNP_DECLARE_SCHEMA(c27855d853a937cc); | ||||
| CAPNP_DECLARE_SCHEMA(9bbf84153dd4bb60); | ||||
| 
 | ||||
| }  // namespace schemas
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| struct JsonValue { | ||||
|   JsonValue() = delete; | ||||
| 
 | ||||
|   class Reader; | ||||
|   class Builder; | ||||
|   class Pipeline; | ||||
|   enum Which: uint16_t { | ||||
|     NULL_, | ||||
|     BOOLEAN, | ||||
|     NUMBER, | ||||
|     STRING, | ||||
|     ARRAY, | ||||
|     OBJECT, | ||||
|     CALL, | ||||
|   }; | ||||
|   struct Field; | ||||
|   struct Call; | ||||
| 
 | ||||
|   struct _capnpPrivate { | ||||
|     CAPNP_DECLARE_STRUCT_HEADER(8825ffaa852cda72, 2, 1) | ||||
|     #if !CAPNP_LITE | ||||
|     static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } | ||||
|     #endif  // !CAPNP_LITE
 | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| struct JsonValue::Field { | ||||
|   Field() = delete; | ||||
| 
 | ||||
|   class Reader; | ||||
|   class Builder; | ||||
|   class Pipeline; | ||||
| 
 | ||||
|   struct _capnpPrivate { | ||||
|     CAPNP_DECLARE_STRUCT_HEADER(c27855d853a937cc, 0, 2) | ||||
|     #if !CAPNP_LITE | ||||
|     static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } | ||||
|     #endif  // !CAPNP_LITE
 | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| struct JsonValue::Call { | ||||
|   Call() = delete; | ||||
| 
 | ||||
|   class Reader; | ||||
|   class Builder; | ||||
|   class Pipeline; | ||||
| 
 | ||||
|   struct _capnpPrivate { | ||||
|     CAPNP_DECLARE_STRUCT_HEADER(9bbf84153dd4bb60, 0, 2) | ||||
|     #if !CAPNP_LITE | ||||
|     static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } | ||||
|     #endif  // !CAPNP_LITE
 | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| class JsonValue::Reader { | ||||
| public: | ||||
|   typedef JsonValue Reads; | ||||
| 
 | ||||
|   Reader() = default; | ||||
|   inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { | ||||
|     return _reader.totalSize().asPublic(); | ||||
|   } | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { | ||||
|     return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); | ||||
|   } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline Which which() const; | ||||
|   inline bool isNull() const; | ||||
|   inline  ::capnp::Void getNull() const; | ||||
| 
 | ||||
|   inline bool isBoolean() const; | ||||
|   inline bool getBoolean() const; | ||||
| 
 | ||||
|   inline bool isNumber() const; | ||||
|   inline double getNumber() const; | ||||
| 
 | ||||
|   inline bool isString() const; | ||||
|   inline bool hasString() const; | ||||
|   inline  ::capnp::Text::Reader getString() const; | ||||
| 
 | ||||
|   inline bool isArray() const; | ||||
|   inline bool hasArray() const; | ||||
|   inline  ::capnp::List< ::capnp::JsonValue>::Reader getArray() const; | ||||
| 
 | ||||
|   inline bool isObject() const; | ||||
|   inline bool hasObject() const; | ||||
|   inline  ::capnp::List< ::capnp::JsonValue::Field>::Reader getObject() const; | ||||
| 
 | ||||
|   inline bool isCall() const; | ||||
|   inline bool hasCall() const; | ||||
|   inline  ::capnp::JsonValue::Call::Reader getCall() const; | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructReader _reader; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::List; | ||||
|   friend class ::capnp::MessageBuilder; | ||||
|   friend class ::capnp::Orphanage; | ||||
| }; | ||||
| 
 | ||||
| class JsonValue::Builder { | ||||
| public: | ||||
|   typedef JsonValue Builds; | ||||
| 
 | ||||
|   Builder() = delete;  // Deleted to discourage incorrect usage.
 | ||||
|                        // You can explicitly initialize to nullptr instead.
 | ||||
|   inline Builder(decltype(nullptr)) {} | ||||
|   inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} | ||||
|   inline operator Reader() const { return Reader(_builder.asReader()); } | ||||
|   inline Reader asReader() const { return *this; } | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { return asReader().toString(); } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline Which which(); | ||||
|   inline bool isNull(); | ||||
|   inline  ::capnp::Void getNull(); | ||||
|   inline void setNull( ::capnp::Void value = ::capnp::VOID); | ||||
| 
 | ||||
|   inline bool isBoolean(); | ||||
|   inline bool getBoolean(); | ||||
|   inline void setBoolean(bool value); | ||||
| 
 | ||||
|   inline bool isNumber(); | ||||
|   inline double getNumber(); | ||||
|   inline void setNumber(double value); | ||||
| 
 | ||||
|   inline bool isString(); | ||||
|   inline bool hasString(); | ||||
|   inline  ::capnp::Text::Builder getString(); | ||||
|   inline void setString( ::capnp::Text::Reader value); | ||||
|   inline  ::capnp::Text::Builder initString(unsigned int size); | ||||
|   inline void adoptString(::capnp::Orphan< ::capnp::Text>&& value); | ||||
|   inline ::capnp::Orphan< ::capnp::Text> disownString(); | ||||
| 
 | ||||
|   inline bool isArray(); | ||||
|   inline bool hasArray(); | ||||
|   inline  ::capnp::List< ::capnp::JsonValue>::Builder getArray(); | ||||
|   inline void setArray( ::capnp::List< ::capnp::JsonValue>::Reader value); | ||||
|   inline  ::capnp::List< ::capnp::JsonValue>::Builder initArray(unsigned int size); | ||||
|   inline void adoptArray(::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>>&& value); | ||||
|   inline ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>> disownArray(); | ||||
| 
 | ||||
|   inline bool isObject(); | ||||
|   inline bool hasObject(); | ||||
|   inline  ::capnp::List< ::capnp::JsonValue::Field>::Builder getObject(); | ||||
|   inline void setObject( ::capnp::List< ::capnp::JsonValue::Field>::Reader value); | ||||
|   inline  ::capnp::List< ::capnp::JsonValue::Field>::Builder initObject(unsigned int size); | ||||
|   inline void adoptObject(::capnp::Orphan< ::capnp::List< ::capnp::JsonValue::Field>>&& value); | ||||
|   inline ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue::Field>> disownObject(); | ||||
| 
 | ||||
|   inline bool isCall(); | ||||
|   inline bool hasCall(); | ||||
|   inline  ::capnp::JsonValue::Call::Builder getCall(); | ||||
|   inline void setCall( ::capnp::JsonValue::Call::Reader value); | ||||
|   inline  ::capnp::JsonValue::Call::Builder initCall(); | ||||
|   inline void adoptCall(::capnp::Orphan< ::capnp::JsonValue::Call>&& value); | ||||
|   inline ::capnp::Orphan< ::capnp::JsonValue::Call> disownCall(); | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructBuilder _builder; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   friend class ::capnp::Orphanage; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
| class JsonValue::Pipeline { | ||||
| public: | ||||
|   typedef JsonValue Pipelines; | ||||
| 
 | ||||
|   inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} | ||||
|   inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) | ||||
|       : _typeless(kj::mv(typeless)) {} | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::AnyPointer::Pipeline _typeless; | ||||
|   friend class ::capnp::PipelineHook; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
| }; | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| class JsonValue::Field::Reader { | ||||
| public: | ||||
|   typedef Field Reads; | ||||
| 
 | ||||
|   Reader() = default; | ||||
|   inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { | ||||
|     return _reader.totalSize().asPublic(); | ||||
|   } | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { | ||||
|     return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); | ||||
|   } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline bool hasName() const; | ||||
|   inline  ::capnp::Text::Reader getName() const; | ||||
| 
 | ||||
|   inline bool hasValue() const; | ||||
|   inline  ::capnp::JsonValue::Reader getValue() const; | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructReader _reader; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::List; | ||||
|   friend class ::capnp::MessageBuilder; | ||||
|   friend class ::capnp::Orphanage; | ||||
| }; | ||||
| 
 | ||||
| class JsonValue::Field::Builder { | ||||
| public: | ||||
|   typedef Field Builds; | ||||
| 
 | ||||
|   Builder() = delete;  // Deleted to discourage incorrect usage.
 | ||||
|                        // You can explicitly initialize to nullptr instead.
 | ||||
|   inline Builder(decltype(nullptr)) {} | ||||
|   inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} | ||||
|   inline operator Reader() const { return Reader(_builder.asReader()); } | ||||
|   inline Reader asReader() const { return *this; } | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { return asReader().toString(); } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline bool hasName(); | ||||
|   inline  ::capnp::Text::Builder getName(); | ||||
|   inline void setName( ::capnp::Text::Reader value); | ||||
|   inline  ::capnp::Text::Builder initName(unsigned int size); | ||||
|   inline void adoptName(::capnp::Orphan< ::capnp::Text>&& value); | ||||
|   inline ::capnp::Orphan< ::capnp::Text> disownName(); | ||||
| 
 | ||||
|   inline bool hasValue(); | ||||
|   inline  ::capnp::JsonValue::Builder getValue(); | ||||
|   inline void setValue( ::capnp::JsonValue::Reader value); | ||||
|   inline  ::capnp::JsonValue::Builder initValue(); | ||||
|   inline void adoptValue(::capnp::Orphan< ::capnp::JsonValue>&& value); | ||||
|   inline ::capnp::Orphan< ::capnp::JsonValue> disownValue(); | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructBuilder _builder; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   friend class ::capnp::Orphanage; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
| class JsonValue::Field::Pipeline { | ||||
| public: | ||||
|   typedef Field Pipelines; | ||||
| 
 | ||||
|   inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} | ||||
|   inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) | ||||
|       : _typeless(kj::mv(typeless)) {} | ||||
| 
 | ||||
|   inline  ::capnp::JsonValue::Pipeline getValue(); | ||||
| private: | ||||
|   ::capnp::AnyPointer::Pipeline _typeless; | ||||
|   friend class ::capnp::PipelineHook; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
| }; | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| class JsonValue::Call::Reader { | ||||
| public: | ||||
|   typedef Call Reads; | ||||
| 
 | ||||
|   Reader() = default; | ||||
|   inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { | ||||
|     return _reader.totalSize().asPublic(); | ||||
|   } | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { | ||||
|     return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); | ||||
|   } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline bool hasFunction() const; | ||||
|   inline  ::capnp::Text::Reader getFunction() const; | ||||
| 
 | ||||
|   inline bool hasParams() const; | ||||
|   inline  ::capnp::List< ::capnp::JsonValue>::Reader getParams() const; | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructReader _reader; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::List; | ||||
|   friend class ::capnp::MessageBuilder; | ||||
|   friend class ::capnp::Orphanage; | ||||
| }; | ||||
| 
 | ||||
| class JsonValue::Call::Builder { | ||||
| public: | ||||
|   typedef Call Builds; | ||||
| 
 | ||||
|   Builder() = delete;  // Deleted to discourage incorrect usage.
 | ||||
|                        // You can explicitly initialize to nullptr instead.
 | ||||
|   inline Builder(decltype(nullptr)) {} | ||||
|   inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} | ||||
|   inline operator Reader() const { return Reader(_builder.asReader()); } | ||||
|   inline Reader asReader() const { return *this; } | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { return asReader().toString(); } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline bool hasFunction(); | ||||
|   inline  ::capnp::Text::Builder getFunction(); | ||||
|   inline void setFunction( ::capnp::Text::Reader value); | ||||
|   inline  ::capnp::Text::Builder initFunction(unsigned int size); | ||||
|   inline void adoptFunction(::capnp::Orphan< ::capnp::Text>&& value); | ||||
|   inline ::capnp::Orphan< ::capnp::Text> disownFunction(); | ||||
| 
 | ||||
|   inline bool hasParams(); | ||||
|   inline  ::capnp::List< ::capnp::JsonValue>::Builder getParams(); | ||||
|   inline void setParams( ::capnp::List< ::capnp::JsonValue>::Reader value); | ||||
|   inline  ::capnp::List< ::capnp::JsonValue>::Builder initParams(unsigned int size); | ||||
|   inline void adoptParams(::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>>&& value); | ||||
|   inline ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>> disownParams(); | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructBuilder _builder; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   friend class ::capnp::Orphanage; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
| class JsonValue::Call::Pipeline { | ||||
| public: | ||||
|   typedef Call Pipelines; | ||||
| 
 | ||||
|   inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} | ||||
|   inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) | ||||
|       : _typeless(kj::mv(typeless)) {} | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::AnyPointer::Pipeline _typeless; | ||||
|   friend class ::capnp::PipelineHook; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
| }; | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| inline  ::capnp::JsonValue::Which JsonValue::Reader::which() const { | ||||
|   return _reader.getDataField<Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| inline  ::capnp::JsonValue::Which JsonValue::Builder::which() { | ||||
|   return _builder.getDataField<Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| inline bool JsonValue::Reader::isNull() const { | ||||
|   return which() == JsonValue::NULL_; | ||||
| } | ||||
| inline bool JsonValue::Builder::isNull() { | ||||
|   return which() == JsonValue::NULL_; | ||||
| } | ||||
| inline  ::capnp::Void JsonValue::Reader::getNull() const { | ||||
|   KJ_IREQUIRE((which() == JsonValue::NULL_), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return _reader.getDataField< ::capnp::Void>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| inline  ::capnp::Void JsonValue::Builder::getNull() { | ||||
|   KJ_IREQUIRE((which() == JsonValue::NULL_), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return _builder.getDataField< ::capnp::Void>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| inline void JsonValue::Builder::setNull( ::capnp::Void value) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::NULL_); | ||||
|   _builder.setDataField< ::capnp::Void>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); | ||||
| } | ||||
| 
 | ||||
| inline bool JsonValue::Reader::isBoolean() const { | ||||
|   return which() == JsonValue::BOOLEAN; | ||||
| } | ||||
| inline bool JsonValue::Builder::isBoolean() { | ||||
|   return which() == JsonValue::BOOLEAN; | ||||
| } | ||||
| inline bool JsonValue::Reader::getBoolean() const { | ||||
|   KJ_IREQUIRE((which() == JsonValue::BOOLEAN), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return _reader.getDataField<bool>( | ||||
|       ::capnp::bounded<16>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| inline bool JsonValue::Builder::getBoolean() { | ||||
|   KJ_IREQUIRE((which() == JsonValue::BOOLEAN), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return _builder.getDataField<bool>( | ||||
|       ::capnp::bounded<16>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| inline void JsonValue::Builder::setBoolean(bool value) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::BOOLEAN); | ||||
|   _builder.setDataField<bool>( | ||||
|       ::capnp::bounded<16>() * ::capnp::ELEMENTS, value); | ||||
| } | ||||
| 
 | ||||
| inline bool JsonValue::Reader::isNumber() const { | ||||
|   return which() == JsonValue::NUMBER; | ||||
| } | ||||
| inline bool JsonValue::Builder::isNumber() { | ||||
|   return which() == JsonValue::NUMBER; | ||||
| } | ||||
| inline double JsonValue::Reader::getNumber() const { | ||||
|   KJ_IREQUIRE((which() == JsonValue::NUMBER), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return _reader.getDataField<double>( | ||||
|       ::capnp::bounded<1>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| inline double JsonValue::Builder::getNumber() { | ||||
|   KJ_IREQUIRE((which() == JsonValue::NUMBER), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return _builder.getDataField<double>( | ||||
|       ::capnp::bounded<1>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| inline void JsonValue::Builder::setNumber(double value) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::NUMBER); | ||||
|   _builder.setDataField<double>( | ||||
|       ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); | ||||
| } | ||||
| 
 | ||||
| inline bool JsonValue::Reader::isString() const { | ||||
|   return which() == JsonValue::STRING; | ||||
| } | ||||
| inline bool JsonValue::Builder::isString() { | ||||
|   return which() == JsonValue::STRING; | ||||
| } | ||||
| inline bool JsonValue::Reader::hasString() const { | ||||
|   if (which() != JsonValue::STRING) return false; | ||||
|   return !_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline bool JsonValue::Builder::hasString() { | ||||
|   if (which() != JsonValue::STRING) return false; | ||||
|   return !_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline  ::capnp::Text::Reader JsonValue::Reader::getString() const { | ||||
|   KJ_IREQUIRE((which() == JsonValue::STRING), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline  ::capnp::Text::Builder JsonValue::Builder::getString() { | ||||
|   KJ_IREQUIRE((which() == JsonValue::STRING), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline void JsonValue::Builder::setString( ::capnp::Text::Reader value) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::STRING); | ||||
|   ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), value); | ||||
| } | ||||
| inline  ::capnp::Text::Builder JsonValue::Builder::initString(unsigned int size) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::STRING); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), size); | ||||
| } | ||||
| inline void JsonValue::Builder::adoptString( | ||||
|     ::capnp::Orphan< ::capnp::Text>&& value) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::STRING); | ||||
|   ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); | ||||
| } | ||||
| inline ::capnp::Orphan< ::capnp::Text> JsonValue::Builder::disownString() { | ||||
|   KJ_IREQUIRE((which() == JsonValue::STRING), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| 
 | ||||
| inline bool JsonValue::Reader::isArray() const { | ||||
|   return which() == JsonValue::ARRAY; | ||||
| } | ||||
| inline bool JsonValue::Builder::isArray() { | ||||
|   return which() == JsonValue::ARRAY; | ||||
| } | ||||
| inline bool JsonValue::Reader::hasArray() const { | ||||
|   if (which() != JsonValue::ARRAY) return false; | ||||
|   return !_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline bool JsonValue::Builder::hasArray() { | ||||
|   if (which() != JsonValue::ARRAY) return false; | ||||
|   return !_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline  ::capnp::List< ::capnp::JsonValue>::Reader JsonValue::Reader::getArray() const { | ||||
|   KJ_IREQUIRE((which() == JsonValue::ARRAY), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::get(_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline  ::capnp::List< ::capnp::JsonValue>::Builder JsonValue::Builder::getArray() { | ||||
|   KJ_IREQUIRE((which() == JsonValue::ARRAY), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::get(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline void JsonValue::Builder::setArray( ::capnp::List< ::capnp::JsonValue>::Reader value) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::ARRAY); | ||||
|   ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::set(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), value); | ||||
| } | ||||
| inline  ::capnp::List< ::capnp::JsonValue>::Builder JsonValue::Builder::initArray(unsigned int size) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::ARRAY); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::init(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), size); | ||||
| } | ||||
| inline void JsonValue::Builder::adoptArray( | ||||
|     ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>>&& value) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::ARRAY); | ||||
|   ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::adopt(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); | ||||
| } | ||||
| inline ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>> JsonValue::Builder::disownArray() { | ||||
|   KJ_IREQUIRE((which() == JsonValue::ARRAY), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::disown(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| 
 | ||||
| inline bool JsonValue::Reader::isObject() const { | ||||
|   return which() == JsonValue::OBJECT; | ||||
| } | ||||
| inline bool JsonValue::Builder::isObject() { | ||||
|   return which() == JsonValue::OBJECT; | ||||
| } | ||||
| inline bool JsonValue::Reader::hasObject() const { | ||||
|   if (which() != JsonValue::OBJECT) return false; | ||||
|   return !_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline bool JsonValue::Builder::hasObject() { | ||||
|   if (which() != JsonValue::OBJECT) return false; | ||||
|   return !_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline  ::capnp::List< ::capnp::JsonValue::Field>::Reader JsonValue::Reader::getObject() const { | ||||
|   KJ_IREQUIRE((which() == JsonValue::OBJECT), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue::Field>>::get(_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline  ::capnp::List< ::capnp::JsonValue::Field>::Builder JsonValue::Builder::getObject() { | ||||
|   KJ_IREQUIRE((which() == JsonValue::OBJECT), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue::Field>>::get(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline void JsonValue::Builder::setObject( ::capnp::List< ::capnp::JsonValue::Field>::Reader value) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::OBJECT); | ||||
|   ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue::Field>>::set(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), value); | ||||
| } | ||||
| inline  ::capnp::List< ::capnp::JsonValue::Field>::Builder JsonValue::Builder::initObject(unsigned int size) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::OBJECT); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue::Field>>::init(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), size); | ||||
| } | ||||
| inline void JsonValue::Builder::adoptObject( | ||||
|     ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue::Field>>&& value) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::OBJECT); | ||||
|   ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue::Field>>::adopt(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); | ||||
| } | ||||
| inline ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue::Field>> JsonValue::Builder::disownObject() { | ||||
|   KJ_IREQUIRE((which() == JsonValue::OBJECT), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue::Field>>::disown(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| 
 | ||||
| inline bool JsonValue::Reader::isCall() const { | ||||
|   return which() == JsonValue::CALL; | ||||
| } | ||||
| inline bool JsonValue::Builder::isCall() { | ||||
|   return which() == JsonValue::CALL; | ||||
| } | ||||
| inline bool JsonValue::Reader::hasCall() const { | ||||
|   if (which() != JsonValue::CALL) return false; | ||||
|   return !_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline bool JsonValue::Builder::hasCall() { | ||||
|   if (which() != JsonValue::CALL) return false; | ||||
|   return !_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline  ::capnp::JsonValue::Call::Reader JsonValue::Reader::getCall() const { | ||||
|   KJ_IREQUIRE((which() == JsonValue::CALL), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::JsonValue::Call>::get(_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline  ::capnp::JsonValue::Call::Builder JsonValue::Builder::getCall() { | ||||
|   KJ_IREQUIRE((which() == JsonValue::CALL), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::JsonValue::Call>::get(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline void JsonValue::Builder::setCall( ::capnp::JsonValue::Call::Reader value) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::CALL); | ||||
|   ::capnp::_::PointerHelpers< ::capnp::JsonValue::Call>::set(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), value); | ||||
| } | ||||
| inline  ::capnp::JsonValue::Call::Builder JsonValue::Builder::initCall() { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::CALL); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::JsonValue::Call>::init(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline void JsonValue::Builder::adoptCall( | ||||
|     ::capnp::Orphan< ::capnp::JsonValue::Call>&& value) { | ||||
|   _builder.setDataField<JsonValue::Which>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::CALL); | ||||
|   ::capnp::_::PointerHelpers< ::capnp::JsonValue::Call>::adopt(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); | ||||
| } | ||||
| inline ::capnp::Orphan< ::capnp::JsonValue::Call> JsonValue::Builder::disownCall() { | ||||
|   KJ_IREQUIRE((which() == JsonValue::CALL), | ||||
|               "Must check which() before get()ing a union member."); | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::JsonValue::Call>::disown(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| 
 | ||||
| inline bool JsonValue::Field::Reader::hasName() const { | ||||
|   return !_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline bool JsonValue::Field::Builder::hasName() { | ||||
|   return !_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline  ::capnp::Text::Reader JsonValue::Field::Reader::getName() const { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline  ::capnp::Text::Builder JsonValue::Field::Builder::getName() { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline void JsonValue::Field::Builder::setName( ::capnp::Text::Reader value) { | ||||
|   ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), value); | ||||
| } | ||||
| inline  ::capnp::Text::Builder JsonValue::Field::Builder::initName(unsigned int size) { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), size); | ||||
| } | ||||
| inline void JsonValue::Field::Builder::adoptName( | ||||
|     ::capnp::Orphan< ::capnp::Text>&& value) { | ||||
|   ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); | ||||
| } | ||||
| inline ::capnp::Orphan< ::capnp::Text> JsonValue::Field::Builder::disownName() { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| 
 | ||||
| inline bool JsonValue::Field::Reader::hasValue() const { | ||||
|   return !_reader.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline bool JsonValue::Field::Builder::hasValue() { | ||||
|   return !_builder.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline  ::capnp::JsonValue::Reader JsonValue::Field::Reader::getValue() const { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::JsonValue>::get(_reader.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline  ::capnp::JsonValue::Builder JsonValue::Field::Builder::getValue() { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::JsonValue>::get(_builder.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS)); | ||||
| } | ||||
| #if !CAPNP_LITE | ||||
| inline  ::capnp::JsonValue::Pipeline JsonValue::Field::Pipeline::getValue() { | ||||
|   return  ::capnp::JsonValue::Pipeline(_typeless.getPointerField(1)); | ||||
| } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| inline void JsonValue::Field::Builder::setValue( ::capnp::JsonValue::Reader value) { | ||||
|   ::capnp::_::PointerHelpers< ::capnp::JsonValue>::set(_builder.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS), value); | ||||
| } | ||||
| inline  ::capnp::JsonValue::Builder JsonValue::Field::Builder::initValue() { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::JsonValue>::init(_builder.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline void JsonValue::Field::Builder::adoptValue( | ||||
|     ::capnp::Orphan< ::capnp::JsonValue>&& value) { | ||||
|   ::capnp::_::PointerHelpers< ::capnp::JsonValue>::adopt(_builder.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); | ||||
| } | ||||
| inline ::capnp::Orphan< ::capnp::JsonValue> JsonValue::Field::Builder::disownValue() { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::JsonValue>::disown(_builder.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS)); | ||||
| } | ||||
| 
 | ||||
| inline bool JsonValue::Call::Reader::hasFunction() const { | ||||
|   return !_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline bool JsonValue::Call::Builder::hasFunction() { | ||||
|   return !_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline  ::capnp::Text::Reader JsonValue::Call::Reader::getFunction() const { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline  ::capnp::Text::Builder JsonValue::Call::Builder::getFunction() { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline void JsonValue::Call::Builder::setFunction( ::capnp::Text::Reader value) { | ||||
|   ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), value); | ||||
| } | ||||
| inline  ::capnp::Text::Builder JsonValue::Call::Builder::initFunction(unsigned int size) { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), size); | ||||
| } | ||||
| inline void JsonValue::Call::Builder::adoptFunction( | ||||
|     ::capnp::Orphan< ::capnp::Text>&& value) { | ||||
|   ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); | ||||
| } | ||||
| inline ::capnp::Orphan< ::capnp::Text> JsonValue::Call::Builder::disownFunction() { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| 
 | ||||
| inline bool JsonValue::Call::Reader::hasParams() const { | ||||
|   return !_reader.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline bool JsonValue::Call::Builder::hasParams() { | ||||
|   return !_builder.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline  ::capnp::List< ::capnp::JsonValue>::Reader JsonValue::Call::Reader::getParams() const { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::get(_reader.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline  ::capnp::List< ::capnp::JsonValue>::Builder JsonValue::Call::Builder::getParams() { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::get(_builder.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline void JsonValue::Call::Builder::setParams( ::capnp::List< ::capnp::JsonValue>::Reader value) { | ||||
|   ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::set(_builder.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS), value); | ||||
| } | ||||
| inline  ::capnp::List< ::capnp::JsonValue>::Builder JsonValue::Call::Builder::initParams(unsigned int size) { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::init(_builder.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS), size); | ||||
| } | ||||
| inline void JsonValue::Call::Builder::adoptParams( | ||||
|     ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>>&& value) { | ||||
|   ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::adopt(_builder.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); | ||||
| } | ||||
| inline ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>> JsonValue::Call::Builder::disownParams() { | ||||
|   return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::disown(_builder.getPointerField( | ||||
|       ::capnp::bounded<1>() * ::capnp::POINTERS)); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| #endif  // CAPNP_INCLUDED_8ef99297a43a5e34_
 | ||||
| @ -0,0 +1,462 @@ | ||||
| // Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_COMPAT_JSON_H_ | ||||
| #define CAPNP_COMPAT_JSON_H_ | ||||
| 
 | ||||
| #include <capnp/schema.h> | ||||
| #include <capnp/dynamic.h> | ||||
| #include <capnp/compat/json.capnp.h> | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| class JsonCodec { | ||||
|   // Flexible class for encoding Cap'n Proto types as JSON, and decoding JSON back to Cap'n Proto.
 | ||||
|   //
 | ||||
|   // Typical usage:
 | ||||
|   //
 | ||||
|   //     JsonCodec json;
 | ||||
|   //
 | ||||
|   //     // encode
 | ||||
|   //     kj::String encoded = json.encode(someStructReader);
 | ||||
|   //
 | ||||
|   //     // decode
 | ||||
|   //     json.decode(encoded, someStructBuilder);
 | ||||
|   //
 | ||||
|   // Advanced users can do fancy things like override the way certain types or fields are
 | ||||
|   // represented in JSON by registering handlers. See the unit test for an example.
 | ||||
|   //
 | ||||
|   // Notes:
 | ||||
|   // - When encoding, all primitive fields are always encoded, even if default-valued. Pointer
 | ||||
|   //   fields are only encoded if they are non-null.
 | ||||
|   // - 64-bit integers are encoded as strings, since JSON "numbers" are double-precision floating
 | ||||
|   //   points which cannot store a 64-bit integer without losing data.
 | ||||
|   // - NaNs and infinite floating point numbers are not allowed by the JSON spec, and so are encoded
 | ||||
|   //   as null. This matches the behavior of `JSON.stringify` in at least Firefox and Chrome.
 | ||||
|   // - Data is encoded as an array of numbers in the range [0,255]. You probably want to register
 | ||||
|   //   a handler that does something better, like maybe base64 encoding, but there are a zillion
 | ||||
|   //   different ways people do this.
 | ||||
|   // - Encoding/decoding capabilities and AnyPointers requires registering a Handler, since there's
 | ||||
|   //   no obvious default behavior.
 | ||||
|   // - When decoding, unrecognized field names are ignored. Note: This means that JSON is NOT a
 | ||||
|   //   good format for receiving input from a human. Consider `capnp eval` or the SchemaParser
 | ||||
|   //   library for human input.
 | ||||
| 
 | ||||
| public: | ||||
|   JsonCodec(); | ||||
|   ~JsonCodec() noexcept(false); | ||||
| 
 | ||||
|   // ---------------------------------------------------------------------------
 | ||||
|   // standard API
 | ||||
| 
 | ||||
|   void setPrettyPrint(bool enabled); | ||||
|   // Enable to insert newlines, indentation, and other extra spacing into the output. The default
 | ||||
|   // is to use minimal whitespace.
 | ||||
| 
 | ||||
|   void setMaxNestingDepth(size_t maxNestingDepth); | ||||
|   // Set maximum nesting depth when decoding JSON to prevent highly nested input from overflowing
 | ||||
|   // the call stack. The default is 64.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   kj::String encode(T&& value); | ||||
|   // Encode any Cap'n Proto value to JSON, including primitives and
 | ||||
|   // Dynamic{Enum,Struct,List,Capability}, but not DynamicValue (see below).
 | ||||
| 
 | ||||
|   kj::String encode(DynamicValue::Reader value, Type type) const; | ||||
|   // Encode a DynamicValue to JSON. `type` is needed because `DynamicValue` itself does
 | ||||
|   // not distinguish between e.g. int32 and int64, which in JSON are handled differently. Most
 | ||||
|   // of the time, though, you can use the single-argument templated version of `encode()` instead.
 | ||||
| 
 | ||||
|   void decode(kj::ArrayPtr<const char> input, DynamicStruct::Builder output) const; | ||||
|   // Decode JSON text directly into a struct builder. This only works for structs since lists
 | ||||
|   // need to be allocated with the correct size in advance.
 | ||||
|   //
 | ||||
|   // (Remember that any Cap'n Proto struct reader type can be implicitly cast to
 | ||||
|   // DynamicStruct::Reader.)
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   Orphan<T> decode(kj::ArrayPtr<const char> input, Orphanage orphanage) const; | ||||
|   // Decode JSON text to any Cap'n Proto object (pointer value), allocated using the given
 | ||||
|   // orphanage. T must be specified explicitly and cannot be dynamic, e.g.:
 | ||||
|   //
 | ||||
|   //     Orphan<MyType> orphan = json.decode<MyType>(text, orphanage);
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   ReaderFor<T> decode(kj::ArrayPtr<const char> input) const; | ||||
|   // Decode JSON text into a primitive or capability value. T must be specified explicitly and
 | ||||
|   // cannot be dynamic, e.g.:
 | ||||
|   //
 | ||||
|   //     uint32_t n = json.decode<uint32_t>(text);
 | ||||
| 
 | ||||
|   Orphan<DynamicValue> decode(kj::ArrayPtr<const char> input, Type type, Orphanage orphanage) const; | ||||
|   Orphan<DynamicList> decode( | ||||
|       kj::ArrayPtr<const char> input, ListSchema type, Orphanage orphanage) const; | ||||
|   Orphan<DynamicStruct> decode( | ||||
|       kj::ArrayPtr<const char> input, StructSchema type, Orphanage orphanage) const; | ||||
|   DynamicCapability::Client decode(kj::ArrayPtr<const char> input, InterfaceSchema type) const; | ||||
|   DynamicEnum decode(kj::ArrayPtr<const char> input, EnumSchema type) const; | ||||
|   // Decode to a dynamic value, specifying the type schema.
 | ||||
| 
 | ||||
|   // ---------------------------------------------------------------------------
 | ||||
|   // layered API
 | ||||
|   //
 | ||||
|   // You can separate text <-> JsonValue from JsonValue <-> T. These are particularly useful
 | ||||
|   // for calling from Handler implementations.
 | ||||
| 
 | ||||
|   kj::String encodeRaw(JsonValue::Reader value) const; | ||||
|   void decodeRaw(kj::ArrayPtr<const char> input, JsonValue::Builder output) const; | ||||
|   // Translate JsonValue <-> text.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   void encode(T&& value, JsonValue::Builder output); | ||||
|   void encode(DynamicValue::Reader input, Type type, JsonValue::Builder output) const; | ||||
|   void decode(JsonValue::Reader input, DynamicStruct::Builder output) const; | ||||
|   template <typename T> | ||||
|   Orphan<T> decode(JsonValue::Reader input, Orphanage orphanage) const; | ||||
|   template <typename T> | ||||
|   ReaderFor<T> decode(JsonValue::Reader input) const; | ||||
| 
 | ||||
|   Orphan<DynamicValue> decode(JsonValue::Reader input, Type type, Orphanage orphanage) const; | ||||
|   Orphan<DynamicList> decode(JsonValue::Reader input, ListSchema type, Orphanage orphanage) const; | ||||
|   Orphan<DynamicStruct> decode( | ||||
|       JsonValue::Reader input, StructSchema type, Orphanage orphanage) const; | ||||
|   DynamicCapability::Client decode(JsonValue::Reader input, InterfaceSchema type) const; | ||||
|   DynamicEnum decode(JsonValue::Reader input, EnumSchema type) const; | ||||
| 
 | ||||
|   // ---------------------------------------------------------------------------
 | ||||
|   // specializing particular types
 | ||||
| 
 | ||||
|   template <typename T, Style s = style<T>()> | ||||
|   class Handler; | ||||
|   // Implement this interface to specify a special encoding for a particular type or field.
 | ||||
|   //
 | ||||
|   // The templates are a bit ugly, but subclasses of this type essentially implement two methods,
 | ||||
|   // one to encode values of this type and one to decode values of this type. `encode()` is simple:
 | ||||
|   //
 | ||||
|   //   void encode(const JsonCodec& codec, ReaderFor<T> input, JsonValue::Builder output) const;
 | ||||
|   //
 | ||||
|   // `decode()` is a bit trickier. When T is a struct (including DynamicStruct), it is:
 | ||||
|   //
 | ||||
|   //   void decode(const JsonCodec& codec, JsonValue::Reader input, BuilderFor<T> output) const;
 | ||||
|   //
 | ||||
|   // However, when T is a primitive, decode() is:
 | ||||
|   //
 | ||||
|   //   T decode(const JsonCodec& codec, JsonValue::Reader input) const;
 | ||||
|   //
 | ||||
|   // Or when T is any non-struct object (list, blob), decode() is:
 | ||||
|   //
 | ||||
|   //   Orphan<T> decode(const JsonCodec& codec, JsonValue::Reader input, Orphanage orphanage) const;
 | ||||
|   //
 | ||||
|   // Or when T is an interface:
 | ||||
|   //
 | ||||
|   //   T::Client decode(const JsonCodec& codec, JsonValue::Reader input) const;
 | ||||
|   //
 | ||||
|   // Additionally, when T is a struct you can *optionally* also implement the orphan-returning form
 | ||||
|   // of decode(), but it will only be called when the struct would be allocated as an individual
 | ||||
|   // object, not as part of a list. This allows you to return "nullptr" in these cases to say that
 | ||||
|   // the pointer value should be null. This does not apply to list elements because struct list
 | ||||
|   // elements cannot ever be null (since Cap'n Proto encodes struct lists as a flat list rather
 | ||||
|   // than list-of-pointers).
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   void addTypeHandler(Handler<T>& handler); | ||||
|   void addTypeHandler(Type type, Handler<DynamicValue>& handler); | ||||
|   void addTypeHandler(EnumSchema type, Handler<DynamicEnum>& handler); | ||||
|   void addTypeHandler(StructSchema type, Handler<DynamicStruct>& handler); | ||||
|   void addTypeHandler(ListSchema type, Handler<DynamicList>& handler); | ||||
|   void addTypeHandler(InterfaceSchema type, Handler<DynamicCapability>& handler); | ||||
|   // Arrange that whenever the type T appears in the message, your handler will be used to
 | ||||
|   // encode/decode it.
 | ||||
|   //
 | ||||
|   // Note that if you register a handler for a capability type, it will also apply to subtypes.
 | ||||
|   // Thus Handler<Capability> handles all capabilities.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   void addFieldHandler(StructSchema::Field field, Handler<T>& handler); | ||||
|   // Matches only the specific field. T can be a dynamic type. T must match the field's type.
 | ||||
| 
 | ||||
| private: | ||||
|   class HandlerBase; | ||||
|   struct Impl; | ||||
| 
 | ||||
|   kj::Own<Impl> impl; | ||||
| 
 | ||||
|   void encodeField(StructSchema::Field field, DynamicValue::Reader input, | ||||
|                    JsonValue::Builder output) const; | ||||
|   void decodeArray(List<JsonValue>::Reader input, DynamicList::Builder output) const; | ||||
|   void decodeObject(List<JsonValue::Field>::Reader input, DynamicStruct::Builder output) const; | ||||
|   void addTypeHandlerImpl(Type type, HandlerBase& handler); | ||||
|   void addFieldHandlerImpl(StructSchema::Field field, Type type, HandlerBase& handler); | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // inline implementation details
 | ||||
| 
 | ||||
| template <typename T> | ||||
| kj::String JsonCodec::encode(T&& value) { | ||||
|   typedef FromAny<kj::Decay<T>> Base; | ||||
|   return encode(DynamicValue::Reader(ReaderFor<Base>(kj::fwd<T>(value))), Type::from<Base>()); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline Orphan<T> JsonCodec::decode(kj::ArrayPtr<const char> input, Orphanage orphanage) const { | ||||
|   return decode(input, Type::from<T>(), orphanage).template releaseAs<T>(); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline ReaderFor<T> JsonCodec::decode(kj::ArrayPtr<const char> input) const { | ||||
|   static_assert(style<T>() == Style::PRIMITIVE || style<T>() == Style::CAPABILITY, | ||||
|                 "must specify an orphanage to decode an object type"); | ||||
|   return decode(input, Type::from<T>(), Orphanage()).getReader().template as<T>(); | ||||
| } | ||||
| 
 | ||||
| inline Orphan<DynamicList> JsonCodec::decode( | ||||
|     kj::ArrayPtr<const char> input, ListSchema type, Orphanage orphanage) const { | ||||
|   return decode(input, Type(type), orphanage).releaseAs<DynamicList>(); | ||||
| } | ||||
| inline Orphan<DynamicStruct> JsonCodec::decode( | ||||
|     kj::ArrayPtr<const char> input, StructSchema type, Orphanage orphanage) const { | ||||
|   return decode(input, Type(type), orphanage).releaseAs<DynamicStruct>(); | ||||
| } | ||||
| inline DynamicCapability::Client JsonCodec::decode( | ||||
|     kj::ArrayPtr<const char> input, InterfaceSchema type) const { | ||||
|   return decode(input, Type(type), Orphanage()).getReader().as<DynamicCapability>(); | ||||
| } | ||||
| inline DynamicEnum JsonCodec::decode(kj::ArrayPtr<const char> input, EnumSchema type) const { | ||||
|   return decode(input, Type(type), Orphanage()).getReader().as<DynamicEnum>(); | ||||
| } | ||||
| 
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| template <typename T> | ||||
| void JsonCodec::encode(T&& value, JsonValue::Builder output) { | ||||
|   typedef FromAny<kj::Decay<T>> Base; | ||||
|   encode(DynamicValue::Reader(ReaderFor<Base>(kj::fwd<T>(value))), Type::from<Base>(), output); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline Orphan<T> JsonCodec::decode(JsonValue::Reader input, Orphanage orphanage) const { | ||||
|   return decode(input, Type::from<T>(), orphanage).template releaseAs<T>(); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline ReaderFor<T> JsonCodec::decode(JsonValue::Reader input) const { | ||||
|   static_assert(style<T>() == Style::PRIMITIVE || style<T>() == Style::CAPABILITY, | ||||
|                 "must specify an orphanage to decode an object type"); | ||||
|   return decode(input, Type::from<T>(), Orphanage()).getReader().template as<T>(); | ||||
| } | ||||
| 
 | ||||
| inline Orphan<DynamicList> JsonCodec::decode( | ||||
|     JsonValue::Reader input, ListSchema type, Orphanage orphanage) const { | ||||
|   return decode(input, Type(type), orphanage).releaseAs<DynamicList>(); | ||||
| } | ||||
| inline Orphan<DynamicStruct> JsonCodec::decode( | ||||
|     JsonValue::Reader input, StructSchema type, Orphanage orphanage) const { | ||||
|   return decode(input, Type(type), orphanage).releaseAs<DynamicStruct>(); | ||||
| } | ||||
| inline DynamicCapability::Client JsonCodec::decode( | ||||
|     JsonValue::Reader input, InterfaceSchema type) const { | ||||
|   return decode(input, Type(type), Orphanage()).getReader().as<DynamicCapability>(); | ||||
| } | ||||
| inline DynamicEnum JsonCodec::decode(JsonValue::Reader input, EnumSchema type) const { | ||||
|   return decode(input, Type(type), Orphanage()).getReader().as<DynamicEnum>(); | ||||
| } | ||||
| 
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| class JsonCodec::HandlerBase { | ||||
|   // Internal helper; ignore.
 | ||||
| public: | ||||
|   virtual void encodeBase(const JsonCodec& codec, DynamicValue::Reader input, | ||||
|                           JsonValue::Builder output) const = 0; | ||||
|   virtual Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                                           Type type, Orphanage orphanage) const; | ||||
|   virtual void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                                 DynamicStruct::Builder output) const; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class JsonCodec::Handler<T, Style::POINTER>: private JsonCodec::HandlerBase { | ||||
| public: | ||||
|   virtual void encode(const JsonCodec& codec, ReaderFor<T> input, | ||||
|                       JsonValue::Builder output) const = 0; | ||||
|   virtual Orphan<T> decode(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                            Orphanage orphanage) const = 0; | ||||
| 
 | ||||
| private: | ||||
|   void encodeBase(const JsonCodec& codec, DynamicValue::Reader input, | ||||
|                   JsonValue::Builder output) const override final { | ||||
|     encode(codec, input.as<T>(), output); | ||||
|   } | ||||
|   Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                                   Type type, Orphanage orphanage) const override final { | ||||
|     return decode(codec, input, orphanage); | ||||
|   } | ||||
|   friend class JsonCodec; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class JsonCodec::Handler<T, Style::STRUCT>: private JsonCodec::HandlerBase { | ||||
| public: | ||||
|   virtual void encode(const JsonCodec& codec, ReaderFor<T> input, | ||||
|                       JsonValue::Builder output) const = 0; | ||||
|   virtual void decode(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                       BuilderFor<T> output) const = 0; | ||||
|   virtual Orphan<T> decode(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                            Orphanage orphanage) const { | ||||
|     // If subclass does not override, fall back to regular version.
 | ||||
|     auto result = orphanage.newOrphan<T>(); | ||||
|     decode(codec, input, result.get()); | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   void encodeBase(const JsonCodec& codec, DynamicValue::Reader input, | ||||
|                   JsonValue::Builder output) const override final { | ||||
|     encode(codec, input.as<T>(), output); | ||||
|   } | ||||
|   Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                                   Type type, Orphanage orphanage) const override final { | ||||
|     return decode(codec, input, orphanage); | ||||
|   } | ||||
|   void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                         DynamicStruct::Builder output) const override final { | ||||
|     decode(codec, input, output.as<T>()); | ||||
|   } | ||||
|   friend class JsonCodec; | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| class JsonCodec::Handler<DynamicStruct>: private JsonCodec::HandlerBase { | ||||
|   // Almost identical to Style::STRUCT except that we pass the struct type to decode().
 | ||||
| 
 | ||||
| public: | ||||
|   virtual void encode(const JsonCodec& codec, DynamicStruct::Reader input, | ||||
|                       JsonValue::Builder output) const = 0; | ||||
|   virtual void decode(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                       DynamicStruct::Builder output) const = 0; | ||||
|   virtual Orphan<DynamicStruct> decode(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                                        StructSchema type, Orphanage orphanage) const { | ||||
|     // If subclass does not override, fall back to regular version.
 | ||||
|     auto result = orphanage.newOrphan(type); | ||||
|     decode(codec, input, result.get()); | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   void encodeBase(const JsonCodec& codec, DynamicValue::Reader input, | ||||
|                   JsonValue::Builder output) const override final { | ||||
|     encode(codec, input.as<DynamicStruct>(), output); | ||||
|   } | ||||
|   Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                                   Type type, Orphanage orphanage) const override final { | ||||
|     return decode(codec, input, type.asStruct(), orphanage); | ||||
|   } | ||||
|   void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                         DynamicStruct::Builder output) const override final { | ||||
|     decode(codec, input, output.as<DynamicStruct>()); | ||||
|   } | ||||
|   friend class JsonCodec; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class JsonCodec::Handler<T, Style::PRIMITIVE>: private JsonCodec::HandlerBase { | ||||
| public: | ||||
|   virtual void encode(const JsonCodec& codec, T input, JsonValue::Builder output) const = 0; | ||||
|   virtual T decode(const JsonCodec& codec, JsonValue::Reader input) const = 0; | ||||
| 
 | ||||
| private: | ||||
|   void encodeBase(const JsonCodec& codec, DynamicValue::Reader input, | ||||
|                   JsonValue::Builder output) const override final { | ||||
|     encode(codec, input.as<T>(), output); | ||||
|   } | ||||
|   Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                                   Type type, Orphanage orphanage) const override final { | ||||
|     return decode(codec, input); | ||||
|   } | ||||
|   friend class JsonCodec; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class JsonCodec::Handler<T, Style::CAPABILITY>: private JsonCodec::HandlerBase { | ||||
| public: | ||||
|   virtual void encode(const JsonCodec& codec, typename T::Client input, | ||||
|                       JsonValue::Builder output) const = 0; | ||||
|   virtual typename T::Client decode(const JsonCodec& codec, JsonValue::Reader input) const = 0; | ||||
| 
 | ||||
| private: | ||||
|   void encodeBase(const JsonCodec& codec, DynamicValue::Reader input, | ||||
|                   JsonValue::Builder output) const override final { | ||||
|     encode(codec, input.as<T>(), output); | ||||
|   } | ||||
|   Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input, | ||||
|                                   Type type, Orphanage orphanage) const override final { | ||||
|     return orphanage.newOrphanCopy(decode(codec, input)); | ||||
|   } | ||||
|   friend class JsonCodec; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| inline void JsonCodec::addTypeHandler(Handler<T>& handler) { | ||||
|   addTypeHandlerImpl(Type::from<T>(), handler); | ||||
| } | ||||
| inline void JsonCodec::addTypeHandler(Type type, Handler<DynamicValue>& handler) { | ||||
|   addTypeHandlerImpl(type, handler); | ||||
| } | ||||
| inline void JsonCodec::addTypeHandler(EnumSchema type, Handler<DynamicEnum>& handler) { | ||||
|   addTypeHandlerImpl(type, handler); | ||||
| } | ||||
| inline void JsonCodec::addTypeHandler(StructSchema type, Handler<DynamicStruct>& handler) { | ||||
|   addTypeHandlerImpl(type, handler); | ||||
| } | ||||
| inline void JsonCodec::addTypeHandler(ListSchema type, Handler<DynamicList>& handler) { | ||||
|   addTypeHandlerImpl(type, handler); | ||||
| } | ||||
| inline void JsonCodec::addTypeHandler(InterfaceSchema type, Handler<DynamicCapability>& handler) { | ||||
|   addTypeHandlerImpl(type, handler); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline void JsonCodec::addFieldHandler(StructSchema::Field field, Handler<T>& handler) { | ||||
|   addFieldHandlerImpl(field, Type::from<T>(), handler); | ||||
| } | ||||
| 
 | ||||
| template <> void JsonCodec::addTypeHandler(Handler<DynamicValue>& handler) | ||||
|     KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; " | ||||
|                    "try specifying a specific type schema as the first parameter"); | ||||
| template <> void JsonCodec::addTypeHandler(Handler<DynamicEnum>& handler) | ||||
|     KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; " | ||||
|                    "try specifying a specific type schema as the first parameter"); | ||||
| template <> void JsonCodec::addTypeHandler(Handler<DynamicStruct>& handler) | ||||
|     KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; " | ||||
|                    "try specifying a specific type schema as the first parameter"); | ||||
| template <> void JsonCodec::addTypeHandler(Handler<DynamicList>& handler) | ||||
|     KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; " | ||||
|                    "try specifying a specific type schema as the first parameter"); | ||||
| template <> void JsonCodec::addTypeHandler(Handler<DynamicCapability>& handler) | ||||
|     KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; " | ||||
|                    "try specifying a specific type schema as the first parameter"); | ||||
| // TODO(someday): Implement support for registering handlers that cover thinsg like "all structs"
 | ||||
| //   or "all lists". Currently you can only target a specific struct or list type.
 | ||||
| 
 | ||||
| } // namespace capnp
 | ||||
| 
 | ||||
| #endif // CAPNP_COMPAT_JSON_H_
 | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -0,0 +1,309 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_ENDIAN_H_ | ||||
| #define CAPNP_ENDIAN_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "common.h" | ||||
| #include <inttypes.h> | ||||
| #include <string.h>  // memcpy | ||||
| 
 | ||||
| namespace capnp { | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| // WireValue
 | ||||
| //
 | ||||
| // Wraps a primitive value as it appears on the wire.  Namely, values are little-endian on the
 | ||||
| // wire, because little-endian is the most common endianness in modern CPUs.
 | ||||
| //
 | ||||
| // Note:  In general, code that depends cares about byte ordering is bad.  See:
 | ||||
| //     http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
 | ||||
| //   Cap'n Proto is special because it is essentially doing compiler-like things, fussing over
 | ||||
| //   allocation and layout of memory, in order to squeeze out every last drop of performance.
 | ||||
| 
 | ||||
| #if _MSC_VER | ||||
| // Assume Windows is little-endian.
 | ||||
| //
 | ||||
| // TODO(msvc): This is ugly. Maybe refactor later checks to be based on CAPNP_BYTE_ORDER or
 | ||||
| //   CAPNP_SWAP_BYTES or something, and define that in turn based on _MSC_VER or the GCC
 | ||||
| //   intrinsics.
 | ||||
| 
 | ||||
| #ifndef __ORDER_BIG_ENDIAN__ | ||||
| #define __ORDER_BIG_ENDIAN__ 4321 | ||||
| #endif | ||||
| #ifndef __ORDER_LITTLE_ENDIAN__ | ||||
| #define __ORDER_LITTLE_ENDIAN__ 1234 | ||||
| #endif | ||||
| #ifndef __BYTE_ORDER__ | ||||
| #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| #if CAPNP_REVERSE_ENDIAN | ||||
| #define CAPNP_WIRE_BYTE_ORDER __ORDER_BIG_ENDIAN__ | ||||
| #define CAPNP_OPPOSITE_OF_WIRE_BYTE_ORDER __ORDER_LITTLE_ENDIAN__ | ||||
| #else | ||||
| #define CAPNP_WIRE_BYTE_ORDER __ORDER_LITTLE_ENDIAN__ | ||||
| #define CAPNP_OPPOSITE_OF_WIRE_BYTE_ORDER __ORDER_BIG_ENDIAN__ | ||||
| #endif | ||||
| 
 | ||||
| #if defined(__BYTE_ORDER__) && \ | ||||
|     __BYTE_ORDER__ == CAPNP_WIRE_BYTE_ORDER && \
 | ||||
|     !CAPNP_DISABLE_ENDIAN_DETECTION | ||||
| // CPU is little-endian.  We can just read/write the memory directly.
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class DirectWireValue { | ||||
| public: | ||||
|   KJ_ALWAYS_INLINE(T get() const) { return value; } | ||||
|   KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; } | ||||
| 
 | ||||
| private: | ||||
|   T value; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| using WireValue = DirectWireValue<T>; | ||||
| // To prevent ODR problems when endian-test, endian-reverse-test, and endian-fallback-test are
 | ||||
| // linked together, we define each implementation with a different name and define an alias to the
 | ||||
| // one we want to use.
 | ||||
| 
 | ||||
| #elif defined(__BYTE_ORDER__) && \ | ||||
|       __BYTE_ORDER__ == CAPNP_OPPOSITE_OF_WIRE_BYTE_ORDER && \
 | ||||
|       defined(__GNUC__) && !CAPNP_DISABLE_ENDIAN_DETECTION | ||||
| // Big-endian, but GCC's __builtin_bswap() is available.
 | ||||
| 
 | ||||
| // TODO(perf):  Use dedicated instructions to read little-endian data on big-endian CPUs that have
 | ||||
| //   them.
 | ||||
| 
 | ||||
| // TODO(perf):  Verify that this code optimizes reasonably.  In particular, ensure that the
 | ||||
| //   compiler optimizes away the memcpy()s and keeps everything in registers.
 | ||||
| 
 | ||||
| template <typename T, size_t size = sizeof(T)> | ||||
| class SwappingWireValue; | ||||
| 
 | ||||
| template <typename T> | ||||
| class SwappingWireValue<T, 1> { | ||||
| public: | ||||
|   KJ_ALWAYS_INLINE(T get() const) { return value; } | ||||
|   KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; } | ||||
| 
 | ||||
| private: | ||||
|   T value; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class SwappingWireValue<T, 2> { | ||||
| public: | ||||
|   KJ_ALWAYS_INLINE(T get() const) { | ||||
|     // Not all platforms have __builtin_bswap16() for some reason.  In particular, it is missing
 | ||||
|     // on gcc-4.7.3-cygwin32 (but present on gcc-4.8.1-cygwin64).
 | ||||
|     uint16_t swapped = (value << 8) | (value >> 8); | ||||
|     T result; | ||||
|     memcpy(&result, &swapped, sizeof(T)); | ||||
|     return result; | ||||
|   } | ||||
|   KJ_ALWAYS_INLINE(void set(T newValue)) { | ||||
|     uint16_t raw; | ||||
|     memcpy(&raw, &newValue, sizeof(T)); | ||||
|     // Not all platforms have __builtin_bswap16() for some reason.  In particular, it is missing
 | ||||
|     // on gcc-4.7.3-cygwin32 (but present on gcc-4.8.1-cygwin64).
 | ||||
|     value = (raw << 8) | (raw >> 8); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   uint16_t value; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class SwappingWireValue<T, 4> { | ||||
| public: | ||||
|   KJ_ALWAYS_INLINE(T get() const) { | ||||
|     uint32_t swapped = __builtin_bswap32(value); | ||||
|     T result; | ||||
|     memcpy(&result, &swapped, sizeof(T)); | ||||
|     return result; | ||||
|   } | ||||
|   KJ_ALWAYS_INLINE(void set(T newValue)) { | ||||
|     uint32_t raw; | ||||
|     memcpy(&raw, &newValue, sizeof(T)); | ||||
|     value = __builtin_bswap32(raw); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   uint32_t value; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class SwappingWireValue<T, 8> { | ||||
| public: | ||||
|   KJ_ALWAYS_INLINE(T get() const) { | ||||
|     uint64_t swapped = __builtin_bswap64(value); | ||||
|     T result; | ||||
|     memcpy(&result, &swapped, sizeof(T)); | ||||
|     return result; | ||||
|   } | ||||
|   KJ_ALWAYS_INLINE(void set(T newValue)) { | ||||
|     uint64_t raw; | ||||
|     memcpy(&raw, &newValue, sizeof(T)); | ||||
|     value = __builtin_bswap64(raw); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   uint64_t value; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| using WireValue = SwappingWireValue<T>; | ||||
| // To prevent ODR problems when endian-test, endian-reverse-test, and endian-fallback-test are
 | ||||
| // linked together, we define each implementation with a different name and define an alias to the
 | ||||
| // one we want to use.
 | ||||
| 
 | ||||
| #else | ||||
| // Unknown endianness.  Fall back to bit shifts.
 | ||||
| 
 | ||||
| #if !CAPNP_DISABLE_ENDIAN_DETECTION | ||||
| #if _MSC_VER | ||||
| #pragma message("Couldn't detect endianness of your platform.  Using unoptimized fallback implementation.") | ||||
| #pragma message("Consider changing this code to detect your platform and send us a patch!") | ||||
| #else | ||||
| #warning "Couldn't detect endianness of your platform.  Using unoptimized fallback implementation." | ||||
| #warning "Consider changing this code to detect your platform and send us a patch!" | ||||
| #endif | ||||
| #endif  // !CAPNP_DISABLE_ENDIAN_DETECTION
 | ||||
| 
 | ||||
| template <typename T, size_t size = sizeof(T)> | ||||
| class ShiftingWireValue; | ||||
| 
 | ||||
| template <typename T> | ||||
| class ShiftingWireValue<T, 1> { | ||||
| public: | ||||
|   KJ_ALWAYS_INLINE(T get() const) { return value; } | ||||
|   KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; } | ||||
| 
 | ||||
| private: | ||||
|   T value; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class ShiftingWireValue<T, 2> { | ||||
| public: | ||||
|   KJ_ALWAYS_INLINE(T get() const) { | ||||
|     uint16_t raw = (static_cast<uint16_t>(bytes[0])     ) | | ||||
|                    (static_cast<uint16_t>(bytes[1]) << 8); | ||||
|     T result; | ||||
|     memcpy(&result, &raw, sizeof(T)); | ||||
|     return result; | ||||
|   } | ||||
|   KJ_ALWAYS_INLINE(void set(T newValue)) { | ||||
|     uint16_t raw; | ||||
|     memcpy(&raw, &newValue, sizeof(T)); | ||||
|     bytes[0] = raw; | ||||
|     bytes[1] = raw >> 8; | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   union { | ||||
|     byte bytes[2]; | ||||
|     uint16_t align; | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class ShiftingWireValue<T, 4> { | ||||
| public: | ||||
|   KJ_ALWAYS_INLINE(T get() const) { | ||||
|     uint32_t raw = (static_cast<uint32_t>(bytes[0])      ) | | ||||
|                    (static_cast<uint32_t>(bytes[1]) <<  8) | | ||||
|                    (static_cast<uint32_t>(bytes[2]) << 16) | | ||||
|                    (static_cast<uint32_t>(bytes[3]) << 24); | ||||
|     T result; | ||||
|     memcpy(&result, &raw, sizeof(T)); | ||||
|     return result; | ||||
|   } | ||||
|   KJ_ALWAYS_INLINE(void set(T newValue)) { | ||||
|     uint32_t raw; | ||||
|     memcpy(&raw, &newValue, sizeof(T)); | ||||
|     bytes[0] = raw; | ||||
|     bytes[1] = raw >> 8; | ||||
|     bytes[2] = raw >> 16; | ||||
|     bytes[3] = raw >> 24; | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   union { | ||||
|     byte bytes[4]; | ||||
|     uint32_t align; | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class ShiftingWireValue<T, 8> { | ||||
| public: | ||||
|   KJ_ALWAYS_INLINE(T get() const) { | ||||
|     uint64_t raw = (static_cast<uint64_t>(bytes[0])      ) | | ||||
|                    (static_cast<uint64_t>(bytes[1]) <<  8) | | ||||
|                    (static_cast<uint64_t>(bytes[2]) << 16) | | ||||
|                    (static_cast<uint64_t>(bytes[3]) << 24) | | ||||
|                    (static_cast<uint64_t>(bytes[4]) << 32) | | ||||
|                    (static_cast<uint64_t>(bytes[5]) << 40) | | ||||
|                    (static_cast<uint64_t>(bytes[6]) << 48) | | ||||
|                    (static_cast<uint64_t>(bytes[7]) << 56); | ||||
|     T result; | ||||
|     memcpy(&result, &raw, sizeof(T)); | ||||
|     return result; | ||||
|   } | ||||
|   KJ_ALWAYS_INLINE(void set(T newValue)) { | ||||
|     uint64_t raw; | ||||
|     memcpy(&raw, &newValue, sizeof(T)); | ||||
|     bytes[0] = raw; | ||||
|     bytes[1] = raw >> 8; | ||||
|     bytes[2] = raw >> 16; | ||||
|     bytes[3] = raw >> 24; | ||||
|     bytes[4] = raw >> 32; | ||||
|     bytes[5] = raw >> 40; | ||||
|     bytes[6] = raw >> 48; | ||||
|     bytes[7] = raw >> 56; | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   union { | ||||
|     byte bytes[8]; | ||||
|     uint64_t align; | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| using WireValue = ShiftingWireValue<T>; | ||||
| // To prevent ODR problems when endian-test, endian-reverse-test, and endian-fallback-test are
 | ||||
| // linked together, we define each implementation with a different name and define an alias to the
 | ||||
| // one we want to use.
 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_ENDIAN_H_
 | ||||
| @ -0,0 +1,254 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_EZ_RPC_H_ | ||||
| #define CAPNP_EZ_RPC_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "rpc.h" | ||||
| #include "message.h" | ||||
| 
 | ||||
| struct sockaddr; | ||||
| 
 | ||||
| namespace kj { class AsyncIoProvider; class LowLevelAsyncIoProvider; } | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| class EzRpcContext; | ||||
| 
 | ||||
| class EzRpcClient { | ||||
|   // Super-simple interface for setting up a Cap'n Proto RPC client.  Example:
 | ||||
|   //
 | ||||
|   //     # Cap'n Proto schema
 | ||||
|   //     interface Adder {
 | ||||
|   //       add @0 (left :Int32, right :Int32) -> (value :Int32);
 | ||||
|   //     }
 | ||||
|   //
 | ||||
|   //     // C++ client
 | ||||
|   //     int main() {
 | ||||
|   //       capnp::EzRpcClient client("localhost:3456");
 | ||||
|   //       Adder::Client adder = client.getMain<Adder>();
 | ||||
|   //       auto request = adder.addRequest();
 | ||||
|   //       request.setLeft(12);
 | ||||
|   //       request.setRight(34);
 | ||||
|   //       auto response = request.send().wait(client.getWaitScope());
 | ||||
|   //       assert(response.getValue() == 46);
 | ||||
|   //       return 0;
 | ||||
|   //     }
 | ||||
|   //
 | ||||
|   //     // C++ server
 | ||||
|   //     class AdderImpl final: public Adder::Server {
 | ||||
|   //     public:
 | ||||
|   //       kj::Promise<void> add(AddContext context) override {
 | ||||
|   //         auto params = context.getParams();
 | ||||
|   //         context.getResults().setValue(params.getLeft() + params.getRight());
 | ||||
|   //         return kj::READY_NOW;
 | ||||
|   //       }
 | ||||
|   //     };
 | ||||
|   //
 | ||||
|   //     int main() {
 | ||||
|   //       capnp::EzRpcServer server(kj::heap<AdderImpl>(), "*:3456");
 | ||||
|   //       kj::NEVER_DONE.wait(server.getWaitScope());
 | ||||
|   //     }
 | ||||
|   //
 | ||||
|   // This interface is easy, but it hides a lot of useful features available from the lower-level
 | ||||
|   // classes:
 | ||||
|   // - The server can only export a small set of public, singleton capabilities under well-known
 | ||||
|   //   string names.  This is fine for transient services where no state needs to be kept between
 | ||||
|   //   connections, but hides the power of Cap'n Proto when it comes to long-lived resources.
 | ||||
|   // - EzRpcClient/EzRpcServer automatically set up a `kj::EventLoop` and make it current for the
 | ||||
|   //   thread.  Only one `kj::EventLoop` can exist per thread, so you cannot use these interfaces
 | ||||
|   //   if you wish to set up your own event loop.  (However, you can safely create multiple
 | ||||
|   //   EzRpcClient / EzRpcServer objects in a single thread; they will make sure to make no more
 | ||||
|   //   than one EventLoop.)
 | ||||
|   // - These classes only support simple two-party connections, not multilateral VatNetworks.
 | ||||
|   // - These classes only support communication over a raw, unencrypted socket.  If you want to
 | ||||
|   //   build on an abstract stream (perhaps one which supports encryption), you must use the
 | ||||
|   //   lower-level interfaces.
 | ||||
|   //
 | ||||
|   // Some of these restrictions will probably be lifted in future versions, but some things will
 | ||||
|   // always require using the low-level interfaces directly.  If you are interested in working
 | ||||
|   // at a lower level, start by looking at these interfaces:
 | ||||
|   // - `kj::setupAsyncIo()` in `kj/async-io.h`.
 | ||||
|   // - `RpcSystem` in `capnp/rpc.h`.
 | ||||
|   // - `TwoPartyVatNetwork` in `capnp/rpc-twoparty.h`.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit EzRpcClient(kj::StringPtr serverAddress, uint defaultPort = 0, | ||||
|                        ReaderOptions readerOpts = ReaderOptions()); | ||||
|   // Construct a new EzRpcClient and connect to the given address.  The connection is formed in
 | ||||
|   // the background -- if it fails, calls to capabilities returned by importCap() will fail with an
 | ||||
|   // appropriate exception.
 | ||||
|   //
 | ||||
|   // `defaultPort` is the IP port number to use if `serverAddress` does not include it explicitly.
 | ||||
|   // If unspecified, the port is required in `serverAddress`.
 | ||||
|   //
 | ||||
|   // The address is parsed by `kj::Network` in `kj/async-io.h`.  See that interface for more info
 | ||||
|   // on the address format, but basically it's what you'd expect.
 | ||||
|   //
 | ||||
|   // `readerOpts` is the ReaderOptions structure used to read each incoming message on the
 | ||||
|   // connection. Setting this may be necessary if you need to receive very large individual
 | ||||
|   // messages or messages. However, it is recommended that you instead think about how to change
 | ||||
|   // your protocol to send large data blobs in multiple small chunks -- this is much better for
 | ||||
|   // both security and performance. See `ReaderOptions` in `message.h` for more details.
 | ||||
| 
 | ||||
|   EzRpcClient(const struct sockaddr* serverAddress, uint addrSize, | ||||
|               ReaderOptions readerOpts = ReaderOptions()); | ||||
|   // Like the above constructor, but connects to an already-resolved socket address.  Any address
 | ||||
|   // format supported by `kj::Network` in `kj/async-io.h` is accepted.
 | ||||
| 
 | ||||
|   explicit EzRpcClient(int socketFd, ReaderOptions readerOpts = ReaderOptions()); | ||||
|   // Create a client on top of an already-connected socket.
 | ||||
|   // `readerOpts` acts as in the first constructor.
 | ||||
| 
 | ||||
|   ~EzRpcClient() noexcept(false); | ||||
| 
 | ||||
|   template <typename Type> | ||||
|   typename Type::Client getMain(); | ||||
|   Capability::Client getMain(); | ||||
|   // Get the server's main (aka "bootstrap") interface.
 | ||||
| 
 | ||||
|   template <typename Type> | ||||
|   typename Type::Client importCap(kj::StringPtr name) | ||||
|       KJ_DEPRECATED("Change your server to export a main interface, then use getMain() instead."); | ||||
|   Capability::Client importCap(kj::StringPtr name) | ||||
|       KJ_DEPRECATED("Change your server to export a main interface, then use getMain() instead."); | ||||
|   // ** DEPRECATED **
 | ||||
|   //
 | ||||
|   // Ask the sever for the capability with the given name.  You may specify a type to automatically
 | ||||
|   // down-cast to that type.  It is up to you to specify the correct expected type.
 | ||||
|   //
 | ||||
|   // Named interfaces are deprecated. The new preferred usage pattern is for the server to export
 | ||||
|   // a "main" interface which itself has methods for getting any other interfaces.
 | ||||
| 
 | ||||
|   kj::WaitScope& getWaitScope(); | ||||
|   // Get the `WaitScope` for the client's `EventLoop`, which allows you to synchronously wait on
 | ||||
|   // promises.
 | ||||
| 
 | ||||
|   kj::AsyncIoProvider& getIoProvider(); | ||||
|   // Get the underlying AsyncIoProvider set up by the RPC system.  This is useful if you want
 | ||||
|   // to do some non-RPC I/O in asynchronous fashion.
 | ||||
| 
 | ||||
|   kj::LowLevelAsyncIoProvider& getLowLevelIoProvider(); | ||||
|   // Get the underlying LowLevelAsyncIoProvider set up by the RPC system.  This is useful if you
 | ||||
|   // want to do some non-RPC I/O in asynchronous fashion.
 | ||||
| 
 | ||||
| private: | ||||
|   struct Impl; | ||||
|   kj::Own<Impl> impl; | ||||
| }; | ||||
| 
 | ||||
| class EzRpcServer { | ||||
|   // The server counterpart to `EzRpcClient`.  See `EzRpcClient` for an example.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit EzRpcServer(Capability::Client mainInterface, kj::StringPtr bindAddress, | ||||
|                        uint defaultPort = 0, ReaderOptions readerOpts = ReaderOptions()); | ||||
|   // Construct a new `EzRpcServer` that binds to the given address.  An address of "*" means to
 | ||||
|   // bind to all local addresses.
 | ||||
|   //
 | ||||
|   // `defaultPort` is the IP port number to use if `serverAddress` does not include it explicitly.
 | ||||
|   // If unspecified, a port is chosen automatically, and you must call getPort() to find out what
 | ||||
|   // it is.
 | ||||
|   //
 | ||||
|   // The address is parsed by `kj::Network` in `kj/async-io.h`.  See that interface for more info
 | ||||
|   // on the address format, but basically it's what you'd expect.
 | ||||
|   //
 | ||||
|   // The server might not begin listening immediately, especially if `bindAddress` needs to be
 | ||||
|   // resolved.  If you need to wait until the server is definitely up, wait on the promise returned
 | ||||
|   // by `getPort()`.
 | ||||
|   //
 | ||||
|   // `readerOpts` is the ReaderOptions structure used to read each incoming message on the
 | ||||
|   // connection. Setting this may be necessary if you need to receive very large individual
 | ||||
|   // messages or messages. However, it is recommended that you instead think about how to change
 | ||||
|   // your protocol to send large data blobs in multiple small chunks -- this is much better for
 | ||||
|   // both security and performance. See `ReaderOptions` in `message.h` for more details.
 | ||||
| 
 | ||||
|   EzRpcServer(Capability::Client mainInterface, struct sockaddr* bindAddress, uint addrSize, | ||||
|               ReaderOptions readerOpts = ReaderOptions()); | ||||
|   // Like the above constructor, but binds to an already-resolved socket address.  Any address
 | ||||
|   // format supported by `kj::Network` in `kj/async-io.h` is accepted.
 | ||||
| 
 | ||||
|   EzRpcServer(Capability::Client mainInterface, int socketFd, uint port, | ||||
|               ReaderOptions readerOpts = ReaderOptions()); | ||||
|   // Create a server on top of an already-listening socket (i.e. one on which accept() may be
 | ||||
|   // called).  `port` is returned by `getPort()` -- it serves no other purpose.
 | ||||
|   // `readerOpts` acts as in the other two above constructors.
 | ||||
| 
 | ||||
|   explicit EzRpcServer(kj::StringPtr bindAddress, uint defaultPort = 0, | ||||
|                        ReaderOptions readerOpts = ReaderOptions()) | ||||
|       KJ_DEPRECATED("Please specify a main interface for your server."); | ||||
|   EzRpcServer(struct sockaddr* bindAddress, uint addrSize, | ||||
|               ReaderOptions readerOpts = ReaderOptions()) | ||||
|       KJ_DEPRECATED("Please specify a main interface for your server."); | ||||
|   EzRpcServer(int socketFd, uint port, ReaderOptions readerOpts = ReaderOptions()) | ||||
|       KJ_DEPRECATED("Please specify a main interface for your server."); | ||||
| 
 | ||||
|   ~EzRpcServer() noexcept(false); | ||||
| 
 | ||||
|   void exportCap(kj::StringPtr name, Capability::Client cap); | ||||
|   // Export a capability publicly under the given name, so that clients can import it.
 | ||||
|   //
 | ||||
|   // Keep in mind that you can implicitly convert `kj::Own<MyType::Server>&&` to
 | ||||
|   // `Capability::Client`, so it's typical to pass something like
 | ||||
|   // `kj::heap<MyImplementation>(<constructor params>)` as the second parameter.
 | ||||
| 
 | ||||
|   kj::Promise<uint> getPort(); | ||||
|   // Get the IP port number on which this server is listening.  This promise won't resolve until
 | ||||
|   // the server is actually listening.  If the address was not an IP address (e.g. it was a Unix
 | ||||
|   // domain socket) then getPort() resolves to zero.
 | ||||
| 
 | ||||
|   kj::WaitScope& getWaitScope(); | ||||
|   // Get the `WaitScope` for the client's `EventLoop`, which allows you to synchronously wait on
 | ||||
|   // promises.
 | ||||
| 
 | ||||
|   kj::AsyncIoProvider& getIoProvider(); | ||||
|   // Get the underlying AsyncIoProvider set up by the RPC system.  This is useful if you want
 | ||||
|   // to do some non-RPC I/O in asynchronous fashion.
 | ||||
| 
 | ||||
|   kj::LowLevelAsyncIoProvider& getLowLevelIoProvider(); | ||||
|   // Get the underlying LowLevelAsyncIoProvider set up by the RPC system.  This is useful if you
 | ||||
|   // want to do some non-RPC I/O in asynchronous fashion.
 | ||||
| 
 | ||||
| private: | ||||
|   struct Impl; | ||||
|   kj::Own<Impl> impl; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // inline implementation details
 | ||||
| 
 | ||||
| template <typename Type> | ||||
| inline typename Type::Client EzRpcClient::getMain() { | ||||
|   return getMain().castAs<Type>(); | ||||
| } | ||||
| 
 | ||||
| template <typename Type> | ||||
| inline typename Type::Client EzRpcClient::importCap(kj::StringPtr name) { | ||||
|   return importCap(name).castAs<Type>(); | ||||
| } | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_EZ_RPC_H_
 | ||||
| @ -0,0 +1,407 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| // This file is included from all generated headers.
 | ||||
| 
 | ||||
| #ifndef CAPNP_GENERATED_HEADER_SUPPORT_H_ | ||||
| #define CAPNP_GENERATED_HEADER_SUPPORT_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "raw-schema.h" | ||||
| #include "layout.h" | ||||
| #include "list.h" | ||||
| #include "orphan.h" | ||||
| #include "pointer-helpers.h" | ||||
| #include "any.h" | ||||
| #include <kj/string.h> | ||||
| #include <kj/string-tree.h> | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| class MessageBuilder;  // So that it can be declared a friend.
 | ||||
| 
 | ||||
| template <typename T, Kind k = CAPNP_KIND(T)> | ||||
| struct ToDynamic_;   // Defined in dynamic.h, needs to be declared as everyone's friend.
 | ||||
| 
 | ||||
| struct DynamicStruct;  // So that it can be declared a friend.
 | ||||
| 
 | ||||
| struct Capability;  // To declare brandBindingFor<Capability>()
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
| 
 | ||||
| template <typename T, typename CapnpPrivate = typename T::_capnpPrivate, bool = false> | ||||
| inline const RawSchema& rawSchema() { | ||||
|   return *CapnpPrivate::schema; | ||||
| } | ||||
| template <typename T, uint64_t id = schemas::EnumInfo<T>::typeId> | ||||
| inline const RawSchema& rawSchema() { | ||||
|   return *schemas::EnumInfo<T>::schema; | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename CapnpPrivate = typename T::_capnpPrivate> | ||||
| inline const RawBrandedSchema& rawBrandedSchema() { | ||||
|   return *CapnpPrivate::brand(); | ||||
| } | ||||
| template <typename T, uint64_t id = schemas::EnumInfo<T>::typeId> | ||||
| inline const RawBrandedSchema& rawBrandedSchema() { | ||||
|   return schemas::EnumInfo<T>::schema->defaultBrand; | ||||
| } | ||||
| 
 | ||||
| template <typename TypeTag, typename... Params> | ||||
| struct ChooseBrand; | ||||
| // If all of `Params` are `AnyPointer`, return the type's default brand. Otherwise, return a
 | ||||
| // specific brand instance. TypeTag is the _capnpPrivate struct for the type in question.
 | ||||
| 
 | ||||
| template <typename TypeTag> | ||||
| struct ChooseBrand<TypeTag> { | ||||
|   // All params were AnyPointer. No specific brand needed.
 | ||||
|   static constexpr _::RawBrandedSchema const* brand() { return &TypeTag::schema->defaultBrand; } | ||||
| }; | ||||
| 
 | ||||
| template <typename TypeTag, typename... Rest> | ||||
| struct ChooseBrand<TypeTag, AnyPointer, Rest...>: public ChooseBrand<TypeTag, Rest...> {}; | ||||
| // The first parameter is AnyPointer, so recurse to check the rest.
 | ||||
| 
 | ||||
| template <typename TypeTag, typename First, typename... Rest> | ||||
| struct ChooseBrand<TypeTag, First, Rest...> { | ||||
|   // At least one parameter is not AnyPointer, so use the specificBrand constant.
 | ||||
|   static constexpr _::RawBrandedSchema const* brand() { return &TypeTag::specificBrand; } | ||||
| }; | ||||
| 
 | ||||
| template <typename T, Kind k = kind<T>()> | ||||
| struct BrandBindingFor_; | ||||
| 
 | ||||
| #define HANDLE_TYPE(Type, which) \ | ||||
|   template <> \
 | ||||
|   struct BrandBindingFor_<Type, Kind::PRIMITIVE> { \
 | ||||
|     static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { \
 | ||||
|       return { which, listDepth, nullptr }; \
 | ||||
|     } \
 | ||||
|   } | ||||
| HANDLE_TYPE(Void, 0); | ||||
| HANDLE_TYPE(bool, 1); | ||||
| HANDLE_TYPE(int8_t, 2); | ||||
| HANDLE_TYPE(int16_t, 3); | ||||
| HANDLE_TYPE(int32_t, 4); | ||||
| HANDLE_TYPE(int64_t, 5); | ||||
| HANDLE_TYPE(uint8_t, 6); | ||||
| HANDLE_TYPE(uint16_t, 7); | ||||
| HANDLE_TYPE(uint32_t, 8); | ||||
| HANDLE_TYPE(uint64_t, 9); | ||||
| HANDLE_TYPE(float, 10); | ||||
| HANDLE_TYPE(double, 11); | ||||
| #undef HANDLE_TYPE | ||||
| 
 | ||||
| template <> | ||||
| struct BrandBindingFor_<Text, Kind::BLOB> { | ||||
|   static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { | ||||
|     return { 12, listDepth, nullptr }; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| struct BrandBindingFor_<Data, Kind::BLOB> { | ||||
|   static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { | ||||
|     return { 13, listDepth, nullptr }; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct BrandBindingFor_<List<T>, Kind::LIST> { | ||||
|   static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { | ||||
|     return BrandBindingFor_<T>::get(listDepth + 1); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct BrandBindingFor_<T, Kind::ENUM> { | ||||
|   static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { | ||||
|     return { 15, listDepth, nullptr }; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct BrandBindingFor_<T, Kind::STRUCT> { | ||||
|   static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { | ||||
|     return { 16, listDepth, T::_capnpPrivate::brand() }; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct BrandBindingFor_<T, Kind::INTERFACE> { | ||||
|   static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { | ||||
|     return { 17, listDepth, T::_capnpPrivate::brand() }; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| struct BrandBindingFor_<AnyPointer, Kind::OTHER> { | ||||
|   static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { | ||||
|     return { 18, listDepth, 0, 0 }; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| struct BrandBindingFor_<AnyStruct, Kind::OTHER> { | ||||
|   static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { | ||||
|     return { 18, listDepth, 0, 1 }; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| struct BrandBindingFor_<AnyList, Kind::OTHER> { | ||||
|   static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { | ||||
|     return { 18, listDepth, 0, 2 }; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| struct BrandBindingFor_<Capability, Kind::OTHER> { | ||||
|   static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { | ||||
|     return { 18, listDepth, 0, 3 }; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| constexpr RawBrandedSchema::Binding brandBindingFor() { | ||||
|   return BrandBindingFor_<T>::get(0); | ||||
| } | ||||
| 
 | ||||
| kj::StringTree structString(StructReader reader, const RawBrandedSchema& schema); | ||||
| kj::String enumString(uint16_t value, const RawBrandedSchema& schema); | ||||
| // Declared here so that we can declare inline stringify methods on generated types.
 | ||||
| // Defined in stringify.c++, which depends on dynamic.c++, which is allowed not to be linked in.
 | ||||
| 
 | ||||
| template <typename T> | ||||
| inline kj::StringTree structString(StructReader reader) { | ||||
|   return structString(reader, rawBrandedSchema<T>()); | ||||
| } | ||||
| template <typename T> | ||||
| inline kj::String enumString(T value) { | ||||
|   return enumString(static_cast<uint16_t>(value), rawBrandedSchema<T>()); | ||||
| } | ||||
| 
 | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| // TODO(cleanup):  Unify ConstStruct and ConstList.
 | ||||
| template <typename T> | ||||
| class ConstStruct { | ||||
| public: | ||||
|   ConstStruct() = delete; | ||||
|   KJ_DISALLOW_COPY(ConstStruct); | ||||
|   inline explicit constexpr ConstStruct(const word* ptr): ptr(ptr) {} | ||||
| 
 | ||||
|   inline typename T::Reader get() const { | ||||
|     return AnyPointer::Reader(PointerReader::getRootUnchecked(ptr)).getAs<T>(); | ||||
|   } | ||||
| 
 | ||||
|   inline operator typename T::Reader() const { return get(); } | ||||
|   inline typename T::Reader operator*() const { return get(); } | ||||
|   inline TemporaryPointer<typename T::Reader> operator->() const { return get(); } | ||||
| 
 | ||||
| private: | ||||
|   const word* ptr; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class ConstList { | ||||
| public: | ||||
|   ConstList() = delete; | ||||
|   KJ_DISALLOW_COPY(ConstList); | ||||
|   inline explicit constexpr ConstList(const word* ptr): ptr(ptr) {} | ||||
| 
 | ||||
|   inline typename List<T>::Reader get() const { | ||||
|     return AnyPointer::Reader(PointerReader::getRootUnchecked(ptr)).getAs<List<T>>(); | ||||
|   } | ||||
| 
 | ||||
|   inline operator typename List<T>::Reader() const { return get(); } | ||||
|   inline typename List<T>::Reader operator*() const { return get(); } | ||||
|   inline TemporaryPointer<typename List<T>::Reader> operator->() const { return get(); } | ||||
| 
 | ||||
| private: | ||||
|   const word* ptr; | ||||
| }; | ||||
| 
 | ||||
| template <size_t size> | ||||
| class ConstText { | ||||
| public: | ||||
|   ConstText() = delete; | ||||
|   KJ_DISALLOW_COPY(ConstText); | ||||
|   inline explicit constexpr ConstText(const word* ptr): ptr(ptr) {} | ||||
| 
 | ||||
|   inline Text::Reader get() const { | ||||
|     return Text::Reader(reinterpret_cast<const char*>(ptr), size); | ||||
|   } | ||||
| 
 | ||||
|   inline operator Text::Reader() const { return get(); } | ||||
|   inline Text::Reader operator*() const { return get(); } | ||||
|   inline TemporaryPointer<Text::Reader> operator->() const { return get(); } | ||||
| 
 | ||||
|   inline kj::StringPtr toString() const { | ||||
|     return get(); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   const word* ptr; | ||||
| }; | ||||
| 
 | ||||
| template <size_t size> | ||||
| inline kj::StringPtr KJ_STRINGIFY(const ConstText<size>& s) { | ||||
|   return s.get(); | ||||
| } | ||||
| 
 | ||||
| template <size_t size> | ||||
| class ConstData { | ||||
| public: | ||||
|   ConstData() = delete; | ||||
|   KJ_DISALLOW_COPY(ConstData); | ||||
|   inline explicit constexpr ConstData(const word* ptr): ptr(ptr) {} | ||||
| 
 | ||||
|   inline Data::Reader get() const { | ||||
|     return Data::Reader(reinterpret_cast<const byte*>(ptr), size); | ||||
|   } | ||||
| 
 | ||||
|   inline operator Data::Reader() const { return get(); } | ||||
|   inline Data::Reader operator*() const { return get(); } | ||||
|   inline TemporaryPointer<Data::Reader> operator->() const { return get(); } | ||||
| 
 | ||||
| private: | ||||
|   const word* ptr; | ||||
| }; | ||||
| 
 | ||||
| template <size_t size> | ||||
| inline auto KJ_STRINGIFY(const ConstData<size>& s) -> decltype(kj::toCharSequence(s.get())) { | ||||
|   return kj::toCharSequence(s.get()); | ||||
| } | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename T, typename CapnpPrivate = typename T::_capnpPrivate> | ||||
| inline constexpr uint64_t typeId() { return CapnpPrivate::typeId; } | ||||
| template <typename T, uint64_t id = schemas::EnumInfo<T>::typeId> | ||||
| inline constexpr uint64_t typeId() { return id; } | ||||
| // typeId<MyType>() returns the type ID as defined in the schema.  Works with structs, enums, and
 | ||||
| // interfaces.
 | ||||
| 
 | ||||
| template <typename T> | ||||
| inline constexpr uint sizeInWords() { | ||||
|   // Return the size, in words, of a Struct type, if allocated free-standing (not in a list).
 | ||||
|   // May be useful for pre-computing space needed in order to precisely allocate messages.
 | ||||
| 
 | ||||
|   return unbound((upgradeBound<uint>(_::structSize<T>().data) + | ||||
|       _::structSize<T>().pointers * WORDS_PER_POINTER) / WORDS); | ||||
| } | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #if _MSC_VER | ||||
| // MSVC doesn't understand floating-point constexpr yet.
 | ||||
| //
 | ||||
| // TODO(msvc): Remove this hack when MSVC is fixed.
 | ||||
| #define CAPNP_NON_INT_CONSTEXPR_DECL_INIT(value) | ||||
| #define CAPNP_NON_INT_CONSTEXPR_DEF_INIT(value) = value | ||||
| #else | ||||
| #define CAPNP_NON_INT_CONSTEXPR_DECL_INIT(value) = value | ||||
| #define CAPNP_NON_INT_CONSTEXPR_DEF_INIT(value) | ||||
| #endif | ||||
| 
 | ||||
| #if _MSC_VER | ||||
| // TODO(msvc): A little hack to allow MSVC to use C++14 return type deduction in cases where the
 | ||||
| // explicit type exposes bugs in the compiler.
 | ||||
| #define CAPNP_AUTO_IF_MSVC(...) auto | ||||
| #else | ||||
| #define CAPNP_AUTO_IF_MSVC(...) __VA_ARGS__ | ||||
| #endif | ||||
| 
 | ||||
| #if CAPNP_LITE | ||||
| 
 | ||||
| #define CAPNP_DECLARE_SCHEMA(id) \ | ||||
|     extern ::capnp::word const* const bp_##id | ||||
| 
 | ||||
| #define CAPNP_DECLARE_ENUM(type, id) \ | ||||
|     inline ::kj::String KJ_STRINGIFY(type##_##id value) { \
 | ||||
|       return ::kj::str(static_cast<uint16_t>(value)); \
 | ||||
|     } \
 | ||||
|     template <> struct EnumInfo<type##_##id> { \
 | ||||
|       struct IsEnum; \
 | ||||
|       static constexpr uint64_t typeId = 0x##id; \
 | ||||
|       static inline ::capnp::word const* encodedSchema() { return bp_##id; } \
 | ||||
|     } | ||||
| 
 | ||||
| #if _MSC_VER | ||||
| // TODO(msvc): MSVC dosen't expect constexprs to have definitions.
 | ||||
| #define CAPNP_DEFINE_ENUM(type, id) | ||||
| #else | ||||
| #define CAPNP_DEFINE_ENUM(type, id) \ | ||||
|     constexpr uint64_t EnumInfo<type>::typeId | ||||
| #endif | ||||
| 
 | ||||
| #define CAPNP_DECLARE_STRUCT_HEADER(id, dataWordSize_, pointerCount_) \ | ||||
|       struct IsStruct; \
 | ||||
|       static constexpr uint64_t typeId = 0x##id; \
 | ||||
|       static constexpr uint16_t dataWordSize = dataWordSize_; \
 | ||||
|       static constexpr uint16_t pointerCount = pointerCount_; \
 | ||||
|       static inline ::capnp::word const* encodedSchema() { return ::capnp::schemas::bp_##id; } | ||||
| 
 | ||||
| #else  // CAPNP_LITE
 | ||||
| 
 | ||||
| #define CAPNP_DECLARE_SCHEMA(id) \ | ||||
|     extern ::capnp::word const* const bp_##id; \
 | ||||
|     extern const ::capnp::_::RawSchema s_##id | ||||
| 
 | ||||
| #define CAPNP_DECLARE_ENUM(type, id) \ | ||||
|     inline ::kj::String KJ_STRINGIFY(type##_##id value) { \
 | ||||
|       return ::capnp::_::enumString(value); \
 | ||||
|     } \
 | ||||
|     template <> struct EnumInfo<type##_##id> { \
 | ||||
|       struct IsEnum; \
 | ||||
|       static constexpr uint64_t typeId = 0x##id; \
 | ||||
|       static inline ::capnp::word const* encodedSchema() { return bp_##id; } \
 | ||||
|       static constexpr ::capnp::_::RawSchema const* schema = &s_##id; \
 | ||||
|     } | ||||
| #define CAPNP_DEFINE_ENUM(type, id) \ | ||||
|     constexpr uint64_t EnumInfo<type>::typeId; \
 | ||||
|     constexpr ::capnp::_::RawSchema const* EnumInfo<type>::schema | ||||
| 
 | ||||
| #define CAPNP_DECLARE_STRUCT_HEADER(id, dataWordSize_, pointerCount_) \ | ||||
|       struct IsStruct; \
 | ||||
|       static constexpr uint64_t typeId = 0x##id; \
 | ||||
|       static constexpr ::capnp::Kind kind = ::capnp::Kind::STRUCT; \
 | ||||
|       static constexpr uint16_t dataWordSize = dataWordSize_; \
 | ||||
|       static constexpr uint16_t pointerCount = pointerCount_; \
 | ||||
|       static inline ::capnp::word const* encodedSchema() { return ::capnp::schemas::bp_##id; } \
 | ||||
|       static constexpr ::capnp::_::RawSchema const* schema = &::capnp::schemas::s_##id; | ||||
| 
 | ||||
| #define CAPNP_DECLARE_INTERFACE_HEADER(id) \ | ||||
|       struct IsInterface; \
 | ||||
|       static constexpr uint64_t typeId = 0x##id; \
 | ||||
|       static constexpr ::capnp::Kind kind = ::capnp::Kind::INTERFACE; \
 | ||||
|       static inline ::capnp::word const* encodedSchema() { return ::capnp::schemas::bp_##id; } \
 | ||||
|       static constexpr ::capnp::_::RawSchema const* schema = &::capnp::schemas::s_##id; | ||||
| 
 | ||||
| #endif  // CAPNP_LITE, else
 | ||||
| 
 | ||||
| #endif  // CAPNP_GENERATED_HEADER_SUPPORT_H_
 | ||||
| @ -0,0 +1,58 @@ | ||||
| # Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors | ||||
| # Licensed under the MIT License: | ||||
| # | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| # of this software and associated documentation files (the "Software"), to deal | ||||
| # in the Software without restriction, including without limitation the rights | ||||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| # copies of the Software, and to permit persons to whom the Software is | ||||
| # furnished to do so, subject to the following conditions: | ||||
| # | ||||
| # The above copyright notice and this permission notice shall be included in | ||||
| # all copies or substantial portions of the Software. | ||||
| # | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| # THE SOFTWARE. | ||||
| 
 | ||||
| @0x8ef99297a43a5e34; | ||||
| 
 | ||||
| $import "/capnp/c++.capnp".namespace("capnp"); | ||||
| 
 | ||||
| struct JsonValue { | ||||
|   union { | ||||
|     null @0 :Void; | ||||
|     boolean @1 :Bool; | ||||
|     number @2 :Float64; | ||||
|     string @3 :Text; | ||||
|     array @4 :List(JsonValue); | ||||
|     object @5 :List(Field); | ||||
|     # Standard JSON values. | ||||
| 
 | ||||
|     call @6 :Call; | ||||
|     # Non-standard: A "function call", applying a named function (named by a single identifier) | ||||
|     # to a parameter list. Examples: | ||||
|     # | ||||
|     #     BinData(0, "Zm9vCg==") | ||||
|     #     ISODate("2015-04-15T08:44:50.218Z") | ||||
|     # | ||||
|     # Mongo DB users will recognize the above as exactly the syntax Mongo uses to represent BSON | ||||
|     # "binary" and "date" types in text, since JSON has no analog of these. This is basically the | ||||
|     # reason this extension exists. We do NOT recommend using `call` unless you specifically need | ||||
|     # to be compatible with some silly format that uses this syntax. | ||||
|   } | ||||
| 
 | ||||
|   struct Field { | ||||
|     name @0 :Text; | ||||
|     value @1 :JsonValue; | ||||
|   } | ||||
| 
 | ||||
|   struct Call { | ||||
|     function @0 :Text; | ||||
|     params @1 :List(JsonValue); | ||||
|   } | ||||
| } | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -0,0 +1,546 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_LIST_H_ | ||||
| #define CAPNP_LIST_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "layout.h" | ||||
| #include "orphan.h" | ||||
| #include <initializer_list> | ||||
| #ifdef KJ_STD_COMPAT | ||||
| #include <iterator> | ||||
| #endif  // KJ_STD_COMPAT
 | ||||
| 
 | ||||
| namespace capnp { | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class TemporaryPointer { | ||||
|   // This class is a little hack which lets us define operator->() in cases where it needs to
 | ||||
|   // return a pointer to a temporary value.  We instead construct a TemporaryPointer and return that
 | ||||
|   // (by value).  The compiler then invokes operator->() on the TemporaryPointer, which itself is
 | ||||
|   // able to return a real pointer to its member.
 | ||||
| 
 | ||||
| public: | ||||
|   TemporaryPointer(T&& value): value(kj::mv(value)) {} | ||||
|   TemporaryPointer(const T& value): value(value) {} | ||||
| 
 | ||||
|   inline T* operator->() { return &value; } | ||||
| private: | ||||
|   T value; | ||||
| }; | ||||
| 
 | ||||
| template <typename Container, typename Element> | ||||
| class IndexingIterator { | ||||
| public: | ||||
|   IndexingIterator() = default; | ||||
| 
 | ||||
|   inline Element operator*() const { return (*container)[index]; } | ||||
|   inline TemporaryPointer<Element> operator->() const { | ||||
|     return TemporaryPointer<Element>((*container)[index]); | ||||
|   } | ||||
|   inline Element operator[]( int off) const { return (*container)[index]; } | ||||
|   inline Element operator[](uint off) const { return (*container)[index]; } | ||||
| 
 | ||||
|   inline IndexingIterator& operator++() { ++index; return *this; } | ||||
|   inline IndexingIterator operator++(int) { IndexingIterator other = *this; ++index; return other; } | ||||
|   inline IndexingIterator& operator--() { --index; return *this; } | ||||
|   inline IndexingIterator operator--(int) { IndexingIterator other = *this; --index; return other; } | ||||
| 
 | ||||
|   inline IndexingIterator operator+(uint amount) const { return IndexingIterator(container, index + amount); } | ||||
|   inline IndexingIterator operator-(uint amount) const { return IndexingIterator(container, index - amount); } | ||||
|   inline IndexingIterator operator+( int amount) const { return IndexingIterator(container, index + amount); } | ||||
|   inline IndexingIterator operator-( int amount) const { return IndexingIterator(container, index - amount); } | ||||
| 
 | ||||
|   inline int operator-(const IndexingIterator& other) const { return index - other.index; } | ||||
| 
 | ||||
|   inline IndexingIterator& operator+=(uint amount) { index += amount; return *this; } | ||||
|   inline IndexingIterator& operator-=(uint amount) { index -= amount; return *this; } | ||||
|   inline IndexingIterator& operator+=( int amount) { index += amount; return *this; } | ||||
|   inline IndexingIterator& operator-=( int amount) { index -= amount; return *this; } | ||||
| 
 | ||||
|   // STL says comparing iterators of different containers is not allowed, so we only compare
 | ||||
|   // indices here.
 | ||||
|   inline bool operator==(const IndexingIterator& other) const { return index == other.index; } | ||||
|   inline bool operator!=(const IndexingIterator& other) const { return index != other.index; } | ||||
|   inline bool operator<=(const IndexingIterator& other) const { return index <= other.index; } | ||||
|   inline bool operator>=(const IndexingIterator& other) const { return index >= other.index; } | ||||
|   inline bool operator< (const IndexingIterator& other) const { return index <  other.index; } | ||||
|   inline bool operator> (const IndexingIterator& other) const { return index >  other.index; } | ||||
| 
 | ||||
| private: | ||||
|   Container* container; | ||||
|   uint index; | ||||
| 
 | ||||
|   friend Container; | ||||
|   inline IndexingIterator(Container* container, uint index) | ||||
|       : container(container), index(index) {} | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename T> | ||||
| struct List<T, Kind::PRIMITIVE> { | ||||
|   // List of primitives.
 | ||||
| 
 | ||||
|   List() = delete; | ||||
| 
 | ||||
|   class Reader { | ||||
|   public: | ||||
|     typedef List<T> Reads; | ||||
| 
 | ||||
|     inline Reader(): reader(_::elementSizeForType<T>()) {} | ||||
|     inline explicit Reader(_::ListReader reader): reader(reader) {} | ||||
| 
 | ||||
|     inline uint size() const { return unbound(reader.size() / ELEMENTS); } | ||||
|     inline T operator[](uint index) const { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       return reader.template getDataElement<T>(bounded(index) * ELEMENTS); | ||||
|     } | ||||
| 
 | ||||
|     typedef _::IndexingIterator<const Reader, T> Iterator; | ||||
|     inline Iterator begin() const { return Iterator(this, 0); } | ||||
|     inline Iterator end() const { return Iterator(this, size()); } | ||||
| 
 | ||||
|   private: | ||||
|     _::ListReader reader; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct _::PointerHelpers; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct List; | ||||
|     friend class Orphanage; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct ToDynamic_; | ||||
|   }; | ||||
| 
 | ||||
|   class Builder { | ||||
|   public: | ||||
|     typedef List<T> Builds; | ||||
| 
 | ||||
|     inline Builder(): builder(_::elementSizeForType<T>()) {} | ||||
|     inline Builder(decltype(nullptr)): Builder() {} | ||||
|     inline explicit Builder(_::ListBuilder builder): builder(builder) {} | ||||
| 
 | ||||
|     inline operator Reader() const { return Reader(builder.asReader()); } | ||||
|     inline Reader asReader() const { return Reader(builder.asReader()); } | ||||
| 
 | ||||
|     inline uint size() const { return unbound(builder.size() / ELEMENTS); } | ||||
|     inline T operator[](uint index) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       return builder.template getDataElement<T>(bounded(index) * ELEMENTS); | ||||
|     } | ||||
|     inline void set(uint index, T value) { | ||||
|       // Alas, it is not possible to make operator[] return a reference to which you can assign,
 | ||||
|       // since the encoded representation does not necessarily match the compiler's representation
 | ||||
|       // of the type.  We can't even return a clever class that implements operator T() and
 | ||||
|       // operator=() because it will lead to surprising behavior when using type inference (e.g.
 | ||||
|       // calling a template function with inferred argument types, or using "auto" or "decltype").
 | ||||
| 
 | ||||
|       builder.template setDataElement<T>(bounded(index) * ELEMENTS, value); | ||||
|     } | ||||
| 
 | ||||
|     typedef _::IndexingIterator<Builder, T> Iterator; | ||||
|     inline Iterator begin() { return Iterator(this, 0); } | ||||
|     inline Iterator end() { return Iterator(this, size()); } | ||||
| 
 | ||||
|   private: | ||||
|     _::ListBuilder builder; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct _::PointerHelpers; | ||||
|     friend class Orphanage; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct ToDynamic_; | ||||
|   }; | ||||
| 
 | ||||
|   class Pipeline {}; | ||||
| 
 | ||||
| private: | ||||
|   inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) { | ||||
|     return builder.initList(_::elementSizeForType<T>(), bounded(size) * ELEMENTS); | ||||
|   } | ||||
|   inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) { | ||||
|     return builder.getList(_::elementSizeForType<T>(), defaultValue); | ||||
|   } | ||||
|   inline static _::ListReader getFromPointer( | ||||
|       const _::PointerReader& reader, const word* defaultValue) { | ||||
|     return reader.getList(_::elementSizeForType<T>(), defaultValue); | ||||
|   } | ||||
| 
 | ||||
|   template <typename U, Kind k> | ||||
|   friend struct List; | ||||
|   template <typename U, Kind K> | ||||
|   friend struct _::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct List<T, Kind::ENUM>: public List<T, Kind::PRIMITIVE> {}; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct List<T, Kind::STRUCT> { | ||||
|   // List of structs.
 | ||||
| 
 | ||||
|   List() = delete; | ||||
| 
 | ||||
|   class Reader { | ||||
|   public: | ||||
|     typedef List<T> Reads; | ||||
| 
 | ||||
|     inline Reader(): reader(ElementSize::INLINE_COMPOSITE) {} | ||||
|     inline explicit Reader(_::ListReader reader): reader(reader) {} | ||||
| 
 | ||||
|     inline uint size() const { return unbound(reader.size() / ELEMENTS); } | ||||
|     inline typename T::Reader operator[](uint index) const { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       return typename T::Reader(reader.getStructElement(bounded(index) * ELEMENTS)); | ||||
|     } | ||||
| 
 | ||||
|     typedef _::IndexingIterator<const Reader, typename T::Reader> Iterator; | ||||
|     inline Iterator begin() const { return Iterator(this, 0); } | ||||
|     inline Iterator end() const { return Iterator(this, size()); } | ||||
| 
 | ||||
|   private: | ||||
|     _::ListReader reader; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct _::PointerHelpers; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct List; | ||||
|     friend class Orphanage; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct ToDynamic_; | ||||
|   }; | ||||
| 
 | ||||
|   class Builder { | ||||
|   public: | ||||
|     typedef List<T> Builds; | ||||
| 
 | ||||
|     inline Builder(): builder(ElementSize::INLINE_COMPOSITE) {} | ||||
|     inline Builder(decltype(nullptr)): Builder() {} | ||||
|     inline explicit Builder(_::ListBuilder builder): builder(builder) {} | ||||
| 
 | ||||
|     inline operator Reader() const { return Reader(builder.asReader()); } | ||||
|     inline Reader asReader() const { return Reader(builder.asReader()); } | ||||
| 
 | ||||
|     inline uint size() const { return unbound(builder.size() / ELEMENTS); } | ||||
|     inline typename T::Builder operator[](uint index) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       return typename T::Builder(builder.getStructElement(bounded(index) * ELEMENTS)); | ||||
|     } | ||||
| 
 | ||||
|     inline void adoptWithCaveats(uint index, Orphan<T>&& orphan) { | ||||
|       // Mostly behaves like you'd expect `adopt` to behave, but with two caveats originating from
 | ||||
|       // the fact that structs in a struct list are allocated inline rather than by pointer:
 | ||||
|       // * This actually performs a shallow copy, effectively adopting each of the orphan's
 | ||||
|       //   children rather than adopting the orphan itself.  The orphan ends up being discarded,
 | ||||
|       //   possibly wasting space in the message object.
 | ||||
|       // * If the orphan is larger than the target struct -- say, because the orphan was built
 | ||||
|       //   using a newer version of the schema that has additional fields -- it will be truncated,
 | ||||
|       //   losing data.
 | ||||
| 
 | ||||
|       KJ_IREQUIRE(index < size()); | ||||
| 
 | ||||
|       // We pass a zero-valued StructSize to asStruct() because we do not want the struct to be
 | ||||
|       // expanded under any circumstances.  We're just going to throw it away anyway, and
 | ||||
|       // transferContentFrom() already carefully compares the struct sizes before transferring.
 | ||||
|       builder.getStructElement(bounded(index) * ELEMENTS).transferContentFrom( | ||||
|           orphan.builder.asStruct(_::StructSize(ZERO * WORDS, ZERO * POINTERS))); | ||||
|     } | ||||
|     inline void setWithCaveats(uint index, const typename T::Reader& reader) { | ||||
|       // Mostly behaves like you'd expect `set` to behave, but with a caveat originating from
 | ||||
|       // the fact that structs in a struct list are allocated inline rather than by pointer:
 | ||||
|       // If the source struct is larger than the target struct -- say, because the source was built
 | ||||
|       // using a newer version of the schema that has additional fields -- it will be truncated,
 | ||||
|       // losing data.
 | ||||
|       //
 | ||||
|       // Note: If you are trying to concatenate some lists, use Orphanage::newOrphanConcat() to
 | ||||
|       //   do it without losing any data in case the source lists come from a newer version of the
 | ||||
|       //   protocol. (Plus, it's easier to use anyhow.)
 | ||||
| 
 | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       builder.getStructElement(bounded(index) * ELEMENTS).copyContentFrom(reader._reader); | ||||
|     } | ||||
| 
 | ||||
|     // There are no init(), set(), adopt(), or disown() methods for lists of structs because the
 | ||||
|     // elements of the list are inlined and are initialized when the list is initialized.  This
 | ||||
|     // means that init() would be redundant, and set() would risk data loss if the input struct
 | ||||
|     // were from a newer version of the protocol.
 | ||||
| 
 | ||||
|     typedef _::IndexingIterator<Builder, typename T::Builder> Iterator; | ||||
|     inline Iterator begin() { return Iterator(this, 0); } | ||||
|     inline Iterator end() { return Iterator(this, size()); } | ||||
| 
 | ||||
|   private: | ||||
|     _::ListBuilder builder; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct _::PointerHelpers; | ||||
|     friend class Orphanage; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct ToDynamic_; | ||||
|   }; | ||||
| 
 | ||||
|   class Pipeline {}; | ||||
| 
 | ||||
| private: | ||||
|   inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) { | ||||
|     return builder.initStructList(bounded(size) * ELEMENTS, _::structSize<T>()); | ||||
|   } | ||||
|   inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) { | ||||
|     return builder.getStructList(_::structSize<T>(), defaultValue); | ||||
|   } | ||||
|   inline static _::ListReader getFromPointer( | ||||
|       const _::PointerReader& reader, const word* defaultValue) { | ||||
|     return reader.getList(ElementSize::INLINE_COMPOSITE, defaultValue); | ||||
|   } | ||||
| 
 | ||||
|   template <typename U, Kind k> | ||||
|   friend struct List; | ||||
|   template <typename U, Kind K> | ||||
|   friend struct _::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct List<List<T>, Kind::LIST> { | ||||
|   // List of lists.
 | ||||
| 
 | ||||
|   List() = delete; | ||||
| 
 | ||||
|   class Reader { | ||||
|   public: | ||||
|     typedef List<List<T>> Reads; | ||||
| 
 | ||||
|     inline Reader(): reader(ElementSize::POINTER) {} | ||||
|     inline explicit Reader(_::ListReader reader): reader(reader) {} | ||||
| 
 | ||||
|     inline uint size() const { return unbound(reader.size() / ELEMENTS); } | ||||
|     inline typename List<T>::Reader operator[](uint index) const { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       return typename List<T>::Reader(_::PointerHelpers<List<T>>::get( | ||||
|           reader.getPointerElement(bounded(index) * ELEMENTS))); | ||||
|     } | ||||
| 
 | ||||
|     typedef _::IndexingIterator<const Reader, typename List<T>::Reader> Iterator; | ||||
|     inline Iterator begin() const { return Iterator(this, 0); } | ||||
|     inline Iterator end() const { return Iterator(this, size()); } | ||||
| 
 | ||||
|   private: | ||||
|     _::ListReader reader; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct _::PointerHelpers; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct List; | ||||
|     friend class Orphanage; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct ToDynamic_; | ||||
|   }; | ||||
| 
 | ||||
|   class Builder { | ||||
|   public: | ||||
|     typedef List<List<T>> Builds; | ||||
| 
 | ||||
|     inline Builder(): builder(ElementSize::POINTER) {} | ||||
|     inline Builder(decltype(nullptr)): Builder() {} | ||||
|     inline explicit Builder(_::ListBuilder builder): builder(builder) {} | ||||
| 
 | ||||
|     inline operator Reader() const { return Reader(builder.asReader()); } | ||||
|     inline Reader asReader() const { return Reader(builder.asReader()); } | ||||
| 
 | ||||
|     inline uint size() const { return unbound(builder.size() / ELEMENTS); } | ||||
|     inline typename List<T>::Builder operator[](uint index) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       return typename List<T>::Builder(_::PointerHelpers<List<T>>::get( | ||||
|           builder.getPointerElement(bounded(index) * ELEMENTS))); | ||||
|     } | ||||
|     inline typename List<T>::Builder init(uint index, uint size) { | ||||
|       KJ_IREQUIRE(index < this->size()); | ||||
|       return typename List<T>::Builder(_::PointerHelpers<List<T>>::init( | ||||
|           builder.getPointerElement(bounded(index) * ELEMENTS), size)); | ||||
|     } | ||||
|     inline void set(uint index, typename List<T>::Reader value) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       builder.getPointerElement(bounded(index) * ELEMENTS).setList(value.reader); | ||||
|     } | ||||
|     void set(uint index, std::initializer_list<ReaderFor<T>> value) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       auto l = init(index, value.size()); | ||||
|       uint i = 0; | ||||
|       for (auto& element: value) { | ||||
|         l.set(i++, element); | ||||
|       } | ||||
|     } | ||||
|     inline void adopt(uint index, Orphan<T>&& value) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder)); | ||||
|     } | ||||
|     inline Orphan<T> disown(uint index) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown()); | ||||
|     } | ||||
| 
 | ||||
|     typedef _::IndexingIterator<Builder, typename List<T>::Builder> Iterator; | ||||
|     inline Iterator begin() { return Iterator(this, 0); } | ||||
|     inline Iterator end() { return Iterator(this, size()); } | ||||
| 
 | ||||
|   private: | ||||
|     _::ListBuilder builder; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct _::PointerHelpers; | ||||
|     friend class Orphanage; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct ToDynamic_; | ||||
|   }; | ||||
| 
 | ||||
|   class Pipeline {}; | ||||
| 
 | ||||
| private: | ||||
|   inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) { | ||||
|     return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS); | ||||
|   } | ||||
|   inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) { | ||||
|     return builder.getList(ElementSize::POINTER, defaultValue); | ||||
|   } | ||||
|   inline static _::ListReader getFromPointer( | ||||
|       const _::PointerReader& reader, const word* defaultValue) { | ||||
|     return reader.getList(ElementSize::POINTER, defaultValue); | ||||
|   } | ||||
| 
 | ||||
|   template <typename U, Kind k> | ||||
|   friend struct List; | ||||
|   template <typename U, Kind K> | ||||
|   friend struct _::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct List<T, Kind::BLOB> { | ||||
|   List() = delete; | ||||
| 
 | ||||
|   class Reader { | ||||
|   public: | ||||
|     typedef List<T> Reads; | ||||
| 
 | ||||
|     inline Reader(): reader(ElementSize::POINTER) {} | ||||
|     inline explicit Reader(_::ListReader reader): reader(reader) {} | ||||
| 
 | ||||
|     inline uint size() const { return unbound(reader.size() / ELEMENTS); } | ||||
|     inline typename T::Reader operator[](uint index) const { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       return reader.getPointerElement(bounded(index) * ELEMENTS) | ||||
|           .template getBlob<T>(nullptr, ZERO * BYTES); | ||||
|     } | ||||
| 
 | ||||
|     typedef _::IndexingIterator<const Reader, typename T::Reader> Iterator; | ||||
|     inline Iterator begin() const { return Iterator(this, 0); } | ||||
|     inline Iterator end() const { return Iterator(this, size()); } | ||||
| 
 | ||||
|   private: | ||||
|     _::ListReader reader; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct _::PointerHelpers; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct List; | ||||
|     friend class Orphanage; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct ToDynamic_; | ||||
|   }; | ||||
| 
 | ||||
|   class Builder { | ||||
|   public: | ||||
|     typedef List<T> Builds; | ||||
| 
 | ||||
|     inline Builder(): builder(ElementSize::POINTER) {} | ||||
|     inline Builder(decltype(nullptr)): Builder() {} | ||||
|     inline explicit Builder(_::ListBuilder builder): builder(builder) {} | ||||
| 
 | ||||
|     inline operator Reader() const { return Reader(builder.asReader()); } | ||||
|     inline Reader asReader() const { return Reader(builder.asReader()); } | ||||
| 
 | ||||
|     inline uint size() const { return unbound(builder.size() / ELEMENTS); } | ||||
|     inline typename T::Builder operator[](uint index) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       return builder.getPointerElement(bounded(index) * ELEMENTS) | ||||
|           .template getBlob<T>(nullptr, ZERO * BYTES); | ||||
|     } | ||||
|     inline void set(uint index, typename T::Reader value) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       builder.getPointerElement(bounded(index) * ELEMENTS).template setBlob<T>(value); | ||||
|     } | ||||
|     inline typename T::Builder init(uint index, uint size) { | ||||
|       KJ_IREQUIRE(index < this->size()); | ||||
|       return builder.getPointerElement(bounded(index) * ELEMENTS) | ||||
|           .template initBlob<T>(bounded(size) * BYTES); | ||||
|     } | ||||
|     inline void adopt(uint index, Orphan<T>&& value) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder)); | ||||
|     } | ||||
|     inline Orphan<T> disown(uint index) { | ||||
|       KJ_IREQUIRE(index < size()); | ||||
|       return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown()); | ||||
|     } | ||||
| 
 | ||||
|     typedef _::IndexingIterator<Builder, typename T::Builder> Iterator; | ||||
|     inline Iterator begin() { return Iterator(this, 0); } | ||||
|     inline Iterator end() { return Iterator(this, size()); } | ||||
| 
 | ||||
|   private: | ||||
|     _::ListBuilder builder; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct _::PointerHelpers; | ||||
|     friend class Orphanage; | ||||
|     template <typename U, Kind K> | ||||
|     friend struct ToDynamic_; | ||||
|   }; | ||||
| 
 | ||||
|   class Pipeline {}; | ||||
| 
 | ||||
| private: | ||||
|   inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) { | ||||
|     return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS); | ||||
|   } | ||||
|   inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) { | ||||
|     return builder.getList(ElementSize::POINTER, defaultValue); | ||||
|   } | ||||
|   inline static _::ListReader getFromPointer( | ||||
|       const _::PointerReader& reader, const word* defaultValue) { | ||||
|     return reader.getList(ElementSize::POINTER, defaultValue); | ||||
|   } | ||||
| 
 | ||||
|   template <typename U, Kind k> | ||||
|   friend struct List; | ||||
|   template <typename U, Kind K> | ||||
|   friend struct _::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #ifdef KJ_STD_COMPAT | ||||
| namespace std { | ||||
| 
 | ||||
| template <typename Container, typename Element> | ||||
| struct iterator_traits<capnp::_::IndexingIterator<Container, Element>> | ||||
|       : public std::iterator<std::random_access_iterator_tag, Element, int> {}; | ||||
| 
 | ||||
| }  // namespace std
 | ||||
| #endif  // KJ_STD_COMPAT
 | ||||
| 
 | ||||
| #endif  // CAPNP_LIST_H_
 | ||||
| @ -0,0 +1,202 @@ | ||||
| // Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_MEMBRANE_H_ | ||||
| #define CAPNP_MEMBRANE_H_ | ||||
| // In capability theory, a "membrane" is a wrapper around a capability which (usually) forwards
 | ||||
| // calls but recursively wraps capabilities in those calls in the same membrane. The purpose of a
 | ||||
| // membrane is to enforce a barrier between two capabilities that cannot be bypassed by merely
 | ||||
| // introducing new objects.
 | ||||
| //
 | ||||
| // The most common use case for a membrane is revocation: Say Alice wants to give Bob a capability
 | ||||
| // to access Carol, but wants to be able to revoke this capability later. Alice can accomplish this
 | ||||
| // by wrapping Carol in a revokable wrapper which passes through calls until such a time as Alice
 | ||||
| // indicates it should be revoked, after which all calls through the wrapper will throw exceptions.
 | ||||
| // However, a naive wrapper approach has a problem: if Bob makes a call to Carol and sends a new
 | ||||
| // capability in that call, or if Carol returns a capability to Bob in the response to a call, then
 | ||||
| // the two are now able to communicate using this new capability, which Alice cannot revoke. In
 | ||||
| // order to avoid this problem, Alice must use not just a wrapper but a "membrane", which
 | ||||
| // recursively wraps all objects that pass through it in either direction. Thus, all connections
 | ||||
| // formed between Bob and Carol (originating from Alice's original introduction) can be revoked
 | ||||
| // together by revoking the membrane.
 | ||||
| //
 | ||||
| // Note that when a capability is passed into a membrane and then passed back out, the result is
 | ||||
| // the original capability, not a double-membraned capability. This means that in our revocation
 | ||||
| // example, if Bob uses his capability to Carol to obtain another capability from her, then send
 | ||||
| // it back to her, the capability Carol receives back will NOT be revoked when Bob's access to
 | ||||
| // Carol is revoked. Thus Bob can create long-term irrevocable connections. In most practical use
 | ||||
| // cases, this is what you want. APIs commonly rely on the fact that a capability obtained and then
 | ||||
| // passed back can be recognized as the original capability.
 | ||||
| //
 | ||||
| // Mark Miller on membranes: http://www.eros-os.org/pipermail/e-lang/2003-January/008434.html
 | ||||
| 
 | ||||
| #include "capability.h" | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| class MembranePolicy { | ||||
|   // Applications may implement this interface to define a membrane policy, which allows some
 | ||||
|   // calls crossing the membrane to be blocked or redirected.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual kj::Maybe<Capability::Client> inboundCall( | ||||
|       uint64_t interfaceId, uint16_t methodId, Capability::Client target) = 0; | ||||
|   // Given an inbound call (a call originating "outside" the membrane destined for an object
 | ||||
|   // "inside" the membrane), decides what to do with it. The policy may:
 | ||||
|   //
 | ||||
|   // - Return null to indicate that the call should proceed to the destination. All capabilities
 | ||||
|   //   in the parameters or result will be properly wrapped in the same membrane.
 | ||||
|   // - Return a capability to have the call redirected to that capability. Note that the redirect
 | ||||
|   //   capability will be treated as outside the membrane, so the params and results will not be
 | ||||
|   //   auto-wrapped; however, the callee can easily wrap the returned capability in the membrane
 | ||||
|   //   itself before returning to achieve this effect.
 | ||||
|   // - Throw an exception to cause the call to fail with that exception.
 | ||||
|   //
 | ||||
|   // `target` is the underlying capability (*inside* the membrane) for which the call is destined.
 | ||||
|   // Generally, the only way you should use `target` is to wrap it in some capability which you
 | ||||
|   // return as a redirect. The redirect capability may modify the call in some way and send it to
 | ||||
|   // `target`. Be careful to use `copyIntoMembrane()` and `copyOutOfMembrane()` as appropriate when
 | ||||
|   // copying parameters or results across the membrane.
 | ||||
|   //
 | ||||
|   // Note that since `target` is inside the capability, if you were to directly return it (rather
 | ||||
|   // than return null), the effect would be that the membrane would be broken: the call would
 | ||||
|   // proceed directly and any new capabilities introduced through it would not be membraned. You
 | ||||
|   // generally should not do that.
 | ||||
| 
 | ||||
|   virtual kj::Maybe<Capability::Client> outboundCall( | ||||
|       uint64_t interfaceId, uint16_t methodId, Capability::Client target) = 0; | ||||
|   // Like `inboundCall()`, but applies to calls originating *inside* the membrane and terminating
 | ||||
|   // outside.
 | ||||
|   //
 | ||||
|   // Note: It is strongly recommended that `outboundCall()` returns null in exactly the same cases
 | ||||
|   //   that `inboundCall()` return null. Conversely, for any case where `inboundCall()` would
 | ||||
|   //   redirect or throw, `outboundCall()` should also redirect or throw. Otherwise, you can run
 | ||||
|   //   into inconsistent behavion when a promise is returned across a membrane, and that promise
 | ||||
|   //   later resolves to a capability on the other side of the membrane: calls on the promise
 | ||||
|   //   will enter and then exit the membrane, but calls on the eventual resolution will not cross
 | ||||
|   //   the membrane at all, so it is important that these two cases behave the same.
 | ||||
| 
 | ||||
|   virtual kj::Own<MembranePolicy> addRef() = 0; | ||||
|   // Return a new owned pointer to the same policy.
 | ||||
|   //
 | ||||
|   // Typically an implementation of MembranePolicy should also inherit kj::Refcounted and implement
 | ||||
|   // `addRef()` as `return kj::addRef(*this);`.
 | ||||
|   //
 | ||||
|   // Note that the membraning system considers two membranes created with the same MembranePolicy
 | ||||
|   // object actually to be the *same* membrane. This is relevant when an object passes into the
 | ||||
|   // membrane and then back out (or out and then back in): instead of double-wrapping the object,
 | ||||
|   // the wrapping will be removed.
 | ||||
| }; | ||||
| 
 | ||||
| Capability::Client membrane(Capability::Client inner, kj::Own<MembranePolicy> policy); | ||||
| // Wrap `inner` in a membrane specified by `policy`. `inner` is considered "inside" the membrane,
 | ||||
| // while the returned capability should only be called from outside the membrane.
 | ||||
| 
 | ||||
| Capability::Client reverseMembrane(Capability::Client outer, kj::Own<MembranePolicy> policy); | ||||
| // Like `membrane` but treat the input capability as "outside" the membrane, and return a
 | ||||
| // capability appropriate for use inside.
 | ||||
| //
 | ||||
| // Applications typically won't use this directly; the membraning code automatically sets up
 | ||||
| // reverse membranes where needed.
 | ||||
| 
 | ||||
| template <typename ClientType> | ||||
| ClientType membrane(ClientType inner, kj::Own<MembranePolicy> policy); | ||||
| template <typename ClientType> | ||||
| ClientType reverseMembrane(ClientType inner, kj::Own<MembranePolicy> policy); | ||||
| // Convenience templates which return the same interface type as the input.
 | ||||
| 
 | ||||
| template <typename ServerType> | ||||
| typename ServerType::Serves::Client membrane( | ||||
|     kj::Own<ServerType> inner, kj::Own<MembranePolicy> policy); | ||||
| template <typename ServerType> | ||||
| typename ServerType::Serves::Client reverseMembrane( | ||||
|     kj::Own<ServerType> inner, kj::Own<MembranePolicy> policy); | ||||
| // Convenience templates which input a capability server type and return the appropriate client
 | ||||
| // type.
 | ||||
| 
 | ||||
| template <typename Reader> | ||||
| Orphan<typename kj::Decay<Reader>::Reads> copyIntoMembrane( | ||||
|     Reader&& from, Orphanage to, kj::Own<MembranePolicy> policy); | ||||
| // Copy a Cap'n Proto object (e.g. struct or list), adding the given membrane to any capabilities
 | ||||
| // found within it. `from` is interpreted as "outside" the membrane while `to` is "inside".
 | ||||
| 
 | ||||
| template <typename Reader> | ||||
| Orphan<typename kj::Decay<Reader>::Reads> copyOutOfMembrane( | ||||
|     Reader&& from, Orphanage to, kj::Own<MembranePolicy> policy); | ||||
| // Like copyIntoMembrane() except that `from` is "inside" the membrane and `to` is "outside".
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // inline implementation details
 | ||||
| 
 | ||||
| template <typename ClientType> | ||||
| ClientType membrane(ClientType inner, kj::Own<MembranePolicy> policy) { | ||||
|   return membrane(Capability::Client(kj::mv(inner)), kj::mv(policy)) | ||||
|       .castAs<typename ClientType::Calls>(); | ||||
| } | ||||
| template <typename ClientType> | ||||
| ClientType reverseMembrane(ClientType inner, kj::Own<MembranePolicy> policy) { | ||||
|   return reverseMembrane(Capability::Client(kj::mv(inner)), kj::mv(policy)) | ||||
|       .castAs<typename ClientType::Calls>(); | ||||
| } | ||||
| 
 | ||||
| template <typename ServerType> | ||||
| typename ServerType::Serves::Client membrane( | ||||
|     kj::Own<ServerType> inner, kj::Own<MembranePolicy> policy) { | ||||
|   return membrane(Capability::Client(kj::mv(inner)), kj::mv(policy)) | ||||
|       .castAs<typename ServerType::Serves>(); | ||||
| } | ||||
| template <typename ServerType> | ||||
| typename ServerType::Serves::Client reverseMembrane( | ||||
|     kj::Own<ServerType> inner, kj::Own<MembranePolicy> policy) { | ||||
|   return reverseMembrane(Capability::Client(kj::mv(inner)), kj::mv(policy)) | ||||
|       .castAs<typename ServerType::Serves>(); | ||||
| } | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| OrphanBuilder copyOutOfMembrane(PointerReader from, Orphanage to, | ||||
|                                 kj::Own<MembranePolicy> policy, bool reverse); | ||||
| OrphanBuilder copyOutOfMembrane(StructReader from, Orphanage to, | ||||
|                                 kj::Own<MembranePolicy> policy, bool reverse); | ||||
| OrphanBuilder copyOutOfMembrane(ListReader from, Orphanage to, | ||||
|                                 kj::Own<MembranePolicy> policy, bool reverse); | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename Reader> | ||||
| Orphan<typename kj::Decay<Reader>::Reads> copyIntoMembrane( | ||||
|     Reader&& from, Orphanage to, kj::Own<MembranePolicy> policy) { | ||||
|   return _::copyOutOfMembrane( | ||||
|       _::PointerHelpers<typename kj::Decay<Reader>::Reads>::getInternalReader(from), | ||||
|       to, kj::mv(policy), true); | ||||
| } | ||||
| 
 | ||||
| template <typename Reader> | ||||
| Orphan<typename kj::Decay<Reader>::Reads> copyOutOfMembrane( | ||||
|     Reader&& from, Orphanage to, kj::Own<MembranePolicy> policy) { | ||||
|   return _::copyOutOfMembrane( | ||||
|       _::PointerHelpers<typename kj::Decay<Reader>::Reads>::getInternalReader(from), | ||||
|       to, kj::mv(policy), false); | ||||
| } | ||||
| 
 | ||||
| } // namespace capnp
 | ||||
| 
 | ||||
| #endif // CAPNP_MEMBRANE_H_
 | ||||
| @ -0,0 +1,508 @@ | ||||
| // Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #include <kj/common.h> | ||||
| #include <kj/memory.h> | ||||
| #include <kj/mutex.h> | ||||
| #include <kj/debug.h> | ||||
| #include "common.h" | ||||
| #include "layout.h" | ||||
| #include "any.h" | ||||
| 
 | ||||
| #ifndef CAPNP_MESSAGE_H_ | ||||
| #define CAPNP_MESSAGE_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
|   class ReaderArena; | ||||
|   class BuilderArena; | ||||
| } | ||||
| 
 | ||||
| class StructSchema; | ||||
| class Orphanage; | ||||
| template <typename T> | ||||
| class Orphan; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| struct ReaderOptions { | ||||
|   // Options controlling how data is read.
 | ||||
| 
 | ||||
|   uint64_t traversalLimitInWords = 8 * 1024 * 1024; | ||||
|   // Limits how many total words of data are allowed to be traversed.  Traversal is counted when
 | ||||
|   // a new struct or list builder is obtained, e.g. from a get() accessor.  This means that calling
 | ||||
|   // the getter for the same sub-struct multiple times will cause it to be double-counted.  Once
 | ||||
|   // the traversal limit is reached, an error will be reported.
 | ||||
|   //
 | ||||
|   // This limit exists for security reasons.  It is possible for an attacker to construct a message
 | ||||
|   // in which multiple pointers point at the same location.  This is technically invalid, but hard
 | ||||
|   // to detect.  Using such a message, an attacker could cause a message which is small on the wire
 | ||||
|   // to appear much larger when actually traversed, possibly exhausting server resources leading to
 | ||||
|   // denial-of-service.
 | ||||
|   //
 | ||||
|   // It makes sense to set a traversal limit that is much larger than the underlying message.
 | ||||
|   // Together with sensible coding practices (e.g. trying to avoid calling sub-object getters
 | ||||
|   // multiple times, which is expensive anyway), this should provide adequate protection without
 | ||||
|   // inconvenience.
 | ||||
|   //
 | ||||
|   // The default limit is 64 MiB.  This may or may not be a sensible number for any given use case,
 | ||||
|   // but probably at least prevents easy exploitation while also avoiding causing problems in most
 | ||||
|   // typical cases.
 | ||||
| 
 | ||||
|   int nestingLimit = 64; | ||||
|   // Limits how deeply-nested a message structure can be, e.g. structs containing other structs or
 | ||||
|   // lists of structs.
 | ||||
|   //
 | ||||
|   // Like the traversal limit, this limit exists for security reasons.  Since it is common to use
 | ||||
|   // recursive code to traverse recursive data structures, an attacker could easily cause a stack
 | ||||
|   // overflow by sending a very-deeply-nested (or even cyclic) message, without the message even
 | ||||
|   // being very large.  The default limit of 64 is probably low enough to prevent any chance of
 | ||||
|   // stack overflow, yet high enough that it is never a problem in practice.
 | ||||
| }; | ||||
| 
 | ||||
| class MessageReader { | ||||
|   // Abstract interface for an object used to read a Cap'n Proto message.  Subclasses of
 | ||||
|   // MessageReader are responsible for reading the raw, flat message content.  Callers should
 | ||||
|   // usually call `messageReader.getRoot<MyStructType>()` to get a `MyStructType::Reader`
 | ||||
|   // representing the root of the message, then use that to traverse the message content.
 | ||||
|   //
 | ||||
|   // Some common subclasses of `MessageReader` include `SegmentArrayMessageReader`, whose
 | ||||
|   // constructor accepts pointers to the raw data, and `StreamFdMessageReader` (from
 | ||||
|   // `serialize.h`), which reads the message from a file descriptor.  One might implement other
 | ||||
|   // subclasses to handle things like reading from shared memory segments, mmap()ed files, etc.
 | ||||
| 
 | ||||
| public: | ||||
|   MessageReader(ReaderOptions options); | ||||
|   // It is suggested that subclasses take ReaderOptions as a constructor parameter, but give it a
 | ||||
|   // default value of "ReaderOptions()".  The base class constructor doesn't have a default value
 | ||||
|   // in order to remind subclasses that they really need to give the user a way to provide this.
 | ||||
| 
 | ||||
|   virtual ~MessageReader() noexcept(false); | ||||
| 
 | ||||
|   virtual kj::ArrayPtr<const word> getSegment(uint id) = 0; | ||||
|   // Gets the segment with the given ID, or returns null if no such segment exists. This method
 | ||||
|   // will be called at most once for each segment ID.
 | ||||
| 
 | ||||
|   inline const ReaderOptions& getOptions(); | ||||
|   // Get the options passed to the constructor.
 | ||||
| 
 | ||||
|   template <typename RootType> | ||||
|   typename RootType::Reader getRoot(); | ||||
|   // Get the root struct of the message, interpreting it as the given struct type.
 | ||||
| 
 | ||||
|   template <typename RootType, typename SchemaType> | ||||
|   typename RootType::Reader getRoot(SchemaType schema); | ||||
|   // Dynamically interpret the root struct of the message using the given schema (a StructSchema).
 | ||||
|   // RootType in this case must be DynamicStruct, and you must #include <capnp/dynamic.h> to
 | ||||
|   // use this.
 | ||||
| 
 | ||||
|   bool isCanonical(); | ||||
|   // Returns whether the message encoded in the reader is in canonical form.
 | ||||
| 
 | ||||
| private: | ||||
|   ReaderOptions options; | ||||
| 
 | ||||
|   // Space in which we can construct a ReaderArena.  We don't use ReaderArena directly here
 | ||||
|   // because we don't want clients to have to #include arena.h, which itself includes a bunch of
 | ||||
|   // big STL headers.  We don't use a pointer to a ReaderArena because that would require an
 | ||||
|   // extra malloc on every message which could be expensive when processing small messages.
 | ||||
|   void* arenaSpace[15 + sizeof(kj::MutexGuarded<void*>) / sizeof(void*)]; | ||||
|   bool allocatedArena; | ||||
| 
 | ||||
|   _::ReaderArena* arena() { return reinterpret_cast<_::ReaderArena*>(arenaSpace); } | ||||
|   AnyPointer::Reader getRootInternal(); | ||||
| }; | ||||
| 
 | ||||
| class MessageBuilder { | ||||
|   // Abstract interface for an object used to allocate and build a message.  Subclasses of
 | ||||
|   // MessageBuilder are responsible for allocating the space in which the message will be written.
 | ||||
|   // The most common subclass is `MallocMessageBuilder`, but other subclasses may be used to do
 | ||||
|   // tricky things like allocate messages in shared memory or mmap()ed files.
 | ||||
|   //
 | ||||
|   // Creating a new message ususually means allocating a new MessageBuilder (ideally on the stack)
 | ||||
|   // and then calling `messageBuilder.initRoot<MyStructType>()` to get a `MyStructType::Builder`.
 | ||||
|   // That, in turn, can be used to fill in the message content.  When done, you can call
 | ||||
|   // `messageBuilder.getSegmentsForOutput()` to get a list of flat data arrays containing the
 | ||||
|   // message.
 | ||||
| 
 | ||||
| public: | ||||
|   MessageBuilder(); | ||||
|   virtual ~MessageBuilder() noexcept(false); | ||||
|   KJ_DISALLOW_COPY(MessageBuilder); | ||||
| 
 | ||||
|   struct SegmentInit { | ||||
|     kj::ArrayPtr<word> space; | ||||
| 
 | ||||
|     size_t wordsUsed; | ||||
|     // Number of words in `space` which are used; the rest are free space in which additional
 | ||||
|     // objects may be allocated.
 | ||||
|   }; | ||||
| 
 | ||||
|   explicit MessageBuilder(kj::ArrayPtr<SegmentInit> segments); | ||||
|   // Create a MessageBuilder backed by existing memory. This is an advanced interface that most
 | ||||
|   // people should not use. THIS METHOD IS INSECURE; see below.
 | ||||
|   //
 | ||||
|   // This allows a MessageBuilder to be constructed to modify an in-memory message without first
 | ||||
|   // making a copy of the content. This is especially useful in conjunction with mmap().
 | ||||
|   //
 | ||||
|   // The contents of each segment must outlive the MessageBuilder, but the SegmentInit array itself
 | ||||
|   // only need outlive the constructor.
 | ||||
|   //
 | ||||
|   // SECURITY: Do not use this in conjunction with untrusted data. This constructor assumes that
 | ||||
|   //   the input message is valid. This constructor is designed to be used with data you control,
 | ||||
|   //   e.g. an mmap'd file which is owned and accessed by only one program. When reading data you
 | ||||
|   //   do not trust, you *must* load it into a Reader and then copy into a Builder as a means of
 | ||||
|   //   validating the content.
 | ||||
|   //
 | ||||
|   // WARNING: It is NOT safe to initialize a MessageBuilder in this way from memory that is
 | ||||
|   //   currently in use by another MessageBuilder or MessageReader. Other readers/builders will
 | ||||
|   //   not observe changes to the segment sizes nor newly-allocated segments caused by allocating
 | ||||
|   //   new objects in this message.
 | ||||
| 
 | ||||
|   virtual kj::ArrayPtr<word> allocateSegment(uint minimumSize) = 0; | ||||
|   // Allocates an array of at least the given number of words, throwing an exception or crashing if
 | ||||
|   // this is not possible.  It is expected that this method will usually return more space than
 | ||||
|   // requested, and the caller should use that extra space as much as possible before allocating
 | ||||
|   // more.  The returned space remains valid at least until the MessageBuilder is destroyed.
 | ||||
|   //
 | ||||
|   // Cap'n Proto will only call this once at a time, so the subclass need not worry about
 | ||||
|   // thread-safety.
 | ||||
| 
 | ||||
|   template <typename RootType> | ||||
|   typename RootType::Builder initRoot(); | ||||
|   // Initialize the root struct of the message as the given struct type.
 | ||||
| 
 | ||||
|   template <typename Reader> | ||||
|   void setRoot(Reader&& value); | ||||
|   // Set the root struct to a deep copy of the given struct.
 | ||||
| 
 | ||||
|   template <typename RootType> | ||||
|   typename RootType::Builder getRoot(); | ||||
|   // Get the root struct of the message, interpreting it as the given struct type.
 | ||||
| 
 | ||||
|   template <typename RootType, typename SchemaType> | ||||
|   typename RootType::Builder getRoot(SchemaType schema); | ||||
|   // Dynamically interpret the root struct of the message using the given schema (a StructSchema).
 | ||||
|   // RootType in this case must be DynamicStruct, and you must #include <capnp/dynamic.h> to
 | ||||
|   // use this.
 | ||||
| 
 | ||||
|   template <typename RootType, typename SchemaType> | ||||
|   typename RootType::Builder initRoot(SchemaType schema); | ||||
|   // Dynamically init the root struct of the message using the given schema (a StructSchema).
 | ||||
|   // RootType in this case must be DynamicStruct, and you must #include <capnp/dynamic.h> to
 | ||||
|   // use this.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   void adoptRoot(Orphan<T>&& orphan); | ||||
|   // Like setRoot() but adopts the orphan without copying.
 | ||||
| 
 | ||||
|   kj::ArrayPtr<const kj::ArrayPtr<const word>> getSegmentsForOutput(); | ||||
|   // Get the raw data that makes up the message.
 | ||||
| 
 | ||||
|   Orphanage getOrphanage(); | ||||
| 
 | ||||
|   bool isCanonical(); | ||||
|   // Check whether the message builder is in canonical form
 | ||||
| 
 | ||||
| private: | ||||
|   void* arenaSpace[22]; | ||||
|   // Space in which we can construct a BuilderArena.  We don't use BuilderArena directly here
 | ||||
|   // because we don't want clients to have to #include arena.h, which itself includes a bunch of
 | ||||
|   // big STL headers.  We don't use a pointer to a BuilderArena because that would require an
 | ||||
|   // extra malloc on every message which could be expensive when processing small messages.
 | ||||
| 
 | ||||
|   bool allocatedArena = false; | ||||
|   // We have to initialize the arena lazily because when we do so we want to allocate the root
 | ||||
|   // pointer immediately, and this will allocate a segment, which requires a virtual function
 | ||||
|   // call on the MessageBuilder.  We can't do such a call in the constructor since the subclass
 | ||||
|   // isn't constructed yet.  This is kind of annoying because it means that getOrphanage() is
 | ||||
|   // not thread-safe, but that shouldn't be a huge deal...
 | ||||
| 
 | ||||
|   _::BuilderArena* arena() { return reinterpret_cast<_::BuilderArena*>(arenaSpace); } | ||||
|   _::SegmentBuilder* getRootSegment(); | ||||
|   AnyPointer::Builder getRootInternal(); | ||||
| }; | ||||
| 
 | ||||
| template <typename RootType> | ||||
| typename RootType::Reader readMessageUnchecked(const word* data); | ||||
| // IF THE INPUT IS INVALID, THIS MAY CRASH, CORRUPT MEMORY, CREATE A SECURITY HOLE IN YOUR APP,
 | ||||
| // MURDER YOUR FIRST-BORN CHILD, AND/OR BRING ABOUT ETERNAL DAMNATION ON ALL OF HUMANITY.  DO NOT
 | ||||
| // USE UNLESS YOU UNDERSTAND THE CONSEQUENCES.
 | ||||
| //
 | ||||
| // Given a pointer to a known-valid message located in a single contiguous memory segment,
 | ||||
| // returns a reader for that message.  No bounds-checking will be done while traversing this
 | ||||
| // message.  Use this only if you have already verified that all pointers are valid and in-bounds,
 | ||||
| // and there are no far pointers in the message.
 | ||||
| //
 | ||||
| // To create a message that can be passed to this function, build a message using a MallocAllocator
 | ||||
| // whose preferred segment size is larger than the message size.  This guarantees that the message
 | ||||
| // will be allocated as a single segment, meaning getSegmentsForOutput() returns a single word
 | ||||
| // array.  That word array is your message; you may pass a pointer to its first word into
 | ||||
| // readMessageUnchecked() to read the message.
 | ||||
| //
 | ||||
| // This can be particularly handy for embedding messages in generated code:  you can
 | ||||
| // embed the raw bytes (using AlignedData) then make a Reader for it using this.  This is the way
 | ||||
| // default values are embedded in code generated by the Cap'n Proto compiler.  E.g., if you have
 | ||||
| // a message MyMessage, you can read its default value like so:
 | ||||
| //    MyMessage::Reader reader = Message<MyMessage>::readMessageUnchecked(MyMessage::DEFAULT.words);
 | ||||
| //
 | ||||
| // To sanitize a message from an untrusted source such that it can be safely passed to
 | ||||
| // readMessageUnchecked(), use copyToUnchecked().
 | ||||
| 
 | ||||
| template <typename Reader> | ||||
| void copyToUnchecked(Reader&& reader, kj::ArrayPtr<word> uncheckedBuffer); | ||||
| // Copy the content of the given reader into the given buffer, such that it can safely be passed to
 | ||||
| // readMessageUnchecked().  The buffer's size must be exactly reader.totalSizeInWords() + 1,
 | ||||
| // otherwise an exception will be thrown.  The buffer must be zero'd before calling.
 | ||||
| 
 | ||||
| template <typename RootType> | ||||
| typename RootType::Reader readDataStruct(kj::ArrayPtr<const word> data); | ||||
| // Interprets the given data as a single, data-only struct. Only primitive fields (booleans,
 | ||||
| // numbers, and enums) will be readable; all pointers will be null. This is useful if you want
 | ||||
| // to use Cap'n Proto as a language/platform-neutral way to pack some bits.
 | ||||
| //
 | ||||
| // The input is a word array rather than a byte array to enforce alignment. If you have a byte
 | ||||
| // array which you know is word-aligned (or if your platform supports unaligned reads and you don't
 | ||||
| // mind the performance penalty), then you can use `reinterpret_cast` to convert a byte array into
 | ||||
| // a word array:
 | ||||
| //
 | ||||
| //     kj::arrayPtr(reinterpret_cast<const word*>(bytes.begin()),
 | ||||
| //                  reinterpret_cast<const word*>(bytes.end()))
 | ||||
| 
 | ||||
| template <typename BuilderType> | ||||
| typename kj::ArrayPtr<const word> writeDataStruct(BuilderType builder); | ||||
| // Given a struct builder, get the underlying data section as a word array, suitable for passing
 | ||||
| // to `readDataStruct()`.
 | ||||
| //
 | ||||
| // Note that you may call `.toBytes()` on the returned value to convert to `ArrayPtr<const byte>`.
 | ||||
| 
 | ||||
| template <typename Type> | ||||
| static typename Type::Reader defaultValue(); | ||||
| // Get a default instance of the given struct or list type.
 | ||||
| //
 | ||||
| // TODO(cleanup):  Find a better home for this function?
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| class SegmentArrayMessageReader: public MessageReader { | ||||
|   // A simple MessageReader that reads from an array of word arrays representing all segments.
 | ||||
|   // In particular you can read directly from the output of MessageBuilder::getSegmentsForOutput()
 | ||||
|   // (although it would probably make more sense to call builder.getRoot().asReader() in that case).
 | ||||
| 
 | ||||
| public: | ||||
|   SegmentArrayMessageReader(kj::ArrayPtr<const kj::ArrayPtr<const word>> segments, | ||||
|                             ReaderOptions options = ReaderOptions()); | ||||
|   // Creates a message pointing at the given segment array, without taking ownership of the
 | ||||
|   // segments.  All arrays passed in must remain valid until the MessageReader is destroyed.
 | ||||
| 
 | ||||
|   KJ_DISALLOW_COPY(SegmentArrayMessageReader); | ||||
|   ~SegmentArrayMessageReader() noexcept(false); | ||||
| 
 | ||||
|   virtual kj::ArrayPtr<const word> getSegment(uint id) override; | ||||
| 
 | ||||
| private: | ||||
|   kj::ArrayPtr<const kj::ArrayPtr<const word>> segments; | ||||
| }; | ||||
| 
 | ||||
| enum class AllocationStrategy: uint8_t { | ||||
|   FIXED_SIZE, | ||||
|   // The builder will prefer to allocate the same amount of space for each segment with no
 | ||||
|   // heuristic growth.  It will still allocate larger segments when the preferred size is too small
 | ||||
|   // for some single object.  This mode is generally not recommended, but can be particularly useful
 | ||||
|   // for testing in order to force a message to allocate a predictable number of segments.  Note
 | ||||
|   // that you can force every single object in the message to be located in a separate segment by
 | ||||
|   // using this mode with firstSegmentWords = 0.
 | ||||
| 
 | ||||
|   GROW_HEURISTICALLY | ||||
|   // The builder will heuristically decide how much space to allocate for each segment.  Each
 | ||||
|   // allocated segment will be progressively larger than the previous segments on the assumption
 | ||||
|   // that message sizes are exponentially distributed.  The total number of segments that will be
 | ||||
|   // allocated for a message of size n is O(log n).
 | ||||
| }; | ||||
| 
 | ||||
| constexpr uint SUGGESTED_FIRST_SEGMENT_WORDS = 1024; | ||||
| constexpr AllocationStrategy SUGGESTED_ALLOCATION_STRATEGY = AllocationStrategy::GROW_HEURISTICALLY; | ||||
| 
 | ||||
| class MallocMessageBuilder: public MessageBuilder { | ||||
|   // A simple MessageBuilder that uses malloc() (actually, calloc()) to allocate segments.  This
 | ||||
|   // implementation should be reasonable for any case that doesn't require writing the message to
 | ||||
|   // a specific location in memory.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit MallocMessageBuilder(uint firstSegmentWords = SUGGESTED_FIRST_SEGMENT_WORDS, | ||||
|       AllocationStrategy allocationStrategy = SUGGESTED_ALLOCATION_STRATEGY); | ||||
|   // Creates a BuilderContext which allocates at least the given number of words for the first
 | ||||
|   // segment, and then uses the given strategy to decide how much to allocate for subsequent
 | ||||
|   // segments.  When choosing a value for firstSegmentWords, consider that:
 | ||||
|   // 1) Reading and writing messages gets slower when multiple segments are involved, so it's good
 | ||||
|   //    if most messages fit in a single segment.
 | ||||
|   // 2) Unused bytes will not be written to the wire, so generally it is not a big deal to allocate
 | ||||
|   //    more space than you need.  It only becomes problematic if you are allocating many messages
 | ||||
|   //    in parallel and thus use lots of memory, or if you allocate so much extra space that just
 | ||||
|   //    zeroing it out becomes a bottleneck.
 | ||||
|   // The defaults have been chosen to be reasonable for most people, so don't change them unless you
 | ||||
|   // have reason to believe you need to.
 | ||||
| 
 | ||||
|   explicit MallocMessageBuilder(kj::ArrayPtr<word> firstSegment, | ||||
|       AllocationStrategy allocationStrategy = SUGGESTED_ALLOCATION_STRATEGY); | ||||
|   // This version always returns the given array for the first segment, and then proceeds with the
 | ||||
|   // allocation strategy.  This is useful for optimization when building lots of small messages in
 | ||||
|   // a tight loop:  you can reuse the space for the first segment.
 | ||||
|   //
 | ||||
|   // firstSegment MUST be zero-initialized.  MallocMessageBuilder's destructor will write new zeros
 | ||||
|   // over any space that was used so that it can be reused.
 | ||||
| 
 | ||||
|   KJ_DISALLOW_COPY(MallocMessageBuilder); | ||||
|   virtual ~MallocMessageBuilder() noexcept(false); | ||||
| 
 | ||||
|   virtual kj::ArrayPtr<word> allocateSegment(uint minimumSize) override; | ||||
| 
 | ||||
| private: | ||||
|   uint nextSize; | ||||
|   AllocationStrategy allocationStrategy; | ||||
| 
 | ||||
|   bool ownFirstSegment; | ||||
|   bool returnedFirstSegment; | ||||
| 
 | ||||
|   void* firstSegment; | ||||
| 
 | ||||
|   struct MoreSegments; | ||||
|   kj::Maybe<kj::Own<MoreSegments>> moreSegments; | ||||
| }; | ||||
| 
 | ||||
| class FlatMessageBuilder: public MessageBuilder { | ||||
|   // THIS IS NOT THE CLASS YOU'RE LOOKING FOR.
 | ||||
|   //
 | ||||
|   // If you want to write a message into already-existing scratch space, use `MallocMessageBuilder`
 | ||||
|   // and pass the scratch space to its constructor.  It will then only fall back to malloc() if
 | ||||
|   // the scratch space is not large enough.
 | ||||
|   //
 | ||||
|   // Do NOT use this class unless you really know what you're doing.  This class is problematic
 | ||||
|   // because it requires advance knowledge of the size of your message, which is usually impossible
 | ||||
|   // to determine without actually building the message.  The class was created primarily to
 | ||||
|   // implement `copyToUnchecked()`, which itself exists only to support other internal parts of
 | ||||
|   // the Cap'n Proto implementation.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit FlatMessageBuilder(kj::ArrayPtr<word> array); | ||||
|   KJ_DISALLOW_COPY(FlatMessageBuilder); | ||||
|   virtual ~FlatMessageBuilder() noexcept(false); | ||||
| 
 | ||||
|   void requireFilled(); | ||||
|   // Throws an exception if the flat array is not exactly full.
 | ||||
| 
 | ||||
|   virtual kj::ArrayPtr<word> allocateSegment(uint minimumSize) override; | ||||
| 
 | ||||
| private: | ||||
|   kj::ArrayPtr<word> array; | ||||
|   bool allocated; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // implementation details
 | ||||
| 
 | ||||
| inline const ReaderOptions& MessageReader::getOptions() { | ||||
|   return options; | ||||
| } | ||||
| 
 | ||||
| template <typename RootType> | ||||
| inline typename RootType::Reader MessageReader::getRoot() { | ||||
|   return getRootInternal().getAs<RootType>(); | ||||
| } | ||||
| 
 | ||||
| template <typename RootType> | ||||
| inline typename RootType::Builder MessageBuilder::initRoot() { | ||||
|   return getRootInternal().initAs<RootType>(); | ||||
| } | ||||
| 
 | ||||
| template <typename Reader> | ||||
| inline void MessageBuilder::setRoot(Reader&& value) { | ||||
|   getRootInternal().setAs<FromReader<Reader>>(value); | ||||
| } | ||||
| 
 | ||||
| template <typename RootType> | ||||
| inline typename RootType::Builder MessageBuilder::getRoot() { | ||||
|   return getRootInternal().getAs<RootType>(); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| void MessageBuilder::adoptRoot(Orphan<T>&& orphan) { | ||||
|   return getRootInternal().adopt(kj::mv(orphan)); | ||||
| } | ||||
| 
 | ||||
| template <typename RootType, typename SchemaType> | ||||
| typename RootType::Reader MessageReader::getRoot(SchemaType schema) { | ||||
|   return getRootInternal().getAs<RootType>(schema); | ||||
| } | ||||
| 
 | ||||
| template <typename RootType, typename SchemaType> | ||||
| typename RootType::Builder MessageBuilder::getRoot(SchemaType schema) { | ||||
|   return getRootInternal().getAs<RootType>(schema); | ||||
| } | ||||
| 
 | ||||
| template <typename RootType, typename SchemaType> | ||||
| typename RootType::Builder MessageBuilder::initRoot(SchemaType schema) { | ||||
|   return getRootInternal().initAs<RootType>(schema); | ||||
| } | ||||
| 
 | ||||
| template <typename RootType> | ||||
| typename RootType::Reader readMessageUnchecked(const word* data) { | ||||
|   return AnyPointer::Reader(_::PointerReader::getRootUnchecked(data)).getAs<RootType>(); | ||||
| } | ||||
| 
 | ||||
| template <typename Reader> | ||||
| void copyToUnchecked(Reader&& reader, kj::ArrayPtr<word> uncheckedBuffer) { | ||||
|   FlatMessageBuilder builder(uncheckedBuffer); | ||||
|   builder.setRoot(kj::fwd<Reader>(reader)); | ||||
|   builder.requireFilled(); | ||||
| } | ||||
| 
 | ||||
| template <typename RootType> | ||||
| typename RootType::Reader readDataStruct(kj::ArrayPtr<const word> data) { | ||||
|   return typename RootType::Reader(_::StructReader(data)); | ||||
| } | ||||
| 
 | ||||
| template <typename BuilderType> | ||||
| typename kj::ArrayPtr<const word> writeDataStruct(BuilderType builder) { | ||||
|   auto bytes = _::PointerHelpers<FromBuilder<BuilderType>>::getInternalBuilder(kj::mv(builder)) | ||||
|       .getDataSectionAsBlob(); | ||||
|   return kj::arrayPtr(reinterpret_cast<word*>(bytes.begin()), | ||||
|                       reinterpret_cast<word*>(bytes.end())); | ||||
| } | ||||
| 
 | ||||
| template <typename Type> | ||||
| static typename Type::Reader defaultValue() { | ||||
|   return typename Type::Reader(_::StructReader()); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| kj::Array<word> canonicalize(T&& reader) { | ||||
|     return _::PointerHelpers<FromReader<T>>::getInternalReader(reader).canonicalize(); | ||||
| } | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_MESSAGE_H_
 | ||||
| @ -0,0 +1,440 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_ORPHAN_H_ | ||||
| #define CAPNP_ORPHAN_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "layout.h" | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| class StructSchema; | ||||
| class ListSchema; | ||||
| struct DynamicStruct; | ||||
| struct DynamicList; | ||||
| namespace _ { struct OrphanageInternal; } | ||||
| 
 | ||||
| template <typename T> | ||||
| class Orphan { | ||||
|   // Represents an object which is allocated within some message builder but has no pointers
 | ||||
|   // pointing at it.  An Orphan can later be "adopted" by some other object as one of that object's
 | ||||
|   // fields, without having to copy the orphan.  For a field `foo` of pointer type, the generated
 | ||||
|   // code will define builder methods `void adoptFoo(Orphan<T>)` and `Orphan<T> disownFoo()`.
 | ||||
|   // Orphans can also be created independently of any parent using an Orphanage.
 | ||||
|   //
 | ||||
|   // `Orphan<T>` can be moved but not copied, like `Own<T>`, so that it is impossible for one
 | ||||
|   // orphan to be adopted multiple times.  If an orphan is destroyed without being adopted, its
 | ||||
|   // contents are zero'd out (and possibly reused, if we ever implement the ability to reuse space
 | ||||
|   // in a message arena).
 | ||||
| 
 | ||||
| public: | ||||
|   Orphan() = default; | ||||
|   KJ_DISALLOW_COPY(Orphan); | ||||
|   Orphan(Orphan&&) = default; | ||||
|   Orphan& operator=(Orphan&&) = default; | ||||
|   inline Orphan(_::OrphanBuilder&& builder): builder(kj::mv(builder)) {} | ||||
| 
 | ||||
|   inline BuilderFor<T> get(); | ||||
|   // Get the underlying builder.  If the orphan is null, this will allocate and return a default
 | ||||
|   // object rather than crash.  This is done for security -- otherwise, you might enable a DoS
 | ||||
|   // attack any time you disown a field and fail to check if it is null.  In the case of structs,
 | ||||
|   // this means that the orphan is no longer null after get() returns.  In the case of lists,
 | ||||
|   // no actual object is allocated since a simple empty ListBuilder can be returned.
 | ||||
| 
 | ||||
|   inline ReaderFor<T> getReader() const; | ||||
| 
 | ||||
|   inline bool operator==(decltype(nullptr)) const { return builder == nullptr; } | ||||
|   inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; } | ||||
| 
 | ||||
|   inline void truncate(uint size); | ||||
|   // Resize an object (which must be a list or a blob) to the given size.
 | ||||
|   //
 | ||||
|   // If the new size is less than the original, the remaining elements will be discarded. The
 | ||||
|   // list is never moved in this case. If the list happens to be located at the end of its segment
 | ||||
|   // (which is always true if the list was the last thing allocated), the removed memory will be
 | ||||
|   // reclaimed (reducing the messag size), otherwise it is simply zeroed. The reclaiming behavior
 | ||||
|   // is particularly useful for allocating buffer space when you aren't sure how much space you
 | ||||
|   // actually need: you can pre-allocate, say, a 4k byte array, read() from a file into it, and
 | ||||
|   // then truncate it back to the amount of space actually used.
 | ||||
|   //
 | ||||
|   // If the new size is greater than the original, the list is extended with default values. If
 | ||||
|   // the list is the last object in its segment *and* there is enough space left in the segment to
 | ||||
|   // extend it to cover the new values, then the list is extended in-place. Otherwise, it must be
 | ||||
|   // moved to a new location, leaving a zero'd hole in the previous space that won't be filled.
 | ||||
|   // This copy is shallow; sub-objects will simply be reparented, not copied.
 | ||||
|   //
 | ||||
|   // Any existing readers or builders pointing at the object are invalidated by this call (even if
 | ||||
|   // it doesn't move). You must call `get()` or `getReader()` again to get the new, valid pointer.
 | ||||
| 
 | ||||
| private: | ||||
|   _::OrphanBuilder builder; | ||||
| 
 | ||||
|   template <typename, Kind> | ||||
|   friend struct _::PointerHelpers; | ||||
|   template <typename, Kind> | ||||
|   friend struct List; | ||||
|   template <typename U> | ||||
|   friend class Orphan; | ||||
|   friend class Orphanage; | ||||
|   friend class MessageBuilder; | ||||
| }; | ||||
| 
 | ||||
| class Orphanage: private kj::DisallowConstCopy { | ||||
|   // Use to directly allocate Orphan objects, without having a parent object allocate and then
 | ||||
|   // disown the object.
 | ||||
| 
 | ||||
| public: | ||||
|   inline Orphanage(): arena(nullptr) {} | ||||
| 
 | ||||
|   template <typename BuilderType> | ||||
|   static Orphanage getForMessageContaining(BuilderType builder); | ||||
|   // Construct an Orphanage that allocates within the message containing the given Builder.  This
 | ||||
|   // allows the constructed Orphans to be adopted by objects within said message.
 | ||||
|   //
 | ||||
|   // This constructor takes the builder rather than having the builder have a getOrphanage() method
 | ||||
|   // because this is an advanced feature and we don't want to pollute the builder APIs with it.
 | ||||
|   //
 | ||||
|   // Note that if you have a direct pointer to the `MessageBuilder`, you can simply call its
 | ||||
|   // `getOrphanage()` method.
 | ||||
| 
 | ||||
|   template <typename RootType> | ||||
|   Orphan<RootType> newOrphan() const; | ||||
|   // Allocate a new orphaned struct.
 | ||||
| 
 | ||||
|   template <typename RootType> | ||||
|   Orphan<RootType> newOrphan(uint size) const; | ||||
|   // Allocate a new orphaned list or blob.
 | ||||
| 
 | ||||
|   Orphan<DynamicStruct> newOrphan(StructSchema schema) const; | ||||
|   // Dynamically create an orphan struct with the given schema.  You must
 | ||||
|   // #include <capnp/dynamic.h> to use this.
 | ||||
| 
 | ||||
|   Orphan<DynamicList> newOrphan(ListSchema schema, uint size) const; | ||||
|   // Dynamically create an orphan list with the given schema.  You must #include <capnp/dynamic.h>
 | ||||
|   // to use this.
 | ||||
| 
 | ||||
|   template <typename Reader> | ||||
|   Orphan<FromReader<Reader>> newOrphanCopy(Reader copyFrom) const; | ||||
|   // Allocate a new orphaned object (struct, list, or blob) and initialize it as a copy of the
 | ||||
|   // given object.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   Orphan<List<ListElementType<FromReader<T>>>> newOrphanConcat(kj::ArrayPtr<T> lists) const; | ||||
|   template <typename T> | ||||
|   Orphan<List<ListElementType<FromReader<T>>>> newOrphanConcat(kj::ArrayPtr<const T> lists) const; | ||||
|   // Given an array of List readers, copy and concatenate the lists, creating a new Orphan.
 | ||||
|   //
 | ||||
|   // Note that compared to allocating the list yourself and using `setWithCaveats()` to set each
 | ||||
|   // item, this method avoids the "caveats": the new list will be allocated with the element size
 | ||||
|   // being the maximum of that from all the input lists. This is particularly important when
 | ||||
|   // concatenating struct lists: if the lists were created using a newer version of the protocol
 | ||||
|   // in which some new fields had been added to the struct, using `setWithCaveats()` would
 | ||||
|   // truncate off those new fields.
 | ||||
| 
 | ||||
|   Orphan<Data> referenceExternalData(Data::Reader data) const; | ||||
|   // Creates an Orphan<Data> that points at an existing region of memory (e.g. from another message)
 | ||||
|   // without copying it.  There are some SEVERE restrictions on how this can be used:
 | ||||
|   // - The memory must remain valid until the `MessageBuilder` is destroyed (even if the orphan is
 | ||||
|   //   abandoned).
 | ||||
|   // - Because the data is const, you will not be allowed to obtain a `Data::Builder`
 | ||||
|   //   for this blob.  Any call which would return such a builder will throw an exception.  You
 | ||||
|   //   can, however, obtain a Reader, e.g. via orphan.getReader() or from a parent Reader (once
 | ||||
|   //   the orphan is adopted).  It is your responsibility to make sure your code can deal with
 | ||||
|   //   these problems when using this optimization; if you can't, allocate a copy instead.
 | ||||
|   // - `data.begin()` must be aligned to a machine word boundary (32-bit or 64-bit depending on
 | ||||
|   //   the CPU).  Any pointer returned by malloc() as well as any data blob obtained from another
 | ||||
|   //   Cap'n Proto message satisfies this.
 | ||||
|   // - If `data.size()` is not a multiple of 8, extra bytes past data.end() up until the next 8-byte
 | ||||
|   //   boundary will be visible in the raw message when it is written out.  Thus, there must be no
 | ||||
|   //   secrets in these bytes.  Data blobs obtained from other Cap'n Proto messages should be safe
 | ||||
|   //   as these bytes should be zero (unless the sender had the same problem).
 | ||||
|   //
 | ||||
|   // The array will actually become one of the message's segments.  The data can thus be adopted
 | ||||
|   // into the message tree without copying it.  This is particularly useful when referencing very
 | ||||
|   // large blobs, such as whole mmap'd files.
 | ||||
| 
 | ||||
| private: | ||||
|   _::BuilderArena* arena; | ||||
|   _::CapTableBuilder* capTable; | ||||
| 
 | ||||
|   inline explicit Orphanage(_::BuilderArena* arena, _::CapTableBuilder* capTable) | ||||
|       : arena(arena), capTable(capTable) {} | ||||
| 
 | ||||
|   template <typename T, Kind = CAPNP_KIND(T)> | ||||
|   struct GetInnerBuilder; | ||||
|   template <typename T, Kind = CAPNP_KIND(T)> | ||||
|   struct GetInnerReader; | ||||
|   template <typename T> | ||||
|   struct NewOrphanListImpl; | ||||
| 
 | ||||
|   friend class MessageBuilder; | ||||
|   friend struct _::OrphanageInternal; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Inline implementation details.
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T, Kind = CAPNP_KIND(T)> | ||||
| struct OrphanGetImpl; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct OrphanGetImpl<T, Kind::PRIMITIVE> { | ||||
|   static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { | ||||
|     builder.truncate(size, _::elementSizeForType<T>()); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct OrphanGetImpl<T, Kind::STRUCT> { | ||||
|   static inline typename T::Builder apply(_::OrphanBuilder& builder) { | ||||
|     return typename T::Builder(builder.asStruct(_::structSize<T>())); | ||||
|   } | ||||
|   static inline typename T::Reader applyReader(const _::OrphanBuilder& builder) { | ||||
|     return typename T::Reader(builder.asStructReader(_::structSize<T>())); | ||||
|   } | ||||
|   static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { | ||||
|     builder.truncate(size, _::structSize<T>()); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
| template <typename T> | ||||
| struct OrphanGetImpl<T, Kind::INTERFACE> { | ||||
|   static inline typename T::Client apply(_::OrphanBuilder& builder) { | ||||
|     return typename T::Client(builder.asCapability()); | ||||
|   } | ||||
|   static inline typename T::Client applyReader(const _::OrphanBuilder& builder) { | ||||
|     return typename T::Client(builder.asCapability()); | ||||
|   } | ||||
|   static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { | ||||
|     builder.truncate(size, ElementSize::POINTER); | ||||
|   } | ||||
| }; | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| template <typename T, Kind k> | ||||
| struct OrphanGetImpl<List<T, k>, Kind::LIST> { | ||||
|   static inline typename List<T>::Builder apply(_::OrphanBuilder& builder) { | ||||
|     return typename List<T>::Builder(builder.asList(_::ElementSizeForType<T>::value)); | ||||
|   } | ||||
|   static inline typename List<T>::Reader applyReader(const _::OrphanBuilder& builder) { | ||||
|     return typename List<T>::Reader(builder.asListReader(_::ElementSizeForType<T>::value)); | ||||
|   } | ||||
|   static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { | ||||
|     builder.truncate(size, ElementSize::POINTER); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct OrphanGetImpl<List<T, Kind::STRUCT>, Kind::LIST> { | ||||
|   static inline typename List<T>::Builder apply(_::OrphanBuilder& builder) { | ||||
|     return typename List<T>::Builder(builder.asStructList(_::structSize<T>())); | ||||
|   } | ||||
|   static inline typename List<T>::Reader applyReader(const _::OrphanBuilder& builder) { | ||||
|     return typename List<T>::Reader(builder.asListReader(_::ElementSizeForType<T>::value)); | ||||
|   } | ||||
|   static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { | ||||
|     builder.truncate(size, ElementSize::POINTER); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| struct OrphanGetImpl<Text, Kind::BLOB> { | ||||
|   static inline Text::Builder apply(_::OrphanBuilder& builder) { | ||||
|     return Text::Builder(builder.asText()); | ||||
|   } | ||||
|   static inline Text::Reader applyReader(const _::OrphanBuilder& builder) { | ||||
|     return Text::Reader(builder.asTextReader()); | ||||
|   } | ||||
|   static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { | ||||
|     builder.truncate(size, ElementSize::POINTER); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| struct OrphanGetImpl<Data, Kind::BLOB> { | ||||
|   static inline Data::Builder apply(_::OrphanBuilder& builder) { | ||||
|     return Data::Builder(builder.asData()); | ||||
|   } | ||||
|   static inline Data::Reader applyReader(const _::OrphanBuilder& builder) { | ||||
|     return Data::Reader(builder.asDataReader()); | ||||
|   } | ||||
|   static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { | ||||
|     builder.truncate(size, ElementSize::POINTER); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| struct OrphanageInternal { | ||||
|   static inline _::BuilderArena* getArena(Orphanage orphanage) { return orphanage.arena; } | ||||
|   static inline _::CapTableBuilder* getCapTable(Orphanage orphanage) { return orphanage.capTable; } | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename T> | ||||
| inline BuilderFor<T> Orphan<T>::get() { | ||||
|   return _::OrphanGetImpl<T>::apply(builder); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline ReaderFor<T> Orphan<T>::getReader() const { | ||||
|   return _::OrphanGetImpl<T>::applyReader(builder); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline void Orphan<T>::truncate(uint size) { | ||||
|   _::OrphanGetImpl<ListElementType<T>>::truncateListOf(builder, bounded(size) * ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| template <> | ||||
| inline void Orphan<Text>::truncate(uint size) { | ||||
|   builder.truncateText(bounded(size) * ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| template <> | ||||
| inline void Orphan<Data>::truncate(uint size) { | ||||
|   builder.truncate(bounded(size) * ELEMENTS, ElementSize::BYTE); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| struct Orphanage::GetInnerBuilder<T, Kind::STRUCT> { | ||||
|   static inline _::StructBuilder apply(typename T::Builder& t) { | ||||
|     return t._builder; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct Orphanage::GetInnerBuilder<T, Kind::LIST> { | ||||
|   static inline _::ListBuilder apply(typename T::Builder& t) { | ||||
|     return t.builder; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename BuilderType> | ||||
| Orphanage Orphanage::getForMessageContaining(BuilderType builder) { | ||||
|   auto inner = GetInnerBuilder<FromBuilder<BuilderType>>::apply(builder); | ||||
|   return Orphanage(inner.getArena(), inner.getCapTable()); | ||||
| } | ||||
| 
 | ||||
| template <typename RootType> | ||||
| Orphan<RootType> Orphanage::newOrphan() const { | ||||
|   return Orphan<RootType>(_::OrphanBuilder::initStruct(arena, capTable, _::structSize<RootType>())); | ||||
| } | ||||
| 
 | ||||
| template <typename T, Kind k> | ||||
| struct Orphanage::NewOrphanListImpl<List<T, k>> { | ||||
|   static inline _::OrphanBuilder apply( | ||||
|       _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) { | ||||
|     return _::OrphanBuilder::initList( | ||||
|         arena, capTable, bounded(size) * ELEMENTS, _::ElementSizeForType<T>::value); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct Orphanage::NewOrphanListImpl<List<T, Kind::STRUCT>> { | ||||
|   static inline _::OrphanBuilder apply( | ||||
|       _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) { | ||||
|     return _::OrphanBuilder::initStructList( | ||||
|         arena, capTable, bounded(size) * ELEMENTS, _::structSize<T>()); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| struct Orphanage::NewOrphanListImpl<Text> { | ||||
|   static inline _::OrphanBuilder apply( | ||||
|       _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) { | ||||
|     return _::OrphanBuilder::initText(arena, capTable, bounded(size) * BYTES); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| struct Orphanage::NewOrphanListImpl<Data> { | ||||
|   static inline _::OrphanBuilder apply( | ||||
|       _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) { | ||||
|     return _::OrphanBuilder::initData(arena, capTable, bounded(size) * BYTES); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename RootType> | ||||
| Orphan<RootType> Orphanage::newOrphan(uint size) const { | ||||
|   return Orphan<RootType>(NewOrphanListImpl<RootType>::apply(arena, capTable, size)); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| struct Orphanage::GetInnerReader<T, Kind::STRUCT> { | ||||
|   static inline _::StructReader apply(const typename T::Reader& t) { | ||||
|     return t._reader; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct Orphanage::GetInnerReader<T, Kind::LIST> { | ||||
|   static inline _::ListReader apply(const typename T::Reader& t) { | ||||
|     return t.reader; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct Orphanage::GetInnerReader<T, Kind::BLOB> { | ||||
|   static inline const typename T::Reader& apply(const typename T::Reader& t) { | ||||
|     return t; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename Reader> | ||||
| inline Orphan<FromReader<Reader>> Orphanage::newOrphanCopy(Reader copyFrom) const { | ||||
|   return Orphan<FromReader<Reader>>(_::OrphanBuilder::copy( | ||||
|       arena, capTable, GetInnerReader<FromReader<Reader>>::apply(copyFrom))); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline Orphan<List<ListElementType<FromReader<T>>>> | ||||
| Orphanage::newOrphanConcat(kj::ArrayPtr<T> lists) const { | ||||
|   return newOrphanConcat(kj::implicitCast<kj::ArrayPtr<const T>>(lists)); | ||||
| } | ||||
| template <typename T> | ||||
| inline Orphan<List<ListElementType<FromReader<T>>>> | ||||
| Orphanage::newOrphanConcat(kj::ArrayPtr<const T> lists) const { | ||||
|   // Optimization / simplification: Rely on List<T>::Reader containing nothing except a
 | ||||
|   // _::ListReader.
 | ||||
|   static_assert(sizeof(T) == sizeof(_::ListReader), "lists are not bare readers?"); | ||||
|   kj::ArrayPtr<const _::ListReader> raw( | ||||
|       reinterpret_cast<const _::ListReader*>(lists.begin()), lists.size()); | ||||
|   typedef ListElementType<FromReader<T>> Element; | ||||
|   return Orphan<List<Element>>( | ||||
|       _::OrphanBuilder::concat(arena, capTable, | ||||
|           _::elementSizeForType<Element>(), | ||||
|           _::minStructSizeForElement<Element>(), raw)); | ||||
| } | ||||
| 
 | ||||
| inline Orphan<Data> Orphanage::referenceExternalData(Data::Reader data) const { | ||||
|   return Orphan<Data>(_::OrphanBuilder::referenceExternalData(arena, data)); | ||||
| } | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_ORPHAN_H_
 | ||||
| @ -0,0 +1,139 @@ | ||||
| # Copyright (c) 2014 Sandstorm Development Group, Inc. and contributors | ||||
| # Licensed under the MIT License: | ||||
| # | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| # of this software and associated documentation files (the "Software"), to deal | ||||
| # in the Software without restriction, including without limitation the rights | ||||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| # copies of the Software, and to permit persons to whom the Software is | ||||
| # furnished to do so, subject to the following conditions: | ||||
| # | ||||
| # The above copyright notice and this permission notice shall be included in | ||||
| # all copies or substantial portions of the Software. | ||||
| # | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| # THE SOFTWARE. | ||||
| 
 | ||||
| @0xb8630836983feed7; | ||||
| 
 | ||||
| $import "/capnp/c++.capnp".namespace("capnp"); | ||||
| 
 | ||||
| interface Persistent@0xc8cb212fcd9f5691(SturdyRef, Owner) { | ||||
|   # Interface implemented by capabilities that outlive a single connection. A client may save() | ||||
|   # the capability, producing a SturdyRef. The SturdyRef can be stored to disk, then later used to | ||||
|   # obtain a new reference to the capability on a future connection. | ||||
|   # | ||||
|   # The exact format of SturdyRef depends on the "realm" in which the SturdyRef appears. A "realm" | ||||
|   # is an abstract space in which all SturdyRefs have the same format and refer to the same set of | ||||
|   # resources. Every vat is in exactly one realm. All capability clients within that vat must | ||||
|   # produce SturdyRefs of the format appropriate for the realm. | ||||
|   # | ||||
|   # Similarly, every VatNetwork also resides in a particular realm. Usually, a vat's "realm" | ||||
|   # corresponds to the realm of its main VatNetwork. However, a Vat can in fact communicate over | ||||
|   # a VatNetwork in a different realm -- in this case, all SturdyRefs need to be transformed when | ||||
|   # coming or going through said VatNetwork. The RPC system has hooks for registering | ||||
|   # transformation callbacks for this purpose. | ||||
|   # | ||||
|   # Since the format of SturdyRef is realm-dependent, it is not defined here. An application should | ||||
|   # choose an appropriate realm for itself as part of its design. Note that under Sandstorm, every | ||||
|   # application exists in its own realm and is therefore free to define its own SturdyRef format; | ||||
|   # the Sandstorm platform handles translating between realms. | ||||
|   # | ||||
|   # Note that whether a capability is persistent is often orthogonal to its type. In these cases, | ||||
|   # the capability's interface should NOT inherit `Persistent`; instead, just perform a cast at | ||||
|   # runtime. It's not type-safe, but trying to be type-safe in these cases will likely lead to | ||||
|   # tears. In cases where a particular interface only makes sense on persistent capabilities, it | ||||
|   # still should not explicitly inherit Persistent because the `SturdyRef` and `Owner` types will | ||||
|   # vary between realms (they may even be different at the call site than they are on the | ||||
|   # implementation). Instead, mark persistent interfaces with the $persistent annotation (defined | ||||
|   # below). | ||||
|   # | ||||
|   # Sealing | ||||
|   # ------- | ||||
|   # | ||||
|   # As an added security measure, SturdyRefs may be "sealed" to a particular owner, such that | ||||
|   # if the SturdyRef itself leaks to a third party, that party cannot actually restore it because | ||||
|   # they are not the owner. To restore a sealed capability, you must first prove to its host that | ||||
|   # you are the rightful owner. The precise mechanism for this authentication is defined by the | ||||
|   # realm. | ||||
|   # | ||||
|   # Sealing is a defense-in-depth mechanism meant to mitigate damage in the case of catastrophic | ||||
|   # attacks. For example, say an attacker temporarily gains read access to a database full of | ||||
|   # SturdyRefs: it would be unfortunate if it were then necessary to revoke every single reference | ||||
|   # in the database to prevent the attacker from using them. | ||||
|   # | ||||
|   # In general, an "owner" is a course-grained identity. Because capability-based security is still | ||||
|   # the primary mechanism of security, it is not necessary nor desirable to have a separate "owner" | ||||
|   # identity for every single process or object; that is exactly what capabilities are supposed to | ||||
|   # avoid! Instead, it makes sense for an "owner" to literally identify the owner of the machines | ||||
|   # where the capability is stored. If untrusted third parties are able to run arbitrary code on | ||||
|   # said machines, then the sandbox for that code should be designed using Distributed Confinement | ||||
|   # such that the third-party code never sees the bits of the SturdyRefs and cannot directly | ||||
|   # exercise the owner's power to restore refs. See: | ||||
|   # | ||||
|   #     http://www.erights.org/elib/capability/dist-confine.html | ||||
|   # | ||||
|   # Resist the urge to represent an Owner as a simple public key. The whole point of sealing is to | ||||
|   # defend against leaked-storage attacks. Such attacks can easily result in the owner's private | ||||
|   # key being stolen as well. A better solution is for `Owner` to contain a simple globally unique | ||||
|   # identifier for the owner, and for everyone to separately maintain a mapping of owner IDs to | ||||
|   # public keys. If an owner's private key is compromised, then humans will need to communicate | ||||
|   # and agree on a replacement public key, then update the mapping. | ||||
|   # | ||||
|   # As a concrete example, an `Owner` could simply contain a domain name, and restoring a SturdyRef | ||||
|   # would require signing a request using the domain's private key. Authenticating this key could | ||||
|   # be accomplished through certificate authorities or web-of-trust techniques. | ||||
| 
 | ||||
|   save @0 SaveParams -> SaveResults; | ||||
|   # Save a capability persistently so that it can be restored by a future connection.  Not all | ||||
|   # capabilities can be saved -- application interfaces should define which capabilities support | ||||
|   # this and which do not. | ||||
| 
 | ||||
|   struct SaveParams { | ||||
|     sealFor @0 :Owner; | ||||
|     # Seal the SturdyRef so that it can only be restored by the specified Owner. This is meant | ||||
|     # to mitigate damage when a SturdyRef is leaked. See comments above. | ||||
|     # | ||||
|     # Leaving this value null may or may not be allowed; it is up to the realm to decide. If a | ||||
|     # realm does allow a null owner, this should indicate that anyone is allowed to restore the | ||||
|     # ref. | ||||
|   } | ||||
|   struct SaveResults { | ||||
|     sturdyRef @0 :SturdyRef; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| interface RealmGateway(InternalRef, ExternalRef, InternalOwner, ExternalOwner) { | ||||
|   # Interface invoked when a SturdyRef is about to cross realms. The RPC system supports providing | ||||
|   # a RealmGateway as a callback hook when setting up RPC over some VatNetwork. | ||||
| 
 | ||||
|   import @0 (cap :Persistent(ExternalRef, ExternalOwner), | ||||
|              params :Persistent(InternalRef, InternalOwner).SaveParams) | ||||
|          -> Persistent(InternalRef, InternalOwner).SaveResults; | ||||
|   # Given an external capability, save it and return an internal reference. Used when someone | ||||
|   # inside the realm tries to save a capability from outside the realm. | ||||
| 
 | ||||
|   export @1 (cap :Persistent(InternalRef, InternalOwner), | ||||
|              params :Persistent(ExternalRef, ExternalOwner).SaveParams) | ||||
|          -> Persistent(ExternalRef, ExternalOwner).SaveResults; | ||||
|   # Given an internal capability, save it and return an external reference. Used when someone | ||||
|   # outside the realm tries to save a capability from inside the realm. | ||||
| } | ||||
| 
 | ||||
| annotation persistent(interface, field) :Void; | ||||
| # Apply this annotation to interfaces for objects that will always be persistent, instead of | ||||
| # extending the Persistent capability, since the correct type parameters to Persistent depend on | ||||
| # the realm, which is orthogonal to the interface type and therefore should not be defined | ||||
| # along-side it. | ||||
| # | ||||
| # You may also apply this annotation to a capability-typed field which will always contain a | ||||
| # persistent capability, but where the capability's interface itself is not already marked | ||||
| # persistent. | ||||
| # | ||||
| # Note that absence of the $persistent annotation doesn't mean a capability of that type isn't | ||||
| # persistent; it just means not *all* such capabilities are persistent. | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -0,0 +1,160 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_POINTER_HELPERS_H_ | ||||
| #define CAPNP_POINTER_HELPERS_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "layout.h" | ||||
| #include "list.h" | ||||
| 
 | ||||
| namespace capnp { | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| // PointerHelpers is a template class that assists in wrapping/unwrapping the low-level types in
 | ||||
| // layout.h with the high-level public API and generated types.  This way, the code generator
 | ||||
| // and other templates do not have to specialize on each kind of pointer.
 | ||||
| 
 | ||||
| template <typename T> | ||||
| struct PointerHelpers<T, Kind::STRUCT> { | ||||
|   static inline typename T::Reader get(PointerReader reader, const word* defaultValue = nullptr) { | ||||
|     return typename T::Reader(reader.getStruct(defaultValue)); | ||||
|   } | ||||
|   static inline typename T::Builder get(PointerBuilder builder, | ||||
|                                         const word* defaultValue = nullptr) { | ||||
|     return typename T::Builder(builder.getStruct(structSize<T>(), defaultValue)); | ||||
|   } | ||||
|   static inline void set(PointerBuilder builder, typename T::Reader value) { | ||||
|     builder.setStruct(value._reader); | ||||
|   } | ||||
|   static inline void setCanonical(PointerBuilder builder, typename T::Reader value) { | ||||
|     builder.setStruct(value._reader, true); | ||||
|   } | ||||
|   static inline typename T::Builder init(PointerBuilder builder) { | ||||
|     return typename T::Builder(builder.initStruct(structSize<T>())); | ||||
|   } | ||||
|   static inline void adopt(PointerBuilder builder, Orphan<T>&& value) { | ||||
|     builder.adopt(kj::mv(value.builder)); | ||||
|   } | ||||
|   static inline Orphan<T> disown(PointerBuilder builder) { | ||||
|     return Orphan<T>(builder.disown()); | ||||
|   } | ||||
|   static inline _::StructReader getInternalReader(const typename T::Reader& reader) { | ||||
|     return reader._reader; | ||||
|   } | ||||
|   static inline _::StructBuilder getInternalBuilder(typename T::Builder&& builder) { | ||||
|     return builder._builder; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct PointerHelpers<List<T>, Kind::LIST> { | ||||
|   static inline typename List<T>::Reader get(PointerReader reader, | ||||
|                                              const word* defaultValue = nullptr) { | ||||
|     return typename List<T>::Reader(List<T>::getFromPointer(reader, defaultValue)); | ||||
|   } | ||||
|   static inline typename List<T>::Builder get(PointerBuilder builder, | ||||
|                                               const word* defaultValue = nullptr) { | ||||
|     return typename List<T>::Builder(List<T>::getFromPointer(builder, defaultValue)); | ||||
|   } | ||||
|   static inline void set(PointerBuilder builder, typename List<T>::Reader value) { | ||||
|     builder.setList(value.reader); | ||||
|   } | ||||
|   static inline void setCanonical(PointerBuilder builder, typename List<T>::Reader value) { | ||||
|     builder.setList(value.reader, true); | ||||
|   } | ||||
|   static void set(PointerBuilder builder, kj::ArrayPtr<const ReaderFor<T>> value) { | ||||
|     auto l = init(builder, value.size()); | ||||
|     uint i = 0; | ||||
|     for (auto& element: value) { | ||||
|       l.set(i++, element); | ||||
|     } | ||||
|   } | ||||
|   static inline typename List<T>::Builder init(PointerBuilder builder, uint size) { | ||||
|     return typename List<T>::Builder(List<T>::initPointer(builder, size)); | ||||
|   } | ||||
|   static inline void adopt(PointerBuilder builder, Orphan<List<T>>&& value) { | ||||
|     builder.adopt(kj::mv(value.builder)); | ||||
|   } | ||||
|   static inline Orphan<List<T>> disown(PointerBuilder builder) { | ||||
|     return Orphan<List<T>>(builder.disown()); | ||||
|   } | ||||
|   static inline _::ListReader getInternalReader(const typename List<T>::Reader& reader) { | ||||
|     return reader.reader; | ||||
|   } | ||||
|   static inline _::ListBuilder getInternalBuilder(typename List<T>::Builder&& builder) { | ||||
|     return builder.builder; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct PointerHelpers<T, Kind::BLOB> { | ||||
|   static inline typename T::Reader get(PointerReader reader, | ||||
|                                        const void* defaultValue = nullptr, | ||||
|                                        uint defaultBytes = 0) { | ||||
|     return reader.getBlob<T>(defaultValue, bounded(defaultBytes) * BYTES); | ||||
|   } | ||||
|   static inline typename T::Builder get(PointerBuilder builder, | ||||
|                                         const void* defaultValue = nullptr, | ||||
|                                         uint defaultBytes = 0) { | ||||
|     return builder.getBlob<T>(defaultValue, bounded(defaultBytes) * BYTES); | ||||
|   } | ||||
|   static inline void set(PointerBuilder builder, typename T::Reader value) { | ||||
|     builder.setBlob<T>(value); | ||||
|   } | ||||
|   static inline void setCanonical(PointerBuilder builder, typename T::Reader value) { | ||||
|     builder.setBlob<T>(value); | ||||
|   } | ||||
|   static inline typename T::Builder init(PointerBuilder builder, uint size) { | ||||
|     return builder.initBlob<T>(bounded(size) * BYTES); | ||||
|   } | ||||
|   static inline void adopt(PointerBuilder builder, Orphan<T>&& value) { | ||||
|     builder.adopt(kj::mv(value.builder)); | ||||
|   } | ||||
|   static inline Orphan<T> disown(PointerBuilder builder) { | ||||
|     return Orphan<T>(builder.disown()); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| struct UncheckedMessage { | ||||
|   typedef const word* Reader; | ||||
| }; | ||||
| 
 | ||||
| template <> struct Kind_<UncheckedMessage> { static constexpr Kind kind = Kind::OTHER; }; | ||||
| 
 | ||||
| template <> | ||||
| struct PointerHelpers<UncheckedMessage> { | ||||
|   // Reads an AnyPointer field as an unchecked message pointer.  Requires that the containing
 | ||||
|   // message is itself unchecked.  This hack is currently private.  It is used to locate default
 | ||||
|   // values within encoded schemas.
 | ||||
| 
 | ||||
|   static inline const word* get(PointerReader reader) { | ||||
|     return reader.getUnchecked(); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_POINTER_HELPERS_H_
 | ||||
| @ -0,0 +1,47 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_PRETTY_PRINT_H_ | ||||
| #define CAPNP_PRETTY_PRINT_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "dynamic.h" | ||||
| #include <kj/string-tree.h> | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| kj::StringTree prettyPrint(DynamicStruct::Reader value); | ||||
| kj::StringTree prettyPrint(DynamicStruct::Builder value); | ||||
| kj::StringTree prettyPrint(DynamicList::Reader value); | ||||
| kj::StringTree prettyPrint(DynamicList::Builder value); | ||||
| // Print the given Cap'n Proto struct or list with nice indentation.  Note that you can pass any
 | ||||
| // struct or list reader or builder type to this method, since they can be implicitly converted
 | ||||
| // to one of the dynamic types.
 | ||||
| //
 | ||||
| // If you don't want indentation, just use the value's KJ stringifier (e.g. pass it to kj::str(),
 | ||||
| // any of the KJ debug macros, etc.).
 | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // PRETTY_PRINT_H_
 | ||||
| @ -0,0 +1,242 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_RAW_SCHEMA_H_ | ||||
| #define CAPNP_RAW_SCHEMA_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "common.h"  // for uint and friends | ||||
| 
 | ||||
| #if _MSC_VER | ||||
| #include <atomic> | ||||
| #endif | ||||
| 
 | ||||
| namespace capnp { | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| struct RawSchema; | ||||
| 
 | ||||
| struct RawBrandedSchema { | ||||
|   // Represents a combination of a schema and bindings for its generic parameters.
 | ||||
|   //
 | ||||
|   // Note that while we generate one `RawSchema` per type, we generate a `RawBrandedSchema` for
 | ||||
|   // every _instance_ of a generic type -- or, at least, every instance that is actually used. For
 | ||||
|   // generated-code types, we use template magic to initialize these.
 | ||||
| 
 | ||||
|   const RawSchema* generic; | ||||
|   // Generic type which we're branding.
 | ||||
| 
 | ||||
|   struct Binding { | ||||
|     uint8_t which;       // Numeric value of one of schema::Type::Which.
 | ||||
| 
 | ||||
|     bool isImplicitParameter; | ||||
|     // For AnyPointer, true if it's an implicit method parameter.
 | ||||
| 
 | ||||
|     uint16_t listDepth;  // Number of times to wrap the base type in List().
 | ||||
| 
 | ||||
|     uint16_t paramIndex; | ||||
|     // For AnyPointer. If it's a type parameter (scopeId is non-zero) or it's an implicit parameter
 | ||||
|     // (isImplicitParameter is true), then this is the parameter index. Otherwise this is a numeric
 | ||||
|     // value of one of schema::Type::AnyPointer::Unconstrained::Which.
 | ||||
| 
 | ||||
|     union { | ||||
|       const RawBrandedSchema* schema;  // for struct, enum, interface
 | ||||
|       uint64_t scopeId;                // for AnyPointer, if it's a type parameter
 | ||||
|     }; | ||||
| 
 | ||||
|     Binding() = default; | ||||
|     inline constexpr Binding(uint8_t which, uint16_t listDepth, const RawBrandedSchema* schema) | ||||
|         : which(which), isImplicitParameter(false), listDepth(listDepth), paramIndex(0), | ||||
|           schema(schema) {} | ||||
|     inline constexpr Binding(uint8_t which, uint16_t listDepth, | ||||
|                              uint64_t scopeId, uint16_t paramIndex) | ||||
|         : which(which), isImplicitParameter(false), listDepth(listDepth), paramIndex(paramIndex), | ||||
|           scopeId(scopeId) {} | ||||
|     inline constexpr Binding(uint8_t which, uint16_t listDepth, uint16_t implicitParamIndex) | ||||
|         : which(which), isImplicitParameter(true), listDepth(listDepth), | ||||
|           paramIndex(implicitParamIndex), scopeId(0) {} | ||||
|   }; | ||||
| 
 | ||||
|   struct Scope { | ||||
|     uint64_t typeId; | ||||
|     // Type ID whose parameters are being bound.
 | ||||
| 
 | ||||
|     const Binding* bindings; | ||||
|     uint bindingCount; | ||||
|     // Bindings for those parameters.
 | ||||
| 
 | ||||
|     bool isUnbound; | ||||
|     // This scope is unbound, in the sense of SchemaLoader::getUnbound().
 | ||||
|   }; | ||||
| 
 | ||||
|   const Scope* scopes; | ||||
|   // Array of enclosing scopes for which generic variables have been bound, sorted by type ID.
 | ||||
| 
 | ||||
|   struct Dependency { | ||||
|     uint location; | ||||
|     const RawBrandedSchema* schema; | ||||
|   }; | ||||
| 
 | ||||
|   const Dependency* dependencies; | ||||
|   // Map of branded schemas for dependencies of this type, given our brand. Only dependencies that
 | ||||
|   // are branded are included in this map; if a dependency is missing, use its `defaultBrand`.
 | ||||
| 
 | ||||
|   uint32_t scopeCount; | ||||
|   uint32_t dependencyCount; | ||||
| 
 | ||||
|   enum class DepKind { | ||||
|     // Component of a Dependency::location. Specifies what sort of dependency this is.
 | ||||
| 
 | ||||
|     INVALID, | ||||
|     // Mostly defined to ensure that zero is not a valid location.
 | ||||
| 
 | ||||
|     FIELD, | ||||
|     // Binding needed for a field's type. The index is the field index (NOT ordinal!).
 | ||||
| 
 | ||||
|     METHOD_PARAMS, | ||||
|     // Bindings needed for a method's params type. The index is the method number.
 | ||||
| 
 | ||||
|     METHOD_RESULTS, | ||||
|     // Bindings needed for a method's results type. The index is the method ordinal.
 | ||||
| 
 | ||||
|     SUPERCLASS, | ||||
|     // Bindings needed for a superclass type. The index is the superclass's index in the
 | ||||
|     // "extends" list.
 | ||||
| 
 | ||||
|     CONST_TYPE | ||||
|     // Bindings needed for the type of a constant. The index is zero.
 | ||||
|   }; | ||||
| 
 | ||||
|   static inline uint makeDepLocation(DepKind kind, uint index) { | ||||
|     // Make a number representing the location of a particular dependency within its parent
 | ||||
|     // schema.
 | ||||
| 
 | ||||
|     return (static_cast<uint>(kind) << 24) | index; | ||||
|   } | ||||
| 
 | ||||
|   class Initializer { | ||||
|   public: | ||||
|     virtual void init(const RawBrandedSchema* generic) const = 0; | ||||
|   }; | ||||
| 
 | ||||
|   const Initializer* lazyInitializer; | ||||
|   // Lazy initializer, invoked by ensureInitialized().
 | ||||
| 
 | ||||
|   inline void ensureInitialized() const { | ||||
|     // Lazy initialization support.  Invoke to ensure that initialization has taken place.  This
 | ||||
|     // is required in particular when traversing the dependency list.  RawSchemas for compiled-in
 | ||||
|     // types are always initialized; only dynamically-loaded schemas may be lazy.
 | ||||
| 
 | ||||
| #if __GNUC__ | ||||
|     const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_ACQUIRE); | ||||
| #elif _MSC_VER | ||||
|     const Initializer* i = *static_cast<Initializer const* const volatile*>(&lazyInitializer); | ||||
|     std::atomic_thread_fence(std::memory_order_acquire); | ||||
| #else | ||||
| #error "Platform not supported" | ||||
| #endif | ||||
|     if (i != nullptr) i->init(this); | ||||
|   } | ||||
| 
 | ||||
|   inline bool isUnbound() const; | ||||
|   // Checks if this schema is the result of calling SchemaLoader::getUnbound(), in which case
 | ||||
|   // binding lookups need to be handled specially.
 | ||||
| }; | ||||
| 
 | ||||
| struct RawSchema { | ||||
|   // The generated code defines a constant RawSchema for every compiled declaration.
 | ||||
|   //
 | ||||
|   // This is an internal structure which could change in the future.
 | ||||
| 
 | ||||
|   uint64_t id; | ||||
| 
 | ||||
|   const word* encodedNode; | ||||
|   // Encoded SchemaNode, readable via readMessageUnchecked<schema::Node>(encodedNode).
 | ||||
| 
 | ||||
|   uint32_t encodedSize; | ||||
|   // Size of encodedNode, in words.
 | ||||
| 
 | ||||
|   const RawSchema* const* dependencies; | ||||
|   // Pointers to other types on which this one depends, sorted by ID.  The schemas in this table
 | ||||
|   // may be uninitialized -- you must call ensureInitialized() on the one you wish to use before
 | ||||
|   // using it.
 | ||||
|   //
 | ||||
|   // TODO(someday):  Make this a hashtable.
 | ||||
| 
 | ||||
|   const uint16_t* membersByName; | ||||
|   // Indexes of members sorted by name.  Used to implement name lookup.
 | ||||
|   // TODO(someday):  Make this a hashtable.
 | ||||
| 
 | ||||
|   uint32_t dependencyCount; | ||||
|   uint32_t memberCount; | ||||
|   // Sizes of above tables.
 | ||||
| 
 | ||||
|   const uint16_t* membersByDiscriminant; | ||||
|   // List of all member indexes ordered by discriminant value.  Those which don't have a
 | ||||
|   // discriminant value are listed at the end, in order by ordinal.
 | ||||
| 
 | ||||
|   const RawSchema* canCastTo; | ||||
|   // Points to the RawSchema of a compiled-in type to which it is safe to cast any DynamicValue
 | ||||
|   // with this schema.  This is null for all compiled-in types; it is only set by SchemaLoader on
 | ||||
|   // dynamically-loaded types.
 | ||||
| 
 | ||||
|   class Initializer { | ||||
|   public: | ||||
|     virtual void init(const RawSchema* schema) const = 0; | ||||
|   }; | ||||
| 
 | ||||
|   const Initializer* lazyInitializer; | ||||
|   // Lazy initializer, invoked by ensureInitialized().
 | ||||
| 
 | ||||
|   inline void ensureInitialized() const { | ||||
|     // Lazy initialization support.  Invoke to ensure that initialization has taken place.  This
 | ||||
|     // is required in particular when traversing the dependency list.  RawSchemas for compiled-in
 | ||||
|     // types are always initialized; only dynamically-loaded schemas may be lazy.
 | ||||
| 
 | ||||
| #if __GNUC__ | ||||
|     const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_ACQUIRE); | ||||
| #elif _MSC_VER | ||||
|     const Initializer* i = *static_cast<Initializer const* const volatile*>(&lazyInitializer); | ||||
|     std::atomic_thread_fence(std::memory_order_acquire); | ||||
| #else | ||||
| #error "Platform not supported" | ||||
| #endif | ||||
|     if (i != nullptr) i->init(this); | ||||
|   } | ||||
| 
 | ||||
|   RawBrandedSchema defaultBrand; | ||||
|   // Specifies the brand to use for this schema if no generic parameters have been bound to
 | ||||
|   // anything. Generally, in the default brand, all generic parameters are treated as if they were
 | ||||
|   // bound to `AnyPointer`.
 | ||||
| }; | ||||
| 
 | ||||
| inline bool RawBrandedSchema::isUnbound() const { | ||||
|   // The unbound schema is the only one that has no scopes but is not the default schema.
 | ||||
|   return scopeCount == 0 && this != &generic->defaultBrand; | ||||
| } | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_RAW_SCHEMA_H_
 | ||||
| @ -0,0 +1,130 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| // This file contains a bunch of internal declarations that must appear before rpc.h can start.
 | ||||
| // We don't define these directly in rpc.h because it makes the file hard to read.
 | ||||
| 
 | ||||
| #ifndef CAPNP_RPC_PRELUDE_H_ | ||||
| #define CAPNP_RPC_PRELUDE_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "capability.h" | ||||
| #include "persistent.capnp.h" | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| class OutgoingRpcMessage; | ||||
| class IncomingRpcMessage; | ||||
| 
 | ||||
| template <typename SturdyRefHostId> | ||||
| class RpcSystem; | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| class VatNetworkBase { | ||||
|   // Non-template version of VatNetwork.  Ignore this class; see VatNetwork in rpc.h.
 | ||||
| 
 | ||||
| public: | ||||
|   class Connection; | ||||
| 
 | ||||
|   struct ConnectionAndProvisionId { | ||||
|     kj::Own<Connection> connection; | ||||
|     kj::Own<OutgoingRpcMessage> firstMessage; | ||||
|     Orphan<AnyPointer> provisionId; | ||||
|   }; | ||||
| 
 | ||||
|   class Connection { | ||||
|   public: | ||||
|     virtual kj::Own<OutgoingRpcMessage> newOutgoingMessage(uint firstSegmentWordSize) = 0; | ||||
|     virtual kj::Promise<kj::Maybe<kj::Own<IncomingRpcMessage>>> receiveIncomingMessage() = 0; | ||||
|     virtual kj::Promise<void> shutdown() = 0; | ||||
|     virtual AnyStruct::Reader baseGetPeerVatId() = 0; | ||||
|   }; | ||||
|   virtual kj::Maybe<kj::Own<Connection>> baseConnect(AnyStruct::Reader vatId) = 0; | ||||
|   virtual kj::Promise<kj::Own<Connection>> baseAccept() = 0; | ||||
| }; | ||||
| 
 | ||||
| class SturdyRefRestorerBase { | ||||
| public: | ||||
|   virtual Capability::Client baseRestore(AnyPointer::Reader ref) = 0; | ||||
| }; | ||||
| 
 | ||||
| class BootstrapFactoryBase { | ||||
|   // Non-template version of BootstrapFactory.  Ignore this class; see BootstrapFactory in rpc.h.
 | ||||
| public: | ||||
|   virtual Capability::Client baseCreateFor(AnyStruct::Reader clientId) = 0; | ||||
| }; | ||||
| 
 | ||||
| class RpcSystemBase { | ||||
|   // Non-template version of RpcSystem.  Ignore this class; see RpcSystem in rpc.h.
 | ||||
| 
 | ||||
| public: | ||||
|   RpcSystemBase(VatNetworkBase& network, kj::Maybe<Capability::Client> bootstrapInterface, | ||||
|                 kj::Maybe<RealmGateway<>::Client> gateway); | ||||
|   RpcSystemBase(VatNetworkBase& network, BootstrapFactoryBase& bootstrapFactory, | ||||
|                 kj::Maybe<RealmGateway<>::Client> gateway); | ||||
|   RpcSystemBase(VatNetworkBase& network, SturdyRefRestorerBase& restorer); | ||||
|   RpcSystemBase(RpcSystemBase&& other) noexcept; | ||||
|   ~RpcSystemBase() noexcept(false); | ||||
| 
 | ||||
| private: | ||||
|   class Impl; | ||||
|   kj::Own<Impl> impl; | ||||
| 
 | ||||
|   Capability::Client baseBootstrap(AnyStruct::Reader vatId); | ||||
|   Capability::Client baseRestore(AnyStruct::Reader vatId, AnyPointer::Reader objectId); | ||||
|   void baseSetFlowLimit(size_t words); | ||||
| 
 | ||||
|   template <typename> | ||||
|   friend class capnp::RpcSystem; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> struct InternalRefFromRealmGateway_; | ||||
| template <typename InternalRef, typename ExternalRef, typename InternalOwner, | ||||
|           typename ExternalOwner> | ||||
| struct InternalRefFromRealmGateway_<RealmGateway<InternalRef, ExternalRef, InternalOwner, | ||||
|                                     ExternalOwner>> { | ||||
|   typedef InternalRef Type; | ||||
| }; | ||||
| template <typename T> | ||||
| using InternalRefFromRealmGateway = typename InternalRefFromRealmGateway_<T>::Type; | ||||
| template <typename T> | ||||
| using InternalRefFromRealmGatewayClient = InternalRefFromRealmGateway<typename T::Calls>; | ||||
| 
 | ||||
| template <typename T> struct ExternalRefFromRealmGateway_; | ||||
| template <typename InternalRef, typename ExternalRef, typename InternalOwner, | ||||
|           typename ExternalOwner> | ||||
| struct ExternalRefFromRealmGateway_<RealmGateway<InternalRef, ExternalRef, InternalOwner, | ||||
|                                     ExternalOwner>> { | ||||
|   typedef ExternalRef Type; | ||||
| }; | ||||
| template <typename T> | ||||
| using ExternalRefFromRealmGateway = typename ExternalRefFromRealmGateway_<T>::Type; | ||||
| template <typename T> | ||||
| using ExternalRefFromRealmGatewayClient = ExternalRefFromRealmGateway<typename T::Calls>; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_RPC_PRELUDE_H_
 | ||||
| @ -0,0 +1,169 @@ | ||||
| # Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors | ||||
| # Licensed under the MIT License: | ||||
| # | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| # of this software and associated documentation files (the "Software"), to deal | ||||
| # in the Software without restriction, including without limitation the rights | ||||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| # copies of the Software, and to permit persons to whom the Software is | ||||
| # furnished to do so, subject to the following conditions: | ||||
| # | ||||
| # The above copyright notice and this permission notice shall be included in | ||||
| # all copies or substantial portions of the Software. | ||||
| # | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| # THE SOFTWARE. | ||||
| 
 | ||||
| @0xa184c7885cdaf2a1; | ||||
| # This file defines the "network-specific parameters" in rpc.capnp to support a network consisting | ||||
| # of two vats.  Each of these vats may in fact be in communication with other vats, but any | ||||
| # capabilities they forward must be proxied.  Thus, to each end of the connection, all capabilities | ||||
| # received from the other end appear to live in a single vat. | ||||
| # | ||||
| # Two notable use cases for this model include: | ||||
| # - Regular client-server communications, where a remote client machine (perhaps living on an end | ||||
| #   user's personal device) connects to a server.  The server may be part of a cluster, and may | ||||
| #   call on other servers in the cluster to help service the user's request.  It may even obtain | ||||
| #   capabilities from these other servers which it passes on to the user.  To simplify network | ||||
| #   common traversal problems (e.g. if the user is behind a firewall), it is probably desirable to | ||||
| #   multiplex all communications between the server cluster and the client over the original | ||||
| #   connection rather than form new ones.  This connection should use the two-party protocol, as | ||||
| #   the client has no interest in knowing about additional servers. | ||||
| # - Applications running in a sandbox.  A supervisor process may execute a confined application | ||||
| #   such that all of the confined app's communications with the outside world must pass through | ||||
| #   the supervisor.  In this case, the connection between the confined app and the supervisor might | ||||
| #   as well use the two-party protocol, because the confined app is intentionally prevented from | ||||
| #   talking to any other vat anyway.  Any external resources will be proxied through the supervisor, | ||||
| #   and so to the contained app will appear as if they were hosted by the supervisor itself. | ||||
| # | ||||
| # Since there are only two vats in this network, there is never a need for three-way introductions, | ||||
| # so level 3 is free.  Moreover, because it is never necessary to form new connections, the | ||||
| # two-party protocol can be used easily anywhere where a two-way byte stream exists, without regard | ||||
| # to where that byte stream goes or how it was initiated.  This makes the two-party runtime library | ||||
| # highly reusable. | ||||
| # | ||||
| # Joins (level 4) _could_ be needed in cases where one or both vats are participating in other | ||||
| # networks that use joins.  For instance, if Alice and Bob are speaking through the two-party | ||||
| # protocol, and Bob is also participating on another network, Bob may send Alice two or more | ||||
| # proxied capabilities which, unbeknownst to Bob at the time, are in fact pointing at the same | ||||
| # remote object.  Alice may then request to join these capabilities, at which point Bob will have | ||||
| # to forward the join to the other network.  Note, however, that if Alice is _not_ participating on | ||||
| # any other network, then Alice will never need to _receive_ a Join, because Alice would always | ||||
| # know when two locally-hosted capabilities are the same and would never export a redundant alias | ||||
| # to Bob.  So, Alice can respond to all incoming joins with an error, and only needs to implement | ||||
| # outgoing joins if she herself desires to use this feature.  Also, outgoing joins are relatively | ||||
| # easy to implement in this scenario. | ||||
| # | ||||
| # What all this means is that a level 4 implementation of the confined network is barely more | ||||
| # complicated than a level 2 implementation.  However, such an implementation allows the "client" | ||||
| # or "confined" app to access the server's/supervisor's network with equal functionality to any | ||||
| # native participant.  In other words, an application which implements only the two-party protocol | ||||
| # can be paired with a proxy app in order to participate in any network. | ||||
| # | ||||
| # So, when implementing Cap'n Proto in a new language, it makes sense to implement only the | ||||
| # two-party protocol initially, and then pair applications with an appropriate proxy written in | ||||
| # C++, rather than implement other parameterizations of the RPC protocol directly. | ||||
| 
 | ||||
| using Cxx = import "/capnp/c++.capnp"; | ||||
| $Cxx.namespace("capnp::rpc::twoparty"); | ||||
| 
 | ||||
| # Note: SturdyRef is not specified here. It is up to the application to define semantics of | ||||
| # SturdyRefs if desired. | ||||
| 
 | ||||
| enum Side { | ||||
|   server @0; | ||||
|   # The object lives on the "server" or "supervisor" end of the connection. Only the | ||||
|   # server/supervisor knows how to interpret the ref; to the client, it is opaque. | ||||
|   # | ||||
|   # Note that containers intending to implement strong confinement should rewrite SturdyRefs | ||||
|   # received from the external network before passing them on to the confined app. The confined | ||||
|   # app thus does not ever receive the raw bits of the SturdyRef (which it could perhaps | ||||
|   # maliciously leak), but instead receives only a thing that it can pass back to the container | ||||
|   # later to restore the ref. See: | ||||
|   # http://www.erights.org/elib/capability/dist-confine.html | ||||
| 
 | ||||
|   client @1; | ||||
|   # The object lives on the "client" or "confined app" end of the connection. Only the client | ||||
|   # knows how to interpret the ref; to the server/supervisor, it is opaque. Most clients do not | ||||
|   # actually know how to persist capabilities at all, so use of this is unusual. | ||||
| } | ||||
| 
 | ||||
| struct VatId { | ||||
|   side @0 :Side; | ||||
| } | ||||
| 
 | ||||
| struct ProvisionId { | ||||
|   # Only used for joins, since three-way introductions never happen on a two-party network. | ||||
| 
 | ||||
|   joinId @0 :UInt32; | ||||
|   # The ID from `JoinKeyPart`. | ||||
| } | ||||
| 
 | ||||
| struct RecipientId {} | ||||
| # Never used, because there are only two parties. | ||||
| 
 | ||||
| struct ThirdPartyCapId {} | ||||
| # Never used, because there is no third party. | ||||
| 
 | ||||
| struct JoinKeyPart { | ||||
|   # Joins in the two-party case are simplified by a few observations. | ||||
|   # | ||||
|   # First, on a two-party network, a Join only ever makes sense if the receiving end is also | ||||
|   # connected to other networks.  A vat which is not connected to any other network can safely | ||||
|   # reject all joins. | ||||
|   # | ||||
|   # Second, since a two-party connection bisects the network -- there can be no other connections | ||||
|   # between the networks at either end of the connection -- if one part of a join crosses the | ||||
|   # connection, then _all_ parts must cross it.  Therefore, a vat which is receiving a Join request | ||||
|   # off some other network which needs to be forwarded across the two-party connection can | ||||
|   # collect all the parts on its end and only forward them across the two-party connection when all | ||||
|   # have been received. | ||||
|   # | ||||
|   # For example, imagine that Alice and Bob are vats connected over a two-party connection, and | ||||
|   # each is also connected to other networks.  At some point, Alice receives one part of a Join | ||||
|   # request off her network.  The request is addressed to a capability that Alice received from | ||||
|   # Bob and is proxying to her other network.  Alice goes ahead and responds to the Join part as | ||||
|   # if she hosted the capability locally (this is important so that if not all the Join parts end | ||||
|   # up at Alice, the original sender can detect the failed Join without hanging).  As other parts | ||||
|   # trickle in, Alice verifies that each part is addressed to a capability from Bob and continues | ||||
|   # to respond to each one.  Once the complete set of join parts is received, Alice checks if they | ||||
|   # were all for the exact same capability.  If so, she doesn't need to send anything to Bob at | ||||
|   # all.  Otherwise, she collects the set of capabilities (from Bob) to which the join parts were | ||||
|   # addressed and essentially initiates a _new_ Join request on those capabilities to Bob.  Alice | ||||
|   # does not forward the Join parts she received herself, but essentially forwards the Join as a | ||||
|   # whole. | ||||
|   # | ||||
|   # On Bob's end, since he knows that Alice will always send all parts of a Join together, he | ||||
|   # simply waits until he's received them all, then performs a join on the respective capabilities | ||||
|   # as if it had been requested locally. | ||||
| 
 | ||||
|   joinId @0 :UInt32; | ||||
|   # A number identifying this join, chosen by the sender.  May be reused once `Finish` messages are | ||||
|   # sent corresponding to all of the `Join` messages. | ||||
| 
 | ||||
|   partCount @1 :UInt16; | ||||
|   # The number of capabilities to be joined. | ||||
| 
 | ||||
|   partNum @2 :UInt16; | ||||
|   # Which part this request targets -- a number in the range [0, partCount). | ||||
| } | ||||
| 
 | ||||
| struct JoinResult { | ||||
|   joinId @0 :UInt32; | ||||
|   # Matches `JoinKeyPart`. | ||||
| 
 | ||||
|   succeeded @1 :Bool; | ||||
|   # All JoinResults in the set will have the same value for `succeeded`.  The receiver actually | ||||
|   # implements the join by waiting for all the `JoinKeyParts` and then performing its own join on | ||||
|   # them, then going back and answering all the join requests afterwards. | ||||
| 
 | ||||
|   cap @2 :AnyPointer; | ||||
|   # One of the JoinResults will have a non-null `cap` which is the joined capability. | ||||
|   # | ||||
|   # TODO(cleanup):  Change `AnyPointer` to `Capability` when that is supported. | ||||
| } | ||||
| @ -0,0 +1,726 @@ | ||||
| // Generated by Cap'n Proto compiler, DO NOT EDIT
 | ||||
| // source: rpc-twoparty.capnp
 | ||||
| 
 | ||||
| #ifndef CAPNP_INCLUDED_a184c7885cdaf2a1_ | ||||
| #define CAPNP_INCLUDED_a184c7885cdaf2a1_ | ||||
| 
 | ||||
| #include <capnp/generated-header-support.h> | ||||
| 
 | ||||
| #if CAPNP_VERSION != 6001 | ||||
| #error "Version mismatch between generated code and library headers.  You must use the same version of the Cap'n Proto compiler and library." | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| namespace capnp { | ||||
| namespace schemas { | ||||
| 
 | ||||
| CAPNP_DECLARE_SCHEMA(9fd69ebc87b9719c); | ||||
| enum class Side_9fd69ebc87b9719c: uint16_t { | ||||
|   SERVER, | ||||
|   CLIENT, | ||||
| }; | ||||
| CAPNP_DECLARE_ENUM(Side, 9fd69ebc87b9719c); | ||||
| CAPNP_DECLARE_SCHEMA(d20b909fee733a8e); | ||||
| CAPNP_DECLARE_SCHEMA(b88d09a9c5f39817); | ||||
| CAPNP_DECLARE_SCHEMA(89f389b6fd4082c1); | ||||
| CAPNP_DECLARE_SCHEMA(b47f4979672cb59d); | ||||
| CAPNP_DECLARE_SCHEMA(95b29059097fca83); | ||||
| CAPNP_DECLARE_SCHEMA(9d263a3630b7ebee); | ||||
| 
 | ||||
| }  // namespace schemas
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| namespace capnp { | ||||
| namespace rpc { | ||||
| namespace twoparty { | ||||
| 
 | ||||
| typedef ::capnp::schemas::Side_9fd69ebc87b9719c Side; | ||||
| 
 | ||||
| struct VatId { | ||||
|   VatId() = delete; | ||||
| 
 | ||||
|   class Reader; | ||||
|   class Builder; | ||||
|   class Pipeline; | ||||
| 
 | ||||
|   struct _capnpPrivate { | ||||
|     CAPNP_DECLARE_STRUCT_HEADER(d20b909fee733a8e, 1, 0) | ||||
|     #if !CAPNP_LITE | ||||
|     static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } | ||||
|     #endif  // !CAPNP_LITE
 | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| struct ProvisionId { | ||||
|   ProvisionId() = delete; | ||||
| 
 | ||||
|   class Reader; | ||||
|   class Builder; | ||||
|   class Pipeline; | ||||
| 
 | ||||
|   struct _capnpPrivate { | ||||
|     CAPNP_DECLARE_STRUCT_HEADER(b88d09a9c5f39817, 1, 0) | ||||
|     #if !CAPNP_LITE | ||||
|     static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } | ||||
|     #endif  // !CAPNP_LITE
 | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| struct RecipientId { | ||||
|   RecipientId() = delete; | ||||
| 
 | ||||
|   class Reader; | ||||
|   class Builder; | ||||
|   class Pipeline; | ||||
| 
 | ||||
|   struct _capnpPrivate { | ||||
|     CAPNP_DECLARE_STRUCT_HEADER(89f389b6fd4082c1, 0, 0) | ||||
|     #if !CAPNP_LITE | ||||
|     static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } | ||||
|     #endif  // !CAPNP_LITE
 | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| struct ThirdPartyCapId { | ||||
|   ThirdPartyCapId() = delete; | ||||
| 
 | ||||
|   class Reader; | ||||
|   class Builder; | ||||
|   class Pipeline; | ||||
| 
 | ||||
|   struct _capnpPrivate { | ||||
|     CAPNP_DECLARE_STRUCT_HEADER(b47f4979672cb59d, 0, 0) | ||||
|     #if !CAPNP_LITE | ||||
|     static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } | ||||
|     #endif  // !CAPNP_LITE
 | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| struct JoinKeyPart { | ||||
|   JoinKeyPart() = delete; | ||||
| 
 | ||||
|   class Reader; | ||||
|   class Builder; | ||||
|   class Pipeline; | ||||
| 
 | ||||
|   struct _capnpPrivate { | ||||
|     CAPNP_DECLARE_STRUCT_HEADER(95b29059097fca83, 1, 0) | ||||
|     #if !CAPNP_LITE | ||||
|     static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } | ||||
|     #endif  // !CAPNP_LITE
 | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| struct JoinResult { | ||||
|   JoinResult() = delete; | ||||
| 
 | ||||
|   class Reader; | ||||
|   class Builder; | ||||
|   class Pipeline; | ||||
| 
 | ||||
|   struct _capnpPrivate { | ||||
|     CAPNP_DECLARE_STRUCT_HEADER(9d263a3630b7ebee, 1, 1) | ||||
|     #if !CAPNP_LITE | ||||
|     static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } | ||||
|     #endif  // !CAPNP_LITE
 | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| class VatId::Reader { | ||||
| public: | ||||
|   typedef VatId Reads; | ||||
| 
 | ||||
|   Reader() = default; | ||||
|   inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { | ||||
|     return _reader.totalSize().asPublic(); | ||||
|   } | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { | ||||
|     return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); | ||||
|   } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline  ::capnp::rpc::twoparty::Side getSide() const; | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructReader _reader; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::List; | ||||
|   friend class ::capnp::MessageBuilder; | ||||
|   friend class ::capnp::Orphanage; | ||||
| }; | ||||
| 
 | ||||
| class VatId::Builder { | ||||
| public: | ||||
|   typedef VatId Builds; | ||||
| 
 | ||||
|   Builder() = delete;  // Deleted to discourage incorrect usage.
 | ||||
|                        // You can explicitly initialize to nullptr instead.
 | ||||
|   inline Builder(decltype(nullptr)) {} | ||||
|   inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} | ||||
|   inline operator Reader() const { return Reader(_builder.asReader()); } | ||||
|   inline Reader asReader() const { return *this; } | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { return asReader().toString(); } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline  ::capnp::rpc::twoparty::Side getSide(); | ||||
|   inline void setSide( ::capnp::rpc::twoparty::Side value); | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructBuilder _builder; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   friend class ::capnp::Orphanage; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
| class VatId::Pipeline { | ||||
| public: | ||||
|   typedef VatId Pipelines; | ||||
| 
 | ||||
|   inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} | ||||
|   inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) | ||||
|       : _typeless(kj::mv(typeless)) {} | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::AnyPointer::Pipeline _typeless; | ||||
|   friend class ::capnp::PipelineHook; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
| }; | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| class ProvisionId::Reader { | ||||
| public: | ||||
|   typedef ProvisionId Reads; | ||||
| 
 | ||||
|   Reader() = default; | ||||
|   inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { | ||||
|     return _reader.totalSize().asPublic(); | ||||
|   } | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { | ||||
|     return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); | ||||
|   } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline  ::uint32_t getJoinId() const; | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructReader _reader; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::List; | ||||
|   friend class ::capnp::MessageBuilder; | ||||
|   friend class ::capnp::Orphanage; | ||||
| }; | ||||
| 
 | ||||
| class ProvisionId::Builder { | ||||
| public: | ||||
|   typedef ProvisionId Builds; | ||||
| 
 | ||||
|   Builder() = delete;  // Deleted to discourage incorrect usage.
 | ||||
|                        // You can explicitly initialize to nullptr instead.
 | ||||
|   inline Builder(decltype(nullptr)) {} | ||||
|   inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} | ||||
|   inline operator Reader() const { return Reader(_builder.asReader()); } | ||||
|   inline Reader asReader() const { return *this; } | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { return asReader().toString(); } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline  ::uint32_t getJoinId(); | ||||
|   inline void setJoinId( ::uint32_t value); | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructBuilder _builder; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   friend class ::capnp::Orphanage; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
| class ProvisionId::Pipeline { | ||||
| public: | ||||
|   typedef ProvisionId Pipelines; | ||||
| 
 | ||||
|   inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} | ||||
|   inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) | ||||
|       : _typeless(kj::mv(typeless)) {} | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::AnyPointer::Pipeline _typeless; | ||||
|   friend class ::capnp::PipelineHook; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
| }; | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| class RecipientId::Reader { | ||||
| public: | ||||
|   typedef RecipientId Reads; | ||||
| 
 | ||||
|   Reader() = default; | ||||
|   inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { | ||||
|     return _reader.totalSize().asPublic(); | ||||
|   } | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { | ||||
|     return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); | ||||
|   } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructReader _reader; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::List; | ||||
|   friend class ::capnp::MessageBuilder; | ||||
|   friend class ::capnp::Orphanage; | ||||
| }; | ||||
| 
 | ||||
| class RecipientId::Builder { | ||||
| public: | ||||
|   typedef RecipientId Builds; | ||||
| 
 | ||||
|   Builder() = delete;  // Deleted to discourage incorrect usage.
 | ||||
|                        // You can explicitly initialize to nullptr instead.
 | ||||
|   inline Builder(decltype(nullptr)) {} | ||||
|   inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} | ||||
|   inline operator Reader() const { return Reader(_builder.asReader()); } | ||||
|   inline Reader asReader() const { return *this; } | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { return asReader().toString(); } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructBuilder _builder; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   friend class ::capnp::Orphanage; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
| class RecipientId::Pipeline { | ||||
| public: | ||||
|   typedef RecipientId Pipelines; | ||||
| 
 | ||||
|   inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} | ||||
|   inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) | ||||
|       : _typeless(kj::mv(typeless)) {} | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::AnyPointer::Pipeline _typeless; | ||||
|   friend class ::capnp::PipelineHook; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
| }; | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| class ThirdPartyCapId::Reader { | ||||
| public: | ||||
|   typedef ThirdPartyCapId Reads; | ||||
| 
 | ||||
|   Reader() = default; | ||||
|   inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { | ||||
|     return _reader.totalSize().asPublic(); | ||||
|   } | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { | ||||
|     return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); | ||||
|   } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructReader _reader; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::List; | ||||
|   friend class ::capnp::MessageBuilder; | ||||
|   friend class ::capnp::Orphanage; | ||||
| }; | ||||
| 
 | ||||
| class ThirdPartyCapId::Builder { | ||||
| public: | ||||
|   typedef ThirdPartyCapId Builds; | ||||
| 
 | ||||
|   Builder() = delete;  // Deleted to discourage incorrect usage.
 | ||||
|                        // You can explicitly initialize to nullptr instead.
 | ||||
|   inline Builder(decltype(nullptr)) {} | ||||
|   inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} | ||||
|   inline operator Reader() const { return Reader(_builder.asReader()); } | ||||
|   inline Reader asReader() const { return *this; } | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { return asReader().toString(); } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructBuilder _builder; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   friend class ::capnp::Orphanage; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
| class ThirdPartyCapId::Pipeline { | ||||
| public: | ||||
|   typedef ThirdPartyCapId Pipelines; | ||||
| 
 | ||||
|   inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} | ||||
|   inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) | ||||
|       : _typeless(kj::mv(typeless)) {} | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::AnyPointer::Pipeline _typeless; | ||||
|   friend class ::capnp::PipelineHook; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
| }; | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| class JoinKeyPart::Reader { | ||||
| public: | ||||
|   typedef JoinKeyPart Reads; | ||||
| 
 | ||||
|   Reader() = default; | ||||
|   inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { | ||||
|     return _reader.totalSize().asPublic(); | ||||
|   } | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { | ||||
|     return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); | ||||
|   } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline  ::uint32_t getJoinId() const; | ||||
| 
 | ||||
|   inline  ::uint16_t getPartCount() const; | ||||
| 
 | ||||
|   inline  ::uint16_t getPartNum() const; | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructReader _reader; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::List; | ||||
|   friend class ::capnp::MessageBuilder; | ||||
|   friend class ::capnp::Orphanage; | ||||
| }; | ||||
| 
 | ||||
| class JoinKeyPart::Builder { | ||||
| public: | ||||
|   typedef JoinKeyPart Builds; | ||||
| 
 | ||||
|   Builder() = delete;  // Deleted to discourage incorrect usage.
 | ||||
|                        // You can explicitly initialize to nullptr instead.
 | ||||
|   inline Builder(decltype(nullptr)) {} | ||||
|   inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} | ||||
|   inline operator Reader() const { return Reader(_builder.asReader()); } | ||||
|   inline Reader asReader() const { return *this; } | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { return asReader().toString(); } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline  ::uint32_t getJoinId(); | ||||
|   inline void setJoinId( ::uint32_t value); | ||||
| 
 | ||||
|   inline  ::uint16_t getPartCount(); | ||||
|   inline void setPartCount( ::uint16_t value); | ||||
| 
 | ||||
|   inline  ::uint16_t getPartNum(); | ||||
|   inline void setPartNum( ::uint16_t value); | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructBuilder _builder; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   friend class ::capnp::Orphanage; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
| class JoinKeyPart::Pipeline { | ||||
| public: | ||||
|   typedef JoinKeyPart Pipelines; | ||||
| 
 | ||||
|   inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} | ||||
|   inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) | ||||
|       : _typeless(kj::mv(typeless)) {} | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::AnyPointer::Pipeline _typeless; | ||||
|   friend class ::capnp::PipelineHook; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
| }; | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| class JoinResult::Reader { | ||||
| public: | ||||
|   typedef JoinResult Reads; | ||||
| 
 | ||||
|   Reader() = default; | ||||
|   inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { | ||||
|     return _reader.totalSize().asPublic(); | ||||
|   } | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { | ||||
|     return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); | ||||
|   } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline  ::uint32_t getJoinId() const; | ||||
| 
 | ||||
|   inline bool getSucceeded() const; | ||||
| 
 | ||||
|   inline bool hasCap() const; | ||||
|   inline ::capnp::AnyPointer::Reader getCap() const; | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructReader _reader; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::List; | ||||
|   friend class ::capnp::MessageBuilder; | ||||
|   friend class ::capnp::Orphanage; | ||||
| }; | ||||
| 
 | ||||
| class JoinResult::Builder { | ||||
| public: | ||||
|   typedef JoinResult Builds; | ||||
| 
 | ||||
|   Builder() = delete;  // Deleted to discourage incorrect usage.
 | ||||
|                        // You can explicitly initialize to nullptr instead.
 | ||||
|   inline Builder(decltype(nullptr)) {} | ||||
|   inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} | ||||
|   inline operator Reader() const { return Reader(_builder.asReader()); } | ||||
|   inline Reader asReader() const { return *this; } | ||||
| 
 | ||||
|   inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } | ||||
| #if !CAPNP_LITE | ||||
|   inline ::kj::StringTree toString() const { return asReader().toString(); } | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
|   inline  ::uint32_t getJoinId(); | ||||
|   inline void setJoinId( ::uint32_t value); | ||||
| 
 | ||||
|   inline bool getSucceeded(); | ||||
|   inline void setSucceeded(bool value); | ||||
| 
 | ||||
|   inline bool hasCap(); | ||||
|   inline ::capnp::AnyPointer::Builder getCap(); | ||||
|   inline ::capnp::AnyPointer::Builder initCap(); | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::_::StructBuilder _builder; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
|   friend class ::capnp::Orphanage; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::_::PointerHelpers; | ||||
| }; | ||||
| 
 | ||||
| #if !CAPNP_LITE | ||||
| class JoinResult::Pipeline { | ||||
| public: | ||||
|   typedef JoinResult Pipelines; | ||||
| 
 | ||||
|   inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} | ||||
|   inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) | ||||
|       : _typeless(kj::mv(typeless)) {} | ||||
| 
 | ||||
| private: | ||||
|   ::capnp::AnyPointer::Pipeline _typeless; | ||||
|   friend class ::capnp::PipelineHook; | ||||
|   template <typename, ::capnp::Kind> | ||||
|   friend struct ::capnp::ToDynamic_; | ||||
| }; | ||||
| #endif  // !CAPNP_LITE
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| inline  ::capnp::rpc::twoparty::Side VatId::Reader::getSide() const { | ||||
|   return _reader.getDataField< ::capnp::rpc::twoparty::Side>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| inline  ::capnp::rpc::twoparty::Side VatId::Builder::getSide() { | ||||
|   return _builder.getDataField< ::capnp::rpc::twoparty::Side>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| inline void VatId::Builder::setSide( ::capnp::rpc::twoparty::Side value) { | ||||
|   _builder.setDataField< ::capnp::rpc::twoparty::Side>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); | ||||
| } | ||||
| 
 | ||||
| inline  ::uint32_t ProvisionId::Reader::getJoinId() const { | ||||
|   return _reader.getDataField< ::uint32_t>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| inline  ::uint32_t ProvisionId::Builder::getJoinId() { | ||||
|   return _builder.getDataField< ::uint32_t>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| inline void ProvisionId::Builder::setJoinId( ::uint32_t value) { | ||||
|   _builder.setDataField< ::uint32_t>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); | ||||
| } | ||||
| 
 | ||||
| inline  ::uint32_t JoinKeyPart::Reader::getJoinId() const { | ||||
|   return _reader.getDataField< ::uint32_t>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| inline  ::uint32_t JoinKeyPart::Builder::getJoinId() { | ||||
|   return _builder.getDataField< ::uint32_t>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| inline void JoinKeyPart::Builder::setJoinId( ::uint32_t value) { | ||||
|   _builder.setDataField< ::uint32_t>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); | ||||
| } | ||||
| 
 | ||||
| inline  ::uint16_t JoinKeyPart::Reader::getPartCount() const { | ||||
|   return _reader.getDataField< ::uint16_t>( | ||||
|       ::capnp::bounded<2>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| inline  ::uint16_t JoinKeyPart::Builder::getPartCount() { | ||||
|   return _builder.getDataField< ::uint16_t>( | ||||
|       ::capnp::bounded<2>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| inline void JoinKeyPart::Builder::setPartCount( ::uint16_t value) { | ||||
|   _builder.setDataField< ::uint16_t>( | ||||
|       ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); | ||||
| } | ||||
| 
 | ||||
| inline  ::uint16_t JoinKeyPart::Reader::getPartNum() const { | ||||
|   return _reader.getDataField< ::uint16_t>( | ||||
|       ::capnp::bounded<3>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| inline  ::uint16_t JoinKeyPart::Builder::getPartNum() { | ||||
|   return _builder.getDataField< ::uint16_t>( | ||||
|       ::capnp::bounded<3>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| inline void JoinKeyPart::Builder::setPartNum( ::uint16_t value) { | ||||
|   _builder.setDataField< ::uint16_t>( | ||||
|       ::capnp::bounded<3>() * ::capnp::ELEMENTS, value); | ||||
| } | ||||
| 
 | ||||
| inline  ::uint32_t JoinResult::Reader::getJoinId() const { | ||||
|   return _reader.getDataField< ::uint32_t>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| inline  ::uint32_t JoinResult::Builder::getJoinId() { | ||||
|   return _builder.getDataField< ::uint32_t>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| inline void JoinResult::Builder::setJoinId( ::uint32_t value) { | ||||
|   _builder.setDataField< ::uint32_t>( | ||||
|       ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); | ||||
| } | ||||
| 
 | ||||
| inline bool JoinResult::Reader::getSucceeded() const { | ||||
|   return _reader.getDataField<bool>( | ||||
|       ::capnp::bounded<32>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| 
 | ||||
| inline bool JoinResult::Builder::getSucceeded() { | ||||
|   return _builder.getDataField<bool>( | ||||
|       ::capnp::bounded<32>() * ::capnp::ELEMENTS); | ||||
| } | ||||
| inline void JoinResult::Builder::setSucceeded(bool value) { | ||||
|   _builder.setDataField<bool>( | ||||
|       ::capnp::bounded<32>() * ::capnp::ELEMENTS, value); | ||||
| } | ||||
| 
 | ||||
| inline bool JoinResult::Reader::hasCap() const { | ||||
|   return !_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline bool JoinResult::Builder::hasCap() { | ||||
|   return !_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); | ||||
| } | ||||
| inline ::capnp::AnyPointer::Reader JoinResult::Reader::getCap() const { | ||||
|   return ::capnp::AnyPointer::Reader(_reader.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline ::capnp::AnyPointer::Builder JoinResult::Builder::getCap() { | ||||
|   return ::capnp::AnyPointer::Builder(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
| } | ||||
| inline ::capnp::AnyPointer::Builder JoinResult::Builder::initCap() { | ||||
|   auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( | ||||
|       ::capnp::bounded<0>() * ::capnp::POINTERS)); | ||||
|   result.clear(); | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| }  // namespace
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| #endif  // CAPNP_INCLUDED_a184c7885cdaf2a1_
 | ||||
| @ -0,0 +1,160 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_RPC_TWOPARTY_H_ | ||||
| #define CAPNP_RPC_TWOPARTY_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "rpc.h" | ||||
| #include "message.h" | ||||
| #include <kj/async-io.h> | ||||
| #include <capnp/rpc-twoparty.capnp.h> | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| namespace rpc { | ||||
|   namespace twoparty { | ||||
|     typedef VatId SturdyRefHostId;  // For backwards-compatibility with version 0.4.
 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| typedef VatNetwork<rpc::twoparty::VatId, rpc::twoparty::ProvisionId, | ||||
|     rpc::twoparty::RecipientId, rpc::twoparty::ThirdPartyCapId, rpc::twoparty::JoinResult> | ||||
|     TwoPartyVatNetworkBase; | ||||
| 
 | ||||
| class TwoPartyVatNetwork: public TwoPartyVatNetworkBase, | ||||
|                           private TwoPartyVatNetworkBase::Connection { | ||||
|   // A `VatNetwork` that consists of exactly two parties communicating over an arbitrary byte
 | ||||
|   // stream.  This is used to implement the common case of a client/server network.
 | ||||
|   //
 | ||||
|   // See `ez-rpc.h` for a simple interface for setting up two-party clients and servers.
 | ||||
|   // Use `TwoPartyVatNetwork` only if you need the advanced features.
 | ||||
| 
 | ||||
| public: | ||||
|   TwoPartyVatNetwork(kj::AsyncIoStream& stream, rpc::twoparty::Side side, | ||||
|                      ReaderOptions receiveOptions = ReaderOptions()); | ||||
|   KJ_DISALLOW_COPY(TwoPartyVatNetwork); | ||||
| 
 | ||||
|   kj::Promise<void> onDisconnect() { return disconnectPromise.addBranch(); } | ||||
|   // Returns a promise that resolves when the peer disconnects.
 | ||||
| 
 | ||||
|   rpc::twoparty::Side getSide() { return side; } | ||||
| 
 | ||||
|   // implements VatNetwork -----------------------------------------------------
 | ||||
| 
 | ||||
|   kj::Maybe<kj::Own<TwoPartyVatNetworkBase::Connection>> connect( | ||||
|       rpc::twoparty::VatId::Reader ref) override; | ||||
|   kj::Promise<kj::Own<TwoPartyVatNetworkBase::Connection>> accept() override; | ||||
| 
 | ||||
| private: | ||||
|   class OutgoingMessageImpl; | ||||
|   class IncomingMessageImpl; | ||||
| 
 | ||||
|   kj::AsyncIoStream& stream; | ||||
|   rpc::twoparty::Side side; | ||||
|   MallocMessageBuilder peerVatId; | ||||
|   ReaderOptions receiveOptions; | ||||
|   bool accepted = false; | ||||
| 
 | ||||
|   kj::Maybe<kj::Promise<void>> previousWrite; | ||||
|   // Resolves when the previous write completes.  This effectively serves as the write queue.
 | ||||
|   // Becomes null when shutdown() is called.
 | ||||
| 
 | ||||
|   kj::Own<kj::PromiseFulfiller<kj::Own<TwoPartyVatNetworkBase::Connection>>> acceptFulfiller; | ||||
|   // Fulfiller for the promise returned by acceptConnectionAsRefHost() on the client side, or the
 | ||||
|   // second call on the server side.  Never fulfilled, because there is only one connection.
 | ||||
| 
 | ||||
|   kj::ForkedPromise<void> disconnectPromise = nullptr; | ||||
| 
 | ||||
|   class FulfillerDisposer: public kj::Disposer { | ||||
|     // Hack:  TwoPartyVatNetwork is both a VatNetwork and a VatNetwork::Connection.  When the RPC
 | ||||
|     //   system detects (or initiates) a disconnection, it drops its reference to the Connection.
 | ||||
|     //   When all references have been dropped, then we want disconnectPromise to be fulfilled.
 | ||||
|     //   So we hand out Own<Connection>s with this disposer attached, so that we can detect when
 | ||||
|     //   they are dropped.
 | ||||
| 
 | ||||
|   public: | ||||
|     mutable kj::Own<kj::PromiseFulfiller<void>> fulfiller; | ||||
|     mutable uint refcount = 0; | ||||
| 
 | ||||
|     void disposeImpl(void* pointer) const override; | ||||
|   }; | ||||
|   FulfillerDisposer disconnectFulfiller; | ||||
| 
 | ||||
|   kj::Own<TwoPartyVatNetworkBase::Connection> asConnection(); | ||||
|   // Returns a pointer to this with the disposer set to disconnectFulfiller.
 | ||||
| 
 | ||||
|   // implements Connection -----------------------------------------------------
 | ||||
| 
 | ||||
|   rpc::twoparty::VatId::Reader getPeerVatId() override; | ||||
|   kj::Own<OutgoingRpcMessage> newOutgoingMessage(uint firstSegmentWordSize) override; | ||||
|   kj::Promise<kj::Maybe<kj::Own<IncomingRpcMessage>>> receiveIncomingMessage() override; | ||||
|   kj::Promise<void> shutdown() override; | ||||
| }; | ||||
| 
 | ||||
| class TwoPartyServer: private kj::TaskSet::ErrorHandler { | ||||
|   // Convenience class which implements a simple server which accepts connections on a listener
 | ||||
|   // socket and serices them as two-party connections.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit TwoPartyServer(Capability::Client bootstrapInterface); | ||||
| 
 | ||||
|   void accept(kj::Own<kj::AsyncIoStream>&& connection); | ||||
|   // Accepts the connection for servicing.
 | ||||
| 
 | ||||
|   kj::Promise<void> listen(kj::ConnectionReceiver& listener); | ||||
|   // Listens for connections on the given listener. The returned promise never resolves unless an
 | ||||
|   // exception is thrown while trying to accept. You may discard the returned promise to cancel
 | ||||
|   // listening.
 | ||||
| 
 | ||||
| private: | ||||
|   Capability::Client bootstrapInterface; | ||||
|   kj::TaskSet tasks; | ||||
| 
 | ||||
|   struct AcceptedConnection; | ||||
| 
 | ||||
|   void taskFailed(kj::Exception&& exception) override; | ||||
| }; | ||||
| 
 | ||||
| class TwoPartyClient { | ||||
|   // Convenience class which implements a simple client.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit TwoPartyClient(kj::AsyncIoStream& connection); | ||||
|   TwoPartyClient(kj::AsyncIoStream& connection, Capability::Client bootstrapInterface, | ||||
|                  rpc::twoparty::Side side = rpc::twoparty::Side::CLIENT); | ||||
| 
 | ||||
|   Capability::Client bootstrap(); | ||||
|   // Get the server's bootstrap interface.
 | ||||
| 
 | ||||
|   inline kj::Promise<void> onDisconnect() { return network.onDisconnect(); } | ||||
| 
 | ||||
| private: | ||||
|   TwoPartyVatNetwork network; | ||||
|   RpcSystem<rpc::twoparty::VatId> rpcSystem; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_RPC_TWOPARTY_H_
 | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -0,0 +1,537 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_RPC_H_ | ||||
| #define CAPNP_RPC_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "capability.h" | ||||
| #include "rpc-prelude.h" | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult> | ||||
| class VatNetwork; | ||||
| template <typename SturdyRefObjectId> | ||||
| class SturdyRefRestorer; | ||||
| 
 | ||||
| template <typename VatId> | ||||
| class BootstrapFactory: public _::BootstrapFactoryBase { | ||||
|   // Interface that constructs per-client bootstrap interfaces. Use this if you want each client
 | ||||
|   // who connects to see a different bootstrap interface based on their (authenticated) VatId.
 | ||||
|   // This allows an application to bootstrap off of the authentication performed at the VatNetwork
 | ||||
|   // level. (Typically VatId is some sort of public key.)
 | ||||
|   //
 | ||||
|   // This is only useful for multi-party networks. For TwoPartyVatNetwork, there's no reason to
 | ||||
|   // use a BootstrapFactory; just specify a single bootstrap capability in this case.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual Capability::Client createFor(typename VatId::Reader clientId) = 0; | ||||
|   // Create a bootstrap capability appropriate for exposing to the given client. VatNetwork will
 | ||||
|   // have authenticated the client VatId before this is called.
 | ||||
| 
 | ||||
| private: | ||||
|   Capability::Client baseCreateFor(AnyStruct::Reader clientId) override; | ||||
| }; | ||||
| 
 | ||||
| template <typename VatId> | ||||
| class RpcSystem: public _::RpcSystemBase { | ||||
|   // Represents the RPC system, which is the portal to objects available on the network.
 | ||||
|   //
 | ||||
|   // The RPC implementation sits on top of an implementation of `VatNetwork`.  The `VatNetwork`
 | ||||
|   // determines how to form connections between vats -- specifically, two-way, private, reliable,
 | ||||
|   // sequenced datagram connections.  The RPC implementation determines how to use such connections
 | ||||
|   // to manage object references and make method calls.
 | ||||
|   //
 | ||||
|   // See `makeRpcServer()` and `makeRpcClient()` below for convenient syntax for setting up an
 | ||||
|   // `RpcSystem` given a `VatNetwork`.
 | ||||
|   //
 | ||||
|   // See `ez-rpc.h` for an even simpler interface for setting up RPC in a typical two-party
 | ||||
|   // client/server scenario.
 | ||||
| 
 | ||||
| public: | ||||
|   template <typename ProvisionId, typename RecipientId, | ||||
|             typename ThirdPartyCapId, typename JoinResult> | ||||
|   RpcSystem( | ||||
|       VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|       kj::Maybe<Capability::Client> bootstrapInterface, | ||||
|       kj::Maybe<RealmGateway<>::Client> gateway = nullptr); | ||||
| 
 | ||||
|   template <typename ProvisionId, typename RecipientId, | ||||
|             typename ThirdPartyCapId, typename JoinResult> | ||||
|   RpcSystem( | ||||
|       VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|       BootstrapFactory<VatId>& bootstrapFactory, | ||||
|       kj::Maybe<RealmGateway<>::Client> gateway = nullptr); | ||||
| 
 | ||||
|   template <typename ProvisionId, typename RecipientId, | ||||
|             typename ThirdPartyCapId, typename JoinResult, | ||||
|             typename LocalSturdyRefObjectId> | ||||
|   RpcSystem( | ||||
|       VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|       SturdyRefRestorer<LocalSturdyRefObjectId>& restorer); | ||||
| 
 | ||||
|   RpcSystem(RpcSystem&& other) = default; | ||||
| 
 | ||||
|   Capability::Client bootstrap(typename VatId::Reader vatId); | ||||
|   // Connect to the given vat and return its bootstrap interface.
 | ||||
| 
 | ||||
|   Capability::Client restore(typename VatId::Reader hostId, AnyPointer::Reader objectId) | ||||
|       KJ_DEPRECATED("Please transition to using a bootstrap interface instead."); | ||||
|   // ** DEPRECATED **
 | ||||
|   //
 | ||||
|   // Restores the given SturdyRef from the network and return the capability representing it.
 | ||||
|   //
 | ||||
|   // `hostId` identifies the host from which to request the ref, in the format specified by the
 | ||||
|   // `VatNetwork` in use.  `objectId` is the object ID in whatever format is expected by said host.
 | ||||
|   //
 | ||||
|   // This method will be removed in a future version of Cap'n Proto. Instead, please transition
 | ||||
|   // to using bootstrap(), which is equivalent to calling restore() with a null `objectId`.
 | ||||
|   // You may emulate the old concept of object IDs by exporting a bootstrap interface which has
 | ||||
|   // methods that can be used to obtain other capabilities by ID.
 | ||||
| 
 | ||||
|   void setFlowLimit(size_t words); | ||||
|   // Sets the incoming call flow limit. If more than `words` worth of call messages have not yet
 | ||||
|   // received responses, the RpcSystem will not read further messages from the stream. This can be
 | ||||
|   // used as a crude way to prevent a resource exhaustion attack (or bug) in which a peer makes an
 | ||||
|   // excessive number of simultaneous calls that consume the receiver's RAM.
 | ||||
|   //
 | ||||
|   // There are some caveats. When over the flow limit, all messages are blocked, including returns.
 | ||||
|   // If the outstanding calls are themselves waiting on calls going in the opposite direction, the
 | ||||
|   // flow limit may prevent those calls from completing, leading to deadlock. However, a
 | ||||
|   // sufficiently high limit should make this unlikely.
 | ||||
|   //
 | ||||
|   // Note that a call's parameter size counts against the flow limit until the call returns, even
 | ||||
|   // if the recipient calls releaseParams() to free the parameter memory early. This is because
 | ||||
|   // releaseParams() may simply indicate that the parameters have been forwarded to another
 | ||||
|   // machine, but are still in-memory there. For illustration, say that Alice made a call to Bob
 | ||||
|   // who forwarded the call to Carol. Bob has imposed a flow limit on Alice. Alice's calls are
 | ||||
|   // being forwarded to Carol, so Bob never keeps the parameters in-memory for more than a brief
 | ||||
|   // period. However, the flow limit counts all calls that haven't returned, even if Bob has
 | ||||
|   // already freed the memory they consumed. You might argue that the right solution here is
 | ||||
|   // instead for Carol to impose her own flow limit on Bob. This has a serious problem, though:
 | ||||
|   // Bob might be forwarding requests to Carol on behalf of many different parties, not just Alice.
 | ||||
|   // If Alice can pump enough data to hit the Bob -> Carol flow limit, then those other parties
 | ||||
|   // will be disrupted. Thus, we can only really impose the limit on the Alice -> Bob link, which
 | ||||
|   // only affects Alice. We need that one flow limit to limit Alice's impact on the whole system,
 | ||||
|   // so it has to count all in-flight calls.
 | ||||
|   //
 | ||||
|   // In Sandstorm, flow limits are imposed by the supervisor on calls coming out of a grain, in
 | ||||
|   // order to prevent a grain from inundating the system with in-flight calls. In practice, the
 | ||||
|   // main time this happens is when a grain is pushing a large file download and doesn't implement
 | ||||
|   // proper cooperative flow control.
 | ||||
| }; | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult> | ||||
| RpcSystem<VatId> makeRpcServer( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|     Capability::Client bootstrapInterface); | ||||
| // Make an RPC server.  Typical usage (e.g. in a main() function):
 | ||||
| //
 | ||||
| //    MyEventLoop eventLoop;
 | ||||
| //    kj::WaitScope waitScope(eventLoop);
 | ||||
| //    MyNetwork network;
 | ||||
| //    MyMainInterface::Client bootstrap = makeMain();
 | ||||
| //    auto server = makeRpcServer(network, bootstrap);
 | ||||
| //    kj::NEVER_DONE.wait(waitScope);  // run forever
 | ||||
| //
 | ||||
| // See also ez-rpc.h, which has simpler instructions for the common case of a two-party
 | ||||
| // client-server RPC connection.
 | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult, typename RealmGatewayClient, | ||||
|           typename InternalRef = _::InternalRefFromRealmGatewayClient<RealmGatewayClient>, | ||||
|           typename ExternalRef = _::ExternalRefFromRealmGatewayClient<RealmGatewayClient>> | ||||
| RpcSystem<VatId> makeRpcServer( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|     Capability::Client bootstrapInterface, RealmGatewayClient gateway); | ||||
| // Make an RPC server for a VatNetwork that resides in a different realm from the application.
 | ||||
| // The given RealmGateway is used to translate SturdyRefs between the app's ("internal") format
 | ||||
| // and the network's ("external") format.
 | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult> | ||||
| RpcSystem<VatId> makeRpcServer( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|     BootstrapFactory<VatId>& bootstrapFactory); | ||||
| // Make an RPC server that can serve different bootstrap interfaces to different clients via a
 | ||||
| // BootstrapInterface.
 | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult, typename RealmGatewayClient, | ||||
|           typename InternalRef = _::InternalRefFromRealmGatewayClient<RealmGatewayClient>, | ||||
|           typename ExternalRef = _::ExternalRefFromRealmGatewayClient<RealmGatewayClient>> | ||||
| RpcSystem<VatId> makeRpcServer( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|     BootstrapFactory<VatId>& bootstrapFactory, RealmGatewayClient gateway); | ||||
| // Make an RPC server that can serve different bootstrap interfaces to different clients via a
 | ||||
| // BootstrapInterface and communicates with a different realm than the application is in via a
 | ||||
| // RealmGateway.
 | ||||
| 
 | ||||
| template <typename VatId, typename LocalSturdyRefObjectId, | ||||
|           typename ProvisionId, typename RecipientId, typename ThirdPartyCapId, typename JoinResult> | ||||
| RpcSystem<VatId> makeRpcServer( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|     SturdyRefRestorer<LocalSturdyRefObjectId>& restorer) | ||||
|     KJ_DEPRECATED("Please transition to using a bootstrap interface instead."); | ||||
| // ** DEPRECATED **
 | ||||
| //
 | ||||
| // Create an RPC server which exports multiple main interfaces by object ID. The `restorer` object
 | ||||
| // can be used to look up objects by ID.
 | ||||
| //
 | ||||
| // Please transition to exporting only one interface, which is known as the "bootstrap" interface.
 | ||||
| // For backwards-compatibility with old clients, continue to implement SturdyRefRestorer, but
 | ||||
| // return the new bootstrap interface when the request object ID is null. When new clients connect
 | ||||
| // and request the bootstrap interface, they will get that interface. Eventually, once all clients
 | ||||
| // are updated to request only the bootstrap interface, stop implementing SturdyRefRestorer and
 | ||||
| // switch to passing the bootstrap capability itself as the second parameter to `makeRpcServer()`.
 | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, | ||||
|           typename RecipientId, typename ThirdPartyCapId, typename JoinResult> | ||||
| RpcSystem<VatId> makeRpcClient( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network); | ||||
| // Make an RPC client.  Typical usage (e.g. in a main() function):
 | ||||
| //
 | ||||
| //    MyEventLoop eventLoop;
 | ||||
| //    kj::WaitScope waitScope(eventLoop);
 | ||||
| //    MyNetwork network;
 | ||||
| //    auto client = makeRpcClient(network);
 | ||||
| //    MyCapability::Client cap = client.restore(hostId, objId).castAs<MyCapability>();
 | ||||
| //    auto response = cap.fooRequest().send().wait(waitScope);
 | ||||
| //    handleMyResponse(response);
 | ||||
| //
 | ||||
| // See also ez-rpc.h, which has simpler instructions for the common case of a two-party
 | ||||
| // client-server RPC connection.
 | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult, typename RealmGatewayClient, | ||||
|           typename InternalRef = _::InternalRefFromRealmGatewayClient<RealmGatewayClient>, | ||||
|           typename ExternalRef = _::ExternalRefFromRealmGatewayClient<RealmGatewayClient>> | ||||
| RpcSystem<VatId> makeRpcClient( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|     RealmGatewayClient gateway); | ||||
| // Make an RPC client for a VatNetwork that resides in a different realm from the application.
 | ||||
| // The given RealmGateway is used to translate SturdyRefs between the app's ("internal") format
 | ||||
| // and the network's ("external") format.
 | ||||
| 
 | ||||
| template <typename SturdyRefObjectId> | ||||
| class SturdyRefRestorer: public _::SturdyRefRestorerBase { | ||||
|   // ** DEPRECATED **
 | ||||
|   //
 | ||||
|   // In Cap'n Proto 0.4.x, applications could export multiple main interfaces identified by
 | ||||
|   // object IDs. The callback used to map object IDs to objects was `SturdyRefRestorer`, as we
 | ||||
|   // imagined this would eventually be used for restoring SturdyRefs as well. In practice, it was
 | ||||
|   // never used for real SturdyRefs, only for exporting singleton objects under well-known names.
 | ||||
|   //
 | ||||
|   // The new preferred strategy is to export only a _single_ such interface, called the
 | ||||
|   // "bootstrap interface". That interface can itself have methods for obtaining other objects, of
 | ||||
|   // course, but that is up to the app. `SturdyRefRestorer` exists for backwards-compatibility.
 | ||||
|   //
 | ||||
|   // Hint:  Use SturdyRefRestorer<capnp::Text> to define a server that exports services under
 | ||||
|   //   string names.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual Capability::Client restore(typename SturdyRefObjectId::Reader ref) | ||||
|       KJ_DEPRECATED( | ||||
|           "Please transition to using bootstrap interfaces instead of SturdyRefRestorer.") = 0; | ||||
|   // Restore the given object, returning a capability representing it.
 | ||||
| 
 | ||||
| private: | ||||
|   Capability::Client baseRestore(AnyPointer::Reader ref) override final; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // VatNetwork
 | ||||
| 
 | ||||
| class OutgoingRpcMessage { | ||||
|   // A message to be sent by a `VatNetwork`.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual AnyPointer::Builder getBody() = 0; | ||||
|   // Get the message body, which the caller may fill in any way it wants.  (The standard RPC
 | ||||
|   // implementation initializes it as a Message as defined in rpc.capnp.)
 | ||||
| 
 | ||||
|   virtual void send() = 0; | ||||
|   // Send the message, or at least put it in a queue to be sent later.  Note that the builder
 | ||||
|   // returned by `getBody()` remains valid at least until the `OutgoingRpcMessage` is destroyed.
 | ||||
| }; | ||||
| 
 | ||||
| class IncomingRpcMessage { | ||||
|   // A message received from a `VatNetwork`.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual AnyPointer::Reader getBody() = 0; | ||||
|   // Get the message body, to be interpreted by the caller.  (The standard RPC implementation
 | ||||
|   // interprets it as a Message as defined in rpc.capnp.)
 | ||||
| }; | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult> | ||||
| class VatNetwork: public _::VatNetworkBase { | ||||
|   // Cap'n Proto RPC operates between vats, where a "vat" is some sort of host of objects.
 | ||||
|   // Typically one Cap'n Proto process (in the Unix sense) is one vat.  The RPC system is what
 | ||||
|   // allows calls between objects hosted in different vats.
 | ||||
|   //
 | ||||
|   // The RPC implementation sits on top of an implementation of `VatNetwork`.  The `VatNetwork`
 | ||||
|   // determines how to form connections between vats -- specifically, two-way, private, reliable,
 | ||||
|   // sequenced datagram connections.  The RPC implementation determines how to use such connections
 | ||||
|   // to manage object references and make method calls.
 | ||||
|   //
 | ||||
|   // The most common implementation of VatNetwork is TwoPartyVatNetwork (rpc-twoparty.h).  Most
 | ||||
|   // simple client-server apps will want to use it.  (You may even want to use the EZ RPC
 | ||||
|   // interfaces in `ez-rpc.h` and avoid all of this.)
 | ||||
|   //
 | ||||
|   // TODO(someday):  Provide a standard implementation for the public internet.
 | ||||
| 
 | ||||
| public: | ||||
|   class Connection; | ||||
| 
 | ||||
|   struct ConnectionAndProvisionId { | ||||
|     // Result of connecting to a vat introduced by another vat.
 | ||||
| 
 | ||||
|     kj::Own<Connection> connection; | ||||
|     // Connection to the new vat.
 | ||||
| 
 | ||||
|     kj::Own<OutgoingRpcMessage> firstMessage; | ||||
|     // An already-allocated `OutgoingRpcMessage` associated with `connection`.  The RPC system will
 | ||||
|     // construct this as an `Accept` message and send it.
 | ||||
| 
 | ||||
|     Orphan<ProvisionId> provisionId; | ||||
|     // A `ProvisionId` already allocated inside `firstMessage`, which the RPC system will use to
 | ||||
|     // build the `Accept` message.
 | ||||
|   }; | ||||
| 
 | ||||
|   class Connection: public _::VatNetworkBase::Connection { | ||||
|     // A two-way RPC connection.
 | ||||
|     //
 | ||||
|     // This object may represent a connection that doesn't exist yet, but is expected to exist
 | ||||
|     // in the future.  In this case, sent messages will automatically be queued and sent once the
 | ||||
|     // connection is ready, so that the caller doesn't need to know the difference.
 | ||||
| 
 | ||||
|   public: | ||||
|     // Level 0 features ----------------------------------------------
 | ||||
| 
 | ||||
|     virtual typename VatId::Reader getPeerVatId() = 0; | ||||
|     // Returns the connected vat's authenticated VatId. It is the VatNetwork's responsibility to
 | ||||
|     // authenticate this, so that the caller can be assured that they are really talking to the
 | ||||
|     // identified vat and not an imposter.
 | ||||
| 
 | ||||
|     virtual kj::Own<OutgoingRpcMessage> newOutgoingMessage(uint firstSegmentWordSize) override = 0; | ||||
|     // Allocate a new message to be sent on this connection.
 | ||||
|     //
 | ||||
|     // If `firstSegmentWordSize` is non-zero, it should be treated as a hint suggesting how large
 | ||||
|     // to make the first segment.  This is entirely a hint and the connection may adjust it up or
 | ||||
|     // down.  If it is zero, the connection should choose the size itself.
 | ||||
| 
 | ||||
|     virtual kj::Promise<kj::Maybe<kj::Own<IncomingRpcMessage>>> receiveIncomingMessage() override = 0; | ||||
|     // Wait for a message to be received and return it.  If the read stream cleanly terminates,
 | ||||
|     // return null.  If any other problem occurs, throw an exception.
 | ||||
| 
 | ||||
|     virtual kj::Promise<void> shutdown() override KJ_WARN_UNUSED_RESULT = 0; | ||||
|     // Waits until all outgoing messages have been sent, then shuts down the outgoing stream. The
 | ||||
|     // returned promise resolves after shutdown is complete.
 | ||||
| 
 | ||||
|   private: | ||||
|     AnyStruct::Reader baseGetPeerVatId() override; | ||||
|   }; | ||||
| 
 | ||||
|   // Level 0 features ------------------------------------------------
 | ||||
| 
 | ||||
|   virtual kj::Maybe<kj::Own<Connection>> connect(typename VatId::Reader hostId) = 0; | ||||
|   // Connect to a VatId.  Note that this method immediately returns a `Connection`, even
 | ||||
|   // if the network connection has not yet been established.  Messages can be queued to this
 | ||||
|   // connection and will be delivered once it is open.  The caller must attempt to read from the
 | ||||
|   // connection to verify that it actually succeeded; the read will fail if the connection
 | ||||
|   // couldn't be opened.  Some network implementations may actually start sending messages before
 | ||||
|   // hearing back from the server at all, to avoid a round trip.
 | ||||
|   //
 | ||||
|   // Returns nullptr if `hostId` refers to the local host.
 | ||||
| 
 | ||||
|   virtual kj::Promise<kj::Own<Connection>> accept() = 0; | ||||
|   // Wait for the next incoming connection and return it.
 | ||||
| 
 | ||||
|   // Level 4 features ------------------------------------------------
 | ||||
|   // TODO(someday)
 | ||||
| 
 | ||||
| private: | ||||
|   kj::Maybe<kj::Own<_::VatNetworkBase::Connection>> | ||||
|       baseConnect(AnyStruct::Reader hostId) override final; | ||||
|   kj::Promise<kj::Own<_::VatNetworkBase::Connection>> baseAccept() override final; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // ***************************************************************************************
 | ||||
| // Inline implementation details start here
 | ||||
| // ***************************************************************************************
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| template <typename VatId> | ||||
| Capability::Client BootstrapFactory<VatId>::baseCreateFor(AnyStruct::Reader clientId) { | ||||
|   return createFor(clientId.as<VatId>()); | ||||
| } | ||||
| 
 | ||||
| template <typename SturdyRef, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult> | ||||
| kj::Maybe<kj::Own<_::VatNetworkBase::Connection>> | ||||
|     VatNetwork<SturdyRef, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>:: | ||||
|     baseConnect(AnyStruct::Reader ref) { | ||||
|   auto maybe = connect(ref.as<SturdyRef>()); | ||||
|   return maybe.map([](kj::Own<Connection>& conn) -> kj::Own<_::VatNetworkBase::Connection> { | ||||
|     return kj::mv(conn); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| template <typename SturdyRef, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult> | ||||
| kj::Promise<kj::Own<_::VatNetworkBase::Connection>> | ||||
|     VatNetwork<SturdyRef, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>::baseAccept() { | ||||
|   return accept().then( | ||||
|       [](kj::Own<Connection>&& connection) -> kj::Own<_::VatNetworkBase::Connection> { | ||||
|     return kj::mv(connection); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| template <typename SturdyRef, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult> | ||||
| AnyStruct::Reader VatNetwork< | ||||
|     SturdyRef, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>:: | ||||
|     Connection::baseGetPeerVatId() { | ||||
|   return getPeerVatId(); | ||||
| } | ||||
| 
 | ||||
| template <typename SturdyRef> | ||||
| Capability::Client SturdyRefRestorer<SturdyRef>::baseRestore(AnyPointer::Reader ref) { | ||||
| #pragma GCC diagnostic push | ||||
| #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | ||||
|   return restore(ref.getAs<SturdyRef>()); | ||||
| #pragma GCC diagnostic pop | ||||
| } | ||||
| 
 | ||||
| template <typename VatId> | ||||
| template <typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult> | ||||
| RpcSystem<VatId>::RpcSystem( | ||||
|       VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|       kj::Maybe<Capability::Client> bootstrap, | ||||
|       kj::Maybe<RealmGateway<>::Client> gateway) | ||||
|     : _::RpcSystemBase(network, kj::mv(bootstrap), kj::mv(gateway)) {} | ||||
| 
 | ||||
| template <typename VatId> | ||||
| template <typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult> | ||||
| RpcSystem<VatId>::RpcSystem( | ||||
|       VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|       BootstrapFactory<VatId>& bootstrapFactory, | ||||
|       kj::Maybe<RealmGateway<>::Client> gateway) | ||||
|     : _::RpcSystemBase(network, bootstrapFactory, kj::mv(gateway)) {} | ||||
| 
 | ||||
| template <typename VatId> | ||||
| template <typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult, | ||||
|           typename LocalSturdyRefObjectId> | ||||
| RpcSystem<VatId>::RpcSystem( | ||||
|       VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|       SturdyRefRestorer<LocalSturdyRefObjectId>& restorer) | ||||
|     : _::RpcSystemBase(network, restorer) {} | ||||
| 
 | ||||
| template <typename VatId> | ||||
| Capability::Client RpcSystem<VatId>::bootstrap(typename VatId::Reader vatId) { | ||||
|   return baseBootstrap(_::PointerHelpers<VatId>::getInternalReader(vatId)); | ||||
| } | ||||
| 
 | ||||
| template <typename VatId> | ||||
| Capability::Client RpcSystem<VatId>::restore( | ||||
|     typename VatId::Reader hostId, AnyPointer::Reader objectId) { | ||||
|   return baseRestore(_::PointerHelpers<VatId>::getInternalReader(hostId), objectId); | ||||
| } | ||||
| 
 | ||||
| template <typename VatId> | ||||
| inline void RpcSystem<VatId>::setFlowLimit(size_t words) { | ||||
|   baseSetFlowLimit(words); | ||||
| } | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult> | ||||
| RpcSystem<VatId> makeRpcServer( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|     Capability::Client bootstrapInterface) { | ||||
|   return RpcSystem<VatId>(network, kj::mv(bootstrapInterface)); | ||||
| } | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult, | ||||
|           typename RealmGatewayClient, typename InternalRef, typename ExternalRef> | ||||
| RpcSystem<VatId> makeRpcServer( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|     Capability::Client bootstrapInterface, RealmGatewayClient gateway) { | ||||
|   return RpcSystem<VatId>(network, kj::mv(bootstrapInterface), | ||||
|       gateway.template castAs<RealmGateway<>>()); | ||||
| } | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult> | ||||
| RpcSystem<VatId> makeRpcServer( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|     BootstrapFactory<VatId>& bootstrapFactory) { | ||||
|   return RpcSystem<VatId>(network, bootstrapFactory); | ||||
| } | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, typename RecipientId, | ||||
|           typename ThirdPartyCapId, typename JoinResult, | ||||
|           typename RealmGatewayClient, typename InternalRef, typename ExternalRef> | ||||
| RpcSystem<VatId> makeRpcServer( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|     BootstrapFactory<VatId>& bootstrapFactory, RealmGatewayClient gateway) { | ||||
|   return RpcSystem<VatId>(network, bootstrapFactory, gateway.template castAs<RealmGateway<>>()); | ||||
| } | ||||
| 
 | ||||
| template <typename VatId, typename LocalSturdyRefObjectId, | ||||
|           typename ProvisionId, typename RecipientId, typename ThirdPartyCapId, typename JoinResult> | ||||
| RpcSystem<VatId> makeRpcServer( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|     SturdyRefRestorer<LocalSturdyRefObjectId>& restorer) { | ||||
|   return RpcSystem<VatId>(network, restorer); | ||||
| } | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, | ||||
|           typename RecipientId, typename ThirdPartyCapId, typename JoinResult> | ||||
| RpcSystem<VatId> makeRpcClient( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network) { | ||||
|   return RpcSystem<VatId>(network, nullptr); | ||||
| } | ||||
| 
 | ||||
| template <typename VatId, typename ProvisionId, | ||||
|           typename RecipientId, typename ThirdPartyCapId, typename JoinResult, | ||||
|           typename RealmGatewayClient, typename InternalRef, typename ExternalRef> | ||||
| RpcSystem<VatId> makeRpcClient( | ||||
|     VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network, | ||||
|     RealmGatewayClient gateway) { | ||||
|   return RpcSystem<VatId>(network, nullptr, gateway.template castAs<RealmGateway<>>()); | ||||
| } | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_RPC_H_
 | ||||
| @ -0,0 +1,48 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_SCHEMA_LITE_H_ | ||||
| #define CAPNP_SCHEMA_LITE_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include <capnp/schema.capnp.h> | ||||
| #include "message.h" | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| template <typename T, typename CapnpPrivate = typename T::_capnpPrivate> | ||||
| inline schema::Node::Reader schemaProto() { | ||||
|   // Get the schema::Node for this type's schema. This function works even in lite mode.
 | ||||
|   return readMessageUnchecked<schema::Node>(CapnpPrivate::encodedSchema()); | ||||
| } | ||||
| 
 | ||||
| template <typename T, uint64_t id = schemas::EnumInfo<T>::typeId> | ||||
| inline schema::Node::Reader schemaProto() { | ||||
|   // Get the schema::Node for this type's schema. This function works even in lite mode.
 | ||||
|   return readMessageUnchecked<schema::Node>(schemas::EnumInfo<T>::encodedSchema()); | ||||
| } | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_SCHEMA_LITE_H_
 | ||||
| @ -0,0 +1,173 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_SCHEMA_LOADER_H_ | ||||
| #define CAPNP_SCHEMA_LOADER_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "schema.h" | ||||
| #include <kj/memory.h> | ||||
| #include <kj/mutex.h> | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| class SchemaLoader { | ||||
|   // Class which can be used to construct Schema objects from schema::Nodes as defined in
 | ||||
|   // schema.capnp.
 | ||||
|   //
 | ||||
|   // It is a bad idea to use this class on untrusted input with exceptions disabled -- you may
 | ||||
|   // be exposing yourself to denial-of-service attacks, as attackers can easily construct schemas
 | ||||
|   // that are subtly inconsistent in a way that causes exceptions to be thrown either by
 | ||||
|   // SchemaLoader or by the dynamic API when the schemas are subsequently used.  If you enable and
 | ||||
|   // properly catch exceptions, you should be OK -- assuming no bugs in the Cap'n Proto
 | ||||
|   // implementation, of course.
 | ||||
| 
 | ||||
| public: | ||||
|   class LazyLoadCallback { | ||||
|   public: | ||||
|     virtual void load(const SchemaLoader& loader, uint64_t id) const = 0; | ||||
|     // Request that the schema node with the given ID be loaded into the given SchemaLoader.  If
 | ||||
|     // the callback is able to find a schema for this ID, it should invoke `loadOnce()` on
 | ||||
|     // `loader` to load it.  If no such node exists, it should simply do nothing and return.
 | ||||
|     //
 | ||||
|     // The callback is allowed to load schema nodes other than the one requested, e.g. because it
 | ||||
|     // expects they will be needed soon.
 | ||||
|     //
 | ||||
|     // If the `SchemaLoader` is used from multiple threads, the callback must be thread-safe.
 | ||||
|     // In particular, it's possible for multiple threads to invoke `load()` with the same ID.
 | ||||
|     // If the callback performs a large amount of work to look up IDs, it should be sure to
 | ||||
|     // de-dup these requests.
 | ||||
|   }; | ||||
| 
 | ||||
|   SchemaLoader(); | ||||
| 
 | ||||
|   SchemaLoader(const LazyLoadCallback& callback); | ||||
|   // Construct a SchemaLoader which will invoke the given callback when a schema node is requested
 | ||||
|   // that isn't already loaded.
 | ||||
| 
 | ||||
|   ~SchemaLoader() noexcept(false); | ||||
|   KJ_DISALLOW_COPY(SchemaLoader); | ||||
| 
 | ||||
|   Schema get(uint64_t id, schema::Brand::Reader brand = schema::Brand::Reader(), | ||||
|              Schema scope = Schema()) const; | ||||
|   // Gets the schema for the given ID, throwing an exception if it isn't present.
 | ||||
|   //
 | ||||
|   // The returned schema may be invalidated if load() is called with a new schema for the same ID.
 | ||||
|   // In general, you should not call load() while a schema from this loader is in-use.
 | ||||
|   //
 | ||||
|   // `brand` and `scope` are used to determine brand bindings where relevant. `brand` gives
 | ||||
|   // parameter bindings for the target type's brand parameters that were specified at the reference
 | ||||
|   // site. `scope` specifies the scope in which the type ID appeared -- if `brand` itself contains
 | ||||
|   // parameter references or indicates that some parameters will be inherited, these will be
 | ||||
|   // interpreted within / inherited from `scope`.
 | ||||
| 
 | ||||
|   kj::Maybe<Schema> tryGet(uint64_t id, schema::Brand::Reader bindings = schema::Brand::Reader(), | ||||
|                            Schema scope = Schema()) const; | ||||
|   // Like get() but doesn't throw.
 | ||||
| 
 | ||||
|   Schema getUnbound(uint64_t id) const; | ||||
|   // Gets a special version of the schema in which all brand parameters are "unbound". This means
 | ||||
|   // that if you look up a type via the Schema API, and it resolves to a brand parameter, the
 | ||||
|   // returned Type's getBrandParameter() method will return info about that parameter. Otherwise,
 | ||||
|   // normally, all brand parameters that aren't otherwise bound are assumed to simply be
 | ||||
|   // "AnyPointer".
 | ||||
| 
 | ||||
|   Type getType(schema::Type::Reader type, Schema scope = Schema()) const; | ||||
|   // Convenience method which interprets a schema::Type to produce a Type object. Implemented in
 | ||||
|   // terms of get().
 | ||||
| 
 | ||||
|   Schema load(const schema::Node::Reader& reader); | ||||
|   // Loads the given schema node.  Validates the node and throws an exception if invalid.  This
 | ||||
|   // makes a copy of the schema, so the object passed in can be destroyed after this returns.
 | ||||
|   //
 | ||||
|   // If the node has any dependencies which are not already loaded, they will be initialized as
 | ||||
|   // stubs -- empty schemas of whichever kind is expected.
 | ||||
|   //
 | ||||
|   // If another schema for the given reader has already been seen, the loader will inspect both
 | ||||
|   // schemas to determine which one is newer, and use that that one.  If the two versions are
 | ||||
|   // found to be incompatible, an exception is thrown.  If the two versions differ but are
 | ||||
|   // compatible and the loader cannot determine which is newer (e.g., the only changes are renames),
 | ||||
|   // the existing schema will be preferred.  Note that in any case, the loader will end up keeping
 | ||||
|   // around copies of both schemas, so you shouldn't repeatedly reload schemas into the same loader.
 | ||||
|   //
 | ||||
|   // The following properties of the schema node are validated:
 | ||||
|   // - Struct size and preferred list encoding are valid and consistent.
 | ||||
|   // - Struct members are fields or unions.
 | ||||
|   // - Union members are fields.
 | ||||
|   // - Field offsets are in-bounds.
 | ||||
|   // - Ordinals and codeOrders are sequential starting from zero.
 | ||||
|   // - Values are of the right union case to match their types.
 | ||||
|   //
 | ||||
|   // You should assume anything not listed above is NOT validated.  In particular, things that are
 | ||||
|   // not validated now, but could be in the future, include but are not limited to:
 | ||||
|   // - Names.
 | ||||
|   // - Annotation values.  (This is hard because the annotation declaration is not always
 | ||||
|   //   available.)
 | ||||
|   // - Content of default/constant values of pointer type.  (Validating these would require knowing
 | ||||
|   //   their schema, but even if the schemas are available at validation time, they could be
 | ||||
|   //   updated by a subsequent load(), invalidating existing values.  Instead, these values are
 | ||||
|   //   validated at the time they are used, as usual for Cap'n Proto objects.)
 | ||||
|   //
 | ||||
|   // Also note that unknown types are not considered invalid.  Instead, the dynamic API returns
 | ||||
|   // a DynamicValue with type UNKNOWN for these.
 | ||||
| 
 | ||||
|   Schema loadOnce(const schema::Node::Reader& reader) const; | ||||
|   // Like `load()` but does nothing if a schema with the same ID is already loaded.  In contrast,
 | ||||
|   // `load()` would attempt to compare the schemas and take the newer one.  `loadOnce()` is safe
 | ||||
|   // to call even while concurrently using schemas from this loader.  It should be considered an
 | ||||
|   // error to call `loadOnce()` with two non-identical schemas that share the same ID, although
 | ||||
|   // this error may or may not actually be detected by the implementation.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   void loadCompiledTypeAndDependencies(); | ||||
|   // Load the schema for the given compiled-in type and all of its dependencies.
 | ||||
|   //
 | ||||
|   // If you want to be able to cast a DynamicValue built from this SchemaLoader to the compiled-in
 | ||||
|   // type using as<T>(), you must call this method before constructing the DynamicValue.  Otherwise,
 | ||||
|   // as<T>() will throw an exception complaining about type mismatch.
 | ||||
| 
 | ||||
|   kj::Array<Schema> getAllLoaded() const; | ||||
|   // Get a complete list of all loaded schema nodes.  It is particularly useful to call this after
 | ||||
|   // loadCompiledTypeAndDependencies<T>() in order to get a flat list of all of T's transitive
 | ||||
|   // dependencies.
 | ||||
| 
 | ||||
| private: | ||||
|   class Validator; | ||||
|   class CompatibilityChecker; | ||||
|   class Impl; | ||||
|   class InitializerImpl; | ||||
|   class BrandedInitializerImpl; | ||||
|   kj::MutexGuarded<kj::Own<Impl>> impl; | ||||
| 
 | ||||
|   void loadNative(const _::RawSchema* nativeSchema); | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| inline void SchemaLoader::loadCompiledTypeAndDependencies() { | ||||
|   loadNative(&_::rawSchema<T>()); | ||||
| } | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_SCHEMA_LOADER_H_
 | ||||
| @ -0,0 +1,207 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_SCHEMA_PARSER_H_ | ||||
| #define CAPNP_SCHEMA_PARSER_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "schema-loader.h" | ||||
| #include <kj/string.h> | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| class ParsedSchema; | ||||
| class SchemaFile; | ||||
| 
 | ||||
| class SchemaParser { | ||||
|   // Parses `.capnp` files to produce `Schema` objects.
 | ||||
|   //
 | ||||
|   // This class is thread-safe, hence all its methods are const.
 | ||||
| 
 | ||||
| public: | ||||
|   SchemaParser(); | ||||
|   ~SchemaParser() noexcept(false); | ||||
| 
 | ||||
|   ParsedSchema parseDiskFile(kj::StringPtr displayName, kj::StringPtr diskPath, | ||||
|                              kj::ArrayPtr<const kj::StringPtr> importPath) const; | ||||
|   // Parse a file located on disk.  Throws an exception if the file dosen't exist.
 | ||||
|   //
 | ||||
|   // Parameters:
 | ||||
|   // * `displayName`:  The name that will appear in the file's schema node.  (If the file has
 | ||||
|   //   already been parsed, this will be ignored and the display name from the first time it was
 | ||||
|   //   parsed will be kept.)
 | ||||
|   // * `diskPath`:  The path to the file on disk.
 | ||||
|   // * `importPath`:  Directories to search when resolving absolute imports within this file
 | ||||
|   //   (imports that start with a `/`).  Must remain valid until the SchemaParser is destroyed.
 | ||||
|   //   (If the file has already been parsed, this will be ignored and the import path from the
 | ||||
|   //   first time it was parsed will be kept.)
 | ||||
|   //
 | ||||
|   // This method is a shortcut, equivalent to:
 | ||||
|   //     parser.parseFile(SchemaFile::newDiskFile(displayName, diskPath, importPath))`;
 | ||||
|   //
 | ||||
|   // This method throws an exception if any errors are encountered in the file or in anything the
 | ||||
|   // file depends on.  Note that merely importing another file does not count as a dependency on
 | ||||
|   // anything in the imported file -- only the imported types which are actually used are
 | ||||
|   // "dependencies".
 | ||||
| 
 | ||||
|   ParsedSchema parseFile(kj::Own<SchemaFile>&& file) const; | ||||
|   // Advanced interface for parsing a file that may or may not be located in any global namespace.
 | ||||
|   // Most users will prefer `parseDiskFile()`.
 | ||||
|   //
 | ||||
|   // If the file has already been parsed (that is, a SchemaFile that compares equal to this one
 | ||||
|   // was parsed previously), the existing schema will be returned again.
 | ||||
|   //
 | ||||
|   // This method reports errors by calling SchemaFile::reportError() on the file where the error
 | ||||
|   // is located.  If that call does not throw an exception, `parseFile()` may in fact return
 | ||||
|   // normally.  In this case, the result is a best-effort attempt to compile the schema, but it
 | ||||
|   // may be invalid or corrupt, and using it for anything may cause exceptions to be thrown.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   inline void loadCompiledTypeAndDependencies() { | ||||
|     // See SchemaLoader::loadCompiledTypeAndDependencies().
 | ||||
|     getLoader().loadCompiledTypeAndDependencies<T>(); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   struct Impl; | ||||
|   class ModuleImpl; | ||||
|   kj::Own<Impl> impl; | ||||
|   mutable bool hadErrors = false; | ||||
| 
 | ||||
|   ModuleImpl& getModuleImpl(kj::Own<SchemaFile>&& file) const; | ||||
|   SchemaLoader& getLoader(); | ||||
| 
 | ||||
|   friend class ParsedSchema; | ||||
| }; | ||||
| 
 | ||||
| class ParsedSchema: public Schema { | ||||
|   // ParsedSchema is an extension of Schema which also has the ability to look up nested nodes
 | ||||
|   // by name.  See `SchemaParser`.
 | ||||
| 
 | ||||
| public: | ||||
|   inline ParsedSchema(): parser(nullptr) {} | ||||
| 
 | ||||
|   kj::Maybe<ParsedSchema> findNested(kj::StringPtr name) const; | ||||
|   // Gets the nested node with the given name, or returns null if there is no such nested
 | ||||
|   // declaration.
 | ||||
| 
 | ||||
|   ParsedSchema getNested(kj::StringPtr name) const; | ||||
|   // Gets the nested node with the given name, or throws an exception if there is no such nested
 | ||||
|   // declaration.
 | ||||
| 
 | ||||
| private: | ||||
|   inline ParsedSchema(Schema inner, const SchemaParser& parser): Schema(inner), parser(&parser) {} | ||||
| 
 | ||||
|   const SchemaParser* parser; | ||||
|   friend class SchemaParser; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Advanced API
 | ||||
| 
 | ||||
| class SchemaFile { | ||||
|   // Abstract interface representing a schema file.  You can implement this yourself in order to
 | ||||
|   // gain more control over how the compiler resolves imports and reads files.  For the
 | ||||
|   // common case of files on disk or other global filesystem-like namespaces, use
 | ||||
|   // `SchemaFile::newDiskFile()`.
 | ||||
| 
 | ||||
| public: | ||||
|   class FileReader { | ||||
|   public: | ||||
|     virtual bool exists(kj::StringPtr path) const = 0; | ||||
|     virtual kj::Array<const char> read(kj::StringPtr path) const = 0; | ||||
|   }; | ||||
| 
 | ||||
|   class DiskFileReader final: public FileReader { | ||||
|     // Implementation of FileReader that uses the local disk.  Files are read using mmap() if
 | ||||
|     // possible.
 | ||||
| 
 | ||||
|   public: | ||||
|     static const DiskFileReader instance; | ||||
| 
 | ||||
|     bool exists(kj::StringPtr path) const override; | ||||
|     kj::Array<const char> read(kj::StringPtr path) const override; | ||||
|   }; | ||||
| 
 | ||||
|   static kj::Own<SchemaFile> newDiskFile( | ||||
|       kj::StringPtr displayName, kj::StringPtr diskPath, | ||||
|       kj::ArrayPtr<const kj::StringPtr> importPath, | ||||
|       const FileReader& fileReader = DiskFileReader::instance); | ||||
|   // Construct a SchemaFile representing a file on disk (or located in the filesystem-like
 | ||||
|   // namespace represented by `fileReader`).
 | ||||
|   //
 | ||||
|   // Parameters:
 | ||||
|   // * `displayName`:  The name that will appear in the file's schema node.
 | ||||
|   // * `diskPath`:  The path to the file on disk.
 | ||||
|   // * `importPath`:  Directories to search when resolving absolute imports within this file
 | ||||
|   //   (imports that start with a `/`).  The array content must remain valid as long as the
 | ||||
|   //   SchemaFile exists (which is at least as long as the SchemaParser that parses it exists).
 | ||||
|   // * `fileReader`:  Allows you to use a filesystem other than the actual local disk.  Although,
 | ||||
|   //   if you find yourself using this, it may make more sense for you to implement SchemaFile
 | ||||
|   //   yourself.
 | ||||
|   //
 | ||||
|   // The SchemaFile compares equal to any other SchemaFile that has exactly the same disk path,
 | ||||
|   // after canonicalization.
 | ||||
|   //
 | ||||
|   // The SchemaFile will throw an exception if any errors are reported.
 | ||||
| 
 | ||||
|   // -----------------------------------------------------------------
 | ||||
|   // For more control, you can implement this interface.
 | ||||
| 
 | ||||
|   virtual kj::StringPtr getDisplayName() const = 0; | ||||
|   // Get the file's name, as it should appear in the schema.
 | ||||
| 
 | ||||
|   virtual kj::Array<const char> readContent() const = 0; | ||||
|   // Read the file's entire content and return it as a byte array.
 | ||||
| 
 | ||||
|   virtual kj::Maybe<kj::Own<SchemaFile>> import(kj::StringPtr path) const = 0; | ||||
|   // Resolve an import, relative to this file.
 | ||||
|   //
 | ||||
|   // `path` is exactly what appears between quotes after the `import` keyword in the source code.
 | ||||
|   // It is entirely up to the `SchemaFile` to decide how to map this to another file.  Typically,
 | ||||
|   // a leading '/' means that the file is an "absolute" path and is searched for in some list of
 | ||||
|   // schema file repositories.  On the other hand, a path that doesn't start with '/' is relative
 | ||||
|   // to the importing file.
 | ||||
| 
 | ||||
|   virtual bool operator==(const SchemaFile& other) const = 0; | ||||
|   virtual bool operator!=(const SchemaFile& other) const = 0; | ||||
|   virtual size_t hashCode() const = 0; | ||||
|   // Compare two SchemaFiles to see if they refer to the same underlying file.  This is an
 | ||||
|   // optimization used to avoid the need to re-parse a file to check its ID.
 | ||||
| 
 | ||||
|   struct SourcePos { | ||||
|     uint byte; | ||||
|     uint line; | ||||
|     uint column; | ||||
|   }; | ||||
|   virtual void reportError(SourcePos start, SourcePos end, kj::StringPtr message) const = 0; | ||||
|   // Report that the file contains an error at the given interval.
 | ||||
| 
 | ||||
| private: | ||||
|   class DiskSchemaFile; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_SCHEMA_PARSER_H_
 | ||||
| @ -0,0 +1,498 @@ | ||||
| # Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors | ||||
| # Licensed under the MIT License: | ||||
| # | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| # of this software and associated documentation files (the "Software"), to deal | ||||
| # in the Software without restriction, including without limitation the rights | ||||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| # copies of the Software, and to permit persons to whom the Software is | ||||
| # furnished to do so, subject to the following conditions: | ||||
| # | ||||
| # The above copyright notice and this permission notice shall be included in | ||||
| # all copies or substantial portions of the Software. | ||||
| # | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| # THE SOFTWARE. | ||||
| 
 | ||||
| using Cxx = import "/capnp/c++.capnp"; | ||||
| 
 | ||||
| @0xa93fc509624c72d9; | ||||
| $Cxx.namespace("capnp::schema"); | ||||
| 
 | ||||
| using Id = UInt64; | ||||
| # The globally-unique ID of a file, type, or annotation. | ||||
| 
 | ||||
| struct Node { | ||||
|   id @0 :Id; | ||||
| 
 | ||||
|   displayName @1 :Text; | ||||
|   # Name to present to humans to identify this Node.  You should not attempt to parse this.  Its | ||||
|   # format could change.  It is not guaranteed to be unique. | ||||
|   # | ||||
|   # (On Zooko's triangle, this is the node's nickname.) | ||||
| 
 | ||||
|   displayNamePrefixLength @2 :UInt32; | ||||
|   # If you want a shorter version of `displayName` (just naming this node, without its surrounding | ||||
|   # scope), chop off this many characters from the beginning of `displayName`. | ||||
| 
 | ||||
|   scopeId @3 :Id; | ||||
|   # ID of the lexical parent node.  Typically, the scope node will have a NestedNode pointing back | ||||
|   # at this node, but robust code should avoid relying on this (and, in fact, group nodes are not | ||||
|   # listed in the outer struct's nestedNodes, since they are listed in the fields).  `scopeId` is | ||||
|   # zero if the node has no parent, which is normally only the case with files, but should be | ||||
|   # allowed for any kind of node (in order to make runtime type generation easier). | ||||
| 
 | ||||
|   parameters @32 :List(Parameter); | ||||
|   # If this node is parameterized (generic), the list of parameters. Empty for non-generic types. | ||||
| 
 | ||||
|   isGeneric @33 :Bool; | ||||
|   # True if this node is generic, meaning that it or one of its parent scopes has a non-empty | ||||
|   # `parameters`. | ||||
| 
 | ||||
|   struct Parameter { | ||||
|     # Information about one of the node's parameters. | ||||
| 
 | ||||
|     name @0 :Text; | ||||
|   } | ||||
| 
 | ||||
|   nestedNodes @4 :List(NestedNode); | ||||
|   # List of nodes nested within this node, along with the names under which they were declared. | ||||
| 
 | ||||
|   struct NestedNode { | ||||
|     name @0 :Text; | ||||
|     # Unqualified symbol name.  Unlike Node.displayName, this *can* be used programmatically. | ||||
|     # | ||||
|     # (On Zooko's triangle, this is the node's petname according to its parent scope.) | ||||
| 
 | ||||
|     id @1 :Id; | ||||
|     # ID of the nested node.  Typically, the target node's scopeId points back to this node, but | ||||
|     # robust code should avoid relying on this. | ||||
|   } | ||||
| 
 | ||||
|   annotations @5 :List(Annotation); | ||||
|   # Annotations applied to this node. | ||||
| 
 | ||||
|   union { | ||||
|     # Info specific to each kind of node. | ||||
| 
 | ||||
|     file @6 :Void; | ||||
| 
 | ||||
|     struct :group { | ||||
|       dataWordCount @7 :UInt16; | ||||
|       # Size of the data section, in words. | ||||
| 
 | ||||
|       pointerCount @8 :UInt16; | ||||
|       # Size of the pointer section, in pointers (which are one word each). | ||||
| 
 | ||||
|       preferredListEncoding @9 :ElementSize; | ||||
|       # The preferred element size to use when encoding a list of this struct.  If this is anything | ||||
|       # other than `inlineComposite` then the struct is one word or less in size and is a candidate | ||||
|       # for list packing optimization. | ||||
| 
 | ||||
|       isGroup @10 :Bool; | ||||
|       # If true, then this "struct" node is actually not an independent node, but merely represents | ||||
|       # some named union or group within a particular parent struct.  This node's scopeId refers | ||||
|       # to the parent struct, which may itself be a union/group in yet another struct. | ||||
|       # | ||||
|       # All group nodes share the same dataWordCount and pointerCount as the top-level | ||||
|       # struct, and their fields live in the same ordinal and offset spaces as all other fields in | ||||
|       # the struct. | ||||
|       # | ||||
|       # Note that a named union is considered a special kind of group -- in fact, a named union | ||||
|       # is exactly equivalent to a group that contains nothing but an unnamed union. | ||||
| 
 | ||||
|       discriminantCount @11 :UInt16; | ||||
|       # Number of fields in this struct which are members of an anonymous union, and thus may | ||||
|       # overlap.  If this is non-zero, then a 16-bit discriminant is present indicating which | ||||
|       # of the overlapping fields is active.  This can never be 1 -- if it is non-zero, it must be | ||||
|       # two or more. | ||||
|       # | ||||
|       # Note that the fields of an unnamed union are considered fields of the scope containing the | ||||
|       # union -- an unnamed union is not its own group.  So, a top-level struct may contain a | ||||
|       # non-zero discriminant count.  Named unions, on the other hand, are equivalent to groups | ||||
|       # containing unnamed unions.  So, a named union has its own independent schema node, with | ||||
|       # `isGroup` = true. | ||||
| 
 | ||||
|       discriminantOffset @12 :UInt32; | ||||
|       # If `discriminantCount` is non-zero, this is the offset of the union discriminant, in | ||||
|       # multiples of 16 bits. | ||||
| 
 | ||||
|       fields @13 :List(Field); | ||||
|       # Fields defined within this scope (either the struct's top-level fields, or the fields of | ||||
|       # a particular group; see `isGroup`). | ||||
|       # | ||||
|       # The fields are sorted by ordinal number, but note that because groups share the same | ||||
|       # ordinal space, the field's index in this list is not necessarily exactly its ordinal. | ||||
|       # On the other hand, the field's position in this list does remain the same even as the | ||||
|       # protocol evolves, since it is not possible to insert or remove an earlier ordinal. | ||||
|       # Therefore, for most use cases, if you want to identify a field by number, it may make the | ||||
|       # most sense to use the field's index in this list rather than its ordinal. | ||||
|     } | ||||
| 
 | ||||
|     enum :group { | ||||
|       enumerants@14 :List(Enumerant); | ||||
|       # Enumerants ordered by numeric value (ordinal). | ||||
|     } | ||||
| 
 | ||||
|     interface :group { | ||||
|       methods @15 :List(Method); | ||||
|       # Methods ordered by ordinal. | ||||
| 
 | ||||
|       superclasses @31 :List(Superclass); | ||||
|       # Superclasses of this interface. | ||||
|     } | ||||
| 
 | ||||
|     const :group { | ||||
|       type @16 :Type; | ||||
|       value @17 :Value; | ||||
|     } | ||||
| 
 | ||||
|     annotation :group { | ||||
|       type @18 :Type; | ||||
| 
 | ||||
|       targetsFile @19 :Bool; | ||||
|       targetsConst @20 :Bool; | ||||
|       targetsEnum @21 :Bool; | ||||
|       targetsEnumerant @22 :Bool; | ||||
|       targetsStruct @23 :Bool; | ||||
|       targetsField @24 :Bool; | ||||
|       targetsUnion @25 :Bool; | ||||
|       targetsGroup @26 :Bool; | ||||
|       targetsInterface @27 :Bool; | ||||
|       targetsMethod @28 :Bool; | ||||
|       targetsParam @29 :Bool; | ||||
|       targetsAnnotation @30 :Bool; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| struct Field { | ||||
|   # Schema for a field of a struct. | ||||
| 
 | ||||
|   name @0 :Text; | ||||
| 
 | ||||
|   codeOrder @1 :UInt16; | ||||
|   # Indicates where this member appeared in the code, relative to other members. | ||||
|   # Code ordering may have semantic relevance -- programmers tend to place related fields | ||||
|   # together.  So, using code ordering makes sense in human-readable formats where ordering is | ||||
|   # otherwise irrelevant, like JSON.  The values of codeOrder are tightly-packed, so the maximum | ||||
|   # value is count(members) - 1.  Fields that are members of a union are only ordered relative to | ||||
|   # the other members of that union, so the maximum value there is count(union.members). | ||||
| 
 | ||||
|   annotations @2 :List(Annotation); | ||||
| 
 | ||||
|   const noDiscriminant :UInt16 = 0xffff; | ||||
| 
 | ||||
|   discriminantValue @3 :UInt16 = Field.noDiscriminant; | ||||
|   # If the field is in a union, this is the value which the union's discriminant should take when | ||||
|   # the field is active.  If the field is not in a union, this is 0xffff. | ||||
| 
 | ||||
|   union { | ||||
|     slot :group { | ||||
|       # A regular, non-group, non-fixed-list field. | ||||
| 
 | ||||
|       offset @4 :UInt32; | ||||
|       # Offset, in units of the field's size, from the beginning of the section in which the field | ||||
|       # resides.  E.g. for a UInt32 field, multiply this by 4 to get the byte offset from the | ||||
|       # beginning of the data section. | ||||
| 
 | ||||
|       type @5 :Type; | ||||
|       defaultValue @6 :Value; | ||||
| 
 | ||||
|       hadExplicitDefault @10 :Bool; | ||||
|       # Whether the default value was specified explicitly.  Non-explicit default values are always | ||||
|       # zero or empty values.  Usually, whether the default value was explicit shouldn't matter. | ||||
|       # The main use case for this flag is for structs representing method parameters: | ||||
|       # explicitly-defaulted parameters may be allowed to be omitted when calling the method. | ||||
|     } | ||||
| 
 | ||||
|     group :group { | ||||
|       # A group. | ||||
| 
 | ||||
|       typeId @7 :Id; | ||||
|       # The ID of the group's node. | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ordinal :union { | ||||
|     implicit @8 :Void; | ||||
|     explicit @9 :UInt16; | ||||
|     # The original ordinal number given to the field.  You probably should NOT use this; if you need | ||||
|     # a numeric identifier for a field, use its position within the field array for its scope. | ||||
|     # The ordinal is given here mainly just so that the original schema text can be reproduced given | ||||
|     # the compiled version -- i.e. so that `capnp compile -ocapnp` can do its job. | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| struct Enumerant { | ||||
|   # Schema for member of an enum. | ||||
| 
 | ||||
|   name @0 :Text; | ||||
| 
 | ||||
|   codeOrder @1 :UInt16; | ||||
|   # Specifies order in which the enumerants were declared in the code. | ||||
|   # Like Struct.Field.codeOrder. | ||||
| 
 | ||||
|   annotations @2 :List(Annotation); | ||||
| } | ||||
| 
 | ||||
| struct Superclass { | ||||
|   id @0 :Id; | ||||
|   brand @1 :Brand; | ||||
| } | ||||
| 
 | ||||
| struct Method { | ||||
|   # Schema for method of an interface. | ||||
| 
 | ||||
|   name @0 :Text; | ||||
| 
 | ||||
|   codeOrder @1 :UInt16; | ||||
|   # Specifies order in which the methods were declared in the code. | ||||
|   # Like Struct.Field.codeOrder. | ||||
| 
 | ||||
|   implicitParameters @7 :List(Node.Parameter); | ||||
|   # The parameters listed in [] (typically, type / generic parameters), whose bindings are intended | ||||
|   # to be inferred rather than specified explicitly, although not all languages support this. | ||||
| 
 | ||||
|   paramStructType @2 :Id; | ||||
|   # ID of the parameter struct type.  If a named parameter list was specified in the method | ||||
|   # declaration (rather than a single struct parameter type) then a corresponding struct type is | ||||
|   # auto-generated.  Such an auto-generated type will not be listed in the interface's | ||||
|   # `nestedNodes` and its `scopeId` will be zero -- it is completely detached from the namespace. | ||||
|   # (Awkwardly, it does of course inherit generic parameters from the method's scope, which makes | ||||
|   # this a situation where you can't just climb the scope chain to find where a particular | ||||
|   # generic parameter was introduced. Making the `scopeId` zero was a mistake.) | ||||
| 
 | ||||
|   paramBrand @5 :Brand; | ||||
|   # Brand of param struct type. | ||||
| 
 | ||||
|   resultStructType @3 :Id; | ||||
|   # ID of the return struct type; similar to `paramStructType`. | ||||
| 
 | ||||
|   resultBrand @6 :Brand; | ||||
|   # Brand of result struct type. | ||||
| 
 | ||||
|   annotations @4 :List(Annotation); | ||||
| } | ||||
| 
 | ||||
| struct Type { | ||||
|   # Represents a type expression. | ||||
| 
 | ||||
|   union { | ||||
|     # The ordinals intentionally match those of Value. | ||||
| 
 | ||||
|     void @0 :Void; | ||||
|     bool @1 :Void; | ||||
|     int8 @2 :Void; | ||||
|     int16 @3 :Void; | ||||
|     int32 @4 :Void; | ||||
|     int64 @5 :Void; | ||||
|     uint8 @6 :Void; | ||||
|     uint16 @7 :Void; | ||||
|     uint32 @8 :Void; | ||||
|     uint64 @9 :Void; | ||||
|     float32 @10 :Void; | ||||
|     float64 @11 :Void; | ||||
|     text @12 :Void; | ||||
|     data @13 :Void; | ||||
| 
 | ||||
|     list :group { | ||||
|       elementType @14 :Type; | ||||
|     } | ||||
| 
 | ||||
|     enum :group { | ||||
|       typeId @15 :Id; | ||||
|       brand @21 :Brand; | ||||
|     } | ||||
|     struct :group { | ||||
|       typeId @16 :Id; | ||||
|       brand @22 :Brand; | ||||
|     } | ||||
|     interface :group { | ||||
|       typeId @17 :Id; | ||||
|       brand @23 :Brand; | ||||
|     } | ||||
| 
 | ||||
|     anyPointer :union { | ||||
|       unconstrained :union { | ||||
|         # A regular AnyPointer. | ||||
|         # | ||||
|         # The name "unconstrained" means as opposed to constraining it to match a type parameter. | ||||
|         # In retrospect this name is probably a poor choice given that it may still be constrained | ||||
|         # to be a struct, list, or capability. | ||||
| 
 | ||||
|         anyKind @18 :Void;       # truly AnyPointer | ||||
|         struct @25 :Void;        # AnyStruct | ||||
|         list @26 :Void;          # AnyList | ||||
|         capability @27 :Void;    # Capability | ||||
|       } | ||||
| 
 | ||||
|       parameter :group { | ||||
|         # This is actually a reference to a type parameter defined within this scope. | ||||
| 
 | ||||
|         scopeId @19 :Id; | ||||
|         # ID of the generic type whose parameter we're referencing. This should be a parent of the | ||||
|         # current scope. | ||||
| 
 | ||||
|         parameterIndex @20 :UInt16; | ||||
|         # Index of the parameter within the generic type's parameter list. | ||||
|       } | ||||
| 
 | ||||
|       implicitMethodParameter :group { | ||||
|         # This is actually a reference to an implicit (generic) parameter of a method. The only | ||||
|         # legal context for this type to appear is inside Method.paramBrand or Method.resultBrand. | ||||
| 
 | ||||
|         parameterIndex @24 :UInt16; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| struct Brand { | ||||
|   # Specifies bindings for parameters of generics. Since these bindings turn a generic into a | ||||
|   # non-generic, we call it the "brand". | ||||
| 
 | ||||
|   scopes @0 :List(Scope); | ||||
|   # For each of the target type and each of its parent scopes, a parameterization may be included | ||||
|   # in this list. If no parameterization is included for a particular relevant scope, then either | ||||
|   # that scope has no parameters or all parameters should be considered to be `AnyPointer`. | ||||
| 
 | ||||
|   struct Scope { | ||||
|     scopeId @0 :Id; | ||||
|     # ID of the scope to which these params apply. | ||||
| 
 | ||||
|     union { | ||||
|       bind @1 :List(Binding); | ||||
|       # List of parameter bindings. | ||||
| 
 | ||||
|       inherit @2 :Void; | ||||
|       # The place where this Brand appears is actually within this scope or a sub-scope, | ||||
|       # and the bindings for this scope should be inherited from the reference point. | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   struct Binding { | ||||
|     union { | ||||
|       unbound @0 :Void; | ||||
|       type @1 :Type; | ||||
| 
 | ||||
|       # TODO(someday): Allow non-type parameters? Unsure if useful. | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| struct Value { | ||||
|   # Represents a value, e.g. a field default value, constant value, or annotation value. | ||||
| 
 | ||||
|   union { | ||||
|     # The ordinals intentionally match those of Type. | ||||
| 
 | ||||
|     void @0 :Void; | ||||
|     bool @1 :Bool; | ||||
|     int8 @2 :Int8; | ||||
|     int16 @3 :Int16; | ||||
|     int32 @4 :Int32; | ||||
|     int64 @5 :Int64; | ||||
|     uint8 @6 :UInt8; | ||||
|     uint16 @7 :UInt16; | ||||
|     uint32 @8 :UInt32; | ||||
|     uint64 @9 :UInt64; | ||||
|     float32 @10 :Float32; | ||||
|     float64 @11 :Float64; | ||||
|     text @12 :Text; | ||||
|     data @13 :Data; | ||||
| 
 | ||||
|     list @14 :AnyPointer; | ||||
| 
 | ||||
|     enum @15 :UInt16; | ||||
|     struct @16 :AnyPointer; | ||||
| 
 | ||||
|     interface @17 :Void; | ||||
|     # The only interface value that can be represented statically is "null", whose methods always | ||||
|     # throw exceptions. | ||||
| 
 | ||||
|     anyPointer @18 :AnyPointer; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| struct Annotation { | ||||
|   # Describes an annotation applied to a declaration.  Note AnnotationNode describes the | ||||
|   # annotation's declaration, while this describes a use of the annotation. | ||||
| 
 | ||||
|   id @0 :Id; | ||||
|   # ID of the annotation node. | ||||
| 
 | ||||
|   brand @2 :Brand; | ||||
|   # Brand of the annotation. | ||||
|   # | ||||
|   # Note that the annotation itself is not allowed to be parameterized, but its scope might be. | ||||
| 
 | ||||
|   value @1 :Value; | ||||
| } | ||||
| 
 | ||||
| enum ElementSize { | ||||
|   # Possible element sizes for encoded lists.  These correspond exactly to the possible values of | ||||
|   # the 3-bit element size component of a list pointer. | ||||
| 
 | ||||
|   empty @0;    # aka "void", but that's a keyword. | ||||
|   bit @1; | ||||
|   byte @2; | ||||
|   twoBytes @3; | ||||
|   fourBytes @4; | ||||
|   eightBytes @5; | ||||
|   pointer @6; | ||||
|   inlineComposite @7; | ||||
| } | ||||
| 
 | ||||
| struct CapnpVersion { | ||||
|   major @0 :UInt16; | ||||
|   minor @1 :UInt8; | ||||
|   micro @2 :UInt8; | ||||
| } | ||||
| 
 | ||||
| struct CodeGeneratorRequest { | ||||
|   capnpVersion @2 :CapnpVersion; | ||||
|   # Version of the `capnp` executable. Generally, code generators should ignore this, but the code | ||||
|   # generators that ship with `capnp` itself will print a warning if this mismatches since that | ||||
|   # probably indicates something is misconfigured. | ||||
|   # | ||||
|   # The first version of 'capnp' to set this was 0.6.0. So, if it's missing, the compiler version | ||||
|   # is older than that. | ||||
| 
 | ||||
|   nodes @0 :List(Node); | ||||
|   # All nodes parsed by the compiler, including for the files on the command line and their | ||||
|   # imports. | ||||
| 
 | ||||
|   requestedFiles @1 :List(RequestedFile); | ||||
|   # Files which were listed on the command line. | ||||
| 
 | ||||
|   struct RequestedFile { | ||||
|     id @0 :Id; | ||||
|     # ID of the file. | ||||
| 
 | ||||
|     filename @1 :Text; | ||||
|     # Name of the file as it appeared on the command-line (minus the src-prefix).  You may use | ||||
|     # this to decide where to write the output. | ||||
| 
 | ||||
|     imports @2 :List(Import); | ||||
|     # List of all imported paths seen in this file. | ||||
| 
 | ||||
|     struct Import { | ||||
|       id @0 :Id; | ||||
|       # ID of the imported file. | ||||
| 
 | ||||
|       name @1 :Text; | ||||
|       # Name which *this* file used to refer to the foreign file.  This may be a relative name. | ||||
|       # This information is provided because it might be useful for code generation, e.g. to | ||||
|       # generate #include directives in C++.  We don't put this in Node.file because this | ||||
|       # information is only meaningful at compile time anyway. | ||||
|       # | ||||
|       # (On Zooko's triangle, this is the import's petname according to the importing file.) | ||||
|     } | ||||
|   } | ||||
| } | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -0,0 +1,934 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_SCHEMA_H_ | ||||
| #define CAPNP_SCHEMA_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #if CAPNP_LITE | ||||
| #error "Reflection APIs, including this header, are not available in lite mode." | ||||
| #endif | ||||
| 
 | ||||
| #include <capnp/schema.capnp.h> | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| class Schema; | ||||
| class StructSchema; | ||||
| class EnumSchema; | ||||
| class InterfaceSchema; | ||||
| class ConstSchema; | ||||
| class ListSchema; | ||||
| class Type; | ||||
| 
 | ||||
| template <typename T, Kind k = kind<T>()> struct SchemaType_ { typedef Schema Type; }; | ||||
| template <typename T> struct SchemaType_<T, Kind::PRIMITIVE> { typedef schema::Type::Which Type; }; | ||||
| template <typename T> struct SchemaType_<T, Kind::BLOB> { typedef schema::Type::Which Type; }; | ||||
| template <typename T> struct SchemaType_<T, Kind::ENUM> { typedef EnumSchema Type; }; | ||||
| template <typename T> struct SchemaType_<T, Kind::STRUCT> { typedef StructSchema Type; }; | ||||
| template <typename T> struct SchemaType_<T, Kind::INTERFACE> { typedef InterfaceSchema Type; }; | ||||
| template <typename T> struct SchemaType_<T, Kind::LIST> { typedef ListSchema Type; }; | ||||
| 
 | ||||
| template <typename T> | ||||
| using SchemaType = typename SchemaType_<T>::Type; | ||||
| // SchemaType<T> is the type of T's schema, e.g. StructSchema if T is a struct.
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| extern const RawSchema NULL_SCHEMA; | ||||
| extern const RawSchema NULL_STRUCT_SCHEMA; | ||||
| extern const RawSchema NULL_ENUM_SCHEMA; | ||||
| extern const RawSchema NULL_INTERFACE_SCHEMA; | ||||
| extern const RawSchema NULL_CONST_SCHEMA; | ||||
| // The schema types default to these null (empty) schemas in case of error, especially when
 | ||||
| // exceptions are disabled.
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| class Schema { | ||||
|   // Convenience wrapper around capnp::schema::Node.
 | ||||
| 
 | ||||
| public: | ||||
|   inline Schema(): raw(&_::NULL_SCHEMA.defaultBrand) {} | ||||
| 
 | ||||
|   template <typename T> | ||||
|   static inline SchemaType<T> from() { return SchemaType<T>::template fromImpl<T>(); } | ||||
|   // Get the Schema for a particular compiled-in type.
 | ||||
| 
 | ||||
|   schema::Node::Reader getProto() const; | ||||
|   // Get the underlying Cap'n Proto representation of the schema node.  (Note that this accessor
 | ||||
|   // has performance comparable to accessors of struct-typed fields on Reader classes.)
 | ||||
| 
 | ||||
|   kj::ArrayPtr<const word> asUncheckedMessage() const; | ||||
|   // Get the encoded schema node content as a single message segment.  It is safe to read as an
 | ||||
|   // unchecked message.
 | ||||
| 
 | ||||
|   Schema getDependency(uint64_t id) const KJ_DEPRECATED("Does not handle generics correctly."); | ||||
|   // DEPRECATED: This method cannot correctly account for generic type parameter bindings that
 | ||||
|   //   may apply to the dependency. Instead of using this method, use a method of the Schema API
 | ||||
|   //   that corresponds to the exact kind of dependency. For example, to get a field type, use
 | ||||
|   //   StructSchema::Field::getType().
 | ||||
|   //
 | ||||
|   // Gets the Schema for one of this Schema's dependencies.  For example, if this Schema is for a
 | ||||
|   // struct, you could look up the schema for one of its fields' types.  Throws an exception if this
 | ||||
|   // schema doesn't actually depend on the given id.
 | ||||
|   //
 | ||||
|   // Note that not all type IDs found in the schema node are considered "dependencies" -- only the
 | ||||
|   // ones that are needed to implement the dynamic API are.  That includes:
 | ||||
|   // - Field types.
 | ||||
|   // - Group types.
 | ||||
|   // - scopeId for group nodes, but NOT otherwise.
 | ||||
|   // - Method parameter and return types.
 | ||||
|   //
 | ||||
|   // The following are NOT considered dependencies:
 | ||||
|   // - Nested nodes.
 | ||||
|   // - scopeId for a non-group node.
 | ||||
|   // - Annotations.
 | ||||
|   //
 | ||||
|   // To obtain schemas for those, you would need a SchemaLoader.
 | ||||
| 
 | ||||
|   bool isBranded() const; | ||||
|   // Returns true if this schema represents a non-default parameterization of this type.
 | ||||
| 
 | ||||
|   Schema getGeneric() const; | ||||
|   // Get the version of this schema with any brands removed.
 | ||||
| 
 | ||||
|   class BrandArgumentList; | ||||
|   BrandArgumentList getBrandArgumentsAtScope(uint64_t scopeId) const; | ||||
|   // Gets the values bound to the brand parameters at the given scope.
 | ||||
| 
 | ||||
|   StructSchema asStruct() const; | ||||
|   EnumSchema asEnum() const; | ||||
|   InterfaceSchema asInterface() const; | ||||
|   ConstSchema asConst() const; | ||||
|   // Cast the Schema to a specific type.  Throws an exception if the type doesn't match.  Use
 | ||||
|   // getProto() to determine type, e.g. getProto().isStruct().
 | ||||
| 
 | ||||
|   inline bool operator==(const Schema& other) const { return raw == other.raw; } | ||||
|   inline bool operator!=(const Schema& other) const { return raw != other.raw; } | ||||
|   // Determine whether two Schemas are wrapping the exact same underlying data, by identity.  If
 | ||||
|   // you want to check if two Schemas represent the same type (but possibly different versions of
 | ||||
|   // it), compare their IDs instead.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   void requireUsableAs() const; | ||||
|   // Throws an exception if a value with this Schema cannot safely be cast to a native value of
 | ||||
|   // the given type.  This passes if either:
 | ||||
|   // - *this == from<T>()
 | ||||
|   // - This schema was loaded with SchemaLoader, the type ID matches typeId<T>(), and
 | ||||
|   //   loadCompiledTypeAndDependencies<T>() was called on the SchemaLoader.
 | ||||
| 
 | ||||
|   kj::StringPtr getShortDisplayName() const; | ||||
|   // Get the short version of the node's display name.
 | ||||
| 
 | ||||
| private: | ||||
|   const _::RawBrandedSchema* raw; | ||||
| 
 | ||||
|   inline explicit Schema(const _::RawBrandedSchema* raw): raw(raw) { | ||||
|     KJ_IREQUIRE(raw->lazyInitializer == nullptr, | ||||
|         "Must call ensureInitialized() on RawSchema before constructing Schema."); | ||||
|   } | ||||
| 
 | ||||
|   template <typename T> static inline Schema fromImpl() { | ||||
|     return Schema(&_::rawSchema<T>()); | ||||
|   } | ||||
| 
 | ||||
|   void requireUsableAs(const _::RawSchema* expected) const; | ||||
| 
 | ||||
|   uint32_t getSchemaOffset(const schema::Value::Reader& value) const; | ||||
| 
 | ||||
|   Type getBrandBinding(uint64_t scopeId, uint index) const; | ||||
|   // Look up the binding for a brand parameter used by this Schema. Returns `AnyPointer` if the
 | ||||
|   // parameter is not bound.
 | ||||
|   //
 | ||||
|   // TODO(someday): Public interface for iterating over all bindings?
 | ||||
| 
 | ||||
|   Schema getDependency(uint64_t id, uint location) const; | ||||
|   // Look up schema for a particular dependency of this schema. `location` is the dependency
 | ||||
|   // location number as defined in _::RawBrandedSchema.
 | ||||
| 
 | ||||
|   Type interpretType(schema::Type::Reader proto, uint location) const; | ||||
|   // Interpret a schema::Type in the given location within the schema, compiling it into a
 | ||||
|   // Type object.
 | ||||
| 
 | ||||
|   friend class StructSchema; | ||||
|   friend class EnumSchema; | ||||
|   friend class InterfaceSchema; | ||||
|   friend class ConstSchema; | ||||
|   friend class ListSchema; | ||||
|   friend class SchemaLoader; | ||||
|   friend class Type; | ||||
|   friend kj::StringTree _::structString( | ||||
|       _::StructReader reader, const _::RawBrandedSchema& schema); | ||||
|   friend kj::String _::enumString(uint16_t value, const _::RawBrandedSchema& schema); | ||||
| }; | ||||
| 
 | ||||
| kj::StringPtr KJ_STRINGIFY(const Schema& schema); | ||||
| 
 | ||||
| class Schema::BrandArgumentList { | ||||
|   // A list of generic parameter bindings for parameters of some particular type. Note that since
 | ||||
|   // parameters on an outer type apply to all inner types as well, a deeply-nested type can have
 | ||||
|   // multiple BrandArgumentLists that apply to it.
 | ||||
|   //
 | ||||
|   // A BrandArgumentList only represents the arguments that the client of the type specified. Since
 | ||||
|   // new parameters can be added over time, this list may not cover all defined parameters for the
 | ||||
|   // type. Missing parameters should be treated as AnyPointer. This class's implementation of
 | ||||
|   // operator[] already does this for you; out-of-bounds access will safely return AnyPointer.
 | ||||
| 
 | ||||
| public: | ||||
|   inline BrandArgumentList(): scopeId(0), size_(0), bindings(nullptr) {} | ||||
| 
 | ||||
|   inline uint size() const { return size_; } | ||||
|   Type operator[](uint index) const; | ||||
| 
 | ||||
|   typedef _::IndexingIterator<const BrandArgumentList, Type> Iterator; | ||||
|   inline Iterator begin() const { return Iterator(this, 0); } | ||||
|   inline Iterator end() const { return Iterator(this, size()); } | ||||
| 
 | ||||
| private: | ||||
|   uint64_t scopeId; | ||||
|   uint size_; | ||||
|   bool isUnbound; | ||||
|   const _::RawBrandedSchema::Binding* bindings; | ||||
| 
 | ||||
|   inline BrandArgumentList(uint64_t scopeId, bool isUnbound) | ||||
|       : scopeId(scopeId), size_(0), isUnbound(isUnbound), bindings(nullptr) {} | ||||
|   inline BrandArgumentList(uint64_t scopeId, uint size, | ||||
|                            const _::RawBrandedSchema::Binding* bindings) | ||||
|       : scopeId(scopeId), size_(size), isUnbound(false), bindings(bindings) {} | ||||
| 
 | ||||
|   friend class Schema; | ||||
| }; | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| 
 | ||||
| class StructSchema: public Schema { | ||||
| public: | ||||
|   inline StructSchema(): Schema(&_::NULL_STRUCT_SCHEMA.defaultBrand) {} | ||||
| 
 | ||||
|   class Field; | ||||
|   class FieldList; | ||||
|   class FieldSubset; | ||||
| 
 | ||||
|   FieldList getFields() const; | ||||
|   // List top-level fields of this struct.  This list will contain top-level groups (including
 | ||||
|   // named unions) but not the members of those groups.  The list does, however, contain the
 | ||||
|   // members of the unnamed union, if there is one.
 | ||||
| 
 | ||||
|   FieldSubset getUnionFields() const; | ||||
|   // If the field contains an unnamed union, get a list of fields in the union, ordered by
 | ||||
|   // ordinal.  Since discriminant values are assigned sequentially by ordinal, you may index this
 | ||||
|   // list by discriminant value.
 | ||||
| 
 | ||||
|   FieldSubset getNonUnionFields() const; | ||||
|   // Get the fields of this struct which are not in an unnamed union, ordered by ordinal.
 | ||||
| 
 | ||||
|   kj::Maybe<Field> findFieldByName(kj::StringPtr name) const; | ||||
|   // Find the field with the given name, or return null if there is no such field.  If the struct
 | ||||
|   // contains an unnamed union, then this will find fields of that union in addition to fields
 | ||||
|   // of the outer struct, since they exist in the same namespace.  It will not, however, find
 | ||||
|   // members of groups (including named unions) -- you must first look up the group itself,
 | ||||
|   // then dig into its type.
 | ||||
| 
 | ||||
|   Field getFieldByName(kj::StringPtr name) const; | ||||
|   // Like findFieldByName() but throws an exception on failure.
 | ||||
| 
 | ||||
|   kj::Maybe<Field> getFieldByDiscriminant(uint16_t discriminant) const; | ||||
|   // Finds the field whose `discriminantValue` is equal to the given value, or returns null if
 | ||||
|   // there is no such field.  (If the schema does not represent a union or a struct containing
 | ||||
|   // an unnamed union, then this always returns null.)
 | ||||
| 
 | ||||
| private: | ||||
|   StructSchema(Schema base): Schema(base) {} | ||||
|   template <typename T> static inline StructSchema fromImpl() { | ||||
|     return StructSchema(Schema(&_::rawBrandedSchema<T>())); | ||||
|   } | ||||
|   friend class Schema; | ||||
|   friend class Type; | ||||
| }; | ||||
| 
 | ||||
| class StructSchema::Field { | ||||
| public: | ||||
|   Field() = default; | ||||
| 
 | ||||
|   inline schema::Field::Reader getProto() const { return proto; } | ||||
|   inline StructSchema getContainingStruct() const { return parent; } | ||||
| 
 | ||||
|   inline uint getIndex() const { return index; } | ||||
|   // Get the index of this field within the containing struct or union.
 | ||||
| 
 | ||||
|   Type getType() const; | ||||
|   // Get the type of this field. Note that this is preferred over getProto().getType() as this
 | ||||
|   // method will apply generics.
 | ||||
| 
 | ||||
|   uint32_t getDefaultValueSchemaOffset() const; | ||||
|   // For struct, list, and object fields, returns the offset, in words, within the first segment of
 | ||||
|   // the struct's schema, where this field's default value pointer is located.  The schema is
 | ||||
|   // always stored as a single-segment unchecked message, which in turn means that the default
 | ||||
|   // value pointer itself can be treated as the root of an unchecked message -- if you know where
 | ||||
|   // to find it, which is what this method helps you with.
 | ||||
|   //
 | ||||
|   // For blobs, returns the offset of the beginning of the blob's content within the first segment
 | ||||
|   // of the struct's schema.
 | ||||
|   //
 | ||||
|   // This is primarily useful for code generators.  The C++ code generator, for example, embeds
 | ||||
|   // the entire schema as a raw word array within the generated code.  Of course, to implement
 | ||||
|   // field accessors, it needs access to those fields' default values.  Embedding separate copies
 | ||||
|   // of those default values would be redundant since they are already included in the schema, but
 | ||||
|   // seeking through the schema at runtime to find the default values would be ugly.  Instead,
 | ||||
|   // the code generator can use getDefaultValueSchemaOffset() to find the offset of the default
 | ||||
|   // value within the schema, and can simply apply that offset at runtime.
 | ||||
|   //
 | ||||
|   // If the above does not make sense, you probably don't need this method.
 | ||||
| 
 | ||||
|   inline bool operator==(const Field& other) const; | ||||
|   inline bool operator!=(const Field& other) const { return !(*this == other); } | ||||
| 
 | ||||
| private: | ||||
|   StructSchema parent; | ||||
|   uint index; | ||||
|   schema::Field::Reader proto; | ||||
| 
 | ||||
|   inline Field(StructSchema parent, uint index, schema::Field::Reader proto) | ||||
|       : parent(parent), index(index), proto(proto) {} | ||||
| 
 | ||||
|   friend class StructSchema; | ||||
| }; | ||||
| 
 | ||||
| kj::StringPtr KJ_STRINGIFY(const StructSchema::Field& field); | ||||
| 
 | ||||
| class StructSchema::FieldList { | ||||
| public: | ||||
|   FieldList() = default;  // empty list
 | ||||
| 
 | ||||
|   inline uint size() const { return list.size(); } | ||||
|   inline Field operator[](uint index) const { return Field(parent, index, list[index]); } | ||||
| 
 | ||||
|   typedef _::IndexingIterator<const FieldList, Field> Iterator; | ||||
|   inline Iterator begin() const { return Iterator(this, 0); } | ||||
|   inline Iterator end() const { return Iterator(this, size()); } | ||||
| 
 | ||||
| private: | ||||
|   StructSchema parent; | ||||
|   List<schema::Field>::Reader list; | ||||
| 
 | ||||
|   inline FieldList(StructSchema parent, List<schema::Field>::Reader list) | ||||
|       : parent(parent), list(list) {} | ||||
| 
 | ||||
|   friend class StructSchema; | ||||
| }; | ||||
| 
 | ||||
| class StructSchema::FieldSubset { | ||||
| public: | ||||
|   FieldSubset() = default;  // empty list
 | ||||
| 
 | ||||
|   inline uint size() const { return size_; } | ||||
|   inline Field operator[](uint index) const { | ||||
|     return Field(parent, indices[index], list[indices[index]]); | ||||
|   } | ||||
| 
 | ||||
|   typedef _::IndexingIterator<const FieldSubset, Field> Iterator; | ||||
|   inline Iterator begin() const { return Iterator(this, 0); } | ||||
|   inline Iterator end() const { return Iterator(this, size()); } | ||||
| 
 | ||||
| private: | ||||
|   StructSchema parent; | ||||
|   List<schema::Field>::Reader list; | ||||
|   const uint16_t* indices; | ||||
|   uint size_; | ||||
| 
 | ||||
|   inline FieldSubset(StructSchema parent, List<schema::Field>::Reader list, | ||||
|                      const uint16_t* indices, uint size) | ||||
|       : parent(parent), list(list), indices(indices), size_(size) {} | ||||
| 
 | ||||
|   friend class StructSchema; | ||||
| }; | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| 
 | ||||
| class EnumSchema: public Schema { | ||||
| public: | ||||
|   inline EnumSchema(): Schema(&_::NULL_ENUM_SCHEMA.defaultBrand) {} | ||||
| 
 | ||||
|   class Enumerant; | ||||
|   class EnumerantList; | ||||
| 
 | ||||
|   EnumerantList getEnumerants() const; | ||||
| 
 | ||||
|   kj::Maybe<Enumerant> findEnumerantByName(kj::StringPtr name) const; | ||||
| 
 | ||||
|   Enumerant getEnumerantByName(kj::StringPtr name) const; | ||||
|   // Like findEnumerantByName() but throws an exception on failure.
 | ||||
| 
 | ||||
| private: | ||||
|   EnumSchema(Schema base): Schema(base) {} | ||||
|   template <typename T> static inline EnumSchema fromImpl() { | ||||
|     return EnumSchema(Schema(&_::rawBrandedSchema<T>())); | ||||
|   } | ||||
|   friend class Schema; | ||||
|   friend class Type; | ||||
| }; | ||||
| 
 | ||||
| class EnumSchema::Enumerant { | ||||
| public: | ||||
|   Enumerant() = default; | ||||
| 
 | ||||
|   inline schema::Enumerant::Reader getProto() const { return proto; } | ||||
|   inline EnumSchema getContainingEnum() const { return parent; } | ||||
| 
 | ||||
|   inline uint16_t getOrdinal() const { return ordinal; } | ||||
|   inline uint getIndex() const { return ordinal; } | ||||
| 
 | ||||
|   inline bool operator==(const Enumerant& other) const; | ||||
|   inline bool operator!=(const Enumerant& other) const { return !(*this == other); } | ||||
| 
 | ||||
| private: | ||||
|   EnumSchema parent; | ||||
|   uint16_t ordinal; | ||||
|   schema::Enumerant::Reader proto; | ||||
| 
 | ||||
|   inline Enumerant(EnumSchema parent, uint16_t ordinal, schema::Enumerant::Reader proto) | ||||
|       : parent(parent), ordinal(ordinal), proto(proto) {} | ||||
| 
 | ||||
|   friend class EnumSchema; | ||||
| }; | ||||
| 
 | ||||
| class EnumSchema::EnumerantList { | ||||
| public: | ||||
|   EnumerantList() = default;  // empty list
 | ||||
| 
 | ||||
|   inline uint size() const { return list.size(); } | ||||
|   inline Enumerant operator[](uint index) const { return Enumerant(parent, index, list[index]); } | ||||
| 
 | ||||
|   typedef _::IndexingIterator<const EnumerantList, Enumerant> Iterator; | ||||
|   inline Iterator begin() const { return Iterator(this, 0); } | ||||
|   inline Iterator end() const { return Iterator(this, size()); } | ||||
| 
 | ||||
| private: | ||||
|   EnumSchema parent; | ||||
|   List<schema::Enumerant>::Reader list; | ||||
| 
 | ||||
|   inline EnumerantList(EnumSchema parent, List<schema::Enumerant>::Reader list) | ||||
|       : parent(parent), list(list) {} | ||||
| 
 | ||||
|   friend class EnumSchema; | ||||
| }; | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| 
 | ||||
| class InterfaceSchema: public Schema { | ||||
| public: | ||||
|   inline InterfaceSchema(): Schema(&_::NULL_INTERFACE_SCHEMA.defaultBrand) {} | ||||
| 
 | ||||
|   class Method; | ||||
|   class MethodList; | ||||
| 
 | ||||
|   MethodList getMethods() const; | ||||
| 
 | ||||
|   kj::Maybe<Method> findMethodByName(kj::StringPtr name) const; | ||||
| 
 | ||||
|   Method getMethodByName(kj::StringPtr name) const; | ||||
|   // Like findMethodByName() but throws an exception on failure.
 | ||||
| 
 | ||||
|   class SuperclassList; | ||||
| 
 | ||||
|   SuperclassList getSuperclasses() const; | ||||
|   // Get the immediate superclasses of this type, after applying generics.
 | ||||
| 
 | ||||
|   bool extends(InterfaceSchema other) const; | ||||
|   // Returns true if `other` is a superclass of this interface (including if `other == *this`).
 | ||||
| 
 | ||||
|   kj::Maybe<InterfaceSchema> findSuperclass(uint64_t typeId) const; | ||||
|   // Find the superclass of this interface with the given type ID.  Returns null if the interface
 | ||||
|   // extends no such type.
 | ||||
| 
 | ||||
| private: | ||||
|   InterfaceSchema(Schema base): Schema(base) {} | ||||
|   template <typename T> static inline InterfaceSchema fromImpl() { | ||||
|     return InterfaceSchema(Schema(&_::rawBrandedSchema<T>())); | ||||
|   } | ||||
|   friend class Schema; | ||||
|   friend class Type; | ||||
| 
 | ||||
|   kj::Maybe<Method> findMethodByName(kj::StringPtr name, uint& counter) const; | ||||
|   bool extends(InterfaceSchema other, uint& counter) const; | ||||
|   kj::Maybe<InterfaceSchema> findSuperclass(uint64_t typeId, uint& counter) const; | ||||
|   // We protect against malicious schemas with large or cyclic hierarchies by cutting off the
 | ||||
|   // search when the counter reaches a threshold.
 | ||||
| }; | ||||
| 
 | ||||
| class InterfaceSchema::Method { | ||||
| public: | ||||
|   Method() = default; | ||||
| 
 | ||||
|   inline schema::Method::Reader getProto() const { return proto; } | ||||
|   inline InterfaceSchema getContainingInterface() const { return parent; } | ||||
| 
 | ||||
|   inline uint16_t getOrdinal() const { return ordinal; } | ||||
|   inline uint getIndex() const { return ordinal; } | ||||
| 
 | ||||
|   StructSchema getParamType() const; | ||||
|   StructSchema getResultType() const; | ||||
|   // Get the parameter and result types, including substituting generic parameters.
 | ||||
| 
 | ||||
|   inline bool operator==(const Method& other) const; | ||||
|   inline bool operator!=(const Method& other) const { return !(*this == other); } | ||||
| 
 | ||||
| private: | ||||
|   InterfaceSchema parent; | ||||
|   uint16_t ordinal; | ||||
|   schema::Method::Reader proto; | ||||
| 
 | ||||
|   inline Method(InterfaceSchema parent, uint16_t ordinal, | ||||
|                 schema::Method::Reader proto) | ||||
|       : parent(parent), ordinal(ordinal), proto(proto) {} | ||||
| 
 | ||||
|   friend class InterfaceSchema; | ||||
| }; | ||||
| 
 | ||||
| class InterfaceSchema::MethodList { | ||||
| public: | ||||
|   MethodList() = default;  // empty list
 | ||||
| 
 | ||||
|   inline uint size() const { return list.size(); } | ||||
|   inline Method operator[](uint index) const { return Method(parent, index, list[index]); } | ||||
| 
 | ||||
|   typedef _::IndexingIterator<const MethodList, Method> Iterator; | ||||
|   inline Iterator begin() const { return Iterator(this, 0); } | ||||
|   inline Iterator end() const { return Iterator(this, size()); } | ||||
| 
 | ||||
| private: | ||||
|   InterfaceSchema parent; | ||||
|   List<schema::Method>::Reader list; | ||||
| 
 | ||||
|   inline MethodList(InterfaceSchema parent, List<schema::Method>::Reader list) | ||||
|       : parent(parent), list(list) {} | ||||
| 
 | ||||
|   friend class InterfaceSchema; | ||||
| }; | ||||
| 
 | ||||
| class InterfaceSchema::SuperclassList { | ||||
| public: | ||||
|   SuperclassList() = default;  // empty list
 | ||||
| 
 | ||||
|   inline uint size() const { return list.size(); } | ||||
|   InterfaceSchema operator[](uint index) const; | ||||
| 
 | ||||
|   typedef _::IndexingIterator<const SuperclassList, InterfaceSchema> Iterator; | ||||
|   inline Iterator begin() const { return Iterator(this, 0); } | ||||
|   inline Iterator end() const { return Iterator(this, size()); } | ||||
| 
 | ||||
| private: | ||||
|   InterfaceSchema parent; | ||||
|   List<schema::Superclass>::Reader list; | ||||
| 
 | ||||
|   inline SuperclassList(InterfaceSchema parent, List<schema::Superclass>::Reader list) | ||||
|       : parent(parent), list(list) {} | ||||
| 
 | ||||
|   friend class InterfaceSchema; | ||||
| }; | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| 
 | ||||
| class ConstSchema: public Schema { | ||||
|   // Represents a constant declaration.
 | ||||
|   //
 | ||||
|   // `ConstSchema` can be implicitly cast to DynamicValue to read its value.
 | ||||
| 
 | ||||
| public: | ||||
|   inline ConstSchema(): Schema(&_::NULL_CONST_SCHEMA.defaultBrand) {} | ||||
| 
 | ||||
|   template <typename T> | ||||
|   ReaderFor<T> as() const; | ||||
|   // Read the constant's value.  This is a convenience method equivalent to casting the ConstSchema
 | ||||
|   // to a DynamicValue and then calling its `as<T>()` method.  For dependency reasons, this method
 | ||||
|   // is defined in <capnp/dynamic.h>, which you must #include explicitly.
 | ||||
| 
 | ||||
|   uint32_t getValueSchemaOffset() const; | ||||
|   // Much like StructSchema::Field::getDefaultValueSchemaOffset(), if the constant has pointer
 | ||||
|   // type, this gets the offset from the beginning of the constant's schema node to a pointer
 | ||||
|   // representing the constant value.
 | ||||
| 
 | ||||
|   Type getType() const; | ||||
| 
 | ||||
| private: | ||||
|   ConstSchema(Schema base): Schema(base) {} | ||||
|   friend class Schema; | ||||
| }; | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| 
 | ||||
| class Type { | ||||
| public: | ||||
|   struct BrandParameter { | ||||
|     uint64_t scopeId; | ||||
|     uint index; | ||||
|   }; | ||||
|   struct ImplicitParameter { | ||||
|     uint index; | ||||
|   }; | ||||
| 
 | ||||
|   inline Type(); | ||||
|   inline Type(schema::Type::Which primitive); | ||||
|   inline Type(StructSchema schema); | ||||
|   inline Type(EnumSchema schema); | ||||
|   inline Type(InterfaceSchema schema); | ||||
|   inline Type(ListSchema schema); | ||||
|   inline Type(schema::Type::AnyPointer::Unconstrained::Which anyPointerKind); | ||||
|   inline Type(BrandParameter param); | ||||
|   inline Type(ImplicitParameter param); | ||||
| 
 | ||||
|   template <typename T> | ||||
|   inline static Type from(); | ||||
| 
 | ||||
|   inline schema::Type::Which which() const; | ||||
| 
 | ||||
|   StructSchema asStruct() const; | ||||
|   EnumSchema asEnum() const; | ||||
|   InterfaceSchema asInterface() const; | ||||
|   ListSchema asList() const; | ||||
|   // Each of these methods may only be called if which() returns the corresponding type.
 | ||||
| 
 | ||||
|   kj::Maybe<BrandParameter> getBrandParameter() const; | ||||
|   // Only callable if which() returns ANY_POINTER. Returns null if the type is just a regular
 | ||||
|   // AnyPointer and not a parameter.
 | ||||
| 
 | ||||
|   kj::Maybe<ImplicitParameter> getImplicitParameter() const; | ||||
|   // Only callable if which() returns ANY_POINTER. Returns null if the type is just a regular
 | ||||
|   // AnyPointer and not a parameter. "Implicit parameters" refer to type parameters on methods.
 | ||||
| 
 | ||||
|   inline schema::Type::AnyPointer::Unconstrained::Which whichAnyPointerKind() const; | ||||
|   // Only callable if which() returns ANY_POINTER.
 | ||||
| 
 | ||||
|   inline bool isVoid() const; | ||||
|   inline bool isBool() const; | ||||
|   inline bool isInt8() const; | ||||
|   inline bool isInt16() const; | ||||
|   inline bool isInt32() const; | ||||
|   inline bool isInt64() const; | ||||
|   inline bool isUInt8() const; | ||||
|   inline bool isUInt16() const; | ||||
|   inline bool isUInt32() const; | ||||
|   inline bool isUInt64() const; | ||||
|   inline bool isFloat32() const; | ||||
|   inline bool isFloat64() const; | ||||
|   inline bool isText() const; | ||||
|   inline bool isData() const; | ||||
|   inline bool isList() const; | ||||
|   inline bool isEnum() const; | ||||
|   inline bool isStruct() const; | ||||
|   inline bool isInterface() const; | ||||
|   inline bool isAnyPointer() const; | ||||
| 
 | ||||
|   bool operator==(const Type& other) const; | ||||
|   inline bool operator!=(const Type& other) const { return !(*this == other); } | ||||
| 
 | ||||
|   size_t hashCode() const; | ||||
| 
 | ||||
|   inline Type wrapInList(uint depth = 1) const; | ||||
|   // Return the Type formed by wrapping this type in List() `depth` times.
 | ||||
| 
 | ||||
|   inline Type(schema::Type::Which derived, const _::RawBrandedSchema* schema); | ||||
|   // For internal use.
 | ||||
| 
 | ||||
| private: | ||||
|   schema::Type::Which baseType;  // type not including applications of List()
 | ||||
|   uint8_t listDepth;             // 0 for T, 1 for List(T), 2 for List(List(T)), ...
 | ||||
| 
 | ||||
|   bool isImplicitParam; | ||||
|   // If true, this refers to an implicit method parameter. baseType must be ANY_POINTER, scopeId
 | ||||
|   // must be zero, and paramIndex indicates the parameter index.
 | ||||
| 
 | ||||
|   union { | ||||
|     uint16_t paramIndex; | ||||
|     // If baseType is ANY_POINTER but this Type actually refers to a type parameter, this is the
 | ||||
|     // index of the parameter among the parameters at its scope, and `scopeId` below is the type ID
 | ||||
|     // of the scope where the parameter was defined.
 | ||||
| 
 | ||||
|     schema::Type::AnyPointer::Unconstrained::Which anyPointerKind; | ||||
|     // If scopeId is zero and isImplicitParam is false.
 | ||||
|   }; | ||||
| 
 | ||||
|   union { | ||||
|     const _::RawBrandedSchema* schema;  // if type is struct, enum, interface...
 | ||||
|     uint64_t scopeId;  // if type is AnyPointer but it's actually a type parameter...
 | ||||
|   }; | ||||
| 
 | ||||
|   Type(schema::Type::Which baseType, uint8_t listDepth, const _::RawBrandedSchema* schema) | ||||
|       : baseType(baseType), listDepth(listDepth), schema(schema) { | ||||
|     KJ_IREQUIRE(baseType != schema::Type::ANY_POINTER); | ||||
|   } | ||||
| 
 | ||||
|   void requireUsableAs(Type expected) const; | ||||
| 
 | ||||
|   friend class ListSchema;  // only for requireUsableAs()
 | ||||
| }; | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| 
 | ||||
| class ListSchema { | ||||
|   // ListSchema is a little different because list types are not described by schema nodes.  So,
 | ||||
|   // ListSchema doesn't subclass Schema.
 | ||||
| 
 | ||||
| public: | ||||
|   ListSchema() = default; | ||||
| 
 | ||||
|   static ListSchema of(schema::Type::Which primitiveType); | ||||
|   static ListSchema of(StructSchema elementType); | ||||
|   static ListSchema of(EnumSchema elementType); | ||||
|   static ListSchema of(InterfaceSchema elementType); | ||||
|   static ListSchema of(ListSchema elementType); | ||||
|   static ListSchema of(Type elementType); | ||||
|   // Construct the schema for a list of the given type.
 | ||||
| 
 | ||||
|   static ListSchema of(schema::Type::Reader elementType, Schema context) | ||||
|       KJ_DEPRECATED("Does not handle generics correctly."); | ||||
|   // DEPRECATED: This method cannot correctly account for generic type parameter bindings that
 | ||||
|   //   may apply to the input type. Instead of using this method, use a method of the Schema API
 | ||||
|   //   that corresponds to the exact kind of dependency. For example, to get a field type, use
 | ||||
|   //   StructSchema::Field::getType().
 | ||||
|   //
 | ||||
|   // Construct from an element type schema.  Requires a context which can handle getDependency()
 | ||||
|   // requests for any type ID found in the schema.
 | ||||
| 
 | ||||
|   Type getElementType() const; | ||||
| 
 | ||||
|   inline schema::Type::Which whichElementType() const; | ||||
|   // Get the element type's "which()".  ListSchema does not actually store a schema::Type::Reader
 | ||||
|   // describing the element type, but if it did, this would be equivalent to calling
 | ||||
|   // .getBody().which() on that type.
 | ||||
| 
 | ||||
|   StructSchema getStructElementType() const; | ||||
|   EnumSchema getEnumElementType() const; | ||||
|   InterfaceSchema getInterfaceElementType() const; | ||||
|   ListSchema getListElementType() const; | ||||
|   // Get the schema for complex element types.  Each of these throws an exception if the element
 | ||||
|   // type is not of the requested kind.
 | ||||
| 
 | ||||
|   inline bool operator==(const ListSchema& other) const { return elementType == other.elementType; } | ||||
|   inline bool operator!=(const ListSchema& other) const { return elementType != other.elementType; } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   void requireUsableAs() const; | ||||
| 
 | ||||
| private: | ||||
|   Type elementType; | ||||
| 
 | ||||
|   inline explicit ListSchema(Type elementType): elementType(elementType) {} | ||||
| 
 | ||||
|   template <typename T> | ||||
|   struct FromImpl; | ||||
|   template <typename T> static inline ListSchema fromImpl() { | ||||
|     return FromImpl<T>::get(); | ||||
|   } | ||||
| 
 | ||||
|   void requireUsableAs(ListSchema expected) const; | ||||
| 
 | ||||
|   friend class Schema; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // inline implementation
 | ||||
| 
 | ||||
| template <> inline schema::Type::Which Schema::from<Void>() { return schema::Type::VOID; } | ||||
| template <> inline schema::Type::Which Schema::from<bool>() { return schema::Type::BOOL; } | ||||
| template <> inline schema::Type::Which Schema::from<int8_t>() { return schema::Type::INT8; } | ||||
| template <> inline schema::Type::Which Schema::from<int16_t>() { return schema::Type::INT16; } | ||||
| template <> inline schema::Type::Which Schema::from<int32_t>() { return schema::Type::INT32; } | ||||
| template <> inline schema::Type::Which Schema::from<int64_t>() { return schema::Type::INT64; } | ||||
| template <> inline schema::Type::Which Schema::from<uint8_t>() { return schema::Type::UINT8; } | ||||
| template <> inline schema::Type::Which Schema::from<uint16_t>() { return schema::Type::UINT16; } | ||||
| template <> inline schema::Type::Which Schema::from<uint32_t>() { return schema::Type::UINT32; } | ||||
| template <> inline schema::Type::Which Schema::from<uint64_t>() { return schema::Type::UINT64; } | ||||
| template <> inline schema::Type::Which Schema::from<float>() { return schema::Type::FLOAT32; } | ||||
| template <> inline schema::Type::Which Schema::from<double>() { return schema::Type::FLOAT64; } | ||||
| template <> inline schema::Type::Which Schema::from<Text>() { return schema::Type::TEXT; } | ||||
| template <> inline schema::Type::Which Schema::from<Data>() { return schema::Type::DATA; } | ||||
| 
 | ||||
| inline Schema Schema::getDependency(uint64_t id) const { | ||||
|   return getDependency(id, 0); | ||||
| } | ||||
| 
 | ||||
| inline bool Schema::isBranded() const { | ||||
|   return raw != &raw->generic->defaultBrand; | ||||
| } | ||||
| 
 | ||||
| inline Schema Schema::getGeneric() const { | ||||
|   return Schema(&raw->generic->defaultBrand); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline void Schema::requireUsableAs() const { | ||||
|   requireUsableAs(&_::rawSchema<T>()); | ||||
| } | ||||
| 
 | ||||
| inline bool StructSchema::Field::operator==(const Field& other) const { | ||||
|   return parent == other.parent && index == other.index; | ||||
| } | ||||
| inline bool EnumSchema::Enumerant::operator==(const Enumerant& other) const { | ||||
|   return parent == other.parent && ordinal == other.ordinal; | ||||
| } | ||||
| inline bool InterfaceSchema::Method::operator==(const Method& other) const { | ||||
|   return parent == other.parent && ordinal == other.ordinal; | ||||
| } | ||||
| 
 | ||||
| inline ListSchema ListSchema::of(StructSchema elementType) { | ||||
|   return ListSchema(Type(elementType)); | ||||
| } | ||||
| inline ListSchema ListSchema::of(EnumSchema elementType) { | ||||
|   return ListSchema(Type(elementType)); | ||||
| } | ||||
| inline ListSchema ListSchema::of(InterfaceSchema elementType) { | ||||
|   return ListSchema(Type(elementType)); | ||||
| } | ||||
| inline ListSchema ListSchema::of(ListSchema elementType) { | ||||
|   return ListSchema(Type(elementType)); | ||||
| } | ||||
| inline ListSchema ListSchema::of(Type elementType) { | ||||
|   return ListSchema(elementType); | ||||
| } | ||||
| 
 | ||||
| inline Type ListSchema::getElementType() const { | ||||
|   return elementType; | ||||
| } | ||||
| 
 | ||||
| inline schema::Type::Which ListSchema::whichElementType() const { | ||||
|   return elementType.which(); | ||||
| } | ||||
| 
 | ||||
| inline StructSchema ListSchema::getStructElementType() const { | ||||
|   return elementType.asStruct(); | ||||
| } | ||||
| 
 | ||||
| inline EnumSchema ListSchema::getEnumElementType() const { | ||||
|   return elementType.asEnum(); | ||||
| } | ||||
| 
 | ||||
| inline InterfaceSchema ListSchema::getInterfaceElementType() const { | ||||
|   return elementType.asInterface(); | ||||
| } | ||||
| 
 | ||||
| inline ListSchema ListSchema::getListElementType() const { | ||||
|   return elementType.asList(); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline void ListSchema::requireUsableAs() const { | ||||
|   static_assert(kind<T>() == Kind::LIST, | ||||
|                 "ListSchema::requireUsableAs<T>() requires T is a list type."); | ||||
|   requireUsableAs(Schema::from<T>()); | ||||
| } | ||||
| 
 | ||||
| inline void ListSchema::requireUsableAs(ListSchema expected) const { | ||||
|   elementType.requireUsableAs(expected.elementType); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| struct ListSchema::FromImpl<List<T>> { | ||||
|   static inline ListSchema get() { return of(Schema::from<T>()); } | ||||
| }; | ||||
| 
 | ||||
| inline Type::Type(): baseType(schema::Type::VOID), listDepth(0), schema(nullptr) {} | ||||
| inline Type::Type(schema::Type::Which primitive) | ||||
|     : baseType(primitive), listDepth(0), isImplicitParam(false) { | ||||
|   KJ_IREQUIRE(primitive != schema::Type::STRUCT && | ||||
|               primitive != schema::Type::ENUM && | ||||
|               primitive != schema::Type::INTERFACE && | ||||
|               primitive != schema::Type::LIST); | ||||
|   if (primitive == schema::Type::ANY_POINTER) { | ||||
|     scopeId = 0; | ||||
|     anyPointerKind = schema::Type::AnyPointer::Unconstrained::ANY_KIND; | ||||
|   } else { | ||||
|     schema = nullptr; | ||||
|   } | ||||
| } | ||||
| inline Type::Type(schema::Type::Which derived, const _::RawBrandedSchema* schema) | ||||
|     : baseType(derived), listDepth(0), isImplicitParam(false), schema(schema) { | ||||
|   KJ_IREQUIRE(derived == schema::Type::STRUCT || | ||||
|               derived == schema::Type::ENUM || | ||||
|               derived == schema::Type::INTERFACE); | ||||
| } | ||||
| 
 | ||||
| inline Type::Type(StructSchema schema) | ||||
|     : baseType(schema::Type::STRUCT), listDepth(0), schema(schema.raw) {} | ||||
| inline Type::Type(EnumSchema schema) | ||||
|     : baseType(schema::Type::ENUM), listDepth(0), schema(schema.raw) {} | ||||
| inline Type::Type(InterfaceSchema schema) | ||||
|     : baseType(schema::Type::INTERFACE), listDepth(0), schema(schema.raw) {} | ||||
| inline Type::Type(ListSchema schema) | ||||
|     : Type(schema.getElementType()) { ++listDepth; } | ||||
| inline Type::Type(schema::Type::AnyPointer::Unconstrained::Which anyPointerKind) | ||||
|     : baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(false), | ||||
|       anyPointerKind(anyPointerKind), scopeId(0) {} | ||||
| inline Type::Type(BrandParameter param) | ||||
|     : baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(false), | ||||
|       paramIndex(param.index), scopeId(param.scopeId) {} | ||||
| inline Type::Type(ImplicitParameter param) | ||||
|     : baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(true), | ||||
|       paramIndex(param.index), scopeId(0) {} | ||||
| 
 | ||||
| inline schema::Type::Which Type::which() const { | ||||
|   return listDepth > 0 ? schema::Type::LIST : baseType; | ||||
| } | ||||
| 
 | ||||
| inline schema::Type::AnyPointer::Unconstrained::Which Type::whichAnyPointerKind() const { | ||||
|   KJ_IREQUIRE(baseType == schema::Type::ANY_POINTER); | ||||
|   return !isImplicitParam && scopeId == 0 ? anyPointerKind | ||||
|       : schema::Type::AnyPointer::Unconstrained::ANY_KIND; | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline Type Type::from() { return Type(Schema::from<T>()); } | ||||
| 
 | ||||
| inline bool Type::isVoid   () const { return baseType == schema::Type::VOID     && listDepth == 0; } | ||||
| inline bool Type::isBool   () const { return baseType == schema::Type::BOOL     && listDepth == 0; } | ||||
| inline bool Type::isInt8   () const { return baseType == schema::Type::INT8     && listDepth == 0; } | ||||
| inline bool Type::isInt16  () const { return baseType == schema::Type::INT16    && listDepth == 0; } | ||||
| inline bool Type::isInt32  () const { return baseType == schema::Type::INT32    && listDepth == 0; } | ||||
| inline bool Type::isInt64  () const { return baseType == schema::Type::INT64    && listDepth == 0; } | ||||
| inline bool Type::isUInt8  () const { return baseType == schema::Type::UINT8    && listDepth == 0; } | ||||
| inline bool Type::isUInt16 () const { return baseType == schema::Type::UINT16   && listDepth == 0; } | ||||
| inline bool Type::isUInt32 () const { return baseType == schema::Type::UINT32   && listDepth == 0; } | ||||
| inline bool Type::isUInt64 () const { return baseType == schema::Type::UINT64   && listDepth == 0; } | ||||
| inline bool Type::isFloat32() const { return baseType == schema::Type::FLOAT32  && listDepth == 0; } | ||||
| inline bool Type::isFloat64() const { return baseType == schema::Type::FLOAT64  && listDepth == 0; } | ||||
| inline bool Type::isText   () const { return baseType == schema::Type::TEXT     && listDepth == 0; } | ||||
| inline bool Type::isData   () const { return baseType == schema::Type::DATA     && listDepth == 0; } | ||||
| inline bool Type::isList   () const { return listDepth > 0; } | ||||
| inline bool Type::isEnum   () const { return baseType == schema::Type::ENUM     && listDepth == 0; } | ||||
| inline bool Type::isStruct () const { return baseType == schema::Type::STRUCT   && listDepth == 0; } | ||||
| inline bool Type::isInterface() const { | ||||
|   return baseType == schema::Type::INTERFACE && listDepth == 0; | ||||
| } | ||||
| inline bool Type::isAnyPointer() const { | ||||
|   return baseType == schema::Type::ANY_POINTER && listDepth == 0; | ||||
| } | ||||
| 
 | ||||
| inline Type Type::wrapInList(uint depth) const { | ||||
|   Type result = *this; | ||||
|   result.listDepth += depth; | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_SCHEMA_H_
 | ||||
| @ -0,0 +1,64 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_SERIALIZE_ASYNC_H_ | ||||
| #define CAPNP_SERIALIZE_ASYNC_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include <kj/async-io.h> | ||||
| #include "message.h" | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| kj::Promise<kj::Own<MessageReader>> readMessage( | ||||
|     kj::AsyncInputStream& input, ReaderOptions options = ReaderOptions(), | ||||
|     kj::ArrayPtr<word> scratchSpace = nullptr); | ||||
| // Read a message asynchronously.
 | ||||
| //
 | ||||
| // `input` must remain valid until the returned promise resolves (or is canceled).
 | ||||
| //
 | ||||
| // `scratchSpace`, if provided, must remain valid until the returned MessageReader is destroyed.
 | ||||
| 
 | ||||
| kj::Promise<kj::Maybe<kj::Own<MessageReader>>> tryReadMessage( | ||||
|     kj::AsyncInputStream& input, ReaderOptions options = ReaderOptions(), | ||||
|     kj::ArrayPtr<word> scratchSpace = nullptr); | ||||
| // Like `readMessage` but returns null on EOF.
 | ||||
| 
 | ||||
| kj::Promise<void> writeMessage(kj::AsyncOutputStream& output, | ||||
|                                kj::ArrayPtr<const kj::ArrayPtr<const word>> segments) | ||||
|     KJ_WARN_UNUSED_RESULT; | ||||
| kj::Promise<void> writeMessage(kj::AsyncOutputStream& output, MessageBuilder& builder) | ||||
|     KJ_WARN_UNUSED_RESULT; | ||||
| // Write asynchronously.  The parameters must remain valid until the returned promise resolves.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // inline implementation details
 | ||||
| 
 | ||||
| inline kj::Promise<void> writeMessage(kj::AsyncOutputStream& output, MessageBuilder& builder) { | ||||
|   return writeMessage(output, builder.getSegmentsForOutput()); | ||||
| } | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_SERIALIZE_ASYNC_H_
 | ||||
| @ -0,0 +1,130 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_SERIALIZE_PACKED_H_ | ||||
| #define CAPNP_SERIALIZE_PACKED_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "serialize.h" | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| class PackedInputStream: public kj::InputStream { | ||||
|   // An input stream that unpacks packed data with a picky constraint:  The caller must read data
 | ||||
|   // in the exact same size and sequence as the data was written to PackedOutputStream.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit PackedInputStream(kj::BufferedInputStream& inner); | ||||
|   KJ_DISALLOW_COPY(PackedInputStream); | ||||
|   ~PackedInputStream() noexcept(false); | ||||
| 
 | ||||
|   // implements InputStream ------------------------------------------
 | ||||
|   size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override; | ||||
|   void skip(size_t bytes) override; | ||||
| 
 | ||||
| private: | ||||
|   kj::BufferedInputStream& inner; | ||||
| }; | ||||
| 
 | ||||
| class PackedOutputStream: public kj::OutputStream { | ||||
| public: | ||||
|   explicit PackedOutputStream(kj::BufferedOutputStream& inner); | ||||
|   KJ_DISALLOW_COPY(PackedOutputStream); | ||||
|   ~PackedOutputStream() noexcept(false); | ||||
| 
 | ||||
|   // implements OutputStream -----------------------------------------
 | ||||
|   void write(const void* buffer, size_t bytes) override; | ||||
| 
 | ||||
| private: | ||||
|   kj::BufferedOutputStream& inner; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| class PackedMessageReader: private _::PackedInputStream, public InputStreamMessageReader { | ||||
| public: | ||||
|   PackedMessageReader(kj::BufferedInputStream& inputStream, ReaderOptions options = ReaderOptions(), | ||||
|                       kj::ArrayPtr<word> scratchSpace = nullptr); | ||||
|   KJ_DISALLOW_COPY(PackedMessageReader); | ||||
|   ~PackedMessageReader() noexcept(false); | ||||
| }; | ||||
| 
 | ||||
| class PackedFdMessageReader: private kj::FdInputStream, private kj::BufferedInputStreamWrapper, | ||||
|                              public PackedMessageReader { | ||||
| public: | ||||
|   PackedFdMessageReader(int fd, ReaderOptions options = ReaderOptions(), | ||||
|                         kj::ArrayPtr<word> scratchSpace = nullptr); | ||||
|   // Read message from a file descriptor, without taking ownership of the descriptor.
 | ||||
|   // Note that if you want to reuse the descriptor after the reader is destroyed, you'll need to
 | ||||
|   // seek it, since otherwise the position is unspecified.
 | ||||
| 
 | ||||
|   PackedFdMessageReader(kj::AutoCloseFd fd, ReaderOptions options = ReaderOptions(), | ||||
|                         kj::ArrayPtr<word> scratchSpace = nullptr); | ||||
|   // Read a message from a file descriptor, taking ownership of the descriptor.
 | ||||
| 
 | ||||
|   KJ_DISALLOW_COPY(PackedFdMessageReader); | ||||
| 
 | ||||
|   ~PackedFdMessageReader() noexcept(false); | ||||
| }; | ||||
| 
 | ||||
| void writePackedMessage(kj::BufferedOutputStream& output, MessageBuilder& builder); | ||||
| void writePackedMessage(kj::BufferedOutputStream& output, | ||||
|                         kj::ArrayPtr<const kj::ArrayPtr<const word>> segments); | ||||
| // Write a packed message to a buffered output stream.
 | ||||
| 
 | ||||
| void writePackedMessage(kj::OutputStream& output, MessageBuilder& builder); | ||||
| void writePackedMessage(kj::OutputStream& output, | ||||
|                         kj::ArrayPtr<const kj::ArrayPtr<const word>> segments); | ||||
| // Write a packed message to an unbuffered output stream.  If you intend to write multiple messages
 | ||||
| // in succession, consider wrapping your output in a buffered stream in order to reduce system
 | ||||
| // call overhead.
 | ||||
| 
 | ||||
| void writePackedMessageToFd(int fd, MessageBuilder& builder); | ||||
| void writePackedMessageToFd(int fd, kj::ArrayPtr<const kj::ArrayPtr<const word>> segments); | ||||
| // Write a single packed message to the file descriptor.
 | ||||
| 
 | ||||
| size_t computeUnpackedSizeInWords(kj::ArrayPtr<const byte> packedBytes); | ||||
| // Computes the number of words to which the given packed bytes will unpack. Not intended for use
 | ||||
| // in performance-sensitive situations.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // inline stuff
 | ||||
| 
 | ||||
| inline void writePackedMessage(kj::BufferedOutputStream& output, MessageBuilder& builder) { | ||||
|   writePackedMessage(output, builder.getSegmentsForOutput()); | ||||
| } | ||||
| 
 | ||||
| inline void writePackedMessage(kj::OutputStream& output, MessageBuilder& builder) { | ||||
|   writePackedMessage(output, builder.getSegmentsForOutput()); | ||||
| } | ||||
| 
 | ||||
| inline void writePackedMessageToFd(int fd, MessageBuilder& builder) { | ||||
|   writePackedMessageToFd(fd, builder.getSegmentsForOutput()); | ||||
| } | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_SERIALIZE_PACKED_H_
 | ||||
| @ -0,0 +1,96 @@ | ||||
| // Copyright (c) 2015 Philip Quinn.
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef CAPNP_SERIALIZE_TEXT_H_ | ||||
| #define CAPNP_SERIALIZE_TEXT_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include <kj/string.h> | ||||
| #include "dynamic.h" | ||||
| #include "orphan.h" | ||||
| #include "schema.h" | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| class TextCodec { | ||||
|   // Reads and writes Cap'n Proto objects in a plain text format (as used in the schema
 | ||||
|   // language for constants, and read/written by the 'decode' and 'encode' commands of
 | ||||
|   // the capnp tool).
 | ||||
|   //
 | ||||
|   // This format is useful for debugging or human input, but it is not a robust alternative
 | ||||
|   // to the binary format. Changes to a schema's types or names that are permitted in a
 | ||||
|   // schema's binary evolution will likely break messages stored in this format.
 | ||||
|   //
 | ||||
|   // Note that definitions or references (to constants, other fields, or files) are not
 | ||||
|   // permitted in this format. To evaluate declarations with the full expressiveness of the
 | ||||
|   // schema language, see `capnp::SchemaParser`.
 | ||||
|   //
 | ||||
|   // Requires linking with the capnpc library.
 | ||||
| 
 | ||||
| public: | ||||
|   TextCodec(); | ||||
|   ~TextCodec() noexcept(true); | ||||
| 
 | ||||
|   void setPrettyPrint(bool enabled); | ||||
|   // If enabled, pads the output of `encode()` with spaces and newlines to make it more
 | ||||
|   // human-readable.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   kj::String encode(T&& value) const; | ||||
|   kj::String encode(DynamicValue::Reader value) const; | ||||
|   // Encode any Cap'n Proto value.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   Orphan<T> decode(kj::StringPtr input, Orphanage orphanage) const; | ||||
|   // Decode a text message into a Cap'n Proto object of type T, allocated in the given
 | ||||
|   // orphanage. Any errors parsing the input or assigning the fields of T are thrown as
 | ||||
|   // exceptions.
 | ||||
| 
 | ||||
|   void decode(kj::StringPtr input, DynamicStruct::Builder output) const; | ||||
|   // Decode a text message for a struct into the given builder. Any errors parsing the
 | ||||
|   // input or assigning the fields of the output are thrown as exceptions.
 | ||||
| 
 | ||||
|   // TODO(someday): expose some control over the error handling?
 | ||||
| private: | ||||
|   Orphan<DynamicValue> decode(kj::StringPtr input, Type type, Orphanage orphanage) const; | ||||
| 
 | ||||
|   bool prettyPrint; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // inline stuff
 | ||||
| 
 | ||||
| template <typename T> | ||||
| inline kj::String TextCodec::encode(T&& value) const { | ||||
|   return encode(DynamicValue::Reader(ReaderFor<FromAny<T>>(kj::fwd<T>(value)))); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline Orphan<T> TextCodec::decode(kj::StringPtr input, Orphanage orphanage) const { | ||||
|   return decode(input, Type::from<T>(), orphanage).template releaseAs<T>(); | ||||
| } | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // CAPNP_SERIALIZE_TEXT_H_
 | ||||
| @ -0,0 +1,237 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| // This file implements a simple serialization format for Cap'n Proto messages.  The format
 | ||||
| // is as follows:
 | ||||
| //
 | ||||
| // * 32-bit little-endian segment count (4 bytes).
 | ||||
| // * 32-bit little-endian size of each segment (4*(segment count) bytes).
 | ||||
| // * Padding so that subsequent data is 64-bit-aligned (0 or 4 bytes).  (I.e., if there are an even
 | ||||
| //     number of segments, there are 4 bytes of zeros here, otherwise there is no padding.)
 | ||||
| // * Data from each segment, in order (8*sum(segment sizes) bytes)
 | ||||
| //
 | ||||
| // This format has some important properties:
 | ||||
| // - It is self-delimiting, so multiple messages may be written to a stream without any external
 | ||||
| //   delimiter.
 | ||||
| // - The total size and position of each segment can be determined by reading only the first part
 | ||||
| //   of the message, allowing lazy and random-access reading of the segment data.
 | ||||
| // - A message is always at least 8 bytes.
 | ||||
| // - A single-segment message can be read entirely in two system calls with no buffering.
 | ||||
| // - A multi-segment message can be read entirely in three system calls with no buffering.
 | ||||
| // - The format is appropriate for mmap()ing since all data is aligned.
 | ||||
| 
 | ||||
| #ifndef CAPNP_SERIALIZE_H_ | ||||
| #define CAPNP_SERIALIZE_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "message.h" | ||||
| #include <kj/io.h> | ||||
| 
 | ||||
| namespace capnp { | ||||
| 
 | ||||
| class FlatArrayMessageReader: public MessageReader { | ||||
|   // Parses a message from a flat array.  Note that it makes sense to use this together with mmap()
 | ||||
|   // for extremely fast parsing.
 | ||||
| 
 | ||||
| public: | ||||
|   FlatArrayMessageReader(kj::ArrayPtr<const word> array, ReaderOptions options = ReaderOptions()); | ||||
|   // The array must remain valid until the MessageReader is destroyed.
 | ||||
| 
 | ||||
|   kj::ArrayPtr<const word> getSegment(uint id) override; | ||||
| 
 | ||||
|   const word* getEnd() const { return end; } | ||||
|   // Get a pointer just past the end of the message as determined by reading the message header.
 | ||||
|   // This could actually be before the end of the input array.  This pointer is useful e.g. if
 | ||||
|   // you know that the input array has extra stuff appended after the message and you want to
 | ||||
|   // get at it.
 | ||||
| 
 | ||||
| private: | ||||
|   // Optimize for single-segment case.
 | ||||
|   kj::ArrayPtr<const word> segment0; | ||||
|   kj::Array<kj::ArrayPtr<const word>> moreSegments; | ||||
|   const word* end; | ||||
| }; | ||||
| 
 | ||||
| kj::ArrayPtr<const word> initMessageBuilderFromFlatArrayCopy( | ||||
|     kj::ArrayPtr<const word> array, MessageBuilder& target, | ||||
|     ReaderOptions options = ReaderOptions()); | ||||
| // Convenience function which reads a message using `FlatArrayMessageReader` then copies the
 | ||||
| // content into the target `MessageBuilder`, verifying that the message structure is valid
 | ||||
| // (although not necessarily that it matches the desired schema).
 | ||||
| //
 | ||||
| // Returns an ArrayPtr containing any words left over in the array after consuming the whole
 | ||||
| // message. This is useful when reading multiple messages that have been concatenated. See also
 | ||||
| // FlatArrayMessageReader::getEnd().
 | ||||
| //
 | ||||
| // (Note that it's also possible to initialize a `MessageBuilder` directly without a copy using one
 | ||||
| // of `MessageBuilder`'s constructors. However, this approach skips the validation step and is not
 | ||||
| // safe to use on untrusted input. Therefore, we do not provide a convenience method for it.)
 | ||||
| 
 | ||||
| kj::Array<word> messageToFlatArray(MessageBuilder& builder); | ||||
| // Constructs a flat array containing the entire content of the given message.
 | ||||
| //
 | ||||
| // To output the message as bytes, use `.asBytes()` on the returned word array. Keep in mind that
 | ||||
| // `asBytes()` returns an ArrayPtr, so you have to save the Array as well to prevent it from being
 | ||||
| // deleted. For example:
 | ||||
| //
 | ||||
| //     kj::Array<capnp::word> words = messageToFlatArray(myMessage);
 | ||||
| //     kj::ArrayPtr<kj::byte> bytes = words.asBytes();
 | ||||
| //     write(fd, bytes.begin(), bytes.size());
 | ||||
| 
 | ||||
| kj::Array<word> messageToFlatArray(kj::ArrayPtr<const kj::ArrayPtr<const word>> segments); | ||||
| // Version of messageToFlatArray that takes a raw segment array.
 | ||||
| 
 | ||||
| size_t computeSerializedSizeInWords(MessageBuilder& builder); | ||||
| // Returns the size, in words, that will be needed to serialize the message, including the header.
 | ||||
| 
 | ||||
| size_t computeSerializedSizeInWords(kj::ArrayPtr<const kj::ArrayPtr<const word>> segments); | ||||
| // Version of computeSerializedSizeInWords that takes a raw segment array.
 | ||||
| 
 | ||||
| size_t expectedSizeInWordsFromPrefix(kj::ArrayPtr<const word> messagePrefix); | ||||
| // Given a prefix of a serialized message, try to determine the expected total size of the message,
 | ||||
| // in words. The returned size is based on the information known so far; it may be an underestimate
 | ||||
| // if the prefix doesn't contain the full segment table.
 | ||||
| //
 | ||||
| // If the returned value is greater than `messagePrefix.size()`, then the message is not yet
 | ||||
| // complete and the app cannot parse it yet. If the returned value is less than or equal to
 | ||||
| // `messagePrefix.size()`, then the returned value is the exact total size of the message; any
 | ||||
| // remaining bytes are part of the next message.
 | ||||
| //
 | ||||
| // This function is useful when reading messages from a stream in an asynchronous way, but when
 | ||||
| // using the full KJ async infrastructure would be too difficult. Each time bytes are received,
 | ||||
| // use this function to determine if an entire message is ready to be parsed.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| class InputStreamMessageReader: public MessageReader { | ||||
|   // A MessageReader that reads from an abstract kj::InputStream. See also StreamFdMessageReader
 | ||||
|   // for a subclass specific to file descriptors.
 | ||||
| 
 | ||||
| public: | ||||
|   InputStreamMessageReader(kj::InputStream& inputStream, | ||||
|                            ReaderOptions options = ReaderOptions(), | ||||
|                            kj::ArrayPtr<word> scratchSpace = nullptr); | ||||
|   ~InputStreamMessageReader() noexcept(false); | ||||
| 
 | ||||
|   // implements MessageReader ----------------------------------------
 | ||||
|   kj::ArrayPtr<const word> getSegment(uint id) override; | ||||
| 
 | ||||
| private: | ||||
|   kj::InputStream& inputStream; | ||||
|   byte* readPos; | ||||
| 
 | ||||
|   // Optimize for single-segment case.
 | ||||
|   kj::ArrayPtr<const word> segment0; | ||||
|   kj::Array<kj::ArrayPtr<const word>> moreSegments; | ||||
| 
 | ||||
|   kj::Array<word> ownedSpace; | ||||
|   // Only if scratchSpace wasn't big enough.
 | ||||
| 
 | ||||
|   kj::UnwindDetector unwindDetector; | ||||
| }; | ||||
| 
 | ||||
| void readMessageCopy(kj::InputStream& input, MessageBuilder& target, | ||||
|                      ReaderOptions options = ReaderOptions(), | ||||
|                      kj::ArrayPtr<word> scratchSpace = nullptr); | ||||
| // Convenience function which reads a message using `InputStreamMessageReader` then copies the
 | ||||
| // content into the target `MessageBuilder`, verifying that the message structure is valid
 | ||||
| // (although not necessarily that it matches the desired schema).
 | ||||
| //
 | ||||
| // (Note that it's also possible to initialize a `MessageBuilder` directly without a copy using one
 | ||||
| // of `MessageBuilder`'s constructors. However, this approach skips the validation step and is not
 | ||||
| // safe to use on untrusted input. Therefore, we do not provide a convenience method for it.)
 | ||||
| 
 | ||||
| void writeMessage(kj::OutputStream& output, MessageBuilder& builder); | ||||
| // Write the message to the given output stream.
 | ||||
| 
 | ||||
| void writeMessage(kj::OutputStream& output, kj::ArrayPtr<const kj::ArrayPtr<const word>> segments); | ||||
| // Write the segment array to the given output stream.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Specializations for reading from / writing to file descriptors.
 | ||||
| 
 | ||||
| class StreamFdMessageReader: private kj::FdInputStream, public InputStreamMessageReader { | ||||
|   // A MessageReader that reads from a steam-based file descriptor.
 | ||||
| 
 | ||||
| public: | ||||
|   StreamFdMessageReader(int fd, ReaderOptions options = ReaderOptions(), | ||||
|                         kj::ArrayPtr<word> scratchSpace = nullptr) | ||||
|       : FdInputStream(fd), InputStreamMessageReader(*this, options, scratchSpace) {} | ||||
|   // Read message from a file descriptor, without taking ownership of the descriptor.
 | ||||
| 
 | ||||
|   StreamFdMessageReader(kj::AutoCloseFd fd, ReaderOptions options = ReaderOptions(), | ||||
|                         kj::ArrayPtr<word> scratchSpace = nullptr) | ||||
|       : FdInputStream(kj::mv(fd)), InputStreamMessageReader(*this, options, scratchSpace) {} | ||||
|   // Read a message from a file descriptor, taking ownership of the descriptor.
 | ||||
| 
 | ||||
|   ~StreamFdMessageReader() noexcept(false); | ||||
| }; | ||||
| 
 | ||||
| void readMessageCopyFromFd(int fd, MessageBuilder& target, | ||||
|                            ReaderOptions options = ReaderOptions(), | ||||
|                            kj::ArrayPtr<word> scratchSpace = nullptr); | ||||
| // Convenience function which reads a message using `StreamFdMessageReader` then copies the
 | ||||
| // content into the target `MessageBuilder`, verifying that the message structure is valid
 | ||||
| // (although not necessarily that it matches the desired schema).
 | ||||
| //
 | ||||
| // (Note that it's also possible to initialize a `MessageBuilder` directly without a copy using one
 | ||||
| // of `MessageBuilder`'s constructors. However, this approach skips the validation step and is not
 | ||||
| // safe to use on untrusted input. Therefore, we do not provide a convenience method for it.)
 | ||||
| 
 | ||||
| void writeMessageToFd(int fd, MessageBuilder& builder); | ||||
| // Write the message to the given file descriptor.
 | ||||
| //
 | ||||
| // This function throws an exception on any I/O error.  If your code is not exception-safe, be sure
 | ||||
| // you catch this exception at the call site.  If throwing an exception is not acceptable, you
 | ||||
| // can implement your own OutputStream with arbitrary error handling and then use writeMessage().
 | ||||
| 
 | ||||
| void writeMessageToFd(int fd, kj::ArrayPtr<const kj::ArrayPtr<const word>> segments); | ||||
| // Write the segment array to the given file descriptor.
 | ||||
| //
 | ||||
| // This function throws an exception on any I/O error.  If your code is not exception-safe, be sure
 | ||||
| // you catch this exception at the call site.  If throwing an exception is not acceptable, you
 | ||||
| // can implement your own OutputStream with arbitrary error handling and then use writeMessage().
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // inline stuff
 | ||||
| 
 | ||||
| inline kj::Array<word> messageToFlatArray(MessageBuilder& builder) { | ||||
|   return messageToFlatArray(builder.getSegmentsForOutput()); | ||||
| } | ||||
| 
 | ||||
| inline size_t computeSerializedSizeInWords(MessageBuilder& builder) { | ||||
|   return computeSerializedSizeInWords(builder.getSegmentsForOutput()); | ||||
| } | ||||
| 
 | ||||
| inline void writeMessage(kj::OutputStream& output, MessageBuilder& builder) { | ||||
|   writeMessage(output, builder.getSegmentsForOutput()); | ||||
| } | ||||
| 
 | ||||
| inline void writeMessageToFd(int fd, MessageBuilder& builder) { | ||||
|   writeMessageToFd(fd, builder.getSegmentsForOutput()); | ||||
| } | ||||
| 
 | ||||
| }  // namespace capnp
 | ||||
| 
 | ||||
| #endif  // SERIALIZE_H_
 | ||||
| @ -0,0 +1,426 @@ | ||||
| /* vim: set sw=8 ts=8 sts=8 noet: */ | ||||
| /* capnp_c.h
 | ||||
|  * | ||||
|  * Copyright (C) 2013 James McKaskill | ||||
|  * Copyright (C) 2014 Steve Dee | ||||
|  * | ||||
|  * This software may be modified and distributed under the terms | ||||
|  * of the MIT license.  See the LICENSE file for details. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef CAPNP_C_H | ||||
| #define CAPNP_C_H | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #if defined(unix) && !defined(__APPLE__) | ||||
| #include <endian.h> | ||||
| #endif | ||||
| 
 | ||||
| // ssize_t is not defined in stdint.h in MSVC.
 | ||||
| #ifdef _MSC_VER | ||||
| typedef intmax_t ssize_t; | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #if defined(__cplusplus) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) | ||||
| #define CAPN_INLINE static inline | ||||
| #else | ||||
| #define CAPN_INLINE static | ||||
| #endif | ||||
| 
 | ||||
| #define CAPN_VERSION 1 | ||||
| 
 | ||||
| /* struct capn is a common structure shared between segments in the same
 | ||||
|  * session/context so that far pointers between segments will be created. | ||||
|  * | ||||
|  * lookup is used to lookup segments by id when derefencing a far pointer | ||||
|  * | ||||
|  * create is used to create or lookup an alternate segment that has at least | ||||
|  * sz available (ie returned seg->len + sz <= seg->cap) | ||||
|  * | ||||
|  * create_local is used to create a segment for the copy tree and should be | ||||
|  * allocated in the local memory space. | ||||
|  * | ||||
|  * Allocated segments must be zero initialized. | ||||
|  * | ||||
|  * create and lookup can be NULL if you don't need multiple segments and don't | ||||
|  * want to support copying | ||||
|  * | ||||
|  * seglist and copylist are linked lists which can be used to free up segments | ||||
|  * on cleanup, but should not be modified by the user. | ||||
|  * | ||||
|  * lookup, create, create_local, and user can be set by the user. Other values | ||||
|  * should be zero initialized. | ||||
|  */ | ||||
| struct capn { | ||||
| 	/* user settable */ | ||||
| 	struct capn_segment *(*lookup)(void* /*user*/, uint32_t /*id */); | ||||
| 	struct capn_segment *(*create)(void* /*user*/, uint32_t /*id */, int /*sz*/); | ||||
| 	struct capn_segment *(*create_local)(void* /*user*/, int /*sz*/); | ||||
| 	void *user; | ||||
| 	/* zero initialized, user should not modify */ | ||||
| 	uint32_t segnum; | ||||
| 	struct capn_tree *copy; | ||||
| 	struct capn_tree *segtree; | ||||
| 	struct capn_segment *seglist, *lastseg; | ||||
| 	struct capn_segment *copylist; | ||||
| }; | ||||
| 
 | ||||
| /* struct capn_tree is a rb tree header used internally for the segment id
 | ||||
|  * lookup and copy tree */ | ||||
| struct capn_tree { | ||||
| 	struct capn_tree *parent, *link[2]; | ||||
| 	unsigned int red : 1; | ||||
| }; | ||||
| 
 | ||||
| struct capn_tree *capn_tree_insert(struct capn_tree *root, struct capn_tree *n); | ||||
| 
 | ||||
| /* struct capn_segment contains the information about a single segment.
 | ||||
|  * | ||||
|  * capn points to a struct capn that is shared between segments in the | ||||
|  * same session | ||||
|  * | ||||
|  * id specifies the segment id, used for far pointers | ||||
|  * | ||||
|  * data specifies the segment data. This should not move after creation. | ||||
|  * | ||||
|  * len specifies the current segment length. This is 0 for a blank | ||||
|  * segment. | ||||
|  * | ||||
|  * cap specifies the segment capacity. | ||||
|  * | ||||
|  * When creating new structures len will be incremented until it reaces cap, | ||||
|  * at which point a new segment will be requested via capn->create. The | ||||
|  * create callback can either create a new segment or expand an existing | ||||
|  * one by incrementing cap and returning the expanded segment. | ||||
|  * | ||||
|  * data, len, and cap must all by 8 byte aligned | ||||
|  * | ||||
|  * data, len, cap, and user should all set by the user. Other values | ||||
|  * should be zero initialized. | ||||
|  */ | ||||
| #ifdef _MSC_VER | ||||
| __declspec(align(64)) | ||||
| #endif | ||||
| struct capn_segment { | ||||
| 	struct capn_tree hdr; | ||||
| 	struct capn_segment *next; | ||||
| 	struct capn *capn; | ||||
| 	uint32_t id; | ||||
| 	/* user settable */ | ||||
| 	char *data; | ||||
| 	size_t len, cap; | ||||
| 	void *user; | ||||
| }; | ||||
| 
 | ||||
| enum CAPN_TYPE { | ||||
| 	CAPN_NULL = 0, | ||||
| 	CAPN_STRUCT = 1, | ||||
| 	CAPN_LIST = 2, | ||||
| 	CAPN_PTR_LIST = 3, | ||||
| 	CAPN_BIT_LIST = 4, | ||||
| 	CAPN_FAR_POINTER = 5, | ||||
| }; | ||||
| 
 | ||||
| struct capn_ptr { | ||||
| 	unsigned int type : 4; | ||||
| 	unsigned int has_ptr_tag : 1; | ||||
| 	unsigned int is_list_member : 1; | ||||
| 	unsigned int is_composite_list : 1; | ||||
| 	unsigned int datasz : 19; | ||||
| 	unsigned int ptrs : 16; | ||||
| 	int len; | ||||
| 	char *data; | ||||
| 	struct capn_segment *seg; | ||||
| }; | ||||
| 
 | ||||
| struct capn_text { | ||||
| 	int len; | ||||
| 	const char *str; | ||||
| 	struct capn_segment *seg; | ||||
| }; | ||||
| 
 | ||||
| typedef struct capn_ptr capn_ptr; | ||||
| typedef struct capn_text capn_text; | ||||
| typedef struct {capn_ptr p;} capn_data; | ||||
| typedef struct {capn_ptr p;} capn_list1; | ||||
| typedef struct {capn_ptr p;} capn_list8; | ||||
| typedef struct {capn_ptr p;} capn_list16; | ||||
| typedef struct {capn_ptr p;} capn_list32; | ||||
| typedef struct {capn_ptr p;} capn_list64; | ||||
| 
 | ||||
| struct capn_msg { | ||||
| 	struct capn_segment *seg; | ||||
| 	uint64_t iface; | ||||
| 	uint16_t method; | ||||
| 	capn_ptr args; | ||||
| }; | ||||
| 
 | ||||
| /* capn_append_segment appends a segment to a session */ | ||||
| void capn_append_segment(struct capn*, struct capn_segment*); | ||||
| 
 | ||||
| capn_ptr capn_root(struct capn *c); | ||||
| void capn_resolve(capn_ptr *p); | ||||
| 
 | ||||
| #define capn_len(list) ((list).p.type == CAPN_FAR_POINTER ? (capn_resolve(&(list).p), (list).p.len) : (list).p.len) | ||||
| 
 | ||||
| /* capn_getp|setp functions get/set ptrs in list/structs
 | ||||
|  * off is the list index or pointer index in a struct | ||||
|  * capn_setp will copy the data, create far pointers, etc if the target | ||||
|  * is in a different segment/context. | ||||
|  * Both of these will use/return inner pointers for composite lists. | ||||
|  */ | ||||
| capn_ptr capn_getp(capn_ptr p, int off, int resolve); | ||||
| int capn_setp(capn_ptr p, int off, capn_ptr tgt); | ||||
| 
 | ||||
| capn_text capn_get_text(capn_ptr p, int off, capn_text def); | ||||
| capn_data capn_get_data(capn_ptr p, int off); | ||||
| int capn_set_text(capn_ptr p, int off, capn_text tgt); | ||||
| 
 | ||||
| /* capn_get* functions get data from a list
 | ||||
|  * The length of the list is given by p->size | ||||
|  * off specifies how far into the list to start | ||||
|  * sz indicates the number of elements to get | ||||
|  * The function returns the number of elements read or -1 on an error. | ||||
|  * off must be byte aligned for capn_getv1 | ||||
|  */ | ||||
| int capn_get1(capn_list1 p, int off); | ||||
| uint8_t capn_get8(capn_list8 p, int off); | ||||
| uint16_t capn_get16(capn_list16 p, int off); | ||||
| uint32_t capn_get32(capn_list32 p, int off); | ||||
| uint64_t capn_get64(capn_list64 p, int off); | ||||
| int capn_getv1(capn_list1 p, int off, uint8_t *data, int sz); | ||||
| int capn_getv8(capn_list8 p, int off, uint8_t *data, int sz); | ||||
| int capn_getv16(capn_list16 p, int off, uint16_t *data, int sz); | ||||
| int capn_getv32(capn_list32 p, int off, uint32_t *data, int sz); | ||||
| int capn_getv64(capn_list64 p, int off, uint64_t *data, int sz); | ||||
| 
 | ||||
| /* capn_set* functions set data in a list
 | ||||
|  * off specifies how far into the list to start | ||||
|  * sz indicates the number of elements to write | ||||
|  * The function returns the number of elemnts written or -1 on an error. | ||||
|  * off must be byte aligned for capn_setv1 | ||||
|  */ | ||||
| int capn_set1(capn_list1 p, int off, int v); | ||||
| int capn_set8(capn_list8 p, int off, uint8_t v); | ||||
| int capn_set16(capn_list16 p, int off, uint16_t v); | ||||
| int capn_set32(capn_list32 p, int off, uint32_t v); | ||||
| int capn_set64(capn_list64 p, int off, uint64_t v); | ||||
| int capn_setv1(capn_list1 p, int off, const uint8_t *data, int sz); | ||||
| int capn_setv8(capn_list8 p, int off, const uint8_t *data, int sz); | ||||
| int capn_setv16(capn_list16 p, int off, const uint16_t *data, int sz); | ||||
| int capn_setv32(capn_list32 p, int off, const uint32_t *data, int sz); | ||||
| int capn_setv64(capn_list64 p, int off, const uint64_t *data, int sz); | ||||
| 
 | ||||
| /* capn_new_* functions create a new object
 | ||||
|  * datasz is in bytes, ptrs is # of pointers, sz is # of elements in the list | ||||
|  * On an error a CAPN_NULL pointer is returned | ||||
|  */ | ||||
| capn_ptr capn_new_string(struct capn_segment *seg, const char *str, ssize_t sz); | ||||
| capn_ptr capn_new_struct(struct capn_segment *seg, int datasz, int ptrs); | ||||
| capn_ptr capn_new_interface(struct capn_segment *seg, int datasz, int ptrs); | ||||
| capn_ptr capn_new_ptr_list(struct capn_segment *seg, int sz); | ||||
| capn_ptr capn_new_list(struct capn_segment *seg, int sz, int datasz, int ptrs); | ||||
| capn_list1 capn_new_list1(struct capn_segment *seg, int sz); | ||||
| capn_list8 capn_new_list8(struct capn_segment *seg, int sz); | ||||
| capn_list16 capn_new_list16(struct capn_segment *seg, int sz); | ||||
| capn_list32 capn_new_list32(struct capn_segment *seg, int sz); | ||||
| capn_list64 capn_new_list64(struct capn_segment *seg, int sz); | ||||
| 
 | ||||
| /* capn_read|write* functions read/write struct values
 | ||||
|  * off is the offset into the structure in bytes | ||||
|  * Rarely should these be called directly, instead use the generated code. | ||||
|  * Data must be xored with the default value | ||||
|  * These are inlined | ||||
|  */ | ||||
| CAPN_INLINE uint8_t capn_read8(capn_ptr p, int off); | ||||
| CAPN_INLINE uint16_t capn_read16(capn_ptr p, int off); | ||||
| CAPN_INLINE uint32_t capn_read32(capn_ptr p, int off); | ||||
| CAPN_INLINE uint64_t capn_read64(capn_ptr p, int off); | ||||
| CAPN_INLINE int capn_write1(capn_ptr p, int off, int val); | ||||
| CAPN_INLINE int capn_write8(capn_ptr p, int off, uint8_t val); | ||||
| CAPN_INLINE int capn_write16(capn_ptr p, int off, uint16_t val); | ||||
| CAPN_INLINE int capn_write32(capn_ptr p, int off, uint32_t val); | ||||
| CAPN_INLINE int capn_write64(capn_ptr p, int off, uint64_t val); | ||||
| 
 | ||||
| /* capn_init_malloc inits the capn struct with a create function which
 | ||||
|  * allocates segments on the heap using malloc | ||||
|  * | ||||
|  * capn_init_(fp|mem) inits by reading segments in from the file/memory buffer | ||||
|  * in serialized form (optionally packed). It will then setup the create | ||||
|  * function ala capn_init_malloc so that further segments can be created. | ||||
|  * | ||||
|  * capn_free frees all the segment headers and data created by the create | ||||
|  * function setup by capn_init_* | ||||
|  */ | ||||
| void capn_init_malloc(struct capn *c); | ||||
| int capn_init_fp(struct capn *c, FILE *f, int packed); | ||||
| int capn_init_mem(struct capn *c, const uint8_t *p, size_t sz, int packed); | ||||
| 
 | ||||
| /* capn_write_(fp|mem) writes segments to the file/memory buffer in
 | ||||
|  * serialized form and returns the number of bytes written. | ||||
|  */ | ||||
| /* TODO */ | ||||
| /*int capn_write_fp(struct capn *c, FILE *f, int packed);*/ | ||||
| int capn_write_fd(struct capn *c, ssize_t (*write_fd)(int fd, void *p, size_t count), int fd, int packed); | ||||
| int capn_write_mem(struct capn *c, uint8_t *p, size_t sz, int packed); | ||||
| 
 | ||||
| void capn_free(struct capn *c); | ||||
| void capn_reset_copy(struct capn *c); | ||||
| 
 | ||||
| /* Inline functions */ | ||||
| 
 | ||||
| 
 | ||||
| CAPN_INLINE uint8_t capn_flip8(uint8_t v) { | ||||
| 	return v; | ||||
| } | ||||
| CAPN_INLINE uint16_t capn_flip16(uint16_t v) { | ||||
| #if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) | ||||
| 	return v; | ||||
| #elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) && \ | ||||
|       defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 | ||||
| 	return __builtin_bswap16(v); | ||||
| #else | ||||
| 	union { uint16_t u; uint8_t v[2]; } s; | ||||
| 	s.v[0] = (uint8_t)v; | ||||
| 	s.v[1] = (uint8_t)(v>>8); | ||||
| 	return s.u; | ||||
| #endif | ||||
| } | ||||
| CAPN_INLINE uint32_t capn_flip32(uint32_t v) { | ||||
| #if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) | ||||
| 	return v; | ||||
| #elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) && \ | ||||
|       defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 | ||||
| 	return __builtin_bswap32(v); | ||||
| #else | ||||
| 	union { uint32_t u; uint8_t v[4]; } s; | ||||
| 	s.v[0] = (uint8_t)v; | ||||
| 	s.v[1] = (uint8_t)(v>>8); | ||||
| 	s.v[2] = (uint8_t)(v>>16); | ||||
| 	s.v[3] = (uint8_t)(v>>24); | ||||
| 	return s.u; | ||||
| #endif | ||||
| } | ||||
| CAPN_INLINE uint64_t capn_flip64(uint64_t v) { | ||||
| #if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) | ||||
| 	return v; | ||||
| #elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) && \ | ||||
|       defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 | ||||
| 	return __builtin_bswap64(v); | ||||
| #else | ||||
| 	union { uint64_t u; uint8_t v[8]; } s; | ||||
| 	s.v[0] = (uint8_t)v; | ||||
| 	s.v[1] = (uint8_t)(v>>8); | ||||
| 	s.v[2] = (uint8_t)(v>>16); | ||||
| 	s.v[3] = (uint8_t)(v>>24); | ||||
| 	s.v[4] = (uint8_t)(v>>32); | ||||
| 	s.v[5] = (uint8_t)(v>>40); | ||||
| 	s.v[6] = (uint8_t)(v>>48); | ||||
| 	s.v[7] = (uint8_t)(v>>56); | ||||
| 	return s.u; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| CAPN_INLINE int capn_write1(capn_ptr p, int off, int val) { | ||||
| 	if (off >= p.datasz*8) { | ||||
| 		return -1; | ||||
| 	} else if (val) { | ||||
| 		uint8_t tmp = (uint8_t)(1 << (off & 7)); | ||||
| 		((uint8_t*) p.data)[off >> 3] |= tmp; | ||||
| 		return 0; | ||||
| 	} else { | ||||
| 		uint8_t tmp = (uint8_t)(~(1 << (off & 7))); | ||||
| 		((uint8_t*) p.data)[off >> 3] &= tmp; | ||||
| 		return 0; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| CAPN_INLINE uint8_t capn_read8(capn_ptr p, int off) { | ||||
| 	return off+1 <= p.datasz ? capn_flip8(*(uint8_t*) (p.data+off)) : 0; | ||||
| } | ||||
| CAPN_INLINE int capn_write8(capn_ptr p, int off, uint8_t val) { | ||||
| 	if (off+1 <= p.datasz) { | ||||
| 		*(uint8_t*) (p.data+off) = capn_flip8(val); | ||||
| 		return 0; | ||||
| 	} else { | ||||
| 		return -1; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| CAPN_INLINE uint16_t capn_read16(capn_ptr p, int off) { | ||||
| 	return off+2 <= p.datasz ? capn_flip16(*(uint16_t*) (p.data+off)) : 0; | ||||
| } | ||||
| CAPN_INLINE int capn_write16(capn_ptr p, int off, uint16_t val) { | ||||
| 	if (off+2 <= p.datasz) { | ||||
| 		*(uint16_t*) (p.data+off) = capn_flip16(val); | ||||
| 		return 0; | ||||
| 	} else { | ||||
| 		return -1; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| CAPN_INLINE uint32_t capn_read32(capn_ptr p, int off) { | ||||
| 	return off+4 <= p.datasz ? capn_flip32(*(uint32_t*) (p.data+off)) : 0; | ||||
| } | ||||
| CAPN_INLINE int capn_write32(capn_ptr p, int off, uint32_t val) { | ||||
| 	if (off+4 <= p.datasz) { | ||||
| 		*(uint32_t*) (p.data+off) = capn_flip32(val); | ||||
| 		return 0; | ||||
| 	} else { | ||||
| 		return -1; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| CAPN_INLINE uint64_t capn_read64(capn_ptr p, int off) { | ||||
| 	return off+8 <= p.datasz ? capn_flip64(*(uint64_t*) (p.data+off)) : 0; | ||||
| } | ||||
| CAPN_INLINE int capn_write64(capn_ptr p, int off, uint64_t val) { | ||||
| 	if (off+8 <= p.datasz) { | ||||
| 		*(uint64_t*) (p.data+off) = capn_flip64(val); | ||||
| 		return 0; | ||||
| 	} else { | ||||
| 		return -1; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| union capn_conv_f32 { | ||||
| 	uint32_t u; | ||||
| 	float f; | ||||
| }; | ||||
| 
 | ||||
| union capn_conv_f64 { | ||||
| 	uint64_t u; | ||||
| 	double f; | ||||
| }; | ||||
| 
 | ||||
| CAPN_INLINE float capn_to_f32(uint32_t v) { | ||||
| 	union capn_conv_f32 u; | ||||
| 	u.u = v; | ||||
| 	return u.f; | ||||
| } | ||||
| CAPN_INLINE double capn_to_f64(uint64_t v) { | ||||
| 	union capn_conv_f64 u; | ||||
| 	u.u = v; | ||||
| 	return u.f; | ||||
| } | ||||
| CAPN_INLINE uint32_t capn_from_f32(float v) { | ||||
| 	union capn_conv_f32 u; | ||||
| 	u.f = v; | ||||
| 	return u.u; | ||||
| } | ||||
| CAPN_INLINE uint64_t capn_from_f64(double v) { | ||||
| 	union capn_conv_f64 u; | ||||
| 	u.f = v; | ||||
| 	return u.u; | ||||
| } | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
| @ -0,0 +1,213 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_ARENA_H_ | ||||
| #define KJ_ARENA_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "memory.h" | ||||
| #include "array.h" | ||||
| #include "string.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| class Arena { | ||||
|   // A class which allows several objects to be allocated in contiguous chunks of memory, then
 | ||||
|   // frees them all at once.
 | ||||
|   //
 | ||||
|   // Allocating from the same Arena in multiple threads concurrently is NOT safe, because making
 | ||||
|   // it safe would require atomic operations that would slow down allocation even when
 | ||||
|   // single-threaded.  If you need to use arena allocation in a multithreaded context, consider
 | ||||
|   // allocating thread-local arenas.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit Arena(size_t chunkSizeHint = 1024); | ||||
|   // Create an Arena.  `chunkSizeHint` hints at where to start when allocating chunks, but is only
 | ||||
|   // a hint -- the Arena will, for example, allocate progressively larger chunks as time goes on,
 | ||||
|   // in order to reduce overall allocation overhead.
 | ||||
| 
 | ||||
|   explicit Arena(ArrayPtr<byte> scratch); | ||||
|   // Allocates from the given scratch space first, only resorting to the heap when it runs out.
 | ||||
| 
 | ||||
|   KJ_DISALLOW_COPY(Arena); | ||||
|   ~Arena() noexcept(false); | ||||
| 
 | ||||
|   template <typename T, typename... Params> | ||||
|   T& allocate(Params&&... params); | ||||
|   template <typename T> | ||||
|   ArrayPtr<T> allocateArray(size_t size); | ||||
|   // Allocate an object or array of type T.  If T has a non-trivial destructor, that destructor
 | ||||
|   // will be run during the Arena's destructor.  Such destructors are run in opposite order of
 | ||||
|   // allocation.  Note that these methods must maintain a list of destructors to call, which has
 | ||||
|   // overhead, but this overhead only applies if T has a non-trivial destructor.
 | ||||
| 
 | ||||
|   template <typename T, typename... Params> | ||||
|   Own<T> allocateOwn(Params&&... params); | ||||
|   template <typename T> | ||||
|   Array<T> allocateOwnArray(size_t size); | ||||
|   template <typename T> | ||||
|   ArrayBuilder<T> allocateOwnArrayBuilder(size_t capacity); | ||||
|   // Allocate an object or array of type T.  Destructors are executed when the returned Own<T>
 | ||||
|   // or Array<T> goes out-of-scope, which must happen before the Arena is destroyed.  This variant
 | ||||
|   // is useful when you need to control when the destructor is called.  This variant also avoids
 | ||||
|   // the need for the Arena itself to keep track of destructors to call later, which may make it
 | ||||
|   // slightly more efficient.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   inline T& copy(T&& value) { return allocate<Decay<T>>(kj::fwd<T>(value)); } | ||||
|   // Allocate a copy of the given value in the arena.  This is just a shortcut for calling the
 | ||||
|   // type's copy (or move) constructor.
 | ||||
| 
 | ||||
|   StringPtr copyString(StringPtr content); | ||||
|   // Make a copy of the given string inside the arena, and return a pointer to the copy.
 | ||||
| 
 | ||||
| private: | ||||
|   struct ChunkHeader { | ||||
|     ChunkHeader* next; | ||||
|     byte* pos;  // first unallocated byte in this chunk
 | ||||
|     byte* end;  // end of this chunk
 | ||||
|   }; | ||||
|   struct ObjectHeader { | ||||
|     void (*destructor)(void*); | ||||
|     ObjectHeader* next; | ||||
|   }; | ||||
| 
 | ||||
|   size_t nextChunkSize; | ||||
|   ChunkHeader* chunkList = nullptr; | ||||
|   ObjectHeader* objectList = nullptr; | ||||
| 
 | ||||
|   ChunkHeader* currentChunk = nullptr; | ||||
| 
 | ||||
|   void cleanup(); | ||||
|   // Run all destructors, leaving the above pointers null.  If a destructor throws, the State is
 | ||||
|   // left in a consistent state, such that if cleanup() is called again, it will pick up where
 | ||||
|   // it left off.
 | ||||
| 
 | ||||
|   void* allocateBytes(size_t amount, uint alignment, bool hasDisposer); | ||||
|   // Allocate the given number of bytes.  `hasDisposer` must be true if `setDisposer()` may be
 | ||||
|   // called on this pointer later.
 | ||||
| 
 | ||||
|   void* allocateBytesInternal(size_t amount, uint alignment); | ||||
|   // Try to allocate the given number of bytes without taking a lock.  Fails if and only if there
 | ||||
|   // is no space left in the current chunk.
 | ||||
| 
 | ||||
|   void setDestructor(void* ptr, void (*destructor)(void*)); | ||||
|   // Schedule the given destructor to be executed when the Arena is destroyed.  `ptr` must be a
 | ||||
|   // pointer previously returned by an `allocateBytes()` call for which `hasDisposer` was true.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   static void destroyArray(void* pointer) { | ||||
|     size_t elementCount = *reinterpret_cast<size_t*>(pointer); | ||||
|     constexpr size_t prefixSize = kj::max(alignof(T), sizeof(size_t)); | ||||
|     DestructorOnlyArrayDisposer::instance.disposeImpl( | ||||
|         reinterpret_cast<byte*>(pointer) + prefixSize, | ||||
|         sizeof(T), elementCount, elementCount, &destroyObject<T>); | ||||
|   } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   static void destroyObject(void* pointer) { | ||||
|     dtor(*reinterpret_cast<T*>(pointer)); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Inline implementation details
 | ||||
| 
 | ||||
| template <typename T, typename... Params> | ||||
| T& Arena::allocate(Params&&... params) { | ||||
|   T& result = *reinterpret_cast<T*>(allocateBytes( | ||||
|       sizeof(T), alignof(T), !__has_trivial_destructor(T))); | ||||
|   if (!__has_trivial_constructor(T) || sizeof...(Params) > 0) { | ||||
|     ctor(result, kj::fwd<Params>(params)...); | ||||
|   } | ||||
|   if (!__has_trivial_destructor(T)) { | ||||
|     setDestructor(&result, &destroyObject<T>); | ||||
|   } | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| ArrayPtr<T> Arena::allocateArray(size_t size) { | ||||
|   if (__has_trivial_destructor(T)) { | ||||
|     ArrayPtr<T> result = | ||||
|         arrayPtr(reinterpret_cast<T*>(allocateBytes( | ||||
|             sizeof(T) * size, alignof(T), false)), size); | ||||
|     if (!__has_trivial_constructor(T)) { | ||||
|       for (size_t i = 0; i < size; i++) { | ||||
|         ctor(result[i]); | ||||
|       } | ||||
|     } | ||||
|     return result; | ||||
|   } else { | ||||
|     // Allocate with a 64-bit prefix in which we store the array size.
 | ||||
|     constexpr size_t prefixSize = kj::max(alignof(T), sizeof(size_t)); | ||||
|     void* base = allocateBytes(sizeof(T) * size + prefixSize, alignof(T), true); | ||||
|     size_t& tag = *reinterpret_cast<size_t*>(base); | ||||
|     ArrayPtr<T> result = | ||||
|         arrayPtr(reinterpret_cast<T*>(reinterpret_cast<byte*>(base) + prefixSize), size); | ||||
|     setDestructor(base, &destroyArray<T>); | ||||
| 
 | ||||
|     if (__has_trivial_constructor(T)) { | ||||
|       tag = size; | ||||
|     } else { | ||||
|       // In case of constructor exceptions, we need the tag to end up storing the number of objects
 | ||||
|       // that were successfully constructed, so that they'll be properly destroyed.
 | ||||
|       tag = 0; | ||||
|       for (size_t i = 0; i < size; i++) { | ||||
|         ctor(result[i]); | ||||
|         tag = i + 1; | ||||
|       } | ||||
|     } | ||||
|     return result; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename... Params> | ||||
| Own<T> Arena::allocateOwn(Params&&... params) { | ||||
|   T& result = *reinterpret_cast<T*>(allocateBytes(sizeof(T), alignof(T), false)); | ||||
|   if (!__has_trivial_constructor(T) || sizeof...(Params) > 0) { | ||||
|     ctor(result, kj::fwd<Params>(params)...); | ||||
|   } | ||||
|   return Own<T>(&result, DestructorOnlyDisposer<T>::instance); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| Array<T> Arena::allocateOwnArray(size_t size) { | ||||
|   ArrayBuilder<T> result = allocateOwnArrayBuilder<T>(size); | ||||
|   for (size_t i = 0; i < size; i++) { | ||||
|     result.add(); | ||||
|   } | ||||
|   return result.finish(); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| ArrayBuilder<T> Arena::allocateOwnArrayBuilder(size_t capacity) { | ||||
|   return ArrayBuilder<T>( | ||||
|       reinterpret_cast<T*>(allocateBytes(sizeof(T) * capacity, alignof(T), false)), | ||||
|       capacity, DestructorOnlyArrayDisposer::instance); | ||||
| } | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_ARENA_H_
 | ||||
| @ -0,0 +1,813 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_ARRAY_H_ | ||||
| #define KJ_ARRAY_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "common.h" | ||||
| #include <string.h> | ||||
| #include <initializer_list> | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // ArrayDisposer -- Implementation details.
 | ||||
| 
 | ||||
| class ArrayDisposer { | ||||
|   // Much like Disposer from memory.h.
 | ||||
| 
 | ||||
| protected: | ||||
|   // Do not declare a destructor, as doing so will force a global initializer for
 | ||||
|   // HeapArrayDisposer::instance.
 | ||||
| 
 | ||||
|   virtual void disposeImpl(void* firstElement, size_t elementSize, size_t elementCount, | ||||
|                            size_t capacity, void (*destroyElement)(void*)) const = 0; | ||||
|   // Disposes of the array.  `destroyElement` invokes the destructor of each element, or is nullptr
 | ||||
|   // if the elements have trivial destructors.  `capacity` is the amount of space that was
 | ||||
|   // allocated while `elementCount` is the number of elements that were actually constructed;
 | ||||
|   // these are always the same number for Array<T> but may be different when using ArrayBuilder<T>.
 | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|   template <typename T> | ||||
|   void dispose(T* firstElement, size_t elementCount, size_t capacity) const; | ||||
|   // Helper wrapper around disposeImpl().
 | ||||
|   //
 | ||||
|   // Callers must not call dispose() on the same array twice, even if the first call throws
 | ||||
|   // an exception.
 | ||||
| 
 | ||||
| private: | ||||
|   template <typename T, bool hasTrivialDestructor = __has_trivial_destructor(T)> | ||||
|   struct Dispose_; | ||||
| }; | ||||
| 
 | ||||
| class ExceptionSafeArrayUtil { | ||||
|   // Utility class that assists in constructing or destroying elements of an array, where the
 | ||||
|   // constructor or destructor could throw exceptions.  In case of an exception,
 | ||||
|   // ExceptionSafeArrayUtil's destructor will call destructors on all elements that have been
 | ||||
|   // constructed but not destroyed.  Remember that destructors that throw exceptions are required
 | ||||
|   // to use UnwindDetector to detect unwind and avoid exceptions in this case.  Therefore, no more
 | ||||
|   // than one exception will be thrown (and the program will not terminate).
 | ||||
| 
 | ||||
| public: | ||||
|   inline ExceptionSafeArrayUtil(void* ptr, size_t elementSize, size_t constructedElementCount, | ||||
|                                 void (*destroyElement)(void*)) | ||||
|       : pos(reinterpret_cast<byte*>(ptr) + elementSize * constructedElementCount), | ||||
|         elementSize(elementSize), constructedElementCount(constructedElementCount), | ||||
|         destroyElement(destroyElement) {} | ||||
|   KJ_DISALLOW_COPY(ExceptionSafeArrayUtil); | ||||
| 
 | ||||
|   inline ~ExceptionSafeArrayUtil() noexcept(false) { | ||||
|     if (constructedElementCount > 0) destroyAll(); | ||||
|   } | ||||
| 
 | ||||
|   void construct(size_t count, void (*constructElement)(void*)); | ||||
|   // Construct the given number of elements.
 | ||||
| 
 | ||||
|   void destroyAll(); | ||||
|   // Destroy all elements.  Call this immediately before ExceptionSafeArrayUtil goes out-of-scope
 | ||||
|   // to ensure that one element throwing an exception does not prevent the others from being
 | ||||
|   // destroyed.
 | ||||
| 
 | ||||
|   void release() { constructedElementCount = 0; } | ||||
|   // Prevent ExceptionSafeArrayUtil's destructor from destroying the constructed elements.
 | ||||
|   // Call this after you've successfully finished constructing.
 | ||||
| 
 | ||||
| private: | ||||
|   byte* pos; | ||||
|   size_t elementSize; | ||||
|   size_t constructedElementCount; | ||||
|   void (*destroyElement)(void*); | ||||
| }; | ||||
| 
 | ||||
| class DestructorOnlyArrayDisposer: public ArrayDisposer { | ||||
| public: | ||||
|   static const DestructorOnlyArrayDisposer instance; | ||||
| 
 | ||||
|   void disposeImpl(void* firstElement, size_t elementSize, size_t elementCount, | ||||
|                    size_t capacity, void (*destroyElement)(void*)) const override; | ||||
| }; | ||||
| 
 | ||||
| class NullArrayDisposer: public ArrayDisposer { | ||||
|   // An ArrayDisposer that does nothing.  Can be used to construct a fake Arrays that doesn't
 | ||||
|   // actually own its content.
 | ||||
| 
 | ||||
| public: | ||||
|   static const NullArrayDisposer instance; | ||||
| 
 | ||||
|   void disposeImpl(void* firstElement, size_t elementSize, size_t elementCount, | ||||
|                    size_t capacity, void (*destroyElement)(void*)) const override; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Array
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class Array { | ||||
|   // An owned array which will automatically be disposed of (using an ArrayDisposer) in the
 | ||||
|   // destructor.  Can be moved, but not copied.  Much like Own<T>, but for arrays rather than
 | ||||
|   // single objects.
 | ||||
| 
 | ||||
| public: | ||||
|   inline Array(): ptr(nullptr), size_(0), disposer(nullptr) {} | ||||
|   inline Array(decltype(nullptr)): ptr(nullptr), size_(0), disposer(nullptr) {} | ||||
|   inline Array(Array&& other) noexcept | ||||
|       : ptr(other.ptr), size_(other.size_), disposer(other.disposer) { | ||||
|     other.ptr = nullptr; | ||||
|     other.size_ = 0; | ||||
|   } | ||||
|   inline Array(Array<RemoveConstOrDisable<T>>&& other) noexcept | ||||
|       : ptr(other.ptr), size_(other.size_), disposer(other.disposer) { | ||||
|     other.ptr = nullptr; | ||||
|     other.size_ = 0; | ||||
|   } | ||||
|   inline Array(T* firstElement, size_t size, const ArrayDisposer& disposer) | ||||
|       : ptr(firstElement), size_(size), disposer(&disposer) {} | ||||
| 
 | ||||
|   KJ_DISALLOW_COPY(Array); | ||||
|   inline ~Array() noexcept { dispose(); } | ||||
| 
 | ||||
|   inline operator ArrayPtr<T>() { | ||||
|     return ArrayPtr<T>(ptr, size_); | ||||
|   } | ||||
|   inline operator ArrayPtr<const T>() const { | ||||
|     return ArrayPtr<T>(ptr, size_); | ||||
|   } | ||||
|   inline ArrayPtr<T> asPtr() { | ||||
|     return ArrayPtr<T>(ptr, size_); | ||||
|   } | ||||
|   inline ArrayPtr<const T> asPtr() const { | ||||
|     return ArrayPtr<T>(ptr, size_); | ||||
|   } | ||||
| 
 | ||||
|   inline size_t size() const { return size_; } | ||||
|   inline T& operator[](size_t index) const { | ||||
|     KJ_IREQUIRE(index < size_, "Out-of-bounds Array access."); | ||||
|     return ptr[index]; | ||||
|   } | ||||
| 
 | ||||
|   inline const T* begin() const { return ptr; } | ||||
|   inline const T* end() const { return ptr + size_; } | ||||
|   inline const T& front() const { return *ptr; } | ||||
|   inline const T& back() const { return *(ptr + size_ - 1); } | ||||
|   inline T* begin() { return ptr; } | ||||
|   inline T* end() { return ptr + size_; } | ||||
|   inline T& front() { return *ptr; } | ||||
|   inline T& back() { return *(ptr + size_ - 1); } | ||||
| 
 | ||||
|   inline ArrayPtr<T> slice(size_t start, size_t end) { | ||||
|     KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds Array::slice()."); | ||||
|     return ArrayPtr<T>(ptr + start, end - start); | ||||
|   } | ||||
|   inline ArrayPtr<const T> slice(size_t start, size_t end) const { | ||||
|     KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds Array::slice()."); | ||||
|     return ArrayPtr<const T>(ptr + start, end - start); | ||||
|   } | ||||
| 
 | ||||
|   inline ArrayPtr<const byte> asBytes() const { return asPtr().asBytes(); } | ||||
|   inline ArrayPtr<PropagateConst<T, byte>> asBytes() { return asPtr().asBytes(); } | ||||
|   inline ArrayPtr<const char> asChars() const { return asPtr().asChars(); } | ||||
|   inline ArrayPtr<PropagateConst<T, char>> asChars() { return asPtr().asChars(); } | ||||
| 
 | ||||
|   inline Array<PropagateConst<T, byte>> releaseAsBytes() { | ||||
|     // Like asBytes() but transfers ownership.
 | ||||
|     static_assert(sizeof(T) == sizeof(byte), | ||||
|         "releaseAsBytes() only possible on arrays with byte-size elements (e.g. chars)."); | ||||
|     Array<PropagateConst<T, byte>> result( | ||||
|         reinterpret_cast<PropagateConst<T, byte>*>(ptr), size_, *disposer); | ||||
|     ptr = nullptr; | ||||
|     size_ = 0; | ||||
|     return result; | ||||
|   } | ||||
|   inline Array<PropagateConst<T, char>> releaseAsChars() { | ||||
|     // Like asChars() but transfers ownership.
 | ||||
|     static_assert(sizeof(T) == sizeof(PropagateConst<T, char>), | ||||
|         "releaseAsChars() only possible on arrays with char-size elements (e.g. bytes)."); | ||||
|     Array<PropagateConst<T, char>> result( | ||||
|         reinterpret_cast<PropagateConst<T, char>*>(ptr), size_, *disposer); | ||||
|     ptr = nullptr; | ||||
|     size_ = 0; | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
|   inline bool operator==(decltype(nullptr)) const { return size_ == 0; } | ||||
|   inline bool operator!=(decltype(nullptr)) const { return size_ != 0; } | ||||
| 
 | ||||
|   inline Array& operator=(decltype(nullptr)) { | ||||
|     dispose(); | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   inline Array& operator=(Array&& other) { | ||||
|     dispose(); | ||||
|     ptr = other.ptr; | ||||
|     size_ = other.size_; | ||||
|     disposer = other.disposer; | ||||
|     other.ptr = nullptr; | ||||
|     other.size_ = 0; | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   T* ptr; | ||||
|   size_t size_; | ||||
|   const ArrayDisposer* disposer; | ||||
| 
 | ||||
|   inline void dispose() { | ||||
|     // Make sure that if an exception is thrown, we are left with a null ptr, so we won't possibly
 | ||||
|     // dispose again.
 | ||||
|     T* ptrCopy = ptr; | ||||
|     size_t sizeCopy = size_; | ||||
|     if (ptrCopy != nullptr) { | ||||
|       ptr = nullptr; | ||||
|       size_ = 0; | ||||
|       disposer->dispose(ptrCopy, sizeCopy, sizeCopy); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   template <typename U> | ||||
|   friend class Array; | ||||
| }; | ||||
| 
 | ||||
| static_assert(!canMemcpy<Array<char>>(), "canMemcpy<>() is broken"); | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| class HeapArrayDisposer final: public ArrayDisposer { | ||||
| public: | ||||
|   template <typename T> | ||||
|   static T* allocate(size_t count); | ||||
|   template <typename T> | ||||
|   static T* allocateUninitialized(size_t count); | ||||
| 
 | ||||
|   static const HeapArrayDisposer instance; | ||||
| 
 | ||||
| private: | ||||
|   static void* allocateImpl(size_t elementSize, size_t elementCount, size_t capacity, | ||||
|                             void (*constructElement)(void*), void (*destroyElement)(void*)); | ||||
|   // Allocates and constructs the array.  Both function pointers are null if the constructor is
 | ||||
|   // trivial, otherwise destroyElement is null if the constructor doesn't throw.
 | ||||
| 
 | ||||
|   virtual void disposeImpl(void* firstElement, size_t elementSize, size_t elementCount, | ||||
|                            size_t capacity, void (*destroyElement)(void*)) const override; | ||||
| 
 | ||||
|   template <typename T, bool hasTrivialConstructor = __has_trivial_constructor(T), | ||||
|                         bool hasNothrowConstructor = __has_nothrow_constructor(T)> | ||||
|   struct Allocate_; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename T> | ||||
| inline Array<T> heapArray(size_t size) { | ||||
|   // Much like `heap<T>()` from memory.h, allocates a new array on the heap.
 | ||||
| 
 | ||||
|   return Array<T>(_::HeapArrayDisposer::allocate<T>(size), size, | ||||
|                   _::HeapArrayDisposer::instance); | ||||
| } | ||||
| 
 | ||||
| template <typename T> Array<T> heapArray(const T* content, size_t size); | ||||
| template <typename T> Array<T> heapArray(ArrayPtr<T> content); | ||||
| template <typename T> Array<T> heapArray(ArrayPtr<const T> content); | ||||
| template <typename T, typename Iterator> Array<T> heapArray(Iterator begin, Iterator end); | ||||
| template <typename T> Array<T> heapArray(std::initializer_list<T> init); | ||||
| // Allocate a heap array containing a copy of the given content.
 | ||||
| 
 | ||||
| template <typename T, typename Container> | ||||
| Array<T> heapArrayFromIterable(Container&& a) { return heapArray<T>(a.begin(), a.end()); } | ||||
| template <typename T> | ||||
| Array<T> heapArrayFromIterable(Array<T>&& a) { return mv(a); } | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // ArrayBuilder
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class ArrayBuilder { | ||||
|   // Class which lets you build an Array<T> specifying the exact constructor arguments for each
 | ||||
|   // element, rather than starting by default-constructing them.
 | ||||
| 
 | ||||
| public: | ||||
|   ArrayBuilder(): ptr(nullptr), pos(nullptr), endPtr(nullptr) {} | ||||
|   ArrayBuilder(decltype(nullptr)): ptr(nullptr), pos(nullptr), endPtr(nullptr) {} | ||||
|   explicit ArrayBuilder(RemoveConst<T>* firstElement, size_t capacity, | ||||
|                         const ArrayDisposer& disposer) | ||||
|       : ptr(firstElement), pos(firstElement), endPtr(firstElement + capacity), | ||||
|         disposer(&disposer) {} | ||||
|   ArrayBuilder(ArrayBuilder&& other) | ||||
|       : ptr(other.ptr), pos(other.pos), endPtr(other.endPtr), disposer(other.disposer) { | ||||
|     other.ptr = nullptr; | ||||
|     other.pos = nullptr; | ||||
|     other.endPtr = nullptr; | ||||
|   } | ||||
|   KJ_DISALLOW_COPY(ArrayBuilder); | ||||
|   inline ~ArrayBuilder() noexcept(false) { dispose(); } | ||||
| 
 | ||||
|   inline operator ArrayPtr<T>() { | ||||
|     return arrayPtr(ptr, pos); | ||||
|   } | ||||
|   inline operator ArrayPtr<const T>() const { | ||||
|     return arrayPtr(ptr, pos); | ||||
|   } | ||||
|   inline ArrayPtr<T> asPtr() { | ||||
|     return arrayPtr(ptr, pos); | ||||
|   } | ||||
|   inline ArrayPtr<const T> asPtr() const { | ||||
|     return arrayPtr(ptr, pos); | ||||
|   } | ||||
| 
 | ||||
|   inline size_t size() const { return pos - ptr; } | ||||
|   inline size_t capacity() const { return endPtr - ptr; } | ||||
|   inline T& operator[](size_t index) const { | ||||
|     KJ_IREQUIRE(index < implicitCast<size_t>(pos - ptr), "Out-of-bounds Array access."); | ||||
|     return ptr[index]; | ||||
|   } | ||||
| 
 | ||||
|   inline const T* begin() const { return ptr; } | ||||
|   inline const T* end() const { return pos; } | ||||
|   inline const T& front() const { return *ptr; } | ||||
|   inline const T& back() const { return *(pos - 1); } | ||||
|   inline T* begin() { return ptr; } | ||||
|   inline T* end() { return pos; } | ||||
|   inline T& front() { return *ptr; } | ||||
|   inline T& back() { return *(pos - 1); } | ||||
| 
 | ||||
|   ArrayBuilder& operator=(ArrayBuilder&& other) { | ||||
|     dispose(); | ||||
|     ptr = other.ptr; | ||||
|     pos = other.pos; | ||||
|     endPtr = other.endPtr; | ||||
|     disposer = other.disposer; | ||||
|     other.ptr = nullptr; | ||||
|     other.pos = nullptr; | ||||
|     other.endPtr = nullptr; | ||||
|     return *this; | ||||
|   } | ||||
|   ArrayBuilder& operator=(decltype(nullptr)) { | ||||
|     dispose(); | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   template <typename... Params> | ||||
|   T& add(Params&&... params) { | ||||
|     KJ_IREQUIRE(pos < endPtr, "Added too many elements to ArrayBuilder."); | ||||
|     ctor(*pos, kj::fwd<Params>(params)...); | ||||
|     return *pos++; | ||||
|   } | ||||
| 
 | ||||
|   template <typename Container> | ||||
|   void addAll(Container&& container) { | ||||
|     addAll<decltype(container.begin()), !isReference<Container>()>( | ||||
|         container.begin(), container.end()); | ||||
|   } | ||||
| 
 | ||||
|   template <typename Iterator, bool move = false> | ||||
|   void addAll(Iterator start, Iterator end); | ||||
| 
 | ||||
|   void removeLast() { | ||||
|     KJ_IREQUIRE(pos > ptr, "No elements present to remove."); | ||||
|     kj::dtor(*--pos); | ||||
|   } | ||||
| 
 | ||||
|   void truncate(size_t size) { | ||||
|     KJ_IREQUIRE(size <= this->size(), "can't use truncate() to expand"); | ||||
| 
 | ||||
|     T* target = ptr + size; | ||||
|     if (__has_trivial_destructor(T)) { | ||||
|       pos = target; | ||||
|     } else { | ||||
|       while (pos > target) { | ||||
|         kj::dtor(*--pos); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   void resize(size_t size) { | ||||
|     KJ_IREQUIRE(size <= capacity(), "can't resize past capacity"); | ||||
| 
 | ||||
|     T* target = ptr + size; | ||||
|     if (target > pos) { | ||||
|       // expand
 | ||||
|       if (__has_trivial_constructor(T)) { | ||||
|         pos = target; | ||||
|       } else { | ||||
|         while (pos < target) { | ||||
|           kj::ctor(*pos++); | ||||
|         } | ||||
|       } | ||||
|     } else { | ||||
|       // truncate
 | ||||
|       if (__has_trivial_destructor(T)) { | ||||
|         pos = target; | ||||
|       } else { | ||||
|         while (pos > target) { | ||||
|           kj::dtor(*--pos); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   Array<T> finish() { | ||||
|     // We could safely remove this check if we assume that the disposer implementation doesn't
 | ||||
|     // need to know the original capacity, as is thes case with HeapArrayDisposer since it uses
 | ||||
|     // operator new() or if we created a custom disposer for ArrayBuilder which stores the capacity
 | ||||
|     // in a prefix.  But that would make it hard to write cleverer heap allocators, and anyway this
 | ||||
|     // check might catch bugs.  Probably people should use Vector if they want to build arrays
 | ||||
|     // without knowing the final size in advance.
 | ||||
|     KJ_IREQUIRE(pos == endPtr, "ArrayBuilder::finish() called prematurely."); | ||||
|     Array<T> result(reinterpret_cast<T*>(ptr), pos - ptr, *disposer); | ||||
|     ptr = nullptr; | ||||
|     pos = nullptr; | ||||
|     endPtr = nullptr; | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
|   inline bool isFull() const { | ||||
|     return pos == endPtr; | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   T* ptr; | ||||
|   RemoveConst<T>* pos; | ||||
|   T* endPtr; | ||||
|   const ArrayDisposer* disposer; | ||||
| 
 | ||||
|   inline void dispose() { | ||||
|     // Make sure that if an exception is thrown, we are left with a null ptr, so we won't possibly
 | ||||
|     // dispose again.
 | ||||
|     T* ptrCopy = ptr; | ||||
|     T* posCopy = pos; | ||||
|     T* endCopy = endPtr; | ||||
|     if (ptrCopy != nullptr) { | ||||
|       ptr = nullptr; | ||||
|       pos = nullptr; | ||||
|       endPtr = nullptr; | ||||
|       disposer->dispose(ptrCopy, posCopy - ptrCopy, endCopy - ptrCopy); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| inline ArrayBuilder<T> heapArrayBuilder(size_t size) { | ||||
|   // Like `heapArray<T>()` but does not default-construct the elements.  You must construct them
 | ||||
|   // manually by calling `add()`.
 | ||||
| 
 | ||||
|   return ArrayBuilder<T>(_::HeapArrayDisposer::allocateUninitialized<RemoveConst<T>>(size), | ||||
|                          size, _::HeapArrayDisposer::instance); | ||||
| } | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Inline Arrays
 | ||||
| 
 | ||||
| template <typename T, size_t fixedSize> | ||||
| class FixedArray { | ||||
|   // A fixed-width array whose storage is allocated inline rather than on the heap.
 | ||||
| 
 | ||||
| public: | ||||
|   inline size_t size() const { return fixedSize; } | ||||
|   inline T* begin() { return content; } | ||||
|   inline T* end() { return content + fixedSize; } | ||||
|   inline const T* begin() const { return content; } | ||||
|   inline const T* end() const { return content + fixedSize; } | ||||
| 
 | ||||
|   inline operator ArrayPtr<T>() { | ||||
|     return arrayPtr(content, fixedSize); | ||||
|   } | ||||
|   inline operator ArrayPtr<const T>() const { | ||||
|     return arrayPtr(content, fixedSize); | ||||
|   } | ||||
| 
 | ||||
|   inline T& operator[](size_t index) { return content[index]; } | ||||
|   inline const T& operator[](size_t index) const { return content[index]; } | ||||
| 
 | ||||
| private: | ||||
|   T content[fixedSize]; | ||||
| }; | ||||
| 
 | ||||
| template <typename T, size_t fixedSize> | ||||
| class CappedArray { | ||||
|   // Like `FixedArray` but can be dynamically resized as long as the size does not exceed the limit
 | ||||
|   // specified by the template parameter.
 | ||||
|   //
 | ||||
|   // TODO(someday):  Don't construct elements past currentSize?
 | ||||
| 
 | ||||
| public: | ||||
|   inline KJ_CONSTEXPR() CappedArray(): currentSize(fixedSize) {} | ||||
|   inline explicit constexpr CappedArray(size_t s): currentSize(s) {} | ||||
| 
 | ||||
|   inline size_t size() const { return currentSize; } | ||||
|   inline void setSize(size_t s) { KJ_IREQUIRE(s <= fixedSize); currentSize = s; } | ||||
|   inline T* begin() { return content; } | ||||
|   inline T* end() { return content + currentSize; } | ||||
|   inline const T* begin() const { return content; } | ||||
|   inline const T* end() const { return content + currentSize; } | ||||
| 
 | ||||
|   inline operator ArrayPtr<T>() { | ||||
|     return arrayPtr(content, currentSize); | ||||
|   } | ||||
|   inline operator ArrayPtr<const T>() const { | ||||
|     return arrayPtr(content, currentSize); | ||||
|   } | ||||
| 
 | ||||
|   inline T& operator[](size_t index) { return content[index]; } | ||||
|   inline const T& operator[](size_t index) const { return content[index]; } | ||||
| 
 | ||||
| private: | ||||
|   size_t currentSize; | ||||
|   T content[fixedSize]; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // KJ_MAP
 | ||||
| 
 | ||||
| #define KJ_MAP(elementName, array) \ | ||||
|   ::kj::_::Mapper<KJ_DECLTYPE_REF(array)>(array) * \
 | ||||
|   [&](typename ::kj::_::Mapper<KJ_DECLTYPE_REF(array)>::Element elementName) | ||||
| // Applies some function to every element of an array, returning an Array of the results,  with
 | ||||
| // nice syntax.  Example:
 | ||||
| //
 | ||||
| //     StringPtr foo = "abcd";
 | ||||
| //     Array<char> bar = KJ_MAP(c, foo) -> char { return c + 1; };
 | ||||
| //     KJ_ASSERT(str(bar) == "bcde");
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T> | ||||
| struct Mapper { | ||||
|   T array; | ||||
|   Mapper(T&& array): array(kj::fwd<T>(array)) {} | ||||
|   template <typename Func> | ||||
|   auto operator*(Func&& func) -> Array<decltype(func(*array.begin()))> { | ||||
|     auto builder = heapArrayBuilder<decltype(func(*array.begin()))>(array.size()); | ||||
|     for (auto iter = array.begin(); iter != array.end(); ++iter) { | ||||
|       builder.add(func(*iter)); | ||||
|     } | ||||
|     return builder.finish(); | ||||
|   } | ||||
|   typedef decltype(*kj::instance<T>().begin()) Element; | ||||
| }; | ||||
| 
 | ||||
| template <typename T, size_t s> | ||||
| struct Mapper<T(&)[s]> { | ||||
|   T* array; | ||||
|   Mapper(T* array): array(array) {} | ||||
|   template <typename Func> | ||||
|   auto operator*(Func&& func) -> Array<decltype(func(*array))> { | ||||
|     auto builder = heapArrayBuilder<decltype(func(*array))>(s); | ||||
|     for (size_t i = 0; i < s; i++) { | ||||
|       builder.add(func(array[i])); | ||||
|     } | ||||
|     return builder.finish(); | ||||
|   } | ||||
|   typedef decltype(*array)& Element; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Inline implementation details
 | ||||
| 
 | ||||
| template <typename T> | ||||
| struct ArrayDisposer::Dispose_<T, true> { | ||||
|   static void dispose(T* firstElement, size_t elementCount, size_t capacity, | ||||
|                       const ArrayDisposer& disposer) { | ||||
|     disposer.disposeImpl(const_cast<RemoveConst<T>*>(firstElement), | ||||
|                          sizeof(T), elementCount, capacity, nullptr); | ||||
|   } | ||||
| }; | ||||
| template <typename T> | ||||
| struct ArrayDisposer::Dispose_<T, false> { | ||||
|   static void destruct(void* ptr) { | ||||
|     kj::dtor(*reinterpret_cast<T*>(ptr)); | ||||
|   } | ||||
| 
 | ||||
|   static void dispose(T* firstElement, size_t elementCount, size_t capacity, | ||||
|                       const ArrayDisposer& disposer) { | ||||
|     disposer.disposeImpl(firstElement, sizeof(T), elementCount, capacity, &destruct); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| void ArrayDisposer::dispose(T* firstElement, size_t elementCount, size_t capacity) const { | ||||
|   Dispose_<T>::dispose(firstElement, elementCount, capacity, *this); | ||||
| } | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T> | ||||
| struct HeapArrayDisposer::Allocate_<T, true, true> { | ||||
|   static T* allocate(size_t elementCount, size_t capacity) { | ||||
|     return reinterpret_cast<T*>(allocateImpl( | ||||
|         sizeof(T), elementCount, capacity, nullptr, nullptr)); | ||||
|   } | ||||
| }; | ||||
| template <typename T> | ||||
| struct HeapArrayDisposer::Allocate_<T, false, true> { | ||||
|   static void construct(void* ptr) { | ||||
|     kj::ctor(*reinterpret_cast<T*>(ptr)); | ||||
|   } | ||||
|   static T* allocate(size_t elementCount, size_t capacity) { | ||||
|     return reinterpret_cast<T*>(allocateImpl( | ||||
|         sizeof(T), elementCount, capacity, &construct, nullptr)); | ||||
|   } | ||||
| }; | ||||
| template <typename T> | ||||
| struct HeapArrayDisposer::Allocate_<T, false, false> { | ||||
|   static void construct(void* ptr) { | ||||
|     kj::ctor(*reinterpret_cast<T*>(ptr)); | ||||
|   } | ||||
|   static void destruct(void* ptr) { | ||||
|     kj::dtor(*reinterpret_cast<T*>(ptr)); | ||||
|   } | ||||
|   static T* allocate(size_t elementCount, size_t capacity) { | ||||
|     return reinterpret_cast<T*>(allocateImpl( | ||||
|         sizeof(T), elementCount, capacity, &construct, &destruct)); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| T* HeapArrayDisposer::allocate(size_t count) { | ||||
|   return Allocate_<T>::allocate(count, count); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| T* HeapArrayDisposer::allocateUninitialized(size_t count) { | ||||
|   return Allocate_<T, true, true>::allocate(0, count); | ||||
| } | ||||
| 
 | ||||
| template <typename Element, typename Iterator, bool move, bool = canMemcpy<Element>()> | ||||
| struct CopyConstructArray_; | ||||
| 
 | ||||
| template <typename T, bool move> | ||||
| struct CopyConstructArray_<T, T*, move, true> { | ||||
|   static inline T* apply(T* __restrict__ pos, T* start, T* end) { | ||||
|     memcpy(pos, start, reinterpret_cast<byte*>(end) - reinterpret_cast<byte*>(start)); | ||||
|     return pos + (end - start); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct CopyConstructArray_<T, const T*, false, true> { | ||||
|   static inline T* apply(T* __restrict__ pos, const T* start, const T* end) { | ||||
|     memcpy(pos, start, reinterpret_cast<const byte*>(end) - reinterpret_cast<const byte*>(start)); | ||||
|     return pos + (end - start); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T, typename Iterator, bool move> | ||||
| struct CopyConstructArray_<T, Iterator, move, true> { | ||||
|   static inline T* apply(T* __restrict__ pos, Iterator start, Iterator end) { | ||||
|     // Since both the copy constructor and assignment operator are trivial, we know that assignment
 | ||||
|     // is equivalent to copy-constructing.  So we can make this case somewhat easier for the
 | ||||
|     // compiler to optimize.
 | ||||
|     while (start != end) { | ||||
|       *pos++ = *start++; | ||||
|     } | ||||
|     return pos; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T, typename Iterator> | ||||
| struct CopyConstructArray_<T, Iterator, false, false> { | ||||
|   struct ExceptionGuard { | ||||
|     T* start; | ||||
|     T* pos; | ||||
|     inline explicit ExceptionGuard(T* pos): start(pos), pos(pos) {} | ||||
|     ~ExceptionGuard() noexcept(false) { | ||||
|       while (pos > start) { | ||||
|         dtor(*--pos); | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   static T* apply(T* __restrict__ pos, Iterator start, Iterator end) { | ||||
|     // Verify that T can be *implicitly* constructed from the source values.
 | ||||
|     if (false) implicitCast<T>(*start); | ||||
| 
 | ||||
|     if (noexcept(T(*start))) { | ||||
|       while (start != end) { | ||||
|         ctor(*pos++, *start++); | ||||
|       } | ||||
|       return pos; | ||||
|     } else { | ||||
|       // Crap.  This is complicated.
 | ||||
|       ExceptionGuard guard(pos); | ||||
|       while (start != end) { | ||||
|         ctor(*guard.pos, *start++); | ||||
|         ++guard.pos; | ||||
|       } | ||||
|       guard.start = guard.pos; | ||||
|       return guard.pos; | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T, typename Iterator> | ||||
| struct CopyConstructArray_<T, Iterator, true, false> { | ||||
|   // Actually move-construct.
 | ||||
| 
 | ||||
|   struct ExceptionGuard { | ||||
|     T* start; | ||||
|     T* pos; | ||||
|     inline explicit ExceptionGuard(T* pos): start(pos), pos(pos) {} | ||||
|     ~ExceptionGuard() noexcept(false) { | ||||
|       while (pos > start) { | ||||
|         dtor(*--pos); | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   static T* apply(T* __restrict__ pos, Iterator start, Iterator end) { | ||||
|     // Verify that T can be *implicitly* constructed from the source values.
 | ||||
|     if (false) implicitCast<T>(kj::mv(*start)); | ||||
| 
 | ||||
|     if (noexcept(T(kj::mv(*start)))) { | ||||
|       while (start != end) { | ||||
|         ctor(*pos++, kj::mv(*start++)); | ||||
|       } | ||||
|       return pos; | ||||
|     } else { | ||||
|       // Crap.  This is complicated.
 | ||||
|       ExceptionGuard guard(pos); | ||||
|       while (start != end) { | ||||
|         ctor(*guard.pos, kj::mv(*start++)); | ||||
|         ++guard.pos; | ||||
|       } | ||||
|       guard.start = guard.pos; | ||||
|       return guard.pos; | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename T> | ||||
| template <typename Iterator, bool move> | ||||
| void ArrayBuilder<T>::addAll(Iterator start, Iterator end) { | ||||
|   pos = _::CopyConstructArray_<RemoveConst<T>, Decay<Iterator>, move>::apply(pos, start, end); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| Array<T> heapArray(const T* content, size_t size) { | ||||
|   ArrayBuilder<T> builder = heapArrayBuilder<T>(size); | ||||
|   builder.addAll(content, content + size); | ||||
|   return builder.finish(); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| Array<T> heapArray(T* content, size_t size) { | ||||
|   ArrayBuilder<T> builder = heapArrayBuilder<T>(size); | ||||
|   builder.addAll(content, content + size); | ||||
|   return builder.finish(); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| Array<T> heapArray(ArrayPtr<T> content) { | ||||
|   ArrayBuilder<T> builder = heapArrayBuilder<T>(content.size()); | ||||
|   builder.addAll(content); | ||||
|   return builder.finish(); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| Array<T> heapArray(ArrayPtr<const T> content) { | ||||
|   ArrayBuilder<T> builder = heapArrayBuilder<T>(content.size()); | ||||
|   builder.addAll(content); | ||||
|   return builder.finish(); | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename Iterator> Array<T> | ||||
| heapArray(Iterator begin, Iterator end) { | ||||
|   ArrayBuilder<T> builder = heapArrayBuilder<T>(end - begin); | ||||
|   builder.addAll(begin, end); | ||||
|   return builder.finish(); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline Array<T> heapArray(std::initializer_list<T> init) { | ||||
|   return heapArray<T>(init.begin(), init.end()); | ||||
| } | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_ARRAY_H_
 | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -0,0 +1,561 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_ASYNC_IO_H_ | ||||
| #define KJ_ASYNC_IO_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "async.h" | ||||
| #include "function.h" | ||||
| #include "thread.h" | ||||
| #include "time.h" | ||||
| 
 | ||||
| struct sockaddr; | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| #if _WIN32 | ||||
| class Win32EventPort; | ||||
| #else | ||||
| class UnixEventPort; | ||||
| #endif | ||||
| 
 | ||||
| class NetworkAddress; | ||||
| class AsyncOutputStream; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Streaming I/O
 | ||||
| 
 | ||||
| class AsyncInputStream { | ||||
|   // Asynchronous equivalent of InputStream (from io.h).
 | ||||
| 
 | ||||
| public: | ||||
|   virtual Promise<size_t> read(void* buffer, size_t minBytes, size_t maxBytes); | ||||
|   virtual Promise<size_t> tryRead(void* buffer, size_t minBytes, size_t maxBytes) = 0; | ||||
| 
 | ||||
|   Promise<void> read(void* buffer, size_t bytes); | ||||
| 
 | ||||
|   virtual Maybe<uint64_t> tryGetLength(); | ||||
|   // Get the remaining number of bytes that will be produced by this stream, if known.
 | ||||
|   //
 | ||||
|   // This is used e.g. to fill in the Content-Length header of an HTTP message. If unknown, the
 | ||||
|   // HTTP implementation may need to fall back to Transfer-Encoding: chunked.
 | ||||
|   //
 | ||||
|   // The default implementation always returns null.
 | ||||
| 
 | ||||
|   virtual Promise<uint64_t> pumpTo( | ||||
|       AsyncOutputStream& output, uint64_t amount = kj::maxValue); | ||||
|   // Read `amount` bytes from this stream (or to EOF) and write them to `output`, returning the
 | ||||
|   // total bytes actually pumped (which is only less than `amount` if EOF was reached).
 | ||||
|   //
 | ||||
|   // Override this if your stream type knows how to pump itself to certain kinds of output
 | ||||
|   // streams more efficiently than via the naive approach. You can use
 | ||||
|   // kj::dynamicDowncastIfAvailable() to test for stream types you recognize, and if none match,
 | ||||
|   // delegate to the default implementation.
 | ||||
|   //
 | ||||
|   // The default implementation first tries calling output.tryPumpFrom(), but if that fails, it
 | ||||
|   // performs a naive pump by allocating a buffer and reading to it / writing from it in a loop.
 | ||||
| 
 | ||||
|   Promise<Array<byte>> readAllBytes(); | ||||
|   Promise<String> readAllText(); | ||||
|   // Read until EOF and return as one big byte array or string.
 | ||||
| }; | ||||
| 
 | ||||
| class AsyncOutputStream { | ||||
|   // Asynchronous equivalent of OutputStream (from io.h).
 | ||||
| 
 | ||||
| public: | ||||
|   virtual Promise<void> write(const void* buffer, size_t size) KJ_WARN_UNUSED_RESULT = 0; | ||||
|   virtual Promise<void> write(ArrayPtr<const ArrayPtr<const byte>> pieces) | ||||
|       KJ_WARN_UNUSED_RESULT = 0; | ||||
| 
 | ||||
|   virtual Maybe<Promise<uint64_t>> tryPumpFrom( | ||||
|       AsyncInputStream& input, uint64_t amount = kj::maxValue); | ||||
|   // Implements double-dispatch for AsyncInputStream::pumpTo().
 | ||||
|   //
 | ||||
|   // This method should only be called from within an implementation of pumpTo().
 | ||||
|   //
 | ||||
|   // This method examines the type of `input` to find optimized ways to pump data from it to this
 | ||||
|   // output stream. If it finds one, it performs the pump. Otherwise, it returns null.
 | ||||
|   //
 | ||||
|   // The default implementation always returns null.
 | ||||
| }; | ||||
| 
 | ||||
| class AsyncIoStream: public AsyncInputStream, public AsyncOutputStream { | ||||
|   // A combination input and output stream.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual void shutdownWrite() = 0; | ||||
|   // Cleanly shut down just the write end of the stream, while keeping the read end open.
 | ||||
| 
 | ||||
|   virtual void abortRead() {} | ||||
|   // Similar to shutdownWrite, but this will shut down the read end of the stream, and should only
 | ||||
|   // be called when an error has occurred.
 | ||||
| 
 | ||||
|   virtual void getsockopt(int level, int option, void* value, uint* length); | ||||
|   virtual void setsockopt(int level, int option, const void* value, uint length); | ||||
|   // Corresponds to getsockopt() and setsockopt() syscalls. Will throw an "unimplemented" exception
 | ||||
|   // if the stream is not a socket or the option is not appropriate for the socket type. The
 | ||||
|   // default implementations always throw "unimplemented".
 | ||||
| 
 | ||||
|   virtual void getsockname(struct sockaddr* addr, uint* length); | ||||
|   virtual void getpeername(struct sockaddr* addr, uint* length); | ||||
|   // Corresponds to getsockname() and getpeername() syscalls. Will throw an "unimplemented"
 | ||||
|   // exception if the stream is not a socket. The default implementations always throw
 | ||||
|   // "unimplemented".
 | ||||
|   //
 | ||||
|   // Note that we don't provide methods that return NetworkAddress because it usually wouldn't
 | ||||
|   // be useful. You can't connect() to or listen() on these addresses, obviously, because they are
 | ||||
|   // ephemeral addresses for a single connection.
 | ||||
| }; | ||||
| 
 | ||||
| struct OneWayPipe { | ||||
|   // A data pipe with an input end and an output end.  (Typically backed by pipe() system call.)
 | ||||
| 
 | ||||
|   Own<AsyncInputStream> in; | ||||
|   Own<AsyncOutputStream> out; | ||||
| }; | ||||
| 
 | ||||
| struct TwoWayPipe { | ||||
|   // A data pipe that supports sending in both directions.  Each end's output sends data to the
 | ||||
|   // other end's input.  (Typically backed by socketpair() system call.)
 | ||||
| 
 | ||||
|   Own<AsyncIoStream> ends[2]; | ||||
| }; | ||||
| 
 | ||||
| class ConnectionReceiver { | ||||
|   // Represents a server socket listening on a port.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual Promise<Own<AsyncIoStream>> accept() = 0; | ||||
|   // Accept the next incoming connection.
 | ||||
| 
 | ||||
|   virtual uint getPort() = 0; | ||||
|   // Gets the port number, if applicable (i.e. if listening on IP).  This is useful if you didn't
 | ||||
|   // specify a port when constructing the NetworkAddress -- one will have been assigned
 | ||||
|   // automatically.
 | ||||
| 
 | ||||
|   virtual void getsockopt(int level, int option, void* value, uint* length); | ||||
|   virtual void setsockopt(int level, int option, const void* value, uint length); | ||||
|   // Same as the methods of AsyncIoStream.
 | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Datagram I/O
 | ||||
| 
 | ||||
| class AncillaryMessage { | ||||
|   // Represents an ancillary message (aka control message) received using the recvmsg() system
 | ||||
|   // call (or equivalent). Most apps will not use this.
 | ||||
| 
 | ||||
| public: | ||||
|   inline AncillaryMessage(int level, int type, ArrayPtr<const byte> data); | ||||
|   AncillaryMessage() = default; | ||||
| 
 | ||||
|   inline int getLevel() const; | ||||
|   // Originating protocol / socket level.
 | ||||
| 
 | ||||
|   inline int getType() const; | ||||
|   // Protocol-specific message type.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   inline Maybe<const T&> as(); | ||||
|   // Interpret the ancillary message as the given struct type. Most ancillary messages are some
 | ||||
|   // sort of struct, so this is a convenient way to access it. Returns nullptr if the message
 | ||||
|   // is smaller than the struct -- this can happen if the message was truncated due to
 | ||||
|   // insufficient ancillary buffer space.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   inline ArrayPtr<const T> asArray(); | ||||
|   // Interpret the ancillary message as an array of items. If the message size does not evenly
 | ||||
|   // divide into elements of type T, the remainder is discarded -- this can happen if the message
 | ||||
|   // was truncated due to insufficient ancillary buffer space.
 | ||||
| 
 | ||||
| private: | ||||
|   int level; | ||||
|   int type; | ||||
|   ArrayPtr<const byte> data; | ||||
|   // Message data. In most cases you should use `as()` or `asArray()`.
 | ||||
| }; | ||||
| 
 | ||||
| class DatagramReceiver { | ||||
|   // Class encapsulating the recvmsg() system call. You must specify the DatagramReceiver's
 | ||||
|   // capacity in advance; if a received packet is larger than the capacity, it will be truncated.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual Promise<void> receive() = 0; | ||||
|   // Receive a new message, overwriting this object's content.
 | ||||
|   //
 | ||||
|   // receive() may reuse the same buffers for content and ancillary data with each call.
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   struct MaybeTruncated { | ||||
|     T value; | ||||
| 
 | ||||
|     bool isTruncated; | ||||
|     // True if the Receiver's capacity was insufficient to receive the value and therefore the
 | ||||
|     // value is truncated.
 | ||||
|   }; | ||||
| 
 | ||||
|   virtual MaybeTruncated<ArrayPtr<const byte>> getContent() = 0; | ||||
|   // Get the content of the datagram.
 | ||||
| 
 | ||||
|   virtual MaybeTruncated<ArrayPtr<const AncillaryMessage>> getAncillary() = 0; | ||||
|   // Ancilarry messages received with the datagram. See the recvmsg() system call and the cmsghdr
 | ||||
|   // struct. Most apps don't need this.
 | ||||
|   //
 | ||||
|   // If the returned value is truncated, then the last message in the array may itself be
 | ||||
|   // truncated, meaning its as<T>() method will return nullptr or its asArray<T>() method will
 | ||||
|   // return fewer elements than expected. Truncation can also mean that additional messages were
 | ||||
|   // available but discarded.
 | ||||
| 
 | ||||
|   virtual NetworkAddress& getSource() = 0; | ||||
|   // Get the datagram sender's address.
 | ||||
| 
 | ||||
|   struct Capacity { | ||||
|     size_t content = 8192; | ||||
|     // How much space to allocate for the datagram content. If a datagram is received that is
 | ||||
|     // larger than this, it will be truncated, with no way to recover the tail.
 | ||||
| 
 | ||||
|     size_t ancillary = 0; | ||||
|     // How much space to allocate for ancillary messages. As with content, if the ancillary data
 | ||||
|     // is larger than this, it will be truncated.
 | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| class DatagramPort { | ||||
| public: | ||||
|   virtual Promise<size_t> send(const void* buffer, size_t size, NetworkAddress& destination) = 0; | ||||
|   virtual Promise<size_t> send(ArrayPtr<const ArrayPtr<const byte>> pieces, | ||||
|                                NetworkAddress& destination) = 0; | ||||
| 
 | ||||
|   virtual Own<DatagramReceiver> makeReceiver( | ||||
|       DatagramReceiver::Capacity capacity = DatagramReceiver::Capacity()) = 0; | ||||
|   // Create a new `Receiver` that can be used to receive datagrams. `capacity` specifies how much
 | ||||
|   // space to allocate for the received message. The `DatagramPort` must outlive the `Receiver`.
 | ||||
| 
 | ||||
|   virtual uint getPort() = 0; | ||||
|   // Gets the port number, if applicable (i.e. if listening on IP).  This is useful if you didn't
 | ||||
|   // specify a port when constructing the NetworkAddress -- one will have been assigned
 | ||||
|   // automatically.
 | ||||
| 
 | ||||
|   virtual void getsockopt(int level, int option, void* value, uint* length); | ||||
|   virtual void setsockopt(int level, int option, const void* value, uint length); | ||||
|   // Same as the methods of AsyncIoStream.
 | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Networks
 | ||||
| 
 | ||||
| class NetworkAddress { | ||||
|   // Represents a remote address to which the application can connect.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual Promise<Own<AsyncIoStream>> connect() = 0; | ||||
|   // Make a new connection to this address.
 | ||||
|   //
 | ||||
|   // The address must not be a wildcard ("*").  If it is an IP address, it must have a port number.
 | ||||
| 
 | ||||
|   virtual Own<ConnectionReceiver> listen() = 0; | ||||
|   // Listen for incoming connections on this address.
 | ||||
|   //
 | ||||
|   // The address must be local.
 | ||||
| 
 | ||||
|   virtual Own<DatagramPort> bindDatagramPort(); | ||||
|   // Open this address as a datagram (e.g. UDP) port.
 | ||||
|   //
 | ||||
|   // The address must be local.
 | ||||
| 
 | ||||
|   virtual Own<NetworkAddress> clone() = 0; | ||||
|   // Returns an equivalent copy of this NetworkAddress.
 | ||||
| 
 | ||||
|   virtual String toString() = 0; | ||||
|   // Produce a human-readable string which hopefully can be passed to Network::parseAddress()
 | ||||
|   // to reproduce this address, although whether or not that works of course depends on the Network
 | ||||
|   // implementation.  This should be called only to display the address to human users, who will
 | ||||
|   // hopefully know what they are able to do with it.
 | ||||
| }; | ||||
| 
 | ||||
| class Network { | ||||
|   // Factory for NetworkAddress instances, representing the network services offered by the
 | ||||
|   // operating system.
 | ||||
|   //
 | ||||
|   // This interface typically represents broad authority, and well-designed code should limit its
 | ||||
|   // use to high-level startup code and user interaction.  Low-level APIs should accept
 | ||||
|   // NetworkAddress instances directly and work from there, if at all possible.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual Promise<Own<NetworkAddress>> parseAddress(StringPtr addr, uint portHint = 0) = 0; | ||||
|   // Construct a network address from a user-provided string.  The format of the address
 | ||||
|   // strings is not specified at the API level, and application code should make no assumptions
 | ||||
|   // about them.  These strings should always be provided by humans, and said humans will know
 | ||||
|   // what format to use in their particular context.
 | ||||
|   //
 | ||||
|   // `portHint`, if provided, specifies the "standard" IP port number for the application-level
 | ||||
|   // service in play.  If the address turns out to be an IP address (v4 or v6), and it lacks a
 | ||||
|   // port number, this port will be used.  If `addr` lacks a port number *and* `portHint` is
 | ||||
|   // omitted, then the returned address will only support listen() and bindDatagramPort()
 | ||||
|   // (not connect()), and an unused port will be chosen each time one of those methods is called.
 | ||||
| 
 | ||||
|   virtual Own<NetworkAddress> getSockaddr(const void* sockaddr, uint len) = 0; | ||||
|   // Construct a network address from a legacy struct sockaddr.
 | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // I/O Provider
 | ||||
| 
 | ||||
| class AsyncIoProvider { | ||||
|   // Class which constructs asynchronous wrappers around the operating system's I/O facilities.
 | ||||
|   //
 | ||||
|   // Generally, the implementation of this interface must integrate closely with a particular
 | ||||
|   // `EventLoop` implementation.  Typically, the EventLoop implementation itself will provide
 | ||||
|   // an AsyncIoProvider.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual OneWayPipe newOneWayPipe() = 0; | ||||
|   // Creates an input/output stream pair representing the ends of a one-way pipe (e.g. created with
 | ||||
|   // the pipe(2) system call).
 | ||||
| 
 | ||||
|   virtual TwoWayPipe newTwoWayPipe() = 0; | ||||
|   // Creates two AsyncIoStreams representing the two ends of a two-way pipe (e.g. created with
 | ||||
|   // socketpair(2) system call).  Data written to one end can be read from the other.
 | ||||
| 
 | ||||
|   virtual Network& getNetwork() = 0; | ||||
|   // Creates a new `Network` instance representing the networks exposed by the operating system.
 | ||||
|   //
 | ||||
|   // DO NOT CALL THIS except at the highest levels of your code, ideally in the main() function.  If
 | ||||
|   // you call this from low-level code, then you are preventing higher-level code from injecting an
 | ||||
|   // alternative implementation.  Instead, if your code needs to use network functionality, it
 | ||||
|   // should ask for a `Network` as a constructor or method parameter, so that higher-level code can
 | ||||
|   // chose what implementation to use.  The system network is essentially a singleton.  See:
 | ||||
|   //     http://www.object-oriented-security.org/lets-argue/singletons
 | ||||
|   //
 | ||||
|   // Code that uses the system network should not make any assumptions about what kinds of
 | ||||
|   // addresses it will parse, as this could differ across platforms.  String addresses should come
 | ||||
|   // strictly from the user, who will know how to write them correctly for their system.
 | ||||
|   //
 | ||||
|   // With that said, KJ currently supports the following string address formats:
 | ||||
|   // - IPv4: "1.2.3.4", "1.2.3.4:80"
 | ||||
|   // - IPv6: "1234:5678::abcd", "[1234:5678::abcd]:80"
 | ||||
|   // - Local IP wildcard (covers both v4 and v6):  "*", "*:80"
 | ||||
|   // - Symbolic names:  "example.com", "example.com:80", "example.com:http", "1.2.3.4:http"
 | ||||
|   // - Unix domain: "unix:/path/to/socket"
 | ||||
| 
 | ||||
|   struct PipeThread { | ||||
|     // A combination of a thread and a two-way pipe that communicates with that thread.
 | ||||
|     //
 | ||||
|     // The fields are intentionally ordered so that the pipe will be destroyed (and therefore
 | ||||
|     // disconnected) before the thread is destroyed (and therefore joined).  Thus if the thread
 | ||||
|     // arranges to exit when it detects disconnect, destruction should be clean.
 | ||||
| 
 | ||||
|     Own<Thread> thread; | ||||
|     Own<AsyncIoStream> pipe; | ||||
|   }; | ||||
| 
 | ||||
|   virtual PipeThread newPipeThread( | ||||
|       Function<void(AsyncIoProvider&, AsyncIoStream&, WaitScope&)> startFunc) = 0; | ||||
|   // Create a new thread and set up a two-way pipe (socketpair) which can be used to communicate
 | ||||
|   // with it.  One end of the pipe is passed to the thread's start function and the other end of
 | ||||
|   // the pipe is returned.  The new thread also gets its own `AsyncIoProvider` instance and will
 | ||||
|   // already have an active `EventLoop` when `startFunc` is called.
 | ||||
|   //
 | ||||
|   // TODO(someday):  I'm not entirely comfortable with this interface.  It seems to be doing too
 | ||||
|   //   much at once but I'm not sure how to cleanly break it down.
 | ||||
| 
 | ||||
|   virtual Timer& getTimer() = 0; | ||||
|   // Returns a `Timer` based on real time.  Time does not pass while event handlers are running --
 | ||||
|   // it only updates when the event loop polls for system events.  This means that calling `now()`
 | ||||
|   // on this timer does not require a system call.
 | ||||
|   //
 | ||||
|   // This timer is not affected by changes to the system date.  It is unspecified whether the timer
 | ||||
|   // continues to count while the system is suspended.
 | ||||
| }; | ||||
| 
 | ||||
| class LowLevelAsyncIoProvider { | ||||
|   // Similar to `AsyncIoProvider`, but represents a lower-level interface that may differ on
 | ||||
|   // different operating systems.  You should prefer to use `AsyncIoProvider` over this interface
 | ||||
|   // whenever possible, as `AsyncIoProvider` is portable and friendlier to dependency-injection.
 | ||||
|   //
 | ||||
|   // On Unix, this interface can be used to import native file descriptors into the async framework.
 | ||||
|   // Different implementations of this interface might work on top of different event handling
 | ||||
|   // primitives, such as poll vs. epoll vs. kqueue vs. some higher-level event library.
 | ||||
|   //
 | ||||
|   // On Windows, this interface can be used to import native HANDLEs into the async framework.
 | ||||
|   // Different implementations of this interface might work on top of different event handling
 | ||||
|   // primitives, such as I/O completion ports vs. completion routines.
 | ||||
|   //
 | ||||
|   // TODO(port):  Actually implement Windows support.
 | ||||
| 
 | ||||
| public: | ||||
|   // ---------------------------------------------------------------------------
 | ||||
|   // Unix-specific stuff
 | ||||
| 
 | ||||
|   enum Flags { | ||||
|     // Flags controlling how to wrap a file descriptor.
 | ||||
| 
 | ||||
|     TAKE_OWNERSHIP = 1 << 0, | ||||
|     // The returned object should own the file descriptor, automatically closing it when destroyed.
 | ||||
|     // The close-on-exec flag will be set on the descriptor if it is not already.
 | ||||
|     //
 | ||||
|     // If this flag is not used, then the file descriptor is not automatically closed and the
 | ||||
|     // close-on-exec flag is not modified.
 | ||||
| 
 | ||||
| #if !_WIN32 | ||||
|     ALREADY_CLOEXEC = 1 << 1, | ||||
|     // Indicates that the close-on-exec flag is known already to be set, so need not be set again.
 | ||||
|     // Only relevant when combined with TAKE_OWNERSHIP.
 | ||||
|     //
 | ||||
|     // On Linux, all system calls which yield new file descriptors have flags or variants which
 | ||||
|     // set the close-on-exec flag immediately.  Unfortunately, other OS's do not.
 | ||||
| 
 | ||||
|     ALREADY_NONBLOCK = 1 << 2 | ||||
|     // Indicates that the file descriptor is known already to be in non-blocking mode, so the flag
 | ||||
|     // need not be set again.  Otherwise, all wrap*Fd() methods will enable non-blocking mode
 | ||||
|     // automatically.
 | ||||
|     //
 | ||||
|     // On Linux, all system calls which yield new file descriptors have flags or variants which
 | ||||
|     // enable non-blocking mode immediately.  Unfortunately, other OS's do not.
 | ||||
| #endif | ||||
|   }; | ||||
| 
 | ||||
| #if _WIN32 | ||||
|   typedef uintptr_t Fd; | ||||
|   // On Windows, the `fd` parameter to each of these methods must be a SOCKET, and must have the
 | ||||
|   // flag WSA_FLAG_OVERLAPPED (which socket() uses by default, but WSASocket() wants you to specify
 | ||||
|   // explicitly).
 | ||||
| #else | ||||
|   typedef int Fd; | ||||
|   // On Unix, any arbitrary file descriptor is supported.
 | ||||
| #endif | ||||
| 
 | ||||
|   virtual Own<AsyncInputStream> wrapInputFd(Fd fd, uint flags = 0) = 0; | ||||
|   // Create an AsyncInputStream wrapping a file descriptor.
 | ||||
|   //
 | ||||
|   // `flags` is a bitwise-OR of the values of the `Flags` enum.
 | ||||
| 
 | ||||
|   virtual Own<AsyncOutputStream> wrapOutputFd(Fd fd, uint flags = 0) = 0; | ||||
|   // Create an AsyncOutputStream wrapping a file descriptor.
 | ||||
|   //
 | ||||
|   // `flags` is a bitwise-OR of the values of the `Flags` enum.
 | ||||
| 
 | ||||
|   virtual Own<AsyncIoStream> wrapSocketFd(Fd fd, uint flags = 0) = 0; | ||||
|   // Create an AsyncIoStream wrapping a socket file descriptor.
 | ||||
|   //
 | ||||
|   // `flags` is a bitwise-OR of the values of the `Flags` enum.
 | ||||
| 
 | ||||
|   virtual Promise<Own<AsyncIoStream>> wrapConnectingSocketFd( | ||||
|       Fd fd, const struct sockaddr* addr, uint addrlen, uint flags = 0) = 0; | ||||
|   // Create an AsyncIoStream wrapping a socket and initiate a connection to the given address.
 | ||||
|   // The returned promise does not resolve until connection has completed.
 | ||||
|   //
 | ||||
|   // `flags` is a bitwise-OR of the values of the `Flags` enum.
 | ||||
| 
 | ||||
|   virtual Own<ConnectionReceiver> wrapListenSocketFd(Fd fd, uint flags = 0) = 0; | ||||
|   // Create an AsyncIoStream wrapping a listen socket file descriptor.  This socket should already
 | ||||
|   // have had `bind()` and `listen()` called on it, so it's ready for `accept()`.
 | ||||
|   //
 | ||||
|   // `flags` is a bitwise-OR of the values of the `Flags` enum.
 | ||||
| 
 | ||||
|   virtual Own<DatagramPort> wrapDatagramSocketFd(Fd fd, uint flags = 0); | ||||
| 
 | ||||
|   virtual Timer& getTimer() = 0; | ||||
|   // Returns a `Timer` based on real time.  Time does not pass while event handlers are running --
 | ||||
|   // it only updates when the event loop polls for system events.  This means that calling `now()`
 | ||||
|   // on this timer does not require a system call.
 | ||||
|   //
 | ||||
|   // This timer is not affected by changes to the system date.  It is unspecified whether the timer
 | ||||
|   // continues to count while the system is suspended.
 | ||||
| }; | ||||
| 
 | ||||
| Own<AsyncIoProvider> newAsyncIoProvider(LowLevelAsyncIoProvider& lowLevel); | ||||
| // Make a new AsyncIoProvider wrapping a `LowLevelAsyncIoProvider`.
 | ||||
| 
 | ||||
| struct AsyncIoContext { | ||||
|   Own<LowLevelAsyncIoProvider> lowLevelProvider; | ||||
|   Own<AsyncIoProvider> provider; | ||||
|   WaitScope& waitScope; | ||||
| 
 | ||||
| #if _WIN32 | ||||
|   Win32EventPort& win32EventPort; | ||||
| #else | ||||
|   UnixEventPort& unixEventPort; | ||||
|   // TEMPORARY: Direct access to underlying UnixEventPort, mainly for waiting on signals. This
 | ||||
|   //   field will go away at some point when we have a chance to improve these interfaces.
 | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| AsyncIoContext setupAsyncIo(); | ||||
| // Convenience method which sets up the current thread with everything it needs to do async I/O.
 | ||||
| // The returned objects contain an `EventLoop` which is wrapping an appropriate `EventPort` for
 | ||||
| // doing I/O on the host system, so everything is ready for the thread to start making async calls
 | ||||
| // and waiting on promises.
 | ||||
| //
 | ||||
| // You would typically call this in your main() loop or in the start function of a thread.
 | ||||
| // Example:
 | ||||
| //
 | ||||
| //     int main() {
 | ||||
| //       auto ioContext = kj::setupAsyncIo();
 | ||||
| //
 | ||||
| //       // Now we can call an async function.
 | ||||
| //       Promise<String> textPromise = getHttp(*ioContext.provider, "http://example.com");
 | ||||
| //
 | ||||
| //       // And we can wait for the promise to complete.  Note that you can only use `wait()`
 | ||||
| //       // from the top level, not from inside a promise callback.
 | ||||
| //       String text = textPromise.wait(ioContext.waitScope);
 | ||||
| //       print(text);
 | ||||
| //       return 0;
 | ||||
| //     }
 | ||||
| //
 | ||||
| // WARNING: An AsyncIoContext can only be used in the thread and process that created it. In
 | ||||
| //   particular, note that after a fork(), an AsyncIoContext created in the parent process will
 | ||||
| //   not work correctly in the child, even if the parent ceases to use its copy. In particular
 | ||||
| //   note that this means that server processes which daemonize themselves at startup must wait
 | ||||
| //   until after daemonization to create an AsyncIoContext.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // inline implementation details
 | ||||
| 
 | ||||
| inline AncillaryMessage::AncillaryMessage( | ||||
|     int level, int type, ArrayPtr<const byte> data) | ||||
|     : level(level), type(type), data(data) {} | ||||
| 
 | ||||
| inline int AncillaryMessage::getLevel() const { return level; } | ||||
| inline int AncillaryMessage::getType() const { return type; } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline Maybe<const T&> AncillaryMessage::as() { | ||||
|   if (data.size() >= sizeof(T)) { | ||||
|     return *reinterpret_cast<const T*>(data.begin()); | ||||
|   } else { | ||||
|     return nullptr; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline ArrayPtr<const T> AncillaryMessage::asArray() { | ||||
|   return arrayPtr(reinterpret_cast<const T*>(data.begin()), data.size() / sizeof(T)); | ||||
| } | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_ASYNC_IO_H_
 | ||||
| @ -0,0 +1,218 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| // This file contains a bunch of internal declarations that must appear before async.h can start.
 | ||||
| // We don't define these directly in async.h because it makes the file hard to read.
 | ||||
| 
 | ||||
| #ifndef KJ_ASYNC_PRELUDE_H_ | ||||
| #define KJ_ASYNC_PRELUDE_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "exception.h" | ||||
| #include "tuple.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| class EventLoop; | ||||
| template <typename T> | ||||
| class Promise; | ||||
| class WaitScope; | ||||
| 
 | ||||
| template <typename T> | ||||
| Promise<Array<T>> joinPromises(Array<Promise<T>>&& promises); | ||||
| Promise<void> joinPromises(Array<Promise<void>>&& promises); | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T> struct JoinPromises_ { typedef T Type; }; | ||||
| template <typename T> struct JoinPromises_<Promise<T>> { typedef T Type; }; | ||||
| 
 | ||||
| template <typename T> | ||||
| using JoinPromises = typename JoinPromises_<T>::Type; | ||||
| // If T is Promise<U>, resolves to U, otherwise resolves to T.
 | ||||
| //
 | ||||
| // TODO(cleanup):  Rename to avoid confusion with joinPromises() call which is completely
 | ||||
| //   unrelated.
 | ||||
| 
 | ||||
| class PropagateException { | ||||
|   // A functor which accepts a kj::Exception as a parameter and returns a broken promise of
 | ||||
|   // arbitrary type which simply propagates the exception.
 | ||||
| public: | ||||
|   class Bottom { | ||||
|   public: | ||||
|     Bottom(Exception&& exception): exception(kj::mv(exception)) {} | ||||
| 
 | ||||
|     Exception asException() { return kj::mv(exception); } | ||||
| 
 | ||||
|   private: | ||||
|     Exception exception; | ||||
|   }; | ||||
| 
 | ||||
|   Bottom operator()(Exception&& e) { | ||||
|     return Bottom(kj::mv(e)); | ||||
|   } | ||||
|   Bottom operator()(const  Exception& e) { | ||||
|     return Bottom(kj::cp(e)); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename Func, typename T> | ||||
| struct ReturnType_ { typedef decltype(instance<Func>()(instance<T>())) Type; }; | ||||
| template <typename Func> | ||||
| struct ReturnType_<Func, void> { typedef decltype(instance<Func>()()) Type; }; | ||||
| 
 | ||||
| template <typename Func, typename T> | ||||
| using ReturnType = typename ReturnType_<Func, T>::Type; | ||||
| // The return type of functor Func given a parameter of type T, with the special exception that if
 | ||||
| // T is void, this is the return type of Func called with no arguments.
 | ||||
| 
 | ||||
| template <typename T> struct SplitTuplePromise_ { typedef Promise<T> Type; }; | ||||
| template <typename... T> | ||||
| struct SplitTuplePromise_<kj::_::Tuple<T...>> { | ||||
|   typedef kj::Tuple<Promise<JoinPromises<T>>...> Type; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| using SplitTuplePromise = typename SplitTuplePromise_<T>::Type; | ||||
| // T -> Promise<T>
 | ||||
| // Tuple<T> -> Tuple<Promise<T>>
 | ||||
| 
 | ||||
| struct Void {}; | ||||
| // Application code should NOT refer to this!  See `kj::READY_NOW` instead.
 | ||||
| 
 | ||||
| template <typename T> struct FixVoid_ { typedef T Type; }; | ||||
| template <> struct FixVoid_<void> { typedef Void Type; }; | ||||
| template <typename T> using FixVoid = typename FixVoid_<T>::Type; | ||||
| // FixVoid<T> is just T unless T is void in which case it is _::Void (an empty struct).
 | ||||
| 
 | ||||
| template <typename T> struct UnfixVoid_ { typedef T Type; }; | ||||
| template <> struct UnfixVoid_<Void> { typedef void Type; }; | ||||
| template <typename T> using UnfixVoid = typename UnfixVoid_<T>::Type; | ||||
| // UnfixVoid is the opposite of FixVoid.
 | ||||
| 
 | ||||
| template <typename In, typename Out> | ||||
| struct MaybeVoidCaller { | ||||
|   // Calls the function converting a Void input to an empty parameter list and a void return
 | ||||
|   // value to a Void output.
 | ||||
| 
 | ||||
|   template <typename Func> | ||||
|   static inline Out apply(Func& func, In&& in) { | ||||
|     return func(kj::mv(in)); | ||||
|   } | ||||
| }; | ||||
| template <typename In, typename Out> | ||||
| struct MaybeVoidCaller<In&, Out> { | ||||
|   template <typename Func> | ||||
|   static inline Out apply(Func& func, In& in) { | ||||
|     return func(in); | ||||
|   } | ||||
| }; | ||||
| template <typename Out> | ||||
| struct MaybeVoidCaller<Void, Out> { | ||||
|   template <typename Func> | ||||
|   static inline Out apply(Func& func, Void&& in) { | ||||
|     return func(); | ||||
|   } | ||||
| }; | ||||
| template <typename In> | ||||
| struct MaybeVoidCaller<In, Void> { | ||||
|   template <typename Func> | ||||
|   static inline Void apply(Func& func, In&& in) { | ||||
|     func(kj::mv(in)); | ||||
|     return Void(); | ||||
|   } | ||||
| }; | ||||
| template <typename In> | ||||
| struct MaybeVoidCaller<In&, Void> { | ||||
|   template <typename Func> | ||||
|   static inline Void apply(Func& func, In& in) { | ||||
|     func(in); | ||||
|     return Void(); | ||||
|   } | ||||
| }; | ||||
| template <> | ||||
| struct MaybeVoidCaller<Void, Void> { | ||||
|   template <typename Func> | ||||
|   static inline Void apply(Func& func, Void&& in) { | ||||
|     func(); | ||||
|     return Void(); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| inline T&& returnMaybeVoid(T&& t) { | ||||
|   return kj::fwd<T>(t); | ||||
| } | ||||
| inline void returnMaybeVoid(Void&& v) {} | ||||
| 
 | ||||
| class ExceptionOrValue; | ||||
| class PromiseNode; | ||||
| class ChainPromiseNode; | ||||
| template <typename T> | ||||
| class ForkHub; | ||||
| 
 | ||||
| class TaskSetImpl; | ||||
| 
 | ||||
| class Event; | ||||
| 
 | ||||
| class PromiseBase { | ||||
| public: | ||||
|   kj::String trace(); | ||||
|   // Dump debug info about this promise.
 | ||||
| 
 | ||||
| private: | ||||
|   Own<PromiseNode> node; | ||||
| 
 | ||||
|   PromiseBase() = default; | ||||
|   PromiseBase(Own<PromiseNode>&& node): node(kj::mv(node)) {} | ||||
| 
 | ||||
|   friend class kj::EventLoop; | ||||
|   friend class ChainPromiseNode; | ||||
|   template <typename> | ||||
|   friend class kj::Promise; | ||||
|   friend class TaskSetImpl; | ||||
|   template <typename U> | ||||
|   friend Promise<Array<U>> kj::joinPromises(Array<Promise<U>>&& promises); | ||||
|   friend Promise<void> kj::joinPromises(Array<Promise<void>>&& promises); | ||||
| }; | ||||
| 
 | ||||
| void detach(kj::Promise<void>&& promise); | ||||
| void waitImpl(Own<_::PromiseNode>&& node, _::ExceptionOrValue& result, WaitScope& waitScope); | ||||
| Promise<void> yield(); | ||||
| Own<PromiseNode> neverDone(); | ||||
| 
 | ||||
| class NeverDone { | ||||
| public: | ||||
|   template <typename T> | ||||
|   operator Promise<T>() const { | ||||
|     return Promise<T>(false, neverDone()); | ||||
|   } | ||||
| 
 | ||||
|   KJ_NORETURN(void wait(WaitScope& waitScope) const); | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_ASYNC_PRELUDE_H_
 | ||||
| @ -0,0 +1,274 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_ASYNC_UNIX_H_ | ||||
| #define KJ_ASYNC_UNIX_H_ | ||||
| 
 | ||||
| #if _WIN32 | ||||
| #error "This file is Unix-specific. On Windows, include async-win32.h instead." | ||||
| #endif | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "async.h" | ||||
| #include "time.h" | ||||
| #include "vector.h" | ||||
| #include "io.h" | ||||
| #include <signal.h> | ||||
| 
 | ||||
| #if __linux__ && !__BIONIC__ && !defined(KJ_USE_EPOLL) | ||||
| // Default to epoll on Linux, except on Bionic (Android) which doesn't have signalfd.h.
 | ||||
| #define KJ_USE_EPOLL 1 | ||||
| #endif | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| class UnixEventPort: public EventPort { | ||||
|   // An EventPort implementation which can wait for events on file descriptors as well as signals.
 | ||||
|   // This API only makes sense on Unix.
 | ||||
|   //
 | ||||
|   // The implementation uses `poll()` or possibly a platform-specific API (e.g. epoll, kqueue).
 | ||||
|   // To also wait on signals without race conditions, the implementation may block signals until
 | ||||
|   // just before `poll()` while using a signal handler which `siglongjmp()`s back to just before
 | ||||
|   // the signal was unblocked, or it may use a nicer platform-specific API like signalfd.
 | ||||
|   //
 | ||||
|   // The implementation reserves a signal for internal use.  By default, it uses SIGUSR1.  If you
 | ||||
|   // need to use SIGUSR1 for something else, you must offer a different signal by calling
 | ||||
|   // setReservedSignal() at startup.
 | ||||
|   //
 | ||||
|   // WARNING: A UnixEventPort can only be used in the thread and process that created it. In
 | ||||
|   //   particular, note that after a fork(), a UnixEventPort created in the parent process will
 | ||||
|   //   not work correctly in the child, even if the parent ceases to use its copy. In particular
 | ||||
|   //   note that this means that server processes which daemonize themselves at startup must wait
 | ||||
|   //   until after daemonization to create a UnixEventPort.
 | ||||
| 
 | ||||
| public: | ||||
|   UnixEventPort(); | ||||
|   ~UnixEventPort() noexcept(false); | ||||
| 
 | ||||
|   class FdObserver; | ||||
|   // Class that watches an fd for readability or writability. See definition below.
 | ||||
| 
 | ||||
|   Promise<siginfo_t> onSignal(int signum); | ||||
|   // When the given signal is delivered to this thread, return the corresponding siginfo_t.
 | ||||
|   // The signal must have been captured using `captureSignal()`.
 | ||||
|   //
 | ||||
|   // If `onSignal()` has not been called, the signal will remain blocked in this thread.
 | ||||
|   // Therefore, a signal which arrives before `onSignal()` was called will not be "missed" -- the
 | ||||
|   // next call to 'onSignal()' will receive it.  Also, you can control which thread receives a
 | ||||
|   // process-wide signal by only calling `onSignal()` on that thread's event loop.
 | ||||
|   //
 | ||||
|   // The result of waiting on the same signal twice at once is undefined.
 | ||||
| 
 | ||||
|   static void captureSignal(int signum); | ||||
|   // Arranges for the given signal to be captured and handled via UnixEventPort, so that you may
 | ||||
|   // then pass it to `onSignal()`.  This method is static because it registers a signal handler
 | ||||
|   // which applies process-wide.  If any other threads exist in the process when `captureSignal()`
 | ||||
|   // is called, you *must* set the signal mask in those threads to block this signal, otherwise
 | ||||
|   // terrible things will happen if the signal happens to be delivered to those threads.  If at
 | ||||
|   // all possible, call `captureSignal()` *before* creating threads, so that threads you create in
 | ||||
|   // the future will inherit the proper signal mask.
 | ||||
|   //
 | ||||
|   // To un-capture a signal, simply install a different signal handler and then un-block it from
 | ||||
|   // the signal mask.
 | ||||
| 
 | ||||
|   static void setReservedSignal(int signum); | ||||
|   // Sets the signal number which `UnixEventPort` reserves for internal use.  If your application
 | ||||
|   // needs to use SIGUSR1, call this at startup (before any calls to `captureSignal()` and before
 | ||||
|   // constructing an `UnixEventPort`) to offer a different signal.
 | ||||
| 
 | ||||
|   Timer& getTimer() { return timerImpl; } | ||||
| 
 | ||||
|   // implements EventPort ------------------------------------------------------
 | ||||
|   bool wait() override; | ||||
|   bool poll() override; | ||||
|   void wake() const override; | ||||
| 
 | ||||
| private: | ||||
|   struct TimerSet;  // Defined in source file to avoid STL include.
 | ||||
|   class TimerPromiseAdapter; | ||||
|   class SignalPromiseAdapter; | ||||
| 
 | ||||
|   TimerImpl timerImpl; | ||||
| 
 | ||||
|   SignalPromiseAdapter* signalHead = nullptr; | ||||
|   SignalPromiseAdapter** signalTail = &signalHead; | ||||
| 
 | ||||
|   TimePoint readClock(); | ||||
|   void gotSignal(const siginfo_t& siginfo); | ||||
| 
 | ||||
|   friend class TimerPromiseAdapter; | ||||
| 
 | ||||
| #if KJ_USE_EPOLL | ||||
|   AutoCloseFd epollFd; | ||||
|   AutoCloseFd signalFd; | ||||
|   AutoCloseFd eventFd;   // Used for cross-thread wakeups.
 | ||||
| 
 | ||||
|   sigset_t signalFdSigset; | ||||
|   // Signal mask as currently set on the signalFd. Tracked so we can detect whether or not it
 | ||||
|   // needs updating.
 | ||||
| 
 | ||||
|   bool doEpollWait(int timeout); | ||||
| 
 | ||||
| #else | ||||
|   class PollContext; | ||||
| 
 | ||||
|   FdObserver* observersHead = nullptr; | ||||
|   FdObserver** observersTail = &observersHead; | ||||
| 
 | ||||
|   unsigned long long threadId;  // actually pthread_t
 | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| class UnixEventPort::FdObserver { | ||||
|   // Object which watches a file descriptor to determine when it is readable or writable.
 | ||||
|   //
 | ||||
|   // For listen sockets, "readable" means that there is a connection to accept(). For everything
 | ||||
|   // else, it means that read() (or recv()) will return data.
 | ||||
|   //
 | ||||
|   // The presence of out-of-band data should NOT fire this event. However, the event may
 | ||||
|   // occasionally fire spuriously (when there is actually no data to read), and one thing that can
 | ||||
|   // cause such spurious events is the arrival of OOB data on certain platforms whose event
 | ||||
|   // interfaces fail to distinguish between regular and OOB data (e.g. Mac OSX).
 | ||||
|   //
 | ||||
|   // WARNING: The exact behavior of this class differs across systems, since event interfaces
 | ||||
|   //   vary wildly. Be sure to read the documentation carefully and avoid depending on unspecified
 | ||||
|   //   behavior. If at all possible, use the higher-level AsyncInputStream interface instead.
 | ||||
| 
 | ||||
| public: | ||||
|   enum Flags { | ||||
|     OBSERVE_READ = 1, | ||||
|     OBSERVE_WRITE = 2, | ||||
|     OBSERVE_URGENT = 4, | ||||
|     OBSERVE_READ_WRITE = OBSERVE_READ | OBSERVE_WRITE | ||||
|   }; | ||||
| 
 | ||||
|   FdObserver(UnixEventPort& eventPort, int fd, uint flags); | ||||
|   // Begin watching the given file descriptor for readability. Only one ReadObserver may exist
 | ||||
|   // for a given file descriptor at a time.
 | ||||
| 
 | ||||
|   ~FdObserver() noexcept(false); | ||||
| 
 | ||||
|   KJ_DISALLOW_COPY(FdObserver); | ||||
| 
 | ||||
|   Promise<void> whenBecomesReadable(); | ||||
|   // Resolves the next time the file descriptor transitions from having no data to read to having
 | ||||
|   // some data to read.
 | ||||
|   //
 | ||||
|   // KJ uses "edge-triggered" event notification whenever possible. As a result, it is an error
 | ||||
|   // to call this method when there is already data in the read buffer which has been there since
 | ||||
|   // prior to the last turn of the event loop or prior to creation FdWatcher. In this case, it is
 | ||||
|   // unspecified whether the promise will ever resolve -- it depends on the underlying event
 | ||||
|   // mechanism being used.
 | ||||
|   //
 | ||||
|   // In order to avoid this problem, make sure that you only call `whenBecomesReadable()`
 | ||||
|   // only at times when you know the buffer is empty. You know this for sure when one of the
 | ||||
|   // following happens:
 | ||||
|   // * read() or recv() fails with EAGAIN or EWOULDBLOCK. (You MUST have non-blocking mode
 | ||||
|   //   enabled on the fd!)
 | ||||
|   // * The file descriptor is a regular byte-oriented object (like a socket or pipe),
 | ||||
|   //   read() or recv() returns fewer than the number of bytes requested, and `atEndHint()`
 | ||||
|   //   returns false. This can only happen if the buffer is empty but EOF is not reached. (Note,
 | ||||
|   //   though, that for record-oriented file descriptors like Linux's inotify interface, this
 | ||||
|   //   rule does not hold, because it could simply be that the next record did not fit into the
 | ||||
|   //   space available.)
 | ||||
|   //
 | ||||
|   // It is an error to call `whenBecomesReadable()` again when the promise returned previously
 | ||||
|   // has not yet resolved. If you do this, the previous promise may throw an exception.
 | ||||
| 
 | ||||
|   inline Maybe<bool> atEndHint() { return atEnd; } | ||||
|   // Returns true if the event system has indicated that EOF has been received. There may still
 | ||||
|   // be data in the read buffer, but once that is gone, there's nothing left.
 | ||||
|   //
 | ||||
|   // Returns false if the event system has indicated that EOF had NOT been received as of the
 | ||||
|   // last turn of the event loop.
 | ||||
|   //
 | ||||
|   // Returns nullptr if the event system does not know whether EOF has been reached. In this
 | ||||
|   // case, the only way to know for sure is to call read() or recv() and check if it returns
 | ||||
|   // zero.
 | ||||
|   //
 | ||||
|   // This hint may be useful as an optimization to avoid an unnecessary system call.
 | ||||
| 
 | ||||
|   Promise<void> whenBecomesWritable(); | ||||
|   // Resolves the next time the file descriptor transitions from having no space available in the
 | ||||
|   // write buffer to having some space available.
 | ||||
|   //
 | ||||
|   // KJ uses "edge-triggered" event notification whenever possible. As a result, it is an error
 | ||||
|   // to call this method when there is already space in the write buffer which has been there
 | ||||
|   // since prior to the last turn of the event loop or prior to creation FdWatcher. In this case,
 | ||||
|   // it is unspecified whether the promise will ever resolve -- it depends on the underlying
 | ||||
|   // event mechanism being used.
 | ||||
|   //
 | ||||
|   // In order to avoid this problem, make sure that you only call `whenBecomesWritable()`
 | ||||
|   // only at times when you know the buffer is full. You know this for sure when one of the
 | ||||
|   // following happens:
 | ||||
|   // * write() or send() fails with EAGAIN or EWOULDBLOCK. (You MUST have non-blocking mode
 | ||||
|   //   enabled on the fd!)
 | ||||
|   // * write() or send() succeeds but accepts fewer than the number of bytes provided. This can
 | ||||
|   //   only happen if the buffer is full.
 | ||||
|   //
 | ||||
|   // It is an error to call `whenBecomesWritable()` again when the promise returned previously
 | ||||
|   // has not yet resolved. If you do this, the previous promise may throw an exception.
 | ||||
| 
 | ||||
|   Promise<void> whenUrgentDataAvailable(); | ||||
|   // Resolves the next time the file descriptor's read buffer contains "urgent" data.
 | ||||
|   //
 | ||||
|   // The conditions for availability of urgent data are specific to the file descriptor's
 | ||||
|   // underlying implementation.
 | ||||
|   //
 | ||||
|   // It is an error to call `whenUrgentDataAvailable()` again when the promise returned previously
 | ||||
|   // has not yet resolved. If you do this, the previous promise may throw an exception.
 | ||||
|   //
 | ||||
|   // WARNING: This has some known weird behavior on macOS. See
 | ||||
|   //   https://github.com/sandstorm-io/capnproto/issues/374.
 | ||||
| 
 | ||||
| private: | ||||
|   UnixEventPort& eventPort; | ||||
|   int fd; | ||||
|   uint flags; | ||||
| 
 | ||||
|   kj::Maybe<Own<PromiseFulfiller<void>>> readFulfiller; | ||||
|   kj::Maybe<Own<PromiseFulfiller<void>>> writeFulfiller; | ||||
|   kj::Maybe<Own<PromiseFulfiller<void>>> urgentFulfiller; | ||||
|   // Replaced each time `whenBecomesReadable()` or `whenBecomesWritable()` is called. Reverted to
 | ||||
|   // null every time an event is fired.
 | ||||
| 
 | ||||
|   Maybe<bool> atEnd; | ||||
| 
 | ||||
|   void fire(short events); | ||||
| 
 | ||||
| #if !KJ_USE_EPOLL | ||||
|   FdObserver* next; | ||||
|   FdObserver** prev; | ||||
|   // Linked list of observers which currently have a non-null readFulfiller or writeFulfiller.
 | ||||
|   // If `prev` is null then the observer is not currently in the list.
 | ||||
| 
 | ||||
|   short getEventMask(); | ||||
| #endif | ||||
| 
 | ||||
|   friend class UnixEventPort; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_ASYNC_UNIX_H_
 | ||||
| @ -0,0 +1,234 @@ | ||||
| // Copyright (c) 2016 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_ASYNC_WIN32_H_ | ||||
| #define KJ_ASYNC_WIN32_H_ | ||||
| 
 | ||||
| #if !_WIN32 | ||||
| #error "This file is Windows-specific. On Unix, include async-unix.h instead." | ||||
| #endif | ||||
| 
 | ||||
| #include "async.h" | ||||
| #include "time.h" | ||||
| #include "io.h" | ||||
| #include <atomic> | ||||
| #include <inttypes.h> | ||||
| 
 | ||||
| // Include windows.h as lean as possible. (If you need more of the Windows API for your app,
 | ||||
| // #include windows.h yourself before including this header.)
 | ||||
| #define WIN32_LEAN_AND_MEAN 1 | ||||
| #define NOSERVICE 1 | ||||
| #define NOMCX 1 | ||||
| #define NOIME 1 | ||||
| #include <windows.h> | ||||
| #include "windows-sanity.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| class Win32EventPort: public EventPort { | ||||
|   // Abstract base interface for EventPorts that can listen on Win32 event types. Due to the
 | ||||
|   // absurd complexity of the Win32 API, it's not possible to standardize on a single
 | ||||
|   // implementation of EventPort. In particular, there is no way for a single thread to use I/O
 | ||||
|   // completion ports (the most efficient way of handling I/O) while at the same time waiting for
 | ||||
|   // signalable handles or UI messages.
 | ||||
|   //
 | ||||
|   // Note that UI messages are not supported at all by this interface because the message queue
 | ||||
|   // is implemented by user32.dll and we want libkj to depend only on kernel32.dll. A separate
 | ||||
|   // compat library could provide a Win32EventPort implementation that works with the UI message
 | ||||
|   // queue.
 | ||||
| 
 | ||||
| public: | ||||
|   // ---------------------------------------------------------------------------
 | ||||
|   // overlapped I/O
 | ||||
| 
 | ||||
|   struct IoResult { | ||||
|     DWORD errorCode; | ||||
|     DWORD bytesTransferred; | ||||
|   }; | ||||
| 
 | ||||
|   class IoOperation { | ||||
|   public: | ||||
|     virtual LPOVERLAPPED getOverlapped() = 0; | ||||
|     // Gets the OVERLAPPED structure to pass to the Win32 I/O call. Do NOT modify it; just pass it
 | ||||
|     // on.
 | ||||
| 
 | ||||
|     virtual Promise<IoResult> onComplete() = 0; | ||||
|     // After making the Win32 call, if the return value indicates that the operation was
 | ||||
|     // successfully queued (i.e. the completion event will definitely occur), call this to wait
 | ||||
|     // for completion.
 | ||||
|     //
 | ||||
|     // You MUST call this if the operation was successfully queued, and you MUST NOT call this
 | ||||
|     // otherwise. If the Win32 call failed (without queuing any operation or event) then you should
 | ||||
|     // simply drop the IoOperation object.
 | ||||
|     //
 | ||||
|     // Dropping the returned Promise cancels the operation via Win32's CancelIoEx(). The destructor
 | ||||
|     // will wait for the cancellation to complete, such that after dropping the proimse it is safe
 | ||||
|     // to free the buffer that the operation was reading from / writing to.
 | ||||
|     //
 | ||||
|     // You may safely drop the `IoOperation` while still waiting for this promise. You may not,
 | ||||
|     // however, drop the `IoObserver`.
 | ||||
|   }; | ||||
| 
 | ||||
|   class IoObserver { | ||||
|   public: | ||||
|     virtual Own<IoOperation> newOperation(uint64_t offset) = 0; | ||||
|     // Begin an I/O operation. For file operations, `offset` is the offset within the file at
 | ||||
|     // which the operation will start. For stream operations, `offset` is ignored.
 | ||||
|   }; | ||||
| 
 | ||||
|   virtual Own<IoObserver> observeIo(HANDLE handle) = 0; | ||||
|   // Given a handle which supports overlapped I/O, arrange to receive I/O completion events via
 | ||||
|   // this EventPort.
 | ||||
|   //
 | ||||
|   // Different Win32EventPort implementations may handle this in different ways, such as by using
 | ||||
|   // completion routines (APCs) or by using I/O completion ports. The caller should not assume
 | ||||
|   // any particular technique.
 | ||||
|   //
 | ||||
|   // WARNING: It is only safe to call observeIo() on a particular handle once during its lifetime.
 | ||||
|   //   You cannot observe the same handle from multiple Win32EventPorts, even if not at the same
 | ||||
|   //   time. This is because the Win32 API provides no way to disassociate a handle from an I/O
 | ||||
|   //   completion port once it is associated.
 | ||||
| 
 | ||||
|   // ---------------------------------------------------------------------------
 | ||||
|   // signalable handles
 | ||||
|   //
 | ||||
|   // Warning: Due to limitations in the Win32 API, implementations of EventPort may be forced to
 | ||||
|   //   spawn additional threads to wait for signaled objects. This is necessary if the EventPort
 | ||||
|   //   implementation is based on I/O completion ports, or if you need to wait on more than 64
 | ||||
|   //   handles at once.
 | ||||
| 
 | ||||
|   class SignalObserver { | ||||
|   public: | ||||
|     virtual Promise<void> onSignaled() = 0; | ||||
|     // Returns a promise that completes the next time the handle enters the signaled state.
 | ||||
|     //
 | ||||
|     // Depending on the type of handle, the handle may automatically be reset to a non-signaled
 | ||||
|     // state before the promise resolves. The underlying implementaiton uses WaitForSingleObject()
 | ||||
|     // or an equivalent wait call, so check the documentation for that to understand the semantics.
 | ||||
|     //
 | ||||
|     // If the handle is a mutex and it is abandoned without being unlocked, the promise breaks with
 | ||||
|     // an exception.
 | ||||
| 
 | ||||
|     virtual Promise<bool> onSignaledOrAbandoned() = 0; | ||||
|     // Like onSingaled(), but instead of throwing when a mutex is abandoned, resolves to `true`.
 | ||||
|     // Resolves to `false` for non-abandoned signals.
 | ||||
|   }; | ||||
| 
 | ||||
|   virtual Own<SignalObserver> observeSignalState(HANDLE handle) = 0; | ||||
|   // Given a handle that supports waiting for it to become "signaled" via WaitForSingleObject(),
 | ||||
|   // return an object that can wait for this state using the EventPort.
 | ||||
| 
 | ||||
|   // ---------------------------------------------------------------------------
 | ||||
|   // APCs
 | ||||
| 
 | ||||
|   virtual void allowApc() = 0; | ||||
|   // If this is ever called, the Win32EventPort will switch modes so that APCs can be scheduled
 | ||||
|   // on the thread, e.g. through the Win32 QueueUserAPC() call. In the future, this may be enabled
 | ||||
|   // by default. However, as of this writing, Wine does not support the necessary
 | ||||
|   // GetQueuedCompletionStatusEx() call, thus allowApc() breaks Wine support. (Tested on Wine
 | ||||
|   // 1.8.7.)
 | ||||
|   //
 | ||||
|   // If the event port implementation can't support APCs for some reason, this throws.
 | ||||
| 
 | ||||
|   // ---------------------------------------------------------------------------
 | ||||
|   // time
 | ||||
| 
 | ||||
|   virtual Timer& getTimer() = 0; | ||||
| }; | ||||
| 
 | ||||
| class Win32WaitObjectThreadPool { | ||||
|   // Helper class that implements Win32EventPort::observeSignalState() by spawning additional
 | ||||
|   // threads as needed to perform the actual waiting.
 | ||||
|   //
 | ||||
|   // This class is intended to be used to assist in building Win32EventPort implementations.
 | ||||
| 
 | ||||
| public: | ||||
|   Win32WaitObjectThreadPool(uint mainThreadCount = 0); | ||||
|   // `mainThreadCount` indicates the number of objects the main thread is able to listen on
 | ||||
|   // directly. Typically this would be zero (e.g. if the main thread watches an I/O completion
 | ||||
|   // port) or MAXIMUM_WAIT_OBJECTS (e.g. if the main thread is a UI thread but can use
 | ||||
|   // MsgWaitForMultipleObjectsEx() to wait on some handles at the same time as messages).
 | ||||
| 
 | ||||
|   Own<Win32EventPort::SignalObserver> observeSignalState(HANDLE handle); | ||||
|   // Implemetns Win32EventPort::observeSignalState().
 | ||||
| 
 | ||||
|   uint prepareMainThreadWait(HANDLE* handles[]); | ||||
|   // Call immediately before invoking WaitForMultipleObjects() or similar in the main thread.
 | ||||
|   // Fills in `handles` with the handle pointers to wait on, and returns the number of handles
 | ||||
|   // in this array. (The array should be allocated to be at least the size passed to the
 | ||||
|   // constructor).
 | ||||
|   //
 | ||||
|   // There's no need to call this if `mainThreadCount` as passed to the constructor was zero.
 | ||||
| 
 | ||||
|   bool finishedMainThreadWait(DWORD returnCode); | ||||
|   // Call immediately after invoking WaitForMultipleObjects() or similar in the main thread,
 | ||||
|   // passing the value returend by that call. Returns true if the event indicated by `returnCode`
 | ||||
|   // has been handled (i.e. it was WAIT_OBJECT_n or WAIT_ABANDONED_n where n is in-range for the
 | ||||
|   // last call to prepareMainThreadWait()).
 | ||||
| }; | ||||
| 
 | ||||
| class Win32IocpEventPort final: public Win32EventPort { | ||||
|   // An EventPort implementation which uses Windows I/O completion ports to listen for events.
 | ||||
|   //
 | ||||
|   // With this implementation, observeSignalState() requires spawning a separate thread.
 | ||||
| 
 | ||||
| public: | ||||
|   Win32IocpEventPort(); | ||||
|   ~Win32IocpEventPort() noexcept(false); | ||||
| 
 | ||||
|   // implements EventPort ------------------------------------------------------
 | ||||
|   bool wait() override; | ||||
|   bool poll() override; | ||||
|   void wake() const override; | ||||
| 
 | ||||
|   // implements Win32IocpEventPort ---------------------------------------------
 | ||||
|   Own<IoObserver> observeIo(HANDLE handle) override; | ||||
|   Own<SignalObserver> observeSignalState(HANDLE handle) override; | ||||
|   Timer& getTimer() override { return timerImpl; } | ||||
|   void allowApc() override { isAllowApc = true; } | ||||
| 
 | ||||
| private: | ||||
|   class IoPromiseAdapter; | ||||
|   class IoOperationImpl; | ||||
|   class IoObserverImpl; | ||||
| 
 | ||||
|   AutoCloseHandle iocp; | ||||
|   AutoCloseHandle thread; | ||||
|   Win32WaitObjectThreadPool waitThreads; | ||||
|   TimerImpl timerImpl; | ||||
|   mutable std::atomic<bool> sentWake {false}; | ||||
|   bool isAllowApc = false; | ||||
| 
 | ||||
|   static TimePoint readClock(); | ||||
| 
 | ||||
|   void waitIocp(DWORD timeoutMs); | ||||
|   // Wait on the I/O completion port for up to timeoutMs and pump events. Does not advance the
 | ||||
|   // timer; caller must do that.
 | ||||
| 
 | ||||
|   bool receivedWake(); | ||||
| 
 | ||||
|   static AutoCloseHandle newIocpHandle(); | ||||
|   static AutoCloseHandle openCurrentThread(); | ||||
| }; | ||||
| 
 | ||||
| } // namespace kj
 | ||||
| 
 | ||||
| #endif // KJ_ASYNC_WIN32_H_
 | ||||
| @ -0,0 +1,682 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_ASYNC_H_ | ||||
| #define KJ_ASYNC_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "async-prelude.h" | ||||
| #include "exception.h" | ||||
| #include "refcount.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| class EventLoop; | ||||
| class WaitScope; | ||||
| 
 | ||||
| template <typename T> | ||||
| class Promise; | ||||
| template <typename T> | ||||
| class ForkedPromise; | ||||
| template <typename T> | ||||
| class PromiseFulfiller; | ||||
| template <typename T> | ||||
| struct PromiseFulfillerPair; | ||||
| 
 | ||||
| template <typename Func, typename T> | ||||
| using PromiseForResult = Promise<_::JoinPromises<_::ReturnType<Func, T>>>; | ||||
| // Evaluates to the type of Promise for the result of calling functor type Func with parameter type
 | ||||
| // T.  If T is void, then the promise is for the result of calling Func with no arguments.  If
 | ||||
| // Func itself returns a promise, the promises are joined, so you never get Promise<Promise<T>>.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Promises
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class Promise: protected _::PromiseBase { | ||||
|   // The basic primitive of asynchronous computation in KJ.  Similar to "futures", but designed
 | ||||
|   // specifically for event loop concurrency.  Similar to E promises and JavaScript Promises/A.
 | ||||
|   //
 | ||||
|   // A Promise represents a promise to produce a value of type T some time in the future.  Once
 | ||||
|   // that value has been produced, the promise is "fulfilled".  Alternatively, a promise can be
 | ||||
|   // "broken", with an Exception describing what went wrong.  You may implicitly convert a value of
 | ||||
|   // type T to an already-fulfilled Promise<T>.  You may implicitly convert the constant
 | ||||
|   // `kj::READY_NOW` to an already-fulfilled Promise<void>.  You may also implicitly convert a
 | ||||
|   // `kj::Exception` to an already-broken promise of any type.
 | ||||
|   //
 | ||||
|   // Promises are linear types -- they are moveable but not copyable.  If a Promise is destroyed
 | ||||
|   // or goes out of scope (without being moved elsewhere), any ongoing asynchronous operations
 | ||||
|   // meant to fulfill the promise will be canceled if possible.  All methods of `Promise` (unless
 | ||||
|   // otherwise noted) actually consume the promise in the sense of move semantics.  (Arguably they
 | ||||
|   // should be rvalue-qualified, but at the time this interface was created compilers didn't widely
 | ||||
|   // support that yet and anyway it would be pretty ugly typing kj::mv(promise).whatever().)  If
 | ||||
|   // you want to use one Promise in two different places, you must fork it with `fork()`.
 | ||||
|   //
 | ||||
|   // To use the result of a Promise, you must call `then()` and supply a callback function to
 | ||||
|   // call with the result.  `then()` returns another promise, for the result of the callback.
 | ||||
|   // Any time that this would result in Promise<Promise<T>>, the promises are collapsed into a
 | ||||
|   // simple Promise<T> that first waits for the outer promise, then the inner.  Example:
 | ||||
|   //
 | ||||
|   //     // Open a remote file, read the content, and then count the
 | ||||
|   //     // number of lines of text.
 | ||||
|   //     // Note that none of the calls here block.  `file`, `content`
 | ||||
|   //     // and `lineCount` are all initialized immediately before any
 | ||||
|   //     // asynchronous operations occur.  The lambda callbacks are
 | ||||
|   //     // called later.
 | ||||
|   //     Promise<Own<File>> file = openFtp("ftp://host/foo/bar");
 | ||||
|   //     Promise<String> content = file.then(
 | ||||
|   //         [](Own<File> file) -> Promise<String> {
 | ||||
|   //           return file.readAll();
 | ||||
|   //         });
 | ||||
|   //     Promise<int> lineCount = content.then(
 | ||||
|   //         [](String text) -> int {
 | ||||
|   //           uint count = 0;
 | ||||
|   //           for (char c: text) count += (c == '\n');
 | ||||
|   //           return count;
 | ||||
|   //         });
 | ||||
|   //
 | ||||
|   // For `then()` to work, the current thread must have an active `EventLoop`.  Each callback
 | ||||
|   // is scheduled to execute in that loop.  Since `then()` schedules callbacks only on the current
 | ||||
|   // thread's event loop, you do not need to worry about two callbacks running at the same time.
 | ||||
|   // You will need to set up at least one `EventLoop` at the top level of your program before you
 | ||||
|   // can use promises.
 | ||||
|   //
 | ||||
|   // To adapt a non-Promise-based asynchronous API to promises, use `newAdaptedPromise()`.
 | ||||
|   //
 | ||||
|   // Systems using promises should consider supporting the concept of "pipelining".  Pipelining
 | ||||
|   // means allowing a caller to start issuing method calls against a promised object before the
 | ||||
|   // promise has actually been fulfilled.  This is particularly useful if the promise is for a
 | ||||
|   // remote object living across a network, as this can avoid round trips when chaining a series
 | ||||
|   // of calls.  It is suggested that any class T which supports pipelining implement a subclass of
 | ||||
|   // Promise<T> which adds "eventual send" methods -- methods which, when called, say "please
 | ||||
|   // invoke the corresponding method on the promised value once it is available".  These methods
 | ||||
|   // should in turn return promises for the eventual results of said invocations.  Cap'n Proto,
 | ||||
|   // for example, implements the type `RemotePromise` which supports pipelining RPC requests -- see
 | ||||
|   // `capnp/capability.h`.
 | ||||
|   //
 | ||||
|   // KJ Promises are based on E promises:
 | ||||
|   //   http://wiki.erights.org/wiki/Walnut/Distributed_Computing#Promises
 | ||||
|   //
 | ||||
|   // KJ Promises are also inspired in part by the evolving standards for JavaScript/ECMAScript
 | ||||
|   // promises, which are themselves influenced by E promises:
 | ||||
|   //   http://promisesaplus.com/
 | ||||
|   //   https://github.com/domenic/promises-unwrapping
 | ||||
| 
 | ||||
| public: | ||||
|   Promise(_::FixVoid<T> value); | ||||
|   // Construct an already-fulfilled Promise from a value of type T.  For non-void promises, the
 | ||||
|   // parameter type is simply T.  So, e.g., in a function that returns `Promise<int>`, you can
 | ||||
|   // say `return 123;` to return a promise that is already fulfilled to 123.
 | ||||
|   //
 | ||||
|   // For void promises, use `kj::READY_NOW` as the value, e.g. `return kj::READY_NOW`.
 | ||||
| 
 | ||||
|   Promise(kj::Exception&& e); | ||||
|   // Construct an already-broken Promise.
 | ||||
| 
 | ||||
|   inline Promise(decltype(nullptr)) {} | ||||
| 
 | ||||
|   template <typename Func, typename ErrorFunc = _::PropagateException> | ||||
|   PromiseForResult<Func, T> then(Func&& func, ErrorFunc&& errorHandler = _::PropagateException()) | ||||
|       KJ_WARN_UNUSED_RESULT; | ||||
|   // Register a continuation function to be executed when the promise completes.  The continuation
 | ||||
|   // (`func`) takes the promised value (an rvalue of type `T`) as its parameter.  The continuation
 | ||||
|   // may return a new value; `then()` itself returns a promise for the continuation's eventual
 | ||||
|   // result.  If the continuation itself returns a `Promise<U>`, then `then()` shall also return
 | ||||
|   // a `Promise<U>` which first waits for the original promise, then executes the continuation,
 | ||||
|   // then waits for the inner promise (i.e. it automatically "unwraps" the promise).
 | ||||
|   //
 | ||||
|   // In all cases, `then()` returns immediately.  The continuation is executed later.  The
 | ||||
|   // continuation is always executed on the same EventLoop (and, therefore, the same thread) which
 | ||||
|   // called `then()`, therefore no synchronization is necessary on state shared by the continuation
 | ||||
|   // and the surrounding scope.  If no EventLoop is running on the current thread, `then()` throws
 | ||||
|   // an exception.
 | ||||
|   //
 | ||||
|   // You may also specify an error handler continuation as the second parameter.  `errorHandler`
 | ||||
|   // must be a functor taking a parameter of type `kj::Exception&&`.  It must return the same
 | ||||
|   // type as `func` returns (except when `func` returns `Promise<U>`, in which case `errorHandler`
 | ||||
|   // may return either `Promise<U>` or just `U`).  The default error handler simply propagates the
 | ||||
|   // exception to the returned promise.
 | ||||
|   //
 | ||||
|   // Either `func` or `errorHandler` may, of course, throw an exception, in which case the promise
 | ||||
|   // is broken.  When compiled with -fno-exceptions, the framework will still detect when a
 | ||||
|   // recoverable exception was thrown inside of a continuation and will consider the promise
 | ||||
|   // broken even though a (presumably garbage) result was returned.
 | ||||
|   //
 | ||||
|   // If the returned promise is destroyed before the callback runs, the callback will be canceled
 | ||||
|   // (it will never run).
 | ||||
|   //
 | ||||
|   // Note that `then()` -- like all other Promise methods -- consumes the promise on which it is
 | ||||
|   // called, in the sense of move semantics.  After returning, the original promise is no longer
 | ||||
|   // valid, but `then()` returns a new promise.
 | ||||
|   //
 | ||||
|   // *Advanced implementation tips:*  Most users will never need to worry about the below, but
 | ||||
|   // it is good to be aware of.
 | ||||
|   //
 | ||||
|   // As an optimization, if the callback function `func` does _not_ return another promise, then
 | ||||
|   // execution of `func` itself may be delayed until its result is known to be needed.  The
 | ||||
|   // expectation here is that `func` is just doing some transformation on the results, not
 | ||||
|   // scheduling any other actions, therefore the system doesn't need to be proactive about
 | ||||
|   // evaluating it.  This way, a chain of trivial then() transformations can be executed all at
 | ||||
|   // once without repeatedly re-scheduling through the event loop.  Use the `eagerlyEvaluate()`
 | ||||
|   // method to suppress this behavior.
 | ||||
|   //
 | ||||
|   // On the other hand, if `func` _does_ return another promise, then the system evaluates `func`
 | ||||
|   // as soon as possible, because the promise it returns might be for a newly-scheduled
 | ||||
|   // long-running asynchronous task.
 | ||||
|   //
 | ||||
|   // As another optimization, when a callback function registered with `then()` is actually
 | ||||
|   // scheduled, it is scheduled to occur immediately, preempting other work in the event queue.
 | ||||
|   // This allows a long chain of `then`s to execute all at once, improving cache locality by
 | ||||
|   // clustering operations on the same data.  However, this implies that starvation can occur
 | ||||
|   // if a chain of `then()`s takes a very long time to execute without ever stopping to wait for
 | ||||
|   // actual I/O.  To solve this, use `kj::evalLater()` to yield control; this way, all other events
 | ||||
|   // in the queue will get a chance to run before your callback is executed.
 | ||||
| 
 | ||||
|   Promise<void> ignoreResult() KJ_WARN_UNUSED_RESULT { return then([](T&&) {}); } | ||||
|   // Convenience method to convert the promise to a void promise by ignoring the return value.
 | ||||
|   //
 | ||||
|   // You must still wait on the returned promise if you want the task to execute.
 | ||||
| 
 | ||||
|   template <typename ErrorFunc> | ||||
|   Promise<T> catch_(ErrorFunc&& errorHandler) KJ_WARN_UNUSED_RESULT; | ||||
|   // Equivalent to `.then(identityFunc, errorHandler)`, where `identifyFunc` is a function that
 | ||||
|   // just returns its input.
 | ||||
| 
 | ||||
|   T wait(WaitScope& waitScope); | ||||
|   // Run the event loop until the promise is fulfilled, then return its result.  If the promise
 | ||||
|   // is rejected, throw an exception.
 | ||||
|   //
 | ||||
|   // wait() is primarily useful at the top level of a program -- typically, within the function
 | ||||
|   // that allocated the EventLoop.  For example, a program that performs one or two RPCs and then
 | ||||
|   // exits would likely use wait() in its main() function to wait on each RPC.  On the other hand,
 | ||||
|   // server-side code generally cannot use wait(), because it has to be able to accept multiple
 | ||||
|   // requests at once.
 | ||||
|   //
 | ||||
|   // If the promise is rejected, `wait()` throws an exception.  If the program was compiled without
 | ||||
|   // exceptions (-fno-exceptions), this will usually abort.  In this case you really should first
 | ||||
|   // use `then()` to set an appropriate handler for the exception case, so that the promise you
 | ||||
|   // actually wait on never throws.
 | ||||
|   //
 | ||||
|   // `waitScope` is an object proving that the caller is in a scope where wait() is allowed.  By
 | ||||
|   // convention, any function which might call wait(), or which might call another function which
 | ||||
|   // might call wait(), must take `WaitScope&` as one of its parameters.  This is needed for two
 | ||||
|   // reasons:
 | ||||
|   // * `wait()` is not allowed during an event callback, because event callbacks are themselves
 | ||||
|   //   called during some other `wait()`, and such recursive `wait()`s would only be able to
 | ||||
|   //   complete in LIFO order, which might mean that the outer `wait()` ends up waiting longer
 | ||||
|   //   than it is supposed to.  To prevent this, a `WaitScope` cannot be constructed or used during
 | ||||
|   //   an event callback.
 | ||||
|   // * Since `wait()` runs the event loop, unrelated event callbacks may execute before `wait()`
 | ||||
|   //   returns.  This means that anyone calling `wait()` must be reentrant -- state may change
 | ||||
|   //   around them in arbitrary ways.  Therefore, callers really need to know if a function they
 | ||||
|   //   are calling might wait(), and the `WaitScope&` parameter makes this clear.
 | ||||
|   //
 | ||||
|   // TODO(someday):  Implement fibers, and let them call wait() even when they are handling an
 | ||||
|   //   event.
 | ||||
| 
 | ||||
|   ForkedPromise<T> fork() KJ_WARN_UNUSED_RESULT; | ||||
|   // Forks the promise, so that multiple different clients can independently wait on the result.
 | ||||
|   // `T` must be copy-constructable for this to work.  Or, in the special case where `T` is
 | ||||
|   // `Own<U>`, `U` must have a method `Own<U> addRef()` which returns a new reference to the same
 | ||||
|   // (or an equivalent) object (probably implemented via reference counting).
 | ||||
| 
 | ||||
|   _::SplitTuplePromise<T> split(); | ||||
|   // Split a promise for a tuple into a tuple of promises.
 | ||||
|   //
 | ||||
|   // E.g. if you have `Promise<kj::Tuple<T, U>>`, `split()` returns
 | ||||
|   // `kj::Tuple<Promise<T>, Promise<U>>`.
 | ||||
| 
 | ||||
|   Promise<T> exclusiveJoin(Promise<T>&& other) KJ_WARN_UNUSED_RESULT; | ||||
|   // Return a new promise that resolves when either the original promise resolves or `other`
 | ||||
|   // resolves (whichever comes first).  The promise that didn't resolve first is canceled.
 | ||||
| 
 | ||||
|   // TODO(someday): inclusiveJoin(), or perhaps just join(), which waits for both completions
 | ||||
|   //   and produces a tuple?
 | ||||
| 
 | ||||
|   template <typename... Attachments> | ||||
|   Promise<T> attach(Attachments&&... attachments) KJ_WARN_UNUSED_RESULT; | ||||
|   // "Attaches" one or more movable objects (often, Own<T>s) to the promise, such that they will
 | ||||
|   // be destroyed when the promise resolves.  This is useful when a promise's callback contains
 | ||||
|   // pointers into some object and you want to make sure the object still exists when the callback
 | ||||
|   // runs -- after calling then(), use attach() to add necessary objects to the result.
 | ||||
| 
 | ||||
|   template <typename ErrorFunc> | ||||
|   Promise<T> eagerlyEvaluate(ErrorFunc&& errorHandler) KJ_WARN_UNUSED_RESULT; | ||||
|   Promise<T> eagerlyEvaluate(decltype(nullptr)) KJ_WARN_UNUSED_RESULT; | ||||
|   // Force eager evaluation of this promise.  Use this if you are going to hold on to the promise
 | ||||
|   // for awhile without consuming the result, but you want to make sure that the system actually
 | ||||
|   // processes it.
 | ||||
|   //
 | ||||
|   // `errorHandler` is a function that takes `kj::Exception&&`, like the second parameter to
 | ||||
|   // `then()`, except that it must return void.  We make you specify this because otherwise it's
 | ||||
|   // easy to forget to handle errors in a promise that you never use.  You may specify nullptr for
 | ||||
|   // the error handler if you are sure that ignoring errors is fine, or if you know that you'll
 | ||||
|   // eventually wait on the promise somewhere.
 | ||||
| 
 | ||||
|   template <typename ErrorFunc> | ||||
|   void detach(ErrorFunc&& errorHandler); | ||||
|   // Allows the promise to continue running in the background until it completes or the
 | ||||
|   // `EventLoop` is destroyed.  Be careful when using this: since you can no longer cancel this
 | ||||
|   // promise, you need to make sure that the promise owns all the objects it touches or make sure
 | ||||
|   // those objects outlive the EventLoop.
 | ||||
|   //
 | ||||
|   // `errorHandler` is a function that takes `kj::Exception&&`, like the second parameter to
 | ||||
|   // `then()`, except that it must return void.
 | ||||
|   //
 | ||||
|   // This function exists mainly to implement the Cap'n Proto requirement that RPC calls cannot be
 | ||||
|   // canceled unless the callee explicitly permits it.
 | ||||
| 
 | ||||
|   kj::String trace(); | ||||
|   // Returns a dump of debug info about this promise.  Not for production use.  Requires RTTI.
 | ||||
|   // This method does NOT consume the promise as other methods do.
 | ||||
| 
 | ||||
| private: | ||||
|   Promise(bool, Own<_::PromiseNode>&& node): PromiseBase(kj::mv(node)) {} | ||||
|   // Second parameter prevent ambiguity with immediate-value constructor.
 | ||||
| 
 | ||||
|   template <typename> | ||||
|   friend class Promise; | ||||
|   friend class EventLoop; | ||||
|   template <typename U, typename Adapter, typename... Params> | ||||
|   friend Promise<U> newAdaptedPromise(Params&&... adapterConstructorParams); | ||||
|   template <typename U> | ||||
|   friend PromiseFulfillerPair<U> newPromiseAndFulfiller(); | ||||
|   template <typename> | ||||
|   friend class _::ForkHub; | ||||
|   friend class _::TaskSetImpl; | ||||
|   friend Promise<void> _::yield(); | ||||
|   friend class _::NeverDone; | ||||
|   template <typename U> | ||||
|   friend Promise<Array<U>> joinPromises(Array<Promise<U>>&& promises); | ||||
|   friend Promise<void> joinPromises(Array<Promise<void>>&& promises); | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class ForkedPromise { | ||||
|   // The result of `Promise::fork()` and `EventLoop::fork()`.  Allows branches to be created.
 | ||||
|   // Like `Promise<T>`, this is a pass-by-move type.
 | ||||
| 
 | ||||
| public: | ||||
|   inline ForkedPromise(decltype(nullptr)) {} | ||||
| 
 | ||||
|   Promise<T> addBranch(); | ||||
|   // Add a new branch to the fork.  The branch is equivalent to the original promise.
 | ||||
| 
 | ||||
| private: | ||||
|   Own<_::ForkHub<_::FixVoid<T>>> hub; | ||||
| 
 | ||||
|   inline ForkedPromise(bool, Own<_::ForkHub<_::FixVoid<T>>>&& hub): hub(kj::mv(hub)) {} | ||||
| 
 | ||||
|   friend class Promise<T>; | ||||
|   friend class EventLoop; | ||||
| }; | ||||
| 
 | ||||
| constexpr _::Void READY_NOW = _::Void(); | ||||
| // Use this when you need a Promise<void> that is already fulfilled -- this value can be implicitly
 | ||||
| // cast to `Promise<void>`.
 | ||||
| 
 | ||||
| constexpr _::NeverDone NEVER_DONE = _::NeverDone(); | ||||
| // The opposite of `READY_NOW`, return this when the promise should never resolve.  This can be
 | ||||
| // implicitly converted to any promise type.  You may also call `NEVER_DONE.wait()` to wait
 | ||||
| // forever (useful for servers).
 | ||||
| 
 | ||||
| template <typename Func> | ||||
| PromiseForResult<Func, void> evalLater(Func&& func) KJ_WARN_UNUSED_RESULT; | ||||
| // Schedule for the given zero-parameter function to be executed in the event loop at some
 | ||||
| // point in the near future.  Returns a Promise for its result -- or, if `func()` itself returns
 | ||||
| // a promise, `evalLater()` returns a Promise for the result of resolving that promise.
 | ||||
| //
 | ||||
| // Example usage:
 | ||||
| //     Promise<int> x = evalLater([]() { return 123; });
 | ||||
| //
 | ||||
| // The above is exactly equivalent to:
 | ||||
| //     Promise<int> x = Promise<void>(READY_NOW).then([]() { return 123; });
 | ||||
| //
 | ||||
| // If the returned promise is destroyed before the callback runs, the callback will be canceled
 | ||||
| // (never called).
 | ||||
| //
 | ||||
| // If you schedule several evaluations with `evalLater` during the same callback, they are
 | ||||
| // guaranteed to be executed in order.
 | ||||
| 
 | ||||
| template <typename Func> | ||||
| PromiseForResult<Func, void> evalNow(Func&& func) KJ_WARN_UNUSED_RESULT; | ||||
| // Run `func()` and return a promise for its result. `func()` executes before `evalNow()` returns.
 | ||||
| // If `func()` throws an exception, the exception is caught and wrapped in a promise -- this is the
 | ||||
| // main reason why `evalNow()` is useful.
 | ||||
| 
 | ||||
| template <typename T> | ||||
| Promise<Array<T>> joinPromises(Array<Promise<T>>&& promises); | ||||
| // Join an array of promises into a promise for an array.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Hack for creating a lambda that holds an owned pointer.
 | ||||
| 
 | ||||
| template <typename Func, typename MovedParam> | ||||
| class CaptureByMove { | ||||
| public: | ||||
|   inline CaptureByMove(Func&& func, MovedParam&& param) | ||||
|       : func(kj::mv(func)), param(kj::mv(param)) {} | ||||
| 
 | ||||
|   template <typename... Params> | ||||
|   inline auto operator()(Params&&... params) | ||||
|       -> decltype(kj::instance<Func>()(kj::instance<MovedParam&&>(), kj::fwd<Params>(params)...)) { | ||||
|     return func(kj::mv(param), kj::fwd<Params>(params)...); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   Func func; | ||||
|   MovedParam param; | ||||
| }; | ||||
| 
 | ||||
| template <typename Func, typename MovedParam> | ||||
| inline CaptureByMove<Func, Decay<MovedParam>> mvCapture(MovedParam&& param, Func&& func) { | ||||
|   // Hack to create a "lambda" which captures a variable by moving it rather than copying or
 | ||||
|   // referencing.  C++14 generalized captures should make this obsolete, but for now in C++11 this
 | ||||
|   // is commonly needed for Promise continuations that own their state.  Example usage:
 | ||||
|   //
 | ||||
|   //    Own<Foo> ptr = makeFoo();
 | ||||
|   //    Promise<int> promise = callRpc();
 | ||||
|   //    promise.then(mvCapture(ptr, [](Own<Foo>&& ptr, int result) {
 | ||||
|   //      return ptr->finish(result);
 | ||||
|   //    }));
 | ||||
| 
 | ||||
|   return CaptureByMove<Func, Decay<MovedParam>>(kj::fwd<Func>(func), kj::mv(param)); | ||||
| } | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Advanced promise construction
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class PromiseFulfiller { | ||||
|   // A callback which can be used to fulfill a promise.  Only the first call to fulfill() or
 | ||||
|   // reject() matters; subsequent calls are ignored.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual void fulfill(T&& value) = 0; | ||||
|   // Fulfill the promise with the given value.
 | ||||
| 
 | ||||
|   virtual void reject(Exception&& exception) = 0; | ||||
|   // Reject the promise with an error.
 | ||||
| 
 | ||||
|   virtual bool isWaiting() = 0; | ||||
|   // Returns true if the promise is still unfulfilled and someone is potentially waiting for it.
 | ||||
|   // Returns false if fulfill()/reject() has already been called *or* if the promise to be
 | ||||
|   // fulfilled has been discarded and therefore the result will never be used anyway.
 | ||||
| 
 | ||||
|   template <typename Func> | ||||
|   bool rejectIfThrows(Func&& func); | ||||
|   // Call the function (with no arguments) and return true.  If an exception is thrown, call
 | ||||
|   // `fulfiller.reject()` and then return false.  When compiled with exceptions disabled,
 | ||||
|   // non-fatal exceptions are still detected and handled correctly.
 | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| class PromiseFulfiller<void> { | ||||
|   // Specialization of PromiseFulfiller for void promises.  See PromiseFulfiller<T>.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual void fulfill(_::Void&& value = _::Void()) = 0; | ||||
|   // Call with zero parameters.  The parameter is a dummy that only exists so that subclasses don't
 | ||||
|   // have to specialize for <void>.
 | ||||
| 
 | ||||
|   virtual void reject(Exception&& exception) = 0; | ||||
|   virtual bool isWaiting() = 0; | ||||
| 
 | ||||
|   template <typename Func> | ||||
|   bool rejectIfThrows(Func&& func); | ||||
| }; | ||||
| 
 | ||||
| template <typename T, typename Adapter, typename... Params> | ||||
| Promise<T> newAdaptedPromise(Params&&... adapterConstructorParams); | ||||
| // Creates a new promise which owns an instance of `Adapter` which encapsulates the operation
 | ||||
| // that will eventually fulfill the promise.  This is primarily useful for adapting non-KJ
 | ||||
| // asynchronous APIs to use promises.
 | ||||
| //
 | ||||
| // An instance of `Adapter` will be allocated and owned by the returned `Promise`.  A
 | ||||
| // `PromiseFulfiller<T>&` will be passed as the first parameter to the adapter's constructor,
 | ||||
| // and `adapterConstructorParams` will be forwarded as the subsequent parameters.  The adapter
 | ||||
| // is expected to perform some asynchronous operation and call the `PromiseFulfiller<T>` once
 | ||||
| // it is finished.
 | ||||
| //
 | ||||
| // The adapter is destroyed when its owning Promise is destroyed.  This may occur before the
 | ||||
| // Promise has been fulfilled.  In this case, the adapter's destructor should cancel the
 | ||||
| // asynchronous operation.  Once the adapter is destroyed, the fulfillment callback cannot be
 | ||||
| // called.
 | ||||
| //
 | ||||
| // An adapter implementation should be carefully written to ensure that it cannot accidentally
 | ||||
| // be left unfulfilled permanently because of an exception.  Consider making liberal use of
 | ||||
| // `PromiseFulfiller<T>::rejectIfThrows()`.
 | ||||
| 
 | ||||
| template <typename T> | ||||
| struct PromiseFulfillerPair { | ||||
|   Promise<_::JoinPromises<T>> promise; | ||||
|   Own<PromiseFulfiller<T>> fulfiller; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| PromiseFulfillerPair<T> newPromiseAndFulfiller(); | ||||
| // Construct a Promise and a separate PromiseFulfiller which can be used to fulfill the promise.
 | ||||
| // If the PromiseFulfiller is destroyed before either of its methods are called, the Promise is
 | ||||
| // implicitly rejected.
 | ||||
| //
 | ||||
| // Although this function is easier to use than `newAdaptedPromise()`, it has the serious drawback
 | ||||
| // that there is no way to handle cancellation (i.e. detect when the Promise is discarded).
 | ||||
| //
 | ||||
| // You can arrange to fulfill a promise with another promise by using a promise type for T.  E.g.
 | ||||
| // `newPromiseAndFulfiller<Promise<U>>()` will produce a promise of type `Promise<U>` but the
 | ||||
| // fulfiller will be of type `PromiseFulfiller<Promise<U>>`.  Thus you pass a `Promise<U>` to the
 | ||||
| // `fulfill()` callback, and the promises are chained.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // TaskSet
 | ||||
| 
 | ||||
| class TaskSet { | ||||
|   // Holds a collection of Promise<void>s and ensures that each executes to completion.  Memory
 | ||||
|   // associated with each promise is automatically freed when the promise completes.  Destroying
 | ||||
|   // the TaskSet itself automatically cancels all unfinished promises.
 | ||||
|   //
 | ||||
|   // This is useful for "daemon" objects that perform background tasks which aren't intended to
 | ||||
|   // fulfill any particular external promise, but which may need to be canceled (and thus can't
 | ||||
|   // use `Promise::detach()`).  The daemon object holds a TaskSet to collect these tasks it is
 | ||||
|   // working on.  This way, if the daemon itself is destroyed, the TaskSet is detroyed as well,
 | ||||
|   // and everything the daemon is doing is canceled.
 | ||||
| 
 | ||||
| public: | ||||
|   class ErrorHandler { | ||||
|   public: | ||||
|     virtual void taskFailed(kj::Exception&& exception) = 0; | ||||
|   }; | ||||
| 
 | ||||
|   TaskSet(ErrorHandler& errorHandler); | ||||
|   // `loop` will be used to wait on promises.  `errorHandler` will be executed any time a task
 | ||||
|   // throws an exception, and will execute within the given EventLoop.
 | ||||
| 
 | ||||
|   ~TaskSet() noexcept(false); | ||||
| 
 | ||||
|   void add(Promise<void>&& promise); | ||||
| 
 | ||||
|   kj::String trace(); | ||||
|   // Return debug info about all promises currently in the TaskSet.
 | ||||
| 
 | ||||
| private: | ||||
|   Own<_::TaskSetImpl> impl; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // The EventLoop class
 | ||||
| 
 | ||||
| class EventPort { | ||||
|   // Interfaces between an `EventLoop` and events originating from outside of the loop's thread.
 | ||||
|   // All such events come in through the `EventPort` implementation.
 | ||||
|   //
 | ||||
|   // An `EventPort` implementation may interface with low-level operating system APIs and/or other
 | ||||
|   // threads.  You can also write an `EventPort` which wraps some other (non-KJ) event loop
 | ||||
|   // framework, allowing the two to coexist in a single thread.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual bool wait() = 0; | ||||
|   // Wait for an external event to arrive, sleeping if necessary.  Once at least one event has
 | ||||
|   // arrived, queue it to the event loop (e.g. by fulfilling a promise) and return.
 | ||||
|   //
 | ||||
|   // This is called during `Promise::wait()` whenever the event queue becomes empty, in order to
 | ||||
|   // wait for new events to populate the queue.
 | ||||
|   //
 | ||||
|   // It is safe to return even if nothing has actually been queued, so long as calling `wait()` in
 | ||||
|   // a loop will eventually sleep.  (That is to say, false positives are fine.)
 | ||||
|   //
 | ||||
|   // Returns true if wake() has been called from another thread. (Precisely, returns true if
 | ||||
|   // no previous call to wait `wait()` nor `poll()` has returned true since `wake()` was last
 | ||||
|   // called.)
 | ||||
| 
 | ||||
|   virtual bool poll() = 0; | ||||
|   // Check if any external events have arrived, but do not sleep.  If any events have arrived,
 | ||||
|   // add them to the event queue (e.g. by fulfilling promises) before returning.
 | ||||
|   //
 | ||||
|   // This may be called during `Promise::wait()` when the EventLoop has been executing for a while
 | ||||
|   // without a break but is still non-empty.
 | ||||
|   //
 | ||||
|   // Returns true if wake() has been called from another thread. (Precisely, returns true if
 | ||||
|   // no previous call to wait `wait()` nor `poll()` has returned true since `wake()` was last
 | ||||
|   // called.)
 | ||||
| 
 | ||||
|   virtual void setRunnable(bool runnable); | ||||
|   // Called to notify the `EventPort` when the `EventLoop` has work to do; specifically when it
 | ||||
|   // transitions from empty -> runnable or runnable -> empty.  This is typically useful when
 | ||||
|   // integrating with an external event loop; if the loop is currently runnable then you should
 | ||||
|   // arrange to call run() on it soon.  The default implementation does nothing.
 | ||||
| 
 | ||||
|   virtual void wake() const; | ||||
|   // Wake up the EventPort's thread from another thread.
 | ||||
|   //
 | ||||
|   // Unlike all other methods on this interface, `wake()` may be called from another thread, hence
 | ||||
|   // it is `const`.
 | ||||
|   //
 | ||||
|   // Technically speaking, `wake()` causes the target thread to cease sleeping and not to sleep
 | ||||
|   // again until `wait()` or `poll()` has returned true at least once.
 | ||||
|   //
 | ||||
|   // The default implementation throws an UNIMPLEMENTED exception.
 | ||||
| }; | ||||
| 
 | ||||
| class EventLoop { | ||||
|   // Represents a queue of events being executed in a loop.  Most code won't interact with
 | ||||
|   // EventLoop directly, but instead use `Promise`s to interact with it indirectly.  See the
 | ||||
|   // documentation for `Promise`.
 | ||||
|   //
 | ||||
|   // Each thread can have at most one current EventLoop.  To make an `EventLoop` current for
 | ||||
|   // the thread, create a `WaitScope`.  Async APIs require that the thread has a current EventLoop,
 | ||||
|   // or they will throw exceptions.  APIs that use `Promise::wait()` additionally must explicitly
 | ||||
|   // be passed a reference to the `WaitScope` to make the caller aware that they might block.
 | ||||
|   //
 | ||||
|   // Generally, you will want to construct an `EventLoop` at the top level of your program, e.g.
 | ||||
|   // in the main() function, or in the start function of a thread.  You can then use it to
 | ||||
|   // construct some promises and wait on the result.  Example:
 | ||||
|   //
 | ||||
|   //     int main() {
 | ||||
|   //       // `loop` becomes the official EventLoop for the thread.
 | ||||
|   //       MyEventPort eventPort;
 | ||||
|   //       EventLoop loop(eventPort);
 | ||||
|   //
 | ||||
|   //       // Now we can call an async function.
 | ||||
|   //       Promise<String> textPromise = getHttp("http://example.com");
 | ||||
|   //
 | ||||
|   //       // And we can wait for the promise to complete.  Note that you can only use `wait()`
 | ||||
|   //       // from the top level, not from inside a promise callback.
 | ||||
|   //       String text = textPromise.wait();
 | ||||
|   //       print(text);
 | ||||
|   //       return 0;
 | ||||
|   //     }
 | ||||
|   //
 | ||||
|   // Most applications that do I/O will prefer to use `setupAsyncIo()` from `async-io.h` rather
 | ||||
|   // than allocate an `EventLoop` directly.
 | ||||
| 
 | ||||
| public: | ||||
|   EventLoop(); | ||||
|   // Construct an `EventLoop` which does not receive external events at all.
 | ||||
| 
 | ||||
|   explicit EventLoop(EventPort& port); | ||||
|   // Construct an `EventLoop` which receives external events through the given `EventPort`.
 | ||||
| 
 | ||||
|   ~EventLoop() noexcept(false); | ||||
| 
 | ||||
|   void run(uint maxTurnCount = maxValue); | ||||
|   // Run the event loop for `maxTurnCount` turns or until there is nothing left to be done,
 | ||||
|   // whichever comes first.  This never calls the `EventPort`'s `sleep()` or `poll()`.  It will
 | ||||
|   // call the `EventPort`'s `setRunnable(false)` if the queue becomes empty.
 | ||||
| 
 | ||||
|   bool isRunnable(); | ||||
|   // Returns true if run() would currently do anything, or false if the queue is empty.
 | ||||
| 
 | ||||
| private: | ||||
|   EventPort& port; | ||||
| 
 | ||||
|   bool running = false; | ||||
|   // True while looping -- wait() is then not allowed.
 | ||||
| 
 | ||||
|   bool lastRunnableState = false; | ||||
|   // What did we last pass to port.setRunnable()?
 | ||||
| 
 | ||||
|   _::Event* head = nullptr; | ||||
|   _::Event** tail = &head; | ||||
|   _::Event** depthFirstInsertPoint = &head; | ||||
| 
 | ||||
|   Own<_::TaskSetImpl> daemons; | ||||
| 
 | ||||
|   bool turn(); | ||||
|   void setRunnable(bool runnable); | ||||
|   void enterScope(); | ||||
|   void leaveScope(); | ||||
| 
 | ||||
|   friend void _::detach(kj::Promise<void>&& promise); | ||||
|   friend void _::waitImpl(Own<_::PromiseNode>&& node, _::ExceptionOrValue& result, | ||||
|                           WaitScope& waitScope); | ||||
|   friend class _::Event; | ||||
|   friend class WaitScope; | ||||
| }; | ||||
| 
 | ||||
| class WaitScope { | ||||
|   // Represents a scope in which asynchronous programming can occur.  A `WaitScope` should usually
 | ||||
|   // be allocated on the stack and serves two purposes:
 | ||||
|   // * While the `WaitScope` exists, its `EventLoop` is registered as the current loop for the
 | ||||
|   //   thread.  Most operations dealing with `Promise` (including all of its methods) do not work
 | ||||
|   //   unless the thread has a current `EventLoop`.
 | ||||
|   // * `WaitScope` may be passed to `Promise::wait()` to synchronously wait for a particular
 | ||||
|   //   promise to complete.  See `Promise::wait()` for an extended discussion.
 | ||||
| 
 | ||||
| public: | ||||
|   inline explicit WaitScope(EventLoop& loop): loop(loop) { loop.enterScope(); } | ||||
|   inline ~WaitScope() { loop.leaveScope(); } | ||||
|   KJ_DISALLOW_COPY(WaitScope); | ||||
| 
 | ||||
| private: | ||||
|   EventLoop& loop; | ||||
|   friend class EventLoop; | ||||
|   friend void _::waitImpl(Own<_::PromiseNode>&& node, _::ExceptionOrValue& result, | ||||
|                           WaitScope& waitScope); | ||||
| }; | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #include "async-inl.h" | ||||
| 
 | ||||
| #endif  // KJ_ASYNC_H_
 | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -0,0 +1,122 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_COMPAT_GTEST_H_ | ||||
| #define KJ_COMPAT_GTEST_H_ | ||||
| // This file defines compatibility macros converting Google Test tests into KJ tests.
 | ||||
| //
 | ||||
| // This is only intended to cover the most common functionality. Many tests will likely need
 | ||||
| // additional tweaks. For instance:
 | ||||
| // - Using operator<< to print information on failure is not supported. Instead, switch to
 | ||||
| //   KJ_ASSERT/KJ_EXPECT and pass in stuff to print as additional parameters.
 | ||||
| // - Test fixtures are not supported. Allocate your "test fixture" on the stack instead. Do setup
 | ||||
| //   in the constructor, teardown in the destructor.
 | ||||
| 
 | ||||
| #include "../test.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T> | ||||
| T abs(T value) { return value < 0 ? -value : value; } | ||||
| 
 | ||||
| inline bool floatAlmostEqual(float a, float b) { | ||||
|   return a == b || abs(a - b) < (abs(a) + abs(b)) * 1e-5; | ||||
| } | ||||
| 
 | ||||
| inline bool doubleAlmostEqual(double a, double b) { | ||||
|   return a == b || abs(a - b) < (abs(a) + abs(b)) * 1e-12; | ||||
| } | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| #define EXPECT_FALSE(x) KJ_EXPECT(!(x)) | ||||
| #define EXPECT_TRUE(x) KJ_EXPECT(x) | ||||
| #define EXPECT_EQ(x, y) KJ_EXPECT((x) == (y), x, y) | ||||
| #define EXPECT_NE(x, y) KJ_EXPECT((x) != (y), x, y) | ||||
| #define EXPECT_LE(x, y) KJ_EXPECT((x) <= (y), x, y) | ||||
| #define EXPECT_GE(x, y) KJ_EXPECT((x) >= (y), x, y) | ||||
| #define EXPECT_LT(x, y) KJ_EXPECT((x) <  (y), x, y) | ||||
| #define EXPECT_GT(x, y) KJ_EXPECT((x) >  (y), x, y) | ||||
| #define EXPECT_STREQ(x, y) KJ_EXPECT(::strcmp(x, y) == 0, x, y) | ||||
| #define EXPECT_FLOAT_EQ(x, y) KJ_EXPECT(::kj::_::floatAlmostEqual(y, x), y, x); | ||||
| #define EXPECT_DOUBLE_EQ(x, y) KJ_EXPECT(::kj::_::doubleAlmostEqual(y, x), y, x); | ||||
| 
 | ||||
| #define ASSERT_FALSE(x) KJ_ASSERT(!(x)) | ||||
| #define ASSERT_TRUE(x) KJ_ASSERT(x) | ||||
| #define ASSERT_EQ(x, y) KJ_ASSERT((x) == (y), x, y) | ||||
| #define ASSERT_NE(x, y) KJ_ASSERT((x) != (y), x, y) | ||||
| #define ASSERT_LE(x, y) KJ_ASSERT((x) <= (y), x, y) | ||||
| #define ASSERT_GE(x, y) KJ_ASSERT((x) >= (y), x, y) | ||||
| #define ASSERT_LT(x, y) KJ_ASSERT((x) <  (y), x, y) | ||||
| #define ASSERT_GT(x, y) KJ_ASSERT((x) >  (y), x, y) | ||||
| #define ASSERT_STREQ(x, y) KJ_ASSERT(::strcmp(x, y) == 0, x, y) | ||||
| #define ASSERT_FLOAT_EQ(x, y) KJ_ASSERT(::kj::_::floatAlmostEqual(y, x), y, x); | ||||
| #define ASSERT_DOUBLE_EQ(x, y) KJ_ASSERT(::kj::_::doubleAlmostEqual(y, x), y, x); | ||||
| 
 | ||||
| class AddFailureAdapter { | ||||
| public: | ||||
|   AddFailureAdapter(const char* file, int line): file(file), line(line) {} | ||||
| 
 | ||||
|   ~AddFailureAdapter() { | ||||
|     if (!handled) { | ||||
|       _::Debug::log(file, line, LogSeverity::ERROR, "expectation failed"); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   void operator<<(T&& info) { | ||||
|     handled = true; | ||||
|     _::Debug::log(file, line, LogSeverity::ERROR, "\"expectation failed\", info", | ||||
|                   "expectation failed", kj::fwd<T>(info)); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   bool handled = false; | ||||
|   const char* file; | ||||
|   int line; | ||||
| }; | ||||
| 
 | ||||
| #define ADD_FAILURE() ::kj::AddFailureAdapter(__FILE__, __LINE__) | ||||
| 
 | ||||
| #if KJ_NO_EXCEPTIONS | ||||
| #define EXPECT_ANY_THROW(code) \ | ||||
|     KJ_EXPECT(::kj::_::expectFatalThrow(nullptr, nullptr, [&]() { code; })) | ||||
| #else | ||||
| #define EXPECT_ANY_THROW(code) \ | ||||
|     KJ_EXPECT(::kj::runCatchingExceptions([&]() { code; }) != nullptr) | ||||
| #endif | ||||
| 
 | ||||
| #define EXPECT_NONFATAL_FAILURE(code) \ | ||||
|   EXPECT_TRUE(kj::runCatchingExceptions([&]() { code; }) != nullptr); | ||||
| 
 | ||||
| #ifdef KJ_DEBUG | ||||
| #define EXPECT_DEBUG_ANY_THROW EXPECT_ANY_THROW | ||||
| #else | ||||
| #define EXPECT_DEBUG_ANY_THROW(EXP) | ||||
| #endif | ||||
| 
 | ||||
| #define TEST(x, y) KJ_TEST("legacy test: " #x "/" #y) | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_COMPAT_GTEST_H_
 | ||||
| @ -0,0 +1,636 @@ | ||||
| // Copyright (c) 2017 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_COMPAT_HTTP_H_ | ||||
| #define KJ_COMPAT_HTTP_H_ | ||||
| // The KJ HTTP client/server library.
 | ||||
| //
 | ||||
| // This is a simple library which can be used to implement an HTTP client or server. Properties
 | ||||
| // of this library include:
 | ||||
| // - Uses KJ async framework.
 | ||||
| // - Agnostic to transport layer -- you can provide your own.
 | ||||
| // - Header parsing is zero-copy -- it results in strings that point directly into the buffer
 | ||||
| //   received off the wire.
 | ||||
| // - Application code which reads and writes headers refers to headers by symbolic names, not by
 | ||||
| //   string literals, with lookups being array-index-based, not map-based. To make this possible,
 | ||||
| //   the application announces what headers it cares about in advance, in order to assign numeric
 | ||||
| //   values to them.
 | ||||
| // - Methods are identified by an enum.
 | ||||
| 
 | ||||
| #include <kj/string.h> | ||||
| #include <kj/vector.h> | ||||
| #include <kj/memory.h> | ||||
| #include <kj/one-of.h> | ||||
| #include <kj/async-io.h> | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| #define KJ_HTTP_FOR_EACH_METHOD(MACRO) \ | ||||
|   MACRO(GET) \
 | ||||
|   MACRO(HEAD) \
 | ||||
|   MACRO(POST) \
 | ||||
|   MACRO(PUT) \
 | ||||
|   MACRO(DELETE) \
 | ||||
|   MACRO(PATCH) \
 | ||||
|   MACRO(PURGE) \
 | ||||
|   MACRO(OPTIONS) \
 | ||||
|   MACRO(TRACE) \
 | ||||
|   /* standard methods */ \
 | ||||
|   /* */ \
 | ||||
|   /* (CONNECT is intentionally omitted since it is handled specially in HttpHandler) */ \
 | ||||
|   \
 | ||||
|   MACRO(COPY) \
 | ||||
|   MACRO(LOCK) \
 | ||||
|   MACRO(MKCOL) \
 | ||||
|   MACRO(MOVE) \
 | ||||
|   MACRO(PROPFIND) \
 | ||||
|   MACRO(PROPPATCH) \
 | ||||
|   MACRO(SEARCH) \
 | ||||
|   MACRO(UNLOCK) \
 | ||||
|   /* WebDAV */ \
 | ||||
|   \
 | ||||
|   MACRO(REPORT) \
 | ||||
|   MACRO(MKACTIVITY) \
 | ||||
|   MACRO(CHECKOUT) \
 | ||||
|   MACRO(MERGE) \
 | ||||
|   /* Subversion */ \
 | ||||
|   \
 | ||||
|   MACRO(MSEARCH) \
 | ||||
|   MACRO(NOTIFY) \
 | ||||
|   MACRO(SUBSCRIBE) \
 | ||||
|   MACRO(UNSUBSCRIBE) | ||||
|   /* UPnP */ | ||||
| 
 | ||||
| #define KJ_HTTP_FOR_EACH_CONNECTION_HEADER(MACRO) \ | ||||
|   MACRO(connection, "Connection") \
 | ||||
|   MACRO(contentLength, "Content-Length") \
 | ||||
|   MACRO(keepAlive, "Keep-Alive") \
 | ||||
|   MACRO(te, "TE") \
 | ||||
|   MACRO(trailer, "Trailer") \
 | ||||
|   MACRO(transferEncoding, "Transfer-Encoding") \
 | ||||
|   MACRO(upgrade, "Upgrade") | ||||
| 
 | ||||
| enum class HttpMethod { | ||||
|   // Enum of known HTTP methods.
 | ||||
|   //
 | ||||
|   // We use an enum rather than a string to allow for faster parsing and switching and to reduce
 | ||||
|   // ambiguity.
 | ||||
| 
 | ||||
| #define DECLARE_METHOD(id) id, | ||||
| KJ_HTTP_FOR_EACH_METHOD(DECLARE_METHOD) | ||||
| #undef DECLARE_METHOD | ||||
| }; | ||||
| 
 | ||||
| kj::StringPtr KJ_STRINGIFY(HttpMethod method); | ||||
| kj::Maybe<HttpMethod> tryParseHttpMethod(kj::StringPtr name); | ||||
| 
 | ||||
| class HttpHeaderTable; | ||||
| 
 | ||||
| class HttpHeaderId { | ||||
|   // Identifies an HTTP header by numeric ID that indexes into an HttpHeaderTable.
 | ||||
|   //
 | ||||
|   // The KJ HTTP API prefers that headers be identified by these IDs for a few reasons:
 | ||||
|   // - Integer lookups are much more efficient than string lookups.
 | ||||
|   // - Case-insensitivity is awkward to deal with when const strings are being passed to the lookup
 | ||||
|   //   method.
 | ||||
|   // - Writing out strings less often means fewer typos.
 | ||||
|   //
 | ||||
|   // See HttpHeaderTable for usage hints.
 | ||||
| 
 | ||||
| public: | ||||
|   HttpHeaderId() = default; | ||||
| 
 | ||||
|   inline bool operator==(const HttpHeaderId& other) const { return id == other.id; } | ||||
|   inline bool operator!=(const HttpHeaderId& other) const { return id != other.id; } | ||||
|   inline bool operator< (const HttpHeaderId& other) const { return id <  other.id; } | ||||
|   inline bool operator> (const HttpHeaderId& other) const { return id >  other.id; } | ||||
|   inline bool operator<=(const HttpHeaderId& other) const { return id <= other.id; } | ||||
|   inline bool operator>=(const HttpHeaderId& other) const { return id >= other.id; } | ||||
| 
 | ||||
|   inline size_t hashCode() const { return id; } | ||||
| 
 | ||||
|   kj::StringPtr toString() const; | ||||
| 
 | ||||
|   void requireFrom(HttpHeaderTable& table) const; | ||||
|   // In debug mode, throws an exception if the HttpHeaderId is not from the given table.
 | ||||
|   //
 | ||||
|   // In opt mode, no-op.
 | ||||
| 
 | ||||
| #define KJ_HTTP_FOR_EACH_BUILTIN_HEADER(MACRO) \ | ||||
|   MACRO(HOST, "Host") \
 | ||||
|   MACRO(DATE, "Date") \
 | ||||
|   MACRO(LOCATION, "Location") \
 | ||||
|   MACRO(CONTENT_TYPE, "Content-Type") | ||||
|   // For convenience, these very-common headers are valid for all HttpHeaderTables. You can refer
 | ||||
|   // to them like:
 | ||||
|   //
 | ||||
|   //     HttpHeaderId::HOST
 | ||||
|   //
 | ||||
|   // TODO(0.7): Fill this out with more common headers.
 | ||||
| 
 | ||||
| #define DECLARE_HEADER(id, name) \ | ||||
|   static const HttpHeaderId id; | ||||
|   // Declare a constant for each builtin header, e.g.: HttpHeaderId::CONNECTION
 | ||||
| 
 | ||||
|   KJ_HTTP_FOR_EACH_BUILTIN_HEADER(DECLARE_HEADER); | ||||
| #undef DECLARE_HEADER | ||||
| 
 | ||||
| private: | ||||
|   HttpHeaderTable* table; | ||||
|   uint id; | ||||
| 
 | ||||
|   inline explicit constexpr HttpHeaderId(HttpHeaderTable* table, uint id): table(table), id(id) {} | ||||
|   friend class HttpHeaderTable; | ||||
|   friend class HttpHeaders; | ||||
| }; | ||||
| 
 | ||||
| class HttpHeaderTable { | ||||
|   // Construct an HttpHeaderTable to declare which headers you'll be interested in later on, and
 | ||||
|   // to manufacture IDs for them.
 | ||||
|   //
 | ||||
|   // Example:
 | ||||
|   //
 | ||||
|   //     // Build a header table with the headers we are interested in.
 | ||||
|   //     kj::HttpHeaderTable::Builder builder;
 | ||||
|   //     const HttpHeaderId accept = builder.add("Accept");
 | ||||
|   //     const HttpHeaderId contentType = builder.add("Content-Type");
 | ||||
|   //     kj::HttpHeaderTable table(kj::mv(builder));
 | ||||
|   //
 | ||||
|   //     // Create an HTTP client.
 | ||||
|   //     auto client = kj::newHttpClient(table, network);
 | ||||
|   //
 | ||||
|   //     // Get http://example.com.
 | ||||
|   //     HttpHeaders headers(table);
 | ||||
|   //     headers.set(accept, "text/html");
 | ||||
|   //     auto response = client->send(kj::HttpMethod::GET, "http://example.com", headers)
 | ||||
|   //         .wait(waitScope);
 | ||||
|   //     auto msg = kj::str("Response content type: ", response.headers.get(contentType));
 | ||||
| 
 | ||||
|   struct IdsByNameMap; | ||||
| 
 | ||||
| public: | ||||
|   HttpHeaderTable(); | ||||
|   // Constructs a table that only contains the builtin headers.
 | ||||
| 
 | ||||
|   class Builder { | ||||
|   public: | ||||
|     Builder(); | ||||
|     HttpHeaderId add(kj::StringPtr name); | ||||
|     Own<HttpHeaderTable> build(); | ||||
| 
 | ||||
|     HttpHeaderTable& getFutureTable(); | ||||
|     // Get the still-unbuilt header table. You cannot actually use it until build() has been
 | ||||
|     // called.
 | ||||
|     //
 | ||||
|     // This method exists to help when building a shared header table -- the Builder may be passed
 | ||||
|     // to several components, each of which will register the headers they need and get a reference
 | ||||
|     // to the future table.
 | ||||
| 
 | ||||
|   private: | ||||
|     kj::Own<HttpHeaderTable> table; | ||||
|   }; | ||||
| 
 | ||||
|   KJ_DISALLOW_COPY(HttpHeaderTable);  // Can't copy because HttpHeaderId points to the table.
 | ||||
|   ~HttpHeaderTable() noexcept(false); | ||||
| 
 | ||||
|   uint idCount(); | ||||
|   // Return the number of IDs in the table.
 | ||||
| 
 | ||||
|   kj::Maybe<HttpHeaderId> stringToId(kj::StringPtr name); | ||||
|   // Try to find an ID for the given name. The matching is case-insensitive, per the HTTP spec.
 | ||||
|   //
 | ||||
|   // Note: if `name` contains characters that aren't allowed in HTTP header names, this may return
 | ||||
|   //   a bogus value rather than null, due to optimizations used in case-insensitive matching.
 | ||||
| 
 | ||||
|   kj::StringPtr idToString(HttpHeaderId id); | ||||
|   // Get the canonical string name for the given ID.
 | ||||
| 
 | ||||
| private: | ||||
|   kj::Vector<kj::StringPtr> namesById; | ||||
|   kj::Own<IdsByNameMap> idsByName; | ||||
| }; | ||||
| 
 | ||||
| class HttpHeaders { | ||||
|   // Represents a set of HTTP headers.
 | ||||
|   //
 | ||||
|   // This class guards against basic HTTP header injection attacks: Trying to set a header name or
 | ||||
|   // value containing a newline, carriage return, or other invalid character will throw an
 | ||||
|   // exception.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit HttpHeaders(HttpHeaderTable& table); | ||||
| 
 | ||||
|   KJ_DISALLOW_COPY(HttpHeaders); | ||||
|   HttpHeaders(HttpHeaders&&) = default; | ||||
|   HttpHeaders& operator=(HttpHeaders&&) = default; | ||||
| 
 | ||||
|   void clear(); | ||||
|   // Clears all contents, as if the object was freshly-allocated. However, calling this rather
 | ||||
|   // than actually re-allocating the object may avoid re-allocation of internal objects.
 | ||||
| 
 | ||||
|   HttpHeaders clone() const; | ||||
|   // Creates a deep clone of the HttpHeaders. The returned object owns all strings it references.
 | ||||
| 
 | ||||
|   HttpHeaders cloneShallow() const; | ||||
|   // Creates a shallow clone of the HttpHeaders. The returned object references the same strings
 | ||||
|   // as the original, owning none of them.
 | ||||
| 
 | ||||
|   kj::Maybe<kj::StringPtr> get(HttpHeaderId id) const; | ||||
|   // Read a header.
 | ||||
| 
 | ||||
|   template <typename Func> | ||||
|   void forEach(Func&& func) const; | ||||
|   // Calls `func(name, value)` for each header in the set -- including headers that aren't mapped
 | ||||
|   // to IDs in the header table. Both inputs are of type kj::StringPtr.
 | ||||
| 
 | ||||
|   void set(HttpHeaderId id, kj::StringPtr value); | ||||
|   void set(HttpHeaderId id, kj::String&& value); | ||||
|   // Sets a header value, overwriting the existing value.
 | ||||
|   //
 | ||||
|   // The String&& version is equivalent to calling the other version followed by takeOwnership().
 | ||||
|   //
 | ||||
|   // WARNING: It is the caller's responsibility to ensure that `value` remains valid until the
 | ||||
|   //   HttpHeaders object is destroyed. This allows string literals to be passed without making a
 | ||||
|   //   copy, but complicates the use of dynamic values. Hint: Consider using `takeOwnership()`.
 | ||||
| 
 | ||||
|   void add(kj::StringPtr name, kj::StringPtr value); | ||||
|   void add(kj::StringPtr name, kj::String&& value); | ||||
|   void add(kj::String&& name, kj::String&& value); | ||||
|   // Append a header. `name` will be looked up in the header table, but if it's not mapped, the
 | ||||
|   // header will be added to the list of unmapped headers.
 | ||||
|   //
 | ||||
|   // The String&& versions are equivalent to calling the other version followed by takeOwnership().
 | ||||
|   //
 | ||||
|   // WARNING: It is the caller's responsibility to ensure that `name` and `value` remain valid
 | ||||
|   //   until the HttpHeaders object is destroyed. This allows string literals to be passed without
 | ||||
|   //   making a copy, but complicates the use of dynamic values. Hint: Consider using
 | ||||
|   //   `takeOwnership()`.
 | ||||
| 
 | ||||
|   void unset(HttpHeaderId id); | ||||
|   // Removes a header.
 | ||||
|   //
 | ||||
|   // It's not possible to remove a header by string name because non-indexed headers would take
 | ||||
|   // O(n) time to remove. Instead, construct a new HttpHeaders object and copy contents.
 | ||||
| 
 | ||||
|   void takeOwnership(kj::String&& string); | ||||
|   void takeOwnership(kj::Array<char>&& chars); | ||||
|   void takeOwnership(HttpHeaders&& otherHeaders); | ||||
|   // Takes overship of a string so that it lives until the HttpHeaders object is destroyed. Useful
 | ||||
|   // when you've passed a dynamic value to set() or add() or parse*().
 | ||||
| 
 | ||||
|   struct ConnectionHeaders { | ||||
|     // These headers govern details of the specific HTTP connection or framing of the content.
 | ||||
|     // Hence, they are managed internally within the HTTP library, and never appear in an
 | ||||
|     // HttpHeaders structure.
 | ||||
| 
 | ||||
| #define DECLARE_HEADER(id, name) \ | ||||
|     kj::StringPtr id; | ||||
|     KJ_HTTP_FOR_EACH_CONNECTION_HEADER(DECLARE_HEADER) | ||||
| #undef DECLARE_HEADER | ||||
|   }; | ||||
| 
 | ||||
|   struct Request { | ||||
|     HttpMethod method; | ||||
|     kj::StringPtr url; | ||||
|     ConnectionHeaders connectionHeaders; | ||||
|   }; | ||||
|   struct Response { | ||||
|     uint statusCode; | ||||
|     kj::StringPtr statusText; | ||||
|     ConnectionHeaders connectionHeaders; | ||||
|   }; | ||||
| 
 | ||||
|   kj::Maybe<Request> tryParseRequest(kj::ArrayPtr<char> content); | ||||
|   kj::Maybe<Response> tryParseResponse(kj::ArrayPtr<char> content); | ||||
|   // Parse an HTTP header blob and add all the headers to this object.
 | ||||
|   //
 | ||||
|   // `content` should be all text from the start of the request to the first occurrance of two
 | ||||
|   // newlines in a row -- including the first of these two newlines, but excluding the second.
 | ||||
|   //
 | ||||
|   // The parse is performed with zero copies: The callee clobbers `content` with '\0' characters
 | ||||
|   // to split it into a bunch of shorter strings. The caller must keep `content` valid until the
 | ||||
|   // `HttpHeaders` is destroyed, or pass it to `takeOwnership()`.
 | ||||
| 
 | ||||
|   kj::String serializeRequest(HttpMethod method, kj::StringPtr url, | ||||
|                               const ConnectionHeaders& connectionHeaders) const; | ||||
|   kj::String serializeResponse(uint statusCode, kj::StringPtr statusText, | ||||
|                                const ConnectionHeaders& connectionHeaders) const; | ||||
|   // Serialize the headers as a complete request or response blob. The blob uses '\r\n' newlines
 | ||||
|   // and includes the double-newline to indicate the end of the headers.
 | ||||
| 
 | ||||
|   kj::String toString() const; | ||||
| 
 | ||||
| private: | ||||
|   HttpHeaderTable* table; | ||||
| 
 | ||||
|   kj::Array<kj::StringPtr> indexedHeaders; | ||||
|   // Size is always table->idCount().
 | ||||
| 
 | ||||
|   struct Header { | ||||
|     kj::StringPtr name; | ||||
|     kj::StringPtr value; | ||||
|   }; | ||||
|   kj::Vector<Header> unindexedHeaders; | ||||
| 
 | ||||
|   kj::Vector<kj::Array<char>> ownedStrings; | ||||
| 
 | ||||
|   kj::Maybe<uint> addNoCheck(kj::StringPtr name, kj::StringPtr value); | ||||
| 
 | ||||
|   kj::StringPtr cloneToOwn(kj::StringPtr str); | ||||
| 
 | ||||
|   kj::String serialize(kj::ArrayPtr<const char> word1, | ||||
|                        kj::ArrayPtr<const char> word2, | ||||
|                        kj::ArrayPtr<const char> word3, | ||||
|                        const ConnectionHeaders& connectionHeaders) const; | ||||
| 
 | ||||
|   bool parseHeaders(char* ptr, char* end, ConnectionHeaders& connectionHeaders); | ||||
| 
 | ||||
|   // TODO(perf): Arguably we should store a map, but header sets are never very long
 | ||||
|   // TODO(perf): We could optimize for common headers by storing them directly as fields. We could
 | ||||
|   //   also add direct accessors for those headers.
 | ||||
| }; | ||||
| 
 | ||||
| class WebSocket { | ||||
| public: | ||||
|   WebSocket(kj::Own<kj::AsyncIoStream> stream); | ||||
|   // Create a WebSocket wrapping the given I/O stream.
 | ||||
| 
 | ||||
|   kj::Promise<void> send(kj::ArrayPtr<const byte> message); | ||||
|   kj::Promise<void> send(kj::ArrayPtr<const char> message); | ||||
| }; | ||||
| 
 | ||||
| class HttpClient { | ||||
|   // Interface to the client end of an HTTP connection.
 | ||||
|   //
 | ||||
|   // There are two kinds of clients:
 | ||||
|   // * Host clients are used when talking to a specific host. The `url` specified in a request
 | ||||
|   //   is actually just a path. (A `Host` header is still required in all requests.)
 | ||||
|   // * Proxy clients are used when the target could be any arbitrary host on the internet.
 | ||||
|   //   The `url` specified in a request is a full URL including protocol and hostname.
 | ||||
| 
 | ||||
| public: | ||||
|   struct Response { | ||||
|     uint statusCode; | ||||
|     kj::StringPtr statusText; | ||||
|     const HttpHeaders* headers; | ||||
|     kj::Own<kj::AsyncInputStream> body; | ||||
|     // `statusText` and `headers` remain valid until `body` is dropped.
 | ||||
|   }; | ||||
| 
 | ||||
|   struct Request { | ||||
|     kj::Own<kj::AsyncOutputStream> body; | ||||
|     // Write the request entity body to this stream, then drop it when done.
 | ||||
|     //
 | ||||
|     // May be null for GET and HEAD requests (which have no body) and requests that have
 | ||||
|     // Content-Length: 0.
 | ||||
| 
 | ||||
|     kj::Promise<Response> response; | ||||
|     // Promise for the eventual respnose.
 | ||||
|   }; | ||||
| 
 | ||||
|   virtual Request request(HttpMethod method, kj::StringPtr url, const HttpHeaders& headers, | ||||
|                           kj::Maybe<uint64_t> expectedBodySize = nullptr) = 0; | ||||
|   // Perform an HTTP request.
 | ||||
|   //
 | ||||
|   // `url` may be a full URL (with protocol and host) or it may be only the path part of the URL,
 | ||||
|   // depending on whether the client is a proxy client or a host client.
 | ||||
|   //
 | ||||
|   // `url` and `headers` need only remain valid until `request()` returns (they can be
 | ||||
|   // stack-allocated).
 | ||||
|   //
 | ||||
|   // `expectedBodySize`, if provided, must be exactly the number of bytes that will be written to
 | ||||
|   // the body. This will trigger use of the `Content-Length` connection header. Otherwise,
 | ||||
|   // `Transfer-Encoding: chunked` will be used.
 | ||||
| 
 | ||||
|   struct WebSocketResponse { | ||||
|     uint statusCode; | ||||
|     kj::StringPtr statusText; | ||||
|     const HttpHeaders* headers; | ||||
|     kj::OneOf<kj::Own<kj::AsyncInputStream>, kj::Own<WebSocket>> upstreamOrBody; | ||||
|     // `statusText` and `headers` remain valid until `upstreamOrBody` is dropped.
 | ||||
|   }; | ||||
|   virtual kj::Promise<WebSocketResponse> openWebSocket( | ||||
|       kj::StringPtr url, const HttpHeaders& headers, kj::Own<WebSocket> downstream); | ||||
|   // Tries to open a WebSocket. Default implementation calls send() and never returns a WebSocket.
 | ||||
|   //
 | ||||
|   // `url` and `headers` are invalidated when the returned promise resolves.
 | ||||
| 
 | ||||
|   virtual kj::Promise<kj::Own<kj::AsyncIoStream>> connect(kj::String host); | ||||
|   // Handles CONNECT requests. Only relevant for proxy clients. Default implementation throws
 | ||||
|   // UNIMPLEMENTED.
 | ||||
| }; | ||||
| 
 | ||||
| class HttpService { | ||||
|   // Interface which HTTP services should implement.
 | ||||
|   //
 | ||||
|   // This interface is functionally equivalent to HttpClient, but is intended for applications to
 | ||||
|   // implement rather than call. The ergonomics and performance of the method signatures are
 | ||||
|   // optimized for the serving end.
 | ||||
|   //
 | ||||
|   // As with clients, there are two kinds of services:
 | ||||
|   // * Host services are used when talking to a specific host. The `url` specified in a request
 | ||||
|   //   is actually just a path. (A `Host` header is still required in all requests, and the service
 | ||||
|   //   may in fact serve multiple origins via this header.)
 | ||||
|   // * Proxy services are used when the target could be any arbitrary host on the internet, i.e. to
 | ||||
|   //   implement an HTTP proxy. The `url` specified in a request is a full URL including protocol
 | ||||
|   //   and hostname.
 | ||||
| 
 | ||||
| public: | ||||
|   class Response { | ||||
|   public: | ||||
|     virtual kj::Own<kj::AsyncOutputStream> send( | ||||
|         uint statusCode, kj::StringPtr statusText, const HttpHeaders& headers, | ||||
|         kj::Maybe<uint64_t> expectedBodySize = nullptr) = 0; | ||||
|     // Begin the response.
 | ||||
|     //
 | ||||
|     // `statusText` and `headers` need only remain valid until send() returns (they can be
 | ||||
|     // stack-allocated).
 | ||||
|   }; | ||||
| 
 | ||||
|   virtual kj::Promise<void> request( | ||||
|       HttpMethod method, kj::StringPtr url, const HttpHeaders& headers, | ||||
|       kj::AsyncInputStream& requestBody, Response& response) = 0; | ||||
|   // Perform an HTTP request.
 | ||||
|   //
 | ||||
|   // `url` may be a full URL (with protocol and host) or it may be only the path part of the URL,
 | ||||
|   // depending on whether the service is a proxy service or a host service.
 | ||||
|   //
 | ||||
|   // `url` and `headers` are invalidated on the first read from `requestBody` or when the returned
 | ||||
|   // promise resolves, whichever comes first.
 | ||||
| 
 | ||||
|   class WebSocketResponse: public Response { | ||||
|   public: | ||||
|     kj::Own<WebSocket> startWebSocket( | ||||
|         uint statusCode, kj::StringPtr statusText, const HttpHeaders& headers, | ||||
|         WebSocket& upstream); | ||||
|     // Begin the response.
 | ||||
|     //
 | ||||
|     // `statusText` and `headers` need only remain valid until startWebSocket() returns (they can
 | ||||
|     // be stack-allocated).
 | ||||
|   }; | ||||
| 
 | ||||
|   virtual kj::Promise<void> openWebSocket( | ||||
|       kj::StringPtr url, const HttpHeaders& headers, WebSocketResponse& response); | ||||
|   // Tries to open a WebSocket. Default implementation calls request() and never returns a
 | ||||
|   // WebSocket.
 | ||||
|   //
 | ||||
|   // `url` and `headers` are invalidated when the returned promise resolves.
 | ||||
| 
 | ||||
|   virtual kj::Promise<kj::Own<kj::AsyncIoStream>> connect(kj::String host); | ||||
|   // Handles CONNECT requests. Only relevant for proxy services. Default implementation throws
 | ||||
|   // UNIMPLEMENTED.
 | ||||
| }; | ||||
| 
 | ||||
| kj::Own<HttpClient> newHttpClient(HttpHeaderTable& responseHeaderTable, kj::Network& network, | ||||
|                                   kj::Maybe<kj::Network&> tlsNetwork = nullptr); | ||||
| // Creates a proxy HttpClient that connects to hosts over the given network.
 | ||||
| //
 | ||||
| // `responseHeaderTable` is used when parsing HTTP responses. Requests can use any header table.
 | ||||
| //
 | ||||
| // `tlsNetwork` is required to support HTTPS destination URLs. Otherwise, only HTTP URLs can be
 | ||||
| // fetched.
 | ||||
| 
 | ||||
| kj::Own<HttpClient> newHttpClient(HttpHeaderTable& responseHeaderTable, kj::AsyncIoStream& stream); | ||||
| // Creates an HttpClient that speaks over the given pre-established connection. The client may
 | ||||
| // be used as a proxy client or a host client depending on whether the peer is operating as
 | ||||
| // a proxy.
 | ||||
| //
 | ||||
| // Note that since this client has only one stream to work with, it will try to pipeline all
 | ||||
| // requests on this stream. If one request or response has an I/O failure, all subsequent requests
 | ||||
| // fail as well. If the destination server chooses to close the connection after a response,
 | ||||
| // subsequent requests will fail. If a response takes a long time, it blocks subsequent responses.
 | ||||
| // If a WebSocket is opened successfully, all subsequent requests fail.
 | ||||
| 
 | ||||
| kj::Own<HttpClient> newHttpClient(HttpService& service); | ||||
| kj::Own<HttpService> newHttpService(HttpClient& client); | ||||
| // Adapts an HttpClient to an HttpService and vice versa.
 | ||||
| 
 | ||||
| struct HttpServerSettings { | ||||
|   kj::Duration headerTimeout = 15 * kj::SECONDS; | ||||
|   // After initial connection open, or after receiving the first byte of a pipelined request,
 | ||||
|   // the client must send the complete request within this time.
 | ||||
| 
 | ||||
|   kj::Duration pipelineTimeout = 5 * kj::SECONDS; | ||||
|   // After one request/response completes, we'll wait up to this long for a pipelined request to
 | ||||
|   // arrive.
 | ||||
| }; | ||||
| 
 | ||||
| class HttpServer: private kj::TaskSet::ErrorHandler { | ||||
|   // Class which listens for requests on ports or connections and sends them to an HttpService.
 | ||||
| 
 | ||||
| public: | ||||
|   typedef HttpServerSettings Settings; | ||||
| 
 | ||||
|   HttpServer(kj::Timer& timer, HttpHeaderTable& requestHeaderTable, HttpService& service, | ||||
|              Settings settings = Settings()); | ||||
|   // Set up an HttpServer that directs incoming connections to the given service. The service
 | ||||
|   // may be a host service or a proxy service depending on whether you are intending to implement
 | ||||
|   // an HTTP server or an HTTP proxy.
 | ||||
| 
 | ||||
|   kj::Promise<void> drain(); | ||||
|   // Stop accepting new connections or new requests on existing connections. Finish any requests
 | ||||
|   // that are already executing, then close the connections. Returns once no more requests are
 | ||||
|   // in-flight.
 | ||||
| 
 | ||||
|   kj::Promise<void> listenHttp(kj::ConnectionReceiver& port); | ||||
|   // Accepts HTTP connections on the given port and directs them to the handler.
 | ||||
|   //
 | ||||
|   // The returned promise never completes normally. It may throw if port.accept() throws. Dropping
 | ||||
|   // the returned promise will cause the server to stop listening on the port, but already-open
 | ||||
|   // connections will continue to be served. Destroy the whole HttpServer to cancel all I/O.
 | ||||
| 
 | ||||
|   kj::Promise<void> listenHttp(kj::Own<kj::AsyncIoStream> connection); | ||||
|   // Reads HTTP requests from the given connection and directs them to the handler. A successful
 | ||||
|   // completion of the promise indicates that all requests received on the connection resulted in
 | ||||
|   // a complete response, and the client closed the connection gracefully or drain() was called.
 | ||||
|   // The promise throws if an unparseable request is received or if some I/O error occurs. Dropping
 | ||||
|   // the returned promise will cancel all I/O on the connection and cancel any in-flight requests.
 | ||||
| 
 | ||||
| private: | ||||
|   class Connection; | ||||
| 
 | ||||
|   kj::Timer& timer; | ||||
|   HttpHeaderTable& requestHeaderTable; | ||||
|   HttpService& service; | ||||
|   Settings settings; | ||||
| 
 | ||||
|   bool draining = false; | ||||
|   kj::ForkedPromise<void> onDrain; | ||||
|   kj::Own<kj::PromiseFulfiller<void>> drainFulfiller; | ||||
| 
 | ||||
|   uint connectionCount = 0; | ||||
|   kj::Maybe<kj::Own<kj::PromiseFulfiller<void>>> zeroConnectionsFulfiller; | ||||
| 
 | ||||
|   kj::TaskSet tasks; | ||||
| 
 | ||||
|   HttpServer(kj::Timer& timer, HttpHeaderTable& requestHeaderTable, HttpService& service, | ||||
|              Settings settings, kj::PromiseFulfillerPair<void> paf); | ||||
| 
 | ||||
|   kj::Promise<void> listenLoop(kj::ConnectionReceiver& port); | ||||
| 
 | ||||
|   void taskFailed(kj::Exception&& exception) override; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // inline implementation
 | ||||
| 
 | ||||
| inline void HttpHeaderId::requireFrom(HttpHeaderTable& table) const { | ||||
|   KJ_IREQUIRE(this->table == nullptr || this->table == &table, | ||||
|       "the provided HttpHeaderId is from the wrong HttpHeaderTable"); | ||||
| } | ||||
| 
 | ||||
| inline kj::Own<HttpHeaderTable> HttpHeaderTable::Builder::build() { return kj::mv(table); } | ||||
| inline HttpHeaderTable& HttpHeaderTable::Builder::getFutureTable() { return *table; } | ||||
| 
 | ||||
| inline uint HttpHeaderTable::idCount() { return namesById.size(); } | ||||
| 
 | ||||
| inline kj::StringPtr HttpHeaderTable::idToString(HttpHeaderId id) { | ||||
|   id.requireFrom(*this); | ||||
|   return namesById[id.id]; | ||||
| } | ||||
| 
 | ||||
| inline kj::Maybe<kj::StringPtr> HttpHeaders::get(HttpHeaderId id) const { | ||||
|   id.requireFrom(*table); | ||||
|   auto result = indexedHeaders[id.id]; | ||||
|   return result == nullptr ? kj::Maybe<kj::StringPtr>(nullptr) : result; | ||||
| } | ||||
| 
 | ||||
| inline void HttpHeaders::unset(HttpHeaderId id) { | ||||
|   id.requireFrom(*table); | ||||
|   indexedHeaders[id.id] = nullptr; | ||||
| } | ||||
| 
 | ||||
| template <typename Func> | ||||
| inline void HttpHeaders::forEach(Func&& func) const { | ||||
|   for (auto i: kj::indices(indexedHeaders)) { | ||||
|     if (indexedHeaders[i] != nullptr) { | ||||
|       func(table->idToString(HttpHeaderId(table, i)), indexedHeaders[i]); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   for (auto& header: unindexedHeaders) { | ||||
|     func(header.name, header.value); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif // KJ_COMPAT_HTTP_H_
 | ||||
| @ -0,0 +1,555 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| // This file declares convenient macros for debug logging and error handling.  The macros make
 | ||||
| // it excessively easy to extract useful context information from code.  Example:
 | ||||
| //
 | ||||
| //     KJ_ASSERT(a == b, a, b, "a and b must be the same.");
 | ||||
| //
 | ||||
| // On failure, this will throw an exception whose description looks like:
 | ||||
| //
 | ||||
| //     myfile.c++:43: bug in code: expected a == b; a = 14; b = 72; a and b must be the same.
 | ||||
| //
 | ||||
| // As you can see, all arguments after the first provide additional context.
 | ||||
| //
 | ||||
| // The macros available are:
 | ||||
| //
 | ||||
| // * `KJ_LOG(severity, ...)`:  Just writes a log message, to stderr by default (but you can
 | ||||
| //   intercept messages by implementing an ExceptionCallback).  `severity` is `INFO`, `WARNING`,
 | ||||
| //   `ERROR`, or `FATAL`.  By default, `INFO` logs are not written, but for command-line apps the
 | ||||
| //   user should be able to pass a flag like `--verbose` to enable them.  Other log levels are
 | ||||
| //   enabled by default.  Log messages -- like exceptions -- can be intercepted by registering an
 | ||||
| //   ExceptionCallback.
 | ||||
| //
 | ||||
| // * `KJ_DBG(...)`:  Like `KJ_LOG`, but intended specifically for temporary log lines added while
 | ||||
| //   debugging a particular problem.  Calls to `KJ_DBG` should always be deleted before committing
 | ||||
| //   code.  It is suggested that you set up a pre-commit hook that checks for this.
 | ||||
| //
 | ||||
| // * `KJ_ASSERT(condition, ...)`:  Throws an exception if `condition` is false, or aborts if
 | ||||
| //   exceptions are disabled.  This macro should be used to check for bugs in the surrounding code
 | ||||
| //   and its dependencies, but NOT to check for invalid input.  The macro may be followed by a
 | ||||
| //   brace-delimited code block; if so, the block will be executed in the case where the assertion
 | ||||
| //   fails, before throwing the exception.  If control jumps out of the block (e.g. with "break",
 | ||||
| //   "return", or "goto"), then the error is considered "recoverable" -- in this case, if
 | ||||
| //   exceptions are disabled, execution will continue normally rather than aborting (but if
 | ||||
| //   exceptions are enabled, an exception will still be thrown on exiting the block). A "break"
 | ||||
| //   statement in particular will jump to the code immediately after the block (it does not break
 | ||||
| //   any surrounding loop or switch).  Example:
 | ||||
| //
 | ||||
| //       KJ_ASSERT(value >= 0, "Value cannot be negative.", value) {
 | ||||
| //         // Assertion failed.  Set value to zero to "recover".
 | ||||
| //         value = 0;
 | ||||
| //         // Don't abort if exceptions are disabled.  Continue normally.
 | ||||
| //         // (Still throw an exception if they are enabled, though.)
 | ||||
| //         break;
 | ||||
| //       }
 | ||||
| //       // When exceptions are disabled, we'll get here even if the assertion fails.
 | ||||
| //       // Otherwise, we get here only if the assertion passes.
 | ||||
| //
 | ||||
| // * `KJ_REQUIRE(condition, ...)`:  Like `KJ_ASSERT` but used to check preconditions -- e.g. to
 | ||||
| //   validate parameters passed from a caller.  A failure indicates that the caller is buggy.
 | ||||
| //
 | ||||
| // * `KJ_SYSCALL(code, ...)`:  Executes `code` assuming it makes a system call.  A negative result
 | ||||
| //   is considered an error, with error code reported via `errno`.  EINTR is handled by retrying.
 | ||||
| //   Other errors are handled by throwing an exception.  If you need to examine the return code,
 | ||||
| //   assign it to a variable like so:
 | ||||
| //
 | ||||
| //       int fd;
 | ||||
| //       KJ_SYSCALL(fd = open(filename, O_RDONLY), filename);
 | ||||
| //
 | ||||
| //   `KJ_SYSCALL` can be followed by a recovery block, just like `KJ_ASSERT`.
 | ||||
| //
 | ||||
| // * `KJ_NONBLOCKING_SYSCALL(code, ...)`:  Like KJ_SYSCALL, but will not throw an exception on
 | ||||
| //   EAGAIN/EWOULDBLOCK.  The calling code should check the syscall's return value to see if it
 | ||||
| //   indicates an error; in this case, it can assume the error was EAGAIN because any other error
 | ||||
| //   would have caused an exception to be thrown.
 | ||||
| //
 | ||||
| // * `KJ_CONTEXT(...)`:  Notes additional contextual information relevant to any exceptions thrown
 | ||||
| //   from within the current scope.  That is, until control exits the block in which KJ_CONTEXT()
 | ||||
| //   is used, if any exception is generated, it will contain the given information in its context
 | ||||
| //   chain.  This is helpful because it can otherwise be very difficult to come up with error
 | ||||
| //   messages that make sense within low-level helper code.  Note that the parameters to
 | ||||
| //   KJ_CONTEXT() are only evaluated if an exception is thrown.  This implies that any variables
 | ||||
| //   used must remain valid until the end of the scope.
 | ||||
| //
 | ||||
| // Notes:
 | ||||
| // * Do not write expressions with side-effects in the message content part of the macro, as the
 | ||||
| //   message will not necessarily be evaluated.
 | ||||
| // * For every macro `FOO` above except `LOG`, there is also a `FAIL_FOO` macro used to report
 | ||||
| //   failures that already happened.  For the macros that check a boolean condition, `FAIL_FOO`
 | ||||
| //   omits the first parameter and behaves like it was `false`.  `FAIL_SYSCALL` and
 | ||||
| //   `FAIL_RECOVERABLE_SYSCALL` take a string and an OS error number as the first two parameters.
 | ||||
| //   The string should be the name of the failed system call.
 | ||||
| // * For every macro `FOO` above, there is a `DFOO` version (or `RECOVERABLE_DFOO`) which is only
 | ||||
| //   executed in debug mode, i.e. when KJ_DEBUG is defined.  KJ_DEBUG is defined automatically
 | ||||
| //   by common.h when compiling without optimization (unless NDEBUG is defined), but you can also
 | ||||
| //   define it explicitly (e.g. -DKJ_DEBUG).  Generally, production builds should NOT use KJ_DEBUG
 | ||||
| //   as it may enable expensive checks that are unlikely to fail.
 | ||||
| 
 | ||||
| #ifndef KJ_DEBUG_H_ | ||||
| #define KJ_DEBUG_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "string.h" | ||||
| #include "exception.h" | ||||
| 
 | ||||
| #ifdef ERROR | ||||
| // This is problematic because windows.h #defines ERROR, which we use in an enum here.
 | ||||
| #error "Make sure to to undefine ERROR (or just #include <kj/windows-sanity.h>) before this file" | ||||
| #endif | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| #if _MSC_VER | ||||
| // MSVC does __VA_ARGS__ differently from GCC:
 | ||||
| // - A trailing comma before an empty __VA_ARGS__ is removed automatically, whereas GCC wants
 | ||||
| //   you to request this behavior with "##__VA_ARGS__".
 | ||||
| // - If __VA_ARGS__ is passed directly as an argument to another macro, it will be treated as a
 | ||||
| //   *single* argument rather than an argument list. This can be worked around by wrapping the
 | ||||
| //   outer macro call in KJ_EXPAND(), which appraently forces __VA_ARGS__ to be expanded before
 | ||||
| //   the macro is evaluated. I don't understand the C preprocessor.
 | ||||
| // - Using "#__VA_ARGS__" to stringify __VA_ARGS__ expands to zero tokens when __VA_ARGS__ is
 | ||||
| //   empty, rather than expanding to an empty string literal. We can work around by concatenating
 | ||||
| //   with an empty string literal.
 | ||||
| 
 | ||||
| #define KJ_EXPAND(X) X | ||||
| 
 | ||||
| #define KJ_LOG(severity, ...) \ | ||||
|   if (!::kj::_::Debug::shouldLog(::kj::LogSeverity::severity)) {} else \
 | ||||
|     ::kj::_::Debug::log(__FILE__, __LINE__, ::kj::LogSeverity::severity, \
 | ||||
|                         "" #__VA_ARGS__, __VA_ARGS__) | ||||
| 
 | ||||
| #define KJ_DBG(...) KJ_EXPAND(KJ_LOG(DBG, __VA_ARGS__)) | ||||
| 
 | ||||
| #define KJ_REQUIRE(cond, ...) \ | ||||
|   if (KJ_LIKELY(cond)) {} else \
 | ||||
|     for (::kj::_::Debug::Fault f(__FILE__, __LINE__, ::kj::Exception::Type::FAILED, \
 | ||||
|                                  #cond, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #define KJ_FAIL_REQUIRE(...) \ | ||||
|   for (::kj::_::Debug::Fault f(__FILE__, __LINE__, ::kj::Exception::Type::FAILED, \
 | ||||
|                                nullptr, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #define KJ_SYSCALL(call, ...) \ | ||||
|   if (auto _kjSyscallResult = ::kj::_::Debug::syscall([&](){return (call);}, false)) {} else \
 | ||||
|     for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \
 | ||||
|              _kjSyscallResult.getErrorNumber(), #call, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #define KJ_NONBLOCKING_SYSCALL(call, ...) \ | ||||
|   if (auto _kjSyscallResult = ::kj::_::Debug::syscall([&](){return (call);}, true)) {} else \
 | ||||
|     for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \
 | ||||
|              _kjSyscallResult.getErrorNumber(), #call, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #define KJ_FAIL_SYSCALL(code, errorNumber, ...) \ | ||||
|   for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \
 | ||||
|            errorNumber, code, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #if _WIN32 | ||||
| 
 | ||||
| #define KJ_WIN32(call, ...) \ | ||||
|   if (::kj::_::Debug::isWin32Success(call)) {} else \
 | ||||
|     for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \
 | ||||
|              ::kj::_::Debug::getWin32Error(), #call, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #define KJ_WINSOCK(call, ...) \ | ||||
|   if ((call) != SOCKET_ERROR) {} else \
 | ||||
|     for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \
 | ||||
|              ::kj::_::Debug::getWin32Error(), #call, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #define KJ_FAIL_WIN32(code, errorNumber, ...) \ | ||||
|   for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \
 | ||||
|            ::kj::_::Debug::Win32Error(errorNumber), code, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #define KJ_UNIMPLEMENTED(...) \ | ||||
|   for (::kj::_::Debug::Fault f(__FILE__, __LINE__, ::kj::Exception::Type::UNIMPLEMENTED, \
 | ||||
|                                nullptr, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| // TODO(msvc):  MSVC mis-deduces `ContextImpl<decltype(func)>` as `ContextImpl<int>` in some edge
 | ||||
| // cases, such as inside nested lambdas inside member functions. Wrapping the type in
 | ||||
| // `decltype(instance<...>())` helps it deduce the context function's type correctly.
 | ||||
| #define KJ_CONTEXT(...) \ | ||||
|   auto KJ_UNIQUE_NAME(_kjContextFunc) = [&]() -> ::kj::_::Debug::Context::Value { \
 | ||||
|         return ::kj::_::Debug::Context::Value(__FILE__, __LINE__, \
 | ||||
|             ::kj::_::Debug::makeDescription("" #__VA_ARGS__, __VA_ARGS__)); \
 | ||||
|       }; \
 | ||||
|   decltype(::kj::instance<::kj::_::Debug::ContextImpl<decltype(KJ_UNIQUE_NAME(_kjContextFunc))>>()) \
 | ||||
|       KJ_UNIQUE_NAME(_kjContext)(KJ_UNIQUE_NAME(_kjContextFunc)) | ||||
| 
 | ||||
| #define KJ_REQUIRE_NONNULL(value, ...) \ | ||||
|   (*[&] { \
 | ||||
|     auto _kj_result = ::kj::_::readMaybe(value); \
 | ||||
|     if (KJ_UNLIKELY(!_kj_result)) { \
 | ||||
|       ::kj::_::Debug::Fault(__FILE__, __LINE__, ::kj::Exception::Type::FAILED, \
 | ||||
|                             #value " != nullptr", "" #__VA_ARGS__, __VA_ARGS__).fatal(); \ | ||||
|     } \
 | ||||
|     return _kj_result; \
 | ||||
|   }()) | ||||
| 
 | ||||
| #define KJ_EXCEPTION(type, ...) \ | ||||
|   ::kj::Exception(::kj::Exception::Type::type, __FILE__, __LINE__, \
 | ||||
|       ::kj::_::Debug::makeDescription("" #__VA_ARGS__, __VA_ARGS__)) | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| #define KJ_LOG(severity, ...) \ | ||||
|   if (!::kj::_::Debug::shouldLog(::kj::LogSeverity::severity)) {} else \
 | ||||
|     ::kj::_::Debug::log(__FILE__, __LINE__, ::kj::LogSeverity::severity, \
 | ||||
|                         #__VA_ARGS__, ##__VA_ARGS__) | ||||
| 
 | ||||
| #define KJ_DBG(...) KJ_LOG(DBG, ##__VA_ARGS__) | ||||
| 
 | ||||
| #define KJ_REQUIRE(cond, ...) \ | ||||
|   if (KJ_LIKELY(cond)) {} else \
 | ||||
|     for (::kj::_::Debug::Fault f(__FILE__, __LINE__, ::kj::Exception::Type::FAILED, \
 | ||||
|                                  #cond, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #define KJ_FAIL_REQUIRE(...) \ | ||||
|   for (::kj::_::Debug::Fault f(__FILE__, __LINE__, ::kj::Exception::Type::FAILED, \
 | ||||
|                                nullptr, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #define KJ_SYSCALL(call, ...) \ | ||||
|   if (auto _kjSyscallResult = ::kj::_::Debug::syscall([&](){return (call);}, false)) {} else \
 | ||||
|     for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \
 | ||||
|              _kjSyscallResult.getErrorNumber(), #call, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #define KJ_NONBLOCKING_SYSCALL(call, ...) \ | ||||
|   if (auto _kjSyscallResult = ::kj::_::Debug::syscall([&](){return (call);}, true)) {} else \
 | ||||
|     for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \
 | ||||
|              _kjSyscallResult.getErrorNumber(), #call, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #define KJ_FAIL_SYSCALL(code, errorNumber, ...) \ | ||||
|   for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \
 | ||||
|            errorNumber, code, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #if _WIN32 | ||||
| 
 | ||||
| #define KJ_WIN32(call, ...) \ | ||||
|   if (::kj::_::Debug::isWin32Success(call)) {} else \
 | ||||
|     for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \
 | ||||
|              ::kj::_::Debug::getWin32Error(), #call, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #define KJ_WINSOCK(call, ...) \ | ||||
|   if ((call) != SOCKET_ERROR) {} else \
 | ||||
|     for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \
 | ||||
|              ::kj::_::Debug::getWin32Error(), #call, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #define KJ_FAIL_WIN32(code, errorNumber, ...) \ | ||||
|   for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \
 | ||||
|            ::kj::_::Debug::Win32Error(errorNumber), code, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #define KJ_UNIMPLEMENTED(...) \ | ||||
|   for (::kj::_::Debug::Fault f(__FILE__, __LINE__, ::kj::Exception::Type::UNIMPLEMENTED, \
 | ||||
|                                nullptr, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | ||||
| 
 | ||||
| #define KJ_CONTEXT(...) \ | ||||
|   auto KJ_UNIQUE_NAME(_kjContextFunc) = [&]() -> ::kj::_::Debug::Context::Value { \
 | ||||
|         return ::kj::_::Debug::Context::Value(__FILE__, __LINE__, \
 | ||||
|             ::kj::_::Debug::makeDescription(#__VA_ARGS__, ##__VA_ARGS__)); \
 | ||||
|       }; \
 | ||||
|   ::kj::_::Debug::ContextImpl<decltype(KJ_UNIQUE_NAME(_kjContextFunc))> \
 | ||||
|       KJ_UNIQUE_NAME(_kjContext)(KJ_UNIQUE_NAME(_kjContextFunc)) | ||||
| 
 | ||||
| #define KJ_REQUIRE_NONNULL(value, ...) \ | ||||
|   (*({ \
 | ||||
|     auto _kj_result = ::kj::_::readMaybe(value); \
 | ||||
|     if (KJ_UNLIKELY(!_kj_result)) { \
 | ||||
|       ::kj::_::Debug::Fault(__FILE__, __LINE__, ::kj::Exception::Type::FAILED, \
 | ||||
|                             #value " != nullptr", #__VA_ARGS__, ##__VA_ARGS__).fatal(); \ | ||||
|     } \
 | ||||
|     kj::mv(_kj_result); \
 | ||||
|   })) | ||||
| 
 | ||||
| #define KJ_EXCEPTION(type, ...) \ | ||||
|   ::kj::Exception(::kj::Exception::Type::type, __FILE__, __LINE__, \
 | ||||
|       ::kj::_::Debug::makeDescription(#__VA_ARGS__, ##__VA_ARGS__)) | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #define KJ_SYSCALL_HANDLE_ERRORS(call) \ | ||||
|   if (int _kjSyscallError = ::kj::_::Debug::syscallError([&](){return (call);}, false)) \
 | ||||
|     switch (int error = _kjSyscallError) | ||||
| // Like KJ_SYSCALL, but doesn't throw. Instead, the block after the macro is a switch block on the
 | ||||
| // error. Additionally, the int value `error` is defined within the block. So you can do:
 | ||||
| //
 | ||||
| //     KJ_SYSCALL_HANDLE_ERRORS(foo()) {
 | ||||
| //       case ENOENT:
 | ||||
| //         handleNoSuchFile();
 | ||||
| //         break;
 | ||||
| //       case EEXIST:
 | ||||
| //         handleExists();
 | ||||
| //         break;
 | ||||
| //       default:
 | ||||
| //         KJ_FAIL_SYSCALL("foo()", error);
 | ||||
| //     } else {
 | ||||
| //       handleSuccessCase();
 | ||||
| //     }
 | ||||
| 
 | ||||
| #define KJ_ASSERT KJ_REQUIRE | ||||
| #define KJ_FAIL_ASSERT KJ_FAIL_REQUIRE | ||||
| #define KJ_ASSERT_NONNULL KJ_REQUIRE_NONNULL | ||||
| // Use "ASSERT" in place of "REQUIRE" when the problem is local to the immediate surrounding code.
 | ||||
| // That is, if the assert ever fails, it indicates that the immediate surrounding code is broken.
 | ||||
| 
 | ||||
| #ifdef KJ_DEBUG | ||||
| #define KJ_DLOG KJ_LOG | ||||
| #define KJ_DASSERT KJ_ASSERT | ||||
| #define KJ_DREQUIRE KJ_REQUIRE | ||||
| #else | ||||
| #define KJ_DLOG(...) do {} while (false) | ||||
| #define KJ_DASSERT(...) do {} while (false) | ||||
| #define KJ_DREQUIRE(...) do {} while (false) | ||||
| #endif | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| class Debug { | ||||
| public: | ||||
|   Debug() = delete; | ||||
| 
 | ||||
|   typedef LogSeverity Severity;  // backwards-compatibility
 | ||||
| 
 | ||||
| #if _WIN32 | ||||
|   struct Win32Error { | ||||
|     // Hack for overloading purposes.
 | ||||
|     uint number; | ||||
|     inline explicit Win32Error(uint number): number(number) {} | ||||
|   }; | ||||
| #endif | ||||
| 
 | ||||
|   static inline bool shouldLog(LogSeverity severity) { return severity >= minSeverity; } | ||||
|   // Returns whether messages of the given severity should be logged.
 | ||||
| 
 | ||||
|   static inline void setLogLevel(LogSeverity severity) { minSeverity = severity; } | ||||
|   // Set the minimum message severity which will be logged.
 | ||||
|   //
 | ||||
|   // TODO(someday):  Expose publicly.
 | ||||
| 
 | ||||
|   template <typename... Params> | ||||
|   static void log(const char* file, int line, LogSeverity severity, const char* macroArgs, | ||||
|                   Params&&... params); | ||||
| 
 | ||||
|   class Fault { | ||||
|   public: | ||||
|     template <typename Code, typename... Params> | ||||
|     Fault(const char* file, int line, Code code, | ||||
|           const char* condition, const char* macroArgs, Params&&... params); | ||||
|     Fault(const char* file, int line, Exception::Type type, | ||||
|           const char* condition, const char* macroArgs); | ||||
|     Fault(const char* file, int line, int osErrorNumber, | ||||
|           const char* condition, const char* macroArgs); | ||||
| #if _WIN32 | ||||
|     Fault(const char* file, int line, Win32Error osErrorNumber, | ||||
|           const char* condition, const char* macroArgs); | ||||
| #endif | ||||
|     ~Fault() noexcept(false); | ||||
| 
 | ||||
|     KJ_NOINLINE KJ_NORETURN(void fatal()); | ||||
|     // Throw the exception.
 | ||||
| 
 | ||||
|   private: | ||||
|     void init(const char* file, int line, Exception::Type type, | ||||
|               const char* condition, const char* macroArgs, ArrayPtr<String> argValues); | ||||
|     void init(const char* file, int line, int osErrorNumber, | ||||
|               const char* condition, const char* macroArgs, ArrayPtr<String> argValues); | ||||
| #if _WIN32 | ||||
|     void init(const char* file, int line, Win32Error osErrorNumber, | ||||
|               const char* condition, const char* macroArgs, ArrayPtr<String> argValues); | ||||
| #endif | ||||
| 
 | ||||
|     Exception* exception; | ||||
|   }; | ||||
| 
 | ||||
|   class SyscallResult { | ||||
|   public: | ||||
|     inline SyscallResult(int errorNumber): errorNumber(errorNumber) {} | ||||
|     inline operator void*() { return errorNumber == 0 ? this : nullptr; } | ||||
|     inline int getErrorNumber() { return errorNumber; } | ||||
| 
 | ||||
|   private: | ||||
|     int errorNumber; | ||||
|   }; | ||||
| 
 | ||||
|   template <typename Call> | ||||
|   static SyscallResult syscall(Call&& call, bool nonblocking); | ||||
|   template <typename Call> | ||||
|   static int syscallError(Call&& call, bool nonblocking); | ||||
| 
 | ||||
| #if _WIN32 | ||||
|   static bool isWin32Success(int boolean); | ||||
|   static bool isWin32Success(void* handle); | ||||
|   static Win32Error getWin32Error(); | ||||
| #endif | ||||
| 
 | ||||
|   class Context: public ExceptionCallback { | ||||
|   public: | ||||
|     Context(); | ||||
|     KJ_DISALLOW_COPY(Context); | ||||
|     virtual ~Context() noexcept(false); | ||||
| 
 | ||||
|     struct Value { | ||||
|       const char* file; | ||||
|       int line; | ||||
|       String description; | ||||
| 
 | ||||
|       inline Value(const char* file, int line, String&& description) | ||||
|           : file(file), line(line), description(mv(description)) {} | ||||
|     }; | ||||
| 
 | ||||
|     virtual Value evaluate() = 0; | ||||
| 
 | ||||
|     virtual void onRecoverableException(Exception&& exception) override; | ||||
|     virtual void onFatalException(Exception&& exception) override; | ||||
|     virtual void logMessage(LogSeverity severity, const char* file, int line, int contextDepth, | ||||
|                             String&& text) override; | ||||
| 
 | ||||
|   private: | ||||
|     bool logged; | ||||
|     Maybe<Value> value; | ||||
| 
 | ||||
|     Value ensureInitialized(); | ||||
|   }; | ||||
| 
 | ||||
|   template <typename Func> | ||||
|   class ContextImpl: public Context { | ||||
|   public: | ||||
|     inline ContextImpl(Func& func): func(func) {} | ||||
|     KJ_DISALLOW_COPY(ContextImpl); | ||||
| 
 | ||||
|     Value evaluate() override { | ||||
|       return func(); | ||||
|     } | ||||
|   private: | ||||
|     Func& func; | ||||
|   }; | ||||
| 
 | ||||
|   template <typename... Params> | ||||
|   static String makeDescription(const char* macroArgs, Params&&... params); | ||||
| 
 | ||||
| private: | ||||
|   static LogSeverity minSeverity; | ||||
| 
 | ||||
|   static void logInternal(const char* file, int line, LogSeverity severity, const char* macroArgs, | ||||
|                           ArrayPtr<String> argValues); | ||||
|   static String makeDescriptionInternal(const char* macroArgs, ArrayPtr<String> argValues); | ||||
| 
 | ||||
|   static int getOsErrorNumber(bool nonblocking); | ||||
|   // Get the error code of the last error (e.g. from errno).  Returns -1 on EINTR.
 | ||||
| }; | ||||
| 
 | ||||
| template <typename... Params> | ||||
| void Debug::log(const char* file, int line, LogSeverity severity, const char* macroArgs, | ||||
|                 Params&&... params) { | ||||
|   String argValues[sizeof...(Params)] = {str(params)...}; | ||||
|   logInternal(file, line, severity, macroArgs, arrayPtr(argValues, sizeof...(Params))); | ||||
| } | ||||
| 
 | ||||
| template <> | ||||
| inline void Debug::log<>(const char* file, int line, LogSeverity severity, const char* macroArgs) { | ||||
|   logInternal(file, line, severity, macroArgs, nullptr); | ||||
| } | ||||
| 
 | ||||
| template <typename Code, typename... Params> | ||||
| Debug::Fault::Fault(const char* file, int line, Code code, | ||||
|                     const char* condition, const char* macroArgs, Params&&... params) | ||||
|     : exception(nullptr) { | ||||
|   String argValues[sizeof...(Params)] = {str(params)...}; | ||||
|   init(file, line, code, condition, macroArgs, | ||||
|        arrayPtr(argValues, sizeof...(Params))); | ||||
| } | ||||
| 
 | ||||
| inline Debug::Fault::Fault(const char* file, int line, int osErrorNumber, | ||||
|                            const char* condition, const char* macroArgs) | ||||
|     : exception(nullptr) { | ||||
|   init(file, line, osErrorNumber, condition, macroArgs, nullptr); | ||||
| } | ||||
| 
 | ||||
| inline Debug::Fault::Fault(const char* file, int line, kj::Exception::Type type, | ||||
|                            const char* condition, const char* macroArgs) | ||||
|     : exception(nullptr) { | ||||
|   init(file, line, type, condition, macroArgs, nullptr); | ||||
| } | ||||
| 
 | ||||
| #if _WIN32 | ||||
| inline Debug::Fault::Fault(const char* file, int line, Win32Error osErrorNumber, | ||||
|                            const char* condition, const char* macroArgs) | ||||
|     : exception(nullptr) { | ||||
|   init(file, line, osErrorNumber, condition, macroArgs, nullptr); | ||||
| } | ||||
| 
 | ||||
| inline bool Debug::isWin32Success(int boolean) { | ||||
|   return boolean; | ||||
| } | ||||
| inline bool Debug::isWin32Success(void* handle) { | ||||
|   // Assume null and INVALID_HANDLE_VALUE mean failure.
 | ||||
|   return handle != nullptr && handle != (void*)-1; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| template <typename Call> | ||||
| Debug::SyscallResult Debug::syscall(Call&& call, bool nonblocking) { | ||||
|   while (call() < 0) { | ||||
|     int errorNum = getOsErrorNumber(nonblocking); | ||||
|     // getOsErrorNumber() returns -1 to indicate EINTR.
 | ||||
|     // Also, if nonblocking is true, then it returns 0 on EAGAIN, which will then be treated as a
 | ||||
|     // non-error.
 | ||||
|     if (errorNum != -1) { | ||||
|       return SyscallResult(errorNum); | ||||
|     } | ||||
|   } | ||||
|   return SyscallResult(0); | ||||
| } | ||||
| 
 | ||||
| template <typename Call> | ||||
| int Debug::syscallError(Call&& call, bool nonblocking) { | ||||
|   while (call() < 0) { | ||||
|     int errorNum = getOsErrorNumber(nonblocking); | ||||
|     // getOsErrorNumber() returns -1 to indicate EINTR.
 | ||||
|     // Also, if nonblocking is true, then it returns 0 on EAGAIN, which will then be treated as a
 | ||||
|     // non-error.
 | ||||
|     if (errorNum != -1) { | ||||
|       return errorNum; | ||||
|     } | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| template <typename... Params> | ||||
| String Debug::makeDescription(const char* macroArgs, Params&&... params) { | ||||
|   String argValues[sizeof...(Params)] = {str(params)...}; | ||||
|   return makeDescriptionInternal(macroArgs, arrayPtr(argValues, sizeof...(Params))); | ||||
| } | ||||
| 
 | ||||
| template <> | ||||
| inline String Debug::makeDescription<>(const char* macroArgs) { | ||||
|   return makeDescriptionInternal(macroArgs, nullptr); | ||||
| } | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_DEBUG_H_
 | ||||
| @ -0,0 +1,363 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_EXCEPTION_H_ | ||||
| #define KJ_EXCEPTION_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "memory.h" | ||||
| #include "array.h" | ||||
| #include "string.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| class ExceptionImpl; | ||||
| 
 | ||||
| class Exception { | ||||
|   // Exception thrown in case of fatal errors.
 | ||||
|   //
 | ||||
|   // Actually, a subclass of this which also implements std::exception will be thrown, but we hide
 | ||||
|   // that fact from the interface to avoid #including <exception>.
 | ||||
| 
 | ||||
| public: | ||||
|   enum class Type { | ||||
|     // What kind of failure?
 | ||||
| 
 | ||||
|     FAILED = 0, | ||||
|     // Something went wrong. This is the usual error type. KJ_ASSERT and KJ_REQUIRE throw this
 | ||||
|     // error type.
 | ||||
| 
 | ||||
|     OVERLOADED = 1, | ||||
|     // The call failed because of a temporary lack of resources. This could be space resources
 | ||||
|     // (out of memory, out of disk space) or time resources (request queue overflow, operation
 | ||||
|     // timed out).
 | ||||
|     //
 | ||||
|     // The operation might work if tried again, but it should NOT be repeated immediately as this
 | ||||
|     // may simply exacerbate the problem.
 | ||||
| 
 | ||||
|     DISCONNECTED = 2, | ||||
|     // The call required communication over a connection that has been lost. The callee will need
 | ||||
|     // to re-establish connections and try again.
 | ||||
| 
 | ||||
|     UNIMPLEMENTED = 3 | ||||
|     // The requested method is not implemented. The caller may wish to revert to a fallback
 | ||||
|     // approach based on other methods.
 | ||||
| 
 | ||||
|     // IF YOU ADD A NEW VALUE:
 | ||||
|     // - Update the stringifier.
 | ||||
|     // - Update Cap'n Proto's RPC protocol's Exception.Type enum.
 | ||||
|   }; | ||||
| 
 | ||||
|   Exception(Type type, const char* file, int line, String description = nullptr) noexcept; | ||||
|   Exception(Type type, String file, int line, String description = nullptr) noexcept; | ||||
|   Exception(const Exception& other) noexcept; | ||||
|   Exception(Exception&& other) = default; | ||||
|   ~Exception() noexcept; | ||||
| 
 | ||||
|   const char* getFile() const { return file; } | ||||
|   int getLine() const { return line; } | ||||
|   Type getType() const { return type; } | ||||
|   StringPtr getDescription() const { return description; } | ||||
|   ArrayPtr<void* const> getStackTrace() const { return arrayPtr(trace, traceCount); } | ||||
| 
 | ||||
|   struct Context { | ||||
|     // Describes a bit about what was going on when the exception was thrown.
 | ||||
| 
 | ||||
|     const char* file; | ||||
|     int line; | ||||
|     String description; | ||||
|     Maybe<Own<Context>> next; | ||||
| 
 | ||||
|     Context(const char* file, int line, String&& description, Maybe<Own<Context>>&& next) | ||||
|         : file(file), line(line), description(mv(description)), next(mv(next)) {} | ||||
|     Context(const Context& other) noexcept; | ||||
|   }; | ||||
| 
 | ||||
|   inline Maybe<const Context&> getContext() const { | ||||
|     KJ_IF_MAYBE(c, context) { | ||||
|       return **c; | ||||
|     } else { | ||||
|       return nullptr; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   void wrapContext(const char* file, int line, String&& description); | ||||
|   // Wraps the context in a new node.  This becomes the head node returned by getContext() -- it
 | ||||
|   // is expected that contexts will be added in reverse order as the exception passes up the
 | ||||
|   // callback stack.
 | ||||
| 
 | ||||
|   KJ_NOINLINE void extendTrace(uint ignoreCount); | ||||
|   // Append the current stack trace to the exception's trace, ignoring the first `ignoreCount`
 | ||||
|   // frames (see `getStackTrace()` for discussion of `ignoreCount`).
 | ||||
| 
 | ||||
|   KJ_NOINLINE void truncateCommonTrace(); | ||||
|   // Remove the part of the stack trace which the exception shares with the caller of this method.
 | ||||
|   // This is used by the async library to remove the async infrastructure from the stack trace
 | ||||
|   // before replacing it with the async trace.
 | ||||
| 
 | ||||
|   void addTrace(void* ptr); | ||||
|   // Append the given pointer to the backtrace, if it is not already full. This is used by the
 | ||||
|   // async library to trace through the promise chain that led to the exception.
 | ||||
| 
 | ||||
| private: | ||||
|   String ownFile; | ||||
|   const char* file; | ||||
|   int line; | ||||
|   Type type; | ||||
|   String description; | ||||
|   Maybe<Own<Context>> context; | ||||
|   void* trace[32]; | ||||
|   uint traceCount; | ||||
| 
 | ||||
|   friend class ExceptionImpl; | ||||
| }; | ||||
| 
 | ||||
| StringPtr KJ_STRINGIFY(Exception::Type type); | ||||
| String KJ_STRINGIFY(const Exception& e); | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| enum class LogSeverity { | ||||
|   INFO,      // Information describing what the code is up to, which users may request to see
 | ||||
|              // with a flag like `--verbose`.  Does not indicate a problem.  Not printed by
 | ||||
|              // default; you must call setLogLevel(INFO) to enable.
 | ||||
|   WARNING,   // A problem was detected but execution can continue with correct output.
 | ||||
|   ERROR,     // Something is wrong, but execution can continue with garbage output.
 | ||||
|   FATAL,     // Something went wrong, and execution cannot continue.
 | ||||
|   DBG        // Temporary debug logging.  See KJ_DBG.
 | ||||
| 
 | ||||
|   // Make sure to update the stringifier if you add a new severity level.
 | ||||
| }; | ||||
| 
 | ||||
| StringPtr KJ_STRINGIFY(LogSeverity severity); | ||||
| 
 | ||||
| class ExceptionCallback { | ||||
|   // If you don't like C++ exceptions, you may implement and register an ExceptionCallback in order
 | ||||
|   // to perform your own exception handling.  For example, a reasonable thing to do is to have
 | ||||
|   // onRecoverableException() set a flag indicating that an error occurred, and then check for that
 | ||||
|   // flag just before writing to storage and/or returning results to the user.  If the flag is set,
 | ||||
|   // discard whatever you have and return an error instead.
 | ||||
|   //
 | ||||
|   // ExceptionCallbacks must always be allocated on the stack.  When an exception is thrown, the
 | ||||
|   // newest ExceptionCallback on the calling thread's stack is called.  The default implementation
 | ||||
|   // of each method calls the next-oldest ExceptionCallback for that thread.  Thus the callbacks
 | ||||
|   // behave a lot like try/catch blocks, except that they are called before any stack unwinding
 | ||||
|   // occurs.
 | ||||
| 
 | ||||
| public: | ||||
|   ExceptionCallback(); | ||||
|   KJ_DISALLOW_COPY(ExceptionCallback); | ||||
|   virtual ~ExceptionCallback() noexcept(false); | ||||
| 
 | ||||
|   virtual void onRecoverableException(Exception&& exception); | ||||
|   // Called when an exception has been raised, but the calling code has the ability to continue by
 | ||||
|   // producing garbage output.  This method _should_ throw the exception, but is allowed to simply
 | ||||
|   // return if garbage output is acceptable.
 | ||||
|   //
 | ||||
|   // The global default implementation throws an exception unless the library was compiled with
 | ||||
|   // -fno-exceptions, in which case it logs an error and returns.
 | ||||
| 
 | ||||
|   virtual void onFatalException(Exception&& exception); | ||||
|   // Called when an exception has been raised and the calling code cannot continue.  If this method
 | ||||
|   // returns normally, abort() will be called.  The method must throw the exception to avoid
 | ||||
|   // aborting.
 | ||||
|   //
 | ||||
|   // The global default implementation throws an exception unless the library was compiled with
 | ||||
|   // -fno-exceptions, in which case it logs an error and returns.
 | ||||
| 
 | ||||
|   virtual void logMessage(LogSeverity severity, const char* file, int line, int contextDepth, | ||||
|                           String&& text); | ||||
|   // Called when something wants to log some debug text.  `contextDepth` indicates how many levels
 | ||||
|   // of context the message passed through; it may make sense to indent the message accordingly.
 | ||||
|   //
 | ||||
|   // The global default implementation writes the text to stderr.
 | ||||
| 
 | ||||
|   enum class StackTraceMode { | ||||
|     FULL, | ||||
|     // Stringifying a stack trace will attempt to determine source file and line numbers. This may
 | ||||
|     // be expensive. For example, on Linux, this shells out to `addr2line`.
 | ||||
|     //
 | ||||
|     // This is the default in debug builds.
 | ||||
| 
 | ||||
|     ADDRESS_ONLY, | ||||
|     // Stringifying a stack trace will only generate a list of code addresses.
 | ||||
|     //
 | ||||
|     // This is the default in release builds.
 | ||||
| 
 | ||||
|     NONE | ||||
|     // Generating a stack trace will always return an empty array.
 | ||||
|     //
 | ||||
|     // This avoids ever unwinding the stack. On Windows in particular, the stack unwinding library
 | ||||
|     // has been observed to be pretty slow, so exception-heavy code might benefit significantly
 | ||||
|     // from this setting. (But exceptions should be rare...)
 | ||||
|   }; | ||||
| 
 | ||||
|   virtual StackTraceMode stackTraceMode(); | ||||
|   // Returns the current preferred stack trace mode.
 | ||||
| 
 | ||||
| protected: | ||||
|   ExceptionCallback& next; | ||||
| 
 | ||||
| private: | ||||
|   ExceptionCallback(ExceptionCallback& next); | ||||
| 
 | ||||
|   class RootExceptionCallback; | ||||
|   friend ExceptionCallback& getExceptionCallback(); | ||||
| }; | ||||
| 
 | ||||
| ExceptionCallback& getExceptionCallback(); | ||||
| // Returns the current exception callback.
 | ||||
| 
 | ||||
| KJ_NOINLINE KJ_NORETURN(void throwFatalException(kj::Exception&& exception, uint ignoreCount = 0)); | ||||
| // Invoke the exception callback to throw the given fatal exception.  If the exception callback
 | ||||
| // returns, abort.
 | ||||
| 
 | ||||
| KJ_NOINLINE void throwRecoverableException(kj::Exception&& exception, uint ignoreCount = 0); | ||||
| // Invoke the exception callback to throw the given recoverable exception.  If the exception
 | ||||
| // callback returns, return normally.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| namespace _ { class Runnable; } | ||||
| 
 | ||||
| template <typename Func> | ||||
| Maybe<Exception> runCatchingExceptions(Func&& func) noexcept; | ||||
| // Executes the given function (usually, a lambda returning nothing) catching any exceptions that
 | ||||
| // are thrown.  Returns the Exception if there was one, or null if the operation completed normally.
 | ||||
| // Non-KJ exceptions will be wrapped.
 | ||||
| //
 | ||||
| // If exception are disabled (e.g. with -fno-exceptions), this will still detect whether any
 | ||||
| // recoverable exceptions occurred while running the function and will return those.
 | ||||
| 
 | ||||
| class UnwindDetector { | ||||
|   // Utility for detecting when a destructor is called due to unwind.  Useful for:
 | ||||
|   // - Avoiding throwing exceptions in this case, which would terminate the program.
 | ||||
|   // - Detecting whether to commit or roll back a transaction.
 | ||||
|   //
 | ||||
|   // To use this class, either inherit privately from it or declare it as a member.  The detector
 | ||||
|   // works by comparing the exception state against that when the constructor was called, so for
 | ||||
|   // an object that was actually constructed during exception unwind, it will behave as if no
 | ||||
|   // unwind is taking place.  This is usually the desired behavior.
 | ||||
| 
 | ||||
| public: | ||||
|   UnwindDetector(); | ||||
| 
 | ||||
|   bool isUnwinding() const; | ||||
|   // Returns true if the current thread is in a stack unwind that it wasn't in at the time the
 | ||||
|   // object was constructed.
 | ||||
| 
 | ||||
|   template <typename Func> | ||||
|   void catchExceptionsIfUnwinding(Func&& func) const; | ||||
|   // Runs the given function (e.g., a lambda).  If isUnwinding() is true, any exceptions are
 | ||||
|   // caught and treated as secondary faults, meaning they are considered to be side-effects of the
 | ||||
|   // exception that is unwinding the stack.  Otherwise, exceptions are passed through normally.
 | ||||
| 
 | ||||
| private: | ||||
|   uint uncaughtCount; | ||||
| 
 | ||||
|   void catchExceptionsAsSecondaryFaults(_::Runnable& runnable) const; | ||||
| }; | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| class Runnable { | ||||
| public: | ||||
|   virtual void run() = 0; | ||||
| }; | ||||
| 
 | ||||
| template <typename Func> | ||||
| class RunnableImpl: public Runnable { | ||||
| public: | ||||
|   RunnableImpl(Func&& func): func(kj::mv(func)) {} | ||||
|   void run() override { | ||||
|     func(); | ||||
|   } | ||||
| private: | ||||
|   Func func; | ||||
| }; | ||||
| 
 | ||||
| Maybe<Exception> runCatchingExceptions(Runnable& runnable) noexcept; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename Func> | ||||
| Maybe<Exception> runCatchingExceptions(Func&& func) noexcept { | ||||
|   _::RunnableImpl<Decay<Func>> runnable(kj::fwd<Func>(func)); | ||||
|   return _::runCatchingExceptions(runnable); | ||||
| } | ||||
| 
 | ||||
| template <typename Func> | ||||
| void UnwindDetector::catchExceptionsIfUnwinding(Func&& func) const { | ||||
|   if (isUnwinding()) { | ||||
|     _::RunnableImpl<Decay<Func>> runnable(kj::fwd<Func>(func)); | ||||
|     catchExceptionsAsSecondaryFaults(runnable); | ||||
|   } else { | ||||
|     func(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| #define KJ_ON_SCOPE_SUCCESS(code) \ | ||||
|   ::kj::UnwindDetector KJ_UNIQUE_NAME(_kjUnwindDetector); \
 | ||||
|   KJ_DEFER(if (!KJ_UNIQUE_NAME(_kjUnwindDetector).isUnwinding()) { code; }) | ||||
| // Runs `code` if the current scope is exited normally (not due to an exception).
 | ||||
| 
 | ||||
| #define KJ_ON_SCOPE_FAILURE(code) \ | ||||
|   ::kj::UnwindDetector KJ_UNIQUE_NAME(_kjUnwindDetector); \
 | ||||
|   KJ_DEFER(if (KJ_UNIQUE_NAME(_kjUnwindDetector).isUnwinding()) { code; }) | ||||
| // Runs `code` if the current scope is exited due to an exception.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| KJ_NOINLINE ArrayPtr<void* const> getStackTrace(ArrayPtr<void*> space, uint ignoreCount); | ||||
| // Attempt to get the current stack trace, returning a list of pointers to instructions. The
 | ||||
| // returned array is a slice of `space`. Provide a larger `space` to get a deeper stack trace.
 | ||||
| // If the platform doesn't support stack traces, returns an empty array.
 | ||||
| //
 | ||||
| // `ignoreCount` items will be truncated from the front of the trace. This is useful for chopping
 | ||||
| // off a prefix of the trace that is uninteresting to the developer because it's just locations
 | ||||
| // inside the debug infrastructure that is requesting the trace. Be careful to mark functions as
 | ||||
| // KJ_NOINLINE if you intend to count them in `ignoreCount`. Note that, unfortunately, the
 | ||||
| // ignored entries will still waste space in the `space` array (and the returned array's `begin()`
 | ||||
| // is never exactly equal to `space.begin()` due to this effect, even if `ignoreCount` is zero
 | ||||
| // since `getStackTrace()` needs to ignore its own internal frames).
 | ||||
| 
 | ||||
| String stringifyStackTrace(ArrayPtr<void* const>); | ||||
| // Convert the stack trace to a string with file names and line numbers. This may involve executing
 | ||||
| // suprocesses.
 | ||||
| 
 | ||||
| String getStackTrace(); | ||||
| // Get a stack trace right now and stringify it. Useful for debugging.
 | ||||
| 
 | ||||
| void printStackTraceOnCrash(); | ||||
| // Registers signal handlers on common "crash" signals like SIGSEGV that will (attempt to) print
 | ||||
| // a stack trace. You should call this as early as possible on program startup. Programs using
 | ||||
| // KJ_MAIN get this automatically.
 | ||||
| 
 | ||||
| kj::StringPtr trimSourceFilename(kj::StringPtr filename); | ||||
| // Given a source code file name, trim off noisy prefixes like "src/" or
 | ||||
| // "/ekam-provider/canonical/".
 | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_EXCEPTION_H_
 | ||||
| @ -0,0 +1,277 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_FUNCTION_H_ | ||||
| #define KJ_FUNCTION_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "memory.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| template <typename Signature> | ||||
| class Function; | ||||
| // Function wrapper using virtual-based polymorphism.  Use this when template polymorphism is
 | ||||
| // not possible.  You can, for example, accept a Function as a parameter:
 | ||||
| //
 | ||||
| //     void setFilter(Function<bool(const Widget&)> filter);
 | ||||
| //
 | ||||
| // The caller of `setFilter()` may then pass any callable object as the parameter.  The callable
 | ||||
| // object does not have to have the exact signature specified, just one that is "compatible" --
 | ||||
| // i.e. the return type is covariant and the parameters are contravariant.
 | ||||
| //
 | ||||
| // Unlike `std::function`, `kj::Function`s are movable but not copyable, just like `kj::Own`.  This
 | ||||
| // is to avoid unexpected heap allocation or slow atomic reference counting.
 | ||||
| //
 | ||||
| // When a `Function` is constructed from an lvalue, it captures only a reference to the value.
 | ||||
| // When constructed from an rvalue, it invokes the value's move constructor.  So, for example:
 | ||||
| //
 | ||||
| //     struct AddN {
 | ||||
| //       int n;
 | ||||
| //       int operator(int i) { return i + n; }
 | ||||
| //     }
 | ||||
| //
 | ||||
| //     Function<int(int, int)> f1 = AddN{2};
 | ||||
| //     // f1 owns an instance of AddN.  It may safely be moved out
 | ||||
| //     // of the local scope.
 | ||||
| //
 | ||||
| //     AddN adder(2);
 | ||||
| //     Function<int(int, int)> f2 = adder;
 | ||||
| //     // f2 contains a reference to `adder`.  Thus, it becomes invalid
 | ||||
| //     // when `adder` goes out-of-scope.
 | ||||
| //
 | ||||
| //     AddN adder2(2);
 | ||||
| //     Function<int(int, int)> f3 = kj::mv(adder2);
 | ||||
| //     // f3 owns an insatnce of AddN moved from `adder2`.  f3 may safely
 | ||||
| //     // be moved out of the local scope.
 | ||||
| //
 | ||||
| // Additionally, a Function may be bound to a class method using KJ_BIND_METHOD(object, methodName).
 | ||||
| // For example:
 | ||||
| //
 | ||||
| //     class Printer {
 | ||||
| //     public:
 | ||||
| //       void print(int i);
 | ||||
| //       void print(kj::StringPtr s);
 | ||||
| //     };
 | ||||
| //
 | ||||
| //     Printer p;
 | ||||
| //
 | ||||
| //     Function<void(uint)> intPrinter = KJ_BIND_METHOD(p, print);
 | ||||
| //     // Will call Printer::print(int).
 | ||||
| //
 | ||||
| //     Function<void(const char*)> strPrinter = KJ_BIND_METHOD(p, print);
 | ||||
| //     // Will call Printer::print(kj::StringPtr).
 | ||||
| //
 | ||||
| // Notice how KJ_BIND_METHOD is able to figure out which overload to use depending on the kind of
 | ||||
| // Function it is binding to.
 | ||||
| 
 | ||||
| template <typename Signature> | ||||
| class ConstFunction; | ||||
| // Like Function, but wraps a "const" (i.e. thread-safe) call.
 | ||||
| 
 | ||||
| template <typename Return, typename... Params> | ||||
| class Function<Return(Params...)> { | ||||
| public: | ||||
|   template <typename F> | ||||
|   inline Function(F&& f): impl(heap<Impl<F>>(kj::fwd<F>(f))) {} | ||||
|   Function() = default; | ||||
| 
 | ||||
|   // Make sure people don't accidentally end up wrapping a reference when they meant to return
 | ||||
|   // a function.
 | ||||
|   KJ_DISALLOW_COPY(Function); | ||||
|   Function(Function&) = delete; | ||||
|   Function& operator=(Function&) = delete; | ||||
|   template <typename T> Function(const Function<T>&) = delete; | ||||
|   template <typename T> Function& operator=(const Function<T>&) = delete; | ||||
|   template <typename T> Function(const ConstFunction<T>&) = delete; | ||||
|   template <typename T> Function& operator=(const ConstFunction<T>&) = delete; | ||||
|   Function(Function&&) = default; | ||||
|   Function& operator=(Function&&) = default; | ||||
| 
 | ||||
|   inline Return operator()(Params... params) { | ||||
|     return (*impl)(kj::fwd<Params>(params)...); | ||||
|   } | ||||
| 
 | ||||
|   Function reference() { | ||||
|     // Forms a new Function of the same type that delegates to this Function by reference.
 | ||||
|     // Therefore, this Function must outlive the returned Function, but otherwise they behave
 | ||||
|     // exactly the same.
 | ||||
| 
 | ||||
|     return *impl; | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   class Iface { | ||||
|   public: | ||||
|     virtual Return operator()(Params... params) = 0; | ||||
|   }; | ||||
| 
 | ||||
|   template <typename F> | ||||
|   class Impl final: public Iface { | ||||
|   public: | ||||
|     explicit Impl(F&& f): f(kj::fwd<F>(f)) {} | ||||
| 
 | ||||
|     Return operator()(Params... params) override { | ||||
|       return f(kj::fwd<Params>(params)...); | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     F f; | ||||
|   }; | ||||
| 
 | ||||
|   Own<Iface> impl; | ||||
| }; | ||||
| 
 | ||||
| template <typename Return, typename... Params> | ||||
| class ConstFunction<Return(Params...)> { | ||||
| public: | ||||
|   template <typename F> | ||||
|   inline ConstFunction(F&& f): impl(heap<Impl<F>>(kj::fwd<F>(f))) {} | ||||
|   ConstFunction() = default; | ||||
| 
 | ||||
|   // Make sure people don't accidentally end up wrapping a reference when they meant to return
 | ||||
|   // a function.
 | ||||
|   KJ_DISALLOW_COPY(ConstFunction); | ||||
|   ConstFunction(ConstFunction&) = delete; | ||||
|   ConstFunction& operator=(ConstFunction&) = delete; | ||||
|   template <typename T> ConstFunction(const ConstFunction<T>&) = delete; | ||||
|   template <typename T> ConstFunction& operator=(const ConstFunction<T>&) = delete; | ||||
|   template <typename T> ConstFunction(const Function<T>&) = delete; | ||||
|   template <typename T> ConstFunction& operator=(const Function<T>&) = delete; | ||||
|   ConstFunction(ConstFunction&&) = default; | ||||
|   ConstFunction& operator=(ConstFunction&&) = default; | ||||
| 
 | ||||
|   inline Return operator()(Params... params) const { | ||||
|     return (*impl)(kj::fwd<Params>(params)...); | ||||
|   } | ||||
| 
 | ||||
|   ConstFunction reference() const { | ||||
|     // Forms a new ConstFunction of the same type that delegates to this ConstFunction by reference.
 | ||||
|     // Therefore, this ConstFunction must outlive the returned ConstFunction, but otherwise they
 | ||||
|     // behave exactly the same.
 | ||||
| 
 | ||||
|     return *impl; | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   class Iface { | ||||
|   public: | ||||
|     virtual Return operator()(Params... params) const = 0; | ||||
|   }; | ||||
| 
 | ||||
|   template <typename F> | ||||
|   class Impl final: public Iface { | ||||
|   public: | ||||
|     explicit Impl(F&& f): f(kj::fwd<F>(f)) {} | ||||
| 
 | ||||
|     Return operator()(Params... params) const override { | ||||
|       return f(kj::fwd<Params>(params)...); | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     F f; | ||||
|   }; | ||||
| 
 | ||||
|   Own<Iface> impl; | ||||
| }; | ||||
| 
 | ||||
| #if 1 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T, typename Signature, Signature method> | ||||
| class BoundMethod; | ||||
| 
 | ||||
| template <typename T, typename Return, typename... Params, Return (Decay<T>::*method)(Params...)> | ||||
| class BoundMethod<T, Return (Decay<T>::*)(Params...), method> { | ||||
| public: | ||||
|   BoundMethod(T&& t): t(kj::fwd<T>(t)) {} | ||||
| 
 | ||||
|   Return operator()(Params&&... params) { | ||||
|     return (t.*method)(kj::fwd<Params>(params)...); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   T t; | ||||
| }; | ||||
| 
 | ||||
| template <typename T, typename Return, typename... Params, | ||||
|           Return (Decay<T>::*method)(Params...) const> | ||||
| class BoundMethod<T, Return (Decay<T>::*)(Params...) const, method> { | ||||
| public: | ||||
|   BoundMethod(T&& t): t(kj::fwd<T>(t)) {} | ||||
| 
 | ||||
|   Return operator()(Params&&... params) const { | ||||
|     return (t.*method)(kj::fwd<Params>(params)...); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   T t; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| #define KJ_BIND_METHOD(obj, method) \ | ||||
|   ::kj::_::BoundMethod<KJ_DECLTYPE_REF(obj), \
 | ||||
|                        decltype(&::kj::Decay<decltype(obj)>::method), \
 | ||||
|                        &::kj::Decay<decltype(obj)>::method>(obj) | ||||
| // Macro that produces a functor object which forwards to the method `obj.name`.  If `obj` is an
 | ||||
| // lvalue, the functor will hold a reference to it.  If `obj` is an rvalue, the functor will
 | ||||
| // contain a copy (by move) of it.
 | ||||
| //
 | ||||
| // The current implementation requires that the method is not overloaded.
 | ||||
| //
 | ||||
| // TODO(someday):  C++14's generic lambdas may be able to simplify this code considerably, and
 | ||||
| //   probably make it work with overloaded methods.
 | ||||
| 
 | ||||
| #else | ||||
| // Here's a better implementation of the above that doesn't work with GCC (but does with Clang)
 | ||||
| // because it uses a local class with a template method.  Sigh.  This implementation supports
 | ||||
| // overloaded methods.
 | ||||
| 
 | ||||
| #define KJ_BIND_METHOD(obj, method) \ | ||||
|   ({ \
 | ||||
|     typedef KJ_DECLTYPE_REF(obj) T; \
 | ||||
|     class F { \
 | ||||
|     public: \
 | ||||
|       inline F(T&& t): t(::kj::fwd<T>(t)) {} \
 | ||||
|       template <typename... Params> \
 | ||||
|       auto operator()(Params&&... params) \
 | ||||
|           -> decltype(::kj::instance<T>().method(::kj::fwd<Params>(params)...)) { \
 | ||||
|         return t.method(::kj::fwd<Params>(params)...); \
 | ||||
|       } \
 | ||||
|     private: \
 | ||||
|       T t; \
 | ||||
|     }; \
 | ||||
|     (F(obj)); \
 | ||||
|   }) | ||||
| // Macro that produces a functor object which forwards to the method `obj.name`.  If `obj` is an
 | ||||
| // lvalue, the functor will hold a reference to it.  If `obj` is an rvalue, the functor will
 | ||||
| // contain a copy (by move) of it.
 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_FUNCTION_H_
 | ||||
| @ -0,0 +1,419 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_IO_H_ | ||||
| #define KJ_IO_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include <stddef.h> | ||||
| #include "common.h" | ||||
| #include "array.h" | ||||
| #include "exception.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Abstract interfaces
 | ||||
| 
 | ||||
| class InputStream { | ||||
| public: | ||||
|   virtual ~InputStream() noexcept(false); | ||||
| 
 | ||||
|   size_t read(void* buffer, size_t minBytes, size_t maxBytes); | ||||
|   // Reads at least minBytes and at most maxBytes, copying them into the given buffer.  Returns
 | ||||
|   // the size read.  Throws an exception on errors.  Implemented in terms of tryRead().
 | ||||
|   //
 | ||||
|   // maxBytes is the number of bytes the caller really wants, but minBytes is the minimum amount
 | ||||
|   // needed by the caller before it can start doing useful processing.  If the stream returns less
 | ||||
|   // than maxBytes, the caller will usually call read() again later to get the rest.  Returning
 | ||||
|   // less than maxBytes is useful when it makes sense for the caller to parallelize processing
 | ||||
|   // with I/O.
 | ||||
|   //
 | ||||
|   // Never blocks if minBytes is zero.  If minBytes is zero and maxBytes is non-zero, this may
 | ||||
|   // attempt a non-blocking read or may just return zero.  To force a read, use a non-zero minBytes.
 | ||||
|   // To detect EOF without throwing an exception, use tryRead().
 | ||||
|   //
 | ||||
|   // If the InputStream can't produce minBytes, it MUST throw an exception, as the caller is not
 | ||||
|   // expected to understand how to deal with partial reads.
 | ||||
| 
 | ||||
|   virtual size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) = 0; | ||||
|   // Like read(), but may return fewer than minBytes on EOF.
 | ||||
| 
 | ||||
|   inline void read(void* buffer, size_t bytes) { read(buffer, bytes, bytes); } | ||||
|   // Convenience method for reading an exact number of bytes.
 | ||||
| 
 | ||||
|   virtual void skip(size_t bytes); | ||||
|   // Skips past the given number of bytes, discarding them.  The default implementation read()s
 | ||||
|   // into a scratch buffer.
 | ||||
| }; | ||||
| 
 | ||||
| class OutputStream { | ||||
| public: | ||||
|   virtual ~OutputStream() noexcept(false); | ||||
| 
 | ||||
|   virtual void write(const void* buffer, size_t size) = 0; | ||||
|   // Always writes the full size.  Throws exception on error.
 | ||||
| 
 | ||||
|   virtual void write(ArrayPtr<const ArrayPtr<const byte>> pieces); | ||||
|   // Equivalent to write()ing each byte array in sequence, which is what the default implementation
 | ||||
|   // does.  Override if you can do something better, e.g. use writev() to do the write in a single
 | ||||
|   // syscall.
 | ||||
| }; | ||||
| 
 | ||||
| class BufferedInputStream: public InputStream { | ||||
|   // An input stream which buffers some bytes in memory to reduce system call overhead.
 | ||||
|   // - OR -
 | ||||
|   // An input stream that actually reads from some in-memory data structure and wants to give its
 | ||||
|   // caller a direct pointer to that memory to potentially avoid a copy.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual ~BufferedInputStream() noexcept(false); | ||||
| 
 | ||||
|   ArrayPtr<const byte> getReadBuffer(); | ||||
|   // Get a direct pointer into the read buffer, which contains the next bytes in the input.  If the
 | ||||
|   // caller consumes any bytes, it should then call skip() to indicate this.  This always returns a
 | ||||
|   // non-empty buffer or throws an exception.  Implemented in terms of tryGetReadBuffer().
 | ||||
| 
 | ||||
|   virtual ArrayPtr<const byte> tryGetReadBuffer() = 0; | ||||
|   // Like getReadBuffer() but may return an empty buffer on EOF.
 | ||||
| }; | ||||
| 
 | ||||
| class BufferedOutputStream: public OutputStream { | ||||
|   // An output stream which buffers some bytes in memory to reduce system call overhead.
 | ||||
|   // - OR -
 | ||||
|   // An output stream that actually writes into some in-memory data structure and wants to give its
 | ||||
|   // caller a direct pointer to that memory to potentially avoid a copy.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual ~BufferedOutputStream() noexcept(false); | ||||
| 
 | ||||
|   virtual ArrayPtr<byte> getWriteBuffer() = 0; | ||||
|   // Get a direct pointer into the write buffer.  The caller may choose to fill in some prefix of
 | ||||
|   // this buffer and then pass it to write(), in which case write() may avoid a copy.  It is
 | ||||
|   // incorrect to pass to write any slice of this buffer which is not a prefix.
 | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Buffered streams implemented as wrappers around regular streams
 | ||||
| 
 | ||||
| class BufferedInputStreamWrapper: public BufferedInputStream { | ||||
|   // Implements BufferedInputStream in terms of an InputStream.
 | ||||
|   //
 | ||||
|   // Note that the underlying stream's position is unpredictable once the wrapper is destroyed,
 | ||||
|   // unless the entire stream was consumed.  To read a predictable number of bytes in a buffered
 | ||||
|   // way without going over, you'd need this wrapper to wrap some other wrapper which itself
 | ||||
|   // implements an artificial EOF at the desired point.  Such a stream should be trivial to write
 | ||||
|   // but is not provided by the library at this time.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit BufferedInputStreamWrapper(InputStream& inner, ArrayPtr<byte> buffer = nullptr); | ||||
|   // Creates a buffered stream wrapping the given non-buffered stream.  No guarantee is made about
 | ||||
|   // the position of the inner stream after a buffered wrapper has been created unless the entire
 | ||||
|   // input is read.
 | ||||
|   //
 | ||||
|   // If the second parameter is non-null, the stream uses the given buffer instead of allocating
 | ||||
|   // its own.  This may improve performance if the buffer can be reused.
 | ||||
| 
 | ||||
|   KJ_DISALLOW_COPY(BufferedInputStreamWrapper); | ||||
|   ~BufferedInputStreamWrapper() noexcept(false); | ||||
| 
 | ||||
|   // implements BufferedInputStream ----------------------------------
 | ||||
|   ArrayPtr<const byte> tryGetReadBuffer() override; | ||||
|   size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override; | ||||
|   void skip(size_t bytes) override; | ||||
| 
 | ||||
| private: | ||||
|   InputStream& inner; | ||||
|   Array<byte> ownedBuffer; | ||||
|   ArrayPtr<byte> buffer; | ||||
|   ArrayPtr<byte> bufferAvailable; | ||||
| }; | ||||
| 
 | ||||
| class BufferedOutputStreamWrapper: public BufferedOutputStream { | ||||
|   // Implements BufferedOutputStream in terms of an OutputStream.  Note that writes to the
 | ||||
|   // underlying stream may be delayed until flush() is called or the wrapper is destroyed.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit BufferedOutputStreamWrapper(OutputStream& inner, ArrayPtr<byte> buffer = nullptr); | ||||
|   // Creates a buffered stream wrapping the given non-buffered stream.
 | ||||
|   //
 | ||||
|   // If the second parameter is non-null, the stream uses the given buffer instead of allocating
 | ||||
|   // its own.  This may improve performance if the buffer can be reused.
 | ||||
| 
 | ||||
|   KJ_DISALLOW_COPY(BufferedOutputStreamWrapper); | ||||
|   ~BufferedOutputStreamWrapper() noexcept(false); | ||||
| 
 | ||||
|   void flush(); | ||||
|   // Force the wrapper to write any remaining bytes in its buffer to the inner stream.  Note that
 | ||||
|   // this only flushes this object's buffer; this object has no idea how to flush any other buffers
 | ||||
|   // that may be present in the underlying stream.
 | ||||
| 
 | ||||
|   // implements BufferedOutputStream ---------------------------------
 | ||||
|   ArrayPtr<byte> getWriteBuffer() override; | ||||
|   void write(const void* buffer, size_t size) override; | ||||
| 
 | ||||
| private: | ||||
|   OutputStream& inner; | ||||
|   Array<byte> ownedBuffer; | ||||
|   ArrayPtr<byte> buffer; | ||||
|   byte* bufferPos; | ||||
|   UnwindDetector unwindDetector; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Array I/O
 | ||||
| 
 | ||||
| class ArrayInputStream: public BufferedInputStream { | ||||
| public: | ||||
|   explicit ArrayInputStream(ArrayPtr<const byte> array); | ||||
|   KJ_DISALLOW_COPY(ArrayInputStream); | ||||
|   ~ArrayInputStream() noexcept(false); | ||||
| 
 | ||||
|   // implements BufferedInputStream ----------------------------------
 | ||||
|   ArrayPtr<const byte> tryGetReadBuffer() override; | ||||
|   size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override; | ||||
|   void skip(size_t bytes) override; | ||||
| 
 | ||||
| private: | ||||
|   ArrayPtr<const byte> array; | ||||
| }; | ||||
| 
 | ||||
| class ArrayOutputStream: public BufferedOutputStream { | ||||
| public: | ||||
|   explicit ArrayOutputStream(ArrayPtr<byte> array); | ||||
|   KJ_DISALLOW_COPY(ArrayOutputStream); | ||||
|   ~ArrayOutputStream() noexcept(false); | ||||
| 
 | ||||
|   ArrayPtr<byte> getArray() { | ||||
|     // Get the portion of the array which has been filled in.
 | ||||
|     return arrayPtr(array.begin(), fillPos); | ||||
|   } | ||||
| 
 | ||||
|   // implements BufferedInputStream ----------------------------------
 | ||||
|   ArrayPtr<byte> getWriteBuffer() override; | ||||
|   void write(const void* buffer, size_t size) override; | ||||
| 
 | ||||
| private: | ||||
|   ArrayPtr<byte> array; | ||||
|   byte* fillPos; | ||||
| }; | ||||
| 
 | ||||
| class VectorOutputStream: public BufferedOutputStream { | ||||
| public: | ||||
|   explicit VectorOutputStream(size_t initialCapacity = 4096); | ||||
|   KJ_DISALLOW_COPY(VectorOutputStream); | ||||
|   ~VectorOutputStream() noexcept(false); | ||||
| 
 | ||||
|   ArrayPtr<byte> getArray() { | ||||
|     // Get the portion of the array which has been filled in.
 | ||||
|     return arrayPtr(vector.begin(), fillPos); | ||||
|   } | ||||
| 
 | ||||
|   // implements BufferedInputStream ----------------------------------
 | ||||
|   ArrayPtr<byte> getWriteBuffer() override; | ||||
|   void write(const void* buffer, size_t size) override; | ||||
| 
 | ||||
| private: | ||||
|   Array<byte> vector; | ||||
|   byte* fillPos; | ||||
| 
 | ||||
|   void grow(size_t minSize); | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // File descriptor I/O
 | ||||
| 
 | ||||
| class AutoCloseFd { | ||||
|   // A wrapper around a file descriptor which automatically closes the descriptor when destroyed.
 | ||||
|   // The wrapper supports move construction for transferring ownership of the descriptor.  If
 | ||||
|   // close() returns an error, the destructor throws an exception, UNLESS the destructor is being
 | ||||
|   // called during unwind from another exception, in which case the close error is ignored.
 | ||||
|   //
 | ||||
|   // If your code is not exception-safe, you should not use AutoCloseFd.  In this case you will
 | ||||
|   // have to call close() yourself and handle errors appropriately.
 | ||||
| 
 | ||||
| public: | ||||
|   inline AutoCloseFd(): fd(-1) {} | ||||
|   inline AutoCloseFd(decltype(nullptr)): fd(-1) {} | ||||
|   inline explicit AutoCloseFd(int fd): fd(fd) {} | ||||
|   inline AutoCloseFd(AutoCloseFd&& other) noexcept: fd(other.fd) { other.fd = -1; } | ||||
|   KJ_DISALLOW_COPY(AutoCloseFd); | ||||
|   ~AutoCloseFd() noexcept(false); | ||||
| 
 | ||||
|   inline AutoCloseFd& operator=(AutoCloseFd&& other) { | ||||
|     AutoCloseFd old(kj::mv(*this)); | ||||
|     fd = other.fd; | ||||
|     other.fd = -1; | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   inline AutoCloseFd& operator=(decltype(nullptr)) { | ||||
|     AutoCloseFd old(kj::mv(*this)); | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   inline operator int() const { return fd; } | ||||
|   inline int get() const { return fd; } | ||||
| 
 | ||||
|   operator bool() const = delete; | ||||
|   // Deleting this operator prevents accidental use in boolean contexts, which
 | ||||
|   // the int conversion operator above would otherwise allow.
 | ||||
| 
 | ||||
|   inline bool operator==(decltype(nullptr)) { return fd < 0; } | ||||
|   inline bool operator!=(decltype(nullptr)) { return fd >= 0; } | ||||
| 
 | ||||
| private: | ||||
|   int fd; | ||||
|   UnwindDetector unwindDetector; | ||||
| }; | ||||
| 
 | ||||
| inline auto KJ_STRINGIFY(const AutoCloseFd& fd) | ||||
|     -> decltype(kj::toCharSequence(implicitCast<int>(fd))) { | ||||
|   return kj::toCharSequence(implicitCast<int>(fd)); | ||||
| } | ||||
| 
 | ||||
| class FdInputStream: public InputStream { | ||||
|   // An InputStream wrapping a file descriptor.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit FdInputStream(int fd): fd(fd) {} | ||||
|   explicit FdInputStream(AutoCloseFd fd): fd(fd), autoclose(mv(fd)) {} | ||||
|   KJ_DISALLOW_COPY(FdInputStream); | ||||
|   ~FdInputStream() noexcept(false); | ||||
| 
 | ||||
|   size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override; | ||||
| 
 | ||||
|   inline int getFd() const { return fd; } | ||||
| 
 | ||||
| private: | ||||
|   int fd; | ||||
|   AutoCloseFd autoclose; | ||||
| }; | ||||
| 
 | ||||
| class FdOutputStream: public OutputStream { | ||||
|   // An OutputStream wrapping a file descriptor.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit FdOutputStream(int fd): fd(fd) {} | ||||
|   explicit FdOutputStream(AutoCloseFd fd): fd(fd), autoclose(mv(fd)) {} | ||||
|   KJ_DISALLOW_COPY(FdOutputStream); | ||||
|   ~FdOutputStream() noexcept(false); | ||||
| 
 | ||||
|   void write(const void* buffer, size_t size) override; | ||||
|   void write(ArrayPtr<const ArrayPtr<const byte>> pieces) override; | ||||
| 
 | ||||
|   inline int getFd() const { return fd; } | ||||
| 
 | ||||
| private: | ||||
|   int fd; | ||||
|   AutoCloseFd autoclose; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Win32 Handle I/O
 | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| 
 | ||||
| class AutoCloseHandle { | ||||
|   // A wrapper around a Win32 HANDLE which automatically closes the handle when destroyed.
 | ||||
|   // The wrapper supports move construction for transferring ownership of the handle.  If
 | ||||
|   // CloseHandle() returns an error, the destructor throws an exception, UNLESS the destructor is
 | ||||
|   // being called during unwind from another exception, in which case the close error is ignored.
 | ||||
|   //
 | ||||
|   // If your code is not exception-safe, you should not use AutoCloseHandle.  In this case you will
 | ||||
|   // have to call close() yourself and handle errors appropriately.
 | ||||
| 
 | ||||
| public: | ||||
|   inline AutoCloseHandle(): handle((void*)-1) {} | ||||
|   inline AutoCloseHandle(decltype(nullptr)): handle((void*)-1) {} | ||||
|   inline explicit AutoCloseHandle(void* handle): handle(handle) {} | ||||
|   inline AutoCloseHandle(AutoCloseHandle&& other) noexcept: handle(other.handle) { | ||||
|     other.handle = (void*)-1; | ||||
|   } | ||||
|   KJ_DISALLOW_COPY(AutoCloseHandle); | ||||
|   ~AutoCloseHandle() noexcept(false); | ||||
| 
 | ||||
|   inline AutoCloseHandle& operator=(AutoCloseHandle&& other) { | ||||
|     AutoCloseHandle old(kj::mv(*this)); | ||||
|     handle = other.handle; | ||||
|     other.handle = (void*)-1; | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   inline AutoCloseHandle& operator=(decltype(nullptr)) { | ||||
|     AutoCloseHandle old(kj::mv(*this)); | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   inline operator void*() const { return handle; } | ||||
|   inline void* get() const { return handle; } | ||||
| 
 | ||||
|   operator bool() const = delete; | ||||
|   // Deleting this operator prevents accidental use in boolean contexts, which
 | ||||
|   // the void* conversion operator above would otherwise allow.
 | ||||
| 
 | ||||
|   inline bool operator==(decltype(nullptr)) { return handle != (void*)-1; } | ||||
|   inline bool operator!=(decltype(nullptr)) { return handle == (void*)-1; } | ||||
| 
 | ||||
| private: | ||||
|   void* handle;  // -1 (aka INVALID_HANDLE_VALUE) if not valid.
 | ||||
| }; | ||||
| 
 | ||||
| class HandleInputStream: public InputStream { | ||||
|   // An InputStream wrapping a Win32 HANDLE.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit HandleInputStream(void* handle): handle(handle) {} | ||||
|   explicit HandleInputStream(AutoCloseHandle handle): handle(handle), autoclose(mv(handle)) {} | ||||
|   KJ_DISALLOW_COPY(HandleInputStream); | ||||
|   ~HandleInputStream() noexcept(false); | ||||
| 
 | ||||
|   size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override; | ||||
| 
 | ||||
| private: | ||||
|   void* handle; | ||||
|   AutoCloseHandle autoclose; | ||||
| }; | ||||
| 
 | ||||
| class HandleOutputStream: public OutputStream { | ||||
|   // An OutputStream wrapping a Win32 HANDLE.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit HandleOutputStream(void* handle): handle(handle) {} | ||||
|   explicit HandleOutputStream(AutoCloseHandle handle): handle(handle), autoclose(mv(handle)) {} | ||||
|   KJ_DISALLOW_COPY(HandleOutputStream); | ||||
|   ~HandleOutputStream() noexcept(false); | ||||
| 
 | ||||
|   void write(const void* buffer, size_t size) override; | ||||
| 
 | ||||
| private: | ||||
|   void* handle; | ||||
|   AutoCloseHandle autoclose; | ||||
| }; | ||||
| 
 | ||||
| #endif  // _WIN32
 | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_IO_H_
 | ||||
| @ -0,0 +1,407 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_MAIN_H_ | ||||
| #define KJ_MAIN_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "array.h" | ||||
| #include "string.h" | ||||
| #include "vector.h" | ||||
| #include "function.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| class ProcessContext { | ||||
|   // Context for command-line programs.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual StringPtr getProgramName() = 0; | ||||
|   // Get argv[0] as passed to main().
 | ||||
| 
 | ||||
|   KJ_NORETURN(virtual void exit()) = 0; | ||||
|   // Indicates program completion.  The program is considered successful unless `error()` was
 | ||||
|   // called.  Typically this exits with _Exit(), meaning that the stack is not unwound, buffers
 | ||||
|   // are not flushed, etc. -- it is the responsibility of the caller to flush any buffers that
 | ||||
|   // matter.  However, an alternate context implementation e.g. for unit testing purposes could
 | ||||
|   // choose to throw an exception instead.
 | ||||
|   //
 | ||||
|   // At first this approach may sound crazy.  Isn't it much better to shut down cleanly?  What if
 | ||||
|   // you lose data?  However, it turns out that if you look at each common class of program, _Exit()
 | ||||
|   // is almost always preferable.  Let's break it down:
 | ||||
|   //
 | ||||
|   // * Commands:  A typical program you might run from the command line is single-threaded and
 | ||||
|   //   exits quickly and deterministically.  Commands often use buffered I/O and need to flush
 | ||||
|   //   those buffers before exit.  However, most of the work performed by destructors is not
 | ||||
|   //   flushing buffers, but rather freeing up memory, placing objects into freelists, and closing
 | ||||
|   //   file descriptors.  All of this is irrelevant if the process is about to exit anyway, and
 | ||||
|   //   for a command that runs quickly, time wasted freeing heap space may make a real difference
 | ||||
|   //   in the overall runtime of a script.  Meanwhile, it is usually easy to determine exactly what
 | ||||
|   //   resources need to be flushed before exit, and easy to tell if they are not being flushed
 | ||||
|   //   (because the command fails to produce the expected output).  Therefore, it is reasonably
 | ||||
|   //   easy for commands to explicitly ensure all output is flushed before exiting, and it is
 | ||||
|   //   probably a good idea for them to do so anyway, because write failures should be detected
 | ||||
|   //   and handled.  For commands, a good strategy is to allocate any objects that require clean
 | ||||
|   //   destruction on the stack, and allow them to go out of scope before the command exits.
 | ||||
|   //   Meanwhile, any resources which do not need to be cleaned up should be allocated as members
 | ||||
|   //   of the command's main class, whose destructor normally will not be called.
 | ||||
|   //
 | ||||
|   // * Interactive apps:  Programs that interact with the user (whether they be graphical apps
 | ||||
|   //   with windows or console-based apps like emacs) generally exit only when the user asks them
 | ||||
|   //   to.  Such applications may store large data structures in memory which need to be synced
 | ||||
|   //   to disk, such as documents or user preferences.  However, relying on stack unwind or global
 | ||||
|   //   destructors as the mechanism for ensuring such syncing occurs is probably wrong.  First of
 | ||||
|   //   all, it's 2013, and applications ought to be actively syncing changes to non-volatile
 | ||||
|   //   storage the moment those changes are made.  Applications can crash at any time and a crash
 | ||||
|   //   should never lose data that is more than half a second old.  Meanwhile, if a user actually
 | ||||
|   //   does try to close an application while unsaved changes exist, the application UI should
 | ||||
|   //   prompt the user to decide what to do.  Such a UI mechanism is obviously too high level to
 | ||||
|   //   be implemented via destructors, so KJ's use of _Exit() shouldn't make a difference here.
 | ||||
|   //
 | ||||
|   // * Servers:  A good server is fault-tolerant, prepared for the possibility that at any time
 | ||||
|   //   it could crash, the OS could decide to kill it off, or the machine it is running on could
 | ||||
|   //   just die.  So, using _Exit() should be no problem.  In fact, servers generally never even
 | ||||
|   //   call exit anyway; they are killed externally.
 | ||||
|   //
 | ||||
|   // * Batch jobs:  A long-running batch job is something between a command and a server.  It
 | ||||
|   //   probably knows exactly what needs to be flushed before exiting, and it probably should be
 | ||||
|   //   fault-tolerant.
 | ||||
|   //
 | ||||
|   // Meanwhile, regardless of program type, if you are adhering to KJ style, then the use of
 | ||||
|   // _Exit() shouldn't be a problem anyway:
 | ||||
|   //
 | ||||
|   // * KJ style forbids global mutable state (singletons) in general and global constructors and
 | ||||
|   //   destructors in particular.  Therefore, everything that could possibly need cleanup either
 | ||||
|   //   lives on the stack or is transitively owned by something living on the stack.
 | ||||
|   //
 | ||||
|   // * Calling exit() simply means "Don't clean up anything older than this stack frame.".  If you
 | ||||
|   //   have resources that require cleanup before exit, make sure they are owned by stack frames
 | ||||
|   //   beyond the one that eventually calls exit().  To be as safe as possible, don't place any
 | ||||
|   //   state in your program's main class, and don't call exit() yourself.  Then, runMainAndExit()
 | ||||
|   //   will do it, and the only thing on the stack at that time will be your main class, which
 | ||||
|   //   has no state anyway.
 | ||||
|   //
 | ||||
|   // TODO(someday):  Perhaps we should use the new std::quick_exit(), so that at_quick_exit() is
 | ||||
|   //   available for those who really think they need it.  Unfortunately, it is not yet available
 | ||||
|   //   on many platforms.
 | ||||
| 
 | ||||
|   virtual void warning(StringPtr message) = 0; | ||||
|   // Print the given message to standard error.  A newline is printed after the message if it
 | ||||
|   // doesn't already have one.
 | ||||
| 
 | ||||
|   virtual void error(StringPtr message) = 0; | ||||
|   // Like `warning()`, but also sets a flag indicating that the process has failed, and that when
 | ||||
|   // it eventually exits it should indicate an error status.
 | ||||
| 
 | ||||
|   KJ_NORETURN(virtual void exitError(StringPtr message)) = 0; | ||||
|   // Equivalent to `error(message)` followed by `exit()`.
 | ||||
| 
 | ||||
|   KJ_NORETURN(virtual void exitInfo(StringPtr message)) = 0; | ||||
|   // Displays the given non-error message to the user and then calls `exit()`.  This is used to
 | ||||
|   // implement things like --help.
 | ||||
| 
 | ||||
|   virtual void increaseLoggingVerbosity() = 0; | ||||
|   // Increase the level of detail produced by the debug logging system.  `MainBuilder` invokes
 | ||||
|   // this if the caller uses the -v flag.
 | ||||
| 
 | ||||
|   // TODO(someday):  Add interfaces representing standard OS resources like the filesystem, so that
 | ||||
|   //   these things can be mocked out.
 | ||||
| }; | ||||
| 
 | ||||
| class TopLevelProcessContext final: public ProcessContext { | ||||
|   // A ProcessContext implementation appropriate for use at the actual entry point of a process
 | ||||
|   // (as opposed to when you are trying to call a program's main function from within some other
 | ||||
|   // program).  This implementation writes errors to stderr, and its `exit()` method actually
 | ||||
|   // calls the C `quick_exit()` function.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit TopLevelProcessContext(StringPtr programName); | ||||
| 
 | ||||
|   struct CleanShutdownException { int exitCode; }; | ||||
|   // If the environment variable KJ_CLEAN_SHUTDOWN is set, then exit() will actually throw this
 | ||||
|   // exception rather than exiting.  `kj::runMain()` catches this exception and returns normally.
 | ||||
|   // This is useful primarily for testing purposes, to assist tools like memory leak checkers that
 | ||||
|   // are easily confused by quick_exit().
 | ||||
| 
 | ||||
|   StringPtr getProgramName() override; | ||||
|   KJ_NORETURN(void exit() override); | ||||
|   void warning(StringPtr message) override; | ||||
|   void error(StringPtr message) override; | ||||
|   KJ_NORETURN(void exitError(StringPtr message) override); | ||||
|   KJ_NORETURN(void exitInfo(StringPtr message) override); | ||||
|   void increaseLoggingVerbosity() override; | ||||
| 
 | ||||
| private: | ||||
|   StringPtr programName; | ||||
|   bool cleanShutdown; | ||||
|   bool hadErrors = false; | ||||
| }; | ||||
| 
 | ||||
| typedef Function<void(StringPtr programName, ArrayPtr<const StringPtr> params)> MainFunc; | ||||
| 
 | ||||
| int runMainAndExit(ProcessContext& context, MainFunc&& func, int argc, char* argv[]); | ||||
| // Runs the given main function and then exits using the given context.  If an exception is thrown,
 | ||||
| // this will catch it, report it via the context and exit with an error code.
 | ||||
| //
 | ||||
| // Normally this function does not return, because returning would probably lead to wasting time
 | ||||
| // on cleanup when the process is just going to exit anyway.  However, to facilitate memory leak
 | ||||
| // checkers and other tools that require a clean shutdown to do their job, if the environment
 | ||||
| // variable KJ_CLEAN_SHUTDOWN is set, the function will in fact return an exit code, which should
 | ||||
| // then be returned from main().
 | ||||
| //
 | ||||
| // Most users will use the KJ_MAIN() macro rather than call this function directly.
 | ||||
| 
 | ||||
| #define KJ_MAIN(MainClass) \ | ||||
|   int main(int argc, char* argv[]) { \
 | ||||
|     ::kj::TopLevelProcessContext context(argv[0]); \
 | ||||
|     MainClass mainObject(context); \
 | ||||
|     return ::kj::runMainAndExit(context, mainObject.getMain(), argc, argv); \
 | ||||
|   } | ||||
| // Convenience macro for declaring a main function based on the given class.  The class must have
 | ||||
| // a constructor that accepts a ProcessContext& and a method getMain() which returns
 | ||||
| // kj::MainFunc (probably building it using a MainBuilder).
 | ||||
| 
 | ||||
| class MainBuilder { | ||||
|   // Builds a main() function with nice argument parsing.  As options and arguments are parsed,
 | ||||
|   // corresponding callbacks are called, so that you never have to write a massive switch()
 | ||||
|   // statement to interpret arguments.  Additionally, this approach encourages you to write
 | ||||
|   // main classes that have a reasonable API that can be used as an alternative to their
 | ||||
|   // command-line interface.
 | ||||
|   //
 | ||||
|   // All StringPtrs passed to MainBuilder must remain valid until option parsing completes.  The
 | ||||
|   // assumption is that these strings will all be literals, making this an easy requirement.  If
 | ||||
|   // not, consider allocating them in an Arena.
 | ||||
|   //
 | ||||
|   // Some flags are automatically recognized by the main functions built by this class:
 | ||||
|   //     --help:  Prints help text and exits.  The help text is constructed based on the
 | ||||
|   //       information you provide to the builder as you define each flag.
 | ||||
|   //     --verbose:  Increase logging verbosity.
 | ||||
|   //     --version:  Print version information and exit.
 | ||||
|   //
 | ||||
|   // Example usage:
 | ||||
|   //
 | ||||
|   //     class FooMain {
 | ||||
|   //     public:
 | ||||
|   //       FooMain(kj::ProcessContext& context): context(context) {}
 | ||||
|   //
 | ||||
|   //       bool setAll() { all = true; return true; }
 | ||||
|   //       // Enable the --all flag.
 | ||||
|   //
 | ||||
|   //       kj::MainBuilder::Validity setOutput(kj::StringPtr name) {
 | ||||
|   //         // Set the output file.
 | ||||
|   //
 | ||||
|   //         if (name.endsWith(".foo")) {
 | ||||
|   //           outputFile = name;
 | ||||
|   //           return true;
 | ||||
|   //         } else {
 | ||||
|   //           return "Output file must have extension .foo.";
 | ||||
|   //         }
 | ||||
|   //       }
 | ||||
|   //
 | ||||
|   //       kj::MainBuilder::Validity processInput(kj::StringPtr name) {
 | ||||
|   //         // Process an input file.
 | ||||
|   //
 | ||||
|   //         if (!exists(name)) {
 | ||||
|   //           return kj::str(name, ": file not found");
 | ||||
|   //         }
 | ||||
|   //         // ... process the input file ...
 | ||||
|   //         return true;
 | ||||
|   //       }
 | ||||
|   //
 | ||||
|   //       kj::MainFunc getMain() {
 | ||||
|   //         return MainBuilder(context, "Foo Builder v1.5", "Reads <source>s and builds a Foo.")
 | ||||
|   //             .addOption({'a', "all"}, KJ_BIND_METHOD(*this, setAll),
 | ||||
|   //                 "Frob all the widgets.  Otherwise, only some widgets are frobbed.")
 | ||||
|   //             .addOptionWithArg({'o', "output"}, KJ_BIND_METHOD(*this, setOutput),
 | ||||
|   //                 "<filename>", "Output to <filename>.  Must be a .foo file.")
 | ||||
|   //             .expectOneOrMoreArgs("<source>", KJ_BIND_METHOD(*this, processInput))
 | ||||
|   //             .build();
 | ||||
|   //       }
 | ||||
|   //
 | ||||
|   //     private:
 | ||||
|   //       bool all = false;
 | ||||
|   //       kj::StringPtr outputFile;
 | ||||
|   //       kj::ProcessContext& context;
 | ||||
|   //     };
 | ||||
| 
 | ||||
| public: | ||||
|   MainBuilder(ProcessContext& context, StringPtr version, | ||||
|               StringPtr briefDescription, StringPtr extendedDescription = nullptr); | ||||
|   ~MainBuilder() noexcept(false); | ||||
| 
 | ||||
|   class OptionName { | ||||
|   public: | ||||
|     OptionName() = default; | ||||
|     inline OptionName(char shortName): isLong(false), shortName(shortName) {} | ||||
|     inline OptionName(const char* longName): isLong(true), longName(longName) {} | ||||
| 
 | ||||
|   private: | ||||
|     bool isLong; | ||||
|     union { | ||||
|       char shortName; | ||||
|       const char* longName; | ||||
|     }; | ||||
|     friend class MainBuilder; | ||||
|   }; | ||||
| 
 | ||||
|   class Validity { | ||||
|   public: | ||||
|     inline Validity(bool valid) { | ||||
|       if (!valid) errorMessage = heapString("invalid argument"); | ||||
|     } | ||||
|     inline Validity(const char* errorMessage) | ||||
|         : errorMessage(heapString(errorMessage)) {} | ||||
|     inline Validity(String&& errorMessage) | ||||
|         : errorMessage(kj::mv(errorMessage)) {} | ||||
| 
 | ||||
|     inline const Maybe<String>& getError() const { return errorMessage; } | ||||
|     inline Maybe<String> releaseError() { return kj::mv(errorMessage); } | ||||
| 
 | ||||
|   private: | ||||
|     Maybe<String> errorMessage; | ||||
|     friend class MainBuilder; | ||||
|   }; | ||||
| 
 | ||||
|   MainBuilder& addOption(std::initializer_list<OptionName> names, Function<Validity()> callback, | ||||
|                          StringPtr helpText); | ||||
|   // Defines a new option (flag).  `names` is a list of characters and strings that can be used to
 | ||||
|   // specify the option on the command line.  Single-character names are used with "-" while string
 | ||||
|   // names are used with "--".  `helpText` is a natural-language description of the flag.
 | ||||
|   //
 | ||||
|   // `callback` is called when the option is seen.  Its return value indicates whether the option
 | ||||
|   // was accepted.  If not, further option processing stops, and error is written, and the process
 | ||||
|   // exits.
 | ||||
|   //
 | ||||
|   // Example:
 | ||||
|   //
 | ||||
|   //     builder.addOption({'a', "all"}, KJ_BIND_METHOD(*this, showAll), "Show all files.");
 | ||||
|   //
 | ||||
|   // This option could be specified in the following ways:
 | ||||
|   //
 | ||||
|   //     -a
 | ||||
|   //     --all
 | ||||
|   //
 | ||||
|   // Note that single-character option names can be combined into a single argument.  For example,
 | ||||
|   // `-abcd` is equivalent to `-a -b -c -d`.
 | ||||
|   //
 | ||||
|   // The help text for this option would look like:
 | ||||
|   //
 | ||||
|   //     -a, --all
 | ||||
|   //         Show all files.
 | ||||
|   //
 | ||||
|   // Note that help text is automatically word-wrapped.
 | ||||
| 
 | ||||
|   MainBuilder& addOptionWithArg(std::initializer_list<OptionName> names, | ||||
|                                 Function<Validity(StringPtr)> callback, | ||||
|                                 StringPtr argumentTitle, StringPtr helpText); | ||||
|   // Like `addOption()`, but adds an option which accepts an argument.  `argumentTitle` is used in
 | ||||
|   // the help text.  The argument text is passed to the callback.
 | ||||
|   //
 | ||||
|   // Example:
 | ||||
|   //
 | ||||
|   //     builder.addOptionWithArg({'o', "output"}, KJ_BIND_METHOD(*this, setOutput),
 | ||||
|   //                              "<filename>", "Output to <filename>.");
 | ||||
|   //
 | ||||
|   // This option could be specified with an argument of "foo" in the following ways:
 | ||||
|   //
 | ||||
|   //     -ofoo
 | ||||
|   //     -o foo
 | ||||
|   //     --output=foo
 | ||||
|   //     --output foo
 | ||||
|   //
 | ||||
|   // Note that single-character option names can be combined, but only the last option can have an
 | ||||
|   // argument, since the characters after the option letter are interpreted as the argument.  E.g.
 | ||||
|   // `-abofoo` would be equivalent to `-a -b -o foo`.
 | ||||
|   //
 | ||||
|   // The help text for this option would look like:
 | ||||
|   //
 | ||||
|   //     -o FILENAME, --output=FILENAME
 | ||||
|   //         Output to FILENAME.
 | ||||
| 
 | ||||
|   MainBuilder& addSubCommand(StringPtr name, Function<MainFunc()> getSubParser, | ||||
|                              StringPtr briefHelpText); | ||||
|   // If exactly the given name is seen as an argument, invoke getSubParser() and then pass all
 | ||||
|   // remaining arguments to the parser it returns.  This is useful for implementing commands which
 | ||||
|   // have lots of sub-commands, like "git" (which has sub-commands "checkout", "branch", "pull",
 | ||||
|   // etc.).
 | ||||
|   //
 | ||||
|   // `getSubParser` is only called if the command is seen.  This avoids building main functions
 | ||||
|   // for commands that aren't used.
 | ||||
|   //
 | ||||
|   // `briefHelpText` should be brief enough to show immediately after the command name on a single
 | ||||
|   // line.  It will not be wrapped.  Users can use the built-in "help" command to get extended
 | ||||
|   // help on a particular command.
 | ||||
| 
 | ||||
|   MainBuilder& expectArg(StringPtr title, Function<Validity(StringPtr)> callback); | ||||
|   MainBuilder& expectOptionalArg(StringPtr title, Function<Validity(StringPtr)> callback); | ||||
|   MainBuilder& expectZeroOrMoreArgs(StringPtr title, Function<Validity(StringPtr)> callback); | ||||
|   MainBuilder& expectOneOrMoreArgs(StringPtr title, Function<Validity(StringPtr)> callback); | ||||
|   // Set callbacks to handle arguments.  `expectArg()` and `expectOptionalArg()` specify positional
 | ||||
|   // arguments with special handling, while `expect{Zero,One}OrMoreArgs()` specifies a handler for
 | ||||
|   // an argument list (the handler is called once for each argument in the list).  `title`
 | ||||
|   // specifies how the argument should be represented in the usage text.
 | ||||
|   //
 | ||||
|   // All options callbacks are called before argument callbacks, regardless of their ordering on
 | ||||
|   // the command line.  This matches GNU getopt's behavior of permuting non-flag arguments to the
 | ||||
|   // end of the argument list.  Also matching getopt, the special option "--" indicates that the
 | ||||
|   // rest of the command line is all arguments, not options, even if they start with '-'.
 | ||||
|   //
 | ||||
|   // The interpretation of positional arguments is fairly flexible.  The non-optional arguments can
 | ||||
|   // be expected at the beginning, end, or in the middle.  If more arguments are specified than
 | ||||
|   // the number of non-optional args, they are assigned to the optional argument handlers in the
 | ||||
|   // order of registration.
 | ||||
|   //
 | ||||
|   // For example, say you called:
 | ||||
|   //     builder.expectArg("<foo>", ...);
 | ||||
|   //     builder.expectOptionalArg("<bar>", ...);
 | ||||
|   //     builder.expectArg("<baz>", ...);
 | ||||
|   //     builder.expectZeroOrMoreArgs("<qux>", ...);
 | ||||
|   //     builder.expectArg("<corge>", ...);
 | ||||
|   //
 | ||||
|   // This command requires at least three arguments: foo, baz, and corge.  If four arguments are
 | ||||
|   // given, the second is assigned to bar.  If five or more arguments are specified, then the
 | ||||
|   // arguments between the third and last are assigned to qux.  Note that it never makes sense
 | ||||
|   // to call `expect*OrMoreArgs()` more than once since only the first call would ever be used.
 | ||||
|   //
 | ||||
|   // In practice, you probably shouldn't create such complicated commands as in the above example.
 | ||||
|   // But, this flexibility seems necessary to support commands where the first argument is special
 | ||||
|   // as well as commands (like `cp`) where the last argument is special.
 | ||||
| 
 | ||||
|   MainBuilder& callAfterParsing(Function<Validity()> callback); | ||||
|   // Call the given function after all arguments have been parsed.
 | ||||
| 
 | ||||
|   MainFunc build(); | ||||
|   // Build the "main" function, which simply parses the arguments.  Once this returns, the
 | ||||
|   // `MainBuilder` is no longer valid.
 | ||||
| 
 | ||||
| private: | ||||
|   struct Impl; | ||||
|   Own<Impl> impl; | ||||
| 
 | ||||
|   class MainImpl; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_MAIN_H_
 | ||||
| @ -0,0 +1,406 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_MEMORY_H_ | ||||
| #define KJ_MEMORY_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "common.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Disposer -- Implementation details.
 | ||||
| 
 | ||||
| class Disposer { | ||||
|   // Abstract interface for a thing that "disposes" of objects, where "disposing" usually means
 | ||||
|   // calling the destructor followed by freeing the underlying memory.  `Own<T>` encapsulates an
 | ||||
|   // object pointer with corresponding Disposer.
 | ||||
|   //
 | ||||
|   // Few developers will ever touch this interface.  It is primarily useful for those implementing
 | ||||
|   // custom memory allocators.
 | ||||
| 
 | ||||
| protected: | ||||
|   // Do not declare a destructor, as doing so will force a global initializer for each HeapDisposer
 | ||||
|   // instance.  Eww!
 | ||||
| 
 | ||||
|   virtual void disposeImpl(void* pointer) const = 0; | ||||
|   // Disposes of the object, given a pointer to the beginning of the object.  If the object is
 | ||||
|   // polymorphic, this pointer is determined by dynamic_cast<void*>().  For non-polymorphic types,
 | ||||
|   // Own<T> does not allow any casting, so the pointer exactly matches the original one given to
 | ||||
|   // Own<T>.
 | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|   template <typename T> | ||||
|   void dispose(T* object) const; | ||||
|   // Helper wrapper around disposeImpl().
 | ||||
|   //
 | ||||
|   // If T is polymorphic, calls `disposeImpl(dynamic_cast<void*>(object))`, otherwise calls
 | ||||
|   // `disposeImpl(implicitCast<void*>(object))`.
 | ||||
|   //
 | ||||
|   // Callers must not call dispose() on the same pointer twice, even if the first call throws
 | ||||
|   // an exception.
 | ||||
| 
 | ||||
| private: | ||||
|   template <typename T, bool polymorphic = __is_polymorphic(T)> | ||||
|   struct Dispose_; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class DestructorOnlyDisposer: public Disposer { | ||||
|   // A disposer that merely calls the type's destructor and nothing else.
 | ||||
| 
 | ||||
| public: | ||||
|   static const DestructorOnlyDisposer instance; | ||||
| 
 | ||||
|   void disposeImpl(void* pointer) const override { | ||||
|     reinterpret_cast<T*>(pointer)->~T(); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| const DestructorOnlyDisposer<T> DestructorOnlyDisposer<T>::instance = DestructorOnlyDisposer<T>(); | ||||
| 
 | ||||
| class NullDisposer: public Disposer { | ||||
|   // A disposer that does nothing.
 | ||||
| 
 | ||||
| public: | ||||
|   static const NullDisposer instance; | ||||
| 
 | ||||
|   void disposeImpl(void* pointer) const override {} | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Own<T> -- An owned pointer.
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class Own { | ||||
|   // A transferrable title to a T.  When an Own<T> goes out of scope, the object's Disposer is
 | ||||
|   // called to dispose of it.  An Own<T> can be efficiently passed by move, without relocating the
 | ||||
|   // underlying object; this transfers ownership.
 | ||||
|   //
 | ||||
|   // This is much like std::unique_ptr, except:
 | ||||
|   // - You cannot release().  An owned object is not necessarily allocated with new (see next
 | ||||
|   //   point), so it would be hard to use release() correctly.
 | ||||
|   // - The deleter is made polymorphic by virtual call rather than by template.  This is much
 | ||||
|   //   more powerful -- it allows the use of custom allocators, freelists, etc.  This could
 | ||||
|   //   _almost_ be accomplished with unique_ptr by forcing everyone to use something like
 | ||||
|   //   std::unique_ptr<T, kj::Deleter>, except that things get hairy in the presence of multiple
 | ||||
|   //   inheritance and upcasting, and anyway if you force everyone to use a custom deleter
 | ||||
|   //   then you've lost any benefit to interoperating with the "standard" unique_ptr.
 | ||||
| 
 | ||||
| public: | ||||
|   KJ_DISALLOW_COPY(Own); | ||||
|   inline Own(): disposer(nullptr), ptr(nullptr) {} | ||||
|   inline Own(Own&& other) noexcept | ||||
|       : disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; } | ||||
|   inline Own(Own<RemoveConstOrDisable<T>>&& other) noexcept | ||||
|       : disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; } | ||||
|   template <typename U, typename = EnableIf<canConvert<U*, T*>()>> | ||||
|   inline Own(Own<U>&& other) noexcept | ||||
|       : disposer(other.disposer), ptr(other.ptr) { | ||||
|     static_assert(__is_polymorphic(T), | ||||
|         "Casting owned pointers requires that the target type is polymorphic."); | ||||
|     other.ptr = nullptr; | ||||
|   } | ||||
|   inline Own(T* ptr, const Disposer& disposer) noexcept: disposer(&disposer), ptr(ptr) {} | ||||
| 
 | ||||
|   ~Own() noexcept(false) { dispose(); } | ||||
| 
 | ||||
|   inline Own& operator=(Own&& other) { | ||||
|     // Move-assingnment operator.
 | ||||
| 
 | ||||
|     // Careful, this might own `other`.  Therefore we have to transfer the pointers first, then
 | ||||
|     // dispose.
 | ||||
|     const Disposer* disposerCopy = disposer; | ||||
|     T* ptrCopy = ptr; | ||||
|     disposer = other.disposer; | ||||
|     ptr = other.ptr; | ||||
|     other.ptr = nullptr; | ||||
|     if (ptrCopy != nullptr) { | ||||
|       disposerCopy->dispose(const_cast<RemoveConst<T>*>(ptrCopy)); | ||||
|     } | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   inline Own& operator=(decltype(nullptr)) { | ||||
|     dispose(); | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   template <typename U> | ||||
|   Own<U> downcast() { | ||||
|     // Downcast the pointer to Own<U>, destroying the original pointer.  If this pointer does not
 | ||||
|     // actually point at an instance of U, the results are undefined (throws an exception in debug
 | ||||
|     // mode if RTTI is enabled, otherwise you're on your own).
 | ||||
| 
 | ||||
|     Own<U> result; | ||||
|     if (ptr != nullptr) { | ||||
|       result.ptr = &kj::downcast<U>(*ptr); | ||||
|       result.disposer = disposer; | ||||
|       ptr = nullptr; | ||||
|     } | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
| #define NULLCHECK KJ_IREQUIRE(ptr != nullptr, "null Own<> dereference") | ||||
|   inline T* operator->() { NULLCHECK; return ptr; } | ||||
|   inline const T* operator->() const { NULLCHECK; return ptr; } | ||||
|   inline T& operator*() { NULLCHECK; return *ptr; } | ||||
|   inline const T& operator*() const { NULLCHECK; return *ptr; } | ||||
| #undef NULLCHECK | ||||
|   inline T* get() { return ptr; } | ||||
|   inline const T* get() const { return ptr; } | ||||
|   inline operator T*() { return ptr; } | ||||
|   inline operator const T*() const { return ptr; } | ||||
| 
 | ||||
| private: | ||||
|   const Disposer* disposer;  // Only valid if ptr != nullptr.
 | ||||
|   T* ptr; | ||||
| 
 | ||||
|   inline explicit Own(decltype(nullptr)): disposer(nullptr), ptr(nullptr) {} | ||||
| 
 | ||||
|   inline bool operator==(decltype(nullptr)) { return ptr == nullptr; } | ||||
|   inline bool operator!=(decltype(nullptr)) { return ptr != nullptr; } | ||||
|   // Only called by Maybe<Own<T>>.
 | ||||
| 
 | ||||
|   inline void dispose() { | ||||
|     // Make sure that if an exception is thrown, we are left with a null ptr, so we won't possibly
 | ||||
|     // dispose again.
 | ||||
|     T* ptrCopy = ptr; | ||||
|     if (ptrCopy != nullptr) { | ||||
|       ptr = nullptr; | ||||
|       disposer->dispose(const_cast<RemoveConst<T>*>(ptrCopy)); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   template <typename U> | ||||
|   friend class Own; | ||||
|   friend class Maybe<Own<T>>; | ||||
| }; | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class OwnOwn { | ||||
| public: | ||||
|   inline OwnOwn(Own<T>&& value) noexcept: value(kj::mv(value)) {} | ||||
| 
 | ||||
|   inline Own<T>& operator*() & { return value; } | ||||
|   inline const Own<T>& operator*() const & { return value; } | ||||
|   inline Own<T>&& operator*() && { return kj::mv(value); } | ||||
|   inline const Own<T>&& operator*() const && { return kj::mv(value); } | ||||
|   inline Own<T>* operator->() { return &value; } | ||||
|   inline const Own<T>* operator->() const { return &value; } | ||||
|   inline operator Own<T>*() { return value ? &value : nullptr; } | ||||
|   inline operator const Own<T>*() const { return value ? &value : nullptr; } | ||||
| 
 | ||||
| private: | ||||
|   Own<T> value; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| OwnOwn<T> readMaybe(Maybe<Own<T>>&& maybe) { return OwnOwn<T>(kj::mv(maybe.ptr)); } | ||||
| template <typename T> | ||||
| Own<T>* readMaybe(Maybe<Own<T>>& maybe) { return maybe.ptr ? &maybe.ptr : nullptr; } | ||||
| template <typename T> | ||||
| const Own<T>* readMaybe(const Maybe<Own<T>>& maybe) { return maybe.ptr ? &maybe.ptr : nullptr; } | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class Maybe<Own<T>> { | ||||
| public: | ||||
|   inline Maybe(): ptr(nullptr) {} | ||||
|   inline Maybe(Own<T>&& t) noexcept: ptr(kj::mv(t)) {} | ||||
|   inline Maybe(Maybe&& other) noexcept: ptr(kj::mv(other.ptr)) {} | ||||
| 
 | ||||
|   template <typename U> | ||||
|   inline Maybe(Maybe<Own<U>>&& other): ptr(mv(other.ptr)) {} | ||||
|   template <typename U> | ||||
|   inline Maybe(Own<U>&& other): ptr(mv(other)) {} | ||||
| 
 | ||||
|   inline Maybe(decltype(nullptr)) noexcept: ptr(nullptr) {} | ||||
| 
 | ||||
|   inline operator Maybe<T&>() { return ptr.get(); } | ||||
|   inline operator Maybe<const T&>() const { return ptr.get(); } | ||||
| 
 | ||||
|   inline Maybe& operator=(Maybe&& other) { ptr = kj::mv(other.ptr); return *this; } | ||||
| 
 | ||||
|   inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; } | ||||
|   inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; } | ||||
| 
 | ||||
|   Own<T>& orDefault(Own<T>& defaultValue) { | ||||
|     if (ptr == nullptr) { | ||||
|       return defaultValue; | ||||
|     } else { | ||||
|       return ptr; | ||||
|     } | ||||
|   } | ||||
|   const Own<T>& orDefault(const Own<T>& defaultValue) const { | ||||
|     if (ptr == nullptr) { | ||||
|       return defaultValue; | ||||
|     } else { | ||||
|       return ptr; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   template <typename Func> | ||||
|   auto map(Func&& f) & -> Maybe<decltype(f(instance<Own<T>&>()))> { | ||||
|     if (ptr == nullptr) { | ||||
|       return nullptr; | ||||
|     } else { | ||||
|       return f(ptr); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   template <typename Func> | ||||
|   auto map(Func&& f) const & -> Maybe<decltype(f(instance<const Own<T>&>()))> { | ||||
|     if (ptr == nullptr) { | ||||
|       return nullptr; | ||||
|     } else { | ||||
|       return f(ptr); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   template <typename Func> | ||||
|   auto map(Func&& f) && -> Maybe<decltype(f(instance<Own<T>&&>()))> { | ||||
|     if (ptr == nullptr) { | ||||
|       return nullptr; | ||||
|     } else { | ||||
|       return f(kj::mv(ptr)); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   template <typename Func> | ||||
|   auto map(Func&& f) const && -> Maybe<decltype(f(instance<const Own<T>&&>()))> { | ||||
|     if (ptr == nullptr) { | ||||
|       return nullptr; | ||||
|     } else { | ||||
|       return f(kj::mv(ptr)); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   Own<T> ptr; | ||||
| 
 | ||||
|   template <typename U> | ||||
|   friend class Maybe; | ||||
|   template <typename U> | ||||
|   friend _::OwnOwn<U> _::readMaybe(Maybe<Own<U>>&& maybe); | ||||
|   template <typename U> | ||||
|   friend Own<U>* _::readMaybe(Maybe<Own<U>>& maybe); | ||||
|   template <typename U> | ||||
|   friend const Own<U>* _::readMaybe(const Maybe<Own<U>>& maybe); | ||||
| }; | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class HeapDisposer final: public Disposer { | ||||
| public: | ||||
|   virtual void disposeImpl(void* pointer) const override { delete reinterpret_cast<T*>(pointer); } | ||||
| 
 | ||||
|   static const HeapDisposer instance; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| const HeapDisposer<T> HeapDisposer<T>::instance = HeapDisposer<T>(); | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename T, typename... Params> | ||||
| Own<T> heap(Params&&... params) { | ||||
|   // heap<T>(...) allocates a T on the heap, forwarding the parameters to its constructor.  The
 | ||||
|   // exact heap implementation is unspecified -- for now it is operator new, but you should not
 | ||||
|   // assume this.  (Since we know the object size at delete time, we could actually implement an
 | ||||
|   // allocator that is more efficient than operator new.)
 | ||||
| 
 | ||||
|   return Own<T>(new T(kj::fwd<Params>(params)...), _::HeapDisposer<T>::instance); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| Own<Decay<T>> heap(T&& orig) { | ||||
|   // Allocate a copy (or move) of the argument on the heap.
 | ||||
|   //
 | ||||
|   // The purpose of this overload is to allow you to omit the template parameter as there is only
 | ||||
|   // one argument and the purpose is to copy it.
 | ||||
| 
 | ||||
|   typedef Decay<T> T2; | ||||
|   return Own<T2>(new T2(kj::fwd<T>(orig)), _::HeapDisposer<T2>::instance); | ||||
| } | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // SpaceFor<T> -- assists in manual allocation
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class SpaceFor { | ||||
|   // A class which has the same size and alignment as T but does not call its constructor or
 | ||||
|   // destructor automatically.  Instead, call construct() to construct a T in the space, which
 | ||||
|   // returns an Own<T> which will take care of calling T's destructor later.
 | ||||
| 
 | ||||
| public: | ||||
|   inline SpaceFor() {} | ||||
|   inline ~SpaceFor() {} | ||||
| 
 | ||||
|   template <typename... Params> | ||||
|   Own<T> construct(Params&&... params) { | ||||
|     ctor(value, kj::fwd<Params>(params)...); | ||||
|     return Own<T>(&value, DestructorOnlyDisposer<T>::instance); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   union { | ||||
|     T value; | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Inline implementation details
 | ||||
| 
 | ||||
| template <typename T> | ||||
| struct Disposer::Dispose_<T, true> { | ||||
|   static void dispose(T* object, const Disposer& disposer) { | ||||
|     // Note that dynamic_cast<void*> does not require RTTI to be enabled, because the offset to
 | ||||
|     // the top of the object is in the vtable -- as it obviously needs to be to correctly implement
 | ||||
|     // operator delete.
 | ||||
|     disposer.disposeImpl(dynamic_cast<void*>(object)); | ||||
|   } | ||||
| }; | ||||
| template <typename T> | ||||
| struct Disposer::Dispose_<T, false> { | ||||
|   static void dispose(T* object, const Disposer& disposer) { | ||||
|     disposer.disposeImpl(static_cast<void*>(object)); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| void Disposer::dispose(T* object) const { | ||||
|   Dispose_<T>::dispose(object, *this); | ||||
| } | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_MEMORY_H_
 | ||||
| @ -0,0 +1,369 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_MUTEX_H_ | ||||
| #define KJ_MUTEX_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "memory.h" | ||||
| #include <inttypes.h> | ||||
| 
 | ||||
| #if __linux__ && !defined(KJ_USE_FUTEX) | ||||
| #define KJ_USE_FUTEX 1 | ||||
| #endif | ||||
| 
 | ||||
| #if !KJ_USE_FUTEX && !_WIN32 | ||||
| // On Linux we use futex.  On other platforms we wrap pthreads.
 | ||||
| // TODO(someday):  Write efficient low-level locking primitives for other platforms.
 | ||||
| #include <pthread.h> | ||||
| #endif | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Private details -- public interfaces follow below.
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| class Mutex { | ||||
|   // Internal implementation details.  See `MutexGuarded<T>`.
 | ||||
| 
 | ||||
| public: | ||||
|   Mutex(); | ||||
|   ~Mutex(); | ||||
|   KJ_DISALLOW_COPY(Mutex); | ||||
| 
 | ||||
|   enum Exclusivity { | ||||
|     EXCLUSIVE, | ||||
|     SHARED | ||||
|   }; | ||||
| 
 | ||||
|   void lock(Exclusivity exclusivity); | ||||
|   void unlock(Exclusivity exclusivity); | ||||
| 
 | ||||
|   void assertLockedByCaller(Exclusivity exclusivity); | ||||
|   // In debug mode, assert that the mutex is locked by the calling thread, or if that is
 | ||||
|   // non-trivial, assert that the mutex is locked (which should be good enough to catch problems
 | ||||
|   // in unit tests).  In non-debug builds, do nothing.
 | ||||
| 
 | ||||
| private: | ||||
| #if KJ_USE_FUTEX | ||||
|   uint futex; | ||||
|   // bit 31 (msb) = set if exclusive lock held
 | ||||
|   // bit 30 (msb) = set if threads are waiting for exclusive lock
 | ||||
|   // bits 0-29 = count of readers; If an exclusive lock is held, this is the count of threads
 | ||||
|   //   waiting for a read lock, otherwise it is the count of threads that currently hold a read
 | ||||
|   //   lock.
 | ||||
| 
 | ||||
|   static constexpr uint EXCLUSIVE_HELD = 1u << 31; | ||||
|   static constexpr uint EXCLUSIVE_REQUESTED = 1u << 30; | ||||
|   static constexpr uint SHARED_COUNT_MASK = EXCLUSIVE_REQUESTED - 1; | ||||
| 
 | ||||
| #elif _WIN32 | ||||
|   uintptr_t srwLock;  // Actually an SRWLOCK, but don't want to #include <windows.h> in header.
 | ||||
| 
 | ||||
| #else | ||||
|   mutable pthread_rwlock_t mutex; | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| class Once { | ||||
|   // Internal implementation details.  See `Lazy<T>`.
 | ||||
| 
 | ||||
| public: | ||||
| #if KJ_USE_FUTEX | ||||
|   inline Once(bool startInitialized = false) | ||||
|       : futex(startInitialized ? INITIALIZED : UNINITIALIZED) {} | ||||
| #else | ||||
|   Once(bool startInitialized = false); | ||||
|   ~Once(); | ||||
| #endif | ||||
|   KJ_DISALLOW_COPY(Once); | ||||
| 
 | ||||
|   class Initializer { | ||||
|   public: | ||||
|     virtual void run() = 0; | ||||
|   }; | ||||
| 
 | ||||
|   void runOnce(Initializer& init); | ||||
| 
 | ||||
| #if _WIN32  // TODO(perf): Can we make this inline on win32 somehow?
 | ||||
|   bool isInitialized() noexcept; | ||||
| 
 | ||||
| #else | ||||
|   inline bool isInitialized() noexcept { | ||||
|     // Fast path check to see if runOnce() would simply return immediately.
 | ||||
| #if KJ_USE_FUTEX | ||||
|     return __atomic_load_n(&futex, __ATOMIC_ACQUIRE) == INITIALIZED; | ||||
| #else | ||||
|     return __atomic_load_n(&state, __ATOMIC_ACQUIRE) == INITIALIZED; | ||||
| #endif | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
|   void reset(); | ||||
|   // Returns the state from initialized to uninitialized.  It is an error to call this when
 | ||||
|   // not already initialized, or when runOnce() or isInitialized() might be called concurrently in
 | ||||
|   // another thread.
 | ||||
| 
 | ||||
| private: | ||||
| #if KJ_USE_FUTEX | ||||
|   uint futex; | ||||
| 
 | ||||
|   enum State { | ||||
|     UNINITIALIZED, | ||||
|     INITIALIZING, | ||||
|     INITIALIZING_WITH_WAITERS, | ||||
|     INITIALIZED | ||||
|   }; | ||||
| 
 | ||||
| #elif _WIN32 | ||||
|   uintptr_t initOnce;  // Actually an INIT_ONCE, but don't want to #include <windows.h> in header.
 | ||||
| 
 | ||||
| #else | ||||
|   enum State { | ||||
|     UNINITIALIZED, | ||||
|     INITIALIZED | ||||
|   }; | ||||
|   State state; | ||||
|   pthread_mutex_t mutex; | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Public interface
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class Locked { | ||||
|   // Return type for `MutexGuarded<T>::lock()`.  `Locked<T>` provides access to the bounded object
 | ||||
|   // and unlocks the mutex when it goes out of scope.
 | ||||
| 
 | ||||
| public: | ||||
|   KJ_DISALLOW_COPY(Locked); | ||||
|   inline Locked(): mutex(nullptr), ptr(nullptr) {} | ||||
|   inline Locked(Locked&& other): mutex(other.mutex), ptr(other.ptr) { | ||||
|     other.mutex = nullptr; | ||||
|     other.ptr = nullptr; | ||||
|   } | ||||
|   inline ~Locked() { | ||||
|     if (mutex != nullptr) mutex->unlock(isConst<T>() ? _::Mutex::SHARED : _::Mutex::EXCLUSIVE); | ||||
|   } | ||||
| 
 | ||||
|   inline Locked& operator=(Locked&& other) { | ||||
|     if (mutex != nullptr) mutex->unlock(isConst<T>() ? _::Mutex::SHARED : _::Mutex::EXCLUSIVE); | ||||
|     mutex = other.mutex; | ||||
|     ptr = other.ptr; | ||||
|     other.mutex = nullptr; | ||||
|     other.ptr = nullptr; | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   inline void release() { | ||||
|     if (mutex != nullptr) mutex->unlock(isConst<T>() ? _::Mutex::SHARED : _::Mutex::EXCLUSIVE); | ||||
|     mutex = nullptr; | ||||
|     ptr = nullptr; | ||||
|   } | ||||
| 
 | ||||
|   inline T* operator->() { return ptr; } | ||||
|   inline const T* operator->() const { return ptr; } | ||||
|   inline T& operator*() { return *ptr; } | ||||
|   inline const T& operator*() const { return *ptr; } | ||||
|   inline T* get() { return ptr; } | ||||
|   inline const T* get() const { return ptr; } | ||||
|   inline operator T*() { return ptr; } | ||||
|   inline operator const T*() const { return ptr; } | ||||
| 
 | ||||
| private: | ||||
|   _::Mutex* mutex; | ||||
|   T* ptr; | ||||
| 
 | ||||
|   inline Locked(_::Mutex& mutex, T& value): mutex(&mutex), ptr(&value) {} | ||||
| 
 | ||||
|   template <typename U> | ||||
|   friend class MutexGuarded; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class MutexGuarded { | ||||
|   // An object of type T, bounded by a mutex.  In order to access the object, you must lock it.
 | ||||
|   //
 | ||||
|   // Write locks are not "recursive" -- trying to lock again in a thread that already holds a lock
 | ||||
|   // will deadlock.  Recursive write locks are usually a sign of bad design.
 | ||||
|   //
 | ||||
|   // Unfortunately, **READ LOCKS ARE NOT RECURSIVE** either.  Common sense says they should be.
 | ||||
|   // But on many operating systems (BSD, OSX), recursively read-locking a pthread_rwlock is
 | ||||
|   // actually unsafe.  The problem is that writers are "prioritized" over readers, so a read lock
 | ||||
|   // request will block if any write lock requests are outstanding.  So, if thread A takes a read
 | ||||
|   // lock, thread B requests a write lock (and starts waiting), and then thread A tries to take
 | ||||
|   // another read lock recursively, the result is deadlock.
 | ||||
| 
 | ||||
| public: | ||||
|   template <typename... Params> | ||||
|   explicit MutexGuarded(Params&&... params); | ||||
|   // Initialize the mutex-bounded object by passing the given parameters to its constructor.
 | ||||
| 
 | ||||
|   Locked<T> lockExclusive() const; | ||||
|   // Exclusively locks the object and returns it.  The returned `Locked<T>` can be passed by
 | ||||
|   // move, similar to `Own<T>`.
 | ||||
|   //
 | ||||
|   // This method is declared `const` in accordance with KJ style rules which say that constness
 | ||||
|   // should be used to indicate thread-safety.  It is safe to share a const pointer between threads,
 | ||||
|   // but it is not safe to share a mutable pointer.  Since the whole point of MutexGuarded is to
 | ||||
|   // be shared between threads, its methods should be const, even though locking it produces a
 | ||||
|   // non-const pointer to the contained object.
 | ||||
| 
 | ||||
|   Locked<const T> lockShared() const; | ||||
|   // Lock the value for shared access.  Multiple shared locks can be taken concurrently, but cannot
 | ||||
|   // be held at the same time as a non-shared lock.
 | ||||
| 
 | ||||
|   inline const T& getWithoutLock() const { return value; } | ||||
|   inline T& getWithoutLock() { return value; } | ||||
|   // Escape hatch for cases where some external factor guarantees that it's safe to get the
 | ||||
|   // value.  You should treat these like const_cast -- be highly suspicious of any use.
 | ||||
| 
 | ||||
|   inline const T& getAlreadyLockedShared() const; | ||||
|   inline T& getAlreadyLockedShared(); | ||||
|   inline T& getAlreadyLockedExclusive() const; | ||||
|   // Like `getWithoutLock()`, but asserts that the lock is already held by the calling thread.
 | ||||
| 
 | ||||
| private: | ||||
|   mutable _::Mutex mutex; | ||||
|   mutable T value; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class MutexGuarded<const T> { | ||||
|   // MutexGuarded cannot guard a const type.  This would be pointless anyway, and would complicate
 | ||||
|   // the implementation of Locked<T>, which uses constness to decide what kind of lock it holds.
 | ||||
|   static_assert(sizeof(T) < 0, "MutexGuarded's type cannot be const."); | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class Lazy { | ||||
|   // A lazily-initialized value.
 | ||||
| 
 | ||||
| public: | ||||
|   template <typename Func> | ||||
|   T& get(Func&& init); | ||||
|   template <typename Func> | ||||
|   const T& get(Func&& init) const; | ||||
|   // The first thread to call get() will invoke the given init function to construct the value.
 | ||||
|   // Other threads will block until construction completes, then return the same value.
 | ||||
|   //
 | ||||
|   // `init` is a functor(typically a lambda) which takes `SpaceFor<T>&` as its parameter and returns
 | ||||
|   // `Own<T>`.  If `init` throws an exception, the exception is propagated out of that thread's
 | ||||
|   // call to `get()`, and subsequent calls behave as if `get()` hadn't been called at all yet --
 | ||||
|   // in other words, subsequent calls retry initialization until it succeeds.
 | ||||
| 
 | ||||
| private: | ||||
|   mutable _::Once once; | ||||
|   mutable SpaceFor<T> space; | ||||
|   mutable Own<T> value; | ||||
| 
 | ||||
|   template <typename Func> | ||||
|   class InitImpl; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Inline implementation details
 | ||||
| 
 | ||||
| template <typename T> | ||||
| template <typename... Params> | ||||
| inline MutexGuarded<T>::MutexGuarded(Params&&... params) | ||||
|     : value(kj::fwd<Params>(params)...) {} | ||||
| 
 | ||||
| template <typename T> | ||||
| inline Locked<T> MutexGuarded<T>::lockExclusive() const { | ||||
|   mutex.lock(_::Mutex::EXCLUSIVE); | ||||
|   return Locked<T>(mutex, value); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline Locked<const T> MutexGuarded<T>::lockShared() const { | ||||
|   mutex.lock(_::Mutex::SHARED); | ||||
|   return Locked<const T>(mutex, value); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline const T& MutexGuarded<T>::getAlreadyLockedShared() const { | ||||
| #ifdef KJ_DEBUG | ||||
|   mutex.assertLockedByCaller(_::Mutex::SHARED); | ||||
| #endif | ||||
|   return value; | ||||
| } | ||||
| template <typename T> | ||||
| inline T& MutexGuarded<T>::getAlreadyLockedShared() { | ||||
| #ifdef KJ_DEBUG | ||||
|   mutex.assertLockedByCaller(_::Mutex::SHARED); | ||||
| #endif | ||||
|   return value; | ||||
| } | ||||
| template <typename T> | ||||
| inline T& MutexGuarded<T>::getAlreadyLockedExclusive() const { | ||||
| #ifdef KJ_DEBUG | ||||
|   mutex.assertLockedByCaller(_::Mutex::EXCLUSIVE); | ||||
| #endif | ||||
|   return const_cast<T&>(value); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| template <typename Func> | ||||
| class Lazy<T>::InitImpl: public _::Once::Initializer { | ||||
| public: | ||||
|   inline InitImpl(const Lazy<T>& lazy, Func&& func): lazy(lazy), func(kj::fwd<Func>(func)) {} | ||||
| 
 | ||||
|   void run() override { | ||||
|     lazy.value = func(lazy.space); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   const Lazy<T>& lazy; | ||||
|   Func func; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| template <typename Func> | ||||
| inline T& Lazy<T>::get(Func&& init) { | ||||
|   if (!once.isInitialized()) { | ||||
|     InitImpl<Func> initImpl(*this, kj::fwd<Func>(init)); | ||||
|     once.runOnce(initImpl); | ||||
|   } | ||||
|   return *value; | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| template <typename Func> | ||||
| inline const T& Lazy<T>::get(Func&& init) const { | ||||
|   if (!once.isInitialized()) { | ||||
|     InitImpl<Func> initImpl(*this, kj::fwd<Func>(init)); | ||||
|     once.runOnce(initImpl); | ||||
|   } | ||||
|   return *value; | ||||
| } | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_MUTEX_H_
 | ||||
| @ -0,0 +1,155 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_ONE_OF_H_ | ||||
| #define KJ_ONE_OF_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "common.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <uint i, typename Key, typename First, typename... Rest> | ||||
| struct TypeIndex_ { static constexpr uint value = TypeIndex_<i + 1, Key, Rest...>::value; }; | ||||
| template <uint i, typename Key, typename... Rest> | ||||
| struct TypeIndex_<i, Key, Key, Rest...> { static constexpr uint value = i; }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename... Variants> | ||||
| class OneOf { | ||||
|   template <typename Key> | ||||
|   static inline constexpr uint typeIndex() { return _::TypeIndex_<1, Key, Variants...>::value; } | ||||
|   // Get the 1-based index of Key within the type list Types.
 | ||||
| 
 | ||||
| public: | ||||
|   inline OneOf(): tag(0) {} | ||||
|   OneOf(const OneOf& other) { copyFrom(other); } | ||||
|   OneOf(OneOf&& other) { moveFrom(other); } | ||||
|   ~OneOf() { destroy(); } | ||||
| 
 | ||||
|   OneOf& operator=(const OneOf& other) { if (tag != 0) destroy(); copyFrom(other); return *this; } | ||||
|   OneOf& operator=(OneOf&& other) { if (tag != 0) destroy(); moveFrom(other); return *this; } | ||||
| 
 | ||||
|   inline bool operator==(decltype(nullptr)) const { return tag == 0; } | ||||
|   inline bool operator!=(decltype(nullptr)) const { return tag != 0; } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   bool is() const { | ||||
|     return tag == typeIndex<T>(); | ||||
|   } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   T& get() { | ||||
|     KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>()."); | ||||
|     return *reinterpret_cast<T*>(space); | ||||
|   } | ||||
|   template <typename T> | ||||
|   const T& get() const { | ||||
|     KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>()."); | ||||
|     return *reinterpret_cast<const T*>(space); | ||||
|   } | ||||
| 
 | ||||
|   template <typename T, typename... Params> | ||||
|   T& init(Params&&... params) { | ||||
|     if (tag != 0) destroy(); | ||||
|     ctor(*reinterpret_cast<T*>(space), kj::fwd<Params>(params)...); | ||||
|     tag = typeIndex<T>(); | ||||
|     return *reinterpret_cast<T*>(space); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   uint tag; | ||||
| 
 | ||||
|   static inline constexpr size_t maxSize(size_t a) { | ||||
|     return a; | ||||
|   } | ||||
|   template <typename... Rest> | ||||
|   static inline constexpr size_t maxSize(size_t a, size_t b, Rest... rest) { | ||||
|     return maxSize(kj::max(a, b), rest...); | ||||
|   } | ||||
|   // Returns the maximum of all the parameters.
 | ||||
|   // TODO(someday):  Generalize the above template and make it common.  I tried, but C++ decided to
 | ||||
|   //   be difficult so I cut my losses.
 | ||||
| 
 | ||||
|   static constexpr auto spaceSize = maxSize(sizeof(Variants)...); | ||||
|   // TODO(msvc):  This constant could just as well go directly inside space's bracket's, where it's
 | ||||
|   // used, but MSVC suffers a parse error on `...`.
 | ||||
| 
 | ||||
|   union { | ||||
|     byte space[spaceSize]; | ||||
| 
 | ||||
|     void* forceAligned; | ||||
|     // TODO(someday):  Use C++11 alignas() once we require GCC 4.8 / Clang 3.3.
 | ||||
|   }; | ||||
| 
 | ||||
|   template <typename... T> | ||||
|   inline void doAll(T... t) {} | ||||
| 
 | ||||
|   template <typename T> | ||||
|   inline bool destroyVariant() { | ||||
|     if (tag == typeIndex<T>()) { | ||||
|       tag = 0; | ||||
|       dtor(*reinterpret_cast<T*>(space)); | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
|   void destroy() { | ||||
|     doAll(destroyVariant<Variants>()...); | ||||
|   } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   inline bool copyVariantFrom(const OneOf& other) { | ||||
|     if (other.is<T>()) { | ||||
|       ctor(*reinterpret_cast<T*>(space), other.get<T>()); | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
|   void copyFrom(const OneOf& other) { | ||||
|     // Initialize as a copy of `other`.  Expects that `this` starts out uninitialized, so the tag
 | ||||
|     // is invalid.
 | ||||
|     tag = other.tag; | ||||
|     doAll(copyVariantFrom<Variants>(other)...); | ||||
|   } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   inline bool moveVariantFrom(OneOf& other) { | ||||
|     if (other.is<T>()) { | ||||
|       ctor(*reinterpret_cast<T*>(space), kj::mv(other.get<T>())); | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
|   void moveFrom(OneOf& other) { | ||||
|     // Initialize as a copy of `other`.  Expects that `this` starts out uninitialized, so the tag
 | ||||
|     // is invalid.
 | ||||
|     tag = other.tag; | ||||
|     doAll(moveVariantFrom<Variants>(other)...); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_ONE_OF_H_
 | ||||
| @ -0,0 +1,361 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| // This file contains parsers useful for character stream inputs, including parsers to parse
 | ||||
| // common kinds of tokens like identifiers, numbers, and quoted strings.
 | ||||
| 
 | ||||
| #ifndef KJ_PARSE_CHAR_H_ | ||||
| #define KJ_PARSE_CHAR_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "common.h" | ||||
| #include "../string.h" | ||||
| #include <inttypes.h> | ||||
| 
 | ||||
| namespace kj { | ||||
| namespace parse { | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Exact char/string.
 | ||||
| 
 | ||||
| class ExactString_ { | ||||
| public: | ||||
|   constexpr inline ExactString_(const char* str): str(str) {} | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   Maybe<Tuple<>> operator()(Input& input) const { | ||||
|     const char* ptr = str; | ||||
| 
 | ||||
|     while (*ptr != '\0') { | ||||
|       if (input.atEnd() || input.current() != *ptr) return nullptr; | ||||
|       input.next(); | ||||
|       ++ptr; | ||||
|     } | ||||
| 
 | ||||
|     return Tuple<>(); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   const char* str; | ||||
| }; | ||||
| 
 | ||||
| constexpr inline ExactString_ exactString(const char* str) { | ||||
|   return ExactString_(str); | ||||
| } | ||||
| 
 | ||||
| template <char c> | ||||
| constexpr ExactlyConst_<char, c> exactChar() { | ||||
|   // Returns a parser that matches exactly the character given by the template argument (returning
 | ||||
|   // no result).
 | ||||
|   return ExactlyConst_<char, c>(); | ||||
| } | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Char ranges / sets
 | ||||
| 
 | ||||
| class CharGroup_ { | ||||
| public: | ||||
|   constexpr inline CharGroup_(): bits{0, 0, 0, 0} {} | ||||
| 
 | ||||
|   constexpr inline CharGroup_ orRange(unsigned char first, unsigned char last) const { | ||||
|     return CharGroup_(bits[0] | (oneBits(last +   1) & ~oneBits(first      )), | ||||
|                       bits[1] | (oneBits(last -  63) & ~oneBits(first -  64)), | ||||
|                       bits[2] | (oneBits(last - 127) & ~oneBits(first - 128)), | ||||
|                       bits[3] | (oneBits(last - 191) & ~oneBits(first - 192))); | ||||
|   } | ||||
| 
 | ||||
|   constexpr inline CharGroup_ orAny(const char* chars) const { | ||||
|     return *chars == 0 ? *this : orChar(*chars).orAny(chars + 1); | ||||
|   } | ||||
| 
 | ||||
|   constexpr inline CharGroup_ orChar(unsigned char c) const { | ||||
|     return CharGroup_(bits[0] | bit(c), | ||||
|                       bits[1] | bit(c - 64), | ||||
|                       bits[2] | bit(c - 128), | ||||
|                       bits[3] | bit(c - 256)); | ||||
|   } | ||||
| 
 | ||||
|   constexpr inline CharGroup_ orGroup(CharGroup_ other) const { | ||||
|     return CharGroup_(bits[0] | other.bits[0], | ||||
|                       bits[1] | other.bits[1], | ||||
|                       bits[2] | other.bits[2], | ||||
|                       bits[3] | other.bits[3]); | ||||
|   } | ||||
| 
 | ||||
|   constexpr inline CharGroup_ invert() const { | ||||
|     return CharGroup_(~bits[0], ~bits[1], ~bits[2], ~bits[3]); | ||||
|   } | ||||
| 
 | ||||
|   constexpr inline bool contains(unsigned char c) const { | ||||
|     return (bits[c / 64] & (1ll << (c % 64))) != 0; | ||||
|   } | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   Maybe<char> operator()(Input& input) const { | ||||
|     if (input.atEnd()) return nullptr; | ||||
|     unsigned char c = input.current(); | ||||
|     if (contains(c)) { | ||||
|       input.next(); | ||||
|       return c; | ||||
|     } else { | ||||
|       return nullptr; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   typedef unsigned long long Bits64; | ||||
| 
 | ||||
|   constexpr inline CharGroup_(Bits64 a, Bits64 b, Bits64 c, Bits64 d): bits{a, b, c, d} {} | ||||
|   Bits64 bits[4]; | ||||
| 
 | ||||
|   static constexpr inline Bits64 oneBits(int count) { | ||||
|     return count <= 0 ? 0ll : count >= 64 ? -1ll : ((1ll << count) - 1); | ||||
|   } | ||||
|   static constexpr inline Bits64 bit(int index) { | ||||
|     return index < 0 ? 0 : index >= 64 ? 0 : (1ll << index); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| constexpr inline CharGroup_ charRange(char first, char last) { | ||||
|   // Create a parser which accepts any character in the range from `first` to `last`, inclusive.
 | ||||
|   // For example: `charRange('a', 'z')` matches all lower-case letters.  The parser's result is the
 | ||||
|   // character matched.
 | ||||
|   //
 | ||||
|   // The returned object has methods which can be used to match more characters.  The following
 | ||||
|   // produces a parser which accepts any letter as well as '_', '+', '-', and '.'.
 | ||||
|   //
 | ||||
|   //     charRange('a', 'z').orRange('A', 'Z').orChar('_').orAny("+-.")
 | ||||
|   //
 | ||||
|   // You can also use `.invert()` to match the opposite set of characters.
 | ||||
| 
 | ||||
|   return CharGroup_().orRange(first, last); | ||||
| } | ||||
| 
 | ||||
| #if _MSC_VER | ||||
| #define anyOfChars(chars) CharGroup_().orAny(chars) | ||||
| // TODO(msvc): MSVC ICEs on the proper definition of `anyOfChars()`, which in turn prevents us from
 | ||||
| //   building the compiler or schema parser. We don't know why this happens, but Harris found that
 | ||||
| //   this horrible, horrible hack makes things work. This is awful, but it's better than nothing.
 | ||||
| //   Hopefully, MSVC will get fixed soon and we'll be able to remove this.
 | ||||
| #else | ||||
| constexpr inline CharGroup_ anyOfChars(const char* chars) { | ||||
|   // Returns a parser that accepts any of the characters in the given string (which should usually
 | ||||
|   // be a literal).  The returned parser is of the same type as returned by `charRange()` -- see
 | ||||
|   // that function for more info.
 | ||||
| 
 | ||||
|   return CharGroup_().orAny(chars); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| struct ArrayToString { | ||||
|   inline String operator()(const Array<char>& arr) const { | ||||
|     return heapString(arr); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename SubParser> | ||||
| constexpr inline auto charsToString(SubParser&& subParser) | ||||
|     -> decltype(transform(kj::fwd<SubParser>(subParser), _::ArrayToString())) { | ||||
|   // Wraps a parser that returns Array<char> such that it returns String instead.
 | ||||
|   return parse::transform(kj::fwd<SubParser>(subParser), _::ArrayToString()); | ||||
| } | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Basic character classes.
 | ||||
| 
 | ||||
| constexpr auto alpha = charRange('a', 'z').orRange('A', 'Z'); | ||||
| constexpr auto digit = charRange('0', '9'); | ||||
| constexpr auto alphaNumeric = alpha.orGroup(digit); | ||||
| constexpr auto nameStart = alpha.orChar('_'); | ||||
| constexpr auto nameChar = alphaNumeric.orChar('_'); | ||||
| constexpr auto hexDigit = charRange('0', '9').orRange('a', 'f').orRange('A', 'F'); | ||||
| constexpr auto octDigit = charRange('0', '7'); | ||||
| constexpr auto whitespaceChar = anyOfChars(" \f\n\r\t\v"); | ||||
| constexpr auto controlChar = charRange(0, 0x1f).invert().orGroup(whitespaceChar).invert(); | ||||
| 
 | ||||
| constexpr auto whitespace = many(anyOfChars(" \f\n\r\t\v")); | ||||
| 
 | ||||
| constexpr auto discardWhitespace = discard(many(discard(anyOfChars(" \f\n\r\t\v")))); | ||||
| // Like discard(whitespace) but avoids some memory allocation.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Identifiers
 | ||||
| 
 | ||||
| namespace _ { // private
 | ||||
| 
 | ||||
| struct IdentifierToString { | ||||
|   inline String operator()(char first, const Array<char>& rest) const { | ||||
|     String result = heapString(rest.size() + 1); | ||||
|     result[0] = first; | ||||
|     memcpy(result.begin() + 1, rest.begin(), rest.size()); | ||||
|     return result; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| constexpr auto identifier = transform(sequence(nameStart, many(nameChar)), _::IdentifierToString()); | ||||
| // Parses an identifier (e.g. a C variable name).
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Integers
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| inline char parseDigit(char c) { | ||||
|   if (c < 'A') return c - '0'; | ||||
|   if (c < 'a') return c - 'A' + 10; | ||||
|   return c - 'a' + 10; | ||||
| } | ||||
| 
 | ||||
| template <uint base> | ||||
| struct ParseInteger { | ||||
|   inline uint64_t operator()(const Array<char>& digits) const { | ||||
|     return operator()('0', digits); | ||||
|   } | ||||
|   uint64_t operator()(char first, const Array<char>& digits) const { | ||||
|     uint64_t result = parseDigit(first); | ||||
|     for (char digit: digits) { | ||||
|       result = result * base + parseDigit(digit); | ||||
|     } | ||||
|     return result; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| constexpr auto integer = sequence( | ||||
|     oneOf( | ||||
|       transform(sequence(exactChar<'0'>(), exactChar<'x'>(), oneOrMore(hexDigit)), _::ParseInteger<16>()), | ||||
|       transform(sequence(exactChar<'0'>(), many(octDigit)), _::ParseInteger<8>()), | ||||
|       transform(sequence(charRange('1', '9'), many(digit)), _::ParseInteger<10>())), | ||||
|     notLookingAt(alpha.orAny("_."))); | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Numbers (i.e. floats)
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| struct ParseFloat { | ||||
|   double operator()(const Array<char>& digits, | ||||
|                     const Maybe<Array<char>>& fraction, | ||||
|                     const Maybe<Tuple<Maybe<char>, Array<char>>>& exponent) const; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| constexpr auto number = transform( | ||||
|     sequence( | ||||
|         oneOrMore(digit), | ||||
|         optional(sequence(exactChar<'.'>(), many(digit))), | ||||
|         optional(sequence(discard(anyOfChars("eE")), optional(anyOfChars("+-")), many(digit))), | ||||
|         notLookingAt(alpha.orAny("_."))), | ||||
|     _::ParseFloat()); | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Quoted strings
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| struct InterpretEscape { | ||||
|   char operator()(char c) const { | ||||
|     switch (c) { | ||||
|       case 'a': return '\a'; | ||||
|       case 'b': return '\b'; | ||||
|       case 'f': return '\f'; | ||||
|       case 'n': return '\n'; | ||||
|       case 'r': return '\r'; | ||||
|       case 't': return '\t'; | ||||
|       case 'v': return '\v'; | ||||
|       default: return c; | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| struct ParseHexEscape { | ||||
|   inline char operator()(char first, char second) const { | ||||
|     return (parseDigit(first) << 4) | parseDigit(second); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| struct ParseHexByte { | ||||
|   inline byte operator()(char first, char second) const { | ||||
|     return (parseDigit(first) << 4) | parseDigit(second); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| struct ParseOctEscape { | ||||
|   inline char operator()(char first, Maybe<char> second, Maybe<char> third) const { | ||||
|     char result = first - '0'; | ||||
|     KJ_IF_MAYBE(digit1, second) { | ||||
|       result = (result << 3) | (*digit1 - '0'); | ||||
|       KJ_IF_MAYBE(digit2, third) { | ||||
|         result = (result << 3) | (*digit2 - '0'); | ||||
|       } | ||||
|     } | ||||
|     return result; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| constexpr auto escapeSequence = | ||||
|     sequence(exactChar<'\\'>(), oneOf( | ||||
|         transform(anyOfChars("abfnrtv'\"\\\?"), _::InterpretEscape()), | ||||
|         transform(sequence(exactChar<'x'>(), hexDigit, hexDigit), _::ParseHexEscape()), | ||||
|         transform(sequence(octDigit, optional(octDigit), optional(octDigit)), | ||||
|                   _::ParseOctEscape()))); | ||||
| // A parser that parses a C-string-style escape sequence (starting with a backslash).  Returns
 | ||||
| // a char.
 | ||||
| 
 | ||||
| constexpr auto doubleQuotedString = charsToString(sequence( | ||||
|     exactChar<'\"'>(), | ||||
|     many(oneOf(anyOfChars("\\\n\"").invert(), escapeSequence)), | ||||
|     exactChar<'\"'>())); | ||||
| // Parses a C-style double-quoted string.
 | ||||
| 
 | ||||
| constexpr auto singleQuotedString = charsToString(sequence( | ||||
|     exactChar<'\''>(), | ||||
|     many(oneOf(anyOfChars("\\\n\'").invert(), escapeSequence)), | ||||
|     exactChar<'\''>())); | ||||
| // Parses a C-style single-quoted string.
 | ||||
| 
 | ||||
| constexpr auto doubleQuotedHexBinary = sequence( | ||||
|     exactChar<'0'>(), exactChar<'x'>(), exactChar<'\"'>(), | ||||
|     oneOrMore(transform(sequence(discardWhitespace, hexDigit, hexDigit), _::ParseHexByte())), | ||||
|     discardWhitespace, | ||||
|     exactChar<'\"'>()); | ||||
| // Parses a double-quoted hex binary literal. Returns Array<byte>.
 | ||||
| 
 | ||||
| }  // namespace parse
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_PARSE_CHAR_H_
 | ||||
| @ -0,0 +1,824 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| // Parser combinator framework!
 | ||||
| //
 | ||||
| // This file declares several functions which construct parsers, usually taking other parsers as
 | ||||
| // input, thus making them parser combinators.
 | ||||
| //
 | ||||
| // A valid parser is any functor which takes a reference to an input cursor (defined below) as its
 | ||||
| // input and returns a Maybe.  The parser returns null on parse failure, or returns the parsed
 | ||||
| // result on success.
 | ||||
| //
 | ||||
| // An "input cursor" is any type which implements the same interface as IteratorInput, below.  Such
 | ||||
| // a type acts as a pointer to the current input location.  When a parser returns successfully, it
 | ||||
| // will have updated the input cursor to point to the position just past the end of what was parsed.
 | ||||
| // On failure, the cursor position is unspecified.
 | ||||
| 
 | ||||
| #ifndef KJ_PARSE_COMMON_H_ | ||||
| #define KJ_PARSE_COMMON_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "../common.h" | ||||
| #include "../memory.h" | ||||
| #include "../array.h" | ||||
| #include "../tuple.h" | ||||
| #include "../vector.h" | ||||
| #if _MSC_VER | ||||
| #include <type_traits>  // result_of_t | ||||
| #endif | ||||
| 
 | ||||
| namespace kj { | ||||
| namespace parse { | ||||
| 
 | ||||
| template <typename Element, typename Iterator> | ||||
| class IteratorInput { | ||||
|   // A parser input implementation based on an iterator range.
 | ||||
| 
 | ||||
| public: | ||||
|   IteratorInput(Iterator begin, Iterator end) | ||||
|       : parent(nullptr), pos(begin), end(end), best(begin) {} | ||||
|   explicit IteratorInput(IteratorInput& parent) | ||||
|       : parent(&parent), pos(parent.pos), end(parent.end), best(parent.pos) {} | ||||
|   ~IteratorInput() { | ||||
|     if (parent != nullptr) { | ||||
|       parent->best = kj::max(kj::max(pos, best), parent->best); | ||||
|     } | ||||
|   } | ||||
|   KJ_DISALLOW_COPY(IteratorInput); | ||||
| 
 | ||||
|   void advanceParent() { | ||||
|     parent->pos = pos; | ||||
|   } | ||||
|   void forgetParent() { | ||||
|     parent = nullptr; | ||||
|   } | ||||
| 
 | ||||
|   bool atEnd() { return pos == end; } | ||||
|   auto current() -> decltype(*instance<Iterator>()) { | ||||
|     KJ_IREQUIRE(!atEnd()); | ||||
|     return *pos; | ||||
|   } | ||||
|   auto consume() -> decltype(*instance<Iterator>()) { | ||||
|     KJ_IREQUIRE(!atEnd()); | ||||
|     return *pos++; | ||||
|   } | ||||
|   void next() { | ||||
|     KJ_IREQUIRE(!atEnd()); | ||||
|     ++pos; | ||||
|   } | ||||
| 
 | ||||
|   Iterator getBest() { return kj::max(pos, best); } | ||||
| 
 | ||||
|   Iterator getPosition() { return pos; } | ||||
| 
 | ||||
| private: | ||||
|   IteratorInput* parent; | ||||
|   Iterator pos; | ||||
|   Iterator end; | ||||
|   Iterator best;  // furthest we got with any sub-input
 | ||||
| }; | ||||
| 
 | ||||
| template <typename T> struct OutputType_; | ||||
| template <typename T> struct OutputType_<Maybe<T>> { typedef T Type; }; | ||||
| template <typename Parser, typename Input> | ||||
| using OutputType = typename OutputType_< | ||||
| #if _MSC_VER | ||||
|     std::result_of_t<Parser(Input)> | ||||
|     // The instance<T&>() based version below results in:
 | ||||
|     //   C2064: term does not evaluate to a function taking 1 arguments
 | ||||
| #else | ||||
|     decltype(instance<Parser&>()(instance<Input&>())) | ||||
| #endif | ||||
|     >::Type; | ||||
| // Synonym for the output type of a parser, given the parser type and the input type.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| template <typename Input, typename Output> | ||||
| class ParserRef { | ||||
|   // Acts as a reference to some other parser, with simplified type.  The referenced parser
 | ||||
|   // is polymorphic by virtual call rather than templates.  For grammars of non-trivial size,
 | ||||
|   // it is important to inject refs into the grammar here and there to prevent the parser types
 | ||||
|   // from becoming ridiculous.  Using too many of them can hurt performance, though.
 | ||||
| 
 | ||||
| public: | ||||
|   ParserRef(): parser(nullptr), wrapper(nullptr) {} | ||||
|   ParserRef(const ParserRef&) = default; | ||||
|   ParserRef(ParserRef&&) = default; | ||||
|   ParserRef& operator=(const ParserRef& other) = default; | ||||
|   ParserRef& operator=(ParserRef&& other) = default; | ||||
| 
 | ||||
|   template <typename Other> | ||||
|   constexpr ParserRef(Other&& other) | ||||
|       : parser(&other), wrapper(&WrapperImplInstance<Decay<Other>>::instance) { | ||||
|     static_assert(kj::isReference<Other>(), "ParserRef should not be assigned to a temporary."); | ||||
|   } | ||||
| 
 | ||||
|   template <typename Other> | ||||
|   inline ParserRef& operator=(Other&& other) { | ||||
|     static_assert(kj::isReference<Other>(), "ParserRef should not be assigned to a temporary."); | ||||
|     parser = &other; | ||||
|     wrapper = &WrapperImplInstance<Decay<Other>>::instance; | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   KJ_ALWAYS_INLINE(Maybe<Output> operator()(Input& input) const) { | ||||
|     // Always inline in the hopes that this allows branch prediction to kick in so the virtual call
 | ||||
|     // doesn't hurt so much.
 | ||||
|     return wrapper->parse(parser, input); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   struct Wrapper { | ||||
|     virtual Maybe<Output> parse(const void* parser, Input& input) const = 0; | ||||
|   }; | ||||
|   template <typename ParserImpl> | ||||
|   struct WrapperImpl: public Wrapper { | ||||
|     Maybe<Output> parse(const void* parser, Input& input) const override { | ||||
|       return (*reinterpret_cast<const ParserImpl*>(parser))(input); | ||||
|     } | ||||
|   }; | ||||
|   template <typename ParserImpl> | ||||
|   struct WrapperImplInstance { | ||||
| #if _MSC_VER | ||||
|     // TODO(msvc): MSVC currently fails to initialize vtable pointers for constexpr values so
 | ||||
|     //   we have to make this just const instead.
 | ||||
|     static const WrapperImpl<ParserImpl> instance; | ||||
| #else | ||||
|     static constexpr WrapperImpl<ParserImpl> instance = WrapperImpl<ParserImpl>(); | ||||
| #endif | ||||
|   }; | ||||
| 
 | ||||
|   const void* parser; | ||||
|   const Wrapper* wrapper; | ||||
| }; | ||||
| 
 | ||||
| template <typename Input, typename Output> | ||||
| template <typename ParserImpl> | ||||
| #if _MSC_VER | ||||
| const typename ParserRef<Input, Output>::template WrapperImpl<ParserImpl> | ||||
| ParserRef<Input, Output>::WrapperImplInstance<ParserImpl>::instance = WrapperImpl<ParserImpl>(); | ||||
| #else | ||||
| constexpr typename ParserRef<Input, Output>::template WrapperImpl<ParserImpl> | ||||
| ParserRef<Input, Output>::WrapperImplInstance<ParserImpl>::instance; | ||||
| #endif | ||||
| 
 | ||||
| template <typename Input, typename ParserImpl> | ||||
| constexpr ParserRef<Input, OutputType<ParserImpl, Input>> ref(ParserImpl& impl) { | ||||
|   // Constructs a ParserRef.  You must specify the input type explicitly, e.g.
 | ||||
|   // `ref<MyInput>(myParser)`.
 | ||||
| 
 | ||||
|   return ParserRef<Input, OutputType<ParserImpl, Input>>(impl); | ||||
| } | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| // any
 | ||||
| // Output = one token
 | ||||
| 
 | ||||
| class Any_ { | ||||
| public: | ||||
|   template <typename Input> | ||||
|   Maybe<Decay<decltype(instance<Input>().consume())>> operator()(Input& input) const { | ||||
|     if (input.atEnd()) { | ||||
|       return nullptr; | ||||
|     } else { | ||||
|       return input.consume(); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| constexpr Any_ any = Any_(); | ||||
| // A parser which matches any token and simply returns it.
 | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| // exactly()
 | ||||
| // Output = Tuple<>
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class Exactly_ { | ||||
| public: | ||||
|   explicit constexpr Exactly_(T&& expected): expected(expected) {} | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   Maybe<Tuple<>> operator()(Input& input) const { | ||||
|     if (input.atEnd() || input.current() != expected) { | ||||
|       return nullptr; | ||||
|     } else { | ||||
|       input.next(); | ||||
|       return Tuple<>(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   T expected; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| constexpr Exactly_<T> exactly(T&& expected) { | ||||
|   // Constructs a parser which succeeds when the input is exactly the token specified.  The
 | ||||
|   // result is always the empty tuple.
 | ||||
| 
 | ||||
|   return Exactly_<T>(kj::fwd<T>(expected)); | ||||
| } | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| // exactlyConst()
 | ||||
| // Output = Tuple<>
 | ||||
| 
 | ||||
| template <typename T, T expected> | ||||
| class ExactlyConst_ { | ||||
| public: | ||||
|   explicit constexpr ExactlyConst_() {} | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   Maybe<Tuple<>> operator()(Input& input) const { | ||||
|     if (input.atEnd() || input.current() != expected) { | ||||
|       return nullptr; | ||||
|     } else { | ||||
|       input.next(); | ||||
|       return Tuple<>(); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T, T expected> | ||||
| constexpr ExactlyConst_<T, expected> exactlyConst() { | ||||
|   // Constructs a parser which succeeds when the input is exactly the token specified.  The
 | ||||
|   // result is always the empty tuple.  This parser is templated on the token value which may cause
 | ||||
|   // it to perform better -- or worse.  Be sure to measure.
 | ||||
| 
 | ||||
|   return ExactlyConst_<T, expected>(); | ||||
| } | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| // constResult()
 | ||||
| 
 | ||||
| template <typename SubParser, typename Result> | ||||
| class ConstResult_ { | ||||
| public: | ||||
|   explicit constexpr ConstResult_(SubParser&& subParser, Result&& result) | ||||
|       : subParser(kj::fwd<SubParser>(subParser)), result(kj::fwd<Result>(result)) {} | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   Maybe<Result> operator()(Input& input) const { | ||||
|     if (subParser(input) == nullptr) { | ||||
|       return nullptr; | ||||
|     } else { | ||||
|       return result; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   SubParser subParser; | ||||
|   Result result; | ||||
| }; | ||||
| 
 | ||||
| template <typename SubParser, typename Result> | ||||
| constexpr ConstResult_<SubParser, Result> constResult(SubParser&& subParser, Result&& result) { | ||||
|   // Constructs a parser which returns exactly `result` if `subParser` is successful.
 | ||||
|   return ConstResult_<SubParser, Result>(kj::fwd<SubParser>(subParser), kj::fwd<Result>(result)); | ||||
| } | ||||
| 
 | ||||
| template <typename SubParser> | ||||
| constexpr ConstResult_<SubParser, Tuple<>> discard(SubParser&& subParser) { | ||||
|   // Constructs a parser which wraps `subParser` but discards the result.
 | ||||
|   return constResult(kj::fwd<SubParser>(subParser), Tuple<>()); | ||||
| } | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| // sequence()
 | ||||
| // Output = Flattened Tuple of outputs of sub-parsers.
 | ||||
| 
 | ||||
| template <typename... SubParsers> class Sequence_; | ||||
| 
 | ||||
| template <typename FirstSubParser, typename... SubParsers> | ||||
| class Sequence_<FirstSubParser, SubParsers...> { | ||||
| public: | ||||
|   template <typename T, typename... U> | ||||
|   explicit constexpr Sequence_(T&& firstSubParser, U&&... rest) | ||||
|       : first(kj::fwd<T>(firstSubParser)), rest(kj::fwd<U>(rest)...) {} | ||||
| 
 | ||||
|   // TODO(msvc): The trailing return types on `operator()` and `parseNext()` expose at least two
 | ||||
|   //   bugs in MSVC:
 | ||||
|   //
 | ||||
|   //     1. An ICE.
 | ||||
|   //     2. 'error C2672: 'operator __surrogate_func': no matching overloaded function found)',
 | ||||
|   //        which crops up in numerous places when trying to build the capnp command line tools.
 | ||||
|   //
 | ||||
|   //   The only workaround I found for both bugs is to omit the trailing return types and instead
 | ||||
|   //   rely on C++14's return type deduction.
 | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   auto operator()(Input& input) const | ||||
| #ifndef _MSC_VER | ||||
|       -> Maybe<decltype(tuple( | ||||
|           instance<OutputType<FirstSubParser, Input>>(), | ||||
|           instance<OutputType<SubParsers, Input>>()...))> | ||||
| #endif | ||||
|   { | ||||
|     return parseNext(input); | ||||
|   } | ||||
| 
 | ||||
|   template <typename Input, typename... InitialParams> | ||||
|   auto parseNext(Input& input, InitialParams&&... initialParams) const | ||||
| #ifndef _MSC_VER | ||||
|       -> Maybe<decltype(tuple( | ||||
|           kj::fwd<InitialParams>(initialParams)..., | ||||
|           instance<OutputType<FirstSubParser, Input>>(), | ||||
|           instance<OutputType<SubParsers, Input>>()...))> | ||||
| #endif | ||||
|   { | ||||
|     KJ_IF_MAYBE(firstResult, first(input)) { | ||||
|       return rest.parseNext(input, kj::fwd<InitialParams>(initialParams)..., | ||||
|                             kj::mv(*firstResult)); | ||||
|     } else { | ||||
|       // TODO(msvc): MSVC depends on return type deduction to compile this function, so we need to
 | ||||
|       //   help it deduce the right type on this code path.
 | ||||
|       return Maybe<decltype(tuple( | ||||
|           kj::fwd<InitialParams>(initialParams)..., | ||||
|           instance<OutputType<FirstSubParser, Input>>(), | ||||
|           instance<OutputType<SubParsers, Input>>()...))>{nullptr}; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   FirstSubParser first; | ||||
|   Sequence_<SubParsers...> rest; | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| class Sequence_<> { | ||||
| public: | ||||
|   template <typename Input> | ||||
|   Maybe<Tuple<>> operator()(Input& input) const { | ||||
|     return parseNext(input); | ||||
|   } | ||||
| 
 | ||||
|   template <typename Input, typename... Params> | ||||
|   auto parseNext(Input& input, Params&&... params) const -> | ||||
|       Maybe<decltype(tuple(kj::fwd<Params>(params)...))> { | ||||
|     return tuple(kj::fwd<Params>(params)...); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename... SubParsers> | ||||
| constexpr Sequence_<SubParsers...> sequence(SubParsers&&... subParsers) { | ||||
|   // Constructs a parser that executes each of the parameter parsers in sequence and returns a
 | ||||
|   // tuple of their results.
 | ||||
| 
 | ||||
|   return Sequence_<SubParsers...>(kj::fwd<SubParsers>(subParsers)...); | ||||
| } | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| // many()
 | ||||
| // Output = Array of output of sub-parser, or just a uint count if the sub-parser returns Tuple<>.
 | ||||
| 
 | ||||
| template <typename SubParser, bool atLeastOne> | ||||
| class Many_ { | ||||
|   template <typename Input, typename Output = OutputType<SubParser, Input>> | ||||
|   struct Impl; | ||||
| public: | ||||
|   explicit constexpr Many_(SubParser&& subParser) | ||||
|       : subParser(kj::fwd<SubParser>(subParser)) {} | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   auto operator()(Input& input) const | ||||
|       -> decltype(Impl<Input>::apply(instance<const SubParser&>(), input)); | ||||
| 
 | ||||
| private: | ||||
|   SubParser subParser; | ||||
| }; | ||||
| 
 | ||||
| template <typename SubParser, bool atLeastOne> | ||||
| template <typename Input, typename Output> | ||||
| struct Many_<SubParser, atLeastOne>::Impl { | ||||
|   static Maybe<Array<Output>> apply(const SubParser& subParser, Input& input) { | ||||
|     typedef Vector<OutputType<SubParser, Input>> Results; | ||||
|     Results results; | ||||
| 
 | ||||
|     while (!input.atEnd()) { | ||||
|       Input subInput(input); | ||||
| 
 | ||||
|       KJ_IF_MAYBE(subResult, subParser(subInput)) { | ||||
|         subInput.advanceParent(); | ||||
|         results.add(kj::mv(*subResult)); | ||||
|       } else { | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (atLeastOne && results.empty()) { | ||||
|       return nullptr; | ||||
|     } | ||||
| 
 | ||||
|     return results.releaseAsArray(); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename SubParser, bool atLeastOne> | ||||
| template <typename Input> | ||||
| struct Many_<SubParser, atLeastOne>::Impl<Input, Tuple<>> { | ||||
|   // If the sub-parser output is Tuple<>, just return a count.
 | ||||
| 
 | ||||
|   static Maybe<uint> apply(const SubParser& subParser, Input& input) { | ||||
|     uint count = 0; | ||||
| 
 | ||||
|     while (!input.atEnd()) { | ||||
|       Input subInput(input); | ||||
| 
 | ||||
|       KJ_IF_MAYBE(subResult, subParser(subInput)) { | ||||
|         subInput.advanceParent(); | ||||
|         ++count; | ||||
|       } else { | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (atLeastOne && count == 0) { | ||||
|       return nullptr; | ||||
|     } | ||||
| 
 | ||||
|     return count; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename SubParser, bool atLeastOne> | ||||
| template <typename Input> | ||||
| auto Many_<SubParser, atLeastOne>::operator()(Input& input) const | ||||
|     -> decltype(Impl<Input>::apply(instance<const SubParser&>(), input)) { | ||||
|   return Impl<Input, OutputType<SubParser, Input>>::apply(subParser, input); | ||||
| } | ||||
| 
 | ||||
| template <typename SubParser> | ||||
| constexpr Many_<SubParser, false> many(SubParser&& subParser) { | ||||
|   // Constructs a parser that repeatedly executes the given parser until it fails, returning an
 | ||||
|   // Array of the results (or a uint count if `subParser` returns an empty tuple).
 | ||||
|   return Many_<SubParser, false>(kj::fwd<SubParser>(subParser)); | ||||
| } | ||||
| 
 | ||||
| template <typename SubParser> | ||||
| constexpr Many_<SubParser, true> oneOrMore(SubParser&& subParser) { | ||||
|   // Like `many()` but the parser must parse at least one item to be successful.
 | ||||
|   return Many_<SubParser, true>(kj::fwd<SubParser>(subParser)); | ||||
| } | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| // times()
 | ||||
| // Output = Array of output of sub-parser, or Tuple<> if sub-parser returns Tuple<>.
 | ||||
| 
 | ||||
| template <typename SubParser> | ||||
| class Times_ { | ||||
|   template <typename Input, typename Output = OutputType<SubParser, Input>> | ||||
|   struct Impl; | ||||
| public: | ||||
|   explicit constexpr Times_(SubParser&& subParser, uint count) | ||||
|       : subParser(kj::fwd<SubParser>(subParser)), count(count) {} | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   auto operator()(Input& input) const | ||||
|       -> decltype(Impl<Input>::apply(instance<const SubParser&>(), instance<uint>(), input)); | ||||
| 
 | ||||
| private: | ||||
|   SubParser subParser; | ||||
|   uint count; | ||||
| }; | ||||
| 
 | ||||
| template <typename SubParser> | ||||
| template <typename Input, typename Output> | ||||
| struct Times_<SubParser>::Impl { | ||||
|   static Maybe<Array<Output>> apply(const SubParser& subParser, uint count, Input& input) { | ||||
|     auto results = heapArrayBuilder<OutputType<SubParser, Input>>(count); | ||||
| 
 | ||||
|     while (results.size() < count) { | ||||
|       if (input.atEnd()) { | ||||
|         return nullptr; | ||||
|       } else KJ_IF_MAYBE(subResult, subParser(input)) { | ||||
|         results.add(kj::mv(*subResult)); | ||||
|       } else { | ||||
|         return nullptr; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     return results.finish(); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename SubParser> | ||||
| template <typename Input> | ||||
| struct Times_<SubParser>::Impl<Input, Tuple<>> { | ||||
|   // If the sub-parser output is Tuple<>, just return a count.
 | ||||
| 
 | ||||
|   static Maybe<Tuple<>> apply(const SubParser& subParser, uint count, Input& input) { | ||||
|     uint actualCount = 0; | ||||
| 
 | ||||
|     while (actualCount < count) { | ||||
|       if (input.atEnd()) { | ||||
|         return nullptr; | ||||
|       } else KJ_IF_MAYBE(subResult, subParser(input)) { | ||||
|         ++actualCount; | ||||
|       } else { | ||||
|         return nullptr; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     return tuple(); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename SubParser> | ||||
| template <typename Input> | ||||
| auto Times_<SubParser>::operator()(Input& input) const | ||||
|     -> decltype(Impl<Input>::apply(instance<const SubParser&>(), instance<uint>(), input)) { | ||||
|   return Impl<Input, OutputType<SubParser, Input>>::apply(subParser, count, input); | ||||
| } | ||||
| 
 | ||||
| template <typename SubParser> | ||||
| constexpr Times_<SubParser> times(SubParser&& subParser, uint count) { | ||||
|   // Constructs a parser that repeats the subParser exactly `count` times.
 | ||||
|   return Times_<SubParser>(kj::fwd<SubParser>(subParser), count); | ||||
| } | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| // optional()
 | ||||
| // Output = Maybe<output of sub-parser>
 | ||||
| 
 | ||||
| template <typename SubParser> | ||||
| class Optional_ { | ||||
| public: | ||||
|   explicit constexpr Optional_(SubParser&& subParser) | ||||
|       : subParser(kj::fwd<SubParser>(subParser)) {} | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   Maybe<Maybe<OutputType<SubParser, Input>>> operator()(Input& input) const { | ||||
|     typedef Maybe<OutputType<SubParser, Input>> Result; | ||||
| 
 | ||||
|     Input subInput(input); | ||||
|     KJ_IF_MAYBE(subResult, subParser(subInput)) { | ||||
|       subInput.advanceParent(); | ||||
|       return Result(kj::mv(*subResult)); | ||||
|     } else { | ||||
|       return Result(nullptr); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   SubParser subParser; | ||||
| }; | ||||
| 
 | ||||
| template <typename SubParser> | ||||
| constexpr Optional_<SubParser> optional(SubParser&& subParser) { | ||||
|   // Constructs a parser that accepts zero or one of the given sub-parser, returning a Maybe
 | ||||
|   // of the sub-parser's result.
 | ||||
|   return Optional_<SubParser>(kj::fwd<SubParser>(subParser)); | ||||
| } | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| // oneOf()
 | ||||
| // All SubParsers must have same output type, which becomes the output type of the
 | ||||
| // OneOfParser.
 | ||||
| 
 | ||||
| template <typename... SubParsers> | ||||
| class OneOf_; | ||||
| 
 | ||||
| template <typename FirstSubParser, typename... SubParsers> | ||||
| class OneOf_<FirstSubParser, SubParsers...> { | ||||
| public: | ||||
|   explicit constexpr OneOf_(FirstSubParser&& firstSubParser, SubParsers&&... rest) | ||||
|       : first(kj::fwd<FirstSubParser>(firstSubParser)), rest(kj::fwd<SubParsers>(rest)...) {} | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   Maybe<OutputType<FirstSubParser, Input>> operator()(Input& input) const { | ||||
|     { | ||||
|       Input subInput(input); | ||||
|       Maybe<OutputType<FirstSubParser, Input>> firstResult = first(subInput); | ||||
| 
 | ||||
|       if (firstResult != nullptr) { | ||||
|         subInput.advanceParent(); | ||||
|         return kj::mv(firstResult); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     // Hoping for some tail recursion here...
 | ||||
|     return rest(input); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   FirstSubParser first; | ||||
|   OneOf_<SubParsers...> rest; | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| class OneOf_<> { | ||||
| public: | ||||
|   template <typename Input> | ||||
|   decltype(nullptr) operator()(Input& input) const { | ||||
|     return nullptr; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename... SubParsers> | ||||
| constexpr OneOf_<SubParsers...> oneOf(SubParsers&&... parsers) { | ||||
|   // Constructs a parser that accepts one of a set of options.  The parser behaves as the first
 | ||||
|   // sub-parser in the list which returns successfully.  All of the sub-parsers must return the
 | ||||
|   // same type.
 | ||||
|   return OneOf_<SubParsers...>(kj::fwd<SubParsers>(parsers)...); | ||||
| } | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| // transform()
 | ||||
| // Output = Result of applying transform functor to input value.  If input is a tuple, it is
 | ||||
| // unpacked to form the transformation parameters.
 | ||||
| 
 | ||||
| template <typename Position> | ||||
| struct Span { | ||||
| public: | ||||
|   inline const Position& begin() const { return begin_; } | ||||
|   inline const Position& end() const { return end_; } | ||||
| 
 | ||||
|   Span() = default; | ||||
|   inline constexpr Span(Position&& begin, Position&& end): begin_(mv(begin)), end_(mv(end)) {} | ||||
| 
 | ||||
| private: | ||||
|   Position begin_; | ||||
|   Position end_; | ||||
| }; | ||||
| 
 | ||||
| template <typename Position> | ||||
| constexpr Span<Decay<Position>> span(Position&& start, Position&& end) { | ||||
|   return Span<Decay<Position>>(kj::fwd<Position>(start), kj::fwd<Position>(end)); | ||||
| } | ||||
| 
 | ||||
| template <typename SubParser, typename TransformFunc> | ||||
| class Transform_ { | ||||
| public: | ||||
|   explicit constexpr Transform_(SubParser&& subParser, TransformFunc&& transform) | ||||
|       : subParser(kj::fwd<SubParser>(subParser)), transform(kj::fwd<TransformFunc>(transform)) {} | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   Maybe<decltype(kj::apply(instance<TransformFunc&>(), | ||||
|                            instance<OutputType<SubParser, Input>&&>()))> | ||||
|       operator()(Input& input) const { | ||||
|     KJ_IF_MAYBE(subResult, subParser(input)) { | ||||
|       return kj::apply(transform, kj::mv(*subResult)); | ||||
|     } else { | ||||
|       return nullptr; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   SubParser subParser; | ||||
|   TransformFunc transform; | ||||
| }; | ||||
| 
 | ||||
| template <typename SubParser, typename TransformFunc> | ||||
| class TransformOrReject_ { | ||||
| public: | ||||
|   explicit constexpr TransformOrReject_(SubParser&& subParser, TransformFunc&& transform) | ||||
|       : subParser(kj::fwd<SubParser>(subParser)), transform(kj::fwd<TransformFunc>(transform)) {} | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   decltype(kj::apply(instance<TransformFunc&>(), instance<OutputType<SubParser, Input>&&>())) | ||||
|       operator()(Input& input) const { | ||||
|     KJ_IF_MAYBE(subResult, subParser(input)) { | ||||
|       return kj::apply(transform, kj::mv(*subResult)); | ||||
|     } else { | ||||
|       return nullptr; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   SubParser subParser; | ||||
|   TransformFunc transform; | ||||
| }; | ||||
| 
 | ||||
| template <typename SubParser, typename TransformFunc> | ||||
| class TransformWithLocation_ { | ||||
| public: | ||||
|   explicit constexpr TransformWithLocation_(SubParser&& subParser, TransformFunc&& transform) | ||||
|       : subParser(kj::fwd<SubParser>(subParser)), transform(kj::fwd<TransformFunc>(transform)) {} | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   Maybe<decltype(kj::apply(instance<TransformFunc&>(), | ||||
|                            instance<Span<Decay<decltype(instance<Input&>().getPosition())>>>(), | ||||
|                            instance<OutputType<SubParser, Input>&&>()))> | ||||
|       operator()(Input& input) const { | ||||
|     auto start = input.getPosition(); | ||||
|     KJ_IF_MAYBE(subResult, subParser(input)) { | ||||
|       return kj::apply(transform, Span<decltype(start)>(kj::mv(start), input.getPosition()), | ||||
|                        kj::mv(*subResult)); | ||||
|     } else { | ||||
|       return nullptr; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   SubParser subParser; | ||||
|   TransformFunc transform; | ||||
| }; | ||||
| 
 | ||||
| template <typename SubParser, typename TransformFunc> | ||||
| constexpr Transform_<SubParser, TransformFunc> transform( | ||||
|     SubParser&& subParser, TransformFunc&& functor) { | ||||
|   // Constructs a parser which executes some other parser and then transforms the result by invoking
 | ||||
|   // `functor` on it.  Typically `functor` is a lambda.  It is invoked using `kj::apply`,
 | ||||
|   // meaning tuples will be unpacked as arguments.
 | ||||
|   return Transform_<SubParser, TransformFunc>( | ||||
|       kj::fwd<SubParser>(subParser), kj::fwd<TransformFunc>(functor)); | ||||
| } | ||||
| 
 | ||||
| template <typename SubParser, typename TransformFunc> | ||||
| constexpr TransformOrReject_<SubParser, TransformFunc> transformOrReject( | ||||
|     SubParser&& subParser, TransformFunc&& functor) { | ||||
|   // Like `transform()` except that `functor` returns a `Maybe`.  If it returns null, parsing fails,
 | ||||
|   // otherwise the parser's result is the content of the `Maybe`.
 | ||||
|   return TransformOrReject_<SubParser, TransformFunc>( | ||||
|       kj::fwd<SubParser>(subParser), kj::fwd<TransformFunc>(functor)); | ||||
| } | ||||
| 
 | ||||
| template <typename SubParser, typename TransformFunc> | ||||
| constexpr TransformWithLocation_<SubParser, TransformFunc> transformWithLocation( | ||||
|     SubParser&& subParser, TransformFunc&& functor) { | ||||
|   // Like `transform` except that `functor` also takes a `Span` as its first parameter specifying
 | ||||
|   // the location of the parsed content.  The span's position type is whatever the parser input's
 | ||||
|   // getPosition() returns.
 | ||||
|   return TransformWithLocation_<SubParser, TransformFunc>( | ||||
|       kj::fwd<SubParser>(subParser), kj::fwd<TransformFunc>(functor)); | ||||
| } | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| // notLookingAt()
 | ||||
| // Fails if the given parser succeeds at the current location.
 | ||||
| 
 | ||||
| template <typename SubParser> | ||||
| class NotLookingAt_ { | ||||
| public: | ||||
|   explicit constexpr NotLookingAt_(SubParser&& subParser) | ||||
|       : subParser(kj::fwd<SubParser>(subParser)) {} | ||||
| 
 | ||||
|   template <typename Input> | ||||
|   Maybe<Tuple<>> operator()(Input& input) const { | ||||
|     Input subInput(input); | ||||
|     subInput.forgetParent(); | ||||
|     if (subParser(subInput) == nullptr) { | ||||
|       return Tuple<>(); | ||||
|     } else { | ||||
|       return nullptr; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   SubParser subParser; | ||||
| }; | ||||
| 
 | ||||
| template <typename SubParser> | ||||
| constexpr NotLookingAt_<SubParser> notLookingAt(SubParser&& subParser) { | ||||
|   // Constructs a parser which fails at any position where the given parser succeeds.  Otherwise,
 | ||||
|   // it succeeds without consuming any input and returns an empty tuple.
 | ||||
|   return NotLookingAt_<SubParser>(kj::fwd<SubParser>(subParser)); | ||||
| } | ||||
| 
 | ||||
| // -------------------------------------------------------------------
 | ||||
| // endOfInput()
 | ||||
| // Output = Tuple<>, only succeeds if at end-of-input
 | ||||
| 
 | ||||
| class EndOfInput_ { | ||||
| public: | ||||
|   template <typename Input> | ||||
|   Maybe<Tuple<>> operator()(Input& input) const { | ||||
|     if (input.atEnd()) { | ||||
|       return Tuple<>(); | ||||
|     } else { | ||||
|       return nullptr; | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| constexpr EndOfInput_ endOfInput = EndOfInput_(); | ||||
| // A parser that succeeds only if it is called with no input.
 | ||||
| 
 | ||||
| }  // namespace parse
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_PARSE_COMMON_H_
 | ||||
| @ -0,0 +1,107 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #include "memory.h" | ||||
| 
 | ||||
| #ifndef KJ_REFCOUNT_H_ | ||||
| #define KJ_REFCOUNT_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| class Refcounted: private Disposer { | ||||
|   // Subclass this to create a class that contains a reference count. Then, use
 | ||||
|   // `kj::refcounted<T>()` to allocate a new refcounted pointer.
 | ||||
|   //
 | ||||
|   // Do NOT use this lightly.  Refcounting is a crutch.  Good designs should strive to make object
 | ||||
|   // ownership clear, so that refcounting is not necessary.  All that said, reference counting can
 | ||||
|   // sometimes simplify code that would otherwise become convoluted with explicit ownership, even
 | ||||
|   // when ownership relationships are clear at an abstract level.
 | ||||
|   //
 | ||||
|   // NOT THREADSAFE:  This refcounting implementation assumes that an object's references are
 | ||||
|   // manipulated only in one thread, because atomic (thread-safe) refcounting is surprisingly slow.
 | ||||
|   //
 | ||||
|   // In general, abstract classes should _not_ subclass this.  The concrete class at the bottom
 | ||||
|   // of the hierarchy should be the one to decide how it implements refcounting.  Interfaces should
 | ||||
|   // expose only an `addRef()` method that returns `Own<InterfaceType>`.  There are two reasons for
 | ||||
|   // this rule:
 | ||||
|   // 1. Interfaces would need to virtually inherit Refcounted, otherwise two refcounted interfaces
 | ||||
|   //    could not be inherited by the same subclass.  Virtual inheritance is awkward and
 | ||||
|   //    inefficient.
 | ||||
|   // 2. An implementation may decide that it would rather return a copy than a refcount, or use
 | ||||
|   //    some other strategy.
 | ||||
|   //
 | ||||
|   // TODO(cleanup):  Rethink above.  Virtual inheritance is not necessarily that bad.  OTOH, a
 | ||||
|   //   virtual function call for every refcount is sad in its own way.  A Ref<T> type to replace
 | ||||
|   //   Own<T> could also be nice.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual ~Refcounted() noexcept(false); | ||||
| 
 | ||||
|   inline bool isShared() const { return refcount > 1; } | ||||
|   // Check if there are multiple references to this object. This is sometimes useful for deciding
 | ||||
|   // whether it's safe to modify the object vs. make a copy.
 | ||||
| 
 | ||||
| private: | ||||
|   mutable uint refcount = 0; | ||||
|   // "mutable" because disposeImpl() is const.  Bleh.
 | ||||
| 
 | ||||
|   void disposeImpl(void* pointer) const override; | ||||
|   template <typename T> | ||||
|   static Own<T> addRefInternal(T* object); | ||||
| 
 | ||||
|   template <typename T> | ||||
|   friend Own<T> addRef(T& object); | ||||
|   template <typename T, typename... Params> | ||||
|   friend Own<T> refcounted(Params&&... params); | ||||
| }; | ||||
| 
 | ||||
| template <typename T, typename... Params> | ||||
| inline Own<T> refcounted(Params&&... params) { | ||||
|   // Allocate a new refcounted instance of T, passing `params` to its constructor.  Returns an
 | ||||
|   // initial reference to the object.  More references can be created with `kj::addRef()`.
 | ||||
| 
 | ||||
|   return Refcounted::addRefInternal(new T(kj::fwd<Params>(params)...)); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| Own<T> addRef(T& object) { | ||||
|   // Return a new reference to `object`, which must subclass Refcounted and have been allocated
 | ||||
|   // using `kj::refcounted<>()`.  It is suggested that subclasses implement a non-static addRef()
 | ||||
|   // method which wraps this and returns the appropriate type.
 | ||||
| 
 | ||||
|   KJ_IREQUIRE(object.Refcounted::refcount > 0, "Object not allocated with kj::refcounted()."); | ||||
|   return Refcounted::addRefInternal(&object); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| Own<T> Refcounted::addRefInternal(T* object) { | ||||
|   Refcounted* refcounted = object; | ||||
|   ++refcounted->refcount; | ||||
|   return Own<T>(object, *refcounted); | ||||
| } | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_REFCOUNT_H_
 | ||||
| @ -0,0 +1,88 @@ | ||||
| // Copyright (c) 2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Compatibility layer for stdlib iostream | ||||
|  */ | ||||
| 
 | ||||
| #ifndef KJ_STD_IOSTREAM_H_ | ||||
| #define KJ_STD_IOSTREAM_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "../io.h" | ||||
| #include <iostream> | ||||
| 
 | ||||
| namespace kj { | ||||
| namespace std { | ||||
| 
 | ||||
| class StdOutputStream: public kj::OutputStream { | ||||
| 
 | ||||
| public: | ||||
|   explicit StdOutputStream(::std::ostream& stream) : stream_(stream) {} | ||||
|   ~StdOutputStream() noexcept(false) {} | ||||
| 
 | ||||
|   virtual void write(const void* src, size_t size) override { | ||||
|     // Always writes the full size.
 | ||||
| 
 | ||||
|     stream_.write((char*)src, size); | ||||
|   } | ||||
| 
 | ||||
|   virtual void write(ArrayPtr<const ArrayPtr<const byte>> pieces) override { | ||||
|     // Equivalent to write()ing each byte array in sequence, which is what the
 | ||||
|     // default implementation does. Override if you can do something better,
 | ||||
|     // e.g. use writev() to do the write in a single syscall.
 | ||||
| 
 | ||||
|     for (auto piece : pieces) { | ||||
|       write(piece.begin(), piece.size()); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   ::std::ostream& stream_; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| class StdInputStream: public kj::InputStream { | ||||
| 
 | ||||
| public: | ||||
|   explicit StdInputStream(::std::istream& stream) : stream_(stream) {} | ||||
|   ~StdInputStream() noexcept(false) {} | ||||
| 
 | ||||
|   virtual size_t tryRead( | ||||
|       void* buffer, size_t minBytes, size_t maxBytes) override { | ||||
|     // Like read(), but may return fewer than minBytes on EOF.
 | ||||
| 
 | ||||
|     stream_.read((char*)buffer, maxBytes); | ||||
|     return stream_.gcount(); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   ::std::istream& stream_; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| }  // namespace std
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_STD_IOSTREAM_H_
 | ||||
| @ -0,0 +1,212 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_STRING_TREE_H_ | ||||
| #define KJ_STRING_TREE_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "string.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| class StringTree { | ||||
|   // A long string, represented internally as a tree of strings.  This data structure is like a
 | ||||
|   // String, but optimized for concatenation and iteration at the expense of seek time.  The
 | ||||
|   // structure is intended to be used for building large text blobs from many small pieces, where
 | ||||
|   // repeatedly concatenating smaller strings into larger ones would waste copies.  This structure
 | ||||
|   // is NOT intended for use cases requiring random access or computing substrings.  For those,
 | ||||
|   // you should use a Rope, which is a much more complicated data structure.
 | ||||
|   //
 | ||||
|   // The proper way to construct a StringTree is via kj::strTree(...), which works just like
 | ||||
|   // kj::str(...) but returns a StringTree rather than a String.
 | ||||
|   //
 | ||||
|   // KJ_STRINGIFY() functions that construct large strings from many smaller strings are encouraged
 | ||||
|   // to return StringTree rather than a flat char container.
 | ||||
| 
 | ||||
| public: | ||||
|   inline StringTree(): size_(0) {} | ||||
|   inline StringTree(String&& text): size_(text.size()), text(kj::mv(text)) {} | ||||
| 
 | ||||
|   StringTree(Array<StringTree>&& pieces, StringPtr delim); | ||||
|   // Build a StringTree by concatenating the given pieces, delimited by the given delimiter
 | ||||
|   // (e.g. ", ").
 | ||||
| 
 | ||||
|   inline size_t size() const { return size_; } | ||||
| 
 | ||||
|   template <typename Func> | ||||
|   void visit(Func&& func) const; | ||||
| 
 | ||||
|   String flatten() const; | ||||
|   // Return the contents as a string.
 | ||||
| 
 | ||||
|   // TODO(someday):  flatten() when *this is an rvalue and when branches.size() == 0 could simply
 | ||||
|   //   return `kj::mv(text)`.  Requires reference qualifiers (Clang 3.3 / GCC 4.8).
 | ||||
| 
 | ||||
|   void flattenTo(char* __restrict__ target) const; | ||||
|   // Copy the contents to the given character array.  Does not add a NUL terminator.
 | ||||
| 
 | ||||
| private: | ||||
|   size_t size_; | ||||
|   String text; | ||||
| 
 | ||||
|   struct Branch; | ||||
|   Array<Branch> branches;  // In order.
 | ||||
| 
 | ||||
|   inline void fill(char* pos, size_t branchIndex); | ||||
|   template <typename First, typename... Rest> | ||||
|   void fill(char* pos, size_t branchIndex, First&& first, Rest&&... rest); | ||||
|   template <typename... Rest> | ||||
|   void fill(char* pos, size_t branchIndex, StringTree&& first, Rest&&... rest); | ||||
|   template <typename... Rest> | ||||
|   void fill(char* pos, size_t branchIndex, Array<char>&& first, Rest&&... rest); | ||||
|   template <typename... Rest> | ||||
|   void fill(char* pos, size_t branchIndex, String&& first, Rest&&... rest); | ||||
| 
 | ||||
|   template <typename... Params> | ||||
|   static StringTree concat(Params&&... params); | ||||
|   static StringTree&& concat(StringTree&& param) { return kj::mv(param); } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   static inline size_t flatSize(const T& t) { return t.size(); } | ||||
|   static inline size_t flatSize(String&& s) { return 0; } | ||||
|   static inline size_t flatSize(StringTree&& s) { return 0; } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   static inline size_t branchCount(const T& t) { return 0; } | ||||
|   static inline size_t branchCount(String&& s) { return 1; } | ||||
|   static inline size_t branchCount(StringTree&& s) { return 1; } | ||||
| 
 | ||||
|   template <typename... Params> | ||||
|   friend StringTree strTree(Params&&... params); | ||||
| }; | ||||
| 
 | ||||
| inline StringTree&& KJ_STRINGIFY(StringTree&& tree) { return kj::mv(tree); } | ||||
| inline const StringTree& KJ_STRINGIFY(const StringTree& tree) { return tree; } | ||||
| 
 | ||||
| inline StringTree KJ_STRINGIFY(Array<StringTree>&& trees) { return StringTree(kj::mv(trees), ""); } | ||||
| 
 | ||||
| template <typename... Params> | ||||
| StringTree strTree(Params&&... params); | ||||
| // Build a StringTree by stringifying the given parameters and concatenating the results.
 | ||||
| // If any of the parameters stringify to StringTree rvalues, they will be incorporated as
 | ||||
| // branches to avoid a copy.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Inline implementation details
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename... Rest> | ||||
| char* fill(char* __restrict__ target, const StringTree& first, Rest&&... rest) { | ||||
|   // Make str() work with stringifiers that return StringTree by patching fill().
 | ||||
| 
 | ||||
|   first.flattenTo(target); | ||||
|   return fill(target + first.size(), kj::fwd<Rest>(rest)...); | ||||
| } | ||||
| 
 | ||||
| template <typename T> constexpr bool isStringTree() { return false; } | ||||
| template <> constexpr bool isStringTree<StringTree>() { return true; } | ||||
| 
 | ||||
| inline StringTree&& toStringTreeOrCharSequence(StringTree&& tree) { return kj::mv(tree); } | ||||
| inline StringTree toStringTreeOrCharSequence(String&& str) { return StringTree(kj::mv(str)); } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline auto toStringTreeOrCharSequence(T&& value) | ||||
|     -> decltype(toCharSequence(kj::fwd<T>(value))) { | ||||
|   static_assert(!isStringTree<Decay<T>>(), | ||||
|       "When passing a StringTree into kj::strTree(), either pass it by rvalue " | ||||
|       "(use kj::mv(value)) or explicitly call value.flatten() to make a copy."); | ||||
| 
 | ||||
|   return toCharSequence(kj::fwd<T>(value)); | ||||
| } | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| struct StringTree::Branch { | ||||
|   size_t index; | ||||
|   // Index in `text` where this branch should be inserted.
 | ||||
| 
 | ||||
|   StringTree content; | ||||
| }; | ||||
| 
 | ||||
| template <typename Func> | ||||
| void StringTree::visit(Func&& func) const { | ||||
|   size_t pos = 0; | ||||
|   for (auto& branch: branches) { | ||||
|     if (branch.index > pos) { | ||||
|       func(text.slice(pos, branch.index)); | ||||
|       pos = branch.index; | ||||
|     } | ||||
|     branch.content.visit(func); | ||||
|   } | ||||
|   if (text.size() > pos) { | ||||
|     func(text.slice(pos, text.size())); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| inline void StringTree::fill(char* pos, size_t branchIndex) { | ||||
|   KJ_IREQUIRE(pos == text.end() && branchIndex == branches.size(), | ||||
|               kj::str(text.end() - pos, ' ', branches.size() - branchIndex).cStr()); | ||||
| } | ||||
| 
 | ||||
| template <typename First, typename... Rest> | ||||
| void StringTree::fill(char* pos, size_t branchIndex, First&& first, Rest&&... rest) { | ||||
|   pos = _::fill(pos, kj::fwd<First>(first)); | ||||
|   fill(pos, branchIndex, kj::fwd<Rest>(rest)...); | ||||
| } | ||||
| 
 | ||||
| template <typename... Rest> | ||||
| void StringTree::fill(char* pos, size_t branchIndex, StringTree&& first, Rest&&... rest) { | ||||
|   branches[branchIndex].index = pos - text.begin(); | ||||
|   branches[branchIndex].content = kj::mv(first); | ||||
|   fill(pos, branchIndex + 1, kj::fwd<Rest>(rest)...); | ||||
| } | ||||
| 
 | ||||
| template <typename... Rest> | ||||
| void StringTree::fill(char* pos, size_t branchIndex, String&& first, Rest&&... rest) { | ||||
|   branches[branchIndex].index = pos - text.begin(); | ||||
|   branches[branchIndex].content = StringTree(kj::mv(first)); | ||||
|   fill(pos, branchIndex + 1, kj::fwd<Rest>(rest)...); | ||||
| } | ||||
| 
 | ||||
| template <typename... Params> | ||||
| StringTree StringTree::concat(Params&&... params) { | ||||
|   StringTree result; | ||||
|   result.size_ = _::sum({params.size()...}); | ||||
|   result.text = heapString( | ||||
|       _::sum({StringTree::flatSize(kj::fwd<Params>(params))...})); | ||||
|   result.branches = heapArray<StringTree::Branch>( | ||||
|       _::sum({StringTree::branchCount(kj::fwd<Params>(params))...})); | ||||
|   result.fill(result.text.begin(), 0, kj::fwd<Params>(params)...); | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| template <typename... Params> | ||||
| StringTree strTree(Params&&... params) { | ||||
|   return StringTree::concat(_::toStringTreeOrCharSequence(kj::fwd<Params>(params))...); | ||||
| } | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_STRING_TREE_H_
 | ||||
| @ -0,0 +1,534 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_STRING_H_ | ||||
| #define KJ_STRING_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include <initializer_list> | ||||
| #include "array.h" | ||||
| #include <string.h> | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| class StringPtr; | ||||
| class String; | ||||
| 
 | ||||
| class StringTree;   // string-tree.h
 | ||||
| 
 | ||||
| // Our STL string SFINAE trick does not work with GCC 4.7, but it works with Clang and GCC 4.8, so
 | ||||
| // we'll just preprocess it out if not supported.
 | ||||
| #if __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || _MSC_VER | ||||
| #define KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP 1 | ||||
| #endif | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // StringPtr -- A NUL-terminated ArrayPtr<const char> containing UTF-8 text.
 | ||||
| //
 | ||||
| // NUL bytes are allowed to appear before the end of the string.  The only requirement is that
 | ||||
| // a NUL byte appear immediately after the last byte of the content.  This terminator byte is not
 | ||||
| // counted in the string's size.
 | ||||
| 
 | ||||
| class StringPtr { | ||||
| public: | ||||
|   inline StringPtr(): content("", 1) {} | ||||
|   inline StringPtr(decltype(nullptr)): content("", 1) {} | ||||
|   inline StringPtr(const char* value): content(value, strlen(value) + 1) {} | ||||
|   inline StringPtr(const char* value, size_t size): content(value, size + 1) { | ||||
|     KJ_IREQUIRE(value[size] == '\0', "StringPtr must be NUL-terminated."); | ||||
|   } | ||||
|   inline StringPtr(const char* begin, const char* end): StringPtr(begin, end - begin) {} | ||||
|   inline StringPtr(const String& value); | ||||
| 
 | ||||
| #if KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP | ||||
|   template <typename T, typename = decltype(instance<T>().c_str())> | ||||
|   inline StringPtr(const T& t): StringPtr(t.c_str()) {} | ||||
|   // Allow implicit conversion from any class that has a c_str() method (namely, std::string).
 | ||||
|   // We use a template trick to detect std::string in order to avoid including the header for
 | ||||
|   // those who don't want it.
 | ||||
| 
 | ||||
|   template <typename T, typename = decltype(instance<T>().c_str())> | ||||
|   inline operator T() const { return cStr(); } | ||||
|   // Allow implicit conversion to any class that has a c_str() method (namely, std::string).
 | ||||
|   // We use a template trick to detect std::string in order to avoid including the header for
 | ||||
|   // those who don't want it.
 | ||||
| #endif | ||||
| 
 | ||||
|   inline operator ArrayPtr<const char>() const; | ||||
|   inline ArrayPtr<const char> asArray() const; | ||||
|   inline ArrayPtr<const byte> asBytes() const { return asArray().asBytes(); } | ||||
|   // Result does not include NUL terminator.
 | ||||
| 
 | ||||
|   inline const char* cStr() const { return content.begin(); } | ||||
|   // Returns NUL-terminated string.
 | ||||
| 
 | ||||
|   inline size_t size() const { return content.size() - 1; } | ||||
|   // Result does not include NUL terminator.
 | ||||
| 
 | ||||
|   inline char operator[](size_t index) const { return content[index]; } | ||||
| 
 | ||||
|   inline const char* begin() const { return content.begin(); } | ||||
|   inline const char* end() const { return content.end() - 1; } | ||||
| 
 | ||||
|   inline bool operator==(decltype(nullptr)) const { return content.size() <= 1; } | ||||
|   inline bool operator!=(decltype(nullptr)) const { return content.size() > 1; } | ||||
| 
 | ||||
|   inline bool operator==(const StringPtr& other) const; | ||||
|   inline bool operator!=(const StringPtr& other) const { return !(*this == other); } | ||||
|   inline bool operator< (const StringPtr& other) const; | ||||
|   inline bool operator> (const StringPtr& other) const { return other < *this; } | ||||
|   inline bool operator<=(const StringPtr& other) const { return !(other < *this); } | ||||
|   inline bool operator>=(const StringPtr& other) const { return !(*this < other); } | ||||
| 
 | ||||
|   inline StringPtr slice(size_t start) const; | ||||
|   inline ArrayPtr<const char> slice(size_t start, size_t end) const; | ||||
|   // A string slice is only NUL-terminated if it is a suffix, so slice() has a one-parameter
 | ||||
|   // version that assumes end = size().
 | ||||
| 
 | ||||
|   inline bool startsWith(const StringPtr& other) const; | ||||
|   inline bool endsWith(const StringPtr& other) const; | ||||
| 
 | ||||
|   inline Maybe<size_t> findFirst(char c) const; | ||||
|   inline Maybe<size_t> findLast(char c) const; | ||||
| 
 | ||||
|   template <typename T> | ||||
|   T parseAs() const; | ||||
|   // Parse string as template number type.
 | ||||
|   // Integer numbers prefixed by "0x" and "0X" are parsed in base 16 (like strtoi with base 0).
 | ||||
|   // Integer numbers prefixed by "0" are parsed in base 10 (unlike strtoi with base 0).
 | ||||
|   // Overflowed integer numbers throw exception.
 | ||||
|   // Overflowed floating numbers return inf.
 | ||||
| 
 | ||||
| private: | ||||
|   inline StringPtr(ArrayPtr<const char> content): content(content) {} | ||||
| 
 | ||||
|   ArrayPtr<const char> content; | ||||
| }; | ||||
| 
 | ||||
| inline bool operator==(const char* a, const StringPtr& b) { return b == a; } | ||||
| inline bool operator!=(const char* a, const StringPtr& b) { return b != a; } | ||||
| 
 | ||||
| template <> char StringPtr::parseAs<char>() const; | ||||
| template <> signed char StringPtr::parseAs<signed char>() const; | ||||
| template <> unsigned char StringPtr::parseAs<unsigned char>() const; | ||||
| template <> short StringPtr::parseAs<short>() const; | ||||
| template <> unsigned short StringPtr::parseAs<unsigned short>() const; | ||||
| template <> int StringPtr::parseAs<int>() const; | ||||
| template <> unsigned StringPtr::parseAs<unsigned>() const; | ||||
| template <> long StringPtr::parseAs<long>() const; | ||||
| template <> unsigned long StringPtr::parseAs<unsigned long>() const; | ||||
| template <> long long StringPtr::parseAs<long long>() const; | ||||
| template <> unsigned long long StringPtr::parseAs<unsigned long long>() const; | ||||
| template <> float StringPtr::parseAs<float>() const; | ||||
| template <> double StringPtr::parseAs<double>() const; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // String -- A NUL-terminated Array<char> containing UTF-8 text.
 | ||||
| //
 | ||||
| // NUL bytes are allowed to appear before the end of the string.  The only requirement is that
 | ||||
| // a NUL byte appear immediately after the last byte of the content.  This terminator byte is not
 | ||||
| // counted in the string's size.
 | ||||
| //
 | ||||
| // To allocate a String, you must call kj::heapString().  We do not implement implicit copying to
 | ||||
| // the heap because this hides potential inefficiency from the developer.
 | ||||
| 
 | ||||
| class String { | ||||
| public: | ||||
|   String() = default; | ||||
|   inline String(decltype(nullptr)): content(nullptr) {} | ||||
|   inline String(char* value, size_t size, const ArrayDisposer& disposer); | ||||
|   // Does not copy.  `size` does not include NUL terminator, but `value` must be NUL-terminated.
 | ||||
|   inline explicit String(Array<char> buffer); | ||||
|   // Does not copy.  Requires `buffer` ends with `\0`.
 | ||||
| 
 | ||||
|   inline operator ArrayPtr<char>(); | ||||
|   inline operator ArrayPtr<const char>() const; | ||||
|   inline ArrayPtr<char> asArray(); | ||||
|   inline ArrayPtr<const char> asArray() const; | ||||
|   inline ArrayPtr<byte> asBytes() { return asArray().asBytes(); } | ||||
|   inline ArrayPtr<const byte> asBytes() const { return asArray().asBytes(); } | ||||
|   // Result does not include NUL terminator.
 | ||||
| 
 | ||||
|   inline Array<char> releaseArray() { return kj::mv(content); } | ||||
|   // Disowns the backing array (which includes the NUL terminator) and returns it. The String value
 | ||||
|   // is clobbered (as if moved away).
 | ||||
| 
 | ||||
|   inline const char* cStr() const; | ||||
| 
 | ||||
|   inline size_t size() const; | ||||
|   // Result does not include NUL terminator.
 | ||||
| 
 | ||||
|   inline char operator[](size_t index) const; | ||||
|   inline char& operator[](size_t index); | ||||
| 
 | ||||
|   inline char* begin(); | ||||
|   inline char* end(); | ||||
|   inline const char* begin() const; | ||||
|   inline const char* end() const; | ||||
| 
 | ||||
|   inline bool operator==(decltype(nullptr)) const { return content.size() <= 1; } | ||||
|   inline bool operator!=(decltype(nullptr)) const { return content.size() > 1; } | ||||
| 
 | ||||
|   inline bool operator==(const StringPtr& other) const { return StringPtr(*this) == other; } | ||||
|   inline bool operator!=(const StringPtr& other) const { return StringPtr(*this) != other; } | ||||
|   inline bool operator< (const StringPtr& other) const { return StringPtr(*this) <  other; } | ||||
|   inline bool operator> (const StringPtr& other) const { return StringPtr(*this) >  other; } | ||||
|   inline bool operator<=(const StringPtr& other) const { return StringPtr(*this) <= other; } | ||||
|   inline bool operator>=(const StringPtr& other) const { return StringPtr(*this) >= other; } | ||||
| 
 | ||||
|   inline bool startsWith(const StringPtr& other) const { return StringPtr(*this).startsWith(other);} | ||||
|   inline bool endsWith(const StringPtr& other) const { return StringPtr(*this).endsWith(other); } | ||||
| 
 | ||||
|   inline StringPtr slice(size_t start) const { return StringPtr(*this).slice(start); } | ||||
|   inline ArrayPtr<const char> slice(size_t start, size_t end) const { | ||||
|     return StringPtr(*this).slice(start, end); | ||||
|   } | ||||
| 
 | ||||
|   inline Maybe<size_t> findFirst(char c) const { return StringPtr(*this).findFirst(c); } | ||||
|   inline Maybe<size_t> findLast(char c) const { return StringPtr(*this).findLast(c); } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   T parseAs() const { return StringPtr(*this).parseAs<T>(); } | ||||
|   // Parse as number
 | ||||
| 
 | ||||
| private: | ||||
|   Array<char> content; | ||||
| }; | ||||
| 
 | ||||
| inline bool operator==(const char* a, const String& b) { return b == a; } | ||||
| inline bool operator!=(const char* a, const String& b) { return b != a; } | ||||
| 
 | ||||
| String heapString(size_t size); | ||||
| // Allocate a String of the given size on the heap, not including NUL terminator.  The NUL
 | ||||
| // terminator will be initialized automatically but the rest of the content is not initialized.
 | ||||
| 
 | ||||
| String heapString(const char* value); | ||||
| String heapString(const char* value, size_t size); | ||||
| String heapString(StringPtr value); | ||||
| String heapString(const String& value); | ||||
| String heapString(ArrayPtr<const char> value); | ||||
| // Allocates a copy of the given value on the heap.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Magic str() function which transforms parameters to text and concatenates them into one big
 | ||||
| // String.
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| inline size_t sum(std::initializer_list<size_t> nums) { | ||||
|   size_t result = 0; | ||||
|   for (auto num: nums) { | ||||
|     result += num; | ||||
|   } | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| inline char* fill(char* ptr) { return ptr; } | ||||
| 
 | ||||
| template <typename... Rest> | ||||
| char* fill(char* __restrict__ target, const StringTree& first, Rest&&... rest); | ||||
| // Make str() work with stringifiers that return StringTree by patching fill().
 | ||||
| //
 | ||||
| // Defined in string-tree.h.
 | ||||
| 
 | ||||
| template <typename First, typename... Rest> | ||||
| char* fill(char* __restrict__ target, const First& first, Rest&&... rest) { | ||||
|   auto i = first.begin(); | ||||
|   auto end = first.end(); | ||||
|   while (i != end) { | ||||
|     *target++ = *i++; | ||||
|   } | ||||
|   return fill(target, kj::fwd<Rest>(rest)...); | ||||
| } | ||||
| 
 | ||||
| template <typename... Params> | ||||
| String concat(Params&&... params) { | ||||
|   // Concatenate a bunch of containers into a single Array.  The containers can be anything that
 | ||||
|   // is iterable and whose elements can be converted to `char`.
 | ||||
| 
 | ||||
|   String result = heapString(sum({params.size()...})); | ||||
|   fill(result.begin(), kj::fwd<Params>(params)...); | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| inline String concat(String&& arr) { | ||||
|   return kj::mv(arr); | ||||
| } | ||||
| 
 | ||||
| struct Stringifier { | ||||
|   // This is a dummy type with only one instance: STR (below).  To make an arbitrary type
 | ||||
|   // stringifiable, define `operator*(Stringifier, T)` to return an iterable container of `char`.
 | ||||
|   // The container type must have a `size()` method.  Be sure to declare the operator in the same
 | ||||
|   // namespace as `T` **or** in the global scope.
 | ||||
|   //
 | ||||
|   // A more usual way to accomplish what we're doing here would be to require that you define
 | ||||
|   // a function like `toString(T)` and then rely on argument-dependent lookup.  However, this has
 | ||||
|   // the problem that it pollutes other people's namespaces and even the global namespace.  For
 | ||||
|   // example, some other project may already have functions called `toString` which do something
 | ||||
|   // different.  Declaring `operator*` with `Stringifier` as the left operand cannot conflict with
 | ||||
|   // anything.
 | ||||
| 
 | ||||
|   inline ArrayPtr<const char> operator*(ArrayPtr<const char> s) const { return s; } | ||||
|   inline ArrayPtr<const char> operator*(ArrayPtr<char> s) const { return s; } | ||||
|   inline ArrayPtr<const char> operator*(const Array<const char>& s) const { return s; } | ||||
|   inline ArrayPtr<const char> operator*(const Array<char>& s) const { return s; } | ||||
|   template<size_t n> | ||||
|   inline ArrayPtr<const char> operator*(const CappedArray<char, n>& s) const { return s; } | ||||
|   template<size_t n> | ||||
|   inline ArrayPtr<const char> operator*(const FixedArray<char, n>& s) const { return s; } | ||||
|   inline ArrayPtr<const char> operator*(const char* s) const { return arrayPtr(s, strlen(s)); } | ||||
|   inline ArrayPtr<const char> operator*(const String& s) const { return s.asArray(); } | ||||
|   inline ArrayPtr<const char> operator*(const StringPtr& s) const { return s.asArray(); } | ||||
| 
 | ||||
|   inline Range<char> operator*(const Range<char>& r) const { return r; } | ||||
|   inline Repeat<char> operator*(const Repeat<char>& r) const { return r; } | ||||
| 
 | ||||
|   inline FixedArray<char, 1> operator*(char c) const { | ||||
|     FixedArray<char, 1> result; | ||||
|     result[0] = c; | ||||
|     return result; | ||||
|   } | ||||
| 
 | ||||
|   StringPtr operator*(decltype(nullptr)) const; | ||||
|   StringPtr operator*(bool b) const; | ||||
| 
 | ||||
|   CappedArray<char, 5> operator*(signed char i) const; | ||||
|   CappedArray<char, 5> operator*(unsigned char i) const; | ||||
|   CappedArray<char, sizeof(short) * 3 + 2> operator*(short i) const; | ||||
|   CappedArray<char, sizeof(unsigned short) * 3 + 2> operator*(unsigned short i) const; | ||||
|   CappedArray<char, sizeof(int) * 3 + 2> operator*(int i) const; | ||||
|   CappedArray<char, sizeof(unsigned int) * 3 + 2> operator*(unsigned int i) const; | ||||
|   CappedArray<char, sizeof(long) * 3 + 2> operator*(long i) const; | ||||
|   CappedArray<char, sizeof(unsigned long) * 3 + 2> operator*(unsigned long i) const; | ||||
|   CappedArray<char, sizeof(long long) * 3 + 2> operator*(long long i) const; | ||||
|   CappedArray<char, sizeof(unsigned long long) * 3 + 2> operator*(unsigned long long i) const; | ||||
|   CappedArray<char, 24> operator*(float f) const; | ||||
|   CappedArray<char, 32> operator*(double f) const; | ||||
|   CappedArray<char, sizeof(const void*) * 3 + 2> operator*(const void* s) const; | ||||
| 
 | ||||
|   template <typename T> | ||||
|   String operator*(ArrayPtr<T> arr) const; | ||||
|   template <typename T> | ||||
|   String operator*(const Array<T>& arr) const; | ||||
| 
 | ||||
| #if KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP  // supports expression SFINAE?
 | ||||
|   template <typename T, typename Result = decltype(instance<T>().toString())> | ||||
|   inline Result operator*(T&& value) const { return kj::fwd<T>(value).toString(); } | ||||
| #endif | ||||
| }; | ||||
| static KJ_CONSTEXPR(const) Stringifier STR = Stringifier(); | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename T> | ||||
| auto toCharSequence(T&& value) -> decltype(_::STR * kj::fwd<T>(value)) { | ||||
|   // Returns an iterable of chars that represent a textual representation of the value, suitable
 | ||||
|   // for debugging.
 | ||||
|   //
 | ||||
|   // Most users should use str() instead, but toCharSequence() may occasionally be useful to avoid
 | ||||
|   // heap allocation overhead that str() implies.
 | ||||
|   //
 | ||||
|   // To specialize this function for your type, see KJ_STRINGIFY.
 | ||||
| 
 | ||||
|   return _::STR * kj::fwd<T>(value); | ||||
| } | ||||
| 
 | ||||
| CappedArray<char, sizeof(unsigned char) * 2 + 1> hex(unsigned char i); | ||||
| CappedArray<char, sizeof(unsigned short) * 2 + 1> hex(unsigned short i); | ||||
| CappedArray<char, sizeof(unsigned int) * 2 + 1> hex(unsigned int i); | ||||
| CappedArray<char, sizeof(unsigned long) * 2 + 1> hex(unsigned long i); | ||||
| CappedArray<char, sizeof(unsigned long long) * 2 + 1> hex(unsigned long long i); | ||||
| 
 | ||||
| template <typename... Params> | ||||
| String str(Params&&... params) { | ||||
|   // Magic function which builds a string from a bunch of arbitrary values.  Example:
 | ||||
|   //     str(1, " / ", 2, " = ", 0.5)
 | ||||
|   // returns:
 | ||||
|   //     "1 / 2 = 0.5"
 | ||||
|   // To teach `str` how to stringify a type, see `Stringifier`.
 | ||||
| 
 | ||||
|   return _::concat(toCharSequence(kj::fwd<Params>(params))...); | ||||
| } | ||||
| 
 | ||||
| inline String str(String&& s) { return mv(s); } | ||||
| // Overload to prevent redundant allocation.
 | ||||
| 
 | ||||
| template <typename T> | ||||
| String strArray(T&& arr, const char* delim) { | ||||
|   size_t delimLen = strlen(delim); | ||||
|   KJ_STACK_ARRAY(decltype(_::STR * arr[0]), pieces, kj::size(arr), 8, 32); | ||||
|   size_t size = 0; | ||||
|   for (size_t i = 0; i < kj::size(arr); i++) { | ||||
|     if (i > 0) size += delimLen; | ||||
|     pieces[i] = _::STR * arr[i]; | ||||
|     size += pieces[i].size(); | ||||
|   } | ||||
| 
 | ||||
|   String result = heapString(size); | ||||
|   char* pos = result.begin(); | ||||
|   for (size_t i = 0; i < kj::size(arr); i++) { | ||||
|     if (i > 0) { | ||||
|       memcpy(pos, delim, delimLen); | ||||
|       pos += delimLen; | ||||
|     } | ||||
|     pos = _::fill(pos, pieces[i]); | ||||
|   } | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T> | ||||
| inline String Stringifier::operator*(ArrayPtr<T> arr) const { | ||||
|   return strArray(arr, ", "); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline String Stringifier::operator*(const Array<T>& arr) const { | ||||
|   return strArray(arr, ", "); | ||||
| } | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| #define KJ_STRINGIFY(...) operator*(::kj::_::Stringifier, __VA_ARGS__) | ||||
| // Defines a stringifier for a custom type.  Example:
 | ||||
| //
 | ||||
| //    class Foo {...};
 | ||||
| //    inline StringPtr KJ_STRINGIFY(const Foo& foo) { return foo.name(); }
 | ||||
| //
 | ||||
| // This allows Foo to be passed to str().
 | ||||
| //
 | ||||
| // The function should be declared either in the same namespace as the target type or in the global
 | ||||
| // namespace.  It can return any type which is an iterable container of chars.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // Inline implementation details.
 | ||||
| 
 | ||||
| inline StringPtr::StringPtr(const String& value): content(value.begin(), value.size() + 1) {} | ||||
| 
 | ||||
| inline StringPtr::operator ArrayPtr<const char>() const { | ||||
|   return content.slice(0, content.size() - 1); | ||||
| } | ||||
| 
 | ||||
| inline ArrayPtr<const char> StringPtr::asArray() const { | ||||
|   return content.slice(0, content.size() - 1); | ||||
| } | ||||
| 
 | ||||
| inline bool StringPtr::operator==(const StringPtr& other) const { | ||||
|   return content.size() == other.content.size() && | ||||
|       memcmp(content.begin(), other.content.begin(), content.size() - 1) == 0; | ||||
| } | ||||
| 
 | ||||
| inline bool StringPtr::operator<(const StringPtr& other) const { | ||||
|   bool shorter = content.size() < other.content.size(); | ||||
|   int cmp = memcmp(content.begin(), other.content.begin(), | ||||
|                    shorter ? content.size() : other.content.size()); | ||||
|   return cmp < 0 || (cmp == 0 && shorter); | ||||
| } | ||||
| 
 | ||||
| inline StringPtr StringPtr::slice(size_t start) const { | ||||
|   return StringPtr(content.slice(start, content.size())); | ||||
| } | ||||
| inline ArrayPtr<const char> StringPtr::slice(size_t start, size_t end) const { | ||||
|   return content.slice(start, end); | ||||
| } | ||||
| 
 | ||||
| inline bool StringPtr::startsWith(const StringPtr& other) const { | ||||
|   return other.content.size() <= content.size() && | ||||
|       memcmp(content.begin(), other.content.begin(), other.size()) == 0; | ||||
| } | ||||
| inline bool StringPtr::endsWith(const StringPtr& other) const { | ||||
|   return other.content.size() <= content.size() && | ||||
|       memcmp(end() - other.size(), other.content.begin(), other.size()) == 0; | ||||
| } | ||||
| 
 | ||||
| inline Maybe<size_t> StringPtr::findFirst(char c) const { | ||||
|   const char* pos = reinterpret_cast<const char*>(memchr(content.begin(), c, size())); | ||||
|   if (pos == nullptr) { | ||||
|     return nullptr; | ||||
|   } else { | ||||
|     return pos - content.begin(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| inline Maybe<size_t> StringPtr::findLast(char c) const { | ||||
|   for (size_t i = size(); i > 0; --i) { | ||||
|     if (content[i-1] == c) { | ||||
|       return i-1; | ||||
|     } | ||||
|   } | ||||
|   return nullptr; | ||||
| } | ||||
| 
 | ||||
| inline String::operator ArrayPtr<char>() { | ||||
|   return content == nullptr ? ArrayPtr<char>(nullptr) : content.slice(0, content.size() - 1); | ||||
| } | ||||
| inline String::operator ArrayPtr<const char>() const { | ||||
|   return content == nullptr ? ArrayPtr<const char>(nullptr) : content.slice(0, content.size() - 1); | ||||
| } | ||||
| 
 | ||||
| inline ArrayPtr<char> String::asArray() { | ||||
|   return content == nullptr ? ArrayPtr<char>(nullptr) : content.slice(0, content.size() - 1); | ||||
| } | ||||
| inline ArrayPtr<const char> String::asArray() const { | ||||
|   return content == nullptr ? ArrayPtr<const char>(nullptr) : content.slice(0, content.size() - 1); | ||||
| } | ||||
| 
 | ||||
| inline const char* String::cStr() const { return content == nullptr ? "" : content.begin(); } | ||||
| 
 | ||||
| inline size_t String::size() const { return content == nullptr ? 0 : content.size() - 1; } | ||||
| 
 | ||||
| inline char String::operator[](size_t index) const { return content[index]; } | ||||
| inline char& String::operator[](size_t index) { return content[index]; } | ||||
| 
 | ||||
| inline char* String::begin() { return content == nullptr ? nullptr : content.begin(); } | ||||
| inline char* String::end() { return content == nullptr ? nullptr : content.end() - 1; } | ||||
| inline const char* String::begin() const { return content == nullptr ? nullptr : content.begin(); } | ||||
| inline const char* String::end() const { return content == nullptr ? nullptr : content.end() - 1; } | ||||
| 
 | ||||
| inline String::String(char* value, size_t size, const ArrayDisposer& disposer) | ||||
|     : content(value, size + 1, disposer) { | ||||
|   KJ_IREQUIRE(value[size] == '\0', "String must be NUL-terminated."); | ||||
| } | ||||
| 
 | ||||
| inline String::String(Array<char> buffer): content(kj::mv(buffer)) { | ||||
|   KJ_IREQUIRE(content.size() > 0 && content.back() == '\0', "String must be NUL-terminated."); | ||||
| } | ||||
| 
 | ||||
| inline String heapString(const char* value) { | ||||
|   return heapString(value, strlen(value)); | ||||
| } | ||||
| inline String heapString(StringPtr value) { | ||||
|   return heapString(value.begin(), value.size()); | ||||
| } | ||||
| inline String heapString(const String& value) { | ||||
|   return heapString(value.begin(), value.size()); | ||||
| } | ||||
| inline String heapString(ArrayPtr<const char> value) { | ||||
|   return heapString(value.begin(), value.size()); | ||||
| } | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_STRING_H_
 | ||||
| @ -0,0 +1,167 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_TEST_H_ | ||||
| #define KJ_TEST_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "debug.h" | ||||
| #include "vector.h" | ||||
| #include "function.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| class TestRunner; | ||||
| 
 | ||||
| class TestCase { | ||||
| public: | ||||
|   TestCase(const char* file, uint line, const char* description); | ||||
|   ~TestCase(); | ||||
| 
 | ||||
|   virtual void run() = 0; | ||||
| 
 | ||||
| private: | ||||
|   const char* file; | ||||
|   uint line; | ||||
|   const char* description; | ||||
|   TestCase* next; | ||||
|   TestCase** prev; | ||||
|   bool matchedFilter; | ||||
| 
 | ||||
|   friend class TestRunner; | ||||
| }; | ||||
| 
 | ||||
| #define KJ_TEST(description) \ | ||||
|   /* Make sure the linker fails if tests are not in anonymous namespaces. */ \
 | ||||
|   extern int KJ_CONCAT(YouMustWrapTestsInAnonymousNamespace, __COUNTER__) KJ_UNUSED; \
 | ||||
|   class KJ_UNIQUE_NAME(TestCase): public ::kj::TestCase { \
 | ||||
|   public: \
 | ||||
|     KJ_UNIQUE_NAME(TestCase)(): ::kj::TestCase(__FILE__, __LINE__, description) {} \
 | ||||
|     void run() override; \
 | ||||
|   } KJ_UNIQUE_NAME(testCase); \
 | ||||
|   void KJ_UNIQUE_NAME(TestCase)::run() | ||||
| 
 | ||||
| #if _MSC_VER | ||||
| #define KJ_INDIRECT_EXPAND(m, vargs) m vargs | ||||
| #define KJ_FAIL_EXPECT(...) \ | ||||
|   KJ_INDIRECT_EXPAND(KJ_LOG, (ERROR , __VA_ARGS__)); | ||||
| #define KJ_EXPECT(cond, ...) \ | ||||
|   if (cond); else KJ_INDIRECT_EXPAND(KJ_FAIL_EXPECT, ("failed: expected " #cond , __VA_ARGS__)) | ||||
| #else | ||||
| #define KJ_FAIL_EXPECT(...) \ | ||||
|   KJ_LOG(ERROR, ##__VA_ARGS__); | ||||
| #define KJ_EXPECT(cond, ...) \ | ||||
|   if (cond); else KJ_FAIL_EXPECT("failed: expected " #cond, ##__VA_ARGS__) | ||||
| #endif | ||||
| 
 | ||||
| #define KJ_EXPECT_THROW_RECOVERABLE(type, code) \ | ||||
|   do { \
 | ||||
|     KJ_IF_MAYBE(e, ::kj::runCatchingExceptions([&]() { code; })) { \
 | ||||
|       KJ_EXPECT(e->getType() == ::kj::Exception::Type::type, \
 | ||||
|           "code threw wrong exception type: " #code, e->getType()); \
 | ||||
|     } else { \
 | ||||
|       KJ_FAIL_EXPECT("code did not throw: " #code); \
 | ||||
|     } \
 | ||||
|   } while (false) | ||||
| 
 | ||||
| #define KJ_EXPECT_THROW_RECOVERABLE_MESSAGE(message, code) \ | ||||
|   do { \
 | ||||
|     KJ_IF_MAYBE(e, ::kj::runCatchingExceptions([&]() { code; })) { \
 | ||||
|       KJ_EXPECT(::kj::_::hasSubstring(e->getDescription(), message), \
 | ||||
|           "exception description didn't contain expected substring", e->getDescription()); \
 | ||||
|     } else { \
 | ||||
|       KJ_FAIL_EXPECT("code did not throw: " #code); \
 | ||||
|     } \
 | ||||
|   } while (false) | ||||
| 
 | ||||
| #if KJ_NO_EXCEPTIONS | ||||
| #define KJ_EXPECT_THROW(type, code) \ | ||||
|   do { \
 | ||||
|     KJ_EXPECT(::kj::_::expectFatalThrow(type, nullptr, [&]() { code; })); \
 | ||||
|   } while (false) | ||||
| #define KJ_EXPECT_THROW_MESSAGE(message, code) \ | ||||
|   do { \
 | ||||
|     KJ_EXPECT(::kj::_::expectFatalThrow(nullptr, kj::StringPtr(message), [&]() { code; })); \
 | ||||
|   } while (false) | ||||
| #else | ||||
| #define KJ_EXPECT_THROW KJ_EXPECT_THROW_RECOVERABLE | ||||
| #define KJ_EXPECT_THROW_MESSAGE KJ_EXPECT_THROW_RECOVERABLE_MESSAGE | ||||
| #endif | ||||
| 
 | ||||
| #define KJ_EXPECT_LOG(level, substring) \ | ||||
|   ::kj::_::LogExpectation KJ_UNIQUE_NAME(_kjLogExpectation)(::kj::LogSeverity::level, substring) | ||||
| // Expects that a log message with the given level and substring text will be printed within
 | ||||
| // the current scope. This message will not cause the test to fail, even if it is an error.
 | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| bool hasSubstring(kj::StringPtr haystack, kj::StringPtr needle); | ||||
| 
 | ||||
| #if KJ_NO_EXCEPTIONS | ||||
| bool expectFatalThrow(Maybe<Exception::Type> type, Maybe<StringPtr> message, | ||||
|                       Function<void()> code); | ||||
| // Expects that the given code will throw a fatal exception matching the given type and/or message.
 | ||||
| // Since exceptions are disabled, the test will fork() and run in a subprocess. On Windows, where
 | ||||
| // fork() is not available, this always returns true.
 | ||||
| #endif | ||||
| 
 | ||||
| class LogExpectation: public ExceptionCallback { | ||||
| public: | ||||
|   LogExpectation(LogSeverity severity, StringPtr substring); | ||||
|   ~LogExpectation(); | ||||
| 
 | ||||
|   void logMessage(LogSeverity severity, const char* file, int line, int contextDepth, | ||||
|                   String&& text) override; | ||||
| 
 | ||||
| private: | ||||
|   LogSeverity severity; | ||||
|   StringPtr substring; | ||||
|   bool seen; | ||||
|   UnwindDetector unwindDetector; | ||||
| }; | ||||
| 
 | ||||
| class GlobFilter { | ||||
|   // Implements glob filters for the --filter flag.
 | ||||
|   //
 | ||||
|   // Exposed in header only for testing.
 | ||||
| 
 | ||||
| public: | ||||
|   explicit GlobFilter(const char* pattern); | ||||
|   explicit GlobFilter(ArrayPtr<const char> pattern); | ||||
| 
 | ||||
|   bool matches(StringPtr name); | ||||
| 
 | ||||
| private: | ||||
|   String pattern; | ||||
|   Vector<uint> states; | ||||
| 
 | ||||
|   void applyState(char c, int state); | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif // KJ_TEST_H_
 | ||||
| @ -0,0 +1,82 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_THREAD_H_ | ||||
| #define KJ_THREAD_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "common.h" | ||||
| #include "function.h" | ||||
| #include "exception.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| class Thread { | ||||
|   // A thread!  Pass a lambda to the constructor, and it runs in the thread.  The destructor joins
 | ||||
|   // the thread.  If the function throws an exception, it is rethrown from the thread's destructor
 | ||||
|   // (if not unwinding from another exception).
 | ||||
| 
 | ||||
| public: | ||||
|   explicit Thread(Function<void()> func); | ||||
|   KJ_DISALLOW_COPY(Thread); | ||||
| 
 | ||||
|   ~Thread() noexcept(false); | ||||
| 
 | ||||
| #if !_WIN32 | ||||
|   void sendSignal(int signo); | ||||
|   // Send a Unix signal to the given thread, using pthread_kill or an equivalent.
 | ||||
| #endif | ||||
| 
 | ||||
|   void detach(); | ||||
|   // Don't join the thread in ~Thread().
 | ||||
| 
 | ||||
| private: | ||||
|   struct ThreadState { | ||||
|     Function<void()> func; | ||||
|     kj::Maybe<kj::Exception> exception; | ||||
| 
 | ||||
|     unsigned int refcount; | ||||
|     // Owned by the parent thread and the child thread.
 | ||||
| 
 | ||||
|     void unref(); | ||||
|   }; | ||||
|   ThreadState* state; | ||||
| 
 | ||||
| #if _WIN32 | ||||
|   void* threadHandle; | ||||
| #else | ||||
|   unsigned long long threadId;  // actually pthread_t
 | ||||
| #endif | ||||
|   bool detached = false; | ||||
| 
 | ||||
| #if _WIN32 | ||||
|   static unsigned long __stdcall runThread(void* ptr); | ||||
| #else | ||||
|   static void* runThread(void* ptr); | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_THREAD_H_
 | ||||
| @ -0,0 +1,136 @@ | ||||
| // Copyright (c) 2014, Jason Choy <jjwchoy@gmail.com>
 | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_THREADLOCAL_H_ | ||||
| #define KJ_THREADLOCAL_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| // This file declares a macro `KJ_THREADLOCAL_PTR` for declaring thread-local pointer-typed
 | ||||
| // variables.  Use like:
 | ||||
| //     KJ_THREADLOCAL_PTR(MyType) foo = nullptr;
 | ||||
| // This is equivalent to:
 | ||||
| //     thread_local MyType* foo = nullptr;
 | ||||
| // This can only be used at the global scope.
 | ||||
| //
 | ||||
| // AVOID USING THIS.  Use of thread-locals is discouraged because they often have many of the same
 | ||||
| // properties as singletons: http://www.object-oriented-security.org/lets-argue/singletons
 | ||||
| //
 | ||||
| // Also, thread-locals tend to be hostile to event-driven code, which can be particularly
 | ||||
| // surprising when using fibers (all fibers in the same thread will share the same threadlocals,
 | ||||
| // even though they do not share a stack).
 | ||||
| //
 | ||||
| // That said, thread-locals are sometimes needed for runtime logistics in the KJ framework.  For
 | ||||
| // example, the current exception callback and current EventLoop are stored as thread-local
 | ||||
| // pointers.  Since KJ only ever needs to store pointers, not values, we avoid the question of
 | ||||
| // whether these values' destructors need to be run, and we avoid the need for heap allocation.
 | ||||
| 
 | ||||
| #include "common.h" | ||||
| 
 | ||||
| #if !defined(KJ_USE_PTHREAD_THREADLOCAL) && defined(__APPLE__) | ||||
| #include "TargetConditionals.h" | ||||
| #if TARGET_OS_IPHONE | ||||
| // iOS apparently does not support __thread (nor C++11 thread_local).
 | ||||
| #define KJ_USE_PTHREAD_TLS 1 | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| #if KJ_USE_PTHREAD_TLS | ||||
| #include <pthread.h> | ||||
| #endif | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| #if KJ_USE_PTHREAD_TLS | ||||
| // If __thread is unavailable, we'll fall back to pthreads.
 | ||||
| 
 | ||||
| #define KJ_THREADLOCAL_PTR(type) \ | ||||
|   namespace { struct KJ_UNIQUE_NAME(_kj_TlpTag); } \
 | ||||
|   static ::kj::_::ThreadLocalPtr< type, KJ_UNIQUE_NAME(_kj_TlpTag)> | ||||
| // Hack:  In order to ensure each thread-local results in a unique template instance, we declare
 | ||||
| //   a one-off dummy type to use as the second type parameter.
 | ||||
| 
 | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <typename T, typename> | ||||
| class ThreadLocalPtr { | ||||
|   // Hacky type to emulate __thread T*.  We need a separate instance of the ThreadLocalPtr template
 | ||||
|   // for every thread-local variable, because we don't want to require a global constructor, and in
 | ||||
|   // order to initialize the TLS on first use we need to use a local static variable (in getKey()).
 | ||||
|   // Each template instance will get a separate such local static variable, fulfilling our need.
 | ||||
| 
 | ||||
| public: | ||||
|   ThreadLocalPtr() = default; | ||||
|   constexpr ThreadLocalPtr(decltype(nullptr)) {} | ||||
|   // Allow initialization to nullptr without a global constructor.
 | ||||
| 
 | ||||
|   inline ThreadLocalPtr& operator=(T* val) { | ||||
|     pthread_setspecific(getKey(), val); | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   inline operator T*() const { | ||||
|     return get(); | ||||
|   } | ||||
| 
 | ||||
|   inline T& operator*() const { | ||||
|     return *get(); | ||||
|   } | ||||
| 
 | ||||
|   inline T* operator->() const { | ||||
|     return get(); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   inline T* get() const { | ||||
|     return reinterpret_cast<T*>(pthread_getspecific(getKey())); | ||||
|   } | ||||
| 
 | ||||
|   inline static pthread_key_t getKey() { | ||||
|     static pthread_key_t key = createKey(); | ||||
|     return key; | ||||
|   } | ||||
| 
 | ||||
|   static pthread_key_t createKey() { | ||||
|     pthread_key_t key; | ||||
|     pthread_key_create(&key, 0); | ||||
|     return key; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| #elif __GNUC__ | ||||
| 
 | ||||
| #define KJ_THREADLOCAL_PTR(type) static __thread type* | ||||
| // GCC's __thread is lighter-weight than thread_local and is good enough for our purposes.
 | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| #define KJ_THREADLOCAL_PTR(type) static thread_local type* | ||||
| 
 | ||||
| #endif // KJ_USE_PTHREAD_TLS
 | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_THREADLOCAL_H_
 | ||||
| @ -0,0 +1,174 @@ | ||||
| // Copyright (c) 2014 Google Inc. (contributed by Remy Blank <rblank@google.com>)
 | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_TIME_H_ | ||||
| #define KJ_TIME_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "async.h" | ||||
| #include "units.h" | ||||
| #include <inttypes.h> | ||||
| 
 | ||||
| namespace kj { | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| class NanosecondLabel; | ||||
| class TimeLabel; | ||||
| class DateLabel; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| using Duration = Quantity<int64_t, _::NanosecondLabel>; | ||||
| // A time value, in nanoseconds.
 | ||||
| 
 | ||||
| constexpr Duration NANOSECONDS = unit<Duration>(); | ||||
| constexpr Duration MICROSECONDS = 1000 * NANOSECONDS; | ||||
| constexpr Duration MILLISECONDS = 1000 * MICROSECONDS; | ||||
| constexpr Duration SECONDS = 1000 * MILLISECONDS; | ||||
| constexpr Duration MINUTES = 60 * SECONDS; | ||||
| constexpr Duration HOURS = 60 * MINUTES; | ||||
| constexpr Duration DAYS = 24 * HOURS; | ||||
| 
 | ||||
| using TimePoint = Absolute<Duration, _::TimeLabel>; | ||||
| // An absolute time measured by some particular instance of `Timer`.  `Time`s from two different
 | ||||
| // `Timer`s may be measured from different origins and so are not necessarily compatible.
 | ||||
| 
 | ||||
| using Date = Absolute<Duration, _::DateLabel>; | ||||
| // A point in real-world time, measured relative to the Unix epoch (Jan 1, 1970 00:00:00 UTC).
 | ||||
| 
 | ||||
| constexpr Date UNIX_EPOCH = origin<Date>(); | ||||
| // The `Date` representing Jan 1, 1970 00:00:00 UTC.
 | ||||
| 
 | ||||
| class Clock { | ||||
|   // Interface to read the current date and time.
 | ||||
| public: | ||||
|   virtual Date now() = 0; | ||||
| }; | ||||
| 
 | ||||
| Clock& nullClock(); | ||||
| // A clock which always returns UNIX_EPOCH as the current time. Useful when you don't care about
 | ||||
| // time.
 | ||||
| 
 | ||||
| class Timer { | ||||
|   // Interface to time and timer functionality.
 | ||||
|   //
 | ||||
|   // Each `Timer` may have a different origin, and some `Timer`s may in fact tick at a different
 | ||||
|   // rate than real time (e.g. a `Timer` could represent CPU time consumed by a thread).  However,
 | ||||
|   // all `Timer`s are monotonic: time will never appear to move backwards, even if the calendar
 | ||||
|   // date as tracked by the system is manually modified.
 | ||||
| 
 | ||||
| public: | ||||
|   virtual TimePoint now() = 0; | ||||
|   // Returns the current value of a clock that moves steadily forward, independent of any
 | ||||
|   // changes in the wall clock. The value is updated every time the event loop waits,
 | ||||
|   // and is constant in-between waits.
 | ||||
| 
 | ||||
|   virtual Promise<void> atTime(TimePoint time) = 0; | ||||
|   // Returns a promise that returns as soon as now() >= time.
 | ||||
| 
 | ||||
|   virtual Promise<void> afterDelay(Duration delay) = 0; | ||||
|   // Equivalent to atTime(now() + delay).
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   Promise<T> timeoutAt(TimePoint time, Promise<T>&& promise) KJ_WARN_UNUSED_RESULT; | ||||
|   // Return a promise equivalent to `promise` but which throws an exception (and cancels the
 | ||||
|   // original promise) if it hasn't completed by `time`. The thrown exception is of type
 | ||||
|   // "OVERLOADED".
 | ||||
| 
 | ||||
|   template <typename T> | ||||
|   Promise<T> timeoutAfter(Duration delay, Promise<T>&& promise) KJ_WARN_UNUSED_RESULT; | ||||
|   // Return a promise equivalent to `promise` but which throws an exception (and cancels the
 | ||||
|   // original promise) if it hasn't completed after `delay` from now. The thrown exception is of
 | ||||
|   // type "OVERLOADED".
 | ||||
| 
 | ||||
| private: | ||||
|   static kj::Exception makeTimeoutException(); | ||||
| }; | ||||
| 
 | ||||
| class TimerImpl final: public Timer { | ||||
|   // Implementation of Timer that expects an external caller -- usually, the EventPort
 | ||||
|   // implementation -- to tell it when time has advanced.
 | ||||
| 
 | ||||
| public: | ||||
|   TimerImpl(TimePoint startTime); | ||||
|   ~TimerImpl() noexcept(false); | ||||
| 
 | ||||
|   Maybe<TimePoint> nextEvent(); | ||||
|   // Returns the time at which the next scheduled timer event will occur, or null if no timer
 | ||||
|   // events are scheduled.
 | ||||
| 
 | ||||
|   Maybe<uint64_t> timeoutToNextEvent(TimePoint start, Duration unit, uint64_t max); | ||||
|   // Convenience method which computes a timeout value to pass to an event-waiting system call to
 | ||||
|   // cause it to time out when the next timer event occurs.
 | ||||
|   //
 | ||||
|   // `start` is the time at which the timeout starts counting. This is typically not the same as
 | ||||
|   // now() since some time may have passed since the last time advanceTo() was called.
 | ||||
|   //
 | ||||
|   // `unit` is the time unit in which the timeout is measured. This is often MILLISECONDS. Note
 | ||||
|   // that this method will fractional values *up*, to guarantee that the returned timeout waits
 | ||||
|   // until just *after* the time the event is scheduled.
 | ||||
|   //
 | ||||
|   // The timeout will be clamped to `max`. Use this to avoid an overflow if e.g. the OS wants a
 | ||||
|   // 32-bit value or a signed value.
 | ||||
|   //
 | ||||
|   // Returns nullptr if there are no future events.
 | ||||
| 
 | ||||
|   void advanceTo(TimePoint newTime); | ||||
|   // Set the time to `time` and fire any at() events that have been passed.
 | ||||
| 
 | ||||
|   // implements Timer ----------------------------------------------------------
 | ||||
|   TimePoint now() override; | ||||
|   Promise<void> atTime(TimePoint time) override; | ||||
|   Promise<void> afterDelay(Duration delay) override; | ||||
| 
 | ||||
| private: | ||||
|   struct Impl; | ||||
|   class TimerPromiseAdapter; | ||||
|   TimePoint time; | ||||
|   Own<Impl> impl; | ||||
| }; | ||||
| 
 | ||||
| // =======================================================================================
 | ||||
| // inline implementation details
 | ||||
| 
 | ||||
| template <typename T> | ||||
| Promise<T> Timer::timeoutAt(TimePoint time, Promise<T>&& promise) { | ||||
|   return promise.exclusiveJoin(atTime(time).then([]() -> kj::Promise<T> { | ||||
|     return makeTimeoutException(); | ||||
|   })); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| Promise<T> Timer::timeoutAfter(Duration delay, Promise<T>&& promise) { | ||||
|   return promise.exclusiveJoin(afterDelay(delay).then([]() -> kj::Promise<T> { | ||||
|     return makeTimeoutException(); | ||||
|   })); | ||||
| } | ||||
| 
 | ||||
| inline TimePoint TimerImpl::now() { return time; } | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_TIME_H_
 | ||||
| @ -0,0 +1,364 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| // This file defines a notion of tuples that is simpler that `std::tuple`.  It works as follows:
 | ||||
| // - `kj::Tuple<A, B, C> is the type of a tuple of an A, a B, and a C.
 | ||||
| // - `kj::tuple(a, b, c)` returns a tuple containing a, b, and c.  If any of these are themselves
 | ||||
| //   tuples, they are flattened, so `tuple(a, tuple(b, c), d)` is equivalent to `tuple(a, b, c, d)`.
 | ||||
| // - `kj::get<n>(myTuple)` returns the element of `myTuple` at index n.
 | ||||
| // - `kj::apply(func, ...)` calls func on the following arguments after first expanding any tuples
 | ||||
| //   in the argument list.  So `kj::apply(foo, a, tuple(b, c), d)` would call `foo(a, b, c, d)`.
 | ||||
| //
 | ||||
| // Note that:
 | ||||
| // - The type `Tuple<T>` is a synonym for T.  This is why `get` and `apply` are not members of the
 | ||||
| //   type.
 | ||||
| // - It is illegal for an element of `Tuple` to itself be a tuple, as tuples are meant to be
 | ||||
| //   flattened.
 | ||||
| // - It is illegal for an element of `Tuple` to be a reference, due to problems this would cause
 | ||||
| //   with type inference and `tuple()`.
 | ||||
| 
 | ||||
| #ifndef KJ_TUPLE_H_ | ||||
| #define KJ_TUPLE_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "common.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| namespace _ {  // private
 | ||||
| 
 | ||||
| template <size_t index, typename... T> | ||||
| struct TypeByIndex_; | ||||
| template <typename First, typename... Rest> | ||||
| struct TypeByIndex_<0, First, Rest...> { | ||||
|   typedef First Type; | ||||
| }; | ||||
| template <size_t index, typename First, typename... Rest> | ||||
| struct TypeByIndex_<index, First, Rest...> | ||||
|     : public TypeByIndex_<index - 1, Rest...> {}; | ||||
| template <size_t index> | ||||
| struct TypeByIndex_<index> { | ||||
|   static_assert(index != index, "Index out-of-range."); | ||||
| }; | ||||
| template <size_t index, typename... T> | ||||
| using TypeByIndex = typename TypeByIndex_<index, T...>::Type; | ||||
| // Chose a particular type out of a list of types, by index.
 | ||||
| 
 | ||||
| template <size_t... s> | ||||
| struct Indexes {}; | ||||
| // Dummy helper type that just encapsulates a sequential list of indexes, so that we can match
 | ||||
| // templates against them and unpack them with '...'.
 | ||||
| 
 | ||||
| template <size_t end, size_t... prefix> | ||||
| struct MakeIndexes_: public MakeIndexes_<end - 1, end - 1, prefix...> {}; | ||||
| template <size_t... prefix> | ||||
| struct MakeIndexes_<0, prefix...> { | ||||
|   typedef Indexes<prefix...> Type; | ||||
| }; | ||||
| template <size_t end> | ||||
| using MakeIndexes = typename MakeIndexes_<end>::Type; | ||||
| // Equivalent to Indexes<0, 1, 2, ..., end>.
 | ||||
| 
 | ||||
| template <typename... T> | ||||
| class Tuple; | ||||
| template <size_t index, typename... U> | ||||
| inline TypeByIndex<index, U...>& getImpl(Tuple<U...>& tuple); | ||||
| template <size_t index, typename... U> | ||||
| inline TypeByIndex<index, U...>&& getImpl(Tuple<U...>&& tuple); | ||||
| template <size_t index, typename... U> | ||||
| inline const TypeByIndex<index, U...>& getImpl(const Tuple<U...>& tuple); | ||||
| 
 | ||||
| template <uint index, typename T> | ||||
| struct TupleElement { | ||||
|   // Encapsulates one element of a tuple.  The actual tuple implementation multiply-inherits
 | ||||
|   // from a TupleElement for each element, which is more efficient than a recursive definition.
 | ||||
| 
 | ||||
|   T value; | ||||
|   TupleElement() = default; | ||||
|   constexpr inline TupleElement(const T& value): value(value) {} | ||||
|   constexpr inline TupleElement(T&& value): value(kj::mv(value)) {} | ||||
| }; | ||||
| 
 | ||||
| template <uint index, typename T> | ||||
| struct TupleElement<index, T&> { | ||||
|   // If tuples contained references, one of the following would have to be true:
 | ||||
|   // - `auto x = tuple(y, z)` would cause x to be a tuple of references to y and z, which is
 | ||||
|   //   probably not what you expected.
 | ||||
|   // - `Tuple<Foo&, Bar&> x = tuple(a, b)` would not work, because `tuple()` returned
 | ||||
|   //   Tuple<Foo, Bar>.
 | ||||
|   static_assert(sizeof(T*) == 0, "Sorry, tuples cannot contain references."); | ||||
| }; | ||||
| 
 | ||||
| template <uint index, typename... T> | ||||
| struct TupleElement<index, Tuple<T...>> { | ||||
|   static_assert(sizeof(Tuple<T...>*) == 0, | ||||
|                 "Tuples cannot contain other tuples -- they should be flattened."); | ||||
| }; | ||||
| 
 | ||||
| template <typename Indexes, typename... Types> | ||||
| struct TupleImpl; | ||||
| 
 | ||||
| template <size_t... indexes, typename... Types> | ||||
| struct TupleImpl<Indexes<indexes...>, Types...> | ||||
|     : public TupleElement<indexes, Types>... { | ||||
|   // Implementation of Tuple.  The only reason we need this rather than rolling this into class
 | ||||
|   // Tuple (below) is so that we can get "indexes" as an unpackable list.
 | ||||
| 
 | ||||
|   static_assert(sizeof...(indexes) == sizeof...(Types), "Incorrect use of TupleImpl."); | ||||
| 
 | ||||
|   template <typename... Params> | ||||
|   inline TupleImpl(Params&&... params) | ||||
|       : TupleElement<indexes, Types>(kj::fwd<Params>(params))... { | ||||
|     // Work around Clang 3.2 bug 16303 where this is not detected.  (Unfortunately, Clang sometimes
 | ||||
|     // segfaults instead.)
 | ||||
|     static_assert(sizeof...(params) == sizeof...(indexes), | ||||
|                   "Wrong number of parameters to Tuple constructor."); | ||||
|   } | ||||
| 
 | ||||
|   template <typename... U> | ||||
|   constexpr inline TupleImpl(Tuple<U...>&& other) | ||||
|       : TupleElement<indexes, Types>(kj::mv(getImpl<indexes>(other)))... {} | ||||
|   template <typename... U> | ||||
|   constexpr inline TupleImpl(Tuple<U...>& other) | ||||
|       : TupleElement<indexes, Types>(getImpl<indexes>(other))... {} | ||||
|   template <typename... U> | ||||
|   constexpr inline TupleImpl(const Tuple<U...>& other) | ||||
|       : TupleElement<indexes, Types>(getImpl<indexes>(other))... {} | ||||
| }; | ||||
| 
 | ||||
| struct MakeTupleFunc; | ||||
| 
 | ||||
| template <typename... T> | ||||
| class Tuple { | ||||
|   // The actual Tuple class (used for tuples of size other than 1).
 | ||||
| 
 | ||||
| public: | ||||
|   template <typename... U> | ||||
|   constexpr inline Tuple(Tuple<U...>&& other): impl(kj::mv(other)) {} | ||||
|   template <typename... U> | ||||
|   constexpr inline Tuple(Tuple<U...>& other): impl(other) {} | ||||
|   template <typename... U> | ||||
|   constexpr inline Tuple(const Tuple<U...>& other): impl(other) {} | ||||
| 
 | ||||
| private: | ||||
|   template <typename... Params> | ||||
|   constexpr Tuple(Params&&... params): impl(kj::fwd<Params>(params)...) {} | ||||
| 
 | ||||
|   TupleImpl<MakeIndexes<sizeof...(T)>, T...> impl; | ||||
| 
 | ||||
|   template <size_t index, typename... U> | ||||
|   friend inline TypeByIndex<index, U...>& getImpl(Tuple<U...>& tuple); | ||||
|   template <size_t index, typename... U> | ||||
|   friend inline TypeByIndex<index, U...>&& getImpl(Tuple<U...>&& tuple); | ||||
|   template <size_t index, typename... U> | ||||
|   friend inline const TypeByIndex<index, U...>& getImpl(const Tuple<U...>& tuple); | ||||
|   friend struct MakeTupleFunc; | ||||
| }; | ||||
| 
 | ||||
| template <> | ||||
| class Tuple<> { | ||||
|   // Simplified zero-member version of Tuple.  In particular this is important to make sure that
 | ||||
|   // Tuple<>() is constexpr.
 | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| class Tuple<T>; | ||||
| // Single-element tuple should never be used.  The public API should ensure this.
 | ||||
| 
 | ||||
| template <size_t index, typename... T> | ||||
| inline TypeByIndex<index, T...>& getImpl(Tuple<T...>& tuple) { | ||||
|   // Get member of a Tuple by index, e.g. `get<2>(myTuple)`.
 | ||||
|   static_assert(index < sizeof...(T), "Tuple element index out-of-bounds."); | ||||
|   return implicitCast<TupleElement<index, TypeByIndex<index, T...>>&>(tuple.impl).value; | ||||
| } | ||||
| template <size_t index, typename... T> | ||||
| inline TypeByIndex<index, T...>&& getImpl(Tuple<T...>&& tuple) { | ||||
|   // Get member of a Tuple by index, e.g. `get<2>(myTuple)`.
 | ||||
|   static_assert(index < sizeof...(T), "Tuple element index out-of-bounds."); | ||||
|   return kj::mv(implicitCast<TupleElement<index, TypeByIndex<index, T...>>&>(tuple.impl).value); | ||||
| } | ||||
| template <size_t index, typename... T> | ||||
| inline const TypeByIndex<index, T...>& getImpl(const Tuple<T...>& tuple) { | ||||
|   // Get member of a Tuple by index, e.g. `get<2>(myTuple)`.
 | ||||
|   static_assert(index < sizeof...(T), "Tuple element index out-of-bounds."); | ||||
|   return implicitCast<const TupleElement<index, TypeByIndex<index, T...>>&>(tuple.impl).value; | ||||
| } | ||||
| template <size_t index, typename T> | ||||
| inline T&& getImpl(T&& value) { | ||||
|   // Get member of a Tuple by index, e.g. `getImpl<2>(myTuple)`.
 | ||||
| 
 | ||||
|   // Non-tuples are equivalent to one-element tuples.
 | ||||
|   static_assert(index == 0, "Tuple element index out-of-bounds."); | ||||
|   return kj::fwd<T>(value); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| template <typename Func, typename SoFar, typename... T> | ||||
| struct ExpandAndApplyResult_; | ||||
| // Template which computes the return type of applying Func to T... after flattening tuples.
 | ||||
| // SoFar starts as Tuple<> and accumulates the flattened parameter types -- so after this template
 | ||||
| // is recursively expanded, T... is empty and SoFar is a Tuple containing all the parameters.
 | ||||
| 
 | ||||
| template <typename Func, typename First, typename... Rest, typename... T> | ||||
| struct ExpandAndApplyResult_<Func, Tuple<T...>, First, Rest...> | ||||
|     : public ExpandAndApplyResult_<Func, Tuple<T..., First>, Rest...> {}; | ||||
| template <typename Func, typename... FirstTypes, typename... Rest, typename... T> | ||||
| struct ExpandAndApplyResult_<Func, Tuple<T...>, Tuple<FirstTypes...>, Rest...> | ||||
|     : public ExpandAndApplyResult_<Func, Tuple<T...>, FirstTypes&&..., Rest...> {}; | ||||
| template <typename Func, typename... FirstTypes, typename... Rest, typename... T> | ||||
| struct ExpandAndApplyResult_<Func, Tuple<T...>, Tuple<FirstTypes...>&, Rest...> | ||||
|     : public ExpandAndApplyResult_<Func, Tuple<T...>, FirstTypes&..., Rest...> {}; | ||||
| template <typename Func, typename... FirstTypes, typename... Rest, typename... T> | ||||
| struct ExpandAndApplyResult_<Func, Tuple<T...>, const Tuple<FirstTypes...>&, Rest...> | ||||
|     : public ExpandAndApplyResult_<Func, Tuple<T...>, const FirstTypes&..., Rest...> {}; | ||||
| template <typename Func, typename... T> | ||||
| struct ExpandAndApplyResult_<Func, Tuple<T...>> { | ||||
|   typedef decltype(instance<Func>()(instance<T&&>()...)) Type; | ||||
| }; | ||||
| template <typename Func, typename... T> | ||||
| using ExpandAndApplyResult = typename ExpandAndApplyResult_<Func, Tuple<>, T...>::Type; | ||||
| // Computes the expected return type of `expandAndApply()`.
 | ||||
| 
 | ||||
| template <typename Func> | ||||
| inline auto expandAndApply(Func&& func) -> ExpandAndApplyResult<Func> { | ||||
|   return func(); | ||||
| } | ||||
| 
 | ||||
| template <typename Func, typename First, typename... Rest> | ||||
| struct ExpandAndApplyFunc { | ||||
|   Func&& func; | ||||
|   First&& first; | ||||
|   ExpandAndApplyFunc(Func&& func, First&& first) | ||||
|       : func(kj::fwd<Func>(func)), first(kj::fwd<First>(first)) {} | ||||
|   template <typename... T> | ||||
|   auto operator()(T&&... params) | ||||
|       -> decltype(this->func(kj::fwd<First>(first), kj::fwd<T>(params)...)) { | ||||
|     return this->func(kj::fwd<First>(first), kj::fwd<T>(params)...); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename Func, typename First, typename... Rest> | ||||
| inline auto expandAndApply(Func&& func, First&& first, Rest&&... rest) | ||||
|     -> ExpandAndApplyResult<Func, First, Rest...> { | ||||
| 
 | ||||
|   return expandAndApply( | ||||
|       ExpandAndApplyFunc<Func, First, Rest...>(kj::fwd<Func>(func), kj::fwd<First>(first)), | ||||
|       kj::fwd<Rest>(rest)...); | ||||
| } | ||||
| 
 | ||||
| template <typename Func, typename... FirstTypes, typename... Rest> | ||||
| inline auto expandAndApply(Func&& func, Tuple<FirstTypes...>&& first, Rest&&... rest) | ||||
|     -> ExpandAndApplyResult<Func, FirstTypes&&..., Rest...> { | ||||
|   return expandAndApplyWithIndexes(MakeIndexes<sizeof...(FirstTypes)>(), | ||||
|       kj::fwd<Func>(func), kj::mv(first), kj::fwd<Rest>(rest)...); | ||||
| } | ||||
| 
 | ||||
| template <typename Func, typename... FirstTypes, typename... Rest> | ||||
| inline auto expandAndApply(Func&& func, Tuple<FirstTypes...>& first, Rest&&... rest) | ||||
|     -> ExpandAndApplyResult<Func, FirstTypes..., Rest...> { | ||||
|   return expandAndApplyWithIndexes(MakeIndexes<sizeof...(FirstTypes)>(), | ||||
|       kj::fwd<Func>(func), first, kj::fwd<Rest>(rest)...); | ||||
| } | ||||
| 
 | ||||
| template <typename Func, typename... FirstTypes, typename... Rest> | ||||
| inline auto expandAndApply(Func&& func, const Tuple<FirstTypes...>& first, Rest&&... rest) | ||||
|     -> ExpandAndApplyResult<Func, FirstTypes..., Rest...> { | ||||
|   return expandAndApplyWithIndexes(MakeIndexes<sizeof...(FirstTypes)>(), | ||||
|       kj::fwd<Func>(func), first, kj::fwd<Rest>(rest)...); | ||||
| } | ||||
| 
 | ||||
| template <typename Func, typename... FirstTypes, typename... Rest, size_t... indexes> | ||||
| inline auto expandAndApplyWithIndexes( | ||||
|     Indexes<indexes...>, Func&& func, Tuple<FirstTypes...>&& first, Rest&&... rest) | ||||
|     -> ExpandAndApplyResult<Func, FirstTypes&&..., Rest...> { | ||||
|   return expandAndApply(kj::fwd<Func>(func), kj::mv(getImpl<indexes>(first))..., | ||||
|                         kj::fwd<Rest>(rest)...); | ||||
| } | ||||
| 
 | ||||
| template <typename Func, typename... FirstTypes, typename... Rest, size_t... indexes> | ||||
| inline auto expandAndApplyWithIndexes( | ||||
|     Indexes<indexes...>, Func&& func, const Tuple<FirstTypes...>& first, Rest&&... rest) | ||||
|     -> ExpandAndApplyResult<Func, FirstTypes..., Rest...> { | ||||
|   return expandAndApply(kj::fwd<Func>(func), getImpl<indexes>(first)..., | ||||
|                        kj::fwd<Rest>(rest)...); | ||||
| } | ||||
| 
 | ||||
| struct MakeTupleFunc { | ||||
|   template <typename... Params> | ||||
|   Tuple<Decay<Params>...> operator()(Params&&... params) { | ||||
|     return Tuple<Decay<Params>...>(kj::fwd<Params>(params)...); | ||||
|   } | ||||
|   template <typename Param> | ||||
|   Decay<Param> operator()(Param&& param) { | ||||
|     return kj::fwd<Param>(param); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| }  // namespace _ (private)
 | ||||
| 
 | ||||
| template <typename... T> struct Tuple_ { typedef _::Tuple<T...> Type; }; | ||||
| template <typename T> struct Tuple_<T> { typedef T Type; }; | ||||
| 
 | ||||
| template <typename... T> using Tuple = typename Tuple_<T...>::Type; | ||||
| // Tuple type.  `Tuple<T>` (i.e. a single-element tuple) is a synonym for `T`.  Tuples of size
 | ||||
| // other than 1 expand to an internal type.  Either way, you can construct a Tuple using
 | ||||
| // `kj::tuple(...)`, get an element by index `i` using `kj::get<i>(myTuple)`, and expand the tuple
 | ||||
| // as arguments to a function using `kj::apply(func, myTuple)`.
 | ||||
| //
 | ||||
| // Tuples are always flat -- that is, no element of a Tuple is ever itself a Tuple.  If you
 | ||||
| // construct a tuple from other tuples, the elements are flattened and concatenated.
 | ||||
| 
 | ||||
| template <typename... Params> | ||||
| inline auto tuple(Params&&... params) | ||||
|     -> decltype(_::expandAndApply(_::MakeTupleFunc(), kj::fwd<Params>(params)...)) { | ||||
|   // Construct a new tuple from the given values.  Any tuples in the argument list will be
 | ||||
|   // flattened into the result.
 | ||||
|   return _::expandAndApply(_::MakeTupleFunc(), kj::fwd<Params>(params)...); | ||||
| } | ||||
| 
 | ||||
| template <size_t index, typename Tuple> | ||||
| inline auto get(Tuple&& tuple) -> decltype(_::getImpl<index>(kj::fwd<Tuple>(tuple))) { | ||||
|   // Unpack and return the tuple element at the given index.  The index is specified as a template
 | ||||
|   // parameter, e.g. `kj::get<3>(myTuple)`.
 | ||||
|   return _::getImpl<index>(kj::fwd<Tuple>(tuple)); | ||||
| } | ||||
| 
 | ||||
| template <typename Func, typename... Params> | ||||
| inline auto apply(Func&& func, Params&&... params) | ||||
|     -> decltype(_::expandAndApply(kj::fwd<Func>(func), kj::fwd<Params>(params)...)) { | ||||
|   // Apply a function to some arguments, expanding tuples into separate arguments.
 | ||||
|   return _::expandAndApply(kj::fwd<Func>(func), kj::fwd<Params>(params)...); | ||||
| } | ||||
| 
 | ||||
| template <typename T> struct TupleSize_ { static constexpr size_t size = 1; }; | ||||
| template <typename... T> struct TupleSize_<_::Tuple<T...>> { | ||||
|   static constexpr size_t size = sizeof...(T); | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| constexpr size_t tupleSize() { return TupleSize_<T>::size; } | ||||
| // Returns size of the tuple T.
 | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_TUPLE_H_
 | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -0,0 +1,144 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_VECTOR_H_ | ||||
| #define KJ_VECTOR_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #include "array.h" | ||||
| 
 | ||||
| namespace kj { | ||||
| 
 | ||||
| template <typename T> | ||||
| class Vector { | ||||
|   // Similar to std::vector, but based on KJ framework.
 | ||||
|   //
 | ||||
|   // This implementation always uses move constructors when growing the backing array.  If the
 | ||||
|   // move constructor throws, the Vector is left in an inconsistent state.  This is acceptable
 | ||||
|   // under KJ exception theory which assumes that exceptions leave things in inconsistent states.
 | ||||
| 
 | ||||
|   // TODO(someday): Allow specifying a custom allocator.
 | ||||
| 
 | ||||
| public: | ||||
|   inline Vector() = default; | ||||
|   inline explicit Vector(size_t capacity): builder(heapArrayBuilder<T>(capacity)) {} | ||||
| 
 | ||||
|   inline operator ArrayPtr<T>() { return builder; } | ||||
|   inline operator ArrayPtr<const T>() const { return builder; } | ||||
|   inline ArrayPtr<T> asPtr() { return builder.asPtr(); } | ||||
|   inline ArrayPtr<const T> asPtr() const { return builder.asPtr(); } | ||||
| 
 | ||||
|   inline size_t size() const { return builder.size(); } | ||||
|   inline bool empty() const { return size() == 0; } | ||||
|   inline size_t capacity() const { return builder.capacity(); } | ||||
|   inline T& operator[](size_t index) const { return builder[index]; } | ||||
| 
 | ||||
|   inline const T* begin() const { return builder.begin(); } | ||||
|   inline const T* end() const { return builder.end(); } | ||||
|   inline const T& front() const { return builder.front(); } | ||||
|   inline const T& back() const { return builder.back(); } | ||||
|   inline T* begin() { return builder.begin(); } | ||||
|   inline T* end() { return builder.end(); } | ||||
|   inline T& front() { return builder.front(); } | ||||
|   inline T& back() { return builder.back(); } | ||||
| 
 | ||||
|   inline Array<T> releaseAsArray() { | ||||
|     // TODO(perf):  Avoid a copy/move by allowing Array<T> to point to incomplete space?
 | ||||
|     if (!builder.isFull()) { | ||||
|       setCapacity(size()); | ||||
|     } | ||||
|     return builder.finish(); | ||||
|   } | ||||
| 
 | ||||
|   template <typename... Params> | ||||
|   inline T& add(Params&&... params) { | ||||
|     if (builder.isFull()) grow(); | ||||
|     return builder.add(kj::fwd<Params>(params)...); | ||||
|   } | ||||
| 
 | ||||
|   template <typename Iterator> | ||||
|   inline void addAll(Iterator begin, Iterator end) { | ||||
|     size_t needed = builder.size() + (end - begin); | ||||
|     if (needed > builder.capacity()) grow(needed); | ||||
|     builder.addAll(begin, end); | ||||
|   } | ||||
| 
 | ||||
|   template <typename Container> | ||||
|   inline void addAll(Container&& container) { | ||||
|     addAll(container.begin(), container.end()); | ||||
|   } | ||||
| 
 | ||||
|   inline void removeLast() { | ||||
|     builder.removeLast(); | ||||
|   } | ||||
| 
 | ||||
|   inline void resize(size_t size) { | ||||
|     if (size > builder.capacity()) grow(size); | ||||
|     builder.resize(size); | ||||
|   } | ||||
| 
 | ||||
|   inline void operator=(decltype(nullptr)) { | ||||
|     builder = nullptr; | ||||
|   } | ||||
| 
 | ||||
|   inline void clear() { | ||||
|     while (builder.size() > 0) { | ||||
|       builder.removeLast(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   inline void truncate(size_t size) { | ||||
|     builder.truncate(size); | ||||
|   } | ||||
| 
 | ||||
|   inline void reserve(size_t size) { | ||||
|     if (size > builder.capacity()) { | ||||
|       setCapacity(size); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   ArrayBuilder<T> builder; | ||||
| 
 | ||||
|   void grow(size_t minCapacity = 0) { | ||||
|     setCapacity(kj::max(minCapacity, capacity() == 0 ? 4 : capacity() * 2)); | ||||
|   } | ||||
|   void setCapacity(size_t newSize) { | ||||
|     if (builder.size() > newSize) { | ||||
|       builder.truncate(newSize); | ||||
|     } | ||||
|     ArrayBuilder<T> newBuilder = heapArrayBuilder<T>(newSize); | ||||
|     newBuilder.addAll(kj::mv(builder)); | ||||
|     builder = kj::mv(newBuilder); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| inline auto KJ_STRINGIFY(const Vector<T>& v) -> decltype(toCharSequence(v.asPtr())) { | ||||
|   return toCharSequence(v.asPtr()); | ||||
| } | ||||
| 
 | ||||
| }  // namespace kj
 | ||||
| 
 | ||||
| #endif  // KJ_VECTOR_H_
 | ||||
| @ -0,0 +1,41 @@ | ||||
| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | ||||
| // Licensed under the MIT License:
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| // of this software and associated documentation files (the "Software"), to deal
 | ||||
| // in the Software without restriction, including without limitation the rights
 | ||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| // copies of the Software, and to permit persons to whom the Software is
 | ||||
| // furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice shall be included in
 | ||||
| // all copies or substantial portions of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #ifndef KJ_WINDOWS_SANITY_H_ | ||||
| #define KJ_WINDOWS_SANITY_H_ | ||||
| 
 | ||||
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
| 
 | ||||
| #ifndef _INC_WINDOWS | ||||
| #error "windows.h needs to be included before kj/windows-sanity.h (or perhaps you don't need either?)" | ||||
| #endif | ||||
| 
 | ||||
| namespace win32 { | ||||
|   const auto ERROR_ = ERROR; | ||||
| #undef ERROR | ||||
|   const auto ERROR = ERROR_; | ||||
| } | ||||
| 
 | ||||
| using win32::ERROR; | ||||
| 
 | ||||
| #endif  // KJ_WINDOWS_SANITY_H_
 | ||||
| @ -0,0 +1,41 @@ | ||||
| # libcapnp-json.la - a libtool library file | ||||
| # Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-2 | ||||
| # | ||||
| # Please DO NOT delete this file! | ||||
| # It is necessary for linking the library. | ||||
| 
 | ||||
| # The name that we can dlopen(3). | ||||
| dlname='libcapnp-json-0.6.1.so' | ||||
| 
 | ||||
| # Names of this library. | ||||
| library_names='libcapnp-json-0.6.1.so libcapnp-json-0.6.1.so libcapnp-json.so' | ||||
| 
 | ||||
| # The name of the static archive. | ||||
| old_library='libcapnp-json.a' | ||||
| 
 | ||||
| # Linker flags that cannot go in dependency_libs. | ||||
| inherited_linker_flags=' -pthread' | ||||
| 
 | ||||
| # Libraries that this one depends upon. | ||||
| dependency_libs=' /home/batman/openpilot/external/capnp/lib/libcapnp.la /home/batman/openpilot/external/capnp/lib/libkj.la -lpthread' | ||||
| 
 | ||||
| # Names of additional weak libraries provided by this library | ||||
| weak_library_names='' | ||||
| 
 | ||||
| # Version information for libcapnp-json. | ||||
| current=0 | ||||
| age=0 | ||||
| revision=0 | ||||
| 
 | ||||
| # Is this an already installed library? | ||||
| installed=yes | ||||
| 
 | ||||
| # Should we warn about portability when linking against -modules? | ||||
| shouldnotlink=no | ||||
| 
 | ||||
| # Files to dlopen/dlpreopen | ||||
| dlopen='' | ||||
| dlpreopen='' | ||||
| 
 | ||||
| # Directory that this library needs to be installed in: | ||||
| libdir='/home/batman/openpilot/external/capnp/lib' | ||||
| @ -0,0 +1,41 @@ | ||||
| # libcapnp-rpc.la - a libtool library file | ||||
| # Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-2 | ||||
| # | ||||
| # Please DO NOT delete this file! | ||||
| # It is necessary for linking the library. | ||||
| 
 | ||||
| # The name that we can dlopen(3). | ||||
| dlname='libcapnp-rpc-0.6.1.so' | ||||
| 
 | ||||
| # Names of this library. | ||||
| library_names='libcapnp-rpc-0.6.1.so libcapnp-rpc-0.6.1.so libcapnp-rpc.so' | ||||
| 
 | ||||
| # The name of the static archive. | ||||
| old_library='libcapnp-rpc.a' | ||||
| 
 | ||||
| # Linker flags that cannot go in dependency_libs. | ||||
| inherited_linker_flags=' -pthread' | ||||
| 
 | ||||
| # Libraries that this one depends upon. | ||||
| dependency_libs=' /home/batman/openpilot/external/capnp/lib/libcapnp.la /home/batman/openpilot/external/capnp/lib/libkj-async.la /home/batman/openpilot/external/capnp/lib/libkj.la -lpthread' | ||||
| 
 | ||||
| # Names of additional weak libraries provided by this library | ||||
| weak_library_names='' | ||||
| 
 | ||||
| # Version information for libcapnp-rpc. | ||||
| current=0 | ||||
| age=0 | ||||
| revision=0 | ||||
| 
 | ||||
| # Is this an already installed library? | ||||
| installed=yes | ||||
| 
 | ||||
| # Should we warn about portability when linking against -modules? | ||||
| shouldnotlink=no | ||||
| 
 | ||||
| # Files to dlopen/dlpreopen | ||||
| dlopen='' | ||||
| dlpreopen='' | ||||
| 
 | ||||
| # Directory that this library needs to be installed in: | ||||
| libdir='/home/batman/openpilot/external/capnp/lib' | ||||
| @ -0,0 +1,41 @@ | ||||
| # libcapnp.la - a libtool library file | ||||
| # Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-2 | ||||
| # | ||||
| # Please DO NOT delete this file! | ||||
| # It is necessary for linking the library. | ||||
| 
 | ||||
| # The name that we can dlopen(3). | ||||
| dlname='libcapnp-0.6.1.so' | ||||
| 
 | ||||
| # Names of this library. | ||||
| library_names='libcapnp-0.6.1.so libcapnp-0.6.1.so libcapnp.so' | ||||
| 
 | ||||
| # The name of the static archive. | ||||
| old_library='libcapnp.a' | ||||
| 
 | ||||
| # Linker flags that cannot go in dependency_libs. | ||||
| inherited_linker_flags=' -pthread' | ||||
| 
 | ||||
| # Libraries that this one depends upon. | ||||
| dependency_libs=' /home/batman/openpilot/external/capnp/lib/libkj.la -lpthread' | ||||
| 
 | ||||
| # Names of additional weak libraries provided by this library | ||||
| weak_library_names='' | ||||
| 
 | ||||
| # Version information for libcapnp. | ||||
| current=0 | ||||
| age=0 | ||||
| revision=0 | ||||
| 
 | ||||
| # Is this an already installed library? | ||||
| installed=yes | ||||
| 
 | ||||
| # Should we warn about portability when linking against -modules? | ||||
| shouldnotlink=no | ||||
| 
 | ||||
| # Files to dlopen/dlpreopen | ||||
| dlopen='' | ||||
| dlpreopen='' | ||||
| 
 | ||||
| # Directory that this library needs to be installed in: | ||||
| libdir='/home/batman/openpilot/external/capnp/lib' | ||||
| @ -0,0 +1,41 @@ | ||||
| # libcapnp_c.la - a libtool library file | ||||
| # Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-0.1 | ||||
| # | ||||
| # Please DO NOT delete this file! | ||||
| # It is necessary for linking the library. | ||||
| 
 | ||||
| # The name that we can dlopen(3). | ||||
| dlname='libcapnp_c.so.0' | ||||
| 
 | ||||
| # Names of this library. | ||||
| library_names='libcapnp_c.so.0.0.0 libcapnp_c.so.0 libcapnp_c.so' | ||||
| 
 | ||||
| # The name of the static archive. | ||||
| old_library='libcapnp_c.a' | ||||
| 
 | ||||
| # Linker flags that cannot go in dependency_libs. | ||||
| inherited_linker_flags='' | ||||
| 
 | ||||
| # Libraries that this one depends upon. | ||||
| dependency_libs='' | ||||
| 
 | ||||
| # Names of additional weak libraries provided by this library | ||||
| weak_library_names='' | ||||
| 
 | ||||
| # Version information for libcapnp_c. | ||||
| current=0 | ||||
| age=0 | ||||
| revision=0 | ||||
| 
 | ||||
| # Is this an already installed library? | ||||
| installed=yes | ||||
| 
 | ||||
| # Should we warn about portability when linking against -modules? | ||||
| shouldnotlink=no | ||||
| 
 | ||||
| # Files to dlopen/dlpreopen | ||||
| dlopen='' | ||||
| dlpreopen='' | ||||
| 
 | ||||
| # Directory that this library needs to be installed in: | ||||
| libdir='/home/batman/openpilot/external/capnp/lib' | ||||
| @ -0,0 +1 @@ | ||||
| libcapnp_c.so.0.0.0 | ||||
									
										Binary file not shown.
									
								
							
						| @ -0,0 +1,41 @@ | ||||
| # libcapnpc.la - a libtool library file | ||||
| # Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-2 | ||||
| # | ||||
| # Please DO NOT delete this file! | ||||
| # It is necessary for linking the library. | ||||
| 
 | ||||
| # The name that we can dlopen(3). | ||||
| dlname='libcapnpc-0.6.1.so' | ||||
| 
 | ||||
| # Names of this library. | ||||
| library_names='libcapnpc-0.6.1.so libcapnpc-0.6.1.so libcapnpc.so' | ||||
| 
 | ||||
| # The name of the static archive. | ||||
| old_library='libcapnpc.a' | ||||
| 
 | ||||
| # Linker flags that cannot go in dependency_libs. | ||||
| inherited_linker_flags=' -pthread' | ||||
| 
 | ||||
| # Libraries that this one depends upon. | ||||
| dependency_libs=' /home/batman/openpilot/external/capnp/lib/libcapnp.la /home/batman/openpilot/external/capnp/lib/libkj.la -lpthread' | ||||
| 
 | ||||
| # Names of additional weak libraries provided by this library | ||||
| weak_library_names='' | ||||
| 
 | ||||
| # Version information for libcapnpc. | ||||
| current=0 | ||||
| age=0 | ||||
| revision=0 | ||||
| 
 | ||||
| # Is this an already installed library? | ||||
| installed=yes | ||||
| 
 | ||||
| # Should we warn about portability when linking against -modules? | ||||
| shouldnotlink=no | ||||
| 
 | ||||
| # Files to dlopen/dlpreopen | ||||
| dlopen='' | ||||
| dlpreopen='' | ||||
| 
 | ||||
| # Directory that this library needs to be installed in: | ||||
| libdir='/home/batman/openpilot/external/capnp/lib' | ||||
| @ -0,0 +1,41 @@ | ||||
| # libkj-async.la - a libtool library file | ||||
| # Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-2 | ||||
| # | ||||
| # Please DO NOT delete this file! | ||||
| # It is necessary for linking the library. | ||||
| 
 | ||||
| # The name that we can dlopen(3). | ||||
| dlname='libkj-async-0.6.1.so' | ||||
| 
 | ||||
| # Names of this library. | ||||
| library_names='libkj-async-0.6.1.so libkj-async-0.6.1.so libkj-async.so' | ||||
| 
 | ||||
| # The name of the static archive. | ||||
| old_library='libkj-async.a' | ||||
| 
 | ||||
| # Linker flags that cannot go in dependency_libs. | ||||
| inherited_linker_flags=' -pthread' | ||||
| 
 | ||||
| # Libraries that this one depends upon. | ||||
| dependency_libs=' /home/batman/openpilot/external/capnp/lib/libkj.la -lpthread' | ||||
| 
 | ||||
| # Names of additional weak libraries provided by this library | ||||
| weak_library_names='' | ||||
| 
 | ||||
| # Version information for libkj-async. | ||||
| current=0 | ||||
| age=0 | ||||
| revision=0 | ||||
| 
 | ||||
| # Is this an already installed library? | ||||
| installed=yes | ||||
| 
 | ||||
| # Should we warn about portability when linking against -modules? | ||||
| shouldnotlink=no | ||||
| 
 | ||||
| # Files to dlopen/dlpreopen | ||||
| dlopen='' | ||||
| dlpreopen='' | ||||
| 
 | ||||
| # Directory that this library needs to be installed in: | ||||
| libdir='/home/batman/openpilot/external/capnp/lib' | ||||
| @ -0,0 +1,41 @@ | ||||
| # libkj-http.la - a libtool library file | ||||
| # Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-2 | ||||
| # | ||||
| # Please DO NOT delete this file! | ||||
| # It is necessary for linking the library. | ||||
| 
 | ||||
| # The name that we can dlopen(3). | ||||
| dlname='libkj-http-0.6.1.so' | ||||
| 
 | ||||
| # Names of this library. | ||||
| library_names='libkj-http-0.6.1.so libkj-http-0.6.1.so libkj-http.so' | ||||
| 
 | ||||
| # The name of the static archive. | ||||
| old_library='libkj-http.a' | ||||
| 
 | ||||
| # Linker flags that cannot go in dependency_libs. | ||||
| inherited_linker_flags=' -pthread' | ||||
| 
 | ||||
| # Libraries that this one depends upon. | ||||
| dependency_libs=' /home/batman/openpilot/external/capnp/lib/libkj-async.la /home/batman/openpilot/external/capnp/lib/libkj.la -lpthread' | ||||
| 
 | ||||
| # Names of additional weak libraries provided by this library | ||||
| weak_library_names='' | ||||
| 
 | ||||
| # Version information for libkj-http. | ||||
| current=0 | ||||
| age=0 | ||||
| revision=0 | ||||
| 
 | ||||
| # Is this an already installed library? | ||||
| installed=yes | ||||
| 
 | ||||
| # Should we warn about portability when linking against -modules? | ||||
| shouldnotlink=no | ||||
| 
 | ||||
| # Files to dlopen/dlpreopen | ||||
| dlopen='' | ||||
| dlpreopen='' | ||||
| 
 | ||||
| # Directory that this library needs to be installed in: | ||||
| libdir='/home/batman/openpilot/external/capnp/lib' | ||||
| @ -0,0 +1,41 @@ | ||||
| # libkj-test.la - a libtool library file | ||||
| # Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-2 | ||||
| # | ||||
| # Please DO NOT delete this file! | ||||
| # It is necessary for linking the library. | ||||
| 
 | ||||
| # The name that we can dlopen(3). | ||||
| dlname='libkj-test-0.6.1.so' | ||||
| 
 | ||||
| # Names of this library. | ||||
| library_names='libkj-test-0.6.1.so libkj-test-0.6.1.so libkj-test.so' | ||||
| 
 | ||||
| # The name of the static archive. | ||||
| old_library='libkj-test.a' | ||||
| 
 | ||||
| # Linker flags that cannot go in dependency_libs. | ||||
| inherited_linker_flags=' -pthread' | ||||
| 
 | ||||
| # Libraries that this one depends upon. | ||||
| dependency_libs=' /home/batman/openpilot/external/capnp/lib/libkj.la -lpthread' | ||||
| 
 | ||||
| # Names of additional weak libraries provided by this library | ||||
| weak_library_names='' | ||||
| 
 | ||||
| # Version information for libkj-test. | ||||
| current=0 | ||||
| age=0 | ||||
| revision=0 | ||||
| 
 | ||||
| # Is this an already installed library? | ||||
| installed=yes | ||||
| 
 | ||||
| # Should we warn about portability when linking against -modules? | ||||
| shouldnotlink=no | ||||
| 
 | ||||
| # Files to dlopen/dlpreopen | ||||
| dlopen='' | ||||
| dlpreopen='' | ||||
| 
 | ||||
| # Directory that this library needs to be installed in: | ||||
| libdir='/home/batman/openpilot/external/capnp/lib' | ||||
| @ -0,0 +1,41 @@ | ||||
| # libkj.la - a libtool library file | ||||
| # Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-2 | ||||
| # | ||||
| # Please DO NOT delete this file! | ||||
| # It is necessary for linking the library. | ||||
| 
 | ||||
| # The name that we can dlopen(3). | ||||
| dlname='libkj-0.6.1.so' | ||||
| 
 | ||||
| # Names of this library. | ||||
| library_names='libkj-0.6.1.so libkj-0.6.1.so libkj.so' | ||||
| 
 | ||||
| # The name of the static archive. | ||||
| old_library='libkj.a' | ||||
| 
 | ||||
| # Linker flags that cannot go in dependency_libs. | ||||
| inherited_linker_flags=' -pthread' | ||||
| 
 | ||||
| # Libraries that this one depends upon. | ||||
| dependency_libs=' -lpthread' | ||||
| 
 | ||||
| # Names of additional weak libraries provided by this library | ||||
| weak_library_names='' | ||||
| 
 | ||||
| # Version information for libkj. | ||||
| current=0 | ||||
| age=0 | ||||
| revision=0 | ||||
| 
 | ||||
| # Is this an already installed library? | ||||
| installed=yes | ||||
| 
 | ||||
| # Should we warn about portability when linking against -modules? | ||||
| shouldnotlink=no | ||||
| 
 | ||||
| # Files to dlopen/dlpreopen | ||||
| dlopen='' | ||||
| dlpreopen='' | ||||
| 
 | ||||
| # Directory that this library needs to be installed in: | ||||
| libdir='/home/batman/openpilot/external/capnp/lib' | ||||
| @ -0,0 +1,12 @@ | ||||
| prefix=/home/batman/openpilot/external/capnp | ||||
| exec_prefix=${prefix} | ||||
| libdir=${exec_prefix}/lib | ||||
| bindir=${exec_prefix}/bin | ||||
| includedir=${prefix}/include | ||||
| codegen=${bindir}/capnpc-c | ||||
| 
 | ||||
| Name: c-capnproto | ||||
| Description: Cap'n Proto C bindings | ||||
| Version: 0.2 | ||||
| Libs: -L${libdir} -lcapnp_c | ||||
| Cflags: -I${includedir} | ||||
| @ -0,0 +1,11 @@ | ||||
| prefix=/home/batman/openpilot/external/capnp | ||||
| exec_prefix=${prefix} | ||||
| libdir=${exec_prefix}/lib | ||||
| includedir=${prefix}/include | ||||
| 
 | ||||
| Name: Cap'n Proto RPC | ||||
| Description: Fast object-oriented RPC system | ||||
| Version: 0.6.1 | ||||
| Libs: -L${libdir} -lcapnp-rpc | ||||
| Requires: capnp = 0.6.1 kj-async = 0.6.1 | ||||
| Cflags: -I${includedir} | ||||
| @ -0,0 +1,12 @@ | ||||
| prefix=/home/batman/openpilot/external/capnp | ||||
| exec_prefix=${prefix} | ||||
| libdir=${exec_prefix}/lib | ||||
| includedir=${prefix}/include | ||||
| 
 | ||||
| Name: Cap'n Proto | ||||
| Description: Insanely fast serialization system | ||||
| Version: 0.6.1 | ||||
| Libs: -L${libdir} -lcapnp -pthread  -lpthread  | ||||
| Libs.private:  -lpthread  | ||||
| Requires: kj = 0.6.1 | ||||
| Cflags: -I${includedir} -pthread   | ||||
| @ -0,0 +1,11 @@ | ||||
| prefix=/home/batman/openpilot/external/capnp | ||||
| exec_prefix=${prefix} | ||||
| libdir=${exec_prefix}/lib | ||||
| includedir=${prefix}/include | ||||
| 
 | ||||
| Name: KJ Async Framework Library | ||||
| Description: Basic utility library called KJ (async part) | ||||
| Version: 0.6.1 | ||||
| Libs: -L${libdir} -lkj-async -pthread  -lpthread  | ||||
| Requires: kj = 0.6.1 | ||||
| Cflags: -I${includedir} -pthread   | ||||
| @ -0,0 +1,10 @@ | ||||
| prefix=/home/batman/openpilot/external/capnp | ||||
| exec_prefix=${prefix} | ||||
| libdir=${exec_prefix}/lib | ||||
| includedir=${prefix}/include | ||||
| 
 | ||||
| Name: KJ Framework Library | ||||
| Description: Basic utility library called KJ | ||||
| Version: 0.6.1 | ||||
| Libs: -L${libdir} -lkj -pthread  -lpthread  | ||||
| Cflags: -I${includedir} -pthread   | ||||
					Loading…
					
					
				
		Reference in new issue