From caee18aeef0a9a54ad8f98292a325a1675a43bec Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Mon, 21 Sep 2026 20:05:46 -0700 Subject: [PATCH] Vendor minimal capnproto --- .github/workflows/wheels.yml | 1 - .gitignore | 6 +- MANIFEST.in | 3 +- README.md | 21 +- _custom_build/backend.py | 29 - buildutils/__init__.py | 0 buildutils/build.py | 70 - buildutils/bundle.py | 76 - capnp/includes/capnp_cpp.pxd | 6 +- capnp/includes/schema_cpp.pxd | 2 +- capnp/lib/capnp.pyx | 2 - pyproject.toml | 9 +- setup.cfg | 3 - setup.py | 110 +- test/foo.capnp | 4 - test/test_vendor.py | 30 + vendor/capnproto/CMakeLists.txt | 47 + vendor/capnproto/LICENSE.txt | 23 + vendor/capnproto/README.md | 44 + vendor/capnproto/src/capnp/any.h | 862 +++ vendor/capnproto/src/capnp/arena.c++ | 286 + vendor/capnproto/src/capnp/arena.h | 391 + vendor/capnproto/src/capnp/blob.c++ | 28 + vendor/capnproto/src/capnp/blob.h | 221 + vendor/capnproto/src/capnp/common.h | 684 ++ .../capnproto/src/capnp/compat/std-iterator.h | 47 + .../capnproto/src/capnp/compiler/compiler.c++ | 1126 +++ .../capnproto/src/capnp/compiler/compiler.h | 188 + .../src/capnp/compiler/error-reporter.h | 61 + .../capnproto/src/capnp/compiler/generics.c++ | 627 ++ .../capnproto/src/capnp/compiler/generics.h | 273 + .../src/capnp/compiler/grammar.capnp.c++ | 2978 ++++++++ .../src/capnp/compiler/grammar.capnp.h | 6202 ++++++++++++++++ vendor/capnproto/src/capnp/compiler/lexer.c++ | 259 + .../src/capnp/compiler/lexer.capnp.h | 1022 +++ vendor/capnproto/src/capnp/compiler/lexer.h | 91 + .../src/capnp/compiler/node-translator.c++ | 2086 ++++++ .../src/capnp/compiler/node-translator.h | 205 + .../capnproto/src/capnp/compiler/parser.c++ | 1160 +++ vendor/capnproto/src/capnp/compiler/parser.h | 146 + .../capnproto/src/capnp/compiler/resolver.h | 132 + .../capnproto/src/capnp/compiler/type-id.c++ | 414 ++ vendor/capnproto/src/capnp/compiler/type-id.h | 45 + vendor/capnproto/src/capnp/dynamic.c++ | 1830 +++++ vendor/capnproto/src/capnp/dynamic.h | 1202 +++ vendor/capnproto/src/capnp/endian.h | 284 + .../src/capnp/generated-header-support.h | 337 + vendor/capnproto/src/capnp/layout.c++ | 3073 ++++++++ vendor/capnproto/src/capnp/layout.h | 1105 +++ vendor/capnproto/src/capnp/list.h | 548 ++ vendor/capnproto/src/capnp/message.c++ | 211 + vendor/capnproto/src/capnp/message.h | 464 ++ vendor/capnproto/src/capnp/orphan.h | 308 + vendor/capnproto/src/capnp/pointer-helpers.h | 151 + vendor/capnproto/src/capnp/pretty-print.h | 44 + vendor/capnproto/src/capnp/raw-schema.h | 223 + vendor/capnproto/src/capnp/schema-loader.c++ | 2099 ++++++ vendor/capnproto/src/capnp/schema-loader.h | 183 + vendor/capnproto/src/capnp/schema-parser.c++ | 406 ++ vendor/capnproto/src/capnp/schema-parser.h | 153 + vendor/capnproto/src/capnp/schema.c++ | 796 ++ vendor/capnproto/src/capnp/schema.capnp | 468 ++ vendor/capnproto/src/capnp/schema.capnp.c++ | 3357 +++++++++ vendor/capnproto/src/capnp/schema.capnp.h | 6430 +++++++++++++++++ vendor/capnproto/src/capnp/schema.h | 877 +++ vendor/capnproto/src/capnp/serialize.c++ | 135 + vendor/capnproto/src/capnp/serialize.h | 95 + vendor/capnproto/src/capnp/stringify.c++ | 267 + vendor/capnproto/src/kj/arena.c++ | 167 + vendor/capnproto/src/kj/arena.h | 210 + vendor/capnproto/src/kj/array.c++ | 109 + vendor/capnproto/src/kj/array.h | 913 +++ vendor/capnproto/src/kj/common.c++ | 49 + vendor/capnproto/src/kj/common.h | 1929 +++++ vendor/capnproto/src/kj/debug.c++ | 397 + vendor/capnproto/src/kj/debug.h | 542 ++ vendor/capnproto/src/kj/encoding.c++ | 72 + vendor/capnproto/src/kj/encoding.h | 69 + vendor/capnproto/src/kj/exception.c++ | 822 +++ vendor/capnproto/src/kj/exception.h | 429 ++ .../capnproto/src/kj/filesystem-disk-unix.c++ | 1801 +++++ vendor/capnproto/src/kj/filesystem.c++ | 1496 ++++ vendor/capnproto/src/kj/filesystem.h | 1028 +++ vendor/capnproto/src/kj/function.h | 293 + vendor/capnproto/src/kj/hash.c++ | 65 + vendor/capnproto/src/kj/hash.h | 196 + vendor/capnproto/src/kj/io.c++ | 171 + vendor/capnproto/src/kj/io.h | 129 + vendor/capnproto/src/kj/map.h | 578 ++ vendor/capnproto/src/kj/memory.h | 776 ++ vendor/capnproto/src/kj/miniposix.h | 79 + vendor/capnproto/src/kj/mutex.c++ | 854 +++ vendor/capnproto/src/kj/mutex.h | 739 ++ vendor/capnproto/src/kj/one-of.h | 656 ++ vendor/capnproto/src/kj/parse/char.c++ | 71 + vendor/capnproto/src/kj/parse/char.h | 358 + vendor/capnproto/src/kj/parse/common.h | 799 ++ vendor/capnproto/src/kj/refcount.c++ | 72 + vendor/capnproto/src/kj/refcount.h | 253 + vendor/capnproto/src/kj/source-location.c++ | 28 + vendor/capnproto/src/kj/source-location.h | 111 + vendor/capnproto/src/kj/string-tree.c++ | 73 + vendor/capnproto/src/kj/string-tree.h | 219 + vendor/capnproto/src/kj/string.c++ | 593 ++ vendor/capnproto/src/kj/string.h | 935 +++ vendor/capnproto/src/kj/table.c++ | 945 +++ vendor/capnproto/src/kj/table.h | 1640 +++++ vendor/capnproto/src/kj/threadlocal.h | 66 + vendor/capnproto/src/kj/time.c++ | 127 + vendor/capnproto/src/kj/time.h | 100 + vendor/capnproto/src/kj/tuple.h | 443 ++ vendor/capnproto/src/kj/units.c++ | 31 + vendor/capnproto/src/kj/units.h | 1170 +++ vendor/capnproto/src/kj/vector.h | 153 + 114 files changed, 67532 insertions(+), 290 deletions(-) delete mode 100644 _custom_build/backend.py delete mode 100644 buildutils/__init__.py delete mode 100644 buildutils/build.py delete mode 100644 buildutils/bundle.py delete mode 100644 setup.cfg create mode 100644 test/test_vendor.py create mode 100644 vendor/capnproto/CMakeLists.txt create mode 100644 vendor/capnproto/LICENSE.txt create mode 100644 vendor/capnproto/README.md create mode 100644 vendor/capnproto/src/capnp/any.h create mode 100644 vendor/capnproto/src/capnp/arena.c++ create mode 100644 vendor/capnproto/src/capnp/arena.h create mode 100644 vendor/capnproto/src/capnp/blob.c++ create mode 100644 vendor/capnproto/src/capnp/blob.h create mode 100644 vendor/capnproto/src/capnp/common.h create mode 100644 vendor/capnproto/src/capnp/compat/std-iterator.h create mode 100644 vendor/capnproto/src/capnp/compiler/compiler.c++ create mode 100644 vendor/capnproto/src/capnp/compiler/compiler.h create mode 100644 vendor/capnproto/src/capnp/compiler/error-reporter.h create mode 100644 vendor/capnproto/src/capnp/compiler/generics.c++ create mode 100644 vendor/capnproto/src/capnp/compiler/generics.h create mode 100644 vendor/capnproto/src/capnp/compiler/grammar.capnp.c++ create mode 100644 vendor/capnproto/src/capnp/compiler/grammar.capnp.h create mode 100644 vendor/capnproto/src/capnp/compiler/lexer.c++ create mode 100644 vendor/capnproto/src/capnp/compiler/lexer.capnp.h create mode 100644 vendor/capnproto/src/capnp/compiler/lexer.h create mode 100644 vendor/capnproto/src/capnp/compiler/node-translator.c++ create mode 100644 vendor/capnproto/src/capnp/compiler/node-translator.h create mode 100644 vendor/capnproto/src/capnp/compiler/parser.c++ create mode 100644 vendor/capnproto/src/capnp/compiler/parser.h create mode 100644 vendor/capnproto/src/capnp/compiler/resolver.h create mode 100644 vendor/capnproto/src/capnp/compiler/type-id.c++ create mode 100644 vendor/capnproto/src/capnp/compiler/type-id.h create mode 100644 vendor/capnproto/src/capnp/dynamic.c++ create mode 100644 vendor/capnproto/src/capnp/dynamic.h create mode 100644 vendor/capnproto/src/capnp/endian.h create mode 100644 vendor/capnproto/src/capnp/generated-header-support.h create mode 100644 vendor/capnproto/src/capnp/layout.c++ create mode 100644 vendor/capnproto/src/capnp/layout.h create mode 100644 vendor/capnproto/src/capnp/list.h create mode 100644 vendor/capnproto/src/capnp/message.c++ create mode 100644 vendor/capnproto/src/capnp/message.h create mode 100644 vendor/capnproto/src/capnp/orphan.h create mode 100644 vendor/capnproto/src/capnp/pointer-helpers.h create mode 100644 vendor/capnproto/src/capnp/pretty-print.h create mode 100644 vendor/capnproto/src/capnp/raw-schema.h create mode 100644 vendor/capnproto/src/capnp/schema-loader.c++ create mode 100644 vendor/capnproto/src/capnp/schema-loader.h create mode 100644 vendor/capnproto/src/capnp/schema-parser.c++ create mode 100644 vendor/capnproto/src/capnp/schema-parser.h create mode 100644 vendor/capnproto/src/capnp/schema.c++ create mode 100644 vendor/capnproto/src/capnp/schema.capnp create mode 100644 vendor/capnproto/src/capnp/schema.capnp.c++ create mode 100644 vendor/capnproto/src/capnp/schema.capnp.h create mode 100644 vendor/capnproto/src/capnp/schema.h create mode 100644 vendor/capnproto/src/capnp/serialize.c++ create mode 100644 vendor/capnproto/src/capnp/serialize.h create mode 100644 vendor/capnproto/src/capnp/stringify.c++ create mode 100644 vendor/capnproto/src/kj/arena.c++ create mode 100644 vendor/capnproto/src/kj/arena.h create mode 100644 vendor/capnproto/src/kj/array.c++ create mode 100644 vendor/capnproto/src/kj/array.h create mode 100644 vendor/capnproto/src/kj/common.c++ create mode 100644 vendor/capnproto/src/kj/common.h create mode 100644 vendor/capnproto/src/kj/debug.c++ create mode 100644 vendor/capnproto/src/kj/debug.h create mode 100644 vendor/capnproto/src/kj/encoding.c++ create mode 100644 vendor/capnproto/src/kj/encoding.h create mode 100644 vendor/capnproto/src/kj/exception.c++ create mode 100644 vendor/capnproto/src/kj/exception.h create mode 100644 vendor/capnproto/src/kj/filesystem-disk-unix.c++ create mode 100644 vendor/capnproto/src/kj/filesystem.c++ create mode 100644 vendor/capnproto/src/kj/filesystem.h create mode 100644 vendor/capnproto/src/kj/function.h create mode 100644 vendor/capnproto/src/kj/hash.c++ create mode 100644 vendor/capnproto/src/kj/hash.h create mode 100644 vendor/capnproto/src/kj/io.c++ create mode 100644 vendor/capnproto/src/kj/io.h create mode 100644 vendor/capnproto/src/kj/map.h create mode 100644 vendor/capnproto/src/kj/memory.h create mode 100644 vendor/capnproto/src/kj/miniposix.h create mode 100644 vendor/capnproto/src/kj/mutex.c++ create mode 100644 vendor/capnproto/src/kj/mutex.h create mode 100644 vendor/capnproto/src/kj/one-of.h create mode 100644 vendor/capnproto/src/kj/parse/char.c++ create mode 100644 vendor/capnproto/src/kj/parse/char.h create mode 100644 vendor/capnproto/src/kj/parse/common.h create mode 100644 vendor/capnproto/src/kj/refcount.c++ create mode 100644 vendor/capnproto/src/kj/refcount.h create mode 100644 vendor/capnproto/src/kj/source-location.c++ create mode 100644 vendor/capnproto/src/kj/source-location.h create mode 100644 vendor/capnproto/src/kj/string-tree.c++ create mode 100644 vendor/capnproto/src/kj/string-tree.h create mode 100644 vendor/capnproto/src/kj/string.c++ create mode 100644 vendor/capnproto/src/kj/string.h create mode 100644 vendor/capnproto/src/kj/table.c++ create mode 100644 vendor/capnproto/src/kj/table.h create mode 100644 vendor/capnproto/src/kj/threadlocal.h create mode 100644 vendor/capnproto/src/kj/time.c++ create mode 100644 vendor/capnproto/src/kj/time.h create mode 100644 vendor/capnproto/src/kj/tuple.h create mode 100644 vendor/capnproto/src/kj/units.c++ create mode 100644 vendor/capnproto/src/kj/units.h create mode 100644 vendor/capnproto/src/kj/vector.h diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 741629f..b8130cf 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -23,7 +23,6 @@ jobs: CIBW_ARCHS: ${{ matrix.arch }} CIBW_TEST_REQUIRES: pytest CIBW_TEST_COMMAND: python -m pytest {project}/test - CIBW_CONFIG_SETTINGS: force-bundled-libcapnp=true CMAKE_OSX_ARCHITECTURES: "${{ runner.os == 'macOS' && matrix.arch || '' }}" - uses: actions/upload-artifact@v6 with: diff --git a/.gitignore b/.gitignore index 2a6d478..d0bf410 100644 --- a/.gitignore +++ b/.gitignore @@ -8,8 +8,6 @@ *.egg-info dist build -build32 -build64 eggs parts bin @@ -47,7 +45,6 @@ docs/_build capnp/lib/capnp.cpp capnp/lib/capnp.h capnp/lib/capnp_api.h -bundled/ example *.iml @@ -57,3 +54,6 @@ example .venv/ .pytest_cache/ .ruff_cache/ + +# Source for the trimmed bootstrap schema. +!vendor/capnproto/src/**/*.capnp diff --git a/MANIFEST.in b/MANIFEST.in index dabd5c2..ab27005 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,5 @@ include README.md LICENSE.md -include buildutils/*.py -include _custom_build/*.py +recursive-include vendor/capnproto *.h *.c++ *.txt *.md *.capnp recursive-include capnp *.py *.pyx *.pxd *.h *.cpp recursive-include test *.py *.capnp *.binary *.txt exclude capnp/lib/capnp.cpp capnp/lib/capnp.h capnp/lib/capnp_api.h diff --git a/README.md b/README.md index 83fd21c..e7108e5 100644 --- a/README.md +++ b/README.md @@ -34,22 +34,23 @@ not be installed alongside another distribution providing `capnp`. ## Build and test -Targets: CPython 3.12, Linux x86_64/aarch64, and macOS arm64. A C++14 compiler and -CMake are required for a bundled build. +Targets: CPython 3.12, Linux x86_64/aarch64, and macOS arm64. A C++17 compiler and +CMake are required to build the vendored library. ```sh uv venv --python 3.12 -uv pip install cython setuptools wheel pkgconfig pytest build -.venv/bin/python setup.py build_ext --inplace --force-bundled-libcapnp +uv pip install cython setuptools wheel pytest build +.venv/bin/python setup.py build_ext --inplace .venv/bin/python -m pytest -.venv/bin/python -m build -Cforce-bundled-libcapnp=true +.venv/bin/python -m build ``` -The existing build fallback downloads Cap'n Proto 1.4.0. The extension links only -`capnpc`, `capnp`, and `kj`; it does not link `capnp-rpc` or `kj-async`. `capnpc` is -needed for runtime schema parsing. Owning/vendoring the C++ source itself is a -separate step. To use a system installation, pass `--force-system-libcapnp` to -`build_ext` (or `-Cforce-system-libcapnp=true` to the wheel build). +The C++ library is vendored under [`vendor/capnproto`](vendor/capnproto), based on +Cap'n Proto 1.4.0. Every build compiles and statically links this copy; it does not +search for a system Cap'n Proto installation or download sources. The source +archive includes the vendored files, and wheels contain the compiled library. +Runtime schema parsing remains included, so cereal schemas need no generated +Python bindings. See the vendor README for provenance and the removed features. The retained upstream tests cover message construction, schema loading, reflection, binary fixtures, serialization, and exceptions. Added lifetime tests diff --git a/_custom_build/backend.py b/_custom_build/backend.py deleted file mode 100644 index 8830354..0000000 --- a/_custom_build/backend.py +++ /dev/null @@ -1,29 +0,0 @@ -import sys - -from setuptools.build_meta import * # noqa: F401, F403 -from setuptools.build_meta import build_wheel - -backend_class = build_wheel.__self__.__class__ - - -class _CustomBuildMetaBackend(backend_class): - def run_setup(self, setup_script="setup.py"): - if self.config_settings: - flags = [] - if self.config_settings.get("force-bundled-libcapnp"): - flags.append("--force-bundled-libcapnp") - if self.config_settings.get("force-system-libcapnp"): - flags.append("--force-system-libcapnp") - if self.config_settings.get("libcapnp-url"): - flags.append("--libcapnp-url") - flags.append(self.config_settings["libcapnp-url"]) - if flags: - sys.argv = sys.argv[:1] + ["build_ext"] + flags + sys.argv[1:] - return super().run_setup(setup_script) - - def build_wheel(self, wheel_directory, config_settings=None, metadata_directory=None): - self.config_settings = config_settings - return super().build_wheel(wheel_directory, config_settings, metadata_directory) - - -build_wheel = _CustomBuildMetaBackend().build_wheel diff --git a/buildutils/__init__.py b/buildutils/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/buildutils/build.py b/buildutils/build.py deleted file mode 100644 index 6bd8d80..0000000 --- a/buildutils/build.py +++ /dev/null @@ -1,70 +0,0 @@ -"Build the bundled capnp distribution" - -import subprocess -import os -import shutil -import sys - - -def build_libcapnp(bundle_dir, build_dir): # noqa: C901 - """ - Build capnproto - """ - bundle_dir = os.path.abspath(bundle_dir) - capnp_dir = os.path.join(bundle_dir, "capnproto-c++") - build_dir = os.path.abspath(build_dir) - tmp_dir = os.path.join(capnp_dir, "build") - - # Clean the tmp build directory every time - if os.path.exists(tmp_dir): - shutil.rmtree(tmp_dir) - os.mkdir(tmp_dir) - - cxxflags = os.environ.get("CXXFLAGS", None) - ldflags = os.environ.get("LDFLAGS", None) - os.environ["CXXFLAGS"] = (cxxflags or "") + " -O2 -DNDEBUG" - os.environ["LDFLAGS"] = ldflags or "" - - # Enable ninja for compilation if available - build_type = [] - if shutil.which("ninja"): - build_type = ["-G", "Ninja"] - - if not shutil.which("cmake"): - raise RuntimeError("Could not find cmake in your path!") - - args = [ - "cmake", - "-DCMAKE_POSITION_INDEPENDENT_CODE=1", - "-DBUILD_TESTING=OFF", - "-DBUILD_SHARED_LIBS=OFF", - "-DWITH_OPENSSL=OFF", - "-DCMAKE_INSTALL_PREFIX:PATH={}".format(build_dir), - capnp_dir, - ] - args.extend(build_type) - conf = subprocess.Popen(args, cwd=tmp_dir, stdout=sys.stdout) - returncode = conf.wait() - if returncode != 0: - raise RuntimeError("CMake failed {}".format(returncode)) - - # Run build through cmake - args = [ - "cmake", - "--build", - ".", - "--target", - "install", - ] - build = subprocess.Popen(args, cwd=tmp_dir, stdout=sys.stdout) - returncode = build.wait() - if cxxflags is None: - del os.environ["CXXFLAGS"] - else: - os.environ["CXXFLAGS"] = cxxflags - if ldflags is None: - del os.environ["LDFLAGS"] - else: - os.environ["LDFLAGS"] = ldflags - if returncode != 0: - raise RuntimeError("capnproto compilation failed: {}".format(returncode)) diff --git a/buildutils/bundle.py b/buildutils/bundle.py deleted file mode 100644 index f60de29..0000000 --- a/buildutils/bundle.py +++ /dev/null @@ -1,76 +0,0 @@ -"""utilities for fetching build dependencies.""" - -# -# Copyright (C) PyZMQ Developers -# Distributed under the terms of the Modified BSD License. -# -# This bundling code is largely adapted from pyzmq-static's get.sh by -# Brandon Craig-Rhodes, which is itself BSD licensed. -# -# Adapted for use in pycapnp from pyzmq. See https://github.com/zeromq/pyzmq -# for original project. - -import os -import shutil -import tarfile - -from urllib.request import urlopen - -pjoin = os.path.join - - -# -# Constants -# - - -bundled_version = (1, 4, 0) -libcapnp_name = "capnproto-c++-%i.%i.%i.tar.gz" % (bundled_version) -libcapnp_url = "https://capnproto.org/" + libcapnp_name - - -def fetch_archive(savedir, url): - """download an archive to a specific location""" - req = urlopen(url) - # Lookup filename - fname = req.info().get_filename() - if not fname: - fname = os.path.basename(url) - dest = pjoin(savedir, fname) - if os.path.exists(dest): - print("already have %s" % fname) - return dest - print("fetching %s into %s" % (url, savedir)) - if not os.path.exists(savedir): - os.makedirs(savedir) - with open(dest, "wb") as f: - f.write(req.read()) - return dest - - -# -# libcapnp -# - - -def fetch_libcapnp(savedir, url=None): - """download and extract libcapnp""" - is_preconfigured = False - if url is None: - url = libcapnp_url - is_preconfigured = True - dest = pjoin(savedir, "capnproto-c++") - if os.path.exists(dest): - print("already have %s" % dest) - return - fname = fetch_archive(savedir, url) - tf = tarfile.open(fname) - with_version = pjoin(savedir, tf.firstmember.path) - tf.extractall(savedir) - tf.close() - # remove version suffix: - if is_preconfigured: - shutil.move(with_version, dest) - else: - cpp_dir = os.path.join(with_version, "c++") - shutil.move(cpp_dir, dest) diff --git a/capnp/includes/capnp_cpp.pxd b/capnp/includes/capnp_cpp.pxd index 7fc14a2..684af63 100644 --- a/capnp/includes/capnp_cpp.pxd +++ b/capnp/includes/capnp_cpp.pxd @@ -136,7 +136,7 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp": bint has(char *) except +reraise_kj_exception StructSchema getSchema() Maybe[StructSchema.Field] which() - MessageSize totalSize() + MessageSize totalSize() except +reraise_kj_exception cdef cppclass DynamicStruct_Builder" ::capnp::DynamicStruct::Builder" nogil: # Need to flatten this class out, since nested C++ classes cause havoc with cython fused types @@ -152,7 +152,7 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp": StructSchema getSchema() Maybe[StructSchema.Field] which() DynamicStruct.Reader asReader() - MessageSize totalSize() + MessageSize totalSize() except +reraise_kj_exception cdef extern from "capnp/dynamic.h" namespace " ::capnp": cdef cppclass DynamicEnum nogil: @@ -214,4 +214,4 @@ cdef extern from "capnp/schema-parser.h" namespace " ::capnp": ParsedSchema getNested(char * name) except +reraise_kj_exception cdef cppclass SchemaParser nogil: SchemaParser() - ParsedSchema parseDiskFile(char * displayName, char * diskPath, ArrayPtr[StringPtr] importPath) + ParsedSchema parseDiskFile(char * displayName, char * diskPath, ArrayPtr[StringPtr] importPath) except +reraise_kj_exception diff --git a/capnp/includes/schema_cpp.pxd b/capnp/includes/schema_cpp.pxd index 79225b0..ebbb3d2 100644 --- a/capnp/includes/schema_cpp.pxd +++ b/capnp/includes/schema_cpp.pxd @@ -72,7 +72,7 @@ cdef extern from "capnp/message.h" namespace " ::capnp": cdef cppclass MessageBuilder nogil: DynamicStruct_Builder getRootDynamicStruct 'getRoot< ::capnp::DynamicStruct>'(StructSchema) except +reraise_kj_exception DynamicStruct_Builder initRootDynamicStruct 'initRoot< ::capnp::DynamicStruct>'(StructSchema) - void setRootDynamicStruct 'setRoot< ::capnp::DynamicStruct::Reader>'(DynamicStruct.Reader) + void setRootDynamicStruct 'setRoot< ::capnp::DynamicStruct::Reader>'(DynamicStruct.Reader) except +reraise_kj_exception cdef cppclass MessageReader nogil: DynamicStruct.Reader getRootDynamicStruct 'getRoot< ::capnp::DynamicStruct>'(StructSchema) except +reraise_kj_exception diff --git a/capnp/lib/capnp.pyx b/capnp/lib/capnp.pyx index e9d8830..75b91a9 100644 --- a/capnp/lib/capnp.pyx +++ b/capnp/lib/capnp.pyx @@ -1,6 +1,5 @@ # capnp.pyx # distutils: language = c++ -# distutils: libraries = capnpc capnp kj # distutils: include_dirs = . # cython: c_string_type = str # cython: c_string_encoding = default @@ -1382,7 +1381,6 @@ cdef class SchemaParser: self._last_import_array = importArray ret = _ParsedSchema() - # TODO (HaaTa): Convert to parseFromDirectory() as per deprecation note ret._init_child(self.thisptr.parseDiskFile(displayName, diskPath, importArray.asArrayPtr())) return ret diff --git a/pyproject.toml b/pyproject.toml index e68a0bb..b8d5a23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,6 @@ [build-system] -requires = ["setuptools", "wheel", "pkgconfig", "cython>=3.0"] -build-backend = "backend" -backend-path = ["_custom_build"] +requires = ["setuptools", "wheel", "cython>=3.0"] +build-backend = "setuptools.build_meta" [project] name = "pycapnp" @@ -18,7 +17,7 @@ dynamic = [ dependencies = [] [dependency-groups] -dev = ["cython>=3.0", "setuptools", "wheel", "pkgconfig", "build", {include-group = "test"}, {include-group = "lint"}] +dev = ["cython>=3.0", "setuptools", "wheel", "build", {include-group = "test"}, {include-group = "lint"}] test = ["pytest"] lint = ["ruff==0.16.8"] @@ -28,7 +27,7 @@ testpaths = ["test"] [tool.ruff] target-version = "py312" line-length = 120 -exclude = ["build", "build64", "bundled"] +exclude = ["build", "vendor"] [tool.ruff.lint] select = ["E4", "E7", "E9", "F"] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 04ef73c..0000000 --- a/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[metadata] -description_file = README.md -license_files = LICENSE.md diff --git a/setup.py b/setup.py index e11d021..5c5033e 100644 --- a/setup.py +++ b/setup.py @@ -3,24 +3,17 @@ pycapnp distutils setup.py """ -import glob import os import shutil -import struct -import sys - -import pkgconfig -import setuptools # noqa: F401 from distutils.command.clean import clean as _clean from setuptools import setup, Extension _this_dir = os.path.dirname(__file__) -sys.path.insert(1, _this_dir) -from buildutils.build import build_libcapnp -from buildutils.bundle import fetch_libcapnp +import subprocess +from pathlib import Path MAJOR = 2 MINOR = 2 @@ -72,10 +65,7 @@ class clean(_clean): os.path.join("capnp", "lib", "capnp.h"), os.path.join("capnp", "version.py"), "build", - "build32", - "build64", - "bundled", - ] + glob.glob(os.path.join("capnp", "*.capnp")): + ]: print("removing %s" % x) try: os.remove(x) @@ -91,76 +81,32 @@ class build_libcapnp_ext(build_ext_c): Build capnproto library """ - user_options = build_ext_c.user_options + [ - ("force-bundled-libcapnp", None, "Bundle capnp library into the installer"), - ("force-system-libcapnp", None, "Use system capnp library"), - ("libcapnp-url=", "u", "URL to download libcapnp from (only if bundled)"), - ] - - def initialize_options(self): - build_ext_c.initialize_options(self) - self.force_bundled_libcapnp = None - self.force_system_libcapnp = None - self.libcapnp_url = None - - def run(self): # noqa: C901 - if self.force_bundled_libcapnp: - need_build = True - elif self.force_system_libcapnp: - need_build = False - else: - # Try to use capnp executable to find include and lib path - capnp_executable = shutil.which("capnp") - if capnp_executable: - capnp_dir = os.path.dirname(capnp_executable) - self.include_dirs += [os.path.join(capnp_dir, "..", "include")] - self.library_dirs += [os.path.join(capnp_dir, "..", "lib{}".format(8 * struct.calcsize("P")))] - self.library_dirs += [os.path.join(capnp_dir, "..", "lib")] - - # Look for capnproto using pkg-config (and minimum version) - try: - if pkgconfig.installed("capnp", ">= 0.7.0"): - need_build = False - else: - need_build = True - except EnvironmentError: - # pkg-config not available in path - need_build = True - - if need_build: - print( - "*WARNING* no libcapnp detected or rebuild forced. " - "Attempting to build it from source now. " - "If you have C++ Cap'n Proto installed, it may be out of date or is not being detected. " - "This may take a while..." - ) - bundle_dir = os.path.join(_this_dir, "bundled") - if not os.path.exists(bundle_dir): - os.mkdir(bundle_dir) - build_dir = os.path.join(_this_dir, "build{}".format(8 * struct.calcsize("P"))) - if not os.path.exists(build_dir): - os.mkdir(build_dir) - - # Check if we've already built capnproto - capnp_bin = os.path.join(build_dir, "bin", "capnp") - - if not os.path.exists(capnp_bin): - # Not built, fetch and build - fetch_libcapnp(bundle_dir, self.libcapnp_url) - build_libcapnp(bundle_dir, build_dir) - else: - print("capnproto already built at {}".format(build_dir)) - - self.include_dirs = [os.path.join(build_dir, "include")] + self.include_dirs - self.library_dirs = [ - os.path.join(build_dir, "lib{}".format(8 * struct.calcsize("P"))), - os.path.join(build_dir, "lib"), - ] + self.library_dirs - + def run(self): + source = Path(_this_dir, "vendor", "capnproto").resolve() + build = Path(self.build_temp, "capnproto").resolve() + args = [ + "cmake", + "-S", + str(source), + "-B", + str(build), + "-DCMAKE_BUILD_TYPE=Release", + ] + if os.environ.get("CMAKE_OSX_ARCHITECTURES"): + args.append("-DCMAKE_OSX_ARCHITECTURES=" + os.environ["CMAKE_OSX_ARCHITECTURES"]) + if os.environ.get("MACOSX_DEPLOYMENT_TARGET"): + args.append("-DCMAKE_OSX_DEPLOYMENT_TARGET=" + os.environ["MACOSX_DEPLOYMENT_TARGET"]) + subprocess.run(args, check=True) + subprocess.run(["cmake", "--build", str(build), "--parallel", str(self.parallel or 2)], check=True) + archive = str(build / "libcapnp-vendored.a") + for extension in self.extensions: + extension.include_dirs.insert(0, str(source / "src")) + extension.extra_objects = [archive] + extension.depends = [str(p) for p in source.rglob("*") if p.is_file()] + [archive] return build_ext_c.run(self) -extra_compile_args = ["--std=c++14"] +extra_compile_args = ["-std=c++17", "-pthread"] import Cython.Build # noqa: E402 import Cython # noqa: E402 @@ -172,6 +118,7 @@ extensions = [ "capnp/lib/*.pyx", ], extra_compile_args=extra_compile_args, + extra_link_args=["-pthread"], language="c++", ) ] @@ -203,7 +150,8 @@ setup( description="A cython wrapping of the C++ Cap'n Proto library", long_description=long_description, long_description_content_type="text/markdown", - license="BSD-2-Clause", + license="BSD-2-Clause AND MIT", + license_files=["LICENSE.md", "vendor/capnproto/LICENSE.txt"], # (setup.py only supports 1 author...) author="Jacob Alexander", # <- Current maintainer; Original author -> Jason Paryani author_email="haata@kiibohd.com", diff --git a/test/foo.capnp b/test/foo.capnp index a1bc79b..baec3d7 100644 --- a/test/foo.capnp +++ b/test/foo.capnp @@ -14,7 +14,3 @@ struct Baz{ struct Qux{ id @0 :UInt64; } - -interface Wrapper { - wrapped @0 (object :AnyPointer); -} diff --git a/test/test_vendor.py b/test/test_vendor.py new file mode 100644 index 0000000..dac57fc --- /dev/null +++ b/test/test_vendor.py @@ -0,0 +1,30 @@ +"""Validation of malformed wire data through the trimmed C++ core.""" + +import struct +from pathlib import Path + +import capnp +import pytest + + +@pytest.mark.parametrize("pointer", [3, 7, 0xFFFFFFFF00000003]) +def test_capability_and_reserved_pointers_rejected(pointer): + schema = capnp.load(str(Path(__file__).with_name("addressbook.capnp"))) + # Single segment: AddressBook root (zero data words, one pointer) followed + # by a capability/reserved pointer where the people list should be. + data = struct.pack(" (); }") + with pytest.raises(capnp.KjException, match="Interfaces are not supported"): + capnp.load(str(schema)) diff --git a/vendor/capnproto/CMakeLists.txt b/vendor/capnproto/CMakeLists.txt new file mode 100644 index 0000000..3fb7c05 --- /dev/null +++ b/vendor/capnproto/CMakeLists.txt @@ -0,0 +1,47 @@ +cmake_minimum_required(VERSION 3.16) +project(pycapnp_vendor LANGUAGES CXX) + +add_library(capnp-vendored STATIC + src/capnp/blob.c++ + src/capnp/arena.c++ + src/capnp/layout.c++ + src/capnp/message.c++ + src/capnp/schema.capnp.c++ + src/capnp/serialize.c++ + src/capnp/schema.c++ + src/capnp/schema-loader.c++ + src/capnp/dynamic.c++ + src/capnp/stringify.c++ + src/capnp/compiler/type-id.c++ + src/capnp/compiler/lexer.c++ + src/capnp/compiler/grammar.capnp.c++ + src/capnp/compiler/parser.c++ + src/capnp/compiler/generics.c++ + src/capnp/compiler/node-translator.c++ + src/capnp/compiler/compiler.c++ + src/capnp/schema-parser.c++ + src/kj/array.c++ + src/kj/common.c++ + src/kj/debug.c++ + src/kj/exception.c++ + src/kj/io.c++ + src/kj/mutex.c++ + src/kj/string.c++ + src/kj/source-location.c++ + src/kj/hash.c++ + src/kj/table.c++ + src/kj/arena.c++ + src/kj/units.c++ + src/kj/encoding.c++ + src/kj/refcount.c++ + src/kj/string-tree.c++ + src/kj/time.c++ + src/kj/filesystem.c++ + src/kj/filesystem-disk-unix.c++ + src/kj/parse/char.c++ +) +target_compile_features(capnp-vendored PUBLIC cxx_std_17) +target_include_directories(capnp-vendored PUBLIC src) +set_target_properties(capnp-vendored PROPERTIES POSITION_INDEPENDENT_CODE ON) +find_package(Threads REQUIRED) +target_link_libraries(capnp-vendored PUBLIC Threads::Threads) diff --git a/vendor/capnproto/LICENSE.txt b/vendor/capnproto/LICENSE.txt new file mode 100644 index 0000000..f77abf5 --- /dev/null +++ b/vendor/capnproto/LICENSE.txt @@ -0,0 +1,23 @@ +Copyright (c) 2013-2017 Sandstorm Development Group, Inc.; Cloudflare, Inc.; +and other contributors. Each commit is copyright by its respective author or +author's employer. + +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. diff --git a/vendor/capnproto/README.md b/vendor/capnproto/README.md new file mode 100644 index 0000000..1728e01 --- /dev/null +++ b/vendor/capnproto/README.md @@ -0,0 +1,44 @@ +# Vendored Cap'n Proto + +Based on Cap'n Proto 1.4.0, the version previously downloaded by this fork. + +Source: https://capnproto.org/capnproto-c++-1.4.0.tar.gz + +Archive SHA-256: `fa02378ad522b318916b9ad928d1372fc9abd43dd1f4f0392e50450f5c87828f` + +See LICENSE.txt and individual files for upstream licenses. + +This is an internal serialization/schema-parser subset for pycapnp, not a full +Cap'n Proto distribution. Generated schema sources are checked in; no compiler +executables or network downloads are required to build it. + +Removed: RPC/capabilities, promises/async I/O, networking/TLS/HTTP, JSON, +compression, packed/text/stream/fd message serialization, command-line tools and +code generators, upstream build systems/examples/tests, compiler export helpers, +unused KJ encodings/stream classes/clocks, and opt-in crash handlers. Also removed +are canonicalization, borrowed-memory builders, orphan resizing/concatenation, +schema doc-comment storage, interface-schema support, Windows code, and the +optional lite build. Interface declarations are rejected with a parser error. + +The retained core includes message validation, flat serialization, dynamic +struct/list/enum values, runtime schema compilation (including generics), and +its filesystem, allocation, synchronization, and diagnostic dependencies. +Generated schema reader/builder metadata is retained; pipeline classes are not. +This source tree is for the Python binding, not a drop-in C++ SDK or schema +compiler for openpilot's separate C++ build. + +The retained `src/capnp/schema.capnp` omits compiler-request and documentation +metadata. Its generated C++ was rebuilt with upstream 1.4.0's `capnp` and +`capnpc-c++`, then unused generated pipeline APIs were removed. Regeneration: + +```sh +capnp compile -I/src --src-prefix=vendor/capnproto/src/capnp \ + -o: vendor/capnproto/src/capnp/schema.capnp +``` + +Regeneration must also apply the vendor's removal of Pipeline declarations, +classes and accessors, and Windows-only includes. The unused `LexedTokens` type +was removed from the shipped generated lexer files; the runtime parser uses +`LexedStatements`. Lexer reflection metadata is also omitted; its generated +static reader/builder layouts remain. Generated wire type tags and active field +ordinals are kept. diff --git a/vendor/capnproto/src/capnp/any.h b/vendor/capnproto/src/capnp/any.h new file mode 100644 index 0000000..c8d0cda --- /dev/null +++ b/vendor/capnproto/src/capnp/any.h @@ -0,0 +1,862 @@ +// 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. + +#pragma once + +#include "layout.h" +#include "pointer-helpers.h" +#include "orphan.h" +#include "list.h" +#include + +CAPNP_BEGIN_HEADER + +namespace capnp { + +class StructSchema; +class ListSchema; +class Orphanage; +struct AnyPointer; + +struct AnyList { + AnyList() = delete; + + class Reader; + class Builder; +}; + +struct AnyStruct { + AnyStruct() = delete; + + class Reader; + class Builder; +}; + +template<> +struct List { + List() = delete; + + class Reader; + class Builder; +}; + +namespace _ { // private +template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; +} // namespace _ (private) + +// ======================================================================================= +// AnyPointer! + +struct AnyPointer { + // Reader/Builder for the `AnyPointer` field type, i.e. a pointer that can point to an arbitrary + // object. + + AnyPointer() = delete; + + class Reader { + public: + typedef AnyPointer Reads; + + Reader() = default; + inline Reader(_::PointerReader reader): reader(reader) {} + + inline MessageSize targetSize() const; + // Get the total size of the target object and all its children. + + inline PointerType getPointerType() const; + + inline bool isNull() const { return getPointerType() == PointerType::NULL_; } + inline bool isStruct() const { return getPointerType() == PointerType::STRUCT; } + inline bool isList() const { return getPointerType() == PointerType::LIST; } + inline bool isCapability() const { return getPointerType() == PointerType::CAPABILITY; } + + template + inline ReaderFor getAs() const; + // Valid for T = any generated struct type, List, Text, or Data. + + template + inline ReaderFor getAs(StructSchema schema) const; + // Only valid for T = DynamicStruct. Requires `#include `. + + template + inline ReaderFor getAs(ListSchema schema) const; + // Only valid for T = DynamicList. Requires `#include `. + + private: + _::PointerReader reader; + friend struct AnyPointer; + friend class Orphanage; + friend struct _::PointerHelpers; + }; + + class Builder { + public: + typedef AnyPointer Builds; + + Builder() = delete; + inline Builder(decltype(nullptr)) {} + inline Builder(_::PointerBuilder builder): builder(builder) {} + + inline MessageSize targetSize() const; + // Get the total size of the target object and all its children. + + inline PointerType getPointerType(); + + inline bool isNull() { return getPointerType() == PointerType::NULL_; } + inline bool isStruct() { return getPointerType() == PointerType::STRUCT; } + inline bool isList() { return getPointerType() == PointerType::LIST; } + inline bool isCapability() { return getPointerType() == PointerType::CAPABILITY; } + + inline void clear(); + // Set to null. + + template + inline BuilderFor getAs(); + // Valid for T = any generated struct type, List, Text, or Data. + + template + inline BuilderFor getAs(StructSchema schema); + // Only valid for T = DynamicStruct. Requires `#include `. + + template + inline BuilderFor getAs(ListSchema schema); + // Only valid for T = DynamicList. Requires `#include `. + + template + inline BuilderFor initAs(); + // Valid for T = any generated struct type. + + template + inline BuilderFor initAs(uint elementCount); + // Valid for T = List, Text, or Data. + + template + inline BuilderFor initAs(StructSchema schema); + // Only valid for T = DynamicStruct. Requires `#include `. + + template + inline BuilderFor initAs(ListSchema schema, uint elementCount); + // Only valid for T = DynamicList. Requires `#include `. + + inline AnyList::Builder initAsAnyList(ElementSize elementSize, uint elementCount); + // Note: Does not accept INLINE_COMPOSITE for elementSize. + + inline List::Builder initAsListOfAnyStruct( + uint16_t dataWordCount, uint16_t pointerCount, uint elementCount); + + inline AnyStruct::Builder initAsAnyStruct(uint16_t dataWordCount, uint16_t pointerCount); + + template + inline void setAs(ReaderFor value); + // Valid for ReaderType = T::Reader for T = any generated struct type, List, Text, Data, + // DynamicStruct, or DynamicList (the dynamic types require `#include `). + + template + inline void setAs(std::initializer_list>> list); + // Valid for T = List. + + inline void set(Reader value) { builder.copyFrom(value.reader); } + // Set to a copy of another AnyPointer. + + template + inline void adopt(Orphan&& orphan); + // Valid for T = any generated struct type, List, Text, Data, DynamicList, DynamicStruct, + // or DynamicValue (the dynamic types require `#include `). + + template + inline Orphan disownAs(); + // Valid for T = any generated struct type, List, Text, Data. + + template + inline Orphan disownAs(StructSchema schema); + // Only valid for T = DynamicStruct. Requires `#include `. + + template + inline Orphan disownAs(ListSchema schema); + // Only valid for T = DynamicList. Requires `#include `. + + inline Orphan disown(); + // Disown without a type. + + inline Reader asReader() const { return Reader(builder.asReader()); } + inline operator Reader() const { return Reader(builder.asReader()); } + + private: + _::PointerBuilder builder; + friend class Orphanage; + friend struct _::PointerHelpers; + }; + +}; + +template <> +class Orphan { + // An orphaned object of unknown type. + +public: + Orphan() = default; + KJ_DISALLOW_COPY(Orphan); + Orphan(Orphan&&) = default; + inline Orphan(_::OrphanBuilder&& builder) + : builder(kj::mv(builder)) {} + + Orphan& operator=(Orphan&&) = default; + + template + inline Orphan(Orphan&& other): builder(kj::mv(other.builder)) {} + template + inline Orphan& operator=(Orphan&& other) { builder = kj::mv(other.builder); return *this; } + // Cast from typed orphan. + + // It's not possible to get an AnyPointer::{Reader,Builder} directly since there is no + // underlying pointer (the pointer would normally live in the parent, but this object is + // orphaned). It is possible, however, to request typed readers/builders. + + template + inline BuilderFor getAs(); + template + inline BuilderFor getAs(StructSchema schema); + template + inline BuilderFor getAs(ListSchema schema); + template + inline ReaderFor getAsReader() const; + template + inline ReaderFor getAsReader(StructSchema schema) const; + template + inline ReaderFor getAsReader(ListSchema schema) const; + + template + inline Orphan releaseAs(); + template + inline Orphan releaseAs(StructSchema schema); + template + inline Orphan releaseAs(ListSchema schema); + // Down-cast the orphan to a specific type. + + inline bool operator==(decltype(nullptr)) const { return builder == nullptr; } + inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; } + +private: + _::OrphanBuilder builder; + + template + friend struct _::PointerHelpers; + friend class Orphanage; + template + friend class Orphan; + friend class AnyPointer::Builder; +}; + +template struct AnyTypeFor_; +template <> struct AnyTypeFor_ { typedef AnyStruct Type; }; +template <> struct AnyTypeFor_ { typedef AnyList Type; }; + +template +using AnyTypeFor = typename AnyTypeFor_::Type; + +template +inline ReaderFor>> toAny(T&& value) { + return ReaderFor>>( + _::PointerHelpers>::getInternalReader(value)); +} +template +inline BuilderFor>> toAny(T&& value) { + return BuilderFor>>( + _::PointerHelpers>::getInternalBuilder(kj::mv(value))); +} + +template <> +struct List { + // Note: This cannot be used for a list of structs, since such lists are not encoded as pointer + // lists! Use List. + + List() = delete; + + class Reader { + public: + typedef List Reads; + + inline Reader(): reader(ElementSize::POINTER) {} + inline explicit Reader(_::ListReader reader): reader(reader) {} + + inline uint size() const { return unbound(reader.size() / ELEMENTS); } + inline AnyPointer::Reader operator[](uint index) const { + KJ_IREQUIRE(index < size()); + return AnyPointer::Reader(reader.getPointerElement(bounded(index) * ELEMENTS)); + } + + typedef _::IndexingIterator Iterator; + inline Iterator begin() const { return Iterator(this, 0); } + inline Iterator end() const { return Iterator(this, size()); } + + inline MessageSize totalSize() const { + return reader.totalSize().asPublic(); + } + + private: + _::ListReader reader; + template + friend struct _::PointerHelpers; + template + friend struct List; + friend class Orphanage; + template + friend struct ToDynamic_; + }; + + class Builder { + public: + typedef List Builds; + + Builder() = delete; + inline Builder(decltype(nullptr)): builder(ElementSize::POINTER) {} + 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 AnyPointer::Builder operator[](uint index) { + KJ_IREQUIRE(index < size()); + return AnyPointer::Builder(builder.getPointerElement(bounded(index) * ELEMENTS)); + } + + typedef _::IndexingIterator Iterator; + inline Iterator begin() { return Iterator(this, 0); } + inline Iterator end() { return Iterator(this, size()); } + + private: + _::ListBuilder builder; + template + friend struct _::PointerHelpers; + friend class Orphanage; + template + friend struct ToDynamic_; + }; +}; + +class AnyStruct::Reader { +public: + typedef AnyStruct Reads; + + Reader() = default; + inline Reader(_::StructReader reader): _reader(reader) {} + + template ) == Kind::STRUCT>> + inline Reader(T&& value) + : _reader(_::PointerHelpers>::getInternalReader(kj::fwd(value))) {} + + inline MessageSize totalSize() const { return _reader.totalSize().asPublic(); } + + kj::ArrayPtr getDataSection() const { + return _reader.getDataSectionAsBlob(); + } + List::Reader getPointerSection() const { + return List::Reader(_reader.getPointerSectionAsList()); + } + + template + ReaderFor as() const { + // T must be a struct type. + return typename T::Reader(_reader); + } + + template + ReaderFor as(StructSchema schema) const; + // T must be DynamicStruct. Defined in dynamic.h. + +private: + _::StructReader _reader; + + template + friend struct _::PointerHelpers; + friend class Orphanage; +}; + +class AnyStruct::Builder { +public: + typedef AnyStruct Builds; + + inline Builder(decltype(nullptr)) {} + inline Builder(_::StructBuilder builder): _builder(builder) {} + +#if !_MSC_VER || defined(__clang__) // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves. + template ) == Kind::STRUCT>> + inline Builder(T&& value) + : _builder(_::PointerHelpers>::getInternalBuilder(kj::fwd(value))) {} +#endif + + inline kj::ArrayPtr getDataSection() { + return _builder.getDataSectionAsBlob(); + } + List::Builder getPointerSection() { + return List::Builder(_builder.getPointerSectionAsList()); + } + + inline operator Reader() const { return Reader(_builder.asReader()); } + inline Reader asReader() const { return Reader(_builder.asReader()); } + + template + BuilderFor as() { + // T must be a struct type. + return typename T::Builder(_builder); + } + + template + BuilderFor as(StructSchema schema); + // T must be DynamicStruct. Defined in dynamic.h. + +private: + _::StructBuilder _builder; + friend class Orphanage; +}; + +class List::Reader { +public: + typedef List Reads; + + inline Reader(): reader(ElementSize::INLINE_COMPOSITE) {} + inline explicit Reader(_::ListReader reader): reader(reader) {} + + inline uint size() const { return unbound(reader.size() / ELEMENTS); } + inline AnyStruct::Reader operator[](uint index) const { + KJ_IREQUIRE(index < size()); + return AnyStruct::Reader(reader.getStructElement(bounded(index) * ELEMENTS)); + } + + typedef _::IndexingIterator Iterator; + inline Iterator begin() const { return Iterator(this, 0); } + inline Iterator end() const { return Iterator(this, size()); } + + inline MessageSize totalSize() const { + return reader.totalSize().asPublic(); + } + +private: + _::ListReader reader; + template + friend struct _::PointerHelpers; + template + friend struct List; + friend class Orphanage; + template + friend struct ToDynamic_; +}; + +class List::Builder { +public: + typedef List Builds; + + Builder() = delete; + inline Builder(decltype(nullptr)): builder(ElementSize::INLINE_COMPOSITE) {} + 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 AnyStruct::Builder operator[](uint index) { + KJ_IREQUIRE(index < size()); + return AnyStruct::Builder(builder.getStructElement(bounded(index) * ELEMENTS)); + } + + typedef _::IndexingIterator Iterator; + inline Iterator begin() { return Iterator(this, 0); } + inline Iterator end() { return Iterator(this, size()); } + +private: + _::ListBuilder builder; + template + friend struct _::PointerHelpers; + friend class Orphanage; + template + friend struct ToDynamic_; +}; + +class AnyList::Reader { +public: + typedef AnyList Reads; + + inline Reader(): _reader(ElementSize::VOID) {} + inline Reader(_::ListReader reader): _reader(reader) {} + +#if !_MSC_VER || defined(__clang__) // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves. + template ) == Kind::LIST>> + inline Reader(T&& value) + : _reader(_::PointerHelpers>::getInternalReader(kj::fwd(value))) {} +#endif + + inline ElementSize getElementSize() const { return _reader.getElementSize(); } + inline uint size() const { return unbound(_reader.size() / ELEMENTS); } + + inline kj::ArrayPtr getRawBytes() const { return _reader.asRawBytes(); } + + inline MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + template ReaderFor as() const { + // T must be List. + return ReaderFor(_reader); + } +private: + _::ListReader _reader; + + template + friend struct _::PointerHelpers; + friend class Orphanage; +}; + +class AnyList::Builder { +public: + typedef AnyList Builds; + + inline Builder(decltype(nullptr)): _builder(ElementSize::VOID) {} + inline Builder(_::ListBuilder builder): _builder(builder) {} + +#if !_MSC_VER || defined(__clang__) // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves. + template ) == Kind::LIST>> + inline Builder(T&& value) + : _builder(_::PointerHelpers>::getInternalBuilder(kj::fwd(value))) {} +#endif + + inline ElementSize getElementSize() { return _builder.getElementSize(); } + inline uint size() { return unbound(_builder.size() / ELEMENTS); } + + template BuilderFor as() { + // T must be List. + return BuilderFor(_builder); + } + + inline operator Reader() const { return Reader(_builder.asReader()); } + inline Reader asReader() const { return Reader(_builder.asReader()); } + +private: + _::ListBuilder _builder; + + friend class Orphanage; +}; + +// ======================================================================================= +// Inline implementation details + +inline MessageSize AnyPointer::Reader::targetSize() const { + return reader.targetSize().asPublic(); +} + +inline PointerType AnyPointer::Reader::getPointerType() const { + return reader.getPointerType(); +} + +template +inline ReaderFor AnyPointer::Reader::getAs() const { + return _::PointerHelpers::get(reader); +} + +inline MessageSize AnyPointer::Builder::targetSize() const { + return asReader().targetSize(); +} + +inline PointerType AnyPointer::Builder::getPointerType() { + return builder.getPointerType(); +} + +inline void AnyPointer::Builder::clear() { + return builder.clear(); +} + +template +inline BuilderFor AnyPointer::Builder::getAs() { + return _::PointerHelpers::get(builder); +} + +template +inline BuilderFor AnyPointer::Builder::initAs() { + return _::PointerHelpers::init(builder); +} + +template +inline BuilderFor AnyPointer::Builder::initAs(uint elementCount) { + return _::PointerHelpers::init(builder, elementCount); +} + +inline AnyList::Builder AnyPointer::Builder::initAsAnyList( + ElementSize elementSize, uint elementCount) { + return AnyList::Builder(builder.initList(elementSize, bounded(elementCount) * ELEMENTS)); +} + +inline List::Builder AnyPointer::Builder::initAsListOfAnyStruct( + uint16_t dataWordCount, uint16_t pointerCount, uint elementCount) { + return List::Builder(builder.initStructList(bounded(elementCount) * ELEMENTS, + _::StructSize(bounded(dataWordCount) * WORDS, + bounded(pointerCount) * POINTERS))); +} + +inline AnyStruct::Builder AnyPointer::Builder::initAsAnyStruct( + uint16_t dataWordCount, uint16_t pointerCount) { + return AnyStruct::Builder(builder.initStruct( + _::StructSize(bounded(dataWordCount) * WORDS, + bounded(pointerCount) * POINTERS))); +} + +template +inline void AnyPointer::Builder::setAs(ReaderFor value) { + return _::PointerHelpers::set(builder, value); +} + +template +inline void AnyPointer::Builder::setAs( + std::initializer_list>> list) { + return _::PointerHelpers::set(builder, list); +} + +template +inline void AnyPointer::Builder::adopt(Orphan&& orphan) { + _::PointerHelpers::adopt(builder, kj::mv(orphan)); +} + +template +inline Orphan AnyPointer::Builder::disownAs() { + return _::PointerHelpers::disown(builder); +} + +inline Orphan AnyPointer::Builder::disown() { + return Orphan(builder.disown()); +} + +template <> struct ReaderFor_ { typedef AnyPointer::Reader Type; }; +template <> struct BuilderFor_ { typedef AnyPointer::Builder Type; }; +template <> struct ReaderFor_ { typedef AnyStruct::Reader Type; }; +template <> struct BuilderFor_ { typedef AnyStruct::Builder Type; }; + +template <> +struct Orphanage::GetInnerReader { + static inline _::PointerReader apply(const AnyPointer::Reader& t) { + return t.reader; + } +}; + +template <> +struct Orphanage::GetInnerBuilder { + static inline _::PointerBuilder apply(AnyPointer::Builder& t) { + return t.builder; + } +}; + +template <> +struct Orphanage::GetInnerReader { + static inline _::StructReader apply(const AnyStruct::Reader& t) { + return t._reader; + } +}; + +template <> +struct Orphanage::GetInnerBuilder { + static inline _::StructBuilder apply(AnyStruct::Builder& t) { + return t._builder; + } +}; + +template <> +struct Orphanage::GetInnerReader { + static inline _::ListReader apply(const AnyList::Reader& t) { + return t._reader; + } +}; + +template <> +struct Orphanage::GetInnerBuilder { + static inline _::ListBuilder apply(AnyList::Builder& t) { + return t._builder; + } +}; + +template +inline BuilderFor Orphan::getAs() { + return _::OrphanGetImpl::apply(builder); +} +template +inline ReaderFor Orphan::getAsReader() const { + return _::OrphanGetImpl::applyReader(builder); +} +template +inline Orphan Orphan::releaseAs() { + return Orphan(kj::mv(builder)); +} + +// Using AnyPointer as the template type should work... + +template <> +inline typename AnyPointer::Reader AnyPointer::Reader::getAs() const { + return *this; +} +template <> +inline typename AnyPointer::Builder AnyPointer::Builder::getAs() { + return *this; +} +template <> +inline typename AnyPointer::Builder AnyPointer::Builder::initAs() { + clear(); + return *this; +} +template <> +inline void AnyPointer::Builder::setAs(AnyPointer::Reader value) { + return builder.copyFrom(value.reader); +} +template <> +inline void AnyPointer::Builder::adopt(Orphan&& orphan) { + builder.adopt(kj::mv(orphan.builder)); +} +template <> +inline Orphan AnyPointer::Builder::disownAs() { + return Orphan(builder.disown()); +} +template <> +inline Orphan Orphan::releaseAs() { + return kj::mv(*this); +} + +namespace _ { // private + +// Specialize PointerHelpers for AnyPointer. + +template <> +struct PointerHelpers { + static inline AnyPointer::Reader get(PointerReader reader, + const void* defaultValue = nullptr, + uint defaultBytes = 0) { + return AnyPointer::Reader(reader); + } + static inline AnyPointer::Builder get(PointerBuilder builder, + const void* defaultValue = nullptr, + uint defaultBytes = 0) { + return AnyPointer::Builder(builder); + } + static inline void set(PointerBuilder builder, AnyPointer::Reader value) { + AnyPointer::Builder(builder).set(value); + } + static inline void adopt(PointerBuilder builder, Orphan&& value) { + builder.adopt(kj::mv(value.builder)); + } + static inline Orphan disown(PointerBuilder builder) { + return Orphan(builder.disown()); + } + static inline _::PointerReader getInternalReader(const AnyPointer::Reader& reader) { + return reader.reader; + } + static inline _::PointerBuilder getInternalBuilder(AnyPointer::Builder&& builder) { + return builder.builder; + } +}; + +template <> +struct PointerHelpers { + static inline AnyStruct::Reader get( + PointerReader reader, const word* defaultValue = nullptr) { + return AnyStruct::Reader(reader.getStruct(defaultValue)); + } + static inline AnyStruct::Builder get( + PointerBuilder builder, const word* defaultValue = nullptr) { + // TODO(someday): Allow specifying the size somehow? + return AnyStruct::Builder(builder.getStruct( + _::StructSize(ZERO * WORDS, ZERO * POINTERS), defaultValue)); + } + static inline void set(PointerBuilder builder, AnyStruct::Reader value) { + builder.setStruct(value._reader); + } + static inline AnyStruct::Builder init( + PointerBuilder builder, uint16_t dataWordCount, uint16_t pointerCount) { + return AnyStruct::Builder(builder.initStruct( + StructSize(bounded(dataWordCount) * WORDS, + bounded(pointerCount) * POINTERS))); + } + + static void adopt(PointerBuilder builder, Orphan&& value) { + builder.adopt(kj::mv(value.builder)); + } + static Orphan disown(PointerBuilder builder) { + return Orphan(builder.disown()); + } +}; + +template <> +struct PointerHelpers { + static inline AnyList::Reader get( + PointerReader reader, const word* defaultValue = nullptr) { + return AnyList::Reader(reader.getListAnySize(defaultValue)); + } + static inline AnyList::Builder get( + PointerBuilder builder, const word* defaultValue = nullptr) { + return AnyList::Builder(builder.getListAnySize(defaultValue)); + } + static inline void set(PointerBuilder builder, AnyList::Reader value) { + builder.setList(value._reader); + } + static inline AnyList::Builder init( + PointerBuilder builder, ElementSize elementSize, uint elementCount) { + return AnyList::Builder(builder.initList( + elementSize, bounded(elementCount) * ELEMENTS)); + } + static inline AnyList::Builder init( + PointerBuilder builder, uint16_t dataWordCount, uint16_t pointerCount, uint elementCount) { + return AnyList::Builder(builder.initStructList( + bounded(elementCount) * ELEMENTS, + StructSize(bounded(dataWordCount) * WORDS, + bounded(pointerCount) * POINTERS))); + } + + static void adopt(PointerBuilder builder, Orphan&& value) { + builder.adopt(kj::mv(value.builder)); + } + static Orphan disown(PointerBuilder builder) { + return Orphan(builder.disown()); + } +}; + +template <> +struct OrphanGetImpl { + static inline AnyStruct::Builder apply(_::OrphanBuilder& builder) { + return AnyStruct::Builder(builder.asStruct(_::StructSize(ZERO * WORDS, ZERO * POINTERS))); + } + static inline AnyStruct::Reader applyReader(const _::OrphanBuilder& builder) { + return AnyStruct::Reader(builder.asStructReader(_::StructSize(ZERO * WORDS, ZERO * POINTERS))); + } + +}; + +template <> +struct OrphanGetImpl { + static inline AnyList::Builder apply(_::OrphanBuilder& builder) { + return AnyList::Builder(builder.asListAnySize()); + } + static inline AnyList::Reader applyReader(const _::OrphanBuilder& builder) { + return AnyList::Reader(builder.asListReaderAnySize()); + } + +}; + +} // namespace _ (private) + +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/arena.c++ b/vendor/capnproto/src/capnp/arena.c++ new file mode 100644 index 0000000..0036ac5 --- /dev/null +++ b/vendor/capnproto/src/capnp/arena.c++ @@ -0,0 +1,286 @@ +// 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. + +#define CAPNP_PRIVATE +#include "arena.h" +#include "message.h" +#include +#include +#include +#include +#include +#include + +namespace capnp { +namespace _ { // private + +Arena::~Arena() noexcept(false) {} + +void ReadLimiter::unread(WordCount64 amount) { + // Be careful not to overflow here. Since ReadLimiter has no thread-safety, it's possible that + // the limit value was not updated correctly for one or more reads, and therefore unread() could + // overflow it even if it is only unreading bytes that were actually read. + uint64_t oldValue = readLimit(); + uint64_t newValue = oldValue + unbound(amount / WORDS); + if (newValue > oldValue) { + setLimit(newValue); + } +} + +void SegmentReader::abortCheckObjectFault() { + KJ_LOG(FATAL, "checkObject()'s parameter is not in-range; this would segfault in opt mode", + "this is a serious bug in Cap'n Proto; please notify security@sandstorm.io"); + abort(); +} + +// ======================================================================================= + +static SegmentWordCount verifySegmentSize(size_t size) { + auto gsize = bounded(size) * WORDS; + return assertMaxBits(gsize, [&]() { + KJ_FAIL_REQUIRE("segment is too large", size); + }); +} + +static SegmentWordCount verifySegment(kj::ArrayPtr segment) { +#if !CAPNP_ALLOW_UNALIGNED + KJ_REQUIRE(reinterpret_cast(segment.begin()) % sizeof(void*) == 0, + "Detected unaligned data in Cap'n Proto message. Messages must be aligned to the " + "architecture's word size. Yes, even on x86: Unaligned access is undefined behavior " + "under the C/C++ language standard, and compilers can and do assume alignment for the " + "purpose of optimizations. Unaligned access may lead to crashes or subtle corruption. " + "For example, GCC will use SIMD instructions in optimizations, and those instrsuctions " + "require alignment. If you really insist on taking your changes with unaligned data, " + "compile the Cap'n Proto library with -DCAPNP_ALLOW_UNALIGNED to remove this check.") { + break; + } +#endif + return verifySegmentSize(segment.size()); +} + +inline ReaderArena::ReaderArena(MessageReader* message, const word* firstSegment, + SegmentWordCount firstSegmentSize) + : message(message), + readLimiter(bounded(message->getOptions().traversalLimitInWords) * WORDS), + segment0(this, SegmentId(0), firstSegment, firstSegmentSize, &readLimiter) {} + +inline ReaderArena::ReaderArena(MessageReader* message, kj::ArrayPtr firstSegment) + : ReaderArena(message, firstSegment.begin(), verifySegment(firstSegment)) {} + +ReaderArena::ReaderArena(MessageReader* message) + : ReaderArena(message, message->getSegment(0)) {} + +ReaderArena::~ReaderArena() noexcept(false) {} + +SegmentReader* ReaderArena::tryGetSegment(SegmentId id) { + if (id == SegmentId(0)) { + if (segment0.getArray() == nullptr) { + return nullptr; + } else { + return &segment0; + } + } + + auto lock = moreSegments.lockExclusive(); + + SegmentMap* segments = nullptr; + KJ_IF_MAYBE(s, *lock) { + KJ_IF_MAYBE(segment, s->find(id.value)) { + return *segment; + } + segments = s; + } + + kj::ArrayPtr newSegment = message->getSegment(id.value); + if (newSegment == nullptr) { + return nullptr; + } + + SegmentWordCount newSegmentSize = verifySegment(newSegment); + + if (*lock == nullptr) { + // OK, the segment exists, so allocate the map. + segments = &lock->emplace(); + } + + auto segment = kj::heap( + this, id, newSegment.begin(), newSegmentSize, &readLimiter); + SegmentReader* result = segment; + segments->insert(id.value, kj::mv(segment)); + return result; +} + +void ReaderArena::reportReadLimitReached() { + KJ_FAIL_REQUIRE("Exceeded message traversal limit. See capnp::ReaderOptions.") { + return; + } +} + +// ======================================================================================= + +BuilderArena::BuilderArena(MessageBuilder* message) + : message(message), segment0(nullptr, SegmentId(0), nullptr, nullptr) {} + +BuilderArena::~BuilderArena() noexcept(false) {} + +SegmentBuilder* BuilderArena::getSegment(SegmentId id) { + // This method is allowed to fail if the segment ID is not valid. + if (id == SegmentId(0)) { + return &segment0; + } else { + KJ_IF_MAYBE(s, moreSegments) { + KJ_REQUIRE(id.value - 1 < s->get()->builders.size(), "invalid segment id", id.value); + return const_cast(s->get()->builders[id.value - 1].get()); + } else { + KJ_FAIL_REQUIRE("invalid segment id", id.value); + } + } +} + +BuilderArena::AllocateResult BuilderArena::allocate(SegmentWordCount amount) { + if (segment0.getArena() == nullptr) { + // We're allocating the first segment. + kj::ArrayPtr ptr = message->allocateSegment(unbound(amount / WORDS)); + auto actualSize = verifySegment(ptr); + + // Re-allocate segment0 in-place. This is a bit of a hack, but we have not returned any + // pointers to this segment yet, so it should be fine. + kj::dtor(segment0); + kj::ctor(segment0, this, SegmentId(0), ptr.begin(), actualSize, &this->dummyLimiter); + + segmentWithSpace = &segment0; + return AllocateResult { &segment0, segment0.allocate(amount) }; + } else { + if (segmentWithSpace != nullptr) { + // Check if there is space in an existing segment. + // TODO(perf): Check for available space in more than just the last segment. We don't + // want this to be O(n), though, so we'll need to maintain some sort of table. Complicating + // matters, we want SegmentBuilders::allocate() to be fast, so we can't update any such + // table when allocation actually happens. Instead, we could have a priority queue based + // on the last-known available size, and then re-check the size when we pop segments off it + // and shove them to the back of the queue if they have become too small. + word* attempt = segmentWithSpace->allocate(amount); + if (attempt != nullptr) { + return AllocateResult { segmentWithSpace, attempt }; + } + } + + // Need to allocate a new segment. + SegmentBuilder* result = addSegmentInternal(message->allocateSegment(unbound(amount / WORDS))); + + // Check this new segment first the next time we need to allocate. + segmentWithSpace = result; + + // Allocating from the new segment is guaranteed to succeed since we made it big enough. + return AllocateResult { result, result->allocate(amount) }; + } +} + +SegmentBuilder* BuilderArena::addSegmentInternal(kj::ArrayPtr content) { + // This check should never fail in practice, since you can't get an Orphanage without allocating + // the root segment. + KJ_REQUIRE(segment0.getArena() != nullptr, + "Can't allocate segments before allocating the root segment."); + + auto contentSize = verifySegmentSize(content.size()); + + MultiSegmentState* segmentState; + KJ_IF_MAYBE(s, moreSegments) { + segmentState = *s; + } else { + auto newSegmentState = kj::heap(); + segmentState = newSegmentState; + moreSegments = kj::mv(newSegmentState); + } + + kj::Own newBuilder = kj::heap( + this, SegmentId(segmentState->builders.size() + 1), + content.begin(), contentSize, &this->dummyLimiter); + SegmentBuilder* result = newBuilder.get(); + segmentState->builders.add(kj::mv(newBuilder)); + + // Keep forOutput the right size so that we don't have to re-allocate during + // getSegmentsForOutput(), which callers might reasonably expect is a thread-safe method. + segmentState->forOutput.resize(segmentState->builders.size() + 1); + + return result; +} + +kj::ArrayPtr> BuilderArena::getSegmentsForOutput() { + // Although this is a read-only method, we shouldn't need to lock a mutex here because if this + // is called multiple times simultaneously, we should only be overwriting the array with the + // exact same data. If the number or size of segments is actually changing due to an activity + // in another thread, then the caller has a problem regardless of locking here. + + KJ_IF_MAYBE(segmentState, moreSegments) { + KJ_DASSERT(segmentState->get()->forOutput.size() == segmentState->get()->builders.size() + 1, + "segmentState->forOutput wasn't resized correctly when the last builder was added.", + segmentState->get()->forOutput.size(), segmentState->get()->builders.size()); + + kj::ArrayPtr> result( + &segmentState->get()->forOutput[0], segmentState->get()->forOutput.size()); + uint i = 0; + result[i++] = segment0.currentlyAllocated(); + for (auto& builder: segmentState->get()->builders) { + result[i++] = builder->currentlyAllocated(); + } + return result; + } else { + if (segment0.getArena() == nullptr) { + // We haven't actually allocated any segments yet. + return nullptr; + } else { + // We have only one segment so far. + segment0ForOutput = segment0.currentlyAllocated(); + return kj::arrayPtr(&segment0ForOutput, 1); + } + } +} + +SegmentReader* BuilderArena::tryGetSegment(SegmentId id) { + if (id == SegmentId(0)) { + if (segment0.getArena() == nullptr) { + // We haven't allocated any segments yet. + return nullptr; + } else { + return &segment0; + } + } else { + KJ_IF_MAYBE(segmentState, moreSegments) { + if (id.value <= segmentState->get()->builders.size()) { + // TODO(cleanup): Return a const SegmentReader and tediously constify all SegmentBuilder + // pointers throughout the codebase. + return const_cast(kj::implicitCast( + segmentState->get()->builders[id.value - 1].get())); + } + } + return nullptr; + } +} + +void BuilderArena::reportReadLimitReached() { + KJ_FAIL_ASSERT("Read limit reached for BuilderArena, but it should have been unlimited.") { + return; + } +} + +} // namespace _ (private) +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/arena.h b/vendor/capnproto/src/capnp/arena.h new file mode 100644 index 0000000..745578a --- /dev/null +++ b/vendor/capnproto/src/capnp/arena.h @@ -0,0 +1,391 @@ +// 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. + +#pragma once + +#ifndef CAPNP_PRIVATE +#error "This header is only meant to be included by Cap'n Proto's own source code." +#endif + +#include +#include +#include +#include +#include +#include "common.h" +#include "message.h" +#include "layout.h" +#include + +CAPNP_BEGIN_HEADER + +namespace capnp { + +namespace _ { // private + +class SegmentReader; +class SegmentBuilder; +class Arena; +class BuilderArena; +class ReadLimiter; + +class Segment; +typedef kj::Id SegmentId; + +class ReadLimiter { + // Used to keep track of how much data has been processed from a message, and cut off further + // processing if and when a particular limit is reached. This is primarily intended to guard + // against maliciously-crafted messages which contain cycles or overlapping structures. Cycles + // and overlapping are not permitted by the Cap'n Proto format because in many cases they could + // be used to craft a deceptively small message which could consume excessive server resources to + // process, perhaps even sending it into an infinite loop. Actually detecting overlaps would be + // time-consuming, so instead we just keep track of how many words worth of data structures the + // receiver has actually dereferenced and error out if this gets too high. + // + // This counting takes place as you call getters (for non-primitive values) on the message + // readers. If you call the same getter twice, the data it returns may be double-counted. This + // should not be a big deal in most cases -- just set the read limit high enough that it will + // only trigger in unreasonable cases. + // + // This class is "safe" to use from multiple threads for its intended use case. Threads may + // overwrite each others' changes to the counter, but this is OK because it only means that the + // limit is enforced a bit less strictly -- it will still kick in eventually. + +public: + inline explicit ReadLimiter(); // No limit. + inline explicit ReadLimiter(WordCount64 limit); // Limit to the given number of words. + + KJ_ALWAYS_INLINE(bool canRead(WordCount64 amount, Arena* arena)); + + void unread(WordCount64 amount); + // Adds back some words to the limit. Useful when the caller knows they are double-reading + // some data. + +private: + alignas(8) volatile uint64_t limit; + // Current limit, decremented each time catRead() is called. We modify this variable using atomics + // with "relaxed" thread safety to make TSAN happy (on ARM & x86 this is no different from a + // regular read/write of the variable). See the class comment for why this is OK (previously we + // used a regular volatile variable - this is just to make ASAN happy). + // + // alignas(8) is the default on 64-bit systems, but needed on 32-bit to avoid an expensive + // unaligned atomic operation. + + KJ_DISALLOW_COPY_AND_MOVE(ReadLimiter); + + KJ_ALWAYS_INLINE(void setLimit(uint64_t newLimit)) { +#if defined(__GNUC__) || defined(__clang__) + __atomic_store_n(&limit, newLimit, __ATOMIC_RELAXED); +#else + limit = newLimit; +#endif + } + + KJ_ALWAYS_INLINE(uint64_t readLimit() const) { +#if defined(__GNUC__) || defined(__clang__) + return __atomic_load_n(&limit, __ATOMIC_RELAXED); +#else + return limit; +#endif + } +}; + +class SegmentReader { +public: + inline SegmentReader(Arena* arena, SegmentId id, const word* ptr, SegmentWordCount size, + ReadLimiter* readLimiter); + + KJ_ALWAYS_INLINE(const word* checkOffset(const word* from, ptrdiff_t offset)); + // Adds the given offset to the given pointer, checks that it is still within the bounds of the + // segment, then returns it. Note that the "end" pointer of the segment (which technically points + // to the word after the last in the segment) is considered in-bounds for this purpose, so you + // can't necessarily dereference it. You must call checkObject() next to check that the object + // you want to read is entirely in-bounds. + // + // If `from + offset` is out-of-range, this returns a pointer to the end of the segment. Thus, + // any non-zero-sized object will fail `checkObject()`. We do this instead of throwing to save + // some code footprint. + + KJ_ALWAYS_INLINE(bool checkObject(const word* start, WordCountN<31> size)); + // Assuming that `start` is in-bounds for this segment (probably checked using `checkOffset()`), + // check that `start + size` is also in-bounds, and hence the whole area in-between is valid. + + KJ_ALWAYS_INLINE(bool amplifiedRead(WordCount virtualAmount)); + // Indicates that the reader should pretend that `virtualAmount` additional data was read even + // though no actual pointer was traversed. This is used e.g. when reading a struct list pointer + // where the element sizes are zero -- the sender could set the list size arbitrarily high and + // cause the receiver to iterate over this list even though the message itself is small, so we + // need to defend against DoS attacks based on this. + + inline Arena* getArena(); + inline SegmentId getSegmentId(); + + inline const word* getStartPtr(); + inline SegmentWordCount getOffsetTo(const word* ptr); + inline SegmentWordCount getSize(); + + inline kj::ArrayPtr getArray(); + + inline void unread(WordCount64 amount); + // Add back some words to the ReadLimiter. + +private: + Arena* arena; + SegmentId id; + kj::ArrayPtr ptr; // size guaranteed to fit in SEGMENT_WORD_COUNT_BITS bits + ReadLimiter* readLimiter; + + KJ_DISALLOW_COPY_AND_MOVE(SegmentReader); + + friend class SegmentBuilder; + + [[noreturn]] static void abortCheckObjectFault(); + // Called in debug mode in cases that would segfault in opt mode. (Should be impossible!) +}; + +class SegmentBuilder: public SegmentReader { +public: + inline SegmentBuilder(BuilderArena* arena, SegmentId id, word* ptr, SegmentWordCount size, + ReadLimiter* readLimiter); + inline SegmentBuilder(BuilderArena* arena, SegmentId id, decltype(nullptr), + ReadLimiter* readLimiter); + + KJ_ALWAYS_INLINE(word* allocate(SegmentWordCount amount)); + + KJ_ALWAYS_INLINE(word* getPtrUnchecked(SegmentWordCount offset)); + // Get a writable pointer into the segment. + + inline BuilderArena* getArena(); + + inline kj::ArrayPtr currentlyAllocated(); + +private: + word* pos; + // Pointer to a pointer to the current end point of the segment, i.e. the location where the + // next object should be allocated. + + KJ_DISALLOW_COPY_AND_MOVE(SegmentBuilder); +}; + +class Arena { +public: + virtual ~Arena() noexcept(false); + + virtual SegmentReader* tryGetSegment(SegmentId id) = 0; + // Gets the segment with the given ID, or return nullptr if no such segment exists. + + virtual void reportReadLimitReached() = 0; + // Called to report that the read limit has been reached. See ReadLimiter, below. This invokes + // the VALIDATE_INPUT() macro which may throw an exception; if it returns normally, the caller + // will need to continue with default values. +}; + +class ReaderArena final: public Arena { +public: + explicit ReaderArena(MessageReader* message); + ~ReaderArena() noexcept(false); + KJ_DISALLOW_COPY_AND_MOVE(ReaderArena); + + // implements Arena ------------------------------------------------ + SegmentReader* tryGetSegment(SegmentId id) override; + void reportReadLimitReached() override; + +private: + MessageReader* message; + ReadLimiter readLimiter; + + // Optimize for single-segment messages so that small messages are handled quickly. + SegmentReader segment0; + + typedef kj::HashMap> SegmentMap; + kj::MutexGuarded> moreSegments; + // We need to mutex-guard the segment map because we lazily initialize segments when they are + // first requested, but a Reader is allowed to be used concurrently in multiple threads. Luckily + // this only applies to large messages. + // + // TODO(perf): Thread-local thing instead? Some kind of lockless map? Or do sharing of data + // in a different way, where you have to construct a new MessageReader in each thread (but + // possibly backed by the same data)? + + ReaderArena(MessageReader* message, kj::ArrayPtr firstSegment); + ReaderArena(MessageReader* message, const word* firstSegment, SegmentWordCount firstSegmentSize); +}; + +class BuilderArena final: public Arena { + // A BuilderArena that does not allow the injection of capabilities. + +public: + explicit BuilderArena(MessageBuilder* message); + ~BuilderArena() noexcept(false); + KJ_DISALLOW_COPY_AND_MOVE(BuilderArena); + + inline SegmentBuilder* getRootSegment() { return &segment0; } + + kj::ArrayPtr> getSegmentsForOutput(); + // Get an array of all the segments, suitable for writing out. This only returns the allocated + // portion of each segment, whereas tryGetSegment() returns something that includes + // not-yet-allocated space. + + SegmentBuilder* getSegment(SegmentId id); + // Get the segment with the given id. Crashes or throws an exception if no such segment exists. + + struct AllocateResult { + SegmentBuilder* segment; + word* words; + }; + + AllocateResult allocate(SegmentWordCount amount); + // Find a segment with at least the given amount of space available and allocate the space. + // Note that allocating directly from a particular segment is much faster, but allocating from + // the arena is guaranteed to succeed. Therefore callers should try to allocate from a specific + // segment first if there is one, then fall back to the arena. + + // implements Arena ------------------------------------------------ + SegmentReader* tryGetSegment(SegmentId id) override; + void reportReadLimitReached() override; + +private: + MessageBuilder* message; + ReadLimiter dummyLimiter; + + SegmentBuilder segment0; + kj::ArrayPtr segment0ForOutput; + + struct MultiSegmentState { + kj::Vector> builders; + kj::Vector> forOutput; + }; + kj::Maybe> moreSegments; + + SegmentBuilder* segmentWithSpace = nullptr; + // When allocating, look for space in this segment first before resorting to allocating a new + // segment. + + SegmentBuilder* addSegmentInternal(kj::ArrayPtr content); +}; + +// ======================================================================================= + +inline ReadLimiter::ReadLimiter() + : limit(kj::maxValue) {} + +inline ReadLimiter::ReadLimiter(WordCount64 limit): limit(unbound(limit / WORDS)) {} + +inline bool ReadLimiter::canRead(WordCount64 amount, Arena* arena) { + // Be careful not to store an underflowed value into `limit`, even if multiple threads are + // decrementing it. + uint64_t current = readLimit(); + if (KJ_UNLIKELY(unbound(amount / WORDS) > current)) { + arena->reportReadLimitReached(); + return false; + } else { + setLimit(current - unbound(amount / WORDS)); + return true; + } +} + +// ------------------------------------------------------------------- + +inline SegmentReader::SegmentReader(Arena* arena, SegmentId id, const word* ptr, + SegmentWordCount size, ReadLimiter* readLimiter) + : arena(arena), id(id), ptr(kj::arrayPtr(ptr, unbound(size / WORDS))), + readLimiter(readLimiter) {} + +inline const word* SegmentReader::checkOffset(const word* from, ptrdiff_t offset) { + ptrdiff_t min = ptr.begin() - from; + ptrdiff_t max = ptr.end() - from; + if (offset >= min && offset <= max) { + return from + offset; + } else { + return ptr.end(); + } +} + +inline bool SegmentReader::checkObject(const word* start, WordCountN<31> size) { + auto startOffset = intervalLength(ptr.begin(), start, MAX_SEGMENT_WORDS); +#ifdef KJ_DEBUG + if (startOffset > bounded(ptr.size()) * WORDS) { + abortCheckObjectFault(); + } +#endif + return startOffset + size <= bounded(ptr.size()) * WORDS && + readLimiter->canRead(size, arena); +} + +inline bool SegmentReader::amplifiedRead(WordCount virtualAmount) { + return readLimiter->canRead(virtualAmount, arena); +} + +inline Arena* SegmentReader::getArena() { return arena; } +inline SegmentId SegmentReader::getSegmentId() { return id; } +inline const word* SegmentReader::getStartPtr() { return ptr.begin(); } +inline SegmentWordCount SegmentReader::getOffsetTo(const word* ptr) { + KJ_IREQUIRE(this->ptr.begin() <= ptr && ptr <= this->ptr.end()); + return intervalLength(this->ptr.begin(), ptr, MAX_SEGMENT_WORDS); +} +inline SegmentWordCount SegmentReader::getSize() { + return assumeBits(ptr.size()) * WORDS; +} +inline kj::ArrayPtr SegmentReader::getArray() { return ptr; } +inline void SegmentReader::unread(WordCount64 amount) { readLimiter->unread(amount); } + +// ------------------------------------------------------------------- + +inline SegmentBuilder::SegmentBuilder( + BuilderArena* arena, SegmentId id, word* ptr, SegmentWordCount size, + ReadLimiter* readLimiter) + : SegmentReader(arena, id, ptr, size, readLimiter), + pos(ptr) {} +inline SegmentBuilder::SegmentBuilder(BuilderArena* arena, SegmentId id, decltype(nullptr), + ReadLimiter* readLimiter) + : SegmentReader(arena, id, nullptr, ZERO * WORDS, readLimiter), + pos(nullptr) {} + +inline word* SegmentBuilder::allocate(SegmentWordCount amount) { + if (intervalLength(pos, ptr.end(), MAX_SEGMENT_WORDS) < amount) { + // Not enough space in the segment for this allocation. + return nullptr; + } else { + // Success. + word* result = pos; + pos = pos + amount; + return result; + } +} + +inline word* SegmentBuilder::getPtrUnchecked(SegmentWordCount offset) { + return const_cast(ptr.begin() + offset); +} + +inline BuilderArena* SegmentBuilder::getArena() { + // Down-cast safe because SegmentBuilder's constructor always initializes its SegmentReader base + // class with an Arena pointer that actually points to a BuilderArena. + return static_cast(arena); +} + +inline kj::ArrayPtr SegmentBuilder::currentlyAllocated() { + return kj::arrayPtr(ptr.begin(), pos - ptr.begin()); +} + +} // namespace _ (private) +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/blob.c++ b/vendor/capnproto/src/capnp/blob.c++ new file mode 100644 index 0000000..d31aaa3 --- /dev/null +++ b/vendor/capnproto/src/capnp/blob.c++ @@ -0,0 +1,28 @@ +// 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 "blob.h" + +namespace capnp { + +char Text::Builder::nulstr[1] = ""; + +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/blob.h b/vendor/capnproto/src/capnp/blob.h new file mode 100644 index 0000000..715f490 --- /dev/null +++ b/vendor/capnproto/src/capnp/blob.h @@ -0,0 +1,221 @@ +// 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. + +#pragma once + +#include +#include +#include "common.h" +#include + +CAPNP_BEGIN_HEADER + +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 { + // 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(nullptr) {} + inline Reader(const byte* value, size_t size): ArrayPtr(value, size) {} + inline Reader(const kj::Array& value): ArrayPtr(value) {} + inline Reader(const ArrayPtr& value): ArrayPtr(value) {} + inline Reader(const kj::Array& value): ArrayPtr(value) {} + inline Reader(const ArrayPtr& value): ArrayPtr(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 = kj::EnableIf().c_str()), const char*>()>> + 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 { + // Like Data::Reader except the pointers aren't const. + +public: + typedef Data Builds; + + Builder() = default; + inline Builder(decltype(nullptr)): ArrayPtr(nullptr) {} + inline Builder(byte* value, size_t size): ArrayPtr(value, size) {} + inline Builder(kj::Array& value): ArrayPtr(value) {} + inline Builder(ArrayPtr value): ArrayPtr(value) {} + + inline Data::Reader asReader() const { + return Data::Reader(kj::implicitCast&>(*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(); + inline kj::ArrayPtr asArray(); + inline operator kj::ArrayPtr() const; + inline kj::ArrayPtr asArray() const; + inline kj::ArrayPtr asBytes() { return asArray().asBytes(); } + inline kj::ArrayPtr 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 slice(size_t start, size_t end) const; + inline Builder slice(size_t start); + inline kj::ArrayPtr 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 content): content(content) {} + + kj::ArrayPtr 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 b.asString() == a; } +inline bool operator!=(const char* a, const Text::Builder& b) { return b.asString() != a; } + +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() { + return content.slice(0, content.size() - 1); +} + +inline kj::ArrayPtr Text::Builder::asArray() { + return content.slice(0, content.size() - 1); +} + +inline Text::Builder::operator kj::ArrayPtr() const { + return content.slice(0, content.size() - 1); +} + +inline kj::ArrayPtr 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 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 Text::Builder::slice(size_t start, size_t end) { + return content.slice(start, end); +} + +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/common.h b/vendor/capnproto/src/capnp/common.h new file mode 100644 index 0000000..5a3e659 --- /dev/null +++ b/vendor/capnproto/src/capnp/common.h @@ -0,0 +1,684 @@ +// 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. + +#pragma once + +#include +#include +#include + +#if CAPNP_DEBUG_TYPES +#include +#endif + +#if !defined(CAPNP_HEADER_WARNINGS) || !CAPNP_HEADER_WARNINGS +#define CAPNP_BEGIN_HEADER KJ_BEGIN_SYSTEM_HEADER +#define CAPNP_END_HEADER KJ_END_SYSTEM_HEADER +#else +#define CAPNP_BEGIN_HEADER +#define CAPNP_END_HEADER +#endif + +CAPNP_BEGIN_HEADER + +namespace capnp { + +#define CAPNP_VERSION_MAJOR 1 +#define CAPNP_VERSION_MINOR 4 +#define CAPNP_VERSION_MICRO 0 + +#define CAPNP_VERSION \ + (CAPNP_VERSION_MAJOR * 1000000 + CAPNP_VERSION_MINOR * 1000 + CAPNP_VERSION_MICRO) + + +#if CAPNP_TESTING_CAPNP // defined in Cap'n Proto's own unit tests; others should not define this +#define CAPNP_DEPRECATED(reason) +#else +#define CAPNP_DEPRECATED KJ_DEPRECATED +#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 +struct EnumInfo; + +} // namespace schemas + +namespace _ { // private + +template struct Kind_; + +template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::BLOB; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::BLOB; }; + +template struct Kind_> { + static constexpr Kind kind = Kind::STRUCT; +}; +template struct Kind_> { + static constexpr Kind kind = Kind::INTERFACE; +}; +template struct Kind_::IsEnum>> { + static constexpr Kind kind = Kind::ENUM; +}; + +} // namespace _ (private) + +template ::kind> +inline constexpr Kind kind() { + // This overload of kind() matches types which have a Kind_ specialization. + + return k; +} + + +#define CAPNP_KIND(T) ::capnp::kind() +// Use this macro rather than kind() in any code which must work in MSVC. + + + +template ()> +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; +} + + +template +struct List; + + +template struct ListElementType_; +template struct ListElementType_> { typedef T Type; }; +template using ListElementType = typename ListElementType_::Type; + +namespace _ { // private +template struct Kind_> { + static constexpr Kind kind = Kind::LIST; +}; +} // namespace _ (private) + +template struct ReaderFor_ { typedef typename T::Reader Type; }; +template struct ReaderFor_ { typedef T Type; }; +template struct ReaderFor_ { typedef T Type; }; +template using ReaderFor = typename ReaderFor_::Type; +// The type returned by List::Reader::operator[]. + +template struct BuilderFor_ { typedef typename T::Builder Type; }; +template struct BuilderFor_ { typedef T Type; }; +template struct BuilderFor_ { typedef T Type; }; +template using BuilderFor = typename BuilderFor_::Type; +// The type returned by List::Builder::operator[]. + +template struct TypeIfEnum_; +template struct TypeIfEnum_ { typedef T Type; }; + +template +using TypeIfEnum = typename TypeIfEnum_>::Type; + +template +using FromReader = typename kj::Decay::Reads; +// FromReader = MyType (for any Cap'n Proto type). + +template +using FromBuilder = typename kj::Decay::Builds; +// FromBuilder = MyType (for any Cap'n Proto type). + +template +struct FromAny_; + +template +struct FromAny_>> { + using Type = FromReader; +}; + +template +struct FromAny_>> { + using Type = FromBuilder; +}; + +template +struct FromAny_::kind == Kind::PRIMITIVE || _::Kind_::kind == Kind::ENUM>> { + // TODO(msvc): Ideally the EnableIf condition would be `style() == Style::PRIMITIVE`, but MSVC + // cannot yet use style() in this constexpr context. + + using Type = kj::Decay; +}; + +template +using FromAny = typename FromAny_::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 +// uint32_t -> uint32_t + +namespace _ { // private + +template +struct PointerHelpers; + + +} // namespace _ (private) + +struct MessageSize { + // Size of a message. Every struct and list type has a method `.totalSize()` that returns this. + uint64_t wordCount; + uint capCount; + + inline constexpr MessageSize operator+(const MessageSize& other) const { + return { wordCount + other.wordCount, capCount + other.capCount }; + } +}; + +// ======================================================================================= +// Raw memory types and measures + +using kj::byte; + +class word { + // 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. +public: + word() = default; +private: + uint64_t content KJ_UNUSED_MEMBER; +#if __GNUC__ < 8 || __clang__ + // GCC 8's -Wclass-memaccess complains whenever we try to memcpy() a `word` if we've disallowed + // the copy constructor. We don't want to disable the warning because it's a useful warning and + // we'd have to disable it for all applications that include this header. Instead we allow `word` + // to be copyable on GCC. + KJ_DISALLOW_COPY_AND_MOVE(word); +#endif +}; + +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 +using BitCountN = kj::Quantity(), T>, _::BitLabel>; +template +using ByteCountN = kj::Quantity(), T>, byte>; +template +using WordCountN = kj::Quantity(), T>, word>; +template +using ElementCountN = kj::Quantity(), T>, _::ElementLabel>; +template +using WirePointerCountN = kj::Quantity(), 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 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 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 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 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 WirePointerCount; + +template +using BitsPerElementN = decltype(BitCountN() / ElementCountN()); +template +using BytesPerElementN = decltype(ByteCountN() / ElementCountN()); +template +using WordsPerElementN = decltype(WordCountN() / ElementCountN()); +template +using PointersPerElementN = decltype(WirePointerCountN() / ElementCountN()); + +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 +inline constexpr U* operator+(U* ptr, kj::Quantity offset) { + return ptr + unbound(offset / kj::unit>()); +} +template +inline constexpr const U* operator+(const U* ptr, kj::Quantity offset) { + return ptr + unbound(offset / kj::unit>()); +} +template +inline constexpr U* operator+=(U*& ptr, kj::Quantity offset) { + return ptr = ptr + unbound(offset / kj::unit>()); +} +template +inline constexpr const U* operator+=(const U*& ptr, kj::Quantity offset) { + return ptr = ptr + unbound(offset / kj::unit>()); +} + +template +inline constexpr U* operator-(U* ptr, kj::Quantity offset) { + return ptr - unbound(offset / kj::unit>()); +} +template +inline constexpr const U* operator-(const U* ptr, kj::Quantity offset) { + return ptr - unbound(offset / kj::unit>()); +} +template +inline constexpr U* operator-=(U*& ptr, kj::Quantity offset) { + return ptr = ptr - unbound(offset / kj::unit>()); +} +template +inline constexpr const U* operator-=(const U*& ptr, kj::Quantity offset) { + return ptr = ptr - unbound(offset / kj::unit>()); +} + +constexpr auto BITS = kj::unit>(); +constexpr auto BYTES = kj::unit>(); +constexpr auto WORDS = kj::unit>(); +constexpr auto ELEMENTS = kj::unit>(); +constexpr auto POINTERS = kj::unit>(); + +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 SegmentWordCount; +typedef ElementCountN ListElementCount; +typedef WordCountN StructDataWordCount; +typedef WirePointerCountN StructPointerCount; +typedef ByteCountN BlobSize; + +constexpr auto MAX_SEGMENT_WORDS = + bounded()>() * WORDS; +constexpr auto MAX_LIST_ELEMENTS = + bounded()>() * ELEMENTS; +constexpr auto MAX_STUCT_DATA_WORDS = + bounded()>() * WORDS; +constexpr auto MAX_STRUCT_POINTER_COUNT = + bounded()>() * POINTERS; + +using StructDataBitCount = decltype(WordCountN() * 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() - 1; +typedef kj::Quantity, byte> TextSize; +// Not including NUL terminator. + +template +inline KJ_CONSTEXPR() decltype(bounded() * BYTES / ELEMENTS) bytesPerElement() { + return bounded() * BYTES / ELEMENTS; +} + +template +inline KJ_CONSTEXPR() decltype(bounded() * BITS / ELEMENTS) bitsPerElement() { + return bounded() * BITS / ELEMENTS; +} + +template +inline constexpr kj::Quantity, T> +intervalLength(const T* a, const T* b, kj::Quantity, T>) { + return kj::assumeMax(b - a) * kj::unit, T>>(); +} + +template +inline constexpr kj::ArrayPtr arrayPtr(const U* ptr, kj::Quantity size) { + return kj::ArrayPtr(ptr, unbound(size / kj::unit>())); +} +template +inline constexpr kj::ArrayPtr arrayPtr(U* ptr, kj::Quantity size) { + return kj::ArrayPtr(ptr, unbound(size / kj::unit>())); +} + +#else + +template +using BitCountN = T; +template +using ByteCountN = T; +template +using WordCountN = T; +template +using ElementCountN = T; +template +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 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 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 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 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 WirePointerCount; + +template +using BitsPerElementN = decltype(BitCountN() / ElementCountN()); +template +using BytesPerElementN = decltype(ByteCountN() / ElementCountN()); +template +using WordsPerElementN = decltype(WordCountN() / ElementCountN()); +template +using PointersPerElementN = decltype(WirePointerCountN() / ElementCountN()); + +using kj::ThrowOverflow; +// YYY + +template inline constexpr uint bounded() { return i; } +template inline constexpr T bounded(T i) { return i; } +template inline constexpr T unbound(T i) { return i; } + +template inline constexpr T unboundAs(U i) { return i; } + +template inline constexpr uint unboundMax(T i) { return i; } +template inline constexpr uint unboundMaxBits(T i) { return i; } + +template +inline T assertMax(T value, ErrorFunc&& func) { + if (KJ_UNLIKELY(value > newMax)) func(); + return value; +} + +template +inline T assertMax(uint newMax, T value, ErrorFunc&& func) { + if (KJ_UNLIKELY(value > newMax)) func(); + return value; +} + +template +inline T assertMaxBits(T value, ErrorFunc&& func = ErrorFunc()) { + if (KJ_UNLIKELY(value > kj::maxValueForBits())) func(); + return value; +} + +template +inline T assertMaxBits(uint bits, T value, ErrorFunc&& func = ErrorFunc()) { + if (KJ_UNLIKELY(value > (1ull << bits) - 1)) func(); + return value; +} + +template inline constexpr T upgradeBound(U i) { return i; } + +template inline constexpr T assumeBits(T i) { return i; } +template inline constexpr T assumeMax(T i) { return i; } + +template +inline auto subtractChecked(T a, U b, ErrorFunc&& errorFunc = ErrorFunc()) + -> decltype(a - b) { + if (b > a) errorFunc(); + return a - b; +} + +template +inline auto trySubtract(T a, U b) -> kj::Maybe { + 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 SegmentWordCount; +typedef ElementCountN ListElementCount; +typedef WordCountN StructDataWordCount; +typedef WirePointerCountN StructPointerCount; +typedef ByteCountN BlobSize; +// YYY + +constexpr auto MAX_SEGMENT_WORDS = kj::maxValueForBits(); +constexpr auto MAX_LIST_ELEMENTS = kj::maxValueForBits(); +constexpr auto MAX_STUCT_DATA_WORDS = kj::maxValueForBits(); +constexpr auto MAX_STRUCT_POINTER_COUNT = kj::maxValueForBits(); + +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() - 1; +typedef uint TextSize; + +template +inline KJ_CONSTEXPR() size_t bytesPerElement() { return sizeof(T); } + +template +inline KJ_CONSTEXPR() size_t bitsPerElement() { return sizeof(T) * 8; } + +template +inline constexpr ptrdiff_t intervalLength(const T* a, const T* b, uint) { + return b - a; +} + +template +inline constexpr kj::ArrayPtr arrayPtr(const U* ptr, T size) { + return kj::arrayPtr(ptr, size); +} +template +inline constexpr kj::ArrayPtr arrayPtr(U* ptr, T size) { + return kj::arrayPtr(ptr, size); +} + +#endif + +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/compat/std-iterator.h b/vendor/capnproto/src/capnp/compat/std-iterator.h new file mode 100644 index 0000000..aac249d --- /dev/null +++ b/vendor/capnproto/src/capnp/compat/std-iterator.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. + +#pragma once + +// This exposes IndexingIterator as something compatible with std::iterator so that things like +// std::copy work with List::begin/List::end. + +// Make sure that if this header is before list.h by the user it includes it to make +// IndexingIterator visible to avoid brittle header problems. +#include "../list.h" +#include + +CAPNP_BEGIN_HEADER + +namespace std { + +template +struct iterator_traits> { + using iterator_category = std::random_access_iterator_tag; + using value_type = Element; + using difference_type = int; + using pointer = Element*; + using reference = Element; +}; + +} // namespace std + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/compiler/compiler.c++ b/vendor/capnproto/src/capnp/compiler/compiler.c++ new file mode 100644 index 0000000..538a954 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/compiler.c++ @@ -0,0 +1,1126 @@ +// 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 "compiler.h" +#include "parser.h" // only for generateChildId() +#include +#include +#include +#include +#include +#include +#include +#include "node-translator.h" + +namespace capnp { +namespace compiler { + +class Compiler::Alias { +public: + Alias(CompiledModule& module, Node& parent, const Expression::Reader& targetName) + : module(module), parent(parent), targetName(targetName) {} + + kj::Maybe compile(); + +private: + CompiledModule& module; + Node& parent; + Expression::Reader targetName; + kj::Maybe target; + Orphan brandOrphan; + bool initialized = false; +}; + +class Compiler::Node final: public Resolver { + // Passes through four states: + // - Stub: On initial construction, the Node is just a placeholder object. Its ID has been + // determined, and it is placed in its parent's member table as well as the compiler's + // nodes-by-ID table. + // - Expanded: Nodes have been constructed for all of this Node's nested children. This happens + // the first time a lookup is performed for one of those children. + // - Bootstrap: A NodeTranslator has been built and advanced to the bootstrap phase. + // - Finished: A final Schema object has been constructed. + +public: + explicit Node(CompiledModule& module); + // Create a root node representing the given file. May + + Node(Node& parent, const Declaration::Reader& declaration); + // Create a child node. + + Node(kj::StringPtr name, Declaration::Which kind, + List::Reader genericParams); + // Create a dummy node representing a built-in declaration, like "Int32" or "true". + + uint64_t getId() { return id; } + uint getParameterCount() { return genericParamCount; } + Declaration::Which getKind() { return kind; } + + kj::Maybe getBootstrapSchema(); + kj::Maybe getFinalSchema(); + void loadFinalSchema(const SchemaLoader& loader); + + void traverse(uint eagerness, std::unordered_map& seen, + const SchemaLoader& finalLoader); + // Get the final schema for this node, and also possibly traverse the node's children and + // dependencies to ensure that they are loaded, depending on the mode. + + void addError(kj::StringPtr error); + // Report an error on this Node. + + // implements Resolver --------------------------------------------- + kj::Maybe resolve(kj::StringPtr name) override; + kj::Maybe resolveMember(kj::StringPtr name) override; + ResolvedDecl resolveBuiltin(Declaration::Which which) override; + ResolvedDecl resolveId(uint64_t id) override; + kj::Maybe getParent() override; + ResolvedDecl getTopScope() override; + kj::Maybe resolveBootstrapSchema( + uint64_t id, schema::Brand::Reader brand) override; + kj::Maybe resolveFinalSchema(uint64_t id) override; + kj::Maybe resolveImport(kj::StringPtr name) override; + kj::Maybe> readEmbed(kj::StringPtr name) override; + kj::Maybe resolveBootstrapType(schema::Type::Reader type, Schema scope) override; + +private: + CompiledModule* module; // null iff isBuiltin is true + kj::Maybe parent; + + Declaration::Reader declaration; + // AST of the declaration parsed from the schema file. May become invalid once the content + // state has reached FINISHED. + + uint64_t id; + // The ID of this node, either taken from the AST or computed based on the parent. Or, a dummy + // value, if duplicates were detected. + + kj::StringPtr displayName; + // Fully-qualified display name for this node. For files, this is just the file name, otherwise + // it is "filename:Path.To.Decl". + + Declaration::Which kind; + // Kind of node. + + uint genericParamCount; + // Number of generic parameters. + + bool isBuiltin; + // Whether this is a bulit-in declaration, like "Int32" or "true". + + uint32_t startByte; + uint32_t endByte; + // Start and end byte for reporting general errors. + + struct Content { + inline Content(): state(STUB) {} + + enum State { + STUB, + EXPANDED, + BOOTSTRAP, + FINISHED + }; + State state; + // Indicates which fields below are valid. + + inline bool stateHasReached(State minimumState) { + return state >= minimumState; + } + inline void advanceState(State newState) { + state = newState; + } + + // EXPANDED ------------------------------------ + + typedef std::multimap> NestedNodesMap; + NestedNodesMap nestedNodes; + kj::Vector orderedNestedNodes; + // multimap in case of duplicate member names -- we still want to compile them, even if it's an + // error. + + typedef std::multimap> AliasMap; + AliasMap aliases; + // The "using" declarations. These are just links to nodes elsewhere. + + // BOOTSTRAP ----------------------------------- + + NodeTranslator* translator; + // Node translator, allocated in the bootstrap arena. + + kj::Maybe bootstrapSchema; + // The schema built in the bootstrap loader. Null if the bootstrap loader threw an exception. + + // FINISHED ------------------------------------ + + kj::Maybe finalSchema; + // The completed schema, ready to load into the real schema loader. + + kj::Array auxSchemas; + // Schemas for all auxiliary nodes built by the NodeTranslator. + + // All source info structs as built by the NodeTranslator. + }; + + Content guardedContent; // Read using getContent() only! + bool inGetContent = false; // True while getContent() is running; detects cycles. + + kj::Maybe loadedFinalSchema; + // Copy of `finalSchema` as loaded into the final schema loader. This doesn't go away if the + // workspace is destroyed. + + // --------------------------------------------- + + static uint64_t generateId(uint64_t parentId, kj::StringPtr declName, + Declaration::Id::Reader declId); + // Extract the ID from the declaration, or if it has none, generate one based on the name and + // parent ID. + + static kj::StringPtr joinDisplayName(kj::Arena& arena, Node& parent, kj::StringPtr declName); + // Join the parent's display name with the child's unqualified name to construct the child's + // display name. + + kj::Maybe getContent(Content::State minimumState); + // Advances the content to at least the given state and returns it. Returns null if getContent() + // is being called recursively and the given state has not yet been reached, as this indicates + // that the declaration recursively depends on itself. + + void traverseNodeDependencies(const schema::Node::Reader& schemaNode, uint eagerness, + std::unordered_map& seen, + const SchemaLoader& finalLoader); + void traverseType(const schema::Type::Reader& type, uint eagerness, + std::unordered_map& seen, + const SchemaLoader& finalLoader); + void traverseBrand(const schema::Brand::Reader& brand, uint eagerness, + std::unordered_map& seen, + const SchemaLoader& finalLoader); + void traverseAnnotations(const List::Reader& annotations, uint eagerness, + std::unordered_map& seen, + const SchemaLoader& finalLoader); + void traverseDependency(uint64_t depId, uint eagerness, + std::unordered_map& seen, + const SchemaLoader& finalLoader); + // Helpers for traverse(). +}; + +class Compiler::CompiledModule { +public: + CompiledModule(Compiler::Impl& compiler, Module& parserModule); + + Compiler::Impl& getCompiler() { return compiler; } + + ErrorReporter& getErrorReporter() { return parserModule; } + ParsedFile::Reader getParsedFile() { return content.getReader(); } + Node& getRootNode() { return rootNode; } + kj::StringPtr getSourceName() { return parserModule.getSourceName(); } + + kj::Maybe importRelative(kj::StringPtr importPath); + kj::Maybe> embedRelative(kj::StringPtr importPath); + + +private: + Compiler::Impl& compiler; + Module& parserModule; + MallocMessageBuilder contentArena; + Orphan content; + Node rootNode; +}; + +class Compiler::Impl: public SchemaLoader::LazyLoadCallback { +public: + Impl(); + virtual ~Impl() noexcept(false); + + kj::Maybe lookup(uint64_t parent, kj::StringPtr childName); + void eagerlyCompile(uint64_t id, uint eagerness, const SchemaLoader& loader); + CompiledModule& addInternal(Module& parsedModule); + + struct Workspace { + // Scratch space where stuff can be allocated while working. The Workspace is available + // whenever nodes are actively being compiled, then is destroyed once control exits the + // compiler. Note that since nodes are compiled lazily, a new Workspace may have to be + // constructed in order to compile more nodes later. + + MallocMessageBuilder message; + Orphanage orphanage; + // Orphanage for allocating temporary Cap'n Proto objects. + + kj::Arena arena; + // Arena for allocating temporary native objects. Note that objects in `arena` may contain + // pointers into `message` that will be manipulated on destruction, so `arena` must be declared + // after `message`. + + SchemaLoader bootstrapLoader; + // Loader used to load bootstrap schemas. The bootstrap schema nodes are similar to the final + // versions except that any value expressions which depend on knowledge of other types (e.g. + // default values for struct fields) are left unevaluated (the values in the schema are empty). + // These bootstrap schemas can then be plugged into the dynamic API and used to evaluate these + // remaining values. + + inline explicit Workspace(const SchemaLoader::LazyLoadCallback& loaderCallback) + : orphanage(message.getOrphanage()), + bootstrapLoader(loaderCallback) {} + }; + + kj::Arena& getNodeArena() { return nodeArena; } + // Arena where nodes and other permanent objects should be allocated. + + Workspace& getWorkspace() { return workspace; } + // Temporary workspace that can be used to construct bootstrap objects. + + void clearWorkspace(); + // Reset the temporary workspace. + + uint64_t addNode(uint64_t desiredId, Node& node); + // Add the given node to the by-ID map under the given ID. If another node with the same ID + // already exists, choose a new one arbitrarily and use that instead. Return the ID that was + // finally used. + + kj::Maybe findNode(uint64_t id); + + kj::Maybe lookupBuiltin(kj::StringPtr name); + Node& getBuiltin(Declaration::Which which); + + void load(const SchemaLoader& loader, uint64_t id) const override; + // SchemaLoader callback for the bootstrap loader. + + void loadFinal(const SchemaLoader& loader, uint64_t id); + // Called from the SchemaLoader callback for the final loader. + +private: + kj::Arena nodeArena; + // Arena used to allocate nodes and other permanent objects. + + std::unordered_map> modules; + // Map of parser modules to compiler modules. + + Workspace workspace; + // The temporary workspace. This field must be declared after `modules` because objects + // allocated in the workspace may hold references to the compiled modules in `modules`. + + std::unordered_map nodesById; + // Map of nodes by ID. + + std::map> builtinDecls; + std::map builtinDeclsByKind; + // Map of built-in declarations, like "Int32" and "List", which make up the global scope. + + uint64_t nextBogusId = 1000; + // Counter for assigning bogus IDs to nodes whose real ID is a duplicate. +}; + +// ======================================================================================= + +kj::Maybe Compiler::Alias::compile() { + if (!initialized) { + initialized = true; + + auto& workspace = module.getCompiler().getWorkspace(); + brandOrphan = workspace.orphanage.newOrphan(); + + // If the Workspace is destroyed, revert the alias to the uninitialized state, because the + // orphan we created is no longer valid in this case. + workspace.arena.copy(kj::defer([this]() { + initialized = false; + brandOrphan = Orphan(); + })); + + target = NodeTranslator::compileDecl( + parent.getId(), parent.getParameterCount(), parent, + module.getErrorReporter(), targetName, brandOrphan.get()); + } + + return target; +} + +// ======================================================================================= + +Compiler::Node::Node(CompiledModule& module) + : module(&module), + parent(nullptr), + declaration(module.getParsedFile().getRoot()), + id(generateId(0, declaration.getName().getValue(), declaration.getId())), + displayName(module.getSourceName()), + kind(declaration.which()), + genericParamCount(declaration.getParameters().size()), + isBuiltin(false) { + auto name = declaration.getName(); + if (name.getValue().size() > 0) { + startByte = name.getStartByte(); + endByte = name.getEndByte(); + } else { + startByte = declaration.getStartByte(); + endByte = declaration.getEndByte(); + } + + id = module.getCompiler().addNode(id, *this); +} + +Compiler::Node::Node(Node& parent, const Declaration::Reader& declaration) + : module(parent.module), + parent(parent), + declaration(declaration), + id(generateId(parent.id, declaration.getName().getValue(), declaration.getId())), + displayName(joinDisplayName(parent.module->getCompiler().getNodeArena(), + parent, declaration.getName().getValue())), + kind(declaration.which()), + genericParamCount(declaration.getParameters().size()), + isBuiltin(false) { + auto name = declaration.getName(); + if (name.getValue().size() > 0) { + startByte = name.getStartByte(); + endByte = name.getEndByte(); + } else { + startByte = declaration.getStartByte(); + endByte = declaration.getEndByte(); + } + + id = module->getCompiler().addNode(id, *this); +} + +Compiler::Node::Node(kj::StringPtr name, Declaration::Which kind, + List::Reader genericParams) + : module(nullptr), + parent(nullptr), + // It's helpful if these have unique IDs. Real type IDs can't be under 2^31 anyway. + id(1000 + static_cast(kind)), + displayName(name), + kind(kind), + genericParamCount(genericParams.size()), + isBuiltin(true), + startByte(0), + endByte(0) {} + +uint64_t Compiler::Node::generateId(uint64_t parentId, kj::StringPtr declName, + Declaration::Id::Reader declId) { + if (declId.isUid()) { + return declId.getUid().getValue(); + } + + return generateChildId(parentId, declName); +} + +kj::StringPtr Compiler::Node::joinDisplayName( + kj::Arena& arena, Node& parent, kj::StringPtr declName) { + kj::ArrayPtr result = arena.allocateArray( + parent.displayName.size() + declName.size() + 2); + + size_t separatorPos = parent.displayName.size(); + memcpy(result.begin(), parent.displayName.begin(), separatorPos); + result[separatorPos] = parent.parent == nullptr ? ':' : '.'; + memcpy(result.begin() + separatorPos + 1, declName.begin(), declName.size()); + result[result.size() - 1] = '\0'; + return kj::StringPtr(result.begin(), result.size() - 1); +} + +kj::Maybe Compiler::Node::getContent(Content::State minimumState) { + KJ_REQUIRE(!isBuiltin, "illegal method call for built-in declaration"); + + auto& content = guardedContent; + + if (content.stateHasReached(minimumState)) { + return content; + } + + if (inGetContent) { + addError("Declaration recursively depends on itself."); + return nullptr; + } + + inGetContent = true; + KJ_DEFER(inGetContent = false); + + switch (content.state) { + case Content::STUB: { + if (minimumState <= Content::STUB) break; + + // Expand the child nodes. + auto& arena = module->getCompiler().getNodeArena(); + + for (auto nestedDecl: declaration.getNestedDecls()) { + switch (nestedDecl.which()) { + case Declaration::FILE: + case Declaration::CONST: + case Declaration::ANNOTATION: + case Declaration::ENUM: + case Declaration::STRUCT: + case Declaration::INTERFACE: { + kj::Own subNode = arena.allocateOwn(*this, nestedDecl); + kj::StringPtr name = nestedDecl.getName().getValue(); + content.orderedNestedNodes.add(subNode); + content.nestedNodes.insert(std::make_pair(name, kj::mv(subNode))); + break; + } + + case Declaration::USING: { + kj::Own alias = arena.allocateOwn( + *module, *this, nestedDecl.getUsing().getTarget()); + kj::StringPtr name = nestedDecl.getName().getValue(); + content.aliases.insert(std::make_pair(name, kj::mv(alias))); + break; + } + case Declaration::ENUMERANT: + case Declaration::FIELD: + case Declaration::UNION: + case Declaration::GROUP: + case Declaration::METHOD: + case Declaration::NAKED_ID: + case Declaration::NAKED_ANNOTATION: + // Not a node. Skip. + break; + default: + KJ_FAIL_ASSERT("unknown declaration type", nestedDecl); + break; + } + } + + content.advanceState(Content::EXPANDED); + } KJ_FALLTHROUGH; + + case Content::EXPANDED: { + if (minimumState <= Content::EXPANDED) break; + + // Construct the NodeTranslator. + auto& workspace = module->getCompiler().getWorkspace(); + + auto schemaNode = workspace.orphanage.newOrphan(); + auto builder = schemaNode.get(); + builder.setId(id); + builder.setDisplayName(displayName); + // TODO(cleanup): Would be better if we could remember the prefix length from before we + // added this decl's name to the end. + KJ_IF_MAYBE(lastDot, displayName.findLast('.')) { + builder.setDisplayNamePrefixLength(*lastDot + 1); + } + KJ_IF_MAYBE(lastColon, displayName.findLast(':')) { + if (*lastColon > builder.getDisplayNamePrefixLength()) { + builder.setDisplayNamePrefixLength(*lastColon + 1); + } + } + KJ_IF_MAYBE(p, parent) { + builder.setScopeId(p->id); + } + + auto nestedNodes = builder.initNestedNodes(content.orderedNestedNodes.size()); + auto nestedIter = nestedNodes.begin(); + for (auto node: content.orderedNestedNodes) { + nestedIter->setName(node->declaration.getName().getValue()); + nestedIter->setId(node->id); + ++nestedIter; + } + + content.translator = &workspace.arena.allocate( + *this, module->getErrorReporter(), declaration, kj::mv(schemaNode)); + KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&](){ + auto nodeSet = content.translator->getBootstrapNode(); + for (auto& auxNode: nodeSet.auxNodes) { + workspace.bootstrapLoader.loadOnce(auxNode); + } + content.bootstrapSchema = workspace.bootstrapLoader.loadOnce(nodeSet.node); + })) { + content.bootstrapSchema = nullptr; + // Only bother to report validation failures if we think we haven't seen any errors. + // Otherwise we assume that the errors caused the validation failure. + if (!module->getErrorReporter().hadErrors()) { + addError(kj::str("Internal compiler bug: Bootstrap schema failed validation:\n", + *exception)); + } + } + + // If the Workspace is destroyed, revert the node to the EXPANDED state, because the + // NodeTranslator is no longer valid in this case. + workspace.arena.copy(kj::defer([&content]() { + content.bootstrapSchema = nullptr; + if (content.state > Content::EXPANDED) { + content.state = Content::EXPANDED; + } + })); + + content.advanceState(Content::BOOTSTRAP); + } KJ_FALLTHROUGH; + + case Content::BOOTSTRAP: { + if (minimumState <= Content::BOOTSTRAP) break; + + // Create the final schema. + NodeTranslator::NodeSet nodeSet; + if (content.bootstrapSchema == nullptr) { + // Must have failed in an earlier stage. + KJ_ASSERT(module->getErrorReporter().hadErrors()); + nodeSet = content.translator->getBootstrapNode(); + } else { + nodeSet = content.translator->finish( + module->getCompiler().getWorkspace().bootstrapLoader.getUnbound(id)); + } + + content.finalSchema = nodeSet.node; + content.auxSchemas = kj::mv(nodeSet.auxNodes); + + content.advanceState(Content::FINISHED); + } KJ_FALLTHROUGH; + + case Content::FINISHED: + break; + } + + return content; +} + +kj::Maybe Compiler::Node::getBootstrapSchema() { + KJ_IF_MAYBE(schema, loadedFinalSchema) { + // We don't need to rebuild the bootstrap schema if we already have a final schema. + return module->getCompiler().getWorkspace().bootstrapLoader.loadOnce(*schema); + } else KJ_IF_MAYBE(content, getContent(Content::BOOTSTRAP)) { + if (content->state == Content::FINISHED && content->bootstrapSchema == nullptr) { + // The bootstrap schema was discarded. Copy it from the final schema. + // (We can't just return the final schema because using it could trigger schema loader + // callbacks that would deadlock.) + KJ_IF_MAYBE(finalSchema, content->finalSchema) { + return module->getCompiler().getWorkspace().bootstrapLoader.loadOnce(*finalSchema); + } else { + return nullptr; + } + } else { + return content->bootstrapSchema; + } + } else { + return nullptr; + } +} +kj::Maybe Compiler::Node::getFinalSchema() { + KJ_IF_MAYBE(schema, loadedFinalSchema) { + return *schema; + } else KJ_IF_MAYBE(content, getContent(Content::FINISHED)) { + return content->finalSchema; + } else { + return nullptr; + } +} +void Compiler::Node::loadFinalSchema(const SchemaLoader& loader) { + KJ_IF_MAYBE(content, getContent(Content::FINISHED)) { + KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&](){ + KJ_IF_MAYBE(finalSchema, content->finalSchema) { + KJ_MAP(auxSchema, content->auxSchemas) { + return loader.loadOnce(auxSchema); + }; + loadedFinalSchema = loader.loadOnce(*finalSchema).getProto(); + } + })) { + // Schema validation threw an exception. + + // Don't try loading this again. + content->finalSchema = nullptr; + + // Only bother to report validation failures if we think we haven't seen any errors. + // Otherwise we assume that the errors caused the validation failure. + if (!module->getErrorReporter().hadErrors()) { + addError(kj::str("Internal compiler bug: Schema failed validation:\n", *exception)); + } + } + } +} + +void Compiler::Node::traverse(uint eagerness, std::unordered_map& seen, + const SchemaLoader& finalLoader) { + uint& slot = seen[this]; + if ((slot & eagerness) == eagerness) { + // We've already covered this node. + return; + } + slot |= eagerness; + + KJ_IF_MAYBE(content, getContent(Content::FINISHED)) { + loadFinalSchema(finalLoader); + + KJ_IF_MAYBE(schema, getFinalSchema()) { + if (eagerness / DEPENDENCIES != 0) { + // For traversing dependencies, discard the bits lower than DEPENDENCIES and replace + // them with the bits above DEPENDENCIES shifted over. + uint newEagerness = (eagerness & ~(DEPENDENCIES - 1)) | (eagerness / DEPENDENCIES); + + traverseNodeDependencies(*schema, newEagerness, seen, finalLoader); + for (auto& aux: content->auxSchemas) { + traverseNodeDependencies(aux, newEagerness, seen, finalLoader); + } + } + } + + } + + if (eagerness & PARENTS) { + KJ_IF_MAYBE(p, parent) { + p->traverse(eagerness, seen, finalLoader); + } + } + + if (eagerness & CHILDREN) { + KJ_IF_MAYBE(content, getContent(Content::EXPANDED)) { + for (auto& child: content->orderedNestedNodes) { + child->traverse(eagerness, seen, finalLoader); + } + + // Also traverse `using` declarations. + for (auto& child: content->aliases) { + child.second->compile(); + } + } + } +} + +void Compiler::Node::traverseNodeDependencies( + const schema::Node::Reader& schemaNode, uint eagerness, + std::unordered_map& seen, + const SchemaLoader& finalLoader) { + switch (schemaNode.which()) { + case schema::Node::STRUCT: + for (auto field: schemaNode.getStruct().getFields()) { + switch (field.which()) { + case schema::Field::SLOT: + traverseType(field.getSlot().getType(), eagerness, seen, finalLoader); + break; + case schema::Field::GROUP: + // Aux node will be scanned later. + break; + } + + traverseAnnotations(field.getAnnotations(), eagerness, seen, finalLoader); + } + break; + + case schema::Node::ENUM: + for (auto enumerant: schemaNode.getEnum().getEnumerants()) { + traverseAnnotations(enumerant.getAnnotations(), eagerness, seen, finalLoader); + } + break; + + case schema::Node::INTERFACE: + KJ_FAIL_REQUIRE("Interfaces are not supported."); + + case schema::Node::CONST: + traverseType(schemaNode.getConst().getType(), eagerness, seen, finalLoader); + break; + + case schema::Node::ANNOTATION: + traverseType(schemaNode.getAnnotation().getType(), eagerness, seen, finalLoader); + break; + + default: + break; + } + + traverseAnnotations(schemaNode.getAnnotations(), eagerness, seen, finalLoader); +} + +void Compiler::Node::traverseType(const schema::Type::Reader& type, uint eagerness, + std::unordered_map& seen, + const SchemaLoader& finalLoader) { + uint64_t id = 0; + schema::Brand::Reader brand; + switch (type.which()) { + case schema::Type::STRUCT: + id = type.getStruct().getTypeId(); + brand = type.getStruct().getBrand(); + break; + case schema::Type::ENUM: + id = type.getEnum().getTypeId(); + brand = type.getEnum().getBrand(); + break; + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interfaces are not supported."); + case schema::Type::LIST: + traverseType(type.getList().getElementType(), eagerness, seen, finalLoader); + return; + default: + return; + } + + traverseDependency(id, eagerness, seen, finalLoader); + traverseBrand(brand, eagerness, seen, finalLoader); +} + +void Compiler::Node::traverseBrand( + const schema::Brand::Reader& brand, uint eagerness, + std::unordered_map& seen, + const SchemaLoader& finalLoader) { + for (auto scope: brand.getScopes()) { + switch (scope.which()) { + case schema::Brand::Scope::BIND: + for (auto binding: scope.getBind()) { + switch (binding.which()) { + case schema::Brand::Binding::UNBOUND: + break; + case schema::Brand::Binding::TYPE: + traverseType(binding.getType(), eagerness, seen, finalLoader); + break; + } + } + break; + case schema::Brand::Scope::INHERIT: + break; + } + } +} + +void Compiler::Node::traverseDependency(uint64_t depId, uint eagerness, + std::unordered_map& seen, + const SchemaLoader& finalLoader) { + KJ_IF_MAYBE(node, module->getCompiler().findNode(depId)) { + node->traverse(eagerness, seen, finalLoader); + } else { + KJ_FAIL_ASSERT("Dependency ID not present in compiler?", depId); + } +} + +void Compiler::Node::traverseAnnotations(const List::Reader& annotations, + uint eagerness, + std::unordered_map& seen, + const SchemaLoader& finalLoader) { + for (auto annotation: annotations) { + KJ_IF_MAYBE(node, module->getCompiler().findNode(annotation.getId())) { + node->traverse(eagerness, seen, finalLoader); + } + } +} + + +void Compiler::Node::addError(kj::StringPtr error) { + module->getErrorReporter().addError(startByte, endByte, error); +} + +kj::Maybe +Compiler::Node::resolve(kj::StringPtr name) { + // Check members. + KJ_IF_MAYBE(member, resolveMember(name)) { + return *member; + } + + // Check parameters. + // TODO(perf): Maintain a map? + auto params = declaration.getParameters(); + for (uint i: kj::indices(params)) { + if (params[i].getName() == name) { + ResolveResult result; + result.init(ResolvedParameter {id, i}); + return result; + } + } + + // Check parent scope. + KJ_IF_MAYBE(p, parent) { + return p->resolve(name); + } else KJ_IF_MAYBE(b, module->getCompiler().lookupBuiltin(name)) { + ResolveResult result; + result.init(ResolvedDecl { b->id, b->genericParamCount, 0, b->kind, b, nullptr }); + return result; + } else { + return nullptr; + } +} + +kj::Maybe +Compiler::Node::resolveMember(kj::StringPtr name) { + if (isBuiltin) return nullptr; + + KJ_IF_MAYBE(content, getContent(Content::EXPANDED)) { + { + auto iter = content->nestedNodes.find(name); + if (iter != content->nestedNodes.end()) { + Node* node = iter->second; + ResolveResult result; + result.init(ResolvedDecl { + node->id, node->genericParamCount, id, node->kind, node, nullptr }); + return result; + } + } + { + auto iter = content->aliases.find(name); + if (iter != content->aliases.end()) { + return iter->second->compile(); + } + } + } + return nullptr; +} + +Resolver::ResolvedDecl Compiler::Node::resolveBuiltin(Declaration::Which which) { + auto& b = module->getCompiler().getBuiltin(which); + return { b.id, b.genericParamCount, 0, b.kind, &b, nullptr }; +} + +Resolver::ResolvedDecl Compiler::Node::resolveId(uint64_t id) { + auto& n = KJ_ASSERT_NONNULL(module->getCompiler().findNode(id)); + uint64_t parentId = n.parent.map([](Node& n) { return n.id; }).orDefault(0); + return { n.id, n.genericParamCount, parentId, n.kind, &n, nullptr }; +} + +kj::Maybe Compiler::Node::getParent() { + return parent.map([](Node& parent) { + uint64_t scopeId = parent.parent.map([](Node& gp) { return gp.id; }).orDefault(0); + return ResolvedDecl { parent.id, parent.genericParamCount, scopeId, parent.kind, &parent, nullptr }; + }); +} + +Resolver::ResolvedDecl Compiler::Node::getTopScope() { + Node& node = module->getRootNode(); + return ResolvedDecl { node.id, 0, 0, node.kind, &node, nullptr }; +} + +kj::Maybe Compiler::Node::resolveBootstrapSchema( + uint64_t id, schema::Brand::Reader brand) { + KJ_IF_MAYBE(node, module->getCompiler().findNode(id)) { + // Make sure the bootstrap schema is loaded into the SchemaLoader. + if (node->getBootstrapSchema() == nullptr) { + return nullptr; + } + + // Now we actually invoke get() to evaluate the brand. + return module->getCompiler().getWorkspace().bootstrapLoader.get(id, brand); + } else { + KJ_FAIL_REQUIRE("Tried to get schema for ID we haven't seen before."); + } +} + +kj::Maybe Compiler::Node::resolveFinalSchema(uint64_t id) { + KJ_IF_MAYBE(node, module->getCompiler().findNode(id)) { + return node->getFinalSchema(); + } else { + KJ_FAIL_REQUIRE("Tried to get schema for ID we haven't seen before."); + } +} + +kj::Maybe +Compiler::Node::resolveImport(kj::StringPtr name) { + KJ_IF_MAYBE(m, module->importRelative(name)) { + Node& root = m->getRootNode(); + return ResolvedDecl { root.id, 0, 0, root.kind, &root, nullptr }; + } else { + return nullptr; + } +} + +kj::Maybe> Compiler::Node::readEmbed(kj::StringPtr name) { + return module->embedRelative(name); +} + +kj::Maybe Compiler::Node::resolveBootstrapType(schema::Type::Reader type, Schema scope) { + // TODO(someday): Arguably should return null if the type or its dependencies are placeholders. + + kj::Maybe result; + KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() { + result = module->getCompiler().getWorkspace().bootstrapLoader.getType(type, scope); + })) { + result = nullptr; + if (!module->getErrorReporter().hadErrors()) { + addError(kj::str("Internal compiler bug: Bootstrap schema failed to load:\n", + *exception)); + } + } + return result; +} + +// ======================================================================================= + +Compiler::CompiledModule::CompiledModule(Compiler::Impl& compiler, Module& parserModule) + : compiler(compiler), parserModule(parserModule), + content(parserModule.loadContent(contentArena.getOrphanage())), + rootNode(*this) {} + +kj::Maybe Compiler::CompiledModule::importRelative( + kj::StringPtr importPath) { + return parserModule.importRelative(importPath).map( + [this](Module& module) -> Compiler::CompiledModule& { + return compiler.addInternal(module); + }); +} + +kj::Maybe> Compiler::CompiledModule::embedRelative(kj::StringPtr embedPath) { + return parserModule.embedRelative(embedPath); +} + +// ======================================================================================= + +Compiler::Impl::Impl() + : workspace(*this) { + // Reflectively interpret the members of Declaration.body. Any member prefixed by "builtin" + // defines a builtin declaration visible in the global scope. + + StructSchema declSchema = Schema::from(); + for (auto field: declSchema.getFields()) { + auto fieldProto = field.getProto(); + if (fieldProto.getDiscriminantValue() != schema::Field::NO_DISCRIMINANT) { + auto name = fieldProto.getName(); + if (name.startsWith("builtin")) { + kj::StringPtr symbolName = name.slice(strlen("builtin")); + + List::Reader params; + for (auto annotation: fieldProto.getAnnotations()) { + if (annotation.getId() == 0x94099c3f9eb32d6bull) { + params = annotation.getValue().getList().getAs>(); + break; + } + } + + Declaration::Which which = + static_cast(fieldProto.getDiscriminantValue()); + kj::Own newNode = nodeArena.allocateOwn(symbolName, which, params); + builtinDeclsByKind[which] = newNode; + builtinDecls[symbolName] = kj::mv(newNode); + } + } + } +} + +Compiler::Impl::~Impl() noexcept(false) {} + +void Compiler::Impl::clearWorkspace() { + // Make sure we reconstruct the workspace even if destroying it throws an exception. + KJ_DEFER(kj::ctor(workspace, *this)); + kj::dtor(workspace); +} + +Compiler::CompiledModule& Compiler::Impl::addInternal(Module& parsedModule) { + kj::Own& slot = modules[&parsedModule]; + if (slot.get() == nullptr) { + slot = kj::heap(*this, parsedModule); + } + + return *slot; +} + +uint64_t Compiler::Impl::addNode(uint64_t desiredId, Node& node) { + for (;;) { + auto insertResult = nodesById.insert(std::make_pair(desiredId, &node)); + if (insertResult.second) { + return desiredId; + } + + // Only report an error if this ID is not bogus. Actual IDs specified in the original source + // code are required to have the upper bit set. Anything else must have been manufactured + // at some point to cover up an error. + if (desiredId & (1ull << 63)) { + node.addError(kj::str("Duplicate ID @0x", kj::hex(desiredId), ".")); + insertResult.first->second->addError( + kj::str("ID @0x", kj::hex(desiredId), " originally used here.")); + } + + // Assign a new bogus ID. + desiredId = nextBogusId++; + } +} + +kj::Maybe Compiler::Impl::findNode(uint64_t id) { + auto iter = nodesById.find(id); + if (iter == nodesById.end()) { + return nullptr; + } else { + return *iter->second; + } +} + +kj::Maybe Compiler::Impl::lookupBuiltin(kj::StringPtr name) { + auto iter = builtinDecls.find(name); + if (iter == builtinDecls.end()) { + return nullptr; + } else { + return *iter->second; + } +} + +Compiler::Node& Compiler::Impl::getBuiltin(Declaration::Which which) { + auto iter = builtinDeclsByKind.find(which); + KJ_REQUIRE(iter != builtinDeclsByKind.end(), "invalid builtin", (uint)which); + return *iter->second; +} + +kj::Maybe Compiler::Impl::lookup(uint64_t parent, kj::StringPtr childName) { + // Looking up members does not use the workspace, so we don't need to lock it. + KJ_IF_MAYBE(parentNode, findNode(parent)) { + KJ_IF_MAYBE(child, parentNode->resolveMember(childName)) { + if (child->is()) { + return child->get().id; + } else { + // An alias. We don't support looking up aliases with this method. + return nullptr; + } + } else { + return nullptr; + } + } else { + KJ_FAIL_REQUIRE("lookup()s parameter 'parent' must be a known ID.", parent); + } +} + +void Compiler::Impl::eagerlyCompile(uint64_t id, uint eagerness, + const SchemaLoader& finalLoader) { + KJ_IF_MAYBE(node, findNode(id)) { + std::unordered_map seen; + node->traverse(eagerness, seen, finalLoader); + + } else { + KJ_FAIL_REQUIRE("id did not come from this Compiler.", id); + } +} + +void Compiler::Impl::load(const SchemaLoader& loader, uint64_t id) const { + // We know that this load() is only called from the bootstrap loader which is already protected + // by our mutex, so we can drop thread-safety. + auto& self = const_cast(*this); + + KJ_IF_MAYBE(node, self.findNode(id)) { + node->getBootstrapSchema(); + } +} + +void Compiler::Impl::loadFinal(const SchemaLoader& loader, uint64_t id) { + KJ_IF_MAYBE(node, findNode(id)) { + node->loadFinalSchema(loader); + } +} + +// ======================================================================================= + +Compiler::Compiler() + : impl(kj::heap()), + loader(*this) {} +Compiler::~Compiler() noexcept(false) {} + +Compiler::ModuleScope Compiler::add(Module& module) const { + Node& root = impl.lockExclusive()->get()->addInternal(module).getRootNode(); + return ModuleScope(root.getId()); +} + +kj::Maybe Compiler::lookup(uint64_t parent, kj::StringPtr childName) const { + return impl.lockExclusive()->get()->lookup(parent, childName); +} + +void Compiler::eagerlyCompile(uint64_t id, uint eagerness) const { + impl.lockExclusive()->get()->eagerlyCompile(id, eagerness, loader); +} + +void Compiler::clearWorkspace() const { + impl.lockExclusive()->get()->clearWorkspace(); +} + +void Compiler::load(const SchemaLoader& loader, uint64_t id) const { + impl.lockExclusive()->get()->loadFinal(loader, id); +} + +} // namespace compiler +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/compiler/compiler.h b/vendor/capnproto/src/capnp/compiler/compiler.h new file mode 100644 index 0000000..f83aeb4 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/compiler.h @@ -0,0 +1,188 @@ +// 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. + +#pragma once + +#include +#include +#include +#include "error-reporter.h" +#include "generics.h" + +CAPNP_BEGIN_HEADER + +namespace capnp { +namespace compiler { + +class Module: public ErrorReporter { +public: + virtual kj::StringPtr getSourceName() = 0; + // The name of the module file relative to the source tree. Used to decide where to output + // generated code and to form the `displayName` in the schema. + + virtual Orphan loadContent(Orphanage orphanage) = 0; + // Loads the module content, using the given orphanage to allocate objects if necessary. + + virtual kj::Maybe importRelative(kj::StringPtr importPath) = 0; + // Find another module, relative to this one. Importing the same logical module twice should + // produce the exact same object, comparable by identity. These objects are owned by some + // outside pool that outlives the Compiler instance. + + virtual kj::Maybe> embedRelative(kj::StringPtr embedPath) = 0; + // Read and return the content of a file specified using `embed`. + +}; + +class Compiler final: private SchemaLoader::LazyLoadCallback { + // Cross-links separate modules (schema files) and translates them into schema nodes. + // + // This class is thread-safe, hence all its methods are const. + + class Node; + +public: + Compiler(); + ~Compiler() noexcept(false); + KJ_DISALLOW_COPY_AND_MOVE(Compiler); + + class ModuleScope { + public: + uint64_t getId() { return id; } + + private: + uint64_t id; + explicit ModuleScope(uint64_t id): id(id) {} + friend class Compiler; + }; + + ModuleScope add(Module& module) const; + // Add a module to the Compiler, returning the ID of the top-level scope of + // the module. The module is parsed at the time `add()` is called, but not fully compiled -- + // individual schema nodes are compiled lazily. If you want to force eager compilation, + // see `eagerlyCompile()`, below. + + kj::Maybe lookup(uint64_t parent, kj::StringPtr childName) const; + // Given the type ID of a schema node, find the ID of a node nested within it. Throws an + // exception if the parent ID is not recognized; returns null if the parent has no child of the + // given name. Neither the parent nor the child schema node is actually compiled. + // + // This interface does not handle generic specializations. + + enum Eagerness: uint32_t { + // Flags specifying how eager to be about compilation. These are intended to be bitwise OR'd. + // Used with the method `eagerlyCompile()`. + // + // Schema declarations can be compiled upfront, or they can be compiled lazily as they are + // needed. Usually, the difference is not observable, but it is not a perfect abstraction. + // The difference has the following effects: + // * `getLoader().getAllLoaded()` only returns the schema nodes which have been compiled so + // far. + // * `getLoader().get()` (i.e. searching for a schema by ID) can only find schema nodes that + // have either been compiled already, or which are referenced by schema nodes which have been + // compiled already. This means that if the ID you pass in came from another schema node + // compiled with the same compiler, there should be no observable difference, but if you + // have an ID from elsewhere which you _a priori_ expect is defined in a particular schema + // file, you will need to compile that file eagerly before you look up the node by ID. + // * Errors are reported when they are encountered, so some errors will not be reported until + // the node is actually compiled. + // * If an imported file is not needed, it will never even be read from disk. + // + // The last point is the main reason why you might want to prefer lazy compilation: it allows + // you to use a schema file with missing imports, so long as those missing imports are not + // actually needed. + // + // For example, the flag combo: + // EAGER_NODE | EAGER_CHILDREN | EAGER_DEPENDENCIES | EAGER_DEPENDENCY_PARENTS + // will compile the entire given module, plus all direct dependencies of anything in that + // module, plus all lexical ancestors of those dependencies. This is what the Cap'n Proto + // compiler uses when building initial code generator requests. + + ALL_RELATED_NODES = ~0u, + // Compile everything that is in any way related to the target node, including its entire + // containing file and everything transitively imported by it. + + NODE = 1 << 0, + // Eagerly compile the requested node, but not necessarily any of its parents, children, or + // dependencies. + + PARENTS = 1 << 1, + // Eagerly compile all lexical parents of the requested node. Only meaningful in conjunction + // with NODE. + + CHILDREN = 1 << 2, + // Eagerly compile all of the node's lexically nested nodes. Only meaningful in conjunction + // with NODE. + + DEPENDENCIES = NODE << 15, + // For all nodes compiled as a result of the above flags, also compile their direct + // dependencies. E.g. if Foo is a struct which contains a field of type Bar, and Foo is + // compiled, then also compile Bar. "Dependencies" are defined as field types, method + // parameter and return types, and annotation types. Nested types and outer types are not + // considered dependencies. + + DEPENDENCY_PARENTS = PARENTS * DEPENDENCIES, + DEPENDENCY_CHILDREN = CHILDREN * DEPENDENCIES, + DEPENDENCY_DEPENDENCIES = DEPENDENCIES * DEPENDENCIES, + // Like PARENTS, CHILDREN, and DEPENDENCIES, but applies relative to dependency nodes rather + // than the original requested node. Note that DEPENDENCY_DEPENDENCIES causes all transitive + // dependencies of the requested node to be compiled. + // + // These flags are defined as multiples of the original flag and DEPENDENCIES so that we + // can form the flags to use when traversing a dependency by shifting bits. + }; + + void eagerlyCompile(uint64_t id, uint eagerness) const; + // Force eager compilation of schema nodes related to the given ID. `eagerness` specifies which + // related nodes should be compiled before returning. It is a bitwise OR of the possible values + // of the `Eagerness` enum. + // + // If this returns and no errors have been reported, then it is guaranteed that the compiled + // nodes can be found in the SchemaLoader returned by `getLoader()`. + + const SchemaLoader& getLoader() const { return loader; } + SchemaLoader& getLoader() { return loader; } + // Get a SchemaLoader backed by this compiler. Schema nodes will be lazily constructed as you + // traverse them using this loader. + + void clearWorkspace() const; + // The compiler builds a lot of temporary tables and data structures while it works. It's + // useful to keep these around if more work is expected (especially if you are using lazy + // compilation and plan to look up Schema nodes that haven't already been seen), but once + // the SchemaLoader has everything you need, you can call clearWorkspace() to free up the + // temporary space. Note that it's safe to call clearWorkspace() even if you do expect to + // compile more nodes in the future; it may simply lead to redundant work if the discarded + // structures are needed again. + +private: + class Impl; + kj::MutexGuarded> impl; + SchemaLoader loader; + + class CompiledModule; + class Alias; + + void load(const SchemaLoader& loader, uint64_t id) const override; +}; + +} // namespace compiler +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/compiler/error-reporter.h b/vendor/capnproto/src/capnp/compiler/error-reporter.h new file mode 100644 index 0000000..f213154 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/error-reporter.h @@ -0,0 +1,61 @@ +// 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. + +#pragma once + +#include +#include +#include + +CAPNP_BEGIN_HEADER + +namespace capnp { +namespace compiler { + +class ErrorReporter { + // Callback for reporting errors within a particular file. + +public: + virtual void addError(uint32_t startByte, uint32_t endByte, kj::StringPtr message) = 0; + // Report an error at the given location in the input text. `startByte` and `endByte` indicate + // the span of text that is erroneous. They may be equal, in which case the parser was only + // able to identify where the error begins, not where it ends. + + template + inline void addErrorOn(T&& decl, kj::StringPtr message) { + // Works for any `T` that defines `getStartByte()` and `getEndByte()` methods, which many + // of the Cap'n Proto types defined in `grammar.capnp` do. + + addError(decl.getStartByte(), decl.getEndByte(), message); + } + + virtual bool hadErrors() = 0; + // Return true if any errors have been reported, globally. The main use case for this callback + // is to inhibit the reporting of errors which may have been caused by previous errors, or to + // allow the compiler to bail out entirely if it gets confused and thinks this could be because + // of previous errors. + +}; + +} // namespace compiler +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/compiler/generics.c++ b/vendor/capnproto/src/capnp/compiler/generics.c++ new file mode 100644 index 0000000..6f5b6f9 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/generics.c++ @@ -0,0 +1,627 @@ +// Copyright (c) 2013-2020 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 "generics.h" +#include "parser.h" // for expressionString() + +namespace capnp { +namespace compiler { + +BrandedDecl::BrandedDecl(BrandedDecl& other) + : body(other.body), + source(other.source) { + if (body.is()) { + brand = kj::addRef(*other.brand); + } +} + +BrandedDecl& BrandedDecl::operator=(BrandedDecl& other) { + body = other.body; + source = other.source; + if (body.is()) { + brand = kj::addRef(*other.brand); + } + return *this; +} + +kj::Maybe BrandedDecl::applyParams( + kj::Array params, Expression::Reader subSource) { + if (body.is()) { + return nullptr; + } else { + return brand->setParams(kj::mv(params), body.get().kind, subSource) + .map([&](kj::Own&& scope) { + BrandedDecl result = *this; + result.brand = kj::mv(scope); + result.source = subSource; + return result; + }); + } +} + +kj::Maybe BrandedDecl::getMember( + kj::StringPtr memberName, Expression::Reader subSource) { + if (body.is()) { + return nullptr; + } else KJ_IF_MAYBE(r, body.get().resolver->resolveMember(memberName)) { + return brand->interpretResolve(*body.get().resolver, *r, subSource); + } else { + return nullptr; + } +} + +kj::Maybe BrandedDecl::getKind() { + if (body.is()) { + return nullptr; + } else { + return body.get().kind; + } +} + +kj::Maybe BrandedDecl::getListParam() { + KJ_REQUIRE(body.is()); + + auto& decl = body.get(); + KJ_REQUIRE(decl.kind == Declaration::BUILTIN_LIST); + + auto params = KJ_ASSERT_NONNULL(brand->getParams(decl.id)); + if (params.size() != 1) { + return nullptr; + } else { + return params[0]; + } +} + +Resolver::ResolvedParameter BrandedDecl::asVariable() { + KJ_REQUIRE(body.is()); + + return body.get(); +} + +bool BrandedDecl::compileAsType( + ErrorReporter& errorReporter, schema::Type::Builder target) { + KJ_IF_MAYBE(kind, getKind()) { + switch (*kind) { + case Declaration::ENUM: { + auto enum_ = target.initEnum(); + enum_.setTypeId(getIdAndFillBrand([&]() { return enum_.initBrand(); })); + return true; + } + + case Declaration::STRUCT: { + auto struct_ = target.initStruct(); + struct_.setTypeId(getIdAndFillBrand([&]() { return struct_.initBrand(); })); + return true; + } + + case Declaration::INTERFACE: { + auto interface = target.initInterface(); + interface.setTypeId(getIdAndFillBrand([&]() { return interface.initBrand(); })); + return true; + } + + case Declaration::BUILTIN_LIST: { + auto elementType = target.initList().initElementType(); + + KJ_IF_MAYBE(param, getListParam()) { + if (!param->compileAsType(errorReporter, elementType)) { + return false; + } + } else { + addError(errorReporter, "'List' requires exactly one parameter."); + return false; + } + + if (elementType.isAnyPointer()) { + auto unconstrained = elementType.getAnyPointer().getUnconstrained(); + + if (unconstrained.isAnyKind()) { + addError(errorReporter, "'List(AnyPointer)' is not supported."); + // Seeing List(AnyPointer) later can mess things up, so change the type to Void. + elementType.setVoid(); + return false; + } else if (unconstrained.isStruct()) { + addError(errorReporter, "'List(AnyStruct)' is not supported."); + // Seeing List(AnyStruct) later can mess things up, so change the type to Void. + elementType.setVoid(); + return false; + } + } + + return true; + } + + case Declaration::BUILTIN_VOID: target.setVoid(); return true; + case Declaration::BUILTIN_BOOL: target.setBool(); return true; + case Declaration::BUILTIN_INT8: target.setInt8(); return true; + case Declaration::BUILTIN_INT16: target.setInt16(); return true; + case Declaration::BUILTIN_INT32: target.setInt32(); return true; + case Declaration::BUILTIN_INT64: target.setInt64(); return true; + case Declaration::BUILTIN_U_INT8: target.setUint8(); return true; + case Declaration::BUILTIN_U_INT16: target.setUint16(); return true; + case Declaration::BUILTIN_U_INT32: target.setUint32(); return true; + case Declaration::BUILTIN_U_INT64: target.setUint64(); return true; + case Declaration::BUILTIN_FLOAT32: target.setFloat32(); return true; + case Declaration::BUILTIN_FLOAT64: target.setFloat64(); return true; + case Declaration::BUILTIN_TEXT: target.setText(); return true; + case Declaration::BUILTIN_DATA: target.setData(); return true; + + case Declaration::BUILTIN_OBJECT: + addError(errorReporter, + "As of Cap'n Proto 0.4, 'Object' has been renamed to 'AnyPointer'. Sorry for the " + "inconvenience, and thanks for being an early adopter. :)"); + KJ_FALLTHROUGH; + case Declaration::BUILTIN_ANY_POINTER: + target.initAnyPointer().initUnconstrained().setAnyKind(); + return true; + case Declaration::BUILTIN_ANY_STRUCT: + target.initAnyPointer().initUnconstrained().setStruct(); + return true; + case Declaration::BUILTIN_ANY_LIST: + target.initAnyPointer().initUnconstrained().setList(); + return true; + case Declaration::BUILTIN_CAPABILITY: + target.initAnyPointer().initUnconstrained().setCapability(); + return true; + + case Declaration::FILE: + case Declaration::USING: + case Declaration::CONST: + case Declaration::ENUMERANT: + case Declaration::FIELD: + case Declaration::UNION: + case Declaration::GROUP: + case Declaration::METHOD: + case Declaration::ANNOTATION: + case Declaration::NAKED_ID: + case Declaration::NAKED_ANNOTATION: + addError(errorReporter, kj::str("'", toString(), "' is not a type.")); + return false; + } + + KJ_UNREACHABLE; + } else { + // Oh, this is a type variable. + auto var = asVariable(); + auto builder = target.initAnyPointer().initParameter(); + builder.setScopeId(var.id); + builder.setParameterIndex(var.index); + return true; + } +} + +Resolver::ResolveResult BrandedDecl::asResolveResult( + uint64_t scopeId, schema::Brand::Builder brandBuilder) { + auto result = body; + if (result.is()) { + // May need to compile our context as the "brand". + + result.get().scopeId = scopeId; + + getIdAndFillBrand([&]() { + result.get().brand = brandBuilder.asReader(); + return brandBuilder; + }); + } + return result; +} + +kj::String BrandedDecl::toString() { + return expressionString(source); +} + +BrandScope::BrandScope(ErrorReporter& errorReporter, uint64_t startingScopeId, + uint startingScopeParamCount, Resolver& startingScope) + : errorReporter(errorReporter), parent(nullptr), leafId(startingScopeId), + leafParamCount(startingScopeParamCount), inherited(true) { + // Create all lexical parent scopes, all with no brand bindings. + KJ_IF_MAYBE(p, startingScope.getParent()) { + parent = kj::refcounted( + errorReporter, p->id, p->genericParamCount, *p->resolver); + } +} + +bool BrandScope::isGeneric() { + if (leafParamCount > 0) return true; + + KJ_IF_MAYBE(p, parent) { + return p->get()->isGeneric(); + } else { + return false; + } +} + +kj::Own BrandScope::push(uint64_t typeId, uint paramCount) { + return kj::refcounted(kj::addRef(*this), typeId, paramCount); +} + +kj::Maybe> BrandScope::setParams( + kj::Array params, Declaration::Which genericType, Expression::Reader source) { + if (this->params.size() != 0) { + errorReporter.addErrorOn(source, "Double-application of generic parameters."); + return nullptr; + } else if (params.size() > leafParamCount) { + if (leafParamCount == 0) { + errorReporter.addErrorOn(source, "Declaration does not accept generic parameters."); + } else { + errorReporter.addErrorOn(source, "Too many generic parameters."); + } + return nullptr; + } else if (params.size() < leafParamCount) { + errorReporter.addErrorOn(source, "Not enough generic parameters."); + return nullptr; + } else { + if (genericType != Declaration::BUILTIN_LIST) { + for (auto& param: params) { + KJ_IF_MAYBE(kind, param.getKind()) { + switch (*kind) { + case Declaration::BUILTIN_LIST: + case Declaration::BUILTIN_TEXT: + case Declaration::BUILTIN_DATA: + case Declaration::BUILTIN_ANY_POINTER: + case Declaration::STRUCT: + case Declaration::INTERFACE: + break; + + default: + param.addError(errorReporter, + "Sorry, only pointer types can be used as generic parameters."); + break; + } + } + } + } + + return kj::refcounted(*this, kj::mv(params)); + } +} + +kj::Own BrandScope::pop(uint64_t newLeafId) { + if (leafId == newLeafId) { + return kj::addRef(*this); + } + KJ_IF_MAYBE(p, parent) { + return (*p)->pop(newLeafId); + } else { + // Looks like we're moving into a whole top-level scope. + return kj::refcounted(errorReporter, newLeafId); + } +} + +kj::Maybe BrandScope::lookupParameter( + Resolver& resolver, uint64_t scopeId, uint index) { + // Returns null if the param should be inherited from the client scope. + + if (scopeId == leafId) { + if (index < params.size()) { + return params[index]; + } else if (inherited) { + return nullptr; + } else { + // Unbound and not inherited, so return AnyPointer. + auto decl = resolver.resolveBuiltin(Declaration::BUILTIN_ANY_POINTER); + return BrandedDecl(decl, + evaluateBrand(resolver, decl, List::Reader()), + Expression::Reader()); + } + } else KJ_IF_MAYBE(p, parent) { + return p->get()->lookupParameter(resolver, scopeId, index); + } else { + KJ_FAIL_REQUIRE("scope is not a parent"); + } +} + +kj::Maybe> BrandScope::getParams(uint64_t scopeId) { + // Returns null if params at the requested scope should be inherited from the client scope. + + if (scopeId == leafId) { + if (inherited) { + return nullptr; + } else { + return params.asPtr(); + } + } else KJ_IF_MAYBE(p, parent) { + return p->get()->getParams(scopeId); + } else { + KJ_FAIL_REQUIRE("scope is not a parent"); + } +} + +BrandedDecl BrandScope::interpretResolve( + Resolver& resolver, Resolver::ResolveResult& result, Expression::Reader source) { + if (result.is()) { + auto& decl = result.get(); + + auto scope = pop(decl.scopeId); + KJ_IF_MAYBE(brand, decl.brand) { + scope = scope->evaluateBrand(resolver, decl, brand->getScopes()); + } else { + scope = scope->push(decl.id, decl.genericParamCount); + } + + return BrandedDecl(decl, kj::mv(scope), source); + } else { + auto& param = result.get(); + KJ_IF_MAYBE(p, lookupParameter(resolver, param.id, param.index)) { + return *p; + } else { + return BrandedDecl(param, source); + } + } +} + +kj::Own BrandScope::evaluateBrand( + Resolver& resolver, Resolver::ResolvedDecl decl, + List::Reader brand, uint index) { + auto result = kj::refcounted(errorReporter, decl.id); + result->leafParamCount = decl.genericParamCount; + + // Fill in `params`. + if (index < brand.size()) { + auto nextScope = brand[index]; + if (decl.id == nextScope.getScopeId()) { + // Initialize our parameters. + + switch (nextScope.which()) { + case schema::Brand::Scope::BIND: { + auto bindings = nextScope.getBind(); + auto params = kj::heapArrayBuilder(bindings.size()); + for (auto binding: bindings) { + switch (binding.which()) { + case schema::Brand::Binding::UNBOUND: { + // Build an AnyPointer-equivalent. + auto anyPointerDecl = resolver.resolveBuiltin(Declaration::BUILTIN_ANY_POINTER); + params.add(BrandedDecl(anyPointerDecl, + kj::refcounted(errorReporter, anyPointerDecl.scopeId), + Expression::Reader())); + break; + } + + case schema::Brand::Binding::TYPE: + // Reverse this schema::Type back into a BrandedDecl. + params.add(decompileType(resolver, binding.getType())); + break; + } + } + result->params = params.finish(); + break; + } + + case schema::Brand::Scope::INHERIT: + KJ_IF_MAYBE(p, getParams(decl.id)) { + result->params = kj::heapArray(*p); + } else { + result->inherited = true; + } + break; + } + + // Parent should start one level deeper in the list. + ++index; + } + } + + // Fill in `parent`. + KJ_IF_MAYBE(parent, decl.resolver->getParent()) { + result->parent = evaluateBrand(resolver, *parent, brand, index); + } + + return result; +} + +BrandedDecl BrandScope::decompileType( + Resolver& resolver, schema::Type::Reader type) { + auto builtin = [&](Declaration::Which which) -> BrandedDecl { + auto decl = resolver.resolveBuiltin(which); + return BrandedDecl(decl, + evaluateBrand(resolver, decl, List::Reader()), + Expression::Reader()); + }; + + switch (type.which()) { + case schema::Type::VOID: return builtin(Declaration::BUILTIN_VOID); + case schema::Type::BOOL: return builtin(Declaration::BUILTIN_BOOL); + case schema::Type::INT8: return builtin(Declaration::BUILTIN_INT8); + case schema::Type::INT16: return builtin(Declaration::BUILTIN_INT16); + case schema::Type::INT32: return builtin(Declaration::BUILTIN_INT32); + case schema::Type::INT64: return builtin(Declaration::BUILTIN_INT64); + case schema::Type::UINT8: return builtin(Declaration::BUILTIN_U_INT8); + case schema::Type::UINT16: return builtin(Declaration::BUILTIN_U_INT16); + case schema::Type::UINT32: return builtin(Declaration::BUILTIN_U_INT32); + case schema::Type::UINT64: return builtin(Declaration::BUILTIN_U_INT64); + case schema::Type::FLOAT32: return builtin(Declaration::BUILTIN_FLOAT32); + case schema::Type::FLOAT64: return builtin(Declaration::BUILTIN_FLOAT64); + case schema::Type::TEXT: return builtin(Declaration::BUILTIN_TEXT); + case schema::Type::DATA: return builtin(Declaration::BUILTIN_DATA); + + case schema::Type::ENUM: { + auto enumType = type.getEnum(); + Resolver::ResolvedDecl decl = resolver.resolveId(enumType.getTypeId()); + return BrandedDecl(decl, + evaluateBrand(resolver, decl, enumType.getBrand().getScopes()), + Expression::Reader()); + } + + case schema::Type::INTERFACE: { + auto interfaceType = type.getInterface(); + Resolver::ResolvedDecl decl = resolver.resolveId(interfaceType.getTypeId()); + return BrandedDecl(decl, + evaluateBrand(resolver, decl, interfaceType.getBrand().getScopes()), + Expression::Reader()); + } + + case schema::Type::STRUCT: { + auto structType = type.getStruct(); + Resolver::ResolvedDecl decl = resolver.resolveId(structType.getTypeId()); + return BrandedDecl(decl, + evaluateBrand(resolver, decl, structType.getBrand().getScopes()), + Expression::Reader()); + } + + case schema::Type::LIST: { + auto elementType = decompileType(resolver, type.getList().getElementType()); + return KJ_ASSERT_NONNULL(builtin(Declaration::BUILTIN_LIST) + .applyParams(kj::heapArray(&elementType, 1), Expression::Reader())); + } + + case schema::Type::ANY_POINTER: { + auto anyPointer = type.getAnyPointer(); + switch (anyPointer.which()) { + case schema::Type::AnyPointer::UNCONSTRAINED: + return builtin(Declaration::BUILTIN_ANY_POINTER); + + case schema::Type::AnyPointer::PARAMETER: { + auto param = anyPointer.getParameter(); + auto id = param.getScopeId(); + uint index = param.getParameterIndex(); + KJ_IF_MAYBE(binding, lookupParameter(resolver, id, index)) { + return *binding; + } else { + return BrandedDecl(Resolver::ResolvedParameter {id, index}, Expression::Reader()); + } + } + + case schema::Type::AnyPointer::IMPLICIT_METHOD_PARAMETER: + KJ_FAIL_ASSERT("Alias pointed to implicit method type parameter?"); + } + + KJ_UNREACHABLE; + } + } + + KJ_UNREACHABLE; +} + +kj::Maybe BrandScope::compileDeclExpression( + Expression::Reader source, Resolver& resolver) { + switch (source.which()) { + case Expression::UNKNOWN: + // Error reported earlier. + return nullptr; + + case Expression::POSITIVE_INT: + case Expression::NEGATIVE_INT: + case Expression::FLOAT: + case Expression::STRING: + case Expression::BINARY: + case Expression::LIST: + case Expression::TUPLE: + case Expression::EMBED: + errorReporter.addErrorOn(source, "Expected name."); + return nullptr; + + case Expression::RELATIVE_NAME: { + auto name = source.getRelativeName(); + auto nameValue = name.getValue(); + + KJ_IF_MAYBE(r, resolver.resolve(nameValue)) { + auto result = interpretResolve(resolver, *r, source); + return kj::mv(result); + } else { + errorReporter.addErrorOn(name, kj::str("Not defined: ", nameValue)); + return nullptr; + } + } + + case Expression::ABSOLUTE_NAME: { + auto name = source.getAbsoluteName(); + KJ_IF_MAYBE(r, resolver.getTopScope().resolver->resolveMember(name.getValue())) { + auto result = interpretResolve(resolver, *r, source); + return kj::mv(result); + } else { + errorReporter.addErrorOn(name, kj::str("Not defined: ", name.getValue())); + return nullptr; + } + } + + case Expression::IMPORT: { + auto filename = source.getImport(); + KJ_IF_MAYBE(decl, resolver.resolveImport(filename.getValue())) { + // Import is always a root scope, so create a fresh BrandScope. + return BrandedDecl(*decl, kj::refcounted( + errorReporter, decl->id, decl->genericParamCount, *decl->resolver), source); + } else { + errorReporter.addErrorOn(filename, kj::str("Import failed: ", filename.getValue())); + return nullptr; + } + } + + case Expression::APPLICATION: { + auto app = source.getApplication(); + KJ_IF_MAYBE(decl, compileDeclExpression(app.getFunction(), resolver)) { + // Compile all params. + auto params = app.getParams(); + auto compiledParams = kj::heapArrayBuilder(params.size()); + bool paramFailed = false; + for (auto param: params) { + if (param.isNamed()) { + errorReporter.addErrorOn(param.getNamed(), "Named parameter not allowed here."); + } + + KJ_IF_MAYBE(d, compileDeclExpression(param.getValue(), resolver)) { + compiledParams.add(kj::mv(*d)); + } else { + // Param failed to compile. Error was already reported. + paramFailed = true; + } + }; + + if (paramFailed) { + return kj::mv(*decl); + } + + // Add the parameters to the brand. + KJ_IF_MAYBE(applied, decl->applyParams(compiledParams.finish(), source)) { + return kj::mv(*applied); + } else { + // Error already reported. Ignore parameters. + return kj::mv(*decl); + } + } else { + // error already reported + return nullptr; + } + } + + case Expression::MEMBER: { + auto member = source.getMember(); + KJ_IF_MAYBE(decl, compileDeclExpression(member.getParent(), resolver)) { + auto name = member.getName(); + KJ_IF_MAYBE(memberDecl, decl->getMember(name.getValue(), source)) { + return kj::mv(*memberDecl); + } else { + errorReporter.addErrorOn(name, kj::str( + "'", expressionString(member.getParent()), + "' has no member named '", name.getValue(), "'")); + return nullptr; + } + } else { + // error already reported + return nullptr; + } + } + } + + KJ_UNREACHABLE; +} + +} // namespace compiler +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/compiler/generics.h b/vendor/capnproto/src/capnp/compiler/generics.h new file mode 100644 index 0000000..067f1e4 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/generics.h @@ -0,0 +1,273 @@ +// Copyright (c) 2013-2020 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. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "error-reporter.h" +#include "resolver.h" + +CAPNP_BEGIN_HEADER + +namespace capnp { +namespace compiler { + +class BrandedDecl; +class BrandScope; + +class BrandedDecl { + // Represents a declaration possibly with generic parameter bindings. + +public: + inline BrandedDecl(Resolver::ResolvedDecl decl, + kj::Own&& brand, + Expression::Reader source) + : brand(kj::mv(brand)), source(source) { + // `source`, is the expression which specified this branded decl. It is provided so that errors + // can be reported against it. It is acceptable to pass a default-initialized reader if there's + // no source expression; errors will then be reported at 0, 0. + + body.init(kj::mv(decl)); + } + inline BrandedDecl(Resolver::ResolvedParameter variable, Expression::Reader source) + : source(source) { + body.init(kj::mv(variable)); + } + inline BrandedDecl(decltype(nullptr)) {} + inline BrandedDecl() {} // exists only for ExternalMutexGuarded to work... + + BrandedDecl(BrandedDecl& other); + BrandedDecl(BrandedDecl&& other) = default; + + BrandedDecl& operator=(BrandedDecl& other); + BrandedDecl& operator=(BrandedDecl&& other) = default; + + kj::Maybe applyParams(kj::Array params, Expression::Reader subSource); + // Treat the declaration as a generic and apply it to the given parameter list. + + kj::Maybe getMember(kj::StringPtr memberName, Expression::Reader subSource); + // Get a member of this declaration. + + kj::Maybe getKind(); + // Returns the kind of declaration, or null if this is an unbound generic variable. + + template + uint64_t getIdAndFillBrand(InitBrandFunc&& initBrand); + // Returns the type ID of this node. `initBrand` is a zero-arg functor which returns + // schema::Brand::Builder; this will be called if this decl has brand bindings, and + // the returned builder filled in to reflect those bindings. + // + // It is an error to call this when `getKind()` returns null. + + kj::Maybe getListParam(); + // Only if the kind is BUILTIN_LIST: Get the list's type parameter. + + Resolver::ResolvedParameter asVariable(); + // If this is an unbound generic variable (i.e. `getKind()` returns null), return information + // about the variable. + // + // It is an error to call this when `getKind()` does not return null. + + bool compileAsType(ErrorReporter& errorReporter, schema::Type::Builder target); + // Compile this decl to a schema::Type. + + inline void addError(ErrorReporter& errorReporter, kj::StringPtr message) { + errorReporter.addErrorOn(source, message); + } + + Resolver::ResolveResult asResolveResult(uint64_t scopeId, schema::Brand::Builder brandBuilder); + // Reverse this into a ResolveResult. If necessary, use `brandBuilder` to fill in + // ResolvedDecl.brand. + + kj::String toString(); + +private: + Resolver::ResolveResult body; + kj::Own brand; // null if parameter + Expression::Reader source; +}; + +class BrandScope: public kj::Refcounted { + // Tracks the brand parameter bindings affecting the scope specified by some expression. For + // example, if we are interpreting the type expression "Foo(Text).Bar", we would start with the + // current scope's BrandScope, create a new child BrandScope representing "Foo", add the "(Text)" + // parameter bindings to it, then create a further child scope for "Bar". Thus the BrandScope for + // Bar knows that Foo's parameter list has been bound to "(Text)". + +public: + BrandScope(ErrorReporter& errorReporter, uint64_t startingScopeId, + uint startingScopeParamCount, Resolver& startingScope); + // TODO(bug): Passing an `errorReporter` to the constructor of `BrandScope` turns out not to + // make a ton of sense, as an `errorReporter` is meant to report errors in a specific module, + // but `BrandScope` might be constructed while compiling one module but then used when + // compiling a different module, or not compiling a module at all. Note, though, that it DOES + // make sense for BrandedDecl to have an ErrorReporter, specifically associated with its + // `source` expression. + + bool isGeneric(); + // Returns true if this scope or any parent scope is a generic (has brand parameters). + + kj::Own push(uint64_t typeId, uint paramCount); + // Creates a new child scope with the given type ID and number of brand parameters. + + kj::Maybe> setParams( + kj::Array params, Declaration::Which genericType, Expression::Reader source); + // Create a new BrandScope representing the same scope, but with parameters filled in. + // + // This should only be called on the generic version of the scope. If called on a branded + // version, an error will be reported. + // + // Returns null if an error occurred that prevented creating the BrandScope; the error will have + // been reported to the ErrorReporter. + + kj::Own pop(uint64_t newLeafId); + // Return the parent scope. + + kj::Maybe lookupParameter(Resolver& resolver, uint64_t scopeId, uint index); + // Search up the scope chain for the scope matching `scopeId`, and return its `index`th parameter + // binding. Returns null if the parameter is from a scope that we are currently compiling, and + // hasn't otherwise been bound to any argument (see Brand.Scope.inherit in schema.capnp). + // + // In the case that a parameter wasn't specified, but isn't part of the current scope, this + // returns the declaration for `AnyPointer`. + // + // TODO(cleanup): Should be called lookupArgument()? + + kj::Maybe> getParams(uint64_t scopeId); + // Get the whole list of parameter bindings at the given scope. Returns null if the scope is + // currently be compiled and the parameters are unbound. + // + // Note that it's possible that not all declared parameters were actually specified for a given + // scope. For example, if you declare a generic `Foo(T, U)`, and then you intiantiate it + // somewhere as `Foo(Text)`, then `U` is unspecified -- this is not an error, because Cap'n + // Proto allows new type parameters to be added over time. `U` should be treated as `AnyPointer` + // in this case, but `getParams()` doesn't know how many parameters are expected, so it will + // return an array that only contains one item. Use `lookupParameter()` if you want unspecified + // parameters to be filled in with `AnyPointer` automatically. + // + // TODO(cleanup): Should be called getArguments()? + + template + void compile(InitBrandFunc&& initBrand); + // Constructs the schema::Brand corresponding to this brand scope. + // + // `initBrand` is a zero-arg functor which returns an empty schema::Brand::Builder, into which + // the brand is constructed. If no generics are present, then `initBrand` is never called. + // + // TODO(cleanup): Should this return Maybe> instead? + + kj::Maybe compileDeclExpression( + Expression::Reader source, Resolver& resolver); + // Interpret a type expression within this branded scope. + + BrandedDecl interpretResolve( + Resolver& resolver, Resolver::ResolveResult& result, Expression::Reader source); + // After using a Resolver to resolve a symbol, call interpretResolve() to interpret the result + // within the current brand scope. For example, if a name resolved to a brand parameter, this + // replaces it with the appropriate argument from the scope. + + inline uint64_t getScopeId() { return leafId; } + +private: + ErrorReporter& errorReporter; + kj::Maybe> parent; + uint64_t leafId; // zero = this is the root + uint leafParamCount; // number of generic parameters on this leaf + bool inherited; + kj::Array params; + + BrandScope(kj::Own parent, uint64_t leafId, uint leafParamCount) + : errorReporter(parent->errorReporter), + parent(kj::mv(parent)), leafId(leafId), leafParamCount(leafParamCount), + inherited(false) {} + BrandScope(BrandScope& base, kj::Array params) + : errorReporter(base.errorReporter), + leafId(base.leafId), leafParamCount(base.leafParamCount), + inherited(false), params(kj::mv(params)) { + KJ_IF_MAYBE(p, base.parent) { + parent = kj::addRef(**p); + } + } + BrandScope(ErrorReporter& errorReporter, uint64_t scopeId) + : errorReporter(errorReporter), leafId(scopeId), leafParamCount(0), inherited(false) {} + + kj::Own evaluateBrand( + Resolver& resolver, Resolver::ResolvedDecl decl, + List::Reader brand, uint index = 0); + + BrandedDecl decompileType(Resolver& resolver, schema::Type::Reader type); + + template + friend kj::Own kj::refcounted(Params&&... params); + friend class BrandedDecl; +}; + +template +uint64_t BrandedDecl::getIdAndFillBrand(InitBrandFunc&& initBrand) { + KJ_REQUIRE(body.is()); + + brand->compile(kj::fwd(initBrand)); + return body.get().id; +} + +template +void BrandScope::compile(InitBrandFunc&& initBrand) { + kj::Vector levels; + BrandScope* ptr = this; + for (;;) { + if (ptr->params.size() > 0 || (ptr->inherited && ptr->leafParamCount > 0)) { + levels.add(ptr); + } + KJ_IF_MAYBE(p, ptr->parent) { + ptr = *p; + } else { + break; + } + } + + if (levels.size() > 0) { + auto scopes = initBrand().initScopes(levels.size()); + for (uint i: kj::indices(levels)) { + auto scope = scopes[i]; + scope.setScopeId(levels[i]->leafId); + + if (levels[i]->inherited) { + scope.setInherit(); + } else { + auto bindings = scope.initBind(levels[i]->params.size()); + for (uint j: kj::indices(bindings)) { + levels[i]->params[j].compileAsType(errorReporter, bindings[j].initType()); + } + } + } + } +} + +} // namespace compiler +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/compiler/grammar.capnp.c++ b/vendor/capnproto/src/capnp/compiler/grammar.capnp.c++ new file mode 100644 index 0000000..3a2c3a6 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/grammar.capnp.c++ @@ -0,0 +1,2978 @@ +// Generated by Cap'n Proto compiler, DO NOT EDIT +// source: grammar.capnp + +#include "grammar.capnp.h" + +namespace capnp { +namespace schemas { +static const ::capnp::_::AlignedData<66> b_e75816b56529d464 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 100, 212, 41, 101, 181, 22, 88, 231, + 29, 0, 0, 0, 1, 0, 1, 0, + 198, 195, 187, 220, 104, 225, 107, 197, + 1, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 74, 1, 0, 0, + 41, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 37, 0, 0, 0, 175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 76, 111, 99, + 97, 116, 101, 100, 84, 101, 120, 116, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 12, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 69, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 3, 0, 1, 0, + 76, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 73, 0, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 72, 0, 0, 0, 3, 0, 1, 0, + 84, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 81, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 3, 0, 1, 0, + 88, 0, 0, 0, 2, 0, 1, 0, + 118, 97, 108, 117, 101, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 97, 114, 116, 66, 121, 116, + 101, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 110, 100, 66, 121, 116, 101, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_e75816b56529d464 = b_e75816b56529d464.words; +static const uint16_t m_e75816b56529d464[] = {2, 1, 0}; +static const uint16_t i_e75816b56529d464[] = {0, 1, 2}; +const ::capnp::_::RawSchema s_e75816b56529d464 = { + 0xe75816b56529d464, b_e75816b56529d464.words, 66, nullptr, m_e75816b56529d464, + 0, 3, i_e75816b56529d464, nullptr, nullptr, { &s_e75816b56529d464, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<66> b_991c7a3693d62cf2 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 242, 44, 214, 147, 54, 122, 28, 153, + 29, 0, 0, 0, 1, 0, 2, 0, + 198, 195, 187, 220, 104, 225, 107, 197, + 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 98, 1, 0, 0, + 41, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 37, 0, 0, 0, 175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 76, 111, 99, + 97, 116, 101, 100, 73, 110, 116, 101, + 103, 101, 114, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 12, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 69, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 3, 0, 1, 0, + 76, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 73, 0, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 72, 0, 0, 0, 3, 0, 1, 0, + 84, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 81, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 3, 0, 1, 0, + 88, 0, 0, 0, 2, 0, 1, 0, + 118, 97, 108, 117, 101, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 97, 114, 116, 66, 121, 116, + 101, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 110, 100, 66, 121, 116, 101, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_991c7a3693d62cf2 = b_991c7a3693d62cf2.words; +static const uint16_t m_991c7a3693d62cf2[] = {2, 1, 0}; +static const uint16_t i_991c7a3693d62cf2[] = {0, 1, 2}; +const ::capnp::_::RawSchema s_991c7a3693d62cf2 = { + 0x991c7a3693d62cf2, b_991c7a3693d62cf2.words, 66, nullptr, m_991c7a3693d62cf2, + 0, 3, i_991c7a3693d62cf2, nullptr, nullptr, { &s_991c7a3693d62cf2, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<66> b_90f2a60678fd2367 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 103, 35, 253, 120, 6, 166, 242, 144, + 29, 0, 0, 0, 1, 0, 2, 0, + 198, 195, 187, 220, 104, 225, 107, 197, + 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 82, 1, 0, 0, + 41, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 37, 0, 0, 0, 175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 76, 111, 99, + 97, 116, 101, 100, 70, 108, 111, 97, + 116, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 12, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 69, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 3, 0, 1, 0, + 76, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 73, 0, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 72, 0, 0, 0, 3, 0, 1, 0, + 84, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 81, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 3, 0, 1, 0, + 88, 0, 0, 0, 2, 0, 1, 0, + 118, 97, 108, 117, 101, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 97, 114, 116, 66, 121, 116, + 101, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 110, 100, 66, 121, 116, 101, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_90f2a60678fd2367 = b_90f2a60678fd2367.words; +static const uint16_t m_90f2a60678fd2367[] = {2, 1, 0}; +static const uint16_t i_90f2a60678fd2367[] = {0, 1, 2}; +const ::capnp::_::RawSchema s_90f2a60678fd2367 = { + 0x90f2a60678fd2367, b_90f2a60678fd2367.words, 66, nullptr, m_90f2a60678fd2367, + 0, 3, i_90f2a60678fd2367, nullptr, nullptr, { &s_90f2a60678fd2367, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<262> b_8e207d4dfe54d0de = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 29, 0, 0, 0, 1, 0, 3, 0, + 198, 195, 187, 220, 104, 225, 107, 197, + 2, 0, 7, 0, 0, 0, 14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 66, 1, 0, 0, + 37, 0, 0, 0, 23, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 135, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 69, 120, 112, + 114, 101, 115, 115, 105, 111, 110, 0, + 4, 0, 0, 0, 1, 0, 1, 0, + 170, 219, 222, 26, 183, 70, 2, 201, + 1, 0, 0, 0, 50, 0, 0, 0, + 80, 97, 114, 97, 109, 0, 0, 0, + 64, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 177, 1, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 172, 1, 0, 0, 3, 0, 1, 0, + 184, 1, 0, 0, 2, 0, 1, 0, + 1, 0, 254, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 181, 1, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 180, 1, 0, 0, 3, 0, 1, 0, + 192, 1, 0, 0, 2, 0, 1, 0, + 2, 0, 253, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 189, 1, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 188, 1, 0, 0, 3, 0, 1, 0, + 200, 1, 0, 0, 2, 0, 1, 0, + 3, 0, 252, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 197, 1, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 192, 1, 0, 0, 3, 0, 1, 0, + 204, 1, 0, 0, 2, 0, 1, 0, + 4, 0, 251, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 201, 1, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 196, 1, 0, 0, 3, 0, 1, 0, + 208, 1, 0, 0, 2, 0, 1, 0, + 6, 0, 250, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 205, 1, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 204, 1, 0, 0, 3, 0, 1, 0, + 216, 1, 0, 0, 2, 0, 1, 0, + 10, 0, 249, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 213, 1, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 208, 1, 0, 0, 3, 0, 1, 0, + 236, 1, 0, 0, 2, 0, 1, 0, + 11, 0, 248, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 233, 1, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 228, 1, 0, 0, 3, 0, 1, 0, + 0, 2, 0, 0, 2, 0, 1, 0, + 14, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 253, 1, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 252, 1, 0, 0, 3, 0, 1, 0, + 8, 2, 0, 0, 2, 0, 1, 0, + 15, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 1, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 2, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 3, 0, 1, 0, + 12, 2, 0, 0, 2, 0, 1, 0, + 5, 0, 247, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 2, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 2, 0, 0, 3, 0, 1, 0, + 16, 2, 0, 0, 2, 0, 1, 0, + 12, 0, 246, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 122, 223, 176, 64, 112, 57, 232, 174, + 13, 2, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 245, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 89, 51, 121, 13, 64, 225, 40, 170, + 249, 1, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 244, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 225, 1, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 224, 1, 0, 0, 3, 0, 1, 0, + 236, 1, 0, 0, 2, 0, 1, 0, + 8, 0, 243, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 233, 1, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 228, 1, 0, 0, 3, 0, 1, 0, + 240, 1, 0, 0, 2, 0, 1, 0, + 9, 0, 242, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 237, 1, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 232, 1, 0, 0, 3, 0, 1, 0, + 244, 1, 0, 0, 2, 0, 1, 0, + 117, 110, 107, 110, 111, 119, 110, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 111, 115, 105, 116, 105, 118, 101, + 73, 110, 116, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 110, 101, 103, 97, 116, 105, 118, 101, + 73, 110, 116, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 102, 108, 111, 97, 116, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 114, 105, 110, 103, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 114, 101, 108, 97, 116, 105, 118, 101, + 78, 97, 109, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 100, 212, 41, 101, 181, 22, 88, 231, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 108, 105, 115, 116, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 117, 112, 108, 101, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 170, 219, 222, 26, 183, 70, 2, 201, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 97, 114, 116, 66, 121, 116, + 101, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 110, 100, 66, 121, 116, 101, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 105, 110, 97, 114, 121, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 112, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 0, 0, 0, 0, 0, + 109, 101, 109, 98, 101, 114, 0, 0, + 97, 98, 115, 111, 108, 117, 116, 101, + 78, 97, 109, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 100, 212, 41, 101, 181, 22, 88, 231, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 109, 112, 111, 114, 116, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 100, 212, 41, 101, 181, 22, 88, 231, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 109, 98, 101, 100, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 100, 212, 41, 101, 181, 22, 88, 231, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_8e207d4dfe54d0de = b_8e207d4dfe54d0de.words; +static const ::capnp::_::RawSchema* const d_8e207d4dfe54d0de[] = { + &s_8e207d4dfe54d0de, + &s_aa28e1400d793359, + &s_aee8397040b0df7a, + &s_c90246b71adedbaa, + &s_e75816b56529d464, +}; +static const uint16_t m_8e207d4dfe54d0de[] = {13, 11, 10, 15, 9, 3, 14, 6, 12, 2, 1, 5, 8, 4, 7, 0}; +static const uint16_t i_8e207d4dfe54d0de[] = {0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 8, 9}; +const ::capnp::_::RawSchema s_8e207d4dfe54d0de = { + 0x8e207d4dfe54d0de, b_8e207d4dfe54d0de.words, 262, d_8e207d4dfe54d0de, m_8e207d4dfe54d0de, + 5, 16, i_8e207d4dfe54d0de, nullptr, nullptr, { &s_8e207d4dfe54d0de, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<65> b_c90246b71adedbaa = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 170, 219, 222, 26, 183, 70, 2, 201, + 40, 0, 0, 0, 1, 0, 1, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 2, 0, 7, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 114, 1, 0, 0, + 41, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 37, 0, 0, 0, 175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 69, 120, 112, + 114, 101, 115, 115, 105, 111, 110, 46, + 80, 97, 114, 97, 109, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 12, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 69, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 3, 0, 1, 0, + 76, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 254, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 73, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 68, 0, 0, 0, 3, 0, 1, 0, + 80, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 77, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 72, 0, 0, 0, 3, 0, 1, 0, + 84, 0, 0, 0, 2, 0, 1, 0, + 117, 110, 110, 97, 109, 101, 100, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 110, 97, 109, 101, 100, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 100, 212, 41, 101, 181, 22, 88, 231, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 118, 97, 108, 117, 101, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_c90246b71adedbaa = b_c90246b71adedbaa.words; +static const ::capnp::_::RawSchema* const d_c90246b71adedbaa[] = { + &s_8e207d4dfe54d0de, + &s_e75816b56529d464, +}; +static const uint16_t m_c90246b71adedbaa[] = {1, 0, 2}; +static const uint16_t i_c90246b71adedbaa[] = {0, 1, 2}; +const ::capnp::_::RawSchema s_c90246b71adedbaa = { + 0xc90246b71adedbaa, b_c90246b71adedbaa.words, 65, d_c90246b71adedbaa, m_c90246b71adedbaa, + 2, 3, i_c90246b71adedbaa, nullptr, nullptr, { &s_c90246b71adedbaa, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<55> b_aee8397040b0df7a = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 122, 223, 176, 64, 112, 57, 232, 174, + 40, 0, 0, 0, 1, 0, 3, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 2, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 162, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 37, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 69, 120, 112, + 114, 101, 115, 115, 105, 111, 110, 46, + 97, 112, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 74, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 52, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 49, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 44, 0, 0, 0, 3, 0, 1, 0, + 72, 0, 0, 0, 2, 0, 1, 0, + 102, 117, 110, 99, 116, 105, 111, 110, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 97, 114, 97, 109, 115, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 170, 219, 222, 26, 183, 70, 2, 201, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_aee8397040b0df7a = b_aee8397040b0df7a.words; +static const ::capnp::_::RawSchema* const d_aee8397040b0df7a[] = { + &s_8e207d4dfe54d0de, + &s_c90246b71adedbaa, +}; +static const uint16_t m_aee8397040b0df7a[] = {0, 1}; +static const uint16_t i_aee8397040b0df7a[] = {0, 1}; +const ::capnp::_::RawSchema s_aee8397040b0df7a = { + 0xaee8397040b0df7a, b_aee8397040b0df7a.words, 55, d_aee8397040b0df7a, m_aee8397040b0df7a, + 2, 2, i_aee8397040b0df7a, nullptr, nullptr, { &s_aee8397040b0df7a, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<49> b_aa28e1400d793359 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 89, 51, 121, 13, 64, 225, 40, 170, + 40, 0, 0, 0, 1, 0, 3, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 2, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 122, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 69, 120, 112, + 114, 101, 115, 115, 105, 111, 110, 46, + 109, 101, 109, 98, 101, 114, 0, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 52, 0, 0, 0, 2, 0, 1, 0, + 112, 97, 114, 101, 110, 116, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 110, 97, 109, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 100, 212, 41, 101, 181, 22, 88, 231, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_aa28e1400d793359 = b_aa28e1400d793359.words; +static const ::capnp::_::RawSchema* const d_aa28e1400d793359[] = { + &s_8e207d4dfe54d0de, + &s_e75816b56529d464, +}; +static const uint16_t m_aa28e1400d793359[] = {1, 0}; +static const uint16_t i_aa28e1400d793359[] = {0, 1}; +const ::capnp::_::RawSchema s_aa28e1400d793359 = { + 0xaa28e1400d793359, b_aa28e1400d793359.words, 49, d_aa28e1400d793359, m_aa28e1400d793359, + 2, 2, i_aa28e1400d793359, nullptr, nullptr, { &s_aa28e1400d793359, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<677> b_96efe787c17e83bb = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 29, 0, 0, 0, 1, 0, 2, 0, + 198, 195, 187, 220, 104, 225, 107, 197, + 8, 0, 7, 0, 0, 0, 34, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 74, 1, 0, 0, + 41, 0, 0, 0, 87, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 117, 0, 0, 0, 55, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 0, 0, 0, 0, 0, 0, 0, 0, + 20, 0, 0, 0, 1, 0, 1, 0, + 117, 225, 28, 175, 68, 17, 231, 213, + 33, 0, 0, 0, 122, 0, 0, 0, + 144, 98, 130, 115, 212, 137, 4, 208, + 33, 0, 0, 0, 178, 0, 0, 0, + 107, 45, 179, 158, 63, 156, 9, 148, + 37, 0, 0, 0, 114, 0, 0, 0, + 205, 27, 216, 121, 122, 110, 246, 179, + 37, 0, 0, 0, 82, 0, 0, 0, + 165, 210, 151, 166, 169, 8, 254, 255, + 37, 0, 0, 0, 50, 0, 0, 0, + 66, 114, 97, 110, 100, 80, 97, 114, + 97, 109, 101, 116, 101, 114, 0, 0, + 65, 110, 110, 111, 116, 97, 116, 105, + 111, 110, 65, 112, 112, 108, 105, 99, + 97, 116, 105, 111, 110, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 80, + 97, 114, 97, 109, 115, 0, 0, 0, + 80, 97, 114, 97, 109, 76, 105, 115, + 116, 0, 0, 0, 0, 0, 0, 0, + 80, 97, 114, 97, 109, 0, 0, 0, + 168, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 137, 4, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 132, 4, 0, 0, 3, 0, 1, 0, + 144, 4, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 150, 174, 3, 193, 115, 201, 240, 137, + 141, 4, 0, 0, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 117, 4, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 4, 0, 0, 3, 0, 1, 0, + 144, 4, 0, 0, 2, 0, 1, 0, + 4, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 1, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 141, 4, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 140, 4, 0, 0, 3, 0, 1, 0, + 168, 4, 0, 0, 2, 0, 1, 0, + 5, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 165, 4, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 164, 4, 0, 0, 3, 0, 1, 0, + 176, 4, 0, 0, 2, 0, 1, 0, + 6, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 173, 4, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 168, 4, 0, 0, 3, 0, 1, 0, + 180, 4, 0, 0, 2, 0, 1, 0, + 7, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 1, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 177, 4, 0, 0, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 176, 4, 0, 0, 3, 0, 1, 0, + 188, 4, 0, 0, 2, 0, 1, 0, + 8, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 185, 4, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 180, 4, 0, 0, 3, 0, 1, 0, + 192, 4, 0, 0, 2, 0, 1, 0, + 9, 0, 254, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 207, 44, 254, 11, 168, 100, 49, 233, + 189, 4, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 0, 253, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 12, 13, 207, 141, 42, 50, 72, 179, + 165, 4, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 11, 0, 252, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 141, 4, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 136, 4, 0, 0, 3, 0, 1, 0, + 148, 4, 0, 0, 2, 0, 1, 0, + 12, 0, 251, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 145, 4, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 144, 4, 0, 0, 3, 0, 1, 0, + 156, 4, 0, 0, 2, 0, 1, 0, + 13, 0, 250, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 153, 4, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 148, 4, 0, 0, 3, 0, 1, 0, + 160, 4, 0, 0, 2, 0, 1, 0, + 14, 0, 249, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 200, 88, 179, 143, 32, 34, 38, 143, + 157, 4, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 15, 0, 248, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 133, 4, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 128, 4, 0, 0, 3, 0, 1, 0, + 140, 4, 0, 0, 2, 0, 1, 0, + 16, 0, 247, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 20, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 137, 4, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 132, 4, 0, 0, 3, 0, 1, 0, + 144, 4, 0, 0, 2, 0, 1, 0, + 17, 0, 246, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 211, 53, 2, 243, 234, 144, 42, 153, + 141, 4, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 18, 0, 245, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 185, 192, 23, 214, 71, 24, 151, 235, + 121, 4, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 0, 244, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 127, 3, 152, 49, 110, 232, 185, 156, + 97, 4, 0, 0, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 20, 0, 243, 255, 5, 0, 0, 0, + 0, 0, 1, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 77, 4, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 72, 4, 0, 0, 3, 0, 1, 0, + 84, 4, 0, 0, 2, 0, 1, 0, + 21, 0, 242, 255, 5, 0, 0, 0, + 0, 0, 1, 0, 39, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 81, 4, 0, 0, 130, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 80, 4, 0, 0, 3, 0, 1, 0, + 92, 4, 0, 0, 2, 0, 1, 0, + 22, 0, 241, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 40, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 89, 4, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 88, 4, 0, 0, 3, 0, 1, 0, + 100, 4, 0, 0, 2, 0, 1, 0, + 23, 0, 240, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 41, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 4, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 96, 4, 0, 0, 3, 0, 1, 0, + 108, 4, 0, 0, 2, 0, 1, 0, + 24, 0, 239, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 4, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 104, 4, 0, 0, 3, 0, 1, 0, + 116, 4, 0, 0, 2, 0, 1, 0, + 25, 0, 238, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 43, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 113, 4, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 4, 0, 0, 3, 0, 1, 0, + 124, 4, 0, 0, 2, 0, 1, 0, + 26, 0, 237, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 44, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 121, 4, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 120, 4, 0, 0, 3, 0, 1, 0, + 132, 4, 0, 0, 2, 0, 1, 0, + 27, 0, 236, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 45, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 129, 4, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 128, 4, 0, 0, 3, 0, 1, 0, + 140, 4, 0, 0, 2, 0, 1, 0, + 28, 0, 235, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 46, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 137, 4, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 136, 4, 0, 0, 3, 0, 1, 0, + 148, 4, 0, 0, 2, 0, 1, 0, + 29, 0, 234, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 47, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 145, 4, 0, 0, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 144, 4, 0, 0, 3, 0, 1, 0, + 156, 4, 0, 0, 2, 0, 1, 0, + 30, 0, 233, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 153, 4, 0, 0, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 152, 4, 0, 0, 3, 0, 1, 0, + 164, 4, 0, 0, 2, 0, 1, 0, + 31, 0, 232, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 49, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 161, 4, 0, 0, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 160, 4, 0, 0, 3, 0, 1, 0, + 172, 4, 0, 0, 2, 0, 1, 0, + 32, 0, 231, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 169, 4, 0, 0, 122, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 168, 4, 0, 0, 3, 0, 1, 0, + 180, 4, 0, 0, 2, 0, 1, 0, + 33, 0, 230, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 51, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 177, 4, 0, 0, 122, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 176, 4, 0, 0, 3, 0, 1, 0, + 188, 4, 0, 0, 2, 0, 1, 0, + 34, 0, 229, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 52, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 185, 4, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 184, 4, 0, 0, 3, 0, 1, 0, + 196, 4, 0, 0, 2, 0, 1, 0, + 35, 0, 228, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 53, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 193, 4, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 192, 4, 0, 0, 3, 0, 1, 0, + 204, 4, 0, 0, 2, 0, 1, 0, + 36, 0, 227, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 54, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 201, 4, 0, 0, 98, 0, 0, 0, + 205, 4, 0, 0, 31, 0, 0, 0, + 248, 4, 0, 0, 3, 0, 1, 0, + 4, 5, 0, 0, 2, 0, 1, 0, + 37, 0, 226, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 55, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 5, 0, 0, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 0, 0, 3, 0, 1, 0, + 12, 5, 0, 0, 2, 0, 1, 0, + 38, 0, 225, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 5, 0, 0, 146, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 5, 0, 0, 3, 0, 1, 0, + 24, 5, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 1, 0, 57, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 5, 0, 0, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 20, 5, 0, 0, 3, 0, 1, 0, + 48, 5, 0, 0, 2, 0, 1, 0, + 39, 0, 224, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 5, 0, 0, 138, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 48, 5, 0, 0, 3, 0, 1, 0, + 60, 5, 0, 0, 2, 0, 1, 0, + 40, 0, 223, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 59, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 57, 5, 0, 0, 122, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 56, 5, 0, 0, 3, 0, 1, 0, + 68, 5, 0, 0, 2, 0, 1, 0, + 41, 0, 222, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 60, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 65, 5, 0, 0, 146, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 68, 5, 0, 0, 3, 0, 1, 0, + 80, 5, 0, 0, 2, 0, 1, 0, + 110, 97, 109, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 100, 212, 41, 101, 181, 22, 88, 231, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 100, 0, 0, 0, 0, 0, 0, + 110, 101, 115, 116, 101, 100, 68, 101, + 99, 108, 115, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 110, 110, 111, 116, 97, 116, 105, + 111, 110, 115, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 144, 98, 130, 115, 212, 137, 4, 208, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 97, 114, 116, 66, 121, 116, + 101, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 110, 100, 66, 121, 116, 101, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 111, 99, 67, 111, 109, 109, 101, + 110, 116, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 102, 105, 108, 101, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 117, 115, 105, 110, 103, 0, 0, 0, + 99, 111, 110, 115, 116, 0, 0, 0, + 101, 110, 117, 109, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 110, 117, 109, 101, 114, 97, 110, + 116, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 114, 117, 99, 116, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 102, 105, 101, 108, 100, 0, 0, 0, + 117, 110, 105, 111, 110, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 103, 114, 111, 117, 112, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 110, 116, 101, 114, 102, 97, 99, + 101, 0, 0, 0, 0, 0, 0, 0, + 109, 101, 116, 104, 111, 100, 0, 0, + 97, 110, 110, 111, 116, 97, 116, 105, + 111, 110, 0, 0, 0, 0, 0, 0, + 110, 97, 107, 101, 100, 73, 100, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 242, 44, 214, 147, 54, 122, 28, 153, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 110, 97, 107, 101, 100, 65, 110, 110, + 111, 116, 97, 116, 105, 111, 110, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 144, 98, 130, 115, 212, 137, 4, 208, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 86, + 111, 105, 100, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 66, + 111, 111, 108, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 73, + 110, 116, 56, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 73, + 110, 116, 49, 54, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 73, + 110, 116, 51, 50, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 73, + 110, 116, 54, 52, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 85, + 73, 110, 116, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 85, + 73, 110, 116, 49, 54, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 85, + 73, 110, 116, 51, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 85, + 73, 110, 116, 54, 52, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 70, + 108, 111, 97, 116, 51, 50, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 70, + 108, 111, 97, 116, 54, 52, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 84, + 101, 120, 116, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 68, + 97, 116, 97, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 76, + 105, 115, 116, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 1, 0, 2, 0, + 107, 45, 179, 158, 63, 156, 9, 148, + 4, 0, 0, 0, 2, 0, 1, 0, + 28, 0, 0, 0, 0, 0, 1, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 23, 0, 0, 0, + 4, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 66, 0, 0, 0, + 69, 108, 101, 109, 101, 110, 116, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 79, + 98, 106, 101, 99, 116, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 65, + 110, 121, 80, 111, 105, 110, 116, 101, + 114, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 97, 114, 97, 109, 101, 116, 101, + 114, 115, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 117, 225, 28, 175, 68, 17, 231, 213, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 65, + 110, 121, 83, 116, 114, 117, 99, 116, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 65, + 110, 121, 76, 105, 115, 116, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 117, 105, 108, 116, 105, 110, 67, + 97, 112, 97, 98, 105, 108, 105, 116, + 121, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_96efe787c17e83bb = b_96efe787c17e83bb.words; +static const ::capnp::_::RawSchema* const d_96efe787c17e83bb[] = { + &s_89f0c973c103ae96, + &s_8f2622208fb358c8, + &s_96efe787c17e83bb, + &s_991c7a3693d62cf2, + &s_992a90eaf30235d3, + &s_9cb9e86e3198037f, + &s_b348322a8dcf0d0c, + &s_d00489d473826290, + &s_d5e71144af1ce175, + &s_e75816b56529d464, + &s_e93164a80bfe2ccf, + &s_eb971847d617c0b9, +}; +static const uint16_t m_96efe787c17e83bb[] = {18, 3, 40, 37, 39, 22, 41, 34, 31, 32, 24, 25, 26, 23, 35, 36, 33, 28, 29, 30, 27, 21, 9, 6, 5, 10, 11, 13, 7, 15, 1, 16, 17, 20, 19, 0, 2, 38, 4, 12, 14, 8}; +static const uint16_t i_96efe787c17e83bb[] = {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 40, 41, 0, 1, 2, 3, 4, 5, 6, 38}; +const ::capnp::_::RawSchema s_96efe787c17e83bb = { + 0x96efe787c17e83bb, b_96efe787c17e83bb.words, 677, d_96efe787c17e83bb, m_96efe787c17e83bb, + 12, 42, i_96efe787c17e83bb, nullptr, nullptr, { &s_96efe787c17e83bb, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<67> b_d5e71144af1ce175 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 117, 225, 28, 175, 68, 17, 231, 213, + 41, 0, 0, 0, 1, 0, 1, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 1, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 194, 1, 0, 0, + 45, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 66, 114, 97, 110, 100, 80, 97, + 114, 97, 109, 101, 116, 101, 114, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 12, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 69, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 3, 0, 1, 0, + 76, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 73, 0, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 72, 0, 0, 0, 3, 0, 1, 0, + 84, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 81, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 3, 0, 1, 0, + 88, 0, 0, 0, 2, 0, 1, 0, + 110, 97, 109, 101, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 97, 114, 116, 66, 121, 116, + 101, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 110, 100, 66, 121, 116, 101, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_d5e71144af1ce175 = b_d5e71144af1ce175.words; +static const uint16_t m_d5e71144af1ce175[] = {2, 0, 1}; +static const uint16_t i_d5e71144af1ce175[] = {0, 1, 2}; +const ::capnp::_::RawSchema s_d5e71144af1ce175 = { + 0xd5e71144af1ce175, b_d5e71144af1ce175.words, 67, nullptr, m_d5e71144af1ce175, + 0, 3, i_d5e71144af1ce175, nullptr, nullptr, { &s_d5e71144af1ce175, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<45> b_d00489d473826290 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 144, 98, 130, 115, 212, 137, 4, 208, + 41, 0, 0, 0, 1, 0, 1, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 2, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 250, 1, 0, 0, + 49, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 65, 110, 110, 111, 116, 97, 116, + 105, 111, 110, 65, 112, 112, 108, 105, + 99, 97, 116, 105, 111, 110, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 249, 106, 223, 92, 217, 238, 90, 251, + 45, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 110, 97, 109, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 118, 97, 108, 117, 101, 0, 0, 0, } +}; +::capnp::word const* const bp_d00489d473826290 = b_d00489d473826290.words; +static const ::capnp::_::RawSchema* const d_d00489d473826290[] = { + &s_8e207d4dfe54d0de, + &s_fb5aeed95cdf6af9, +}; +static const uint16_t m_d00489d473826290[] = {0, 1}; +static const uint16_t i_d00489d473826290[] = {0, 1}; +const ::capnp::_::RawSchema s_d00489d473826290 = { + 0xd00489d473826290, b_d00489d473826290.words, 45, d_d00489d473826290, m_d00489d473826290, + 2, 2, i_d00489d473826290, nullptr, nullptr, { &s_d00489d473826290, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<53> b_fb5aeed95cdf6af9 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 249, 106, 223, 92, 217, 238, 90, 251, + 63, 0, 0, 0, 1, 0, 1, 0, + 144, 98, 130, 115, 212, 137, 4, 208, + 2, 0, 7, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 42, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 65, 110, 110, 111, 116, 97, 116, + 105, 111, 110, 65, 112, 112, 108, 105, + 99, 97, 116, 105, 111, 110, 46, 118, + 97, 108, 117, 101, 0, 0, 0, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 254, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 44, 0, 0, 0, 3, 0, 1, 0, + 56, 0, 0, 0, 2, 0, 1, 0, + 110, 111, 110, 101, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 120, 112, 114, 101, 115, 115, 105, + 111, 110, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_fb5aeed95cdf6af9 = b_fb5aeed95cdf6af9.words; +static const ::capnp::_::RawSchema* const d_fb5aeed95cdf6af9[] = { + &s_8e207d4dfe54d0de, + &s_d00489d473826290, +}; +static const uint16_t m_fb5aeed95cdf6af9[] = {1, 0}; +static const uint16_t i_fb5aeed95cdf6af9[] = {0, 1}; +const ::capnp::_::RawSchema s_fb5aeed95cdf6af9 = { + 0xfb5aeed95cdf6af9, b_fb5aeed95cdf6af9.words, 53, d_fb5aeed95cdf6af9, m_fb5aeed95cdf6af9, + 2, 2, i_fb5aeed95cdf6af9, nullptr, nullptr, { &s_fb5aeed95cdf6af9, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<28> b_94099c3f9eb32d6b = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 107, 45, 179, 158, 63, 156, 9, 148, + 41, 0, 0, 0, 5, 0, 32, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 186, 1, 0, 0, + 45, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 98, 117, 105, 108, 116, 105, 110, + 80, 97, 114, 97, 109, 115, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 117, 225, 28, 175, 68, 17, 231, 213, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_94099c3f9eb32d6b = b_94099c3f9eb32d6b.words; +const ::capnp::_::RawSchema s_94099c3f9eb32d6b = { + 0x94099c3f9eb32d6b, b_94099c3f9eb32d6b.words, 28, nullptr, nullptr, + 0, 0, nullptr, nullptr, nullptr, { &s_94099c3f9eb32d6b, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<102> b_b3f66e7a79d81bcd = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 205, 27, 216, 121, 122, 110, 246, 179, + 41, 0, 0, 0, 1, 0, 2, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 1, 0, 7, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 154, 1, 0, 0, + 45, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 31, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 80, 97, 114, 97, 109, 76, 105, + 115, 116, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 20, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 125, 0, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 124, 0, 0, 0, 3, 0, 1, 0, + 152, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 254, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 149, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 144, 0, 0, 0, 3, 0, 1, 0, + 156, 0, 0, 0, 2, 0, 1, 0, + 3, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 153, 0, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 152, 0, 0, 0, 3, 0, 1, 0, + 164, 0, 0, 0, 2, 0, 1, 0, + 4, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 161, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 156, 0, 0, 0, 3, 0, 1, 0, + 168, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 253, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 165, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 160, 0, 0, 0, 3, 0, 1, 0, + 172, 0, 0, 0, 2, 0, 1, 0, + 110, 97, 109, 101, 100, 76, 105, 115, + 116, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 165, 210, 151, 166, 169, 8, 254, 255, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 121, 112, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 97, 114, 116, 66, 121, 116, + 101, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 110, 100, 66, 121, 116, 101, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 114, 101, 97, 109, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_b3f66e7a79d81bcd = b_b3f66e7a79d81bcd.words; +static const ::capnp::_::RawSchema* const d_b3f66e7a79d81bcd[] = { + &s_8e207d4dfe54d0de, + &s_fffe08a9a697d2a5, +}; +static const uint16_t m_b3f66e7a79d81bcd[] = {3, 0, 2, 4, 1}; +static const uint16_t i_b3f66e7a79d81bcd[] = {0, 1, 4, 2, 3}; +const ::capnp::_::RawSchema s_b3f66e7a79d81bcd = { + 0xb3f66e7a79d81bcd, b_b3f66e7a79d81bcd.words, 102, d_b3f66e7a79d81bcd, m_b3f66e7a79d81bcd, + 2, 5, i_b3f66e7a79d81bcd, nullptr, nullptr, { &s_b3f66e7a79d81bcd, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<110> b_fffe08a9a697d2a5 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 165, 210, 151, 166, 169, 8, 254, 255, + 41, 0, 0, 0, 1, 0, 2, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 4, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 122, 1, 0, 0, + 41, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 37, 0, 0, 0, 87, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 80, 97, 114, 97, 109, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 24, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 153, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 148, 0, 0, 0, 3, 0, 1, 0, + 160, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 157, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 152, 0, 0, 0, 3, 0, 1, 0, + 164, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 161, 0, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 160, 0, 0, 0, 3, 0, 1, 0, + 188, 0, 0, 0, 2, 0, 1, 0, + 3, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 71, 234, 136, 253, 21, 69, 16, 229, + 185, 0, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 165, 0, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 164, 0, 0, 0, 3, 0, 1, 0, + 176, 0, 0, 0, 2, 0, 1, 0, + 5, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 173, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 168, 0, 0, 0, 3, 0, 1, 0, + 180, 0, 0, 0, 2, 0, 1, 0, + 110, 97, 109, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 100, 212, 41, 101, 181, 22, 88, 231, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 121, 112, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 110, 110, 111, 116, 97, 116, 105, + 111, 110, 115, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 144, 98, 130, 115, 212, 137, 4, 208, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 101, 102, 97, 117, 108, 116, 86, + 97, 108, 117, 101, 0, 0, 0, 0, + 115, 116, 97, 114, 116, 66, 121, 116, + 101, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 110, 100, 66, 121, 116, 101, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_fffe08a9a697d2a5 = b_fffe08a9a697d2a5.words; +static const ::capnp::_::RawSchema* const d_fffe08a9a697d2a5[] = { + &s_8e207d4dfe54d0de, + &s_d00489d473826290, + &s_e5104515fd88ea47, + &s_e75816b56529d464, +}; +static const uint16_t m_fffe08a9a697d2a5[] = {2, 3, 5, 0, 4, 1}; +static const uint16_t i_fffe08a9a697d2a5[] = {0, 1, 2, 3, 4, 5}; +const ::capnp::_::RawSchema s_fffe08a9a697d2a5 = { + 0xfffe08a9a697d2a5, b_fffe08a9a697d2a5.words, 110, d_fffe08a9a697d2a5, m_fffe08a9a697d2a5, + 4, 6, i_fffe08a9a697d2a5, nullptr, nullptr, { &s_fffe08a9a697d2a5, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<51> b_e5104515fd88ea47 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 71, 234, 136, 253, 21, 69, 16, 229, + 47, 0, 0, 0, 1, 0, 2, 0, + 165, 210, 151, 166, 169, 8, 254, 255, + 4, 0, 7, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 226, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 80, 97, 114, 97, 109, 46, 100, + 101, 102, 97, 117, 108, 116, 86, 97, + 108, 117, 101, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 254, 255, 3, 0, 0, 0, + 0, 0, 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 52, 0, 0, 0, 2, 0, 1, 0, + 110, 111, 110, 101, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 118, 97, 108, 117, 101, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_e5104515fd88ea47 = b_e5104515fd88ea47.words; +static const ::capnp::_::RawSchema* const d_e5104515fd88ea47[] = { + &s_8e207d4dfe54d0de, + &s_fffe08a9a697d2a5, +}; +static const uint16_t m_e5104515fd88ea47[] = {0, 1}; +static const uint16_t i_e5104515fd88ea47[] = {0, 1}; +const ::capnp::_::RawSchema s_e5104515fd88ea47 = { + 0xe5104515fd88ea47, b_e5104515fd88ea47.words, 51, d_e5104515fd88ea47, m_e5104515fd88ea47, + 2, 2, i_e5104515fd88ea47, nullptr, nullptr, { &s_e5104515fd88ea47, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<65> b_89f0c973c103ae96 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 150, 174, 3, 193, 115, 201, 240, 137, + 41, 0, 0, 0, 1, 0, 2, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 8, 0, 7, 0, 1, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 98, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 105, 100, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 69, 0, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 68, 0, 0, 0, 3, 0, 1, 0, + 80, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 254, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 77, 0, 0, 0, 34, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 72, 0, 0, 0, 3, 0, 1, 0, + 84, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 253, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 81, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 3, 0, 1, 0, + 88, 0, 0, 0, 2, 0, 1, 0, + 117, 110, 115, 112, 101, 99, 105, 102, + 105, 101, 100, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 117, 105, 100, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 242, 44, 214, 147, 54, 122, 28, 153, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 111, 114, 100, 105, 110, 97, 108, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 242, 44, 214, 147, 54, 122, 28, 153, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_89f0c973c103ae96 = b_89f0c973c103ae96.words; +static const ::capnp::_::RawSchema* const d_89f0c973c103ae96[] = { + &s_96efe787c17e83bb, + &s_991c7a3693d62cf2, +}; +static const uint16_t m_89f0c973c103ae96[] = {2, 1, 0}; +static const uint16_t i_89f0c973c103ae96[] = {0, 1, 2}; +const ::capnp::_::RawSchema s_89f0c973c103ae96 = { + 0x89f0c973c103ae96, b_89f0c973c103ae96.words, 65, d_89f0c973c103ae96, m_89f0c973c103ae96, + 2, 3, i_89f0c973c103ae96, nullptr, nullptr, { &s_89f0c973c103ae96, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<34> b_e93164a80bfe2ccf = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 207, 44, 254, 11, 168, 100, 49, 233, + 41, 0, 0, 0, 1, 0, 2, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 8, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 122, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 63, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 117, 115, 105, 110, 103, 0, 0, + 4, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 1, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 3, 0, 1, 0, + 20, 0, 0, 0, 2, 0, 1, 0, + 116, 97, 114, 103, 101, 116, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_e93164a80bfe2ccf = b_e93164a80bfe2ccf.words; +static const ::capnp::_::RawSchema* const d_e93164a80bfe2ccf[] = { + &s_8e207d4dfe54d0de, + &s_96efe787c17e83bb, +}; +static const uint16_t m_e93164a80bfe2ccf[] = {0}; +static const uint16_t i_e93164a80bfe2ccf[] = {0}; +const ::capnp::_::RawSchema s_e93164a80bfe2ccf = { + 0xe93164a80bfe2ccf, b_e93164a80bfe2ccf.words, 34, d_e93164a80bfe2ccf, m_e93164a80bfe2ccf, + 2, 1, i_e93164a80bfe2ccf, nullptr, nullptr, { &s_e93164a80bfe2ccf, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<49> b_b348322a8dcf0d0c = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 12, 13, 207, 141, 42, 50, 72, 179, + 41, 0, 0, 0, 1, 0, 2, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 8, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 122, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 99, 111, 110, 115, 116, 0, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 1, 0, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 1, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 52, 0, 0, 0, 2, 0, 1, 0, + 116, 121, 112, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 118, 97, 108, 117, 101, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_b348322a8dcf0d0c = b_b348322a8dcf0d0c.words; +static const ::capnp::_::RawSchema* const d_b348322a8dcf0d0c[] = { + &s_8e207d4dfe54d0de, + &s_96efe787c17e83bb, +}; +static const uint16_t m_b348322a8dcf0d0c[] = {0, 1}; +static const uint16_t i_b348322a8dcf0d0c[] = {0, 1}; +const ::capnp::_::RawSchema s_b348322a8dcf0d0c = { + 0xb348322a8dcf0d0c, b_b348322a8dcf0d0c.words, 49, d_b348322a8dcf0d0c, m_b348322a8dcf0d0c, + 2, 2, i_b348322a8dcf0d0c, nullptr, nullptr, { &s_b348322a8dcf0d0c, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<43> b_8f2622208fb358c8 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 200, 88, 179, 143, 32, 34, 38, 143, + 41, 0, 0, 0, 1, 0, 2, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 8, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 122, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 102, 105, 101, 108, 100, 0, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 1, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 31, 149, 23, 230, 29, 162, 209, 208, + 45, 0, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 121, 112, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 101, 102, 97, 117, 108, 116, 86, + 97, 108, 117, 101, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_8f2622208fb358c8 = b_8f2622208fb358c8.words; +static const ::capnp::_::RawSchema* const d_8f2622208fb358c8[] = { + &s_8e207d4dfe54d0de, + &s_96efe787c17e83bb, + &s_d0d1a21de617951f, +}; +static const uint16_t m_8f2622208fb358c8[] = {1, 0}; +static const uint16_t i_8f2622208fb358c8[] = {0, 1}; +const ::capnp::_::RawSchema s_8f2622208fb358c8 = { + 0x8f2622208fb358c8, b_8f2622208fb358c8.words, 43, d_8f2622208fb358c8, m_8f2622208fb358c8, + 3, 2, i_8f2622208fb358c8, nullptr, nullptr, { &s_8f2622208fb358c8, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<51> b_d0d1a21de617951f = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 31, 149, 23, 230, 29, 162, 209, 208, + 47, 0, 0, 0, 1, 0, 2, 0, + 200, 88, 179, 143, 32, 34, 38, 143, + 8, 0, 7, 0, 1, 0, 2, 0, + 6, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 226, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 102, 105, 101, 108, 100, 46, 100, + 101, 102, 97, 117, 108, 116, 86, 97, + 108, 117, 101, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 254, 255, 6, 0, 0, 0, + 0, 0, 1, 0, 18, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 52, 0, 0, 0, 2, 0, 1, 0, + 110, 111, 110, 101, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 118, 97, 108, 117, 101, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_d0d1a21de617951f = b_d0d1a21de617951f.words; +static const ::capnp::_::RawSchema* const d_d0d1a21de617951f[] = { + &s_8e207d4dfe54d0de, + &s_8f2622208fb358c8, +}; +static const uint16_t m_d0d1a21de617951f[] = {0, 1}; +static const uint16_t i_d0d1a21de617951f[] = {0, 1}; +const ::capnp::_::RawSchema s_d0d1a21de617951f = { + 0xd0d1a21de617951f, b_d0d1a21de617951f.words, 51, d_d0d1a21de617951f, m_d0d1a21de617951f, + 2, 2, i_d0d1a21de617951f, nullptr, nullptr, { &s_d0d1a21de617951f, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<40> b_992a90eaf30235d3 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 211, 53, 2, 243, 234, 144, 42, 153, + 41, 0, 0, 0, 1, 0, 2, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 8, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 154, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 37, 0, 0, 0, 63, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 105, 110, 116, 101, 114, 102, 97, + 99, 101, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 1, 0, 21, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 3, 0, 1, 0, + 40, 0, 0, 0, 2, 0, 1, 0, + 115, 117, 112, 101, 114, 99, 108, 97, + 115, 115, 101, 115, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_992a90eaf30235d3 = b_992a90eaf30235d3.words; +static const ::capnp::_::RawSchema* const d_992a90eaf30235d3[] = { + &s_8e207d4dfe54d0de, + &s_96efe787c17e83bb, +}; +static const uint16_t m_992a90eaf30235d3[] = {0}; +static const uint16_t i_992a90eaf30235d3[] = {0}; +const ::capnp::_::RawSchema s_992a90eaf30235d3 = { + 0x992a90eaf30235d3, b_992a90eaf30235d3.words, 40, d_992a90eaf30235d3, m_992a90eaf30235d3, + 2, 1, i_992a90eaf30235d3, nullptr, nullptr, { &s_992a90eaf30235d3, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<42> b_eb971847d617c0b9 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 185, 192, 23, 214, 71, 24, 151, 235, + 41, 0, 0, 0, 1, 0, 2, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 8, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 130, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 109, 101, 116, 104, 111, 100, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 1, 0, 22, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 115, 81, 214, 98, 125, 140, 35, 198, + 45, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 97, 114, 97, 109, 115, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 205, 27, 216, 121, 122, 110, 246, 179, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 114, 101, 115, 117, 108, 116, 115, 0, } +}; +::capnp::word const* const bp_eb971847d617c0b9 = b_eb971847d617c0b9.words; +static const ::capnp::_::RawSchema* const d_eb971847d617c0b9[] = { + &s_96efe787c17e83bb, + &s_b3f66e7a79d81bcd, + &s_c6238c7d62d65173, +}; +static const uint16_t m_eb971847d617c0b9[] = {0, 1}; +static const uint16_t i_eb971847d617c0b9[] = {0, 1}; +const ::capnp::_::RawSchema s_eb971847d617c0b9 = { + 0xeb971847d617c0b9, b_eb971847d617c0b9.words, 42, d_eb971847d617c0b9, m_eb971847d617c0b9, + 3, 2, i_eb971847d617c0b9, nullptr, nullptr, { &s_eb971847d617c0b9, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<51> b_c6238c7d62d65173 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 115, 81, 214, 98, 125, 140, 35, 198, + 48, 0, 0, 0, 1, 0, 2, 0, + 185, 192, 23, 214, 71, 24, 151, 235, + 8, 0, 7, 0, 1, 0, 2, 0, + 6, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 194, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 37, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 109, 101, 116, 104, 111, 100, 46, + 114, 101, 115, 117, 108, 116, 115, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 23, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 254, 255, 6, 0, 0, 0, + 0, 0, 1, 0, 24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 74, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 44, 0, 0, 0, 3, 0, 1, 0, + 56, 0, 0, 0, 2, 0, 1, 0, + 110, 111, 110, 101, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 120, 112, 108, 105, 99, 105, 116, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 205, 27, 216, 121, 122, 110, 246, 179, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_c6238c7d62d65173 = b_c6238c7d62d65173.words; +static const ::capnp::_::RawSchema* const d_c6238c7d62d65173[] = { + &s_b3f66e7a79d81bcd, + &s_eb971847d617c0b9, +}; +static const uint16_t m_c6238c7d62d65173[] = {1, 0}; +static const uint16_t i_c6238c7d62d65173[] = {0, 1}; +const ::capnp::_::RawSchema s_c6238c7d62d65173 = { + 0xc6238c7d62d65173, b_c6238c7d62d65173.words, 51, d_c6238c7d62d65173, m_c6238c7d62d65173, + 2, 2, i_c6238c7d62d65173, nullptr, nullptr, { &s_c6238c7d62d65173, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<230> b_9cb9e86e3198037f = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 127, 3, 152, 49, 110, 232, 185, 156, + 41, 0, 0, 0, 1, 0, 2, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 8, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 162, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 37, 0, 0, 0, 223, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 68, 101, 99, + 108, 97, 114, 97, 116, 105, 111, 110, + 46, 97, 110, 110, 111, 116, 97, 116, + 105, 111, 110, 0, 0, 0, 0, 0, + 52, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 1, 0, 25, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 93, 1, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 88, 1, 0, 0, 3, 0, 1, 0, + 100, 1, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 96, 0, 0, 0, + 0, 0, 1, 0, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 1, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 96, 1, 0, 0, 3, 0, 1, 0, + 108, 1, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 97, 0, 0, 0, + 0, 0, 1, 0, 27, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 1, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 104, 1, 0, 0, 3, 0, 1, 0, + 116, 1, 0, 0, 2, 0, 1, 0, + 3, 0, 0, 0, 98, 0, 0, 0, + 0, 0, 1, 0, 28, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 113, 1, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 1, 0, 0, 3, 0, 1, 0, + 124, 1, 0, 0, 2, 0, 1, 0, + 4, 0, 0, 0, 99, 0, 0, 0, + 0, 0, 1, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 121, 1, 0, 0, 138, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 124, 1, 0, 0, 3, 0, 1, 0, + 136, 1, 0, 0, 2, 0, 1, 0, + 5, 0, 0, 0, 100, 0, 0, 0, + 0, 0, 1, 0, 30, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 133, 1, 0, 0, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 132, 1, 0, 0, 3, 0, 1, 0, + 144, 1, 0, 0, 2, 0, 1, 0, + 6, 0, 0, 0, 101, 0, 0, 0, + 0, 0, 1, 0, 31, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 141, 1, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 140, 1, 0, 0, 3, 0, 1, 0, + 152, 1, 0, 0, 2, 0, 1, 0, + 7, 0, 0, 0, 102, 0, 0, 0, + 0, 0, 1, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 149, 1, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 148, 1, 0, 0, 3, 0, 1, 0, + 160, 1, 0, 0, 2, 0, 1, 0, + 8, 0, 0, 0, 103, 0, 0, 0, + 0, 0, 1, 0, 33, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 157, 1, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 156, 1, 0, 0, 3, 0, 1, 0, + 168, 1, 0, 0, 2, 0, 1, 0, + 9, 0, 0, 0, 104, 0, 0, 0, + 0, 0, 1, 0, 34, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 165, 1, 0, 0, 138, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 168, 1, 0, 0, 3, 0, 1, 0, + 180, 1, 0, 0, 2, 0, 1, 0, + 10, 0, 0, 0, 105, 0, 0, 0, + 0, 0, 1, 0, 35, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 177, 1, 0, 0, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 176, 1, 0, 0, 3, 0, 1, 0, + 188, 1, 0, 0, 2, 0, 1, 0, + 11, 0, 0, 0, 106, 0, 0, 0, + 0, 0, 1, 0, 36, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 185, 1, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 184, 1, 0, 0, 3, 0, 1, 0, + 196, 1, 0, 0, 2, 0, 1, 0, + 12, 0, 0, 0, 107, 0, 0, 0, + 0, 0, 1, 0, 37, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 193, 1, 0, 0, 146, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 196, 1, 0, 0, 3, 0, 1, 0, + 208, 1, 0, 0, 2, 0, 1, 0, + 116, 121, 112, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 222, 208, 84, 254, 77, 125, 32, 142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 70, + 105, 108, 101, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 67, + 111, 110, 115, 116, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 69, + 110, 117, 109, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 69, + 110, 117, 109, 101, 114, 97, 110, 116, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 83, + 116, 114, 117, 99, 116, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 70, + 105, 101, 108, 100, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 85, + 110, 105, 111, 110, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 71, + 114, 111, 117, 112, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 73, + 110, 116, 101, 114, 102, 97, 99, 101, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 77, + 101, 116, 104, 111, 100, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 80, + 97, 114, 97, 109, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 65, + 110, 110, 111, 116, 97, 116, 105, 111, + 110, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_9cb9e86e3198037f = b_9cb9e86e3198037f.words; +static const ::capnp::_::RawSchema* const d_9cb9e86e3198037f[] = { + &s_8e207d4dfe54d0de, + &s_96efe787c17e83bb, +}; +static const uint16_t m_9cb9e86e3198037f[] = {12, 2, 3, 4, 6, 1, 8, 9, 10, 11, 5, 7, 0}; +static const uint16_t i_9cb9e86e3198037f[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; +const ::capnp::_::RawSchema s_9cb9e86e3198037f = { + 0x9cb9e86e3198037f, b_9cb9e86e3198037f.words, 230, d_9cb9e86e3198037f, m_9cb9e86e3198037f, + 2, 13, i_9cb9e86e3198037f, nullptr, nullptr, { &s_9cb9e86e3198037f, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<34> b_84e4f3f5a807605c = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 92, 96, 7, 168, 245, 243, 228, 132, + 29, 0, 0, 0, 1, 0, 0, 0, + 198, 195, 187, 220, 104, 225, 107, 197, + 1, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 66, 1, 0, 0, + 37, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 63, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 110, 112, 47, 99, 111, + 109, 112, 105, 108, 101, 114, 47, 103, + 114, 97, 109, 109, 97, 114, 46, 99, + 97, 112, 110, 112, 58, 80, 97, 114, + 115, 101, 100, 70, 105, 108, 101, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 4, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 3, 0, 1, 0, + 20, 0, 0, 0, 2, 0, 1, 0, + 114, 111, 111, 116, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 187, 131, 126, 193, 135, 231, 239, 150, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_84e4f3f5a807605c = b_84e4f3f5a807605c.words; +static const ::capnp::_::RawSchema* const d_84e4f3f5a807605c[] = { + &s_96efe787c17e83bb, +}; +static const uint16_t m_84e4f3f5a807605c[] = {0}; +static const uint16_t i_84e4f3f5a807605c[] = {0}; +const ::capnp::_::RawSchema s_84e4f3f5a807605c = { + 0x84e4f3f5a807605c, b_84e4f3f5a807605c.words, 34, d_84e4f3f5a807605c, m_84e4f3f5a807605c, + 1, 1, i_84e4f3f5a807605c, nullptr, nullptr, { &s_84e4f3f5a807605c, nullptr, nullptr, 0, 0, nullptr }, false +}; +} // namespace schemas +} // namespace capnp + +// ======================================================================================= + +namespace capnp { +namespace compiler { + +// LocatedText +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t LocatedText::_capnpPrivate::dataWordSize; +constexpr uint16_t LocatedText::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind LocatedText::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* LocatedText::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// LocatedInteger +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t LocatedInteger::_capnpPrivate::dataWordSize; +constexpr uint16_t LocatedInteger::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind LocatedInteger::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* LocatedInteger::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// LocatedFloat +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t LocatedFloat::_capnpPrivate::dataWordSize; +constexpr uint16_t LocatedFloat::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind LocatedFloat::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* LocatedFloat::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Expression +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Expression::_capnpPrivate::dataWordSize; +constexpr uint16_t Expression::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Expression::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Expression::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Expression::Param +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Expression::Param::_capnpPrivate::dataWordSize; +constexpr uint16_t Expression::Param::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Expression::Param::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Expression::Param::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Expression::Application +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Expression::Application::_capnpPrivate::dataWordSize; +constexpr uint16_t Expression::Application::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Expression::Application::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Expression::Application::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Expression::Member +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Expression::Member::_capnpPrivate::dataWordSize; +constexpr uint16_t Expression::Member::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Expression::Member::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Expression::Member::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::BrandParameter +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::BrandParameter::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::BrandParameter::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::BrandParameter::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::BrandParameter::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::AnnotationApplication +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::AnnotationApplication::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::AnnotationApplication::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::AnnotationApplication::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::AnnotationApplication::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::AnnotationApplication::Value +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::AnnotationApplication::Value::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::AnnotationApplication::Value::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::AnnotationApplication::Value::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::AnnotationApplication::Value::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::ParamList +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::ParamList::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::ParamList::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::ParamList::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::ParamList::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::Param +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::Param::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::Param::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::Param::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::Param::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::Param::DefaultValue +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::Param::DefaultValue::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::Param::DefaultValue::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::Param::DefaultValue::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::Param::DefaultValue::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::Id +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::Id::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::Id::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::Id::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::Id::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::Using +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::Using::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::Using::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::Using::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::Using::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::Const +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::Const::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::Const::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::Const::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::Const::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::Field +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::Field::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::Field::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::Field::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::Field::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::Field::DefaultValue +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::Field::DefaultValue::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::Field::DefaultValue::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::Field::DefaultValue::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::Field::DefaultValue::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::Interface +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::Interface::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::Interface::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::Interface::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::Interface::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::Method +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::Method::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::Method::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::Method::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::Method::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::Method::Results +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::Method::Results::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::Method::Results::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::Method::Results::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::Method::Results::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Declaration::Annotation +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Declaration::Annotation::_capnpPrivate::dataWordSize; +constexpr uint16_t Declaration::Annotation::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Declaration::Annotation::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Declaration::Annotation::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// ParsedFile +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t ParsedFile::_capnpPrivate::dataWordSize; +constexpr uint16_t ParsedFile::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind ParsedFile::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* ParsedFile::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + + +} // namespace +} // namespace diff --git a/vendor/capnproto/src/capnp/compiler/grammar.capnp.h b/vendor/capnproto/src/capnp/compiler/grammar.capnp.h new file mode 100644 index 0000000..7036ad5 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/grammar.capnp.h @@ -0,0 +1,6202 @@ +// Generated by Cap'n Proto compiler, DO NOT EDIT +// source: grammar.capnp + +#pragma once + +#include + +#ifndef CAPNP_VERSION +#error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?" +#elif CAPNP_VERSION != 1004000 +#error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." +#endif + + +CAPNP_BEGIN_HEADER + +namespace capnp { +namespace schemas { + +CAPNP_DECLARE_SCHEMA(e75816b56529d464); +CAPNP_DECLARE_SCHEMA(991c7a3693d62cf2); +CAPNP_DECLARE_SCHEMA(90f2a60678fd2367); +CAPNP_DECLARE_SCHEMA(8e207d4dfe54d0de); +CAPNP_DECLARE_SCHEMA(c90246b71adedbaa); +CAPNP_DECLARE_SCHEMA(aee8397040b0df7a); +CAPNP_DECLARE_SCHEMA(aa28e1400d793359); +CAPNP_DECLARE_SCHEMA(96efe787c17e83bb); +CAPNP_DECLARE_SCHEMA(d5e71144af1ce175); +CAPNP_DECLARE_SCHEMA(d00489d473826290); +CAPNP_DECLARE_SCHEMA(fb5aeed95cdf6af9); +CAPNP_DECLARE_SCHEMA(94099c3f9eb32d6b); +CAPNP_DECLARE_SCHEMA(b3f66e7a79d81bcd); +CAPNP_DECLARE_SCHEMA(fffe08a9a697d2a5); +CAPNP_DECLARE_SCHEMA(e5104515fd88ea47); +CAPNP_DECLARE_SCHEMA(89f0c973c103ae96); +CAPNP_DECLARE_SCHEMA(e93164a80bfe2ccf); +CAPNP_DECLARE_SCHEMA(b348322a8dcf0d0c); +CAPNP_DECLARE_SCHEMA(8f2622208fb358c8); +CAPNP_DECLARE_SCHEMA(d0d1a21de617951f); +CAPNP_DECLARE_SCHEMA(992a90eaf30235d3); +CAPNP_DECLARE_SCHEMA(eb971847d617c0b9); +CAPNP_DECLARE_SCHEMA(c6238c7d62d65173); +CAPNP_DECLARE_SCHEMA(9cb9e86e3198037f); +CAPNP_DECLARE_SCHEMA(84e4f3f5a807605c); + +} // namespace schemas +} // namespace capnp + +namespace capnp { +namespace compiler { + +struct LocatedText { + LocatedText() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(e75816b56529d464, 1, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct LocatedInteger { + LocatedInteger() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(991c7a3693d62cf2, 2, 0) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct LocatedFloat { + LocatedFloat() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(90f2a60678fd2367, 2, 0) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Expression { + Expression() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + UNKNOWN, + POSITIVE_INT, + NEGATIVE_INT, + FLOAT, + STRING, + RELATIVE_NAME, + LIST, + TUPLE, + BINARY, + APPLICATION, + MEMBER, + ABSOLUTE_NAME, + IMPORT, + EMBED, + }; + struct Param; + struct Application; + struct Member; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(8e207d4dfe54d0de, 3, 2) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Expression::Param { + Param() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + UNNAMED, + NAMED, + }; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(c90246b71adedbaa, 1, 2) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Expression::Application { + Application() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(aee8397040b0df7a, 3, 2) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Expression::Member { + Member() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(aa28e1400d793359, 3, 2) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration { + Declaration() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + FILE, + USING, + CONST, + ENUM, + ENUMERANT, + STRUCT, + FIELD, + UNION, + GROUP, + INTERFACE, + METHOD, + ANNOTATION, + NAKED_ID, + NAKED_ANNOTATION, + BUILTIN_VOID, + BUILTIN_BOOL, + BUILTIN_INT8, + BUILTIN_INT16, + BUILTIN_INT32, + BUILTIN_INT64, + BUILTIN_U_INT8, + BUILTIN_U_INT16, + BUILTIN_U_INT32, + BUILTIN_U_INT64, + BUILTIN_FLOAT32, + BUILTIN_FLOAT64, + BUILTIN_TEXT, + BUILTIN_DATA, + BUILTIN_LIST, + BUILTIN_OBJECT, + BUILTIN_ANY_POINTER, + BUILTIN_ANY_STRUCT, + BUILTIN_ANY_LIST, + BUILTIN_CAPABILITY, + }; + struct BrandParameter; + struct AnnotationApplication; + struct ParamList; + struct Param; + struct Id; + struct Using; + struct Const; + struct Field; + struct Interface; + struct Method; + struct Annotation; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(96efe787c17e83bb, 2, 8) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::BrandParameter { + BrandParameter() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(d5e71144af1ce175, 1, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::AnnotationApplication { + AnnotationApplication() = delete; + + class Reader; + class Builder; + struct Value; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(d00489d473826290, 1, 2) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::AnnotationApplication::Value { + Value() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + NONE, + EXPRESSION, + }; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(fb5aeed95cdf6af9, 1, 2) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::ParamList { + ParamList() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + NAMED_LIST, + TYPE, + STREAM, + }; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(b3f66e7a79d81bcd, 2, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::Param { + Param() = delete; + + class Reader; + class Builder; + struct DefaultValue; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(fffe08a9a697d2a5, 2, 4) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::Param::DefaultValue { + DefaultValue() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + NONE, + VALUE, + }; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(e5104515fd88ea47, 2, 4) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::Id { + Id() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + UNSPECIFIED, + UID, + ORDINAL, + }; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(89f0c973c103ae96, 2, 8) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::Using { + Using() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(e93164a80bfe2ccf, 2, 8) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::Const { + Const() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(b348322a8dcf0d0c, 2, 8) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::Field { + Field() = delete; + + class Reader; + class Builder; + struct DefaultValue; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(8f2622208fb358c8, 2, 8) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::Field::DefaultValue { + DefaultValue() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + NONE, + VALUE, + }; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(d0d1a21de617951f, 2, 8) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::Interface { + Interface() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(992a90eaf30235d3, 2, 8) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::Method { + Method() = delete; + + class Reader; + class Builder; + struct Results; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(eb971847d617c0b9, 2, 8) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::Method::Results { + Results() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + NONE, + EXPLICIT, + }; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(c6238c7d62d65173, 2, 8) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Declaration::Annotation { + Annotation() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(9cb9e86e3198037f, 2, 8) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct ParsedFile { + ParsedFile() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(84e4f3f5a807605c, 0, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +// ======================================================================================= + +class LocatedText::Reader { +public: + typedef LocatedText Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasValue() const; + inline ::capnp::Text::Reader getValue() const; + + inline ::uint32_t getStartByte() const; + + inline ::uint32_t getEndByte() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class LocatedText::Builder { +public: + typedef LocatedText 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasValue(); + inline ::capnp::Text::Builder getValue(); + inline void setValue( ::capnp::Text::Reader value); + inline ::capnp::Text::Builder initValue(unsigned int size); + inline void adoptValue(::capnp::Orphan< ::capnp::Text>&& value); + inline ::capnp::Orphan< ::capnp::Text> disownValue(); + + inline ::uint32_t getStartByte(); + inline void setStartByte( ::uint32_t value); + + inline ::uint32_t getEndByte(); + inline void setEndByte( ::uint32_t value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class LocatedInteger::Reader { +public: + typedef LocatedInteger Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline ::uint64_t getValue() const; + + inline ::uint32_t getStartByte() const; + + inline ::uint32_t getEndByte() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class LocatedInteger::Builder { +public: + typedef LocatedInteger 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline ::uint64_t getValue(); + inline void setValue( ::uint64_t value); + + inline ::uint32_t getStartByte(); + inline void setStartByte( ::uint32_t value); + + inline ::uint32_t getEndByte(); + inline void setEndByte( ::uint32_t value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class LocatedFloat::Reader { +public: + typedef LocatedFloat Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline double getValue() const; + + inline ::uint32_t getStartByte() const; + + inline ::uint32_t getEndByte() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class LocatedFloat::Builder { +public: + typedef LocatedFloat 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline double getValue(); + inline void setValue(double value); + + inline ::uint32_t getStartByte(); + inline void setStartByte( ::uint32_t value); + + inline ::uint32_t getEndByte(); + inline void setEndByte( ::uint32_t value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Expression::Reader { +public: + typedef Expression Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isUnknown() const; + inline ::capnp::Void getUnknown() const; + + inline bool isPositiveInt() const; + inline ::uint64_t getPositiveInt() const; + + inline bool isNegativeInt() const; + inline ::uint64_t getNegativeInt() const; + + inline bool isFloat() const; + inline double getFloat() const; + + inline bool isString() const; + inline bool hasString() const; + inline ::capnp::Text::Reader getString() const; + + inline bool isRelativeName() const; + inline bool hasRelativeName() const; + inline ::capnp::compiler::LocatedText::Reader getRelativeName() const; + + inline bool isList() const; + inline bool hasList() const; + inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader getList() const; + + inline bool isTuple() const; + inline bool hasTuple() const; + inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader getTuple() const; + + inline ::uint32_t getStartByte() const; + + inline ::uint32_t getEndByte() const; + + inline bool isBinary() const; + inline bool hasBinary() const; + inline ::capnp::Data::Reader getBinary() const; + + inline bool isApplication() const; + inline typename Application::Reader getApplication() const; + + inline bool isMember() const; + inline typename Member::Reader getMember() const; + + inline bool isAbsoluteName() const; + inline bool hasAbsoluteName() const; + inline ::capnp::compiler::LocatedText::Reader getAbsoluteName() const; + + inline bool isImport() const; + inline bool hasImport() const; + inline ::capnp::compiler::LocatedText::Reader getImport() const; + + inline bool isEmbed() const; + inline bool hasEmbed() const; + inline ::capnp::compiler::LocatedText::Reader getEmbed() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Expression::Builder { +public: + typedef Expression 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isUnknown(); + inline ::capnp::Void getUnknown(); + inline void setUnknown( ::capnp::Void value = ::capnp::VOID); + + inline bool isPositiveInt(); + inline ::uint64_t getPositiveInt(); + inline void setPositiveInt( ::uint64_t value); + + inline bool isNegativeInt(); + inline ::uint64_t getNegativeInt(); + inline void setNegativeInt( ::uint64_t value); + + inline bool isFloat(); + inline double getFloat(); + inline void setFloat(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 isRelativeName(); + inline bool hasRelativeName(); + inline ::capnp::compiler::LocatedText::Builder getRelativeName(); + inline void setRelativeName( ::capnp::compiler::LocatedText::Reader value); + inline ::capnp::compiler::LocatedText::Builder initRelativeName(); + inline void adoptRelativeName(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); + inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownRelativeName(); + + inline bool isList(); + inline bool hasList(); + inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder getList(); + inline void setList( ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder initList(unsigned int size); + inline void adoptList(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>> disownList(); + + inline bool isTuple(); + inline bool hasTuple(); + inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder getTuple(); + inline void setTuple( ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder initTuple(unsigned int size); + inline void adoptTuple(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>> disownTuple(); + + inline ::uint32_t getStartByte(); + inline void setStartByte( ::uint32_t value); + + inline ::uint32_t getEndByte(); + inline void setEndByte( ::uint32_t value); + + inline bool isBinary(); + inline bool hasBinary(); + inline ::capnp::Data::Builder getBinary(); + inline void setBinary( ::capnp::Data::Reader value); + inline ::capnp::Data::Builder initBinary(unsigned int size); + inline void adoptBinary(::capnp::Orphan< ::capnp::Data>&& value); + inline ::capnp::Orphan< ::capnp::Data> disownBinary(); + + inline bool isApplication(); + inline typename Application::Builder getApplication(); + inline typename Application::Builder initApplication(); + + inline bool isMember(); + inline typename Member::Builder getMember(); + inline typename Member::Builder initMember(); + + inline bool isAbsoluteName(); + inline bool hasAbsoluteName(); + inline ::capnp::compiler::LocatedText::Builder getAbsoluteName(); + inline void setAbsoluteName( ::capnp::compiler::LocatedText::Reader value); + inline ::capnp::compiler::LocatedText::Builder initAbsoluteName(); + inline void adoptAbsoluteName(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); + inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownAbsoluteName(); + + inline bool isImport(); + inline bool hasImport(); + inline ::capnp::compiler::LocatedText::Builder getImport(); + inline void setImport( ::capnp::compiler::LocatedText::Reader value); + inline ::capnp::compiler::LocatedText::Builder initImport(); + inline void adoptImport(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); + inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownImport(); + + inline bool isEmbed(); + inline bool hasEmbed(); + inline ::capnp::compiler::LocatedText::Builder getEmbed(); + inline void setEmbed( ::capnp::compiler::LocatedText::Reader value); + inline ::capnp::compiler::LocatedText::Builder initEmbed(); + inline void adoptEmbed(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); + inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownEmbed(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Expression::Param::Reader { +public: + typedef Param Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isUnnamed() const; + inline ::capnp::Void getUnnamed() const; + + inline bool isNamed() const; + inline bool hasNamed() const; + inline ::capnp::compiler::LocatedText::Reader getNamed() const; + + inline bool hasValue() const; + inline ::capnp::compiler::Expression::Reader getValue() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Expression::Param::Builder { +public: + typedef Param 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isUnnamed(); + inline ::capnp::Void getUnnamed(); + inline void setUnnamed( ::capnp::Void value = ::capnp::VOID); + + inline bool isNamed(); + inline bool hasNamed(); + inline ::capnp::compiler::LocatedText::Builder getNamed(); + inline void setNamed( ::capnp::compiler::LocatedText::Reader value); + inline ::capnp::compiler::LocatedText::Builder initNamed(); + inline void adoptNamed(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); + inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownNamed(); + + inline bool hasValue(); + inline ::capnp::compiler::Expression::Builder getValue(); + inline void setValue( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initValue(); + inline void adoptValue(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownValue(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Expression::Application::Reader { +public: + typedef Application Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasFunction() const; + inline ::capnp::compiler::Expression::Reader getFunction() const; + + inline bool hasParams() const; + inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader getParams() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Expression::Application::Builder { +public: + typedef Application 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasFunction(); + inline ::capnp::compiler::Expression::Builder getFunction(); + inline void setFunction( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initFunction(); + inline void adoptFunction(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownFunction(); + + inline bool hasParams(); + inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder getParams(); + inline void setParams( ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder initParams(unsigned int size); + inline void adoptParams(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>> disownParams(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Expression::Member::Reader { +public: + typedef Member Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasParent() const; + inline ::capnp::compiler::Expression::Reader getParent() const; + + inline bool hasName() const; + inline ::capnp::compiler::LocatedText::Reader getName() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Expression::Member::Builder { +public: + typedef Member 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasParent(); + inline ::capnp::compiler::Expression::Builder getParent(); + inline void setParent( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initParent(); + inline void adoptParent(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownParent(); + + inline bool hasName(); + inline ::capnp::compiler::LocatedText::Builder getName(); + inline void setName( ::capnp::compiler::LocatedText::Reader value); + inline ::capnp::compiler::LocatedText::Builder initName(); + inline void adoptName(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); + inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownName(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::Reader { +public: + typedef Declaration Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool hasName() const; + inline ::capnp::compiler::LocatedText::Reader getName() const; + + inline typename Id::Reader getId() const; + + inline bool hasNestedDecls() const; + inline ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Reader getNestedDecls() const; + + inline bool hasAnnotations() const; + inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader getAnnotations() const; + + inline ::uint32_t getStartByte() const; + + inline ::uint32_t getEndByte() const; + + inline bool hasDocComment() const; + inline ::capnp::Text::Reader getDocComment() const; + + inline bool isFile() const; + inline ::capnp::Void getFile() const; + + inline bool isUsing() const; + inline typename Using::Reader getUsing() const; + + inline bool isConst() const; + inline typename Const::Reader getConst() const; + + inline bool isEnum() const; + inline ::capnp::Void getEnum() const; + + inline bool isEnumerant() const; + inline ::capnp::Void getEnumerant() const; + + inline bool isStruct() const; + inline ::capnp::Void getStruct() const; + + inline bool isField() const; + inline typename Field::Reader getField() const; + + inline bool isUnion() const; + inline ::capnp::Void getUnion() const; + + inline bool isGroup() const; + inline ::capnp::Void getGroup() const; + + inline bool isInterface() const; + inline typename Interface::Reader getInterface() const; + + inline bool isMethod() const; + inline typename Method::Reader getMethod() const; + + inline bool isAnnotation() const; + inline typename Annotation::Reader getAnnotation() const; + + inline bool isNakedId() const; + inline bool hasNakedId() const; + inline ::capnp::compiler::LocatedInteger::Reader getNakedId() const; + + inline bool isNakedAnnotation() const; + inline bool hasNakedAnnotation() const; + inline ::capnp::compiler::Declaration::AnnotationApplication::Reader getNakedAnnotation() const; + + inline bool isBuiltinVoid() const; + inline ::capnp::Void getBuiltinVoid() const; + + inline bool isBuiltinBool() const; + inline ::capnp::Void getBuiltinBool() const; + + inline bool isBuiltinInt8() const; + inline ::capnp::Void getBuiltinInt8() const; + + inline bool isBuiltinInt16() const; + inline ::capnp::Void getBuiltinInt16() const; + + inline bool isBuiltinInt32() const; + inline ::capnp::Void getBuiltinInt32() const; + + inline bool isBuiltinInt64() const; + inline ::capnp::Void getBuiltinInt64() const; + + inline bool isBuiltinUInt8() const; + inline ::capnp::Void getBuiltinUInt8() const; + + inline bool isBuiltinUInt16() const; + inline ::capnp::Void getBuiltinUInt16() const; + + inline bool isBuiltinUInt32() const; + inline ::capnp::Void getBuiltinUInt32() const; + + inline bool isBuiltinUInt64() const; + inline ::capnp::Void getBuiltinUInt64() const; + + inline bool isBuiltinFloat32() const; + inline ::capnp::Void getBuiltinFloat32() const; + + inline bool isBuiltinFloat64() const; + inline ::capnp::Void getBuiltinFloat64() const; + + inline bool isBuiltinText() const; + inline ::capnp::Void getBuiltinText() const; + + inline bool isBuiltinData() const; + inline ::capnp::Void getBuiltinData() const; + + inline bool isBuiltinList() const; + inline ::capnp::Void getBuiltinList() const; + + inline bool isBuiltinObject() const; + inline ::capnp::Void getBuiltinObject() const; + + inline bool isBuiltinAnyPointer() const; + inline ::capnp::Void getBuiltinAnyPointer() const; + + inline bool hasParameters() const; + inline ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Reader getParameters() const; + + inline bool isBuiltinAnyStruct() const; + inline ::capnp::Void getBuiltinAnyStruct() const; + + inline bool isBuiltinAnyList() const; + inline ::capnp::Void getBuiltinAnyList() const; + + inline bool isBuiltinCapability() const; + inline ::capnp::Void getBuiltinCapability() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::Builder { +public: + typedef Declaration 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool hasName(); + inline ::capnp::compiler::LocatedText::Builder getName(); + inline void setName( ::capnp::compiler::LocatedText::Reader value); + inline ::capnp::compiler::LocatedText::Builder initName(); + inline void adoptName(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); + inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownName(); + + inline typename Id::Builder getId(); + inline typename Id::Builder initId(); + + inline bool hasNestedDecls(); + inline ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Builder getNestedDecls(); + inline void setNestedDecls( ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Builder initNestedDecls(unsigned int size); + inline void adoptNestedDecls(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>> disownNestedDecls(); + + inline bool hasAnnotations(); + inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder getAnnotations(); + inline void setAnnotations( ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder initAnnotations(unsigned int size); + inline void adoptAnnotations(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>> disownAnnotations(); + + inline ::uint32_t getStartByte(); + inline void setStartByte( ::uint32_t value); + + inline ::uint32_t getEndByte(); + inline void setEndByte( ::uint32_t value); + + inline bool hasDocComment(); + inline ::capnp::Text::Builder getDocComment(); + inline void setDocComment( ::capnp::Text::Reader value); + inline ::capnp::Text::Builder initDocComment(unsigned int size); + inline void adoptDocComment(::capnp::Orphan< ::capnp::Text>&& value); + inline ::capnp::Orphan< ::capnp::Text> disownDocComment(); + + inline bool isFile(); + inline ::capnp::Void getFile(); + inline void setFile( ::capnp::Void value = ::capnp::VOID); + + inline bool isUsing(); + inline typename Using::Builder getUsing(); + inline typename Using::Builder initUsing(); + + inline bool isConst(); + inline typename Const::Builder getConst(); + inline typename Const::Builder initConst(); + + inline bool isEnum(); + inline ::capnp::Void getEnum(); + inline void setEnum( ::capnp::Void value = ::capnp::VOID); + + inline bool isEnumerant(); + inline ::capnp::Void getEnumerant(); + inline void setEnumerant( ::capnp::Void value = ::capnp::VOID); + + inline bool isStruct(); + inline ::capnp::Void getStruct(); + inline void setStruct( ::capnp::Void value = ::capnp::VOID); + + inline bool isField(); + inline typename Field::Builder getField(); + inline typename Field::Builder initField(); + + inline bool isUnion(); + inline ::capnp::Void getUnion(); + inline void setUnion( ::capnp::Void value = ::capnp::VOID); + + inline bool isGroup(); + inline ::capnp::Void getGroup(); + inline void setGroup( ::capnp::Void value = ::capnp::VOID); + + inline bool isInterface(); + inline typename Interface::Builder getInterface(); + inline typename Interface::Builder initInterface(); + + inline bool isMethod(); + inline typename Method::Builder getMethod(); + inline typename Method::Builder initMethod(); + + inline bool isAnnotation(); + inline typename Annotation::Builder getAnnotation(); + inline typename Annotation::Builder initAnnotation(); + + inline bool isNakedId(); + inline bool hasNakedId(); + inline ::capnp::compiler::LocatedInteger::Builder getNakedId(); + inline void setNakedId( ::capnp::compiler::LocatedInteger::Reader value); + inline ::capnp::compiler::LocatedInteger::Builder initNakedId(); + inline void adoptNakedId(::capnp::Orphan< ::capnp::compiler::LocatedInteger>&& value); + inline ::capnp::Orphan< ::capnp::compiler::LocatedInteger> disownNakedId(); + + inline bool isNakedAnnotation(); + inline bool hasNakedAnnotation(); + inline ::capnp::compiler::Declaration::AnnotationApplication::Builder getNakedAnnotation(); + inline void setNakedAnnotation( ::capnp::compiler::Declaration::AnnotationApplication::Reader value); + inline ::capnp::compiler::Declaration::AnnotationApplication::Builder initNakedAnnotation(); + inline void adoptNakedAnnotation(::capnp::Orphan< ::capnp::compiler::Declaration::AnnotationApplication>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Declaration::AnnotationApplication> disownNakedAnnotation(); + + inline bool isBuiltinVoid(); + inline ::capnp::Void getBuiltinVoid(); + inline void setBuiltinVoid( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinBool(); + inline ::capnp::Void getBuiltinBool(); + inline void setBuiltinBool( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinInt8(); + inline ::capnp::Void getBuiltinInt8(); + inline void setBuiltinInt8( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinInt16(); + inline ::capnp::Void getBuiltinInt16(); + inline void setBuiltinInt16( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinInt32(); + inline ::capnp::Void getBuiltinInt32(); + inline void setBuiltinInt32( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinInt64(); + inline ::capnp::Void getBuiltinInt64(); + inline void setBuiltinInt64( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinUInt8(); + inline ::capnp::Void getBuiltinUInt8(); + inline void setBuiltinUInt8( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinUInt16(); + inline ::capnp::Void getBuiltinUInt16(); + inline void setBuiltinUInt16( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinUInt32(); + inline ::capnp::Void getBuiltinUInt32(); + inline void setBuiltinUInt32( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinUInt64(); + inline ::capnp::Void getBuiltinUInt64(); + inline void setBuiltinUInt64( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinFloat32(); + inline ::capnp::Void getBuiltinFloat32(); + inline void setBuiltinFloat32( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinFloat64(); + inline ::capnp::Void getBuiltinFloat64(); + inline void setBuiltinFloat64( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinText(); + inline ::capnp::Void getBuiltinText(); + inline void setBuiltinText( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinData(); + inline ::capnp::Void getBuiltinData(); + inline void setBuiltinData( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinList(); + inline ::capnp::Void getBuiltinList(); + inline void setBuiltinList( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinObject(); + inline ::capnp::Void getBuiltinObject(); + inline void setBuiltinObject( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinAnyPointer(); + inline ::capnp::Void getBuiltinAnyPointer(); + inline void setBuiltinAnyPointer( ::capnp::Void value = ::capnp::VOID); + + inline bool hasParameters(); + inline ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Builder getParameters(); + inline void setParameters( ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Builder initParameters(unsigned int size); + inline void adoptParameters(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>> disownParameters(); + + inline bool isBuiltinAnyStruct(); + inline ::capnp::Void getBuiltinAnyStruct(); + inline void setBuiltinAnyStruct( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinAnyList(); + inline ::capnp::Void getBuiltinAnyList(); + inline void setBuiltinAnyList( ::capnp::Void value = ::capnp::VOID); + + inline bool isBuiltinCapability(); + inline ::capnp::Void getBuiltinCapability(); + inline void setBuiltinCapability( ::capnp::Void value = ::capnp::VOID); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::BrandParameter::Reader { +public: + typedef BrandParameter Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasName() const; + inline ::capnp::Text::Reader getName() const; + + inline ::uint32_t getStartByte() const; + + inline ::uint32_t getEndByte() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::BrandParameter::Builder { +public: + typedef BrandParameter 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + 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 ::uint32_t getStartByte(); + inline void setStartByte( ::uint32_t value); + + inline ::uint32_t getEndByte(); + inline void setEndByte( ::uint32_t value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::AnnotationApplication::Reader { +public: + typedef AnnotationApplication Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasName() const; + inline ::capnp::compiler::Expression::Reader getName() const; + + inline typename Value::Reader getValue() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::AnnotationApplication::Builder { +public: + typedef AnnotationApplication 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasName(); + inline ::capnp::compiler::Expression::Builder getName(); + inline void setName( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initName(); + inline void adoptName(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownName(); + + inline typename Value::Builder getValue(); + inline typename Value::Builder initValue(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::AnnotationApplication::Value::Reader { +public: + typedef Value Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isNone() const; + inline ::capnp::Void getNone() const; + + inline bool isExpression() const; + inline bool hasExpression() const; + inline ::capnp::compiler::Expression::Reader getExpression() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::AnnotationApplication::Value::Builder { +public: + typedef Value 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isNone(); + inline ::capnp::Void getNone(); + inline void setNone( ::capnp::Void value = ::capnp::VOID); + + inline bool isExpression(); + inline bool hasExpression(); + inline ::capnp::compiler::Expression::Builder getExpression(); + inline void setExpression( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initExpression(); + inline void adoptExpression(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownExpression(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::ParamList::Reader { +public: + typedef ParamList Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isNamedList() const; + inline bool hasNamedList() const; + inline ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Reader getNamedList() const; + + inline bool isType() const; + inline bool hasType() const; + inline ::capnp::compiler::Expression::Reader getType() const; + + inline ::uint32_t getStartByte() const; + + inline ::uint32_t getEndByte() const; + + inline bool isStream() const; + inline ::capnp::Void getStream() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::ParamList::Builder { +public: + typedef ParamList 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isNamedList(); + inline bool hasNamedList(); + inline ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Builder getNamedList(); + inline void setNamedList( ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Builder initNamedList(unsigned int size); + inline void adoptNamedList(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>> disownNamedList(); + + inline bool isType(); + inline bool hasType(); + inline ::capnp::compiler::Expression::Builder getType(); + inline void setType( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initType(); + inline void adoptType(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownType(); + + inline ::uint32_t getStartByte(); + inline void setStartByte( ::uint32_t value); + + inline ::uint32_t getEndByte(); + inline void setEndByte( ::uint32_t value); + + inline bool isStream(); + inline ::capnp::Void getStream(); + inline void setStream( ::capnp::Void value = ::capnp::VOID); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::Param::Reader { +public: + typedef Param Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasName() const; + inline ::capnp::compiler::LocatedText::Reader getName() const; + + inline bool hasType() const; + inline ::capnp::compiler::Expression::Reader getType() const; + + inline bool hasAnnotations() const; + inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader getAnnotations() const; + + inline typename DefaultValue::Reader getDefaultValue() const; + + inline ::uint32_t getStartByte() const; + + inline ::uint32_t getEndByte() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::Param::Builder { +public: + typedef Param 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasName(); + inline ::capnp::compiler::LocatedText::Builder getName(); + inline void setName( ::capnp::compiler::LocatedText::Reader value); + inline ::capnp::compiler::LocatedText::Builder initName(); + inline void adoptName(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); + inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownName(); + + inline bool hasType(); + inline ::capnp::compiler::Expression::Builder getType(); + inline void setType( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initType(); + inline void adoptType(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownType(); + + inline bool hasAnnotations(); + inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder getAnnotations(); + inline void setAnnotations( ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder initAnnotations(unsigned int size); + inline void adoptAnnotations(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>> disownAnnotations(); + + inline typename DefaultValue::Builder getDefaultValue(); + inline typename DefaultValue::Builder initDefaultValue(); + + inline ::uint32_t getStartByte(); + inline void setStartByte( ::uint32_t value); + + inline ::uint32_t getEndByte(); + inline void setEndByte( ::uint32_t value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::Param::DefaultValue::Reader { +public: + typedef DefaultValue Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isNone() const; + inline ::capnp::Void getNone() const; + + inline bool isValue() const; + inline bool hasValue() const; + inline ::capnp::compiler::Expression::Reader getValue() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::Param::DefaultValue::Builder { +public: + typedef DefaultValue 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isNone(); + inline ::capnp::Void getNone(); + inline void setNone( ::capnp::Void value = ::capnp::VOID); + + inline bool isValue(); + inline bool hasValue(); + inline ::capnp::compiler::Expression::Builder getValue(); + inline void setValue( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initValue(); + inline void adoptValue(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownValue(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::Id::Reader { +public: + typedef Id Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isUnspecified() const; + inline ::capnp::Void getUnspecified() const; + + inline bool isUid() const; + inline bool hasUid() const; + inline ::capnp::compiler::LocatedInteger::Reader getUid() const; + + inline bool isOrdinal() const; + inline bool hasOrdinal() const; + inline ::capnp::compiler::LocatedInteger::Reader getOrdinal() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::Id::Builder { +public: + typedef Id 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isUnspecified(); + inline ::capnp::Void getUnspecified(); + inline void setUnspecified( ::capnp::Void value = ::capnp::VOID); + + inline bool isUid(); + inline bool hasUid(); + inline ::capnp::compiler::LocatedInteger::Builder getUid(); + inline void setUid( ::capnp::compiler::LocatedInteger::Reader value); + inline ::capnp::compiler::LocatedInteger::Builder initUid(); + inline void adoptUid(::capnp::Orphan< ::capnp::compiler::LocatedInteger>&& value); + inline ::capnp::Orphan< ::capnp::compiler::LocatedInteger> disownUid(); + + inline bool isOrdinal(); + inline bool hasOrdinal(); + inline ::capnp::compiler::LocatedInteger::Builder getOrdinal(); + inline void setOrdinal( ::capnp::compiler::LocatedInteger::Reader value); + inline ::capnp::compiler::LocatedInteger::Builder initOrdinal(); + inline void adoptOrdinal(::capnp::Orphan< ::capnp::compiler::LocatedInteger>&& value); + inline ::capnp::Orphan< ::capnp::compiler::LocatedInteger> disownOrdinal(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::Using::Reader { +public: + typedef Using Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasTarget() const; + inline ::capnp::compiler::Expression::Reader getTarget() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::Using::Builder { +public: + typedef Using 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasTarget(); + inline ::capnp::compiler::Expression::Builder getTarget(); + inline void setTarget( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initTarget(); + inline void adoptTarget(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownTarget(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::Const::Reader { +public: + typedef Const Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasType() const; + inline ::capnp::compiler::Expression::Reader getType() const; + + inline bool hasValue() const; + inline ::capnp::compiler::Expression::Reader getValue() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::Const::Builder { +public: + typedef Const 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasType(); + inline ::capnp::compiler::Expression::Builder getType(); + inline void setType( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initType(); + inline void adoptType(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownType(); + + inline bool hasValue(); + inline ::capnp::compiler::Expression::Builder getValue(); + inline void setValue( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initValue(); + inline void adoptValue(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownValue(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::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(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasType() const; + inline ::capnp::compiler::Expression::Reader getType() const; + + inline typename DefaultValue::Reader getDefaultValue() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasType(); + inline ::capnp::compiler::Expression::Builder getType(); + inline void setType( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initType(); + inline void adoptType(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownType(); + + inline typename DefaultValue::Builder getDefaultValue(); + inline typename DefaultValue::Builder initDefaultValue(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::Field::DefaultValue::Reader { +public: + typedef DefaultValue Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isNone() const; + inline ::capnp::Void getNone() const; + + inline bool isValue() const; + inline bool hasValue() const; + inline ::capnp::compiler::Expression::Reader getValue() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::Field::DefaultValue::Builder { +public: + typedef DefaultValue 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isNone(); + inline ::capnp::Void getNone(); + inline void setNone( ::capnp::Void value = ::capnp::VOID); + + inline bool isValue(); + inline bool hasValue(); + inline ::capnp::compiler::Expression::Builder getValue(); + inline void setValue( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initValue(); + inline void adoptValue(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownValue(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::Interface::Reader { +public: + typedef Interface Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasSuperclasses() const; + inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader getSuperclasses() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::Interface::Builder { +public: + typedef Interface 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasSuperclasses(); + inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder getSuperclasses(); + inline void setSuperclasses( ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder initSuperclasses(unsigned int size); + inline void adoptSuperclasses(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>> disownSuperclasses(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::Method::Reader { +public: + typedef Method Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasParams() const; + inline ::capnp::compiler::Declaration::ParamList::Reader getParams() const; + + inline typename Results::Reader getResults() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::Method::Builder { +public: + typedef Method 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasParams(); + inline ::capnp::compiler::Declaration::ParamList::Builder getParams(); + inline void setParams( ::capnp::compiler::Declaration::ParamList::Reader value); + inline ::capnp::compiler::Declaration::ParamList::Builder initParams(); + inline void adoptParams(::capnp::Orphan< ::capnp::compiler::Declaration::ParamList>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Declaration::ParamList> disownParams(); + + inline typename Results::Builder getResults(); + inline typename Results::Builder initResults(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::Method::Results::Reader { +public: + typedef Results Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isNone() const; + inline ::capnp::Void getNone() const; + + inline bool isExplicit() const; + inline bool hasExplicit() const; + inline ::capnp::compiler::Declaration::ParamList::Reader getExplicit() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::Method::Results::Builder { +public: + typedef Results 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isNone(); + inline ::capnp::Void getNone(); + inline void setNone( ::capnp::Void value = ::capnp::VOID); + + inline bool isExplicit(); + inline bool hasExplicit(); + inline ::capnp::compiler::Declaration::ParamList::Builder getExplicit(); + inline void setExplicit( ::capnp::compiler::Declaration::ParamList::Reader value); + inline ::capnp::compiler::Declaration::ParamList::Builder initExplicit(); + inline void adoptExplicit(::capnp::Orphan< ::capnp::compiler::Declaration::ParamList>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Declaration::ParamList> disownExplicit(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Declaration::Annotation::Reader { +public: + typedef Annotation Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasType() const; + inline ::capnp::compiler::Expression::Reader getType() const; + + inline bool getTargetsFile() const; + + inline bool getTargetsConst() const; + + inline bool getTargetsEnum() const; + + inline bool getTargetsEnumerant() const; + + inline bool getTargetsStruct() const; + + inline bool getTargetsField() const; + + inline bool getTargetsUnion() const; + + inline bool getTargetsGroup() const; + + inline bool getTargetsInterface() const; + + inline bool getTargetsMethod() const; + + inline bool getTargetsParam() const; + + inline bool getTargetsAnnotation() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Declaration::Annotation::Builder { +public: + typedef Annotation 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasType(); + inline ::capnp::compiler::Expression::Builder getType(); + inline void setType( ::capnp::compiler::Expression::Reader value); + inline ::capnp::compiler::Expression::Builder initType(); + inline void adoptType(::capnp::Orphan< ::capnp::compiler::Expression>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Expression> disownType(); + + inline bool getTargetsFile(); + inline void setTargetsFile(bool value); + + inline bool getTargetsConst(); + inline void setTargetsConst(bool value); + + inline bool getTargetsEnum(); + inline void setTargetsEnum(bool value); + + inline bool getTargetsEnumerant(); + inline void setTargetsEnumerant(bool value); + + inline bool getTargetsStruct(); + inline void setTargetsStruct(bool value); + + inline bool getTargetsField(); + inline void setTargetsField(bool value); + + inline bool getTargetsUnion(); + inline void setTargetsUnion(bool value); + + inline bool getTargetsGroup(); + inline void setTargetsGroup(bool value); + + inline bool getTargetsInterface(); + inline void setTargetsInterface(bool value); + + inline bool getTargetsMethod(); + inline void setTargetsMethod(bool value); + + inline bool getTargetsParam(); + inline void setTargetsParam(bool value); + + inline bool getTargetsAnnotation(); + inline void setTargetsAnnotation(bool value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class ParsedFile::Reader { +public: + typedef ParsedFile Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasRoot() const; + inline ::capnp::compiler::Declaration::Reader getRoot() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class ParsedFile::Builder { +public: + typedef ParsedFile 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasRoot(); + inline ::capnp::compiler::Declaration::Builder getRoot(); + inline void setRoot( ::capnp::compiler::Declaration::Reader value); + inline ::capnp::compiler::Declaration::Builder initRoot(); + inline void adoptRoot(::capnp::Orphan< ::capnp::compiler::Declaration>&& value); + inline ::capnp::Orphan< ::capnp::compiler::Declaration> disownRoot(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +// ======================================================================================= + +inline bool LocatedText::Reader::hasValue() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool LocatedText::Builder::hasValue() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader LocatedText::Reader::getValue() const { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::Text::Builder LocatedText::Builder::getValue() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void LocatedText::Builder::setValue( ::capnp::Text::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder LocatedText::Builder::initValue(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void LocatedText::Builder::adoptValue( + ::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> LocatedText::Builder::disownValue() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::uint32_t LocatedText::Reader::getStartByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t LocatedText::Builder::getStartByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void LocatedText::Builder::setStartByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t LocatedText::Reader::getEndByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t LocatedText::Builder::getEndByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void LocatedText::Builder::setEndByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline ::uint64_t LocatedInteger::Reader::getValue() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t LocatedInteger::Builder::getValue() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void LocatedInteger::Builder::setValue( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t LocatedInteger::Reader::getStartByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t LocatedInteger::Builder::getStartByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} +inline void LocatedInteger::Builder::setStartByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t LocatedInteger::Reader::getEndByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<3>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t LocatedInteger::Builder::getEndByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<3>() * ::capnp::ELEMENTS); +} +inline void LocatedInteger::Builder::setEndByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<3>() * ::capnp::ELEMENTS, value); +} + +inline double LocatedFloat::Reader::getValue() const { + return _reader.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline double LocatedFloat::Builder::getValue() { + return _builder.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void LocatedFloat::Builder::setValue(double value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t LocatedFloat::Reader::getStartByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t LocatedFloat::Builder::getStartByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} +inline void LocatedFloat::Builder::setStartByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t LocatedFloat::Reader::getEndByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<3>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t LocatedFloat::Builder::getEndByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<3>() * ::capnp::ELEMENTS); +} +inline void LocatedFloat::Builder::setEndByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<3>() * ::capnp::ELEMENTS, value); +} + +inline ::capnp::compiler::Expression::Which Expression::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline ::capnp::compiler::Expression::Which Expression::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline bool Expression::Reader::isUnknown() const { + return which() == Expression::UNKNOWN; +} +inline bool Expression::Builder::isUnknown() { + return which() == Expression::UNKNOWN; +} +inline ::capnp::Void Expression::Reader::getUnknown() const { + KJ_IREQUIRE((which() == Expression::UNKNOWN), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Expression::Builder::getUnknown() { + KJ_IREQUIRE((which() == Expression::UNKNOWN), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Expression::Builder::setUnknown( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::UNKNOWN); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Expression::Reader::isPositiveInt() const { + return which() == Expression::POSITIVE_INT; +} +inline bool Expression::Builder::isPositiveInt() { + return which() == Expression::POSITIVE_INT; +} +inline ::uint64_t Expression::Reader::getPositiveInt() const { + KJ_IREQUIRE((which() == Expression::POSITIVE_INT), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Expression::Builder::getPositiveInt() { + KJ_IREQUIRE((which() == Expression::POSITIVE_INT), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Expression::Builder::setPositiveInt( ::uint64_t value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::POSITIVE_INT); + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Expression::Reader::isNegativeInt() const { + return which() == Expression::NEGATIVE_INT; +} +inline bool Expression::Builder::isNegativeInt() { + return which() == Expression::NEGATIVE_INT; +} +inline ::uint64_t Expression::Reader::getNegativeInt() const { + KJ_IREQUIRE((which() == Expression::NEGATIVE_INT), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Expression::Builder::getNegativeInt() { + KJ_IREQUIRE((which() == Expression::NEGATIVE_INT), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Expression::Builder::setNegativeInt( ::uint64_t value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::NEGATIVE_INT); + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Expression::Reader::isFloat() const { + return which() == Expression::FLOAT; +} +inline bool Expression::Builder::isFloat() { + return which() == Expression::FLOAT; +} +inline double Expression::Reader::getFloat() const { + KJ_IREQUIRE((which() == Expression::FLOAT), + "Must check which() before get()ing a union member."); + return _reader.getDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline double Expression::Builder::getFloat() { + KJ_IREQUIRE((which() == Expression::FLOAT), + "Must check which() before get()ing a union member."); + return _builder.getDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Expression::Builder::setFloat(double value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::FLOAT); + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Expression::Reader::isString() const { + return which() == Expression::STRING; +} +inline bool Expression::Builder::isString() { + return which() == Expression::STRING; +} +inline bool Expression::Reader::hasString() const { + if (which() != Expression::STRING) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Builder::hasString() { + if (which() != Expression::STRING) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Expression::Reader::getString() const { + KJ_IREQUIRE((which() == Expression::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 Expression::Builder::getString() { + KJ_IREQUIRE((which() == Expression::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 Expression::Builder::setString( ::capnp::Text::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::STRING); + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Expression::Builder::initString(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::STRING); + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Expression::Builder::adoptString( + ::capnp::Orphan< ::capnp::Text>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::STRING); + ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::Text> Expression::Builder::disownString() { + KJ_IREQUIRE((which() == Expression::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 Expression::Reader::isRelativeName() const { + return which() == Expression::RELATIVE_NAME; +} +inline bool Expression::Builder::isRelativeName() { + return which() == Expression::RELATIVE_NAME; +} +inline bool Expression::Reader::hasRelativeName() const { + if (which() != Expression::RELATIVE_NAME) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Builder::hasRelativeName() { + if (which() != Expression::RELATIVE_NAME) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::LocatedText::Reader Expression::Reader::getRelativeName() const { + KJ_IREQUIRE((which() == Expression::RELATIVE_NAME), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::LocatedText::Builder Expression::Builder::getRelativeName() { + KJ_IREQUIRE((which() == Expression::RELATIVE_NAME), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Builder::setRelativeName( ::capnp::compiler::LocatedText::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::RELATIVE_NAME); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::LocatedText::Builder Expression::Builder::initRelativeName() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::RELATIVE_NAME); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Builder::adoptRelativeName( + ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::RELATIVE_NAME); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Expression::Builder::disownRelativeName() { + KJ_IREQUIRE((which() == Expression::RELATIVE_NAME), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Expression::Reader::isList() const { + return which() == Expression::LIST; +} +inline bool Expression::Builder::isList() { + return which() == Expression::LIST; +} +inline bool Expression::Reader::hasList() const { + if (which() != Expression::LIST) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Builder::hasList() { + if (which() != Expression::LIST) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader Expression::Reader::getList() const { + KJ_IREQUIRE((which() == Expression::LIST), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder Expression::Builder::getList() { + KJ_IREQUIRE((which() == Expression::LIST), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Builder::setList( ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::LIST); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder Expression::Builder::initList(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::LIST); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Expression::Builder::adoptList( + ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::LIST); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>> Expression::Builder::disownList() { + KJ_IREQUIRE((which() == Expression::LIST), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Expression::Reader::isTuple() const { + return which() == Expression::TUPLE; +} +inline bool Expression::Builder::isTuple() { + return which() == Expression::TUPLE; +} +inline bool Expression::Reader::hasTuple() const { + if (which() != Expression::TUPLE) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Builder::hasTuple() { + if (which() != Expression::TUPLE) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader Expression::Reader::getTuple() const { + KJ_IREQUIRE((which() == Expression::TUPLE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder Expression::Builder::getTuple() { + KJ_IREQUIRE((which() == Expression::TUPLE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Builder::setTuple( ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::TUPLE); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder Expression::Builder::initTuple(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::TUPLE); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Expression::Builder::adoptTuple( + ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::TUPLE); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>> Expression::Builder::disownTuple() { + KJ_IREQUIRE((which() == Expression::TUPLE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::uint32_t Expression::Reader::getStartByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Expression::Builder::getStartByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Expression::Builder::setStartByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t Expression::Reader::getEndByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<4>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Expression::Builder::getEndByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<4>() * ::capnp::ELEMENTS); +} +inline void Expression::Builder::setEndByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<4>() * ::capnp::ELEMENTS, value); +} + +inline bool Expression::Reader::isBinary() const { + return which() == Expression::BINARY; +} +inline bool Expression::Builder::isBinary() { + return which() == Expression::BINARY; +} +inline bool Expression::Reader::hasBinary() const { + if (which() != Expression::BINARY) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Builder::hasBinary() { + if (which() != Expression::BINARY) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Data::Reader Expression::Reader::getBinary() const { + KJ_IREQUIRE((which() == Expression::BINARY), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Data>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::Data::Builder Expression::Builder::getBinary() { + KJ_IREQUIRE((which() == Expression::BINARY), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Data>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Builder::setBinary( ::capnp::Data::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::BINARY); + ::capnp::_::PointerHelpers< ::capnp::Data>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Data::Builder Expression::Builder::initBinary(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::BINARY); + return ::capnp::_::PointerHelpers< ::capnp::Data>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Expression::Builder::adoptBinary( + ::capnp::Orphan< ::capnp::Data>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::BINARY); + ::capnp::_::PointerHelpers< ::capnp::Data>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::Data> Expression::Builder::disownBinary() { + KJ_IREQUIRE((which() == Expression::BINARY), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Data>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Expression::Reader::isApplication() const { + return which() == Expression::APPLICATION; +} +inline bool Expression::Builder::isApplication() { + return which() == Expression::APPLICATION; +} +inline typename Expression::Application::Reader Expression::Reader::getApplication() const { + KJ_IREQUIRE((which() == Expression::APPLICATION), + "Must check which() before get()ing a union member."); + return typename Expression::Application::Reader(_reader); +} +inline typename Expression::Application::Builder Expression::Builder::getApplication() { + KJ_IREQUIRE((which() == Expression::APPLICATION), + "Must check which() before get()ing a union member."); + return typename Expression::Application::Builder(_builder); +} +inline typename Expression::Application::Builder Expression::Builder::initApplication() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::APPLICATION); + _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS).clear(); + _builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS).clear(); + return typename Expression::Application::Builder(_builder); +} +inline bool Expression::Reader::isMember() const { + return which() == Expression::MEMBER; +} +inline bool Expression::Builder::isMember() { + return which() == Expression::MEMBER; +} +inline typename Expression::Member::Reader Expression::Reader::getMember() const { + KJ_IREQUIRE((which() == Expression::MEMBER), + "Must check which() before get()ing a union member."); + return typename Expression::Member::Reader(_reader); +} +inline typename Expression::Member::Builder Expression::Builder::getMember() { + KJ_IREQUIRE((which() == Expression::MEMBER), + "Must check which() before get()ing a union member."); + return typename Expression::Member::Builder(_builder); +} +inline typename Expression::Member::Builder Expression::Builder::initMember() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::MEMBER); + _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS).clear(); + _builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS).clear(); + return typename Expression::Member::Builder(_builder); +} +inline bool Expression::Reader::isAbsoluteName() const { + return which() == Expression::ABSOLUTE_NAME; +} +inline bool Expression::Builder::isAbsoluteName() { + return which() == Expression::ABSOLUTE_NAME; +} +inline bool Expression::Reader::hasAbsoluteName() const { + if (which() != Expression::ABSOLUTE_NAME) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Builder::hasAbsoluteName() { + if (which() != Expression::ABSOLUTE_NAME) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::LocatedText::Reader Expression::Reader::getAbsoluteName() const { + KJ_IREQUIRE((which() == Expression::ABSOLUTE_NAME), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::LocatedText::Builder Expression::Builder::getAbsoluteName() { + KJ_IREQUIRE((which() == Expression::ABSOLUTE_NAME), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Builder::setAbsoluteName( ::capnp::compiler::LocatedText::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::ABSOLUTE_NAME); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::LocatedText::Builder Expression::Builder::initAbsoluteName() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::ABSOLUTE_NAME); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Builder::adoptAbsoluteName( + ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::ABSOLUTE_NAME); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Expression::Builder::disownAbsoluteName() { + KJ_IREQUIRE((which() == Expression::ABSOLUTE_NAME), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Expression::Reader::isImport() const { + return which() == Expression::IMPORT; +} +inline bool Expression::Builder::isImport() { + return which() == Expression::IMPORT; +} +inline bool Expression::Reader::hasImport() const { + if (which() != Expression::IMPORT) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Builder::hasImport() { + if (which() != Expression::IMPORT) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::LocatedText::Reader Expression::Reader::getImport() const { + KJ_IREQUIRE((which() == Expression::IMPORT), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::LocatedText::Builder Expression::Builder::getImport() { + KJ_IREQUIRE((which() == Expression::IMPORT), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Builder::setImport( ::capnp::compiler::LocatedText::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::IMPORT); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::LocatedText::Builder Expression::Builder::initImport() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::IMPORT); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Builder::adoptImport( + ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::IMPORT); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Expression::Builder::disownImport() { + KJ_IREQUIRE((which() == Expression::IMPORT), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Expression::Reader::isEmbed() const { + return which() == Expression::EMBED; +} +inline bool Expression::Builder::isEmbed() { + return which() == Expression::EMBED; +} +inline bool Expression::Reader::hasEmbed() const { + if (which() != Expression::EMBED) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Builder::hasEmbed() { + if (which() != Expression::EMBED) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::LocatedText::Reader Expression::Reader::getEmbed() const { + KJ_IREQUIRE((which() == Expression::EMBED), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::LocatedText::Builder Expression::Builder::getEmbed() { + KJ_IREQUIRE((which() == Expression::EMBED), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Builder::setEmbed( ::capnp::compiler::LocatedText::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::EMBED); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::LocatedText::Builder Expression::Builder::initEmbed() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::EMBED); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Builder::adoptEmbed( + ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::EMBED); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Expression::Builder::disownEmbed() { + KJ_IREQUIRE((which() == Expression::EMBED), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::capnp::compiler::Expression::Param::Which Expression::Param::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline ::capnp::compiler::Expression::Param::Which Expression::Param::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline bool Expression::Param::Reader::isUnnamed() const { + return which() == Expression::Param::UNNAMED; +} +inline bool Expression::Param::Builder::isUnnamed() { + return which() == Expression::Param::UNNAMED; +} +inline ::capnp::Void Expression::Param::Reader::getUnnamed() const { + KJ_IREQUIRE((which() == Expression::Param::UNNAMED), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Expression::Param::Builder::getUnnamed() { + KJ_IREQUIRE((which() == Expression::Param::UNNAMED), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Expression::Param::Builder::setUnnamed( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::Param::UNNAMED); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Expression::Param::Reader::isNamed() const { + return which() == Expression::Param::NAMED; +} +inline bool Expression::Param::Builder::isNamed() { + return which() == Expression::Param::NAMED; +} +inline bool Expression::Param::Reader::hasNamed() const { + if (which() != Expression::Param::NAMED) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Param::Builder::hasNamed() { + if (which() != Expression::Param::NAMED) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::LocatedText::Reader Expression::Param::Reader::getNamed() const { + KJ_IREQUIRE((which() == Expression::Param::NAMED), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::LocatedText::Builder Expression::Param::Builder::getNamed() { + KJ_IREQUIRE((which() == Expression::Param::NAMED), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Param::Builder::setNamed( ::capnp::compiler::LocatedText::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::Param::NAMED); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::LocatedText::Builder Expression::Param::Builder::initNamed() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::Param::NAMED); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Param::Builder::adoptNamed( + ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::Param::NAMED); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Expression::Param::Builder::disownNamed() { + KJ_IREQUIRE((which() == Expression::Param::NAMED), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Expression::Param::Reader::hasValue() const { + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Param::Builder::hasValue() { + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Expression::Param::Reader::getValue() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Expression::Param::Builder::getValue() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Expression::Param::Builder::setValue( ::capnp::compiler::Expression::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Expression::Param::Builder::initValue() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Expression::Param::Builder::adoptValue( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Expression::Param::Builder::disownValue() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +inline bool Expression::Application::Reader::hasFunction() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Application::Builder::hasFunction() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Expression::Application::Reader::getFunction() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Expression::Application::Builder::getFunction() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Application::Builder::setFunction( ::capnp::compiler::Expression::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Expression::Application::Builder::initFunction() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Application::Builder::adoptFunction( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Expression::Application::Builder::disownFunction() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Expression::Application::Reader::hasParams() const { + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Application::Builder::hasParams() { + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader Expression::Application::Reader::getParams() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder Expression::Application::Builder::getParams() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Expression::Application::Builder::setParams( ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder Expression::Application::Builder::initParams(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), size); +} +inline void Expression::Application::Builder::adoptParams( + ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>> Expression::Application::Builder::disownParams() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +inline bool Expression::Member::Reader::hasParent() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Member::Builder::hasParent() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Expression::Member::Reader::getParent() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Expression::Member::Builder::getParent() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Member::Builder::setParent( ::capnp::compiler::Expression::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Expression::Member::Builder::initParent() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Expression::Member::Builder::adoptParent( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Expression::Member::Builder::disownParent() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Expression::Member::Reader::hasName() const { + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool Expression::Member::Builder::hasName() { + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::LocatedText::Reader Expression::Member::Reader::getName() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::LocatedText::Builder Expression::Member::Builder::getName() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Expression::Member::Builder::setName( ::capnp::compiler::LocatedText::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::LocatedText::Builder Expression::Member::Builder::initName() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Expression::Member::Builder::adoptName( + ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Expression::Member::Builder::disownName() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +inline ::capnp::compiler::Declaration::Which Declaration::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline ::capnp::compiler::Declaration::Which Declaration::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Reader::hasName() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Builder::hasName() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::LocatedText::Reader Declaration::Reader::getName() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::LocatedText::Builder Declaration::Builder::getName() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Declaration::Builder::setName( ::capnp::compiler::LocatedText::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::LocatedText::Builder Declaration::Builder::initName() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Declaration::Builder::adoptName( + ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Declaration::Builder::disownName() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline typename Declaration::Id::Reader Declaration::Reader::getId() const { + return typename Declaration::Id::Reader(_reader); +} +inline typename Declaration::Id::Builder Declaration::Builder::getId() { + return typename Declaration::Id::Builder(_builder); +} +inline typename Declaration::Id::Builder Declaration::Builder::initId() { + _builder.setDataField< ::uint16_t>(::capnp::bounded<0>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS).clear(); + return typename Declaration::Id::Builder(_builder); +} +inline bool Declaration::Reader::hasNestedDecls() const { + return !_reader.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Builder::hasNestedDecls() { + return !_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Reader Declaration::Reader::getNestedDecls() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Builder Declaration::Builder::getNestedDecls() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline void Declaration::Builder::setNestedDecls( ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Builder Declaration::Builder::initNestedDecls(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), size); +} +inline void Declaration::Builder::adoptNestedDecls( + ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>> Declaration::Builder::disownNestedDecls() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Reader::hasAnnotations() const { + return !_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Builder::hasAnnotations() { + return !_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader Declaration::Reader::getAnnotations() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder Declaration::Builder::getAnnotations() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Declaration::Builder::setAnnotations( ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder Declaration::Builder::initAnnotations(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), size); +} +inline void Declaration::Builder::adoptAnnotations( + ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>> Declaration::Builder::disownAnnotations() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} + +inline ::uint32_t Declaration::Reader::getStartByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Declaration::Builder::getStartByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setStartByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t Declaration::Reader::getEndByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Declaration::Builder::getEndByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setEndByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::hasDocComment() const { + return !_reader.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Builder::hasDocComment() { + return !_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Declaration::Reader::getDocComment() const { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS)); +} +inline ::capnp::Text::Builder Declaration::Builder::getDocComment() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS)); +} +inline void Declaration::Builder::setDocComment( ::capnp::Text::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Declaration::Builder::initDocComment(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS), size); +} +inline void Declaration::Builder::adoptDocComment( + ::capnp::Orphan< ::capnp::Text>&& value) { + ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::Text> Declaration::Builder::disownDocComment() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Reader::isFile() const { + return which() == Declaration::FILE; +} +inline bool Declaration::Builder::isFile() { + return which() == Declaration::FILE; +} +inline ::capnp::Void Declaration::Reader::getFile() const { + KJ_IREQUIRE((which() == Declaration::FILE), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getFile() { + KJ_IREQUIRE((which() == Declaration::FILE), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setFile( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::FILE); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isUsing() const { + return which() == Declaration::USING; +} +inline bool Declaration::Builder::isUsing() { + return which() == Declaration::USING; +} +inline typename Declaration::Using::Reader Declaration::Reader::getUsing() const { + KJ_IREQUIRE((which() == Declaration::USING), + "Must check which() before get()ing a union member."); + return typename Declaration::Using::Reader(_reader); +} +inline typename Declaration::Using::Builder Declaration::Builder::getUsing() { + KJ_IREQUIRE((which() == Declaration::USING), + "Must check which() before get()ing a union member."); + return typename Declaration::Using::Builder(_builder); +} +inline typename Declaration::Using::Builder Declaration::Builder::initUsing() { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::USING); + _builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear(); + return typename Declaration::Using::Builder(_builder); +} +inline bool Declaration::Reader::isConst() const { + return which() == Declaration::CONST; +} +inline bool Declaration::Builder::isConst() { + return which() == Declaration::CONST; +} +inline typename Declaration::Const::Reader Declaration::Reader::getConst() const { + KJ_IREQUIRE((which() == Declaration::CONST), + "Must check which() before get()ing a union member."); + return typename Declaration::Const::Reader(_reader); +} +inline typename Declaration::Const::Builder Declaration::Builder::getConst() { + KJ_IREQUIRE((which() == Declaration::CONST), + "Must check which() before get()ing a union member."); + return typename Declaration::Const::Builder(_builder); +} +inline typename Declaration::Const::Builder Declaration::Builder::initConst() { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::CONST); + _builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear(); + _builder.getPointerField(::capnp::bounded<6>() * ::capnp::POINTERS).clear(); + return typename Declaration::Const::Builder(_builder); +} +inline bool Declaration::Reader::isEnum() const { + return which() == Declaration::ENUM; +} +inline bool Declaration::Builder::isEnum() { + return which() == Declaration::ENUM; +} +inline ::capnp::Void Declaration::Reader::getEnum() const { + KJ_IREQUIRE((which() == Declaration::ENUM), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getEnum() { + KJ_IREQUIRE((which() == Declaration::ENUM), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setEnum( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::ENUM); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isEnumerant() const { + return which() == Declaration::ENUMERANT; +} +inline bool Declaration::Builder::isEnumerant() { + return which() == Declaration::ENUMERANT; +} +inline ::capnp::Void Declaration::Reader::getEnumerant() const { + KJ_IREQUIRE((which() == Declaration::ENUMERANT), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getEnumerant() { + KJ_IREQUIRE((which() == Declaration::ENUMERANT), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setEnumerant( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::ENUMERANT); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isStruct() const { + return which() == Declaration::STRUCT; +} +inline bool Declaration::Builder::isStruct() { + return which() == Declaration::STRUCT; +} +inline ::capnp::Void Declaration::Reader::getStruct() const { + KJ_IREQUIRE((which() == Declaration::STRUCT), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getStruct() { + KJ_IREQUIRE((which() == Declaration::STRUCT), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setStruct( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::STRUCT); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isField() const { + return which() == Declaration::FIELD; +} +inline bool Declaration::Builder::isField() { + return which() == Declaration::FIELD; +} +inline typename Declaration::Field::Reader Declaration::Reader::getField() const { + KJ_IREQUIRE((which() == Declaration::FIELD), + "Must check which() before get()ing a union member."); + return typename Declaration::Field::Reader(_reader); +} +inline typename Declaration::Field::Builder Declaration::Builder::getField() { + KJ_IREQUIRE((which() == Declaration::FIELD), + "Must check which() before get()ing a union member."); + return typename Declaration::Field::Builder(_builder); +} +inline typename Declaration::Field::Builder Declaration::Builder::initField() { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::FIELD); + _builder.setDataField< ::uint16_t>(::capnp::bounded<6>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear(); + _builder.getPointerField(::capnp::bounded<6>() * ::capnp::POINTERS).clear(); + return typename Declaration::Field::Builder(_builder); +} +inline bool Declaration::Reader::isUnion() const { + return which() == Declaration::UNION; +} +inline bool Declaration::Builder::isUnion() { + return which() == Declaration::UNION; +} +inline ::capnp::Void Declaration::Reader::getUnion() const { + KJ_IREQUIRE((which() == Declaration::UNION), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getUnion() { + KJ_IREQUIRE((which() == Declaration::UNION), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setUnion( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::UNION); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isGroup() const { + return which() == Declaration::GROUP; +} +inline bool Declaration::Builder::isGroup() { + return which() == Declaration::GROUP; +} +inline ::capnp::Void Declaration::Reader::getGroup() const { + KJ_IREQUIRE((which() == Declaration::GROUP), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getGroup() { + KJ_IREQUIRE((which() == Declaration::GROUP), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setGroup( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::GROUP); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isInterface() const { + return which() == Declaration::INTERFACE; +} +inline bool Declaration::Builder::isInterface() { + return which() == Declaration::INTERFACE; +} +inline typename Declaration::Interface::Reader Declaration::Reader::getInterface() const { + KJ_IREQUIRE((which() == Declaration::INTERFACE), + "Must check which() before get()ing a union member."); + return typename Declaration::Interface::Reader(_reader); +} +inline typename Declaration::Interface::Builder Declaration::Builder::getInterface() { + KJ_IREQUIRE((which() == Declaration::INTERFACE), + "Must check which() before get()ing a union member."); + return typename Declaration::Interface::Builder(_builder); +} +inline typename Declaration::Interface::Builder Declaration::Builder::initInterface() { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::INTERFACE); + _builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear(); + return typename Declaration::Interface::Builder(_builder); +} +inline bool Declaration::Reader::isMethod() const { + return which() == Declaration::METHOD; +} +inline bool Declaration::Builder::isMethod() { + return which() == Declaration::METHOD; +} +inline typename Declaration::Method::Reader Declaration::Reader::getMethod() const { + KJ_IREQUIRE((which() == Declaration::METHOD), + "Must check which() before get()ing a union member."); + return typename Declaration::Method::Reader(_reader); +} +inline typename Declaration::Method::Builder Declaration::Builder::getMethod() { + KJ_IREQUIRE((which() == Declaration::METHOD), + "Must check which() before get()ing a union member."); + return typename Declaration::Method::Builder(_builder); +} +inline typename Declaration::Method::Builder Declaration::Builder::initMethod() { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::METHOD); + _builder.setDataField< ::uint16_t>(::capnp::bounded<6>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear(); + _builder.getPointerField(::capnp::bounded<6>() * ::capnp::POINTERS).clear(); + return typename Declaration::Method::Builder(_builder); +} +inline bool Declaration::Reader::isAnnotation() const { + return which() == Declaration::ANNOTATION; +} +inline bool Declaration::Builder::isAnnotation() { + return which() == Declaration::ANNOTATION; +} +inline typename Declaration::Annotation::Reader Declaration::Reader::getAnnotation() const { + KJ_IREQUIRE((which() == Declaration::ANNOTATION), + "Must check which() before get()ing a union member."); + return typename Declaration::Annotation::Reader(_reader); +} +inline typename Declaration::Annotation::Builder Declaration::Builder::getAnnotation() { + KJ_IREQUIRE((which() == Declaration::ANNOTATION), + "Must check which() before get()ing a union member."); + return typename Declaration::Annotation::Builder(_builder); +} +inline typename Declaration::Annotation::Builder Declaration::Builder::initAnnotation() { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::ANNOTATION); + _builder.setDataField(::capnp::bounded<96>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<97>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<98>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<99>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<100>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<101>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<102>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<103>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<104>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<105>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<106>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<107>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear(); + return typename Declaration::Annotation::Builder(_builder); +} +inline bool Declaration::Reader::isNakedId() const { + return which() == Declaration::NAKED_ID; +} +inline bool Declaration::Builder::isNakedId() { + return which() == Declaration::NAKED_ID; +} +inline bool Declaration::Reader::hasNakedId() const { + if (which() != Declaration::NAKED_ID) return false; + return !_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Builder::hasNakedId() { + if (which() != Declaration::NAKED_ID) return false; + return !_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::LocatedInteger::Reader Declaration::Reader::getNakedId() const { + KJ_IREQUIRE((which() == Declaration::NAKED_ID), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::get(_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::LocatedInteger::Builder Declaration::Builder::getNakedId() { + KJ_IREQUIRE((which() == Declaration::NAKED_ID), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::get(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Builder::setNakedId( ::capnp::compiler::LocatedInteger::Reader value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::NAKED_ID); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::set(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::LocatedInteger::Builder Declaration::Builder::initNakedId() { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::NAKED_ID); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::init(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Builder::adoptNakedId( + ::capnp::Orphan< ::capnp::compiler::LocatedInteger>&& value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::NAKED_ID); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::adopt(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::LocatedInteger> Declaration::Builder::disownNakedId() { + KJ_IREQUIRE((which() == Declaration::NAKED_ID), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::disown(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Reader::isNakedAnnotation() const { + return which() == Declaration::NAKED_ANNOTATION; +} +inline bool Declaration::Builder::isNakedAnnotation() { + return which() == Declaration::NAKED_ANNOTATION; +} +inline bool Declaration::Reader::hasNakedAnnotation() const { + if (which() != Declaration::NAKED_ANNOTATION) return false; + return !_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Builder::hasNakedAnnotation() { + if (which() != Declaration::NAKED_ANNOTATION) return false; + return !_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Declaration::AnnotationApplication::Reader Declaration::Reader::getNakedAnnotation() const { + KJ_IREQUIRE((which() == Declaration::NAKED_ANNOTATION), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::AnnotationApplication>::get(_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Declaration::AnnotationApplication::Builder Declaration::Builder::getNakedAnnotation() { + KJ_IREQUIRE((which() == Declaration::NAKED_ANNOTATION), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::AnnotationApplication>::get(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Builder::setNakedAnnotation( ::capnp::compiler::Declaration::AnnotationApplication::Reader value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::NAKED_ANNOTATION); + ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::AnnotationApplication>::set(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Declaration::AnnotationApplication::Builder Declaration::Builder::initNakedAnnotation() { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::NAKED_ANNOTATION); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::AnnotationApplication>::init(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Builder::adoptNakedAnnotation( + ::capnp::Orphan< ::capnp::compiler::Declaration::AnnotationApplication>&& value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::NAKED_ANNOTATION); + ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::AnnotationApplication>::adopt(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Declaration::AnnotationApplication> Declaration::Builder::disownNakedAnnotation() { + KJ_IREQUIRE((which() == Declaration::NAKED_ANNOTATION), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::AnnotationApplication>::disown(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Reader::isBuiltinVoid() const { + return which() == Declaration::BUILTIN_VOID; +} +inline bool Declaration::Builder::isBuiltinVoid() { + return which() == Declaration::BUILTIN_VOID; +} +inline ::capnp::Void Declaration::Reader::getBuiltinVoid() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_VOID), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinVoid() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_VOID), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinVoid( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_VOID); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinBool() const { + return which() == Declaration::BUILTIN_BOOL; +} +inline bool Declaration::Builder::isBuiltinBool() { + return which() == Declaration::BUILTIN_BOOL; +} +inline ::capnp::Void Declaration::Reader::getBuiltinBool() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_BOOL), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinBool() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_BOOL), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinBool( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_BOOL); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinInt8() const { + return which() == Declaration::BUILTIN_INT8; +} +inline bool Declaration::Builder::isBuiltinInt8() { + return which() == Declaration::BUILTIN_INT8; +} +inline ::capnp::Void Declaration::Reader::getBuiltinInt8() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_INT8), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinInt8() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_INT8), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinInt8( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_INT8); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinInt16() const { + return which() == Declaration::BUILTIN_INT16; +} +inline bool Declaration::Builder::isBuiltinInt16() { + return which() == Declaration::BUILTIN_INT16; +} +inline ::capnp::Void Declaration::Reader::getBuiltinInt16() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_INT16), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinInt16() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_INT16), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinInt16( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_INT16); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinInt32() const { + return which() == Declaration::BUILTIN_INT32; +} +inline bool Declaration::Builder::isBuiltinInt32() { + return which() == Declaration::BUILTIN_INT32; +} +inline ::capnp::Void Declaration::Reader::getBuiltinInt32() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_INT32), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinInt32() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_INT32), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinInt32( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_INT32); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinInt64() const { + return which() == Declaration::BUILTIN_INT64; +} +inline bool Declaration::Builder::isBuiltinInt64() { + return which() == Declaration::BUILTIN_INT64; +} +inline ::capnp::Void Declaration::Reader::getBuiltinInt64() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_INT64), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinInt64() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_INT64), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinInt64( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_INT64); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinUInt8() const { + return which() == Declaration::BUILTIN_U_INT8; +} +inline bool Declaration::Builder::isBuiltinUInt8() { + return which() == Declaration::BUILTIN_U_INT8; +} +inline ::capnp::Void Declaration::Reader::getBuiltinUInt8() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT8), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinUInt8() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT8), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinUInt8( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_U_INT8); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinUInt16() const { + return which() == Declaration::BUILTIN_U_INT16; +} +inline bool Declaration::Builder::isBuiltinUInt16() { + return which() == Declaration::BUILTIN_U_INT16; +} +inline ::capnp::Void Declaration::Reader::getBuiltinUInt16() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT16), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinUInt16() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT16), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinUInt16( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_U_INT16); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinUInt32() const { + return which() == Declaration::BUILTIN_U_INT32; +} +inline bool Declaration::Builder::isBuiltinUInt32() { + return which() == Declaration::BUILTIN_U_INT32; +} +inline ::capnp::Void Declaration::Reader::getBuiltinUInt32() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT32), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinUInt32() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT32), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinUInt32( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_U_INT32); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinUInt64() const { + return which() == Declaration::BUILTIN_U_INT64; +} +inline bool Declaration::Builder::isBuiltinUInt64() { + return which() == Declaration::BUILTIN_U_INT64; +} +inline ::capnp::Void Declaration::Reader::getBuiltinUInt64() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT64), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinUInt64() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT64), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinUInt64( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_U_INT64); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinFloat32() const { + return which() == Declaration::BUILTIN_FLOAT32; +} +inline bool Declaration::Builder::isBuiltinFloat32() { + return which() == Declaration::BUILTIN_FLOAT32; +} +inline ::capnp::Void Declaration::Reader::getBuiltinFloat32() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_FLOAT32), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinFloat32() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_FLOAT32), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinFloat32( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_FLOAT32); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinFloat64() const { + return which() == Declaration::BUILTIN_FLOAT64; +} +inline bool Declaration::Builder::isBuiltinFloat64() { + return which() == Declaration::BUILTIN_FLOAT64; +} +inline ::capnp::Void Declaration::Reader::getBuiltinFloat64() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_FLOAT64), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinFloat64() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_FLOAT64), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinFloat64( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_FLOAT64); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinText() const { + return which() == Declaration::BUILTIN_TEXT; +} +inline bool Declaration::Builder::isBuiltinText() { + return which() == Declaration::BUILTIN_TEXT; +} +inline ::capnp::Void Declaration::Reader::getBuiltinText() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_TEXT), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinText() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_TEXT), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinText( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_TEXT); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinData() const { + return which() == Declaration::BUILTIN_DATA; +} +inline bool Declaration::Builder::isBuiltinData() { + return which() == Declaration::BUILTIN_DATA; +} +inline ::capnp::Void Declaration::Reader::getBuiltinData() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_DATA), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinData() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_DATA), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinData( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_DATA); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinList() const { + return which() == Declaration::BUILTIN_LIST; +} +inline bool Declaration::Builder::isBuiltinList() { + return which() == Declaration::BUILTIN_LIST; +} +inline ::capnp::Void Declaration::Reader::getBuiltinList() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_LIST), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinList() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_LIST), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinList( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_LIST); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinObject() const { + return which() == Declaration::BUILTIN_OBJECT; +} +inline bool Declaration::Builder::isBuiltinObject() { + return which() == Declaration::BUILTIN_OBJECT; +} +inline ::capnp::Void Declaration::Reader::getBuiltinObject() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_OBJECT), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinObject() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_OBJECT), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinObject( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_OBJECT); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinAnyPointer() const { + return which() == Declaration::BUILTIN_ANY_POINTER; +} +inline bool Declaration::Builder::isBuiltinAnyPointer() { + return which() == Declaration::BUILTIN_ANY_POINTER; +} +inline ::capnp::Void Declaration::Reader::getBuiltinAnyPointer() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_ANY_POINTER), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinAnyPointer() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_ANY_POINTER), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinAnyPointer( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_ANY_POINTER); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::hasParameters() const { + return !_reader.getPointerField( + ::capnp::bounded<7>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Builder::hasParameters() { + return !_builder.getPointerField( + ::capnp::bounded<7>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Reader Declaration::Reader::getParameters() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<7>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Builder Declaration::Builder::getParameters() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<7>() * ::capnp::POINTERS)); +} +inline void Declaration::Builder::setParameters( ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<7>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Builder Declaration::Builder::initParameters(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<7>() * ::capnp::POINTERS), size); +} +inline void Declaration::Builder::adoptParameters( + ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<7>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>> Declaration::Builder::disownParameters() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<7>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Reader::isBuiltinAnyStruct() const { + return which() == Declaration::BUILTIN_ANY_STRUCT; +} +inline bool Declaration::Builder::isBuiltinAnyStruct() { + return which() == Declaration::BUILTIN_ANY_STRUCT; +} +inline ::capnp::Void Declaration::Reader::getBuiltinAnyStruct() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_ANY_STRUCT), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinAnyStruct() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_ANY_STRUCT), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinAnyStruct( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_ANY_STRUCT); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinAnyList() const { + return which() == Declaration::BUILTIN_ANY_LIST; +} +inline bool Declaration::Builder::isBuiltinAnyList() { + return which() == Declaration::BUILTIN_ANY_LIST; +} +inline ::capnp::Void Declaration::Reader::getBuiltinAnyList() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_ANY_LIST), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinAnyList() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_ANY_LIST), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinAnyList( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_ANY_LIST); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Reader::isBuiltinCapability() const { + return which() == Declaration::BUILTIN_CAPABILITY; +} +inline bool Declaration::Builder::isBuiltinCapability() { + return which() == Declaration::BUILTIN_CAPABILITY; +} +inline ::capnp::Void Declaration::Reader::getBuiltinCapability() const { + KJ_IREQUIRE((which() == Declaration::BUILTIN_CAPABILITY), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Builder::getBuiltinCapability() { + KJ_IREQUIRE((which() == Declaration::BUILTIN_CAPABILITY), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Builder::setBuiltinCapability( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_CAPABILITY); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::BrandParameter::Reader::hasName() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::BrandParameter::Builder::hasName() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Declaration::BrandParameter::Reader::getName() const { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::Text::Builder Declaration::BrandParameter::Builder::getName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Declaration::BrandParameter::Builder::setName( ::capnp::Text::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Declaration::BrandParameter::Builder::initName(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Declaration::BrandParameter::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> Declaration::BrandParameter::Builder::disownName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::uint32_t Declaration::BrandParameter::Reader::getStartByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Declaration::BrandParameter::Builder::getStartByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::BrandParameter::Builder::setStartByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t Declaration::BrandParameter::Reader::getEndByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Declaration::BrandParameter::Builder::getEndByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Declaration::BrandParameter::Builder::setEndByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::AnnotationApplication::Reader::hasName() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::AnnotationApplication::Builder::hasName() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Declaration::AnnotationApplication::Reader::getName() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Declaration::AnnotationApplication::Builder::getName() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Declaration::AnnotationApplication::Builder::setName( ::capnp::compiler::Expression::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Declaration::AnnotationApplication::Builder::initName() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Declaration::AnnotationApplication::Builder::adoptName( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::AnnotationApplication::Builder::disownName() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline typename Declaration::AnnotationApplication::Value::Reader Declaration::AnnotationApplication::Reader::getValue() const { + return typename Declaration::AnnotationApplication::Value::Reader(_reader); +} +inline typename Declaration::AnnotationApplication::Value::Builder Declaration::AnnotationApplication::Builder::getValue() { + return typename Declaration::AnnotationApplication::Value::Builder(_builder); +} +inline typename Declaration::AnnotationApplication::Value::Builder Declaration::AnnotationApplication::Builder::initValue() { + _builder.setDataField< ::uint16_t>(::capnp::bounded<0>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS).clear(); + return typename Declaration::AnnotationApplication::Value::Builder(_builder); +} +inline ::capnp::compiler::Declaration::AnnotationApplication::Value::Which Declaration::AnnotationApplication::Value::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline ::capnp::compiler::Declaration::AnnotationApplication::Value::Which Declaration::AnnotationApplication::Value::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::AnnotationApplication::Value::Reader::isNone() const { + return which() == Declaration::AnnotationApplication::Value::NONE; +} +inline bool Declaration::AnnotationApplication::Value::Builder::isNone() { + return which() == Declaration::AnnotationApplication::Value::NONE; +} +inline ::capnp::Void Declaration::AnnotationApplication::Value::Reader::getNone() const { + KJ_IREQUIRE((which() == Declaration::AnnotationApplication::Value::NONE), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::AnnotationApplication::Value::Builder::getNone() { + KJ_IREQUIRE((which() == Declaration::AnnotationApplication::Value::NONE), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::AnnotationApplication::Value::Builder::setNone( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::AnnotationApplication::Value::NONE); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::AnnotationApplication::Value::Reader::isExpression() const { + return which() == Declaration::AnnotationApplication::Value::EXPRESSION; +} +inline bool Declaration::AnnotationApplication::Value::Builder::isExpression() { + return which() == Declaration::AnnotationApplication::Value::EXPRESSION; +} +inline bool Declaration::AnnotationApplication::Value::Reader::hasExpression() const { + if (which() != Declaration::AnnotationApplication::Value::EXPRESSION) return false; + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::AnnotationApplication::Value::Builder::hasExpression() { + if (which() != Declaration::AnnotationApplication::Value::EXPRESSION) return false; + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Declaration::AnnotationApplication::Value::Reader::getExpression() const { + KJ_IREQUIRE((which() == Declaration::AnnotationApplication::Value::EXPRESSION), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Declaration::AnnotationApplication::Value::Builder::getExpression() { + KJ_IREQUIRE((which() == Declaration::AnnotationApplication::Value::EXPRESSION), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Declaration::AnnotationApplication::Value::Builder::setExpression( ::capnp::compiler::Expression::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::AnnotationApplication::Value::EXPRESSION); + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Declaration::AnnotationApplication::Value::Builder::initExpression() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::AnnotationApplication::Value::EXPRESSION); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Declaration::AnnotationApplication::Value::Builder::adoptExpression( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::AnnotationApplication::Value::EXPRESSION); + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::AnnotationApplication::Value::Builder::disownExpression() { + KJ_IREQUIRE((which() == Declaration::AnnotationApplication::Value::EXPRESSION), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +inline ::capnp::compiler::Declaration::ParamList::Which Declaration::ParamList::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline ::capnp::compiler::Declaration::ParamList::Which Declaration::ParamList::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::ParamList::Reader::isNamedList() const { + return which() == Declaration::ParamList::NAMED_LIST; +} +inline bool Declaration::ParamList::Builder::isNamedList() { + return which() == Declaration::ParamList::NAMED_LIST; +} +inline bool Declaration::ParamList::Reader::hasNamedList() const { + if (which() != Declaration::ParamList::NAMED_LIST) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::ParamList::Builder::hasNamedList() { + if (which() != Declaration::ParamList::NAMED_LIST) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Reader Declaration::ParamList::Reader::getNamedList() const { + KJ_IREQUIRE((which() == Declaration::ParamList::NAMED_LIST), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Builder Declaration::ParamList::Builder::getNamedList() { + KJ_IREQUIRE((which() == Declaration::ParamList::NAMED_LIST), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Declaration::ParamList::Builder::setNamedList( ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::NAMED_LIST); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Builder Declaration::ParamList::Builder::initNamedList(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::NAMED_LIST); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Declaration::ParamList::Builder::adoptNamedList( + ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::NAMED_LIST); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>> Declaration::ParamList::Builder::disownNamedList() { + KJ_IREQUIRE((which() == Declaration::ParamList::NAMED_LIST), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Declaration::ParamList::Reader::isType() const { + return which() == Declaration::ParamList::TYPE; +} +inline bool Declaration::ParamList::Builder::isType() { + return which() == Declaration::ParamList::TYPE; +} +inline bool Declaration::ParamList::Reader::hasType() const { + if (which() != Declaration::ParamList::TYPE) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::ParamList::Builder::hasType() { + if (which() != Declaration::ParamList::TYPE) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Declaration::ParamList::Reader::getType() const { + KJ_IREQUIRE((which() == Declaration::ParamList::TYPE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Declaration::ParamList::Builder::getType() { + KJ_IREQUIRE((which() == Declaration::ParamList::TYPE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Declaration::ParamList::Builder::setType( ::capnp::compiler::Expression::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::TYPE); + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Declaration::ParamList::Builder::initType() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::TYPE); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Declaration::ParamList::Builder::adoptType( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::TYPE); + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::ParamList::Builder::disownType() { + KJ_IREQUIRE((which() == Declaration::ParamList::TYPE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::uint32_t Declaration::ParamList::Reader::getStartByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Declaration::ParamList::Builder::getStartByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Declaration::ParamList::Builder::setStartByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t Declaration::ParamList::Reader::getEndByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Declaration::ParamList::Builder::getEndByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} +inline void Declaration::ParamList::Builder::setEndByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::ParamList::Reader::isStream() const { + return which() == Declaration::ParamList::STREAM; +} +inline bool Declaration::ParamList::Builder::isStream() { + return which() == Declaration::ParamList::STREAM; +} +inline ::capnp::Void Declaration::ParamList::Reader::getStream() const { + KJ_IREQUIRE((which() == Declaration::ParamList::STREAM), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::ParamList::Builder::getStream() { + KJ_IREQUIRE((which() == Declaration::ParamList::STREAM), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::ParamList::Builder::setStream( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::STREAM); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Param::Reader::hasName() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Param::Builder::hasName() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::LocatedText::Reader Declaration::Param::Reader::getName() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::LocatedText::Builder Declaration::Param::Builder::getName() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Declaration::Param::Builder::setName( ::capnp::compiler::LocatedText::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::LocatedText::Builder Declaration::Param::Builder::initName() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Declaration::Param::Builder::adoptName( + ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Declaration::Param::Builder::disownName() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Param::Reader::hasType() const { + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Param::Builder::hasType() { + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Declaration::Param::Reader::getType() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Declaration::Param::Builder::getType() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Declaration::Param::Builder::setType( ::capnp::compiler::Expression::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Declaration::Param::Builder::initType() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Declaration::Param::Builder::adoptType( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Param::Builder::disownType() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Param::Reader::hasAnnotations() const { + return !_reader.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Param::Builder::hasAnnotations() { + return !_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader Declaration::Param::Reader::getAnnotations() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder Declaration::Param::Builder::getAnnotations() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline void Declaration::Param::Builder::setAnnotations( ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder Declaration::Param::Builder::initAnnotations(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), size); +} +inline void Declaration::Param::Builder::adoptAnnotations( + ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>> Declaration::Param::Builder::disownAnnotations() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} + +inline typename Declaration::Param::DefaultValue::Reader Declaration::Param::Reader::getDefaultValue() const { + return typename Declaration::Param::DefaultValue::Reader(_reader); +} +inline typename Declaration::Param::DefaultValue::Builder Declaration::Param::Builder::getDefaultValue() { + return typename Declaration::Param::DefaultValue::Builder(_builder); +} +inline typename Declaration::Param::DefaultValue::Builder Declaration::Param::Builder::initDefaultValue() { + _builder.setDataField< ::uint16_t>(::capnp::bounded<0>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); + return typename Declaration::Param::DefaultValue::Builder(_builder); +} +inline ::uint32_t Declaration::Param::Reader::getStartByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Declaration::Param::Builder::getStartByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Declaration::Param::Builder::setStartByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t Declaration::Param::Reader::getEndByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Declaration::Param::Builder::getEndByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} +inline void Declaration::Param::Builder::setEndByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); +} + +inline ::capnp::compiler::Declaration::Param::DefaultValue::Which Declaration::Param::DefaultValue::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline ::capnp::compiler::Declaration::Param::DefaultValue::Which Declaration::Param::DefaultValue::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Param::DefaultValue::Reader::isNone() const { + return which() == Declaration::Param::DefaultValue::NONE; +} +inline bool Declaration::Param::DefaultValue::Builder::isNone() { + return which() == Declaration::Param::DefaultValue::NONE; +} +inline ::capnp::Void Declaration::Param::DefaultValue::Reader::getNone() const { + KJ_IREQUIRE((which() == Declaration::Param::DefaultValue::NONE), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Param::DefaultValue::Builder::getNone() { + KJ_IREQUIRE((which() == Declaration::Param::DefaultValue::NONE), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Param::DefaultValue::Builder::setNone( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Param::DefaultValue::NONE); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Param::DefaultValue::Reader::isValue() const { + return which() == Declaration::Param::DefaultValue::VALUE; +} +inline bool Declaration::Param::DefaultValue::Builder::isValue() { + return which() == Declaration::Param::DefaultValue::VALUE; +} +inline bool Declaration::Param::DefaultValue::Reader::hasValue() const { + if (which() != Declaration::Param::DefaultValue::VALUE) return false; + return !_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Param::DefaultValue::Builder::hasValue() { + if (which() != Declaration::Param::DefaultValue::VALUE) return false; + return !_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Declaration::Param::DefaultValue::Reader::getValue() const { + KJ_IREQUIRE((which() == Declaration::Param::DefaultValue::VALUE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Declaration::Param::DefaultValue::Builder::getValue() { + KJ_IREQUIRE((which() == Declaration::Param::DefaultValue::VALUE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Declaration::Param::DefaultValue::Builder::setValue( ::capnp::compiler::Expression::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Param::DefaultValue::VALUE); + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Declaration::Param::DefaultValue::Builder::initValue() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Param::DefaultValue::VALUE); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Declaration::Param::DefaultValue::Builder::adoptValue( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Param::DefaultValue::VALUE); + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Param::DefaultValue::Builder::disownValue() { + KJ_IREQUIRE((which() == Declaration::Param::DefaultValue::VALUE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} + +inline ::capnp::compiler::Declaration::Id::Which Declaration::Id::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline ::capnp::compiler::Declaration::Id::Which Declaration::Id::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Id::Reader::isUnspecified() const { + return which() == Declaration::Id::UNSPECIFIED; +} +inline bool Declaration::Id::Builder::isUnspecified() { + return which() == Declaration::Id::UNSPECIFIED; +} +inline ::capnp::Void Declaration::Id::Reader::getUnspecified() const { + KJ_IREQUIRE((which() == Declaration::Id::UNSPECIFIED), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Id::Builder::getUnspecified() { + KJ_IREQUIRE((which() == Declaration::Id::UNSPECIFIED), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Id::Builder::setUnspecified( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::UNSPECIFIED); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Id::Reader::isUid() const { + return which() == Declaration::Id::UID; +} +inline bool Declaration::Id::Builder::isUid() { + return which() == Declaration::Id::UID; +} +inline bool Declaration::Id::Reader::hasUid() const { + if (which() != Declaration::Id::UID) return false; + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Id::Builder::hasUid() { + if (which() != Declaration::Id::UID) return false; + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::LocatedInteger::Reader Declaration::Id::Reader::getUid() const { + KJ_IREQUIRE((which() == Declaration::Id::UID), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::LocatedInteger::Builder Declaration::Id::Builder::getUid() { + KJ_IREQUIRE((which() == Declaration::Id::UID), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Declaration::Id::Builder::setUid( ::capnp::compiler::LocatedInteger::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::UID); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::LocatedInteger::Builder Declaration::Id::Builder::initUid() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::UID); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Declaration::Id::Builder::adoptUid( + ::capnp::Orphan< ::capnp::compiler::LocatedInteger>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::UID); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::LocatedInteger> Declaration::Id::Builder::disownUid() { + KJ_IREQUIRE((which() == Declaration::Id::UID), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Id::Reader::isOrdinal() const { + return which() == Declaration::Id::ORDINAL; +} +inline bool Declaration::Id::Builder::isOrdinal() { + return which() == Declaration::Id::ORDINAL; +} +inline bool Declaration::Id::Reader::hasOrdinal() const { + if (which() != Declaration::Id::ORDINAL) return false; + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Id::Builder::hasOrdinal() { + if (which() != Declaration::Id::ORDINAL) return false; + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::LocatedInteger::Reader Declaration::Id::Reader::getOrdinal() const { + KJ_IREQUIRE((which() == Declaration::Id::ORDINAL), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::LocatedInteger::Builder Declaration::Id::Builder::getOrdinal() { + KJ_IREQUIRE((which() == Declaration::Id::ORDINAL), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Declaration::Id::Builder::setOrdinal( ::capnp::compiler::LocatedInteger::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::ORDINAL); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::LocatedInteger::Builder Declaration::Id::Builder::initOrdinal() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::ORDINAL); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Declaration::Id::Builder::adoptOrdinal( + ::capnp::Orphan< ::capnp::compiler::LocatedInteger>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::ORDINAL); + ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::LocatedInteger> Declaration::Id::Builder::disownOrdinal() { + KJ_IREQUIRE((which() == Declaration::Id::ORDINAL), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Using::Reader::hasTarget() const { + return !_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Using::Builder::hasTarget() { + return !_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Declaration::Using::Reader::getTarget() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Declaration::Using::Builder::getTarget() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Using::Builder::setTarget( ::capnp::compiler::Expression::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Declaration::Using::Builder::initTarget() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Using::Builder::adoptTarget( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Using::Builder::disownTarget() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Const::Reader::hasType() const { + return !_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Const::Builder::hasType() { + return !_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Declaration::Const::Reader::getType() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Declaration::Const::Builder::getType() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Const::Builder::setType( ::capnp::compiler::Expression::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Declaration::Const::Builder::initType() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Const::Builder::adoptType( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Const::Builder::disownType() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Const::Reader::hasValue() const { + return !_reader.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Const::Builder::hasValue() { + return !_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Declaration::Const::Reader::getValue() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Declaration::Const::Builder::getValue() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS)); +} +inline void Declaration::Const::Builder::setValue( ::capnp::compiler::Expression::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Declaration::Const::Builder::initValue() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS)); +} +inline void Declaration::Const::Builder::adoptValue( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Const::Builder::disownValue() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Field::Reader::hasType() const { + return !_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Field::Builder::hasType() { + return !_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Declaration::Field::Reader::getType() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Declaration::Field::Builder::getType() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Field::Builder::setType( ::capnp::compiler::Expression::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Declaration::Field::Builder::initType() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Field::Builder::adoptType( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Field::Builder::disownType() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} + +inline typename Declaration::Field::DefaultValue::Reader Declaration::Field::Reader::getDefaultValue() const { + return typename Declaration::Field::DefaultValue::Reader(_reader); +} +inline typename Declaration::Field::DefaultValue::Builder Declaration::Field::Builder::getDefaultValue() { + return typename Declaration::Field::DefaultValue::Builder(_builder); +} +inline typename Declaration::Field::DefaultValue::Builder Declaration::Field::Builder::initDefaultValue() { + _builder.setDataField< ::uint16_t>(::capnp::bounded<6>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<6>() * ::capnp::POINTERS).clear(); + return typename Declaration::Field::DefaultValue::Builder(_builder); +} +inline ::capnp::compiler::Declaration::Field::DefaultValue::Which Declaration::Field::DefaultValue::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS); +} +inline ::capnp::compiler::Declaration::Field::DefaultValue::Which Declaration::Field::DefaultValue::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Field::DefaultValue::Reader::isNone() const { + return which() == Declaration::Field::DefaultValue::NONE; +} +inline bool Declaration::Field::DefaultValue::Builder::isNone() { + return which() == Declaration::Field::DefaultValue::NONE; +} +inline ::capnp::Void Declaration::Field::DefaultValue::Reader::getNone() const { + KJ_IREQUIRE((which() == Declaration::Field::DefaultValue::NONE), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Field::DefaultValue::Builder::getNone() { + KJ_IREQUIRE((which() == Declaration::Field::DefaultValue::NONE), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Field::DefaultValue::Builder::setNone( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Field::DefaultValue::NONE); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Field::DefaultValue::Reader::isValue() const { + return which() == Declaration::Field::DefaultValue::VALUE; +} +inline bool Declaration::Field::DefaultValue::Builder::isValue() { + return which() == Declaration::Field::DefaultValue::VALUE; +} +inline bool Declaration::Field::DefaultValue::Reader::hasValue() const { + if (which() != Declaration::Field::DefaultValue::VALUE) return false; + return !_reader.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Field::DefaultValue::Builder::hasValue() { + if (which() != Declaration::Field::DefaultValue::VALUE) return false; + return !_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Declaration::Field::DefaultValue::Reader::getValue() const { + KJ_IREQUIRE((which() == Declaration::Field::DefaultValue::VALUE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Declaration::Field::DefaultValue::Builder::getValue() { + KJ_IREQUIRE((which() == Declaration::Field::DefaultValue::VALUE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS)); +} +inline void Declaration::Field::DefaultValue::Builder::setValue( ::capnp::compiler::Expression::Reader value) { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Field::DefaultValue::VALUE); + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Declaration::Field::DefaultValue::Builder::initValue() { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Field::DefaultValue::VALUE); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS)); +} +inline void Declaration::Field::DefaultValue::Builder::adoptValue( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Field::DefaultValue::VALUE); + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Field::DefaultValue::Builder::disownValue() { + KJ_IREQUIRE((which() == Declaration::Field::DefaultValue::VALUE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Interface::Reader::hasSuperclasses() const { + return !_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Interface::Builder::hasSuperclasses() { + return !_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader Declaration::Interface::Reader::getSuperclasses() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder Declaration::Interface::Builder::getSuperclasses() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Interface::Builder::setSuperclasses( ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder Declaration::Interface::Builder::initSuperclasses(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), size); +} +inline void Declaration::Interface::Builder::adoptSuperclasses( + ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>> Declaration::Interface::Builder::disownSuperclasses() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Method::Reader::hasParams() const { + return !_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Method::Builder::hasParams() { + return !_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Declaration::ParamList::Reader Declaration::Method::Reader::getParams() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::get(_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Declaration::ParamList::Builder Declaration::Method::Builder::getParams() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::get(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Method::Builder::setParams( ::capnp::compiler::Declaration::ParamList::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::set(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Declaration::ParamList::Builder Declaration::Method::Builder::initParams() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::init(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Method::Builder::adoptParams( + ::capnp::Orphan< ::capnp::compiler::Declaration::ParamList>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::adopt(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Declaration::ParamList> Declaration::Method::Builder::disownParams() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::disown(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} + +inline typename Declaration::Method::Results::Reader Declaration::Method::Reader::getResults() const { + return typename Declaration::Method::Results::Reader(_reader); +} +inline typename Declaration::Method::Results::Builder Declaration::Method::Builder::getResults() { + return typename Declaration::Method::Results::Builder(_builder); +} +inline typename Declaration::Method::Results::Builder Declaration::Method::Builder::initResults() { + _builder.setDataField< ::uint16_t>(::capnp::bounded<6>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<6>() * ::capnp::POINTERS).clear(); + return typename Declaration::Method::Results::Builder(_builder); +} +inline ::capnp::compiler::Declaration::Method::Results::Which Declaration::Method::Results::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS); +} +inline ::capnp::compiler::Declaration::Method::Results::Which Declaration::Method::Results::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Method::Results::Reader::isNone() const { + return which() == Declaration::Method::Results::NONE; +} +inline bool Declaration::Method::Results::Builder::isNone() { + return which() == Declaration::Method::Results::NONE; +} +inline ::capnp::Void Declaration::Method::Results::Reader::getNone() const { + KJ_IREQUIRE((which() == Declaration::Method::Results::NONE), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Declaration::Method::Results::Builder::getNone() { + KJ_IREQUIRE((which() == Declaration::Method::Results::NONE), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Declaration::Method::Results::Builder::setNone( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Method::Results::NONE); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Method::Results::Reader::isExplicit() const { + return which() == Declaration::Method::Results::EXPLICIT; +} +inline bool Declaration::Method::Results::Builder::isExplicit() { + return which() == Declaration::Method::Results::EXPLICIT; +} +inline bool Declaration::Method::Results::Reader::hasExplicit() const { + if (which() != Declaration::Method::Results::EXPLICIT) return false; + return !_reader.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Method::Results::Builder::hasExplicit() { + if (which() != Declaration::Method::Results::EXPLICIT) return false; + return !_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Declaration::ParamList::Reader Declaration::Method::Results::Reader::getExplicit() const { + KJ_IREQUIRE((which() == Declaration::Method::Results::EXPLICIT), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::get(_reader.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Declaration::ParamList::Builder Declaration::Method::Results::Builder::getExplicit() { + KJ_IREQUIRE((which() == Declaration::Method::Results::EXPLICIT), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::get(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS)); +} +inline void Declaration::Method::Results::Builder::setExplicit( ::capnp::compiler::Declaration::ParamList::Reader value) { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Method::Results::EXPLICIT); + ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::set(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Declaration::ParamList::Builder Declaration::Method::Results::Builder::initExplicit() { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Method::Results::EXPLICIT); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::init(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS)); +} +inline void Declaration::Method::Results::Builder::adoptExplicit( + ::capnp::Orphan< ::capnp::compiler::Declaration::ParamList>&& value) { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Method::Results::EXPLICIT); + ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::adopt(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Declaration::ParamList> Declaration::Method::Results::Builder::disownExplicit() { + KJ_IREQUIRE((which() == Declaration::Method::Results::EXPLICIT), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::disown(_builder.getPointerField( + ::capnp::bounded<6>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Annotation::Reader::hasType() const { + return !_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline bool Declaration::Annotation::Builder::hasType() { + return !_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Expression::Reader Declaration::Annotation::Reader::getType() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Expression::Builder Declaration::Annotation::Builder::getType() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Annotation::Builder::setType( ::capnp::compiler::Expression::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Expression::Builder Declaration::Annotation::Builder::initType() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Declaration::Annotation::Builder::adoptType( + ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Annotation::Builder::disownType() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} + +inline bool Declaration::Annotation::Reader::getTargetsFile() const { + return _reader.getDataField( + ::capnp::bounded<96>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Annotation::Builder::getTargetsFile() { + return _builder.getDataField( + ::capnp::bounded<96>() * ::capnp::ELEMENTS); +} +inline void Declaration::Annotation::Builder::setTargetsFile(bool value) { + _builder.setDataField( + ::capnp::bounded<96>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Annotation::Reader::getTargetsConst() const { + return _reader.getDataField( + ::capnp::bounded<97>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Annotation::Builder::getTargetsConst() { + return _builder.getDataField( + ::capnp::bounded<97>() * ::capnp::ELEMENTS); +} +inline void Declaration::Annotation::Builder::setTargetsConst(bool value) { + _builder.setDataField( + ::capnp::bounded<97>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Annotation::Reader::getTargetsEnum() const { + return _reader.getDataField( + ::capnp::bounded<98>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Annotation::Builder::getTargetsEnum() { + return _builder.getDataField( + ::capnp::bounded<98>() * ::capnp::ELEMENTS); +} +inline void Declaration::Annotation::Builder::setTargetsEnum(bool value) { + _builder.setDataField( + ::capnp::bounded<98>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Annotation::Reader::getTargetsEnumerant() const { + return _reader.getDataField( + ::capnp::bounded<99>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Annotation::Builder::getTargetsEnumerant() { + return _builder.getDataField( + ::capnp::bounded<99>() * ::capnp::ELEMENTS); +} +inline void Declaration::Annotation::Builder::setTargetsEnumerant(bool value) { + _builder.setDataField( + ::capnp::bounded<99>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Annotation::Reader::getTargetsStruct() const { + return _reader.getDataField( + ::capnp::bounded<100>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Annotation::Builder::getTargetsStruct() { + return _builder.getDataField( + ::capnp::bounded<100>() * ::capnp::ELEMENTS); +} +inline void Declaration::Annotation::Builder::setTargetsStruct(bool value) { + _builder.setDataField( + ::capnp::bounded<100>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Annotation::Reader::getTargetsField() const { + return _reader.getDataField( + ::capnp::bounded<101>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Annotation::Builder::getTargetsField() { + return _builder.getDataField( + ::capnp::bounded<101>() * ::capnp::ELEMENTS); +} +inline void Declaration::Annotation::Builder::setTargetsField(bool value) { + _builder.setDataField( + ::capnp::bounded<101>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Annotation::Reader::getTargetsUnion() const { + return _reader.getDataField( + ::capnp::bounded<102>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Annotation::Builder::getTargetsUnion() { + return _builder.getDataField( + ::capnp::bounded<102>() * ::capnp::ELEMENTS); +} +inline void Declaration::Annotation::Builder::setTargetsUnion(bool value) { + _builder.setDataField( + ::capnp::bounded<102>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Annotation::Reader::getTargetsGroup() const { + return _reader.getDataField( + ::capnp::bounded<103>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Annotation::Builder::getTargetsGroup() { + return _builder.getDataField( + ::capnp::bounded<103>() * ::capnp::ELEMENTS); +} +inline void Declaration::Annotation::Builder::setTargetsGroup(bool value) { + _builder.setDataField( + ::capnp::bounded<103>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Annotation::Reader::getTargetsInterface() const { + return _reader.getDataField( + ::capnp::bounded<104>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Annotation::Builder::getTargetsInterface() { + return _builder.getDataField( + ::capnp::bounded<104>() * ::capnp::ELEMENTS); +} +inline void Declaration::Annotation::Builder::setTargetsInterface(bool value) { + _builder.setDataField( + ::capnp::bounded<104>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Annotation::Reader::getTargetsMethod() const { + return _reader.getDataField( + ::capnp::bounded<105>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Annotation::Builder::getTargetsMethod() { + return _builder.getDataField( + ::capnp::bounded<105>() * ::capnp::ELEMENTS); +} +inline void Declaration::Annotation::Builder::setTargetsMethod(bool value) { + _builder.setDataField( + ::capnp::bounded<105>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Annotation::Reader::getTargetsParam() const { + return _reader.getDataField( + ::capnp::bounded<106>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Annotation::Builder::getTargetsParam() { + return _builder.getDataField( + ::capnp::bounded<106>() * ::capnp::ELEMENTS); +} +inline void Declaration::Annotation::Builder::setTargetsParam(bool value) { + _builder.setDataField( + ::capnp::bounded<106>() * ::capnp::ELEMENTS, value); +} + +inline bool Declaration::Annotation::Reader::getTargetsAnnotation() const { + return _reader.getDataField( + ::capnp::bounded<107>() * ::capnp::ELEMENTS); +} + +inline bool Declaration::Annotation::Builder::getTargetsAnnotation() { + return _builder.getDataField( + ::capnp::bounded<107>() * ::capnp::ELEMENTS); +} +inline void Declaration::Annotation::Builder::setTargetsAnnotation(bool value) { + _builder.setDataField( + ::capnp::bounded<107>() * ::capnp::ELEMENTS, value); +} + +inline bool ParsedFile::Reader::hasRoot() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool ParsedFile::Builder::hasRoot() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::compiler::Declaration::Reader ParsedFile::Reader::getRoot() const { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::compiler::Declaration::Builder ParsedFile::Builder::getRoot() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void ParsedFile::Builder::setRoot( ::capnp::compiler::Declaration::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::compiler::Declaration::Builder ParsedFile::Builder::initRoot() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void ParsedFile::Builder::adoptRoot( + ::capnp::Orphan< ::capnp::compiler::Declaration>&& value) { + ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::compiler::Declaration> ParsedFile::Builder::disownRoot() { + return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +} // namespace +} // namespace + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/compiler/lexer.c++ b/vendor/capnproto/src/capnp/compiler/lexer.c++ new file mode 100644 index 0000000..31440b4 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/lexer.c++ @@ -0,0 +1,259 @@ +// 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 "lexer.h" +#include +#include + +namespace capnp { +namespace compiler { + +namespace p = kj::parse; + +bool lex(kj::ArrayPtr input, LexedStatements::Builder result, + ErrorReporter& errorReporter) { + Lexer lexer(Orphanage::getForMessageContaining(result), errorReporter); + + auto parser = p::sequence(lexer.getParsers().statementSequence, p::endOfInput); + + Lexer::ParserInput parserInput(input.begin(), input.end()); + kj::Maybe>> parseOutput = parser(parserInput); + + KJ_IF_MAYBE(output, parseOutput) { + auto l = result.initStatements(output->size()); + for (uint i = 0; i < output->size(); i++) { + l.adoptWithCaveats(i, kj::mv((*output)[i])); + } + return true; + } else { + uint32_t best = parserInput.getBest(); + errorReporter.addError(best, best, kj::str("Parse error.")); + return false; + } +} + +namespace { + +typedef p::Span Location; + +Token::Builder initTok(Orphan& t, const Location& loc) { + auto builder = t.get(); + builder.setStartByte(loc.begin()); + builder.setEndByte(loc.end()); + return builder; +} + +void buildTokenSequenceList(List>::Builder builder, + kj::Array>>&& items) { + for (uint i = 0; i < items.size(); i++) { + auto& item = items[i]; + auto itemBuilder = builder.init(i, item.size()); + for (uint j = 0; j < item.size(); j++) { + itemBuilder.adoptWithCaveats(j, kj::mv(item[j])); + } + } +} + +constexpr auto discardComment = + sequence(p::exactChar<'#'>(), p::discard(p::many(p::discard(p::anyOfChars("\n").invert()))), + p::oneOf(p::exactChar<'\n'>(), p::endOfInput)); +constexpr auto utf8Bom = + sequence(p::exactChar<'\xef'>(), p::exactChar<'\xbb'>(), p::exactChar<'\xbf'>()); + +constexpr auto bomsAndWhitespace = + sequence(p::discardWhitespace, + p::discard(p::many(sequence(utf8Bom, p::discardWhitespace)))); + +constexpr auto commentsAndWhitespace = + sequence(bomsAndWhitespace, + p::discard(p::many(sequence(discardComment, bomsAndWhitespace)))); + +constexpr auto discardLineWhitespace = + p::discard(p::many(p::discard(p::whitespaceChar.invert().orAny("\r\n").invert()))); +constexpr auto newline = p::oneOf( + p::exactChar<'\n'>(), + sequence(p::exactChar<'\r'>(), p::discard(p::optional(p::exactChar<'\n'>())))); + +constexpr auto docComment = p::discard(p::optional(p::sequence( + discardLineWhitespace, + p::discard(p::optional(newline)), + p::oneOrMore(p::sequence(discardLineWhitespace, discardComment))))); +// Parses a set of comment lines preceded by at most one newline and with no intervening blank +// lines. + +} // namespace + +Lexer::Lexer(Orphanage orphanageParam, ErrorReporter& errorReporter) + : orphanage(orphanageParam) { + + // Note that because passing an lvalue to a parser constructor uses it by-referencee, it's safe + // for us to use parsers.tokenSequence even though we haven't yet constructed it. + auto& tokenSequence = parsers.tokenSequence; + + auto& commaDelimitedList = arena.copy(p::transform( + p::sequence(tokenSequence, p::many(p::sequence(p::exactChar<','>(), tokenSequence))), + [](kj::Array>&& first, kj::Array>>&& rest) + -> kj::Array>> { + if (first == nullptr && rest == nullptr) { + // Completely empty list. + return nullptr; + } else { + uint restSize = rest.size(); + if (restSize > 0 && rest[restSize - 1] == nullptr) { + // Allow for trailing commas by shortening the list by one item if the final token is + // nullptr + restSize--; + } + auto result = kj::heapArrayBuilder>>(1 + restSize); // first+rest + result.add(kj::mv(first)); + for (uint i = 0; i < restSize ; i++) { + result.add(kj::mv(rest[i])); + } + return result.finish(); + } + })); + + auto& token = arena.copy(p::oneOf( + p::transformWithLocation(p::identifier, + [this](Location loc, kj::String name) -> Orphan { + auto t = orphanage.newOrphan(); + initTok(t, loc).setIdentifier(name); + return t; + }), + p::transformWithLocation(p::doubleQuotedString, + [this](Location loc, kj::String text) -> Orphan { + auto t = orphanage.newOrphan(); + initTok(t, loc).setStringLiteral(text); + return t; + }), + p::transformWithLocation( + sequence(p::exactChar<'`'>(), p::many(p::anyOfChars("\r\n").invert())), + [this](Location loc, kj::Array text) -> Orphan { + // Backtick-quoted line. Note that we assume either `\r` or `\n` is a valid line + // ending (to cover all known line ending formats) but we replace the line ending + // with `\n`. This way, changing the line endings of your source code doesn't affect + // the compiled code. + auto t = orphanage.newOrphan(); + // Append '\n' to the text. + auto out = initTok(t, loc).initStringLiteral(text.size() + 1); + memcpy(out.begin(), text.begin(), text.size()); + out[out.size() - 1] = '\n'; + return t; + }), + p::transformWithLocation(p::doubleQuotedHexBinary, + [this](Location loc, kj::Array data) -> Orphan { + auto t = orphanage.newOrphan(); + initTok(t, loc).setBinaryLiteral(data); + return t; + }), + p::transformWithLocation(p::integer, + [this](Location loc, uint64_t i) -> Orphan { + auto t = orphanage.newOrphan(); + initTok(t, loc).setIntegerLiteral(i); + return t; + }), + p::transformWithLocation(p::number, + [this](Location loc, double x) -> Orphan { + auto t = orphanage.newOrphan(); + initTok(t, loc).setFloatLiteral(x); + return t; + }), + p::transformWithLocation( + p::charsToString(p::oneOrMore(p::anyOfChars("!$%&*+-./:<=>?@^|~"))), + [this](Location loc, kj::String text) -> Orphan { + auto t = orphanage.newOrphan(); + initTok(t, loc).setOperator(text); + return t; + }), + p::transformWithLocation( + sequence(p::exactChar<'('>(), commaDelimitedList, p::exactChar<')'>()), + [this](Location loc, kj::Array>>&& items) -> Orphan { + auto t = orphanage.newOrphan(); + buildTokenSequenceList( + initTok(t, loc).initParenthesizedList(items.size()), kj::mv(items)); + return t; + }), + p::transformWithLocation( + sequence(p::exactChar<'['>(), commaDelimitedList, p::exactChar<']'>()), + [this](Location loc, kj::Array>>&& items) -> Orphan { + auto t = orphanage.newOrphan(); + buildTokenSequenceList( + initTok(t, loc).initBracketedList(items.size()), kj::mv(items)); + return t; + }), + p::transformOrReject(p::transformWithLocation( + p::oneOf(sequence(p::exactChar<'\xff'>(), p::exactChar<'\xfe'>()), + sequence(p::exactChar<'\xfe'>(), p::exactChar<'\xff'>()), + sequence(p::exactChar<'\x00'>())), + [&errorReporter](Location loc) -> kj::Maybe> { + errorReporter.addError(loc.begin(), loc.end(), + "Non-UTF-8 input detected. Cap'n Proto schema files must be UTF-8 text."); + return nullptr; + }), [](kj::Maybe> param) { return param; }))); + parsers.tokenSequence = arena.copy(p::sequence( + commentsAndWhitespace, p::many(p::sequence(token, commentsAndWhitespace)))); + + auto& statementSequence = parsers.statementSequence; + + auto& statementEnd = arena.copy(p::oneOf( + transform(p::sequence(p::exactChar<';'>(), docComment), + [this]() -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + builder.setLine(); + return result; + }), + transform( + p::sequence(p::exactChar<'{'>(), docComment, statementSequence, p::exactChar<'}'>(), + docComment), + [this](kj::Array>&& statements) + -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + auto list = builder.initBlock(statements.size()); + for (uint i = 0; i < statements.size(); i++) { + list.adoptWithCaveats(i, kj::mv(statements[i])); + } + return result; + }) + )); + + auto& statement = arena.copy(p::transformWithLocation(p::sequence(tokenSequence, statementEnd), + [](Location loc, kj::Array>&& tokens, Orphan&& statement) { + auto builder = statement.get(); + auto tokensBuilder = builder.initTokens(tokens.size()); + for (uint i = 0; i < tokens.size(); i++) { + tokensBuilder.adoptWithCaveats(i, kj::mv(tokens[i])); + } + builder.setStartByte(loc.begin()); + builder.setEndByte(loc.end()); + return kj::mv(statement); + })); + + parsers.statementSequence = arena.copy(sequence( + commentsAndWhitespace, many(sequence(statement, commentsAndWhitespace)))); + +} + +Lexer::~Lexer() noexcept(false) {} + +} // namespace compiler +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/compiler/lexer.capnp.h b/vendor/capnproto/src/capnp/compiler/lexer.capnp.h new file mode 100644 index 0000000..3689fb8 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/lexer.capnp.h @@ -0,0 +1,1022 @@ +// Generated by Cap'n Proto compiler, DO NOT EDIT +// source: lexer.capnp + +#pragma once + +#include + +#ifndef CAPNP_VERSION +#error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?" +#elif CAPNP_VERSION != 1004000 +#error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." +#endif + +CAPNP_BEGIN_HEADER + +namespace capnp { +namespace compiler { + +struct Token { + Token() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + IDENTIFIER, + STRING_LITERAL, + INTEGER_LITERAL, + FLOAT_LITERAL, + OPERATOR, + PARENTHESIZED_LIST, + BRACKETED_LIST, + BINARY_LITERAL, + }; + + struct _capnpPrivate { + struct IsStruct; + static constexpr ::capnp::Kind kind = ::capnp::Kind::STRUCT; + static constexpr uint16_t dataWordSize = 3; + static constexpr uint16_t pointerCount = 1; + }; +}; + +struct Statement { + Statement() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + LINE, + BLOCK, + }; + + struct _capnpPrivate { + struct IsStruct; + static constexpr ::capnp::Kind kind = ::capnp::Kind::STRUCT; + static constexpr uint16_t dataWordSize = 2; + static constexpr uint16_t pointerCount = 3; + }; +}; + +struct LexedStatements { + LexedStatements() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + struct IsStruct; + static constexpr ::capnp::Kind kind = ::capnp::Kind::STRUCT; + static constexpr uint16_t dataWordSize = 0; + static constexpr uint16_t pointerCount = 1; + }; +}; + +// ======================================================================================= + +class Token::Reader { +public: + typedef Token Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline Which which() const; + inline bool isIdentifier() const; + inline bool hasIdentifier() const; + inline ::capnp::Text::Reader getIdentifier() const; + + inline bool isStringLiteral() const; + inline bool hasStringLiteral() const; + inline ::capnp::Text::Reader getStringLiteral() const; + + inline bool isIntegerLiteral() const; + inline ::uint64_t getIntegerLiteral() const; + + inline bool isFloatLiteral() const; + inline double getFloatLiteral() const; + + inline bool isOperator() const; + inline bool hasOperator() const; + inline ::capnp::Text::Reader getOperator() const; + + inline bool isParenthesizedList() const; + inline bool hasParenthesizedList() const; + inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader getParenthesizedList() const; + + inline bool isBracketedList() const; + inline bool hasBracketedList() const; + inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader getBracketedList() const; + + inline ::uint32_t getStartByte() const; + + inline ::uint32_t getEndByte() const; + + inline bool isBinaryLiteral() const; + inline bool hasBinaryLiteral() const; + inline ::capnp::Data::Reader getBinaryLiteral() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Token::Builder { +public: + typedef Token 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(); } + + inline Which which(); + inline bool isIdentifier(); + inline bool hasIdentifier(); + inline ::capnp::Text::Builder getIdentifier(); + inline void setIdentifier( ::capnp::Text::Reader value); + inline ::capnp::Text::Builder initIdentifier(unsigned int size); + inline void adoptIdentifier(::capnp::Orphan< ::capnp::Text>&& value); + inline ::capnp::Orphan< ::capnp::Text> disownIdentifier(); + + inline bool isStringLiteral(); + inline bool hasStringLiteral(); + inline ::capnp::Text::Builder getStringLiteral(); + inline void setStringLiteral( ::capnp::Text::Reader value); + inline ::capnp::Text::Builder initStringLiteral(unsigned int size); + inline void adoptStringLiteral(::capnp::Orphan< ::capnp::Text>&& value); + inline ::capnp::Orphan< ::capnp::Text> disownStringLiteral(); + + inline bool isIntegerLiteral(); + inline ::uint64_t getIntegerLiteral(); + inline void setIntegerLiteral( ::uint64_t value); + + inline bool isFloatLiteral(); + inline double getFloatLiteral(); + inline void setFloatLiteral(double value); + + inline bool isOperator(); + inline bool hasOperator(); + inline ::capnp::Text::Builder getOperator(); + inline void setOperator( ::capnp::Text::Reader value); + inline ::capnp::Text::Builder initOperator(unsigned int size); + inline void adoptOperator(::capnp::Orphan< ::capnp::Text>&& value); + inline ::capnp::Orphan< ::capnp::Text> disownOperator(); + + inline bool isParenthesizedList(); + inline bool hasParenthesizedList(); + inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder getParenthesizedList(); + inline void setParenthesizedList( ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader value); + inline void setParenthesizedList(::kj::ArrayPtr::Reader> value); + inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder initParenthesizedList(unsigned int size); + inline void adoptParenthesizedList(::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>> disownParenthesizedList(); + + inline bool isBracketedList(); + inline bool hasBracketedList(); + inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder getBracketedList(); + inline void setBracketedList( ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader value); + inline void setBracketedList(::kj::ArrayPtr::Reader> value); + inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder initBracketedList(unsigned int size); + inline void adoptBracketedList(::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>> disownBracketedList(); + + inline ::uint32_t getStartByte(); + inline void setStartByte( ::uint32_t value); + + inline ::uint32_t getEndByte(); + inline void setEndByte( ::uint32_t value); + + inline bool isBinaryLiteral(); + inline bool hasBinaryLiteral(); + inline ::capnp::Data::Builder getBinaryLiteral(); + inline void setBinaryLiteral( ::capnp::Data::Reader value); + inline ::capnp::Data::Builder initBinaryLiteral(unsigned int size); + inline void adoptBinaryLiteral(::capnp::Orphan< ::capnp::Data>&& value); + inline ::capnp::Orphan< ::capnp::Data> disownBinaryLiteral(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + +class Statement::Reader { +public: + typedef Statement Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline Which which() const; + inline bool hasTokens() const; + inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Reader getTokens() const; + + inline bool isLine() const; + inline ::capnp::Void getLine() const; + + inline bool isBlock() const; + inline bool hasBlock() const; + inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader getBlock() const; + + inline bool hasDocComment() const; + inline ::capnp::Text::Reader getDocComment() const; + + inline ::uint32_t getStartByte() const; + + inline ::uint32_t getEndByte() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Statement::Builder { +public: + typedef Statement 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(); } + + inline Which which(); + inline bool hasTokens(); + inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Builder getTokens(); + inline void setTokens( ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Builder initTokens(unsigned int size); + inline void adoptTokens(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>> disownTokens(); + + inline bool isLine(); + inline ::capnp::Void getLine(); + inline void setLine( ::capnp::Void value = ::capnp::VOID); + + inline bool isBlock(); + inline bool hasBlock(); + inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder getBlock(); + inline void setBlock( ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder initBlock(unsigned int size); + inline void adoptBlock(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>> disownBlock(); + + inline bool hasDocComment(); + inline ::capnp::Text::Builder getDocComment(); + inline void setDocComment( ::capnp::Text::Reader value); + inline ::capnp::Text::Builder initDocComment(unsigned int size); + inline void adoptDocComment(::capnp::Orphan< ::capnp::Text>&& value); + inline ::capnp::Orphan< ::capnp::Text> disownDocComment(); + + inline ::uint32_t getStartByte(); + inline void setStartByte( ::uint32_t value); + + inline ::uint32_t getEndByte(); + inline void setEndByte( ::uint32_t value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + +class LexedStatements::Reader { +public: + typedef LexedStatements Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline bool hasStatements() const; + inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader getStatements() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class LexedStatements::Builder { +public: + typedef LexedStatements 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(); } + + inline bool hasStatements(); + inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder getStatements(); + inline void setStatements( ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder initStatements(unsigned int size); + inline void adoptStatements(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>> disownStatements(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + +// ======================================================================================= + +inline ::capnp::compiler::Token::Which Token::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline ::capnp::compiler::Token::Which Token::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline bool Token::Reader::isIdentifier() const { + return which() == Token::IDENTIFIER; +} +inline bool Token::Builder::isIdentifier() { + return which() == Token::IDENTIFIER; +} +inline bool Token::Reader::hasIdentifier() const { + if (which() != Token::IDENTIFIER) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Token::Builder::hasIdentifier() { + if (which() != Token::IDENTIFIER) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Token::Reader::getIdentifier() const { + KJ_IREQUIRE((which() == Token::IDENTIFIER), + "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 Token::Builder::getIdentifier() { + KJ_IREQUIRE((which() == Token::IDENTIFIER), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Token::Builder::setIdentifier( ::capnp::Text::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::IDENTIFIER); + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Token::Builder::initIdentifier(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::IDENTIFIER); + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Token::Builder::adoptIdentifier( + ::capnp::Orphan< ::capnp::Text>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::IDENTIFIER); + ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::Text> Token::Builder::disownIdentifier() { + KJ_IREQUIRE((which() == Token::IDENTIFIER), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Token::Reader::isStringLiteral() const { + return which() == Token::STRING_LITERAL; +} +inline bool Token::Builder::isStringLiteral() { + return which() == Token::STRING_LITERAL; +} +inline bool Token::Reader::hasStringLiteral() const { + if (which() != Token::STRING_LITERAL) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Token::Builder::hasStringLiteral() { + if (which() != Token::STRING_LITERAL) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Token::Reader::getStringLiteral() const { + KJ_IREQUIRE((which() == Token::STRING_LITERAL), + "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 Token::Builder::getStringLiteral() { + KJ_IREQUIRE((which() == Token::STRING_LITERAL), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Token::Builder::setStringLiteral( ::capnp::Text::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::STRING_LITERAL); + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Token::Builder::initStringLiteral(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::STRING_LITERAL); + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Token::Builder::adoptStringLiteral( + ::capnp::Orphan< ::capnp::Text>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::STRING_LITERAL); + ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::Text> Token::Builder::disownStringLiteral() { + KJ_IREQUIRE((which() == Token::STRING_LITERAL), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Token::Reader::isIntegerLiteral() const { + return which() == Token::INTEGER_LITERAL; +} +inline bool Token::Builder::isIntegerLiteral() { + return which() == Token::INTEGER_LITERAL; +} +inline ::uint64_t Token::Reader::getIntegerLiteral() const { + KJ_IREQUIRE((which() == Token::INTEGER_LITERAL), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Token::Builder::getIntegerLiteral() { + KJ_IREQUIRE((which() == Token::INTEGER_LITERAL), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Token::Builder::setIntegerLiteral( ::uint64_t value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::INTEGER_LITERAL); + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Token::Reader::isFloatLiteral() const { + return which() == Token::FLOAT_LITERAL; +} +inline bool Token::Builder::isFloatLiteral() { + return which() == Token::FLOAT_LITERAL; +} +inline double Token::Reader::getFloatLiteral() const { + KJ_IREQUIRE((which() == Token::FLOAT_LITERAL), + "Must check which() before get()ing a union member."); + return _reader.getDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline double Token::Builder::getFloatLiteral() { + KJ_IREQUIRE((which() == Token::FLOAT_LITERAL), + "Must check which() before get()ing a union member."); + return _builder.getDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Token::Builder::setFloatLiteral(double value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::FLOAT_LITERAL); + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Token::Reader::isOperator() const { + return which() == Token::OPERATOR; +} +inline bool Token::Builder::isOperator() { + return which() == Token::OPERATOR; +} +inline bool Token::Reader::hasOperator() const { + if (which() != Token::OPERATOR) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Token::Builder::hasOperator() { + if (which() != Token::OPERATOR) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Token::Reader::getOperator() const { + KJ_IREQUIRE((which() == Token::OPERATOR), + "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 Token::Builder::getOperator() { + KJ_IREQUIRE((which() == Token::OPERATOR), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Token::Builder::setOperator( ::capnp::Text::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::OPERATOR); + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Token::Builder::initOperator(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::OPERATOR); + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Token::Builder::adoptOperator( + ::capnp::Orphan< ::capnp::Text>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::OPERATOR); + ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::Text> Token::Builder::disownOperator() { + KJ_IREQUIRE((which() == Token::OPERATOR), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Token::Reader::isParenthesizedList() const { + return which() == Token::PARENTHESIZED_LIST; +} +inline bool Token::Builder::isParenthesizedList() { + return which() == Token::PARENTHESIZED_LIST; +} +inline bool Token::Reader::hasParenthesizedList() const { + if (which() != Token::PARENTHESIZED_LIST) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Token::Builder::hasParenthesizedList() { + if (which() != Token::PARENTHESIZED_LIST) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader Token::Reader::getParenthesizedList() const { + KJ_IREQUIRE((which() == Token::PARENTHESIZED_LIST), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder Token::Builder::getParenthesizedList() { + KJ_IREQUIRE((which() == Token::PARENTHESIZED_LIST), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Token::Builder::setParenthesizedList( ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::PARENTHESIZED_LIST); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline void Token::Builder::setParenthesizedList(::kj::ArrayPtr::Reader> value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::PARENTHESIZED_LIST); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder Token::Builder::initParenthesizedList(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::PARENTHESIZED_LIST); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Token::Builder::adoptParenthesizedList( + ::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::PARENTHESIZED_LIST); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>> Token::Builder::disownParenthesizedList() { + KJ_IREQUIRE((which() == Token::PARENTHESIZED_LIST), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Token::Reader::isBracketedList() const { + return which() == Token::BRACKETED_LIST; +} +inline bool Token::Builder::isBracketedList() { + return which() == Token::BRACKETED_LIST; +} +inline bool Token::Reader::hasBracketedList() const { + if (which() != Token::BRACKETED_LIST) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Token::Builder::hasBracketedList() { + if (which() != Token::BRACKETED_LIST) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader Token::Reader::getBracketedList() const { + KJ_IREQUIRE((which() == Token::BRACKETED_LIST), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder Token::Builder::getBracketedList() { + KJ_IREQUIRE((which() == Token::BRACKETED_LIST), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Token::Builder::setBracketedList( ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BRACKETED_LIST); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline void Token::Builder::setBracketedList(::kj::ArrayPtr::Reader> value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BRACKETED_LIST); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder Token::Builder::initBracketedList(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BRACKETED_LIST); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Token::Builder::adoptBracketedList( + ::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BRACKETED_LIST); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>> Token::Builder::disownBracketedList() { + KJ_IREQUIRE((which() == Token::BRACKETED_LIST), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::uint32_t Token::Reader::getStartByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Token::Builder::getStartByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Token::Builder::setStartByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t Token::Reader::getEndByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<4>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Token::Builder::getEndByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<4>() * ::capnp::ELEMENTS); +} +inline void Token::Builder::setEndByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<4>() * ::capnp::ELEMENTS, value); +} + +inline bool Token::Reader::isBinaryLiteral() const { + return which() == Token::BINARY_LITERAL; +} +inline bool Token::Builder::isBinaryLiteral() { + return which() == Token::BINARY_LITERAL; +} +inline bool Token::Reader::hasBinaryLiteral() const { + if (which() != Token::BINARY_LITERAL) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Token::Builder::hasBinaryLiteral() { + if (which() != Token::BINARY_LITERAL) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Data::Reader Token::Reader::getBinaryLiteral() const { + KJ_IREQUIRE((which() == Token::BINARY_LITERAL), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Data>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::Data::Builder Token::Builder::getBinaryLiteral() { + KJ_IREQUIRE((which() == Token::BINARY_LITERAL), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Data>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Token::Builder::setBinaryLiteral( ::capnp::Data::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BINARY_LITERAL); + ::capnp::_::PointerHelpers< ::capnp::Data>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Data::Builder Token::Builder::initBinaryLiteral(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BINARY_LITERAL); + return ::capnp::_::PointerHelpers< ::capnp::Data>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Token::Builder::adoptBinaryLiteral( + ::capnp::Orphan< ::capnp::Data>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BINARY_LITERAL); + ::capnp::_::PointerHelpers< ::capnp::Data>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::Data> Token::Builder::disownBinaryLiteral() { + KJ_IREQUIRE((which() == Token::BINARY_LITERAL), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Data>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::capnp::compiler::Statement::Which Statement::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline ::capnp::compiler::Statement::Which Statement::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline bool Statement::Reader::hasTokens() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Statement::Builder::hasTokens() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Reader Statement::Reader::getTokens() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Builder Statement::Builder::getTokens() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Statement::Builder::setTokens( ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Builder Statement::Builder::initTokens(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Statement::Builder::adoptTokens( + ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>> Statement::Builder::disownTokens() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Statement::Reader::isLine() const { + return which() == Statement::LINE; +} +inline bool Statement::Builder::isLine() { + return which() == Statement::LINE; +} +inline ::capnp::Void Statement::Reader::getLine() const { + KJ_IREQUIRE((which() == Statement::LINE), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Statement::Builder::getLine() { + KJ_IREQUIRE((which() == Statement::LINE), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Statement::Builder::setLine( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Statement::LINE); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Statement::Reader::isBlock() const { + return which() == Statement::BLOCK; +} +inline bool Statement::Builder::isBlock() { + return which() == Statement::BLOCK; +} +inline bool Statement::Reader::hasBlock() const { + if (which() != Statement::BLOCK) return false; + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool Statement::Builder::hasBlock() { + if (which() != Statement::BLOCK) return false; + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader Statement::Reader::getBlock() const { + KJ_IREQUIRE((which() == Statement::BLOCK), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder Statement::Builder::getBlock() { + KJ_IREQUIRE((which() == Statement::BLOCK), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Statement::Builder::setBlock( ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Statement::BLOCK); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder Statement::Builder::initBlock(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Statement::BLOCK); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), size); +} +inline void Statement::Builder::adoptBlock( + ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Statement::BLOCK); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>> Statement::Builder::disownBlock() { + KJ_IREQUIRE((which() == Statement::BLOCK), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +inline bool Statement::Reader::hasDocComment() const { + return !_reader.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); +} +inline bool Statement::Builder::hasDocComment() { + return !_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Statement::Reader::getDocComment() const { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline ::capnp::Text::Builder Statement::Builder::getDocComment() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline void Statement::Builder::setDocComment( ::capnp::Text::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Statement::Builder::initDocComment(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), size); +} +inline void Statement::Builder::adoptDocComment( + ::capnp::Orphan< ::capnp::Text>&& value) { + ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::Text> Statement::Builder::disownDocComment() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} + +inline ::uint32_t Statement::Reader::getStartByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Statement::Builder::getStartByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Statement::Builder::setStartByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t Statement::Reader::getEndByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Statement::Builder::getEndByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} +inline void Statement::Builder::setEndByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); +} + +inline bool LexedStatements::Reader::hasStatements() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool LexedStatements::Builder::hasStatements() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader LexedStatements::Reader::getStatements() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder LexedStatements::Builder::getStatements() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void LexedStatements::Builder::setStatements( ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder LexedStatements::Builder::initStatements(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void LexedStatements::Builder::adoptStatements( + ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>> LexedStatements::Builder::disownStatements() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +} // namespace +} // namespace + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/compiler/lexer.h b/vendor/capnproto/src/capnp/compiler/lexer.h new file mode 100644 index 0000000..cff290f --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/lexer.h @@ -0,0 +1,91 @@ +// 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. + +#pragma once + +#include +#include +#include +#include "error-reporter.h" + +CAPNP_BEGIN_HEADER + +namespace capnp { +namespace compiler { + +bool lex(kj::ArrayPtr input, LexedStatements::Builder result, + ErrorReporter& errorReporter); +// Lex the given source code, placing the results in `result`. Returns true if there +// were no errors, false if there were. Even when errors are present, the file may have partial +// content which can be fed into later stages of parsing in order to find more errors. + +class Lexer { + // Advanced lexer interface. This interface exposes the inner parsers so that you can embed them + // into your own parsers. + +public: + Lexer(Orphanage orphanage, ErrorReporter& errorReporter); + // `orphanage` is used to allocate Cap'n Proto message objects in the result. `inputStart` is + // a pointer to the beginning of the input, used to compute byte offsets. + + ~Lexer() noexcept(false); + + class ParserInput: public kj::parse::IteratorInput { + // Like IteratorInput except that positions are measured as byte offsets + // rather than pointers. + + public: + ParserInput(const char* begin, const char* end) + : IteratorInput(begin, end), begin(begin) {} + explicit ParserInput(ParserInput& parent) + : IteratorInput(parent), begin(parent.begin) {} + + inline uint32_t getBest() { + return IteratorInput::getBest() - begin; + } + inline uint32_t getPosition() { + return IteratorInput::getPosition() - begin; + } + + private: + const char* begin; + }; + + template + using Parser = kj::parse::ParserRef; + + struct Parsers { + Parser>> tokenSequence; + Parser>> statementSequence; + }; + + const Parsers& getParsers() { return parsers; } + +private: + Orphanage orphanage; + kj::Arena arena; + Parsers parsers; +}; + +} // namespace compiler +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/compiler/node-translator.c++ b/vendor/capnproto/src/capnp/compiler/node-translator.c++ new file mode 100644 index 0000000..786f30d --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/node-translator.c++ @@ -0,0 +1,2086 @@ +// 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 "node-translator.h" +#include "parser.h" // only for generateGroupId() and expressionString() +#include +#include +#include +#include +#include +#include +#include + +namespace capnp { +namespace compiler { + +bool shouldDetectIssue344() { + return getenv("CAPNP_IGNORE_ISSUE_344") == nullptr; +} + +class NodeTranslator::StructLayout { + // Massive, disgusting class which implements the layout algorithm, which decides the offset + // for each field. + +public: + template + struct HoleSet { + inline HoleSet(): holes{0, 0, 0, 0, 0, 0} {} + + // Represents a set of "holes" within a segment of allocated space, up to one hole of each + // power-of-two size between 1 bit and 32 bits. + // + // The amount of "used" space in a struct's data segment can always be represented as a + // combination of a word count and a HoleSet. The HoleSet represents the space lost to + // "padding". + // + // There can never be more than one hole of any particular size. Why is this? Well, consider + // that every data field has a power-of-two size, every field must be aligned to a multiple of + // its size, and the maximum size of a single field is 64 bits. If we need to add a new field + // of N bits, there are two possibilities: + // 1. A hole of size N or larger exists. In this case, we find the smallest hole that is at + // least N bits. Let's say that that hole has size M. We allocate the first N bits of the + // hole to the new field. The remaining M - N bits become a series of holes of sizes N*2, + // N*4, ..., M / 2. We know no holes of these sizes existed before because we chose M to be + // the smallest available hole larger than N. So, there is still no more than one hole of + // each size, and no hole larger than any hole that existed previously. + // 2. No hole equal or larger N exists. In that case we extend the data section's size by one + // word, creating a new 64-bit hole at the end. We then allocate N bits from it, creating + // a series of holes between N and 64 bits, as described in point (1). Thus, again, there + // is still at most one hole of each size, and the largest hole is 32 bits. + + UIntType holes[6]; + // The offset of each hole as a multiple of its size. A value of zero indicates that no hole + // exists. Notice that it is impossible for any actual hole to have an offset of zero, because + // the first field allocated is always placed at the very beginning of the section. So either + // the section has a size of zero (in which case there are no holes), or offset zero is + // already allocated and therefore cannot be a hole. + + kj::Maybe tryAllocate(UIntType lgSize) { + // Try to find space for a field of size 2^lgSize within the set of holes. If found, + // remove it from the holes, and return its offset (as a multiple of its size). If there + // is no such space, returns zero (no hole can be at offset zero, as explained above). + + if (lgSize >= kj::size(holes)) { + return nullptr; + } else if (holes[lgSize] != 0) { + UIntType result = holes[lgSize]; + holes[lgSize] = 0; + return result; + } else { + KJ_IF_MAYBE(next, tryAllocate(lgSize + 1)) { + UIntType result = *next * 2; + holes[lgSize] = result + 1; + return result; + } else { + return nullptr; + } + } + } + + void addHolesAtEnd(UIntType lgSize, UIntType offset, + UIntType limitLgSize = sizeof(HoleSet::holes) / sizeof(HoleSet::holes[0])) { + // Add new holes of progressively larger sizes in the range [lgSize, limitLgSize) starting + // from the given offset. The idea is that you just allocated an lgSize-sized field from + // an limitLgSize-sized space, such as a newly-added word on the end of the data segment. + + KJ_ASSUME(limitLgSize <= kj::size(holes)); + + while (lgSize < limitLgSize) { + KJ_DREQUIRE(holes[lgSize] == 0); + KJ_DREQUIRE(offset % 2 == 1); + holes[lgSize] = offset; + ++lgSize; + offset = (offset + 1) / 2; + } + } + + bool tryExpand(UIntType oldLgSize, uint oldOffset, uint expansionFactor) { + // Try to expand the value at the given location by combining it with subsequent holes, so + // as to expand the location to be 2^expansionFactor times the size that it started as. + // (In other words, the new lgSize is oldLgSize + expansionFactor.) + + if (expansionFactor == 0) { + // No expansion requested. + return true; + } + if (oldLgSize == kj::size(holes)) { + // Old value is already a full word. Further expansion is impossible. + return false; + } + KJ_ASSERT(oldLgSize < kj::size(holes)); + if (holes[oldLgSize] != oldOffset + 1) { + // The space immediately after the location is not a hole. + return false; + } + + // We can expand the location by one factor by combining it with a hole. Try to further + // expand from there to the number of factors requested. + if (tryExpand(oldLgSize + 1, oldOffset >> 1, expansionFactor - 1)) { + // Success. Consume the hole. + holes[oldLgSize] = 0; + return true; + } else { + return false; + } + } + + kj::Maybe smallestAtLeast(uint size) { + // Return the size of the smallest hole that is equal to or larger than the given size. + + for (uint i = size; i < kj::size(holes); i++) { + if (holes[i] != 0) { + return i; + } + } + return nullptr; + } + + }; + + struct StructOrGroup { + // Abstract interface for scopes in which fields can be added. + + virtual void addVoid() = 0; + virtual uint addData(uint lgSize) = 0; + virtual uint addPointer() = 0; + virtual bool tryExpandData(uint oldLgSize, uint oldOffset, uint expansionFactor) = 0; + // Try to expand the given previously-allocated space by 2^expansionFactor. Succeeds -- + // returning true -- if the following space happens to be empty, making this expansion possible. + // Otherwise, returns false. + }; + + struct Top: public StructOrGroup { + uint dataWordCount = 0; + uint pointerCount = 0; + // Size of the struct so far. + + HoleSet holes; + + void addVoid() override {} + + uint addData(uint lgSize) override { + KJ_IF_MAYBE(hole, holes.tryAllocate(lgSize)) { + return *hole; + } else { + uint offset = dataWordCount++ << (6 - lgSize); + holes.addHolesAtEnd(lgSize, offset + 1); + return offset; + } + } + + uint addPointer() override { + return pointerCount++; + } + + bool tryExpandData(uint oldLgSize, uint oldOffset, uint expansionFactor) override { + return holes.tryExpand(oldLgSize, oldOffset, expansionFactor); + } + + Top() = default; + KJ_DISALLOW_COPY_AND_MOVE(Top); + }; + + struct Union { + struct DataLocation { + uint lgSize; + uint offset; + + bool tryExpandTo(Union& u, uint newLgSize) { + if (newLgSize <= lgSize) { + return true; + } else if (u.parent.tryExpandData(lgSize, offset, newLgSize - lgSize)) { + offset >>= (newLgSize - lgSize); + lgSize = newLgSize; + return true; + } else { + return false; + } + } + }; + + StructOrGroup& parent; + uint groupCount = 0; + kj::Maybe discriminantOffset; + kj::Vector dataLocations; + kj::Vector pointerLocations; + + inline Union(StructOrGroup& parent): parent(parent) {} + KJ_DISALLOW_COPY_AND_MOVE(Union); + + uint addNewDataLocation(uint lgSize) { + // Add a whole new data location to the union with the given size. + + uint offset = parent.addData(lgSize); + dataLocations.add(DataLocation { lgSize, offset }); + return offset; + } + + uint addNewPointerLocation() { + // Add a whole new pointer location to the union with the given size. + + return pointerLocations.add(parent.addPointer()); + } + + void newGroupAddingFirstMember() { + if (++groupCount == 2) { + addDiscriminant(); + } + } + + bool addDiscriminant() { + if (discriminantOffset == nullptr) { + discriminantOffset = parent.addData(4); // 2^4 = 16 bits + return true; + } else { + return false; + } + } + }; + + struct Group final: public StructOrGroup { + public: + class DataLocationUsage { + public: + DataLocationUsage(): isUsed(false) {} + explicit DataLocationUsage(uint lgSize): isUsed(true), lgSizeUsed(lgSize) {} + + kj::Maybe smallestHoleAtLeast(Union::DataLocation& location, uint lgSize) { + // Find the smallest single hole that is at least the given size. This is used to find the + // optimal place to allocate each field -- it is placed in the smallest slot where it fits, + // to reduce fragmentation. Returns the size of the hole, if found. + + if (!isUsed) { + // The location is effectively one big hole. + if (lgSize <= location.lgSize) { + return location.lgSize; + } else { + return nullptr; + } + } else if (lgSize >= lgSizeUsed) { + // Requested size is at least our current usage, so clearly won't fit in any current + // holes, but if the location's size is larger than what we're using, we'd be able to + // expand. + if (lgSize < location.lgSize) { + return lgSize; + } else { + return nullptr; + } + } else KJ_IF_MAYBE(result, holes.smallestAtLeast(lgSize)) { + // There's a hole. + return *result; + } else { + // The requested size is smaller than what we're already using, but there are no holes + // available. If we could double our size, then we could allocate in the new space. + + if (lgSizeUsed < location.lgSize) { + // We effectively create a new hole the same size as the current usage. + return lgSizeUsed; + } else { + return nullptr; + } + } + } + + uint allocateFromHole(Group& group, Union::DataLocation& location, uint lgSize) { + // Allocate the given space from an existing hole, given smallestHoleAtLeast() already + // returned non-null indicating such a hole exists. + + uint result; + + if (!isUsed) { + // The location is totally unused, so just allocate from the beginning. + KJ_DASSERT(lgSize <= location.lgSize, "Did smallestHoleAtLeast() really find a hole?"); + result = 0; + isUsed = true; + lgSizeUsed = lgSize; + } else if (lgSize >= lgSizeUsed) { + // Requested size is at least our current usage, so clearly won't fit in any holes. + // We must expand to double the requested size, and return the second half. + KJ_DASSERT(lgSize < location.lgSize, "Did smallestHoleAtLeast() really find a hole?"); + holes.addHolesAtEnd(lgSizeUsed, 1, lgSize); + lgSizeUsed = lgSize + 1; + result = 1; + } else KJ_IF_MAYBE(hole, holes.tryAllocate(lgSize)) { + // Found a hole. + result = *hole; + } else { + // The requested size is smaller than what we're using so far, but didn't fit in a + // hole. We should double our "used" size, then allocate from the new space. + KJ_DASSERT(lgSizeUsed < location.lgSize, + "Did smallestHoleAtLeast() really find a hole?"); + result = 1 << (lgSizeUsed - lgSize); + holes.addHolesAtEnd(lgSize, result + 1, lgSizeUsed); + lgSizeUsed += 1; + } + + // Adjust the offset according to the location's offset before returning. + uint locationOffset = location.offset << (location.lgSize - lgSize); + return locationOffset + result; + } + + kj::Maybe tryAllocateByExpanding( + Group& group, Union::DataLocation& location, uint lgSize) { + // Attempt to allocate the given size by requesting that the parent union expand this + // location to fit. This is used if smallestHoleAtLeast() already determined that there + // are no holes that would fit, so we don't bother checking that. + + if (!isUsed) { + if (location.tryExpandTo(group.parent, lgSize)) { + isUsed = true; + lgSizeUsed = lgSize; + return location.offset << (location.lgSize - lgSize); + } else { + return nullptr; + } + } else { + uint newSize = kj::max(lgSizeUsed, lgSize) + 1; + if (tryExpandUsage(group, location, newSize, true)) { + uint result = KJ_ASSERT_NONNULL(holes.tryAllocate(lgSize)); + uint locationOffset = location.offset << (location.lgSize - lgSize); + return locationOffset + result; + } else { + return nullptr; + } + } + } + + bool tryExpand(Group& group, Union::DataLocation& location, + uint oldLgSize, uint oldOffset, uint expansionFactor) { + if (oldOffset == 0 && lgSizeUsed == oldLgSize) { + // This location contains exactly the requested data, so just expand the whole thing. + return tryExpandUsage(group, location, oldLgSize + expansionFactor, false); + } else { + // This location contains the requested data plus other stuff. Therefore the data cannot + // possibly expand past the end of the space we've already marked used without either + // overlapping with something else or breaking alignment rules. We only have to combine + // it with holes. + return holes.tryExpand(oldLgSize, oldOffset, expansionFactor); + } + } + + private: + bool isUsed; + // Whether or not this location has been used at all by the group. + + uint8_t lgSizeUsed; + // Amount of space from the location which is "used". This is the minimum size needed to + // cover all allocated space. Only meaningful if `isUsed` is true. + + HoleSet holes; + // Indicates holes present in the space designated by `lgSizeUsed`. The offsets in this + // HoleSet are relative to the beginning of this particular data location, not the beginning + // of the struct. + + bool tryExpandUsage(Group& group, Union::DataLocation& location, uint desiredUsage, + bool newHoles) { + if (desiredUsage > location.lgSize) { + // Need to expand the underlying slot. + if (!location.tryExpandTo(group.parent, desiredUsage)) { + return false; + } + } + + // Underlying slot is big enough, so expand our size and update holes. + if (newHoles) { + holes.addHolesAtEnd(lgSizeUsed, 1, desiredUsage); + } else if (shouldDetectIssue344()) { + // Unfortunately, Cap'n Proto 0.5.x and below would always call addHolesAtEnd(), which + // was the wrong thing to do when called from tryExpand(), which itself is only called + // in cases involving unions nested in other unions. The bug could lead to multiple + // fields in a group incorrectly being assigned overlapping offsets. Although the bug + // is now fixed by adding the `newHoles` parameter, this silently breaks + // backwards-compatibility with affected schemas. Therefore, for now, we throw an + // exception to alert developers of the problem. + // + // TODO(cleanup): Once sufficient time has elapsed, remove this assert. + KJ_FAIL_ASSERT("Bad news: Cap'n Proto 0.5.x and previous contained a bug which would cause this schema to be compiled incorrectly. Please see: https://github.com/capnproto/capnproto/issues/344"); + } + lgSizeUsed = desiredUsage; + return true; + } + }; + + Union& parent; + + kj::Vector parentDataLocationUsage; + // Vector corresponding to the parent union's `dataLocations`, indicating how much of each + // location has already been allocated. + + uint parentPointerLocationUsage = 0; + // Number of parent's pointer locations that have been used by this group. + + bool hasMembers = false; + + inline Group(Union& parent): parent(parent) {} + KJ_DISALLOW_COPY_AND_MOVE(Group); + + void addMember() { + if (!hasMembers) { + hasMembers = true; + parent.newGroupAddingFirstMember(); + } + } + + void addVoid() override { + addMember(); + + // Make sure that if this is a member of a union which is in turn a member of another union, + // that we let the outer union know that a field is being added, even though it is a + // zero-size field. This is important because the union needs to allocate its discriminant + // just before its second member is added. + parent.parent.addVoid(); + } + + uint addData(uint lgSize) override { + addMember(); + + uint bestSize = kj::maxValue; + kj::Maybe bestLocation = nullptr; + + for (uint i = 0; i < parent.dataLocations.size(); i++) { + // If we haven't seen this DataLocation yet, add a corresponding DataLocationUsage. + if (parentDataLocationUsage.size() == i) { + parentDataLocationUsage.add(); + } + + auto& usage = parentDataLocationUsage[i]; + KJ_IF_MAYBE(hole, usage.smallestHoleAtLeast(parent.dataLocations[i], lgSize)) { + if (*hole < bestSize) { + bestSize = *hole; + bestLocation = i; + } + } + } + + KJ_IF_MAYBE(best, bestLocation) { + return parentDataLocationUsage[*best].allocateFromHole( + *this, parent.dataLocations[*best], lgSize); + } + + // There are no holes at all in the union big enough to fit this field. Go back through all + // of the locations and attempt to expand them to fit. + for (uint i = 0; i < parent.dataLocations.size(); i++) { + KJ_IF_MAYBE(result, parentDataLocationUsage[i].tryAllocateByExpanding( + *this, parent.dataLocations[i], lgSize)) { + return *result; + } + } + + // Couldn't find any space in the existing locations, so add a new one. + uint result = parent.addNewDataLocation(lgSize); + parentDataLocationUsage.add(lgSize); + return result; + } + + uint addPointer() override { + addMember(); + + if (parentPointerLocationUsage < parent.pointerLocations.size()) { + return parent.pointerLocations[parentPointerLocationUsage++]; + } else { + parentPointerLocationUsage++; + return parent.addNewPointerLocation(); + } + } + + bool tryExpandData(uint oldLgSize, uint oldOffset, uint expansionFactor) override { + bool mustFail = false; + if (oldLgSize + expansionFactor > 6 || + (oldOffset & ((1 << expansionFactor) - 1)) != 0) { + // Expansion is not possible because the new size is too large or the offset is not + // properly-aligned. + + // Unfortunately, Cap'n Proto 0.5.x and prior forgot to "return false" here, instead + // continuing to execute the rest of the method. In most cases, the method failed later + // on, causing no harm. But, in cases where the method later succeeded, it probably + // led to bogus layouts. We cannot simply add the return statement now as this would + // silently break backwards-compatibility with affected schemas. Instead, we detect the + // problem and throw an exception. + // + // TODO(cleanup): Once sufficient time has elapsed, switch to "return false;" here. + if (shouldDetectIssue344()) { + mustFail = true; + } else { + return false; + } + } + + for (uint i = 0; i < parentDataLocationUsage.size(); i++) { + auto& location = parent.dataLocations[i]; + if (location.lgSize >= oldLgSize && + oldOffset >> (location.lgSize - oldLgSize) == location.offset) { + // The location we're trying to expand is a subset of this data location. + auto& usage = parentDataLocationUsage[i]; + + // Adjust the offset to be only within this location. + uint localOldOffset = oldOffset - (location.offset << (location.lgSize - oldLgSize)); + + // Try to expand. + bool result = usage.tryExpand( + *this, location, oldLgSize, localOldOffset, expansionFactor); + if (mustFail && result) { + KJ_FAIL_ASSERT("Bad news: Cap'n Proto 0.5.x and previous contained a bug which would cause this schema to be compiled incorrectly. Please see: https://github.com/capnproto/capnproto/issues/344"); + } + return result; + } + } + + KJ_FAIL_ASSERT("Tried to expand field that was never allocated."); + return false; + } + }; + + Top& getTop() { return top; } + +private: + Top top; +}; + +// ======================================================================================= + +NodeTranslator::NodeTranslator( + Resolver& resolver, ErrorReporter& errorReporter, + const Declaration::Reader& decl, Orphan wipNodeParam) + : resolver(resolver), errorReporter(errorReporter), + orphanage(Orphanage::getForMessageContaining(wipNodeParam.get())), + localBrand(kj::refcounted( + errorReporter, wipNodeParam.getReader().getId(), + decl.getParameters().size(), resolver)), + wipNode(kj::mv(wipNodeParam)) { + compileNode(decl, wipNode.get()); +} + +NodeTranslator::~NodeTranslator() noexcept(false) {} + +NodeTranslator::NodeSet NodeTranslator::getBootstrapNode() { + return NodeSet { + wipNode.getReader(), + KJ_MAP(g, groups) { return g.getReader(); } + }; +} + +NodeTranslator::NodeSet NodeTranslator::finish(Schema selfBootstrapSchema) { + // Careful about iteration here: compileFinalValue() may actually add more elements to + // `unfinishedValues`, invalidating iterators in the process. + for (size_t i = 0; i < unfinishedValues.size(); i++) { + auto& value = unfinishedValues[i]; + compileValue(value.source, value.type, value.typeScope.orDefault(selfBootstrapSchema), + value.target, false); + } + + return getBootstrapNode(); +} + +class NodeTranslator::DuplicateNameDetector { +public: + inline explicit DuplicateNameDetector(ErrorReporter& errorReporter) + : errorReporter(errorReporter) {} + void check(List::Reader nestedDecls, Declaration::Which parentKind); + +private: + ErrorReporter& errorReporter; + std::map names; +}; + +void NodeTranslator::compileNode(Declaration::Reader decl, schema::Node::Builder builder) { + DuplicateNameDetector(errorReporter) + .check(decl.getNestedDecls(), decl.which()); + + auto genericParams = decl.getParameters(); + if (genericParams.size() > 0) { + auto paramsBuilder = builder.initParameters(genericParams.size()); + for (auto i: kj::indices(genericParams)) { + paramsBuilder[i].setName(genericParams[i].getName()); + } + } + + builder.setIsGeneric(localBrand->isGeneric()); + + kj::StringPtr targetsFlagName; + + switch (decl.which()) { + case Declaration::FILE: + targetsFlagName = "targetsFile"; + break; + case Declaration::CONST: + compileConst(decl.getConst(), builder.initConst()); + targetsFlagName = "targetsConst"; + break; + case Declaration::ANNOTATION: + compileAnnotation(decl.getAnnotation(), builder.initAnnotation()); + targetsFlagName = "targetsAnnotation"; + break; + case Declaration::ENUM: + compileEnum(decl.getEnum(), decl.getNestedDecls(), builder); + targetsFlagName = "targetsEnum"; + break; + case Declaration::STRUCT: + compileStruct(decl.getStruct(), decl.getNestedDecls(), builder); + targetsFlagName = "targetsStruct"; + break; + case Declaration::INTERFACE: + errorReporter.addErrorOn(decl, "Interfaces are not supported."); + return; + + default: + KJ_FAIL_REQUIRE("This Declaration is not a node."); + break; + } + + if (decl.which() != Declaration::ANNOTATION) { + builder.setStartByte(decl.getStartByte()); + builder.setEndByte(decl.getEndByte()); + } + + builder.adoptAnnotations(compileAnnotationApplications(decl.getAnnotations(), targetsFlagName)); + + +} + +static kj::StringPtr getExpressionTargetName(Expression::Reader exp) { + switch (exp.which()) { + case Expression::ABSOLUTE_NAME: + return exp.getAbsoluteName().getValue(); + case Expression::RELATIVE_NAME: + return exp.getRelativeName().getValue(); + case Expression::APPLICATION: + return getExpressionTargetName(exp.getApplication().getFunction()); + case Expression::MEMBER: + return exp.getMember().getName().getValue(); + default: + return nullptr; + } +} + +void NodeTranslator::DuplicateNameDetector::check( + List::Reader nestedDecls, Declaration::Which parentKind) { + for (auto decl: nestedDecls) { + { + auto name = decl.getName(); + auto nameText = name.getValue(); + auto insertResult = names.insert(std::make_pair(nameText, name)); + if (!insertResult.second) { + if (nameText.size() == 0 && decl.isUnion()) { + errorReporter.addErrorOn( + name, kj::str("An unnamed union is already defined in this scope.")); + errorReporter.addErrorOn( + insertResult.first->second, kj::str("Previously defined here.")); + } else { + errorReporter.addErrorOn( + name, kj::str("'", nameText, "' is already defined in this scope.")); + errorReporter.addErrorOn( + insertResult.first->second, kj::str("'", nameText, "' previously defined here.")); + } + } + + switch (decl.which()) { + case Declaration::USING: { + kj::StringPtr targetName = getExpressionTargetName(decl.getUsing().getTarget()); + if (targetName.size() > 0 && targetName[0] >= 'a' && targetName[0] <= 'z') { + // Target starts with lower-case letter, so alias should too. + if (nameText.size() > 0 && (nameText[0] < 'a' || nameText[0] > 'z')) { + errorReporter.addErrorOn(name, + "Non-type names must begin with a lower-case letter."); + } + } else { + // Target starts with capital or is not named (probably, an import). Require + // capitalization. + if (nameText.size() > 0 && (nameText[0] < 'A' || nameText[0] > 'Z')) { + errorReporter.addErrorOn(name, + "Type names must begin with a capital letter."); + } + } + break; + } + + case Declaration::ENUM: + case Declaration::STRUCT: + case Declaration::INTERFACE: + if (nameText.size() > 0 && (nameText[0] < 'A' || nameText[0] > 'Z')) { + errorReporter.addErrorOn(name, + "Type names must begin with a capital letter."); + } + break; + + case Declaration::CONST: + case Declaration::ANNOTATION: + case Declaration::ENUMERANT: + case Declaration::METHOD: + case Declaration::FIELD: + case Declaration::UNION: + case Declaration::GROUP: + if (nameText.size() > 0 && (nameText[0] < 'a' || nameText[0] > 'z')) { + errorReporter.addErrorOn(name, + "Non-type names must begin with a lower-case letter."); + } + break; + + default: + KJ_ASSERT(nameText.size() == 0, "Don't know what naming rules to enforce for node type.", + (uint)decl.which()); + break; + } + + if (nameText.findFirst('_') != nullptr) { + errorReporter.addErrorOn(name, + "Cap'n Proto declaration names should use camelCase and must not contain " + "underscores. (Code generators may convert names to the appropriate style for the " + "target language.)"); + } + } + + switch (decl.which()) { + case Declaration::USING: + case Declaration::CONST: + case Declaration::ENUM: + case Declaration::STRUCT: + case Declaration::INTERFACE: + case Declaration::ANNOTATION: + switch (parentKind) { + case Declaration::FILE: + case Declaration::STRUCT: + case Declaration::INTERFACE: + // OK. + break; + default: + errorReporter.addErrorOn(decl, "This kind of declaration doesn't belong here."); + break; + } + break; + + case Declaration::ENUMERANT: + if (parentKind != Declaration::ENUM) { + errorReporter.addErrorOn(decl, "Enumerants can only appear in enums."); + } + break; + case Declaration::METHOD: + if (parentKind != Declaration::INTERFACE) { + errorReporter.addErrorOn(decl, "Methods can only appear in interfaces."); + } + break; + case Declaration::FIELD: + case Declaration::UNION: + case Declaration::GROUP: + switch (parentKind) { + case Declaration::STRUCT: + case Declaration::UNION: + case Declaration::GROUP: + // OK. + break; + default: + errorReporter.addErrorOn(decl, "This declaration can only appear in structs."); + break; + } + + // Struct members may have nested decls. We need to check those here, because no one else + // is going to do it. + if (decl.getName().getValue().size() == 0) { + // Unnamed union. Check members as if they are in the same scope. + check(decl.getNestedDecls(), decl.which()); + } else { + // Children are in their own scope. + DuplicateNameDetector(errorReporter) + .check(decl.getNestedDecls(), decl.which()); + } + + break; + + default: + errorReporter.addErrorOn(decl, "This kind of declaration doesn't belong here."); + break; + } + } +} + +void NodeTranslator::compileConst(Declaration::Const::Reader decl, + schema::Node::Const::Builder builder) { + auto typeBuilder = builder.initType(); + if (compileType(decl.getType(), typeBuilder)) { + compileBootstrapValue(decl.getValue(), typeBuilder.asReader(), builder.initValue()); + } +} + +void NodeTranslator::compileAnnotation(Declaration::Annotation::Reader decl, + schema::Node::Annotation::Builder builder) { + compileType(decl.getType(), builder.initType()); + + // Dynamically copy over the values of all of the "targets" members. + DynamicStruct::Reader src = decl; + DynamicStruct::Builder dst = builder; + for (auto srcField: src.getSchema().getFields()) { + kj::StringPtr fieldName = srcField.getProto().getName(); + if (fieldName.startsWith("targets")) { + auto dstField = dst.getSchema().getFieldByName(fieldName); + dst.set(dstField, src.get(srcField)); + } + } +} + +class NodeTranslator::DuplicateOrdinalDetector { +public: + DuplicateOrdinalDetector(ErrorReporter& errorReporter): errorReporter(errorReporter) {} + + void check(LocatedInteger::Reader ordinal) { + if (ordinal.getValue() < expectedOrdinal) { + errorReporter.addErrorOn(ordinal, "Duplicate ordinal number."); + KJ_IF_MAYBE(last, lastOrdinalLocation) { + errorReporter.addErrorOn( + *last, kj::str("Ordinal @", last->getValue(), " originally used here.")); + // Don't report original again. + lastOrdinalLocation = nullptr; + } + } else if (ordinal.getValue() > expectedOrdinal) { + errorReporter.addErrorOn(ordinal, + kj::str("Skipped ordinal @", expectedOrdinal, ". Ordinals must be sequential with no " + "holes.")); + expectedOrdinal = ordinal.getValue() + 1; + } else { + ++expectedOrdinal; + lastOrdinalLocation = ordinal; + } + } + +private: + ErrorReporter& errorReporter; + uint expectedOrdinal = 0; + kj::Maybe lastOrdinalLocation; +}; + +void NodeTranslator::compileEnum(Void decl, + List::Reader members, + schema::Node::Builder builder) { + // maps ordinal -> (code order, declaration) + std::multimap> enumerants; + + uint codeOrder = 0; + for (auto member: members) { + if (member.isEnumerant()) { + enumerants.insert( + std::make_pair(member.getId().getOrdinal().getValue(), + std::make_pair(codeOrder++, member))); + } + } + + auto list = builder.initEnum().initEnumerants(enumerants.size()); + uint i = 0; + DuplicateOrdinalDetector dupDetector(errorReporter); + + for (auto& entry: enumerants) { + uint codeOrder = entry.second.first; + Declaration::Reader enumerantDecl = entry.second.second; + + dupDetector.check(enumerantDecl.getId().getOrdinal()); + + + auto enumerantBuilder = list[i++]; + enumerantBuilder.setName(enumerantDecl.getName().getValue()); + enumerantBuilder.setCodeOrder(codeOrder); + enumerantBuilder.adoptAnnotations(compileAnnotationApplications( + enumerantDecl.getAnnotations(), "targetsEnumerant")); + } +} + +// ------------------------------------------------------------------- + +class NodeTranslator::StructTranslator { +public: + explicit StructTranslator(NodeTranslator& translator) + : translator(translator), errorReporter(translator.errorReporter) {} + KJ_DISALLOW_COPY_AND_MOVE(StructTranslator); + + void translate(Void decl, List::Reader members, schema::Node::Builder builder) { + // Build the member-info-by-ordinal map. + MemberInfo root(builder); + traverseTopOrGroup(members, root, layout.getTop()); + translateInternal(root, builder); + } + +private: + NodeTranslator& translator; + ErrorReporter& errorReporter; + StructLayout layout; + kj::Arena arena; + + struct MemberInfo { + MemberInfo* parent; + // The MemberInfo for the parent scope. + + uint codeOrder; + // Code order within the parent. + + uint index = 0; + // Index within the parent. + + uint childCount = 0; + // Number of children this member has. + + uint childInitializedCount = 0; + // Number of children whose `schema` member has been initialized. This initialization happens + // while walking the fields in ordinal order. + + uint unionDiscriminantCount = 0; + // Number of children who are members of the scope's union and have had their discriminant + // value decided. + + bool isInUnion; + // Whether or not this field is in the parent's union. + + kj::StringPtr name; + Declaration::Id::Reader declId; + Declaration::Which declKind; + bool hasDefaultValue = false; // if declKind == FIELD + Expression::Reader fieldType; // if declKind == FIELD + Expression::Reader fieldDefaultValue; // if declKind == FIELD && hasDefaultValue + List::Reader declAnnotations; + uint startByte = 0; + uint endByte = 0; + // Information about the field declaration. + + kj::Maybe schema; + // Schema for the field. Initialized when getSchema() is first called. + + schema::Node::Builder node; + // If it's a group, or the top-level struct. + + union { + StructLayout::StructOrGroup* fieldScope; + // If this member is a field, the scope of that field. This will be used to assign an + // offset for the field when going through in ordinal order. + + StructLayout::Union* unionScope; + // If this member is a union, or it is a group or top-level struct containing an unnamed + // union, this is the union. This will be used to assign a discriminant offset when the + // union's ordinal comes up (if the union has an explicit ordinal), as well as to finally + // copy over the discriminant offset to the schema. + }; + + inline explicit MemberInfo(schema::Node::Builder node) + : parent(nullptr), codeOrder(0), isInUnion(false), node(node), + unionScope(nullptr) {} + inline MemberInfo(MemberInfo& parent, uint codeOrder, + const Declaration::Reader& decl, + StructLayout::StructOrGroup& fieldScope, + bool isInUnion) + : parent(&parent), codeOrder(codeOrder), isInUnion(isInUnion), + name(decl.getName().getValue()), declId(decl.getId()), declKind(Declaration::FIELD), + declAnnotations(decl.getAnnotations()), + startByte(decl.getStartByte()), endByte(decl.getEndByte()), + node(nullptr), fieldScope(&fieldScope) { + KJ_REQUIRE(decl.which() == Declaration::FIELD); + auto fieldDecl = decl.getField(); + fieldType = fieldDecl.getType(); + if (fieldDecl.getDefaultValue().isValue()) { + hasDefaultValue = true; + fieldDefaultValue = fieldDecl.getDefaultValue().getValue(); + } + } + inline MemberInfo(MemberInfo& parent, uint codeOrder, + const Declaration::Reader& decl, + schema::Node::Builder nodeBuilder, + bool isInUnion) + : parent(&parent), codeOrder(codeOrder), isInUnion(isInUnion), + name(decl.getName().getValue()), declId(decl.getId()), declKind(decl.which()), + declAnnotations(decl.getAnnotations()), + startByte(decl.getStartByte()), endByte(decl.getEndByte()), + node(nodeBuilder), unionScope(nullptr) { + KJ_REQUIRE(decl.which() != Declaration::FIELD); + } + + schema::Field::Builder getSchema() { + KJ_IF_MAYBE(result, schema) { + return *result; + } else { + index = parent->childInitializedCount; + auto builder = parent->addMemberSchema(); + if (isInUnion) { + builder.setDiscriminantValue(parent->unionDiscriminantCount++); + } + builder.setName(name); + builder.setCodeOrder(codeOrder); + + + schema = builder; + return builder; + } + } + + schema::Field::Builder addMemberSchema() { + // Get the schema builder for the child member at the given index. This lazily/dynamically + // builds the builder tree. + + KJ_REQUIRE(childInitializedCount < childCount); + + auto structNode = node.getStruct(); + if (!structNode.hasFields()) { + if (parent != nullptr) { + getSchema(); // Make sure field exists in parent once the first child is added. + } + auto result = structNode.initFields(childCount)[childInitializedCount]; + ++childInitializedCount; + return result; + } else { + auto result = structNode.getFields()[childInitializedCount]; + ++childInitializedCount; + return result; + } + } + + void finishGroup() { + if (unionScope != nullptr) { + unionScope->addDiscriminant(); // if it hasn't happened already + auto structNode = node.getStruct(); + structNode.setDiscriminantCount(unionDiscriminantCount); + structNode.setDiscriminantOffset(KJ_ASSERT_NONNULL(unionScope->discriminantOffset)); + } + + if (parent != nullptr) { + uint64_t groupId = generateGroupId(parent->node.getId(), index); + node.setId(groupId); + node.setScopeId(parent->node.getId()); + getSchema().initGroup().setTypeId(groupId); + + } + } + }; + + std::multimap membersByOrdinal; + // Every member that has an explicit ordinal goes into this map. We then iterate over the map + // to assign field offsets (or discriminant offsets for unions). + + kj::Vector allMembers; + // All members, including ones that don't have ordinals. + + void traverseUnion(const Declaration::Reader& decl, + List::Reader members, MemberInfo& parent, + StructLayout::Union& layout, uint& codeOrder) { + if (members.size() < 2) { + errorReporter.addErrorOn(decl, "Union must have at least two members."); + } + + for (auto member: members) { + kj::Maybe ordinal; + MemberInfo* memberInfo = nullptr; + + switch (member.which()) { + case Declaration::FIELD: { + parent.childCount++; + // For layout purposes, pretend this field is enclosed in a one-member group. + StructLayout::Group& singletonGroup = + arena.allocate(layout); + memberInfo = &arena.allocate(parent, codeOrder++, member, singletonGroup, + true); + allMembers.add(memberInfo); + ordinal = member.getId().getOrdinal().getValue(); + break; + } + + case Declaration::UNION: + if (member.getName().getValue() == "") { + errorReporter.addErrorOn(member, "Unions cannot contain unnamed unions."); + } else { + parent.childCount++; + + // For layout purposes, pretend this union is enclosed in a one-member group. + StructLayout::Group& singletonGroup = + arena.allocate(layout); + StructLayout::Union& unionLayout = arena.allocate(singletonGroup); + + memberInfo = &arena.allocate( + parent, codeOrder++, member, + newGroupNode(parent.node, member.getName().getValue()), + true); + allMembers.add(memberInfo); + memberInfo->unionScope = &unionLayout; + uint subCodeOrder = 0; + traverseUnion(member, member.getNestedDecls(), *memberInfo, unionLayout, subCodeOrder); + if (member.getId().isOrdinal()) { + ordinal = member.getId().getOrdinal().getValue(); + } + } + break; + + case Declaration::GROUP: { + parent.childCount++; + StructLayout::Group& group = arena.allocate(layout); + memberInfo = &arena.allocate( + parent, codeOrder++, member, + newGroupNode(parent.node, member.getName().getValue()), + true); + allMembers.add(memberInfo); + traverseGroup(member.getNestedDecls(), *memberInfo, group); + break; + } + + default: + // Ignore others. + break; + } + + KJ_IF_MAYBE(o, ordinal) { + membersByOrdinal.insert(std::make_pair(*o, memberInfo)); + } + } + } + + void traverseGroup(List::Reader members, MemberInfo& parent, + StructLayout::StructOrGroup& layout) { + if (members.size() < 1) { + errorReporter.addError(parent.startByte, parent.endByte, + "Group must have at least one member."); + } + + traverseTopOrGroup(members, parent, layout); + } + + void traverseTopOrGroup(List::Reader members, MemberInfo& parent, + StructLayout::StructOrGroup& layout) { + uint codeOrder = 0; + + for (auto member: members) { + kj::Maybe ordinal; + MemberInfo* memberInfo = nullptr; + + switch (member.which()) { + case Declaration::FIELD: { + parent.childCount++; + memberInfo = &arena.allocate( + parent, codeOrder++, member, layout, false); + allMembers.add(memberInfo); + ordinal = member.getId().getOrdinal().getValue(); + break; + } + + case Declaration::UNION: { + StructLayout::Union& unionLayout = arena.allocate(layout); + + uint independentSubCodeOrder = 0; + uint* subCodeOrder = &independentSubCodeOrder; + if (member.getName().getValue() == "") { + memberInfo = &parent; + subCodeOrder = &codeOrder; + } else { + parent.childCount++; + memberInfo = &arena.allocate( + parent, codeOrder++, member, + newGroupNode(parent.node, member.getName().getValue()), + false); + allMembers.add(memberInfo); + } + memberInfo->unionScope = &unionLayout; + traverseUnion(member, member.getNestedDecls(), *memberInfo, unionLayout, *subCodeOrder); + if (member.getId().isOrdinal()) { + ordinal = member.getId().getOrdinal().getValue(); + } + break; + } + + case Declaration::GROUP: + parent.childCount++; + memberInfo = &arena.allocate( + parent, codeOrder++, member, + newGroupNode(parent.node, member.getName().getValue()), + false); + allMembers.add(memberInfo); + + // Members of the group are laid out just like they were members of the parent, so we + // just pass along the parent layout. + traverseGroup(member.getNestedDecls(), *memberInfo, layout); + + // No ordinal for groups. + break; + + default: + // Ignore others. + break; + } + + KJ_IF_MAYBE(o, ordinal) { + membersByOrdinal.insert(std::make_pair(*o, memberInfo)); + } + } + } + + schema::Node::Builder newGroupNode(schema::Node::Reader parent, kj::StringPtr name) { + auto aux = translator.orphanage.newOrphan(); + auto node = aux.get(); + + // We'll set the ID and scope ID later. + node.setDisplayName(kj::str(parent.getDisplayName(), '.', name)); + node.setDisplayNamePrefixLength(node.getDisplayName().size() - name.size()); + node.setIsGeneric(parent.getIsGeneric()); + node.initStruct().setIsGroup(true); + + // The remaining contents of node.struct will be filled in later. + + translator.groups.add(kj::mv(aux)); + return node; + } + + void translateInternal(MemberInfo& root, schema::Node::Builder builder) { + auto structBuilder = builder.initStruct(); + + // Go through each member in ordinal order, building each member schema. + DuplicateOrdinalDetector dupDetector(errorReporter); + for (auto& entry: membersByOrdinal) { + MemberInfo& member = *entry.second; + + // Make sure the exceptions added relating to + // https://github.com/capnproto/capnproto/issues/344 identify the affected field. + KJ_CONTEXT(member.name); + + if (member.declId.isOrdinal()) { + dupDetector.check(member.declId.getOrdinal()); + } + + schema::Field::Builder fieldBuilder = member.getSchema(); + fieldBuilder.getOrdinal().setExplicit(entry.first); + + switch (member.declKind) { + case Declaration::FIELD: { + auto slot = fieldBuilder.initSlot(); + auto typeBuilder = slot.initType(); + if (translator.compileType(member.fieldType, typeBuilder)) { + if (member.hasDefaultValue) { + translator.compileBootstrapValue(member.fieldDefaultValue, + typeBuilder, slot.initDefaultValue()); + slot.setHadExplicitDefault(true); + } else { + translator.compileDefaultDefaultValue(typeBuilder, slot.initDefaultValue()); + } + } else { + translator.compileDefaultDefaultValue(typeBuilder, slot.initDefaultValue()); + } + + int lgSize = -1; + switch (typeBuilder.which()) { + case schema::Type::VOID: lgSize = -1; break; + case schema::Type::BOOL: lgSize = 0; break; + case schema::Type::INT8: lgSize = 3; break; + case schema::Type::INT16: lgSize = 4; break; + case schema::Type::INT32: lgSize = 5; break; + case schema::Type::INT64: lgSize = 6; break; + case schema::Type::UINT8: lgSize = 3; break; + case schema::Type::UINT16: lgSize = 4; break; + case schema::Type::UINT32: lgSize = 5; break; + case schema::Type::UINT64: lgSize = 6; break; + case schema::Type::FLOAT32: lgSize = 5; break; + case schema::Type::FLOAT64: lgSize = 6; break; + + case schema::Type::TEXT: lgSize = -2; break; + case schema::Type::DATA: lgSize = -2; break; + case schema::Type::LIST: lgSize = -2; break; + case schema::Type::ENUM: lgSize = 4; break; + case schema::Type::STRUCT: lgSize = -2; break; + case schema::Type::INTERFACE: lgSize = -2; break; + case schema::Type::ANY_POINTER: lgSize = -2; break; + } + + if (lgSize == -2) { + // pointer + slot.setOffset(member.fieldScope->addPointer()); + } else if (lgSize == -1) { + // void + member.fieldScope->addVoid(); + slot.setOffset(0); + } else { + slot.setOffset(member.fieldScope->addData(lgSize)); + } + break; + } + + case Declaration::UNION: + if (!member.unionScope->addDiscriminant()) { + errorReporter.addErrorOn(member.declId.getOrdinal(), + "Union ordinal, if specified, must be greater than no more than one of its " + "member ordinals (i.e. there can only be one field retroactively unionized)."); + } + break; + + case Declaration::GROUP: + KJ_FAIL_ASSERT("Groups don't have ordinals."); + break; + + default: + KJ_FAIL_ASSERT("Unexpected member type."); + break; + } + } + + // OK, we should have built all the members. Now go through and make sure the discriminant + // offsets have been copied over to the schemas and annotations have been applied. + root.finishGroup(); + for (auto member: allMembers) { + kj::StringPtr targetsFlagName; + switch (member->declKind) { + case Declaration::FIELD: + targetsFlagName = "targetsField"; + break; + + case Declaration::UNION: + member->finishGroup(); + targetsFlagName = "targetsUnion"; + break; + + case Declaration::GROUP: + member->finishGroup(); + targetsFlagName = "targetsGroup"; + break; + + default: + KJ_FAIL_ASSERT("Unexpected member type."); + break; + } + + member->getSchema().adoptAnnotations(translator.compileAnnotationApplications( + member->declAnnotations, targetsFlagName)); + } + + // And fill in the sizes. + structBuilder.setDataWordCount(layout.getTop().dataWordCount); + structBuilder.setPointerCount(layout.getTop().pointerCount); + structBuilder.setPreferredListEncoding(schema::ElementSize::INLINE_COMPOSITE); + + for (auto& group: translator.groups) { + auto groupBuilder = group.get().getStruct(); + groupBuilder.setDataWordCount(structBuilder.getDataWordCount()); + groupBuilder.setPointerCount(structBuilder.getPointerCount()); + groupBuilder.setPreferredListEncoding(structBuilder.getPreferredListEncoding()); + } + } +}; + +void NodeTranslator::compileStruct(Void decl, List::Reader members, + schema::Node::Builder builder) { + StructTranslator(*this) + .translate(decl, members, builder); +} + +// ------------------------------------------------------------------- + +kj::Maybe +NodeTranslator::compileDeclExpression( + Expression::Reader source) { + return localBrand->compileDeclExpression(source, resolver); +} + +/* static */ kj::Maybe NodeTranslator::compileDecl( + uint64_t scopeId, uint scopeParameterCount, Resolver& resolver, ErrorReporter& errorReporter, + Expression::Reader expression, schema::Brand::Builder brandBuilder) { + auto scope = kj::refcounted(errorReporter, scopeId, scopeParameterCount, resolver); + KJ_IF_MAYBE(decl, scope->compileDeclExpression(expression, resolver)) { + return decl->asResolveResult(scope->getScopeId(), brandBuilder); + } else { + return nullptr; + } +} + +bool NodeTranslator::compileType(Expression::Reader source, schema::Type::Builder target) { + KJ_IF_MAYBE(decl, compileDeclExpression(source)) { + return decl->compileAsType(errorReporter, target); + } else { + return false; + } +} + +// ------------------------------------------------------------------- + +void NodeTranslator::compileDefaultDefaultValue( + schema::Type::Reader type, schema::Value::Builder target) { + switch (type.which()) { + case schema::Type::VOID: target.setVoid(); break; + case schema::Type::BOOL: target.setBool(false); break; + case schema::Type::INT8: target.setInt8(0); break; + case schema::Type::INT16: target.setInt16(0); break; + case schema::Type::INT32: target.setInt32(0); break; + case schema::Type::INT64: target.setInt64(0); break; + case schema::Type::UINT8: target.setUint8(0); break; + case schema::Type::UINT16: target.setUint16(0); break; + case schema::Type::UINT32: target.setUint32(0); break; + case schema::Type::UINT64: target.setUint64(0); break; + case schema::Type::FLOAT32: target.setFloat32(0); break; + case schema::Type::FLOAT64: target.setFloat64(0); break; + case schema::Type::ENUM: target.setEnum(0); break; + case schema::Type::INTERFACE: target.setInterface(); break; + + // Bit of a hack: For Text/Data, we adopt a null orphan, which sets the field to null. + // TODO(cleanup): Create a cleaner way to do this. + case schema::Type::TEXT: target.adoptText(Orphan()); break; + case schema::Type::DATA: target.adoptData(Orphan()); break; + case schema::Type::STRUCT: target.initStruct(); break; + case schema::Type::LIST: target.initList(); break; + case schema::Type::ANY_POINTER: target.initAnyPointer(); break; + } +} + +void NodeTranslator::compileBootstrapValue( + Expression::Reader source, schema::Type::Reader type, schema::Value::Builder target, + kj::Maybe typeScope) { + // Start by filling in a default default value so that if for whatever reason we don't end up + // initializing the value, this won't cause schema validation to fail. + compileDefaultDefaultValue(type, target); + + switch (type.which()) { + case schema::Type::LIST: + case schema::Type::STRUCT: + case schema::Type::INTERFACE: + case schema::Type::ANY_POINTER: + unfinishedValues.add(UnfinishedValue { source, type, typeScope, target }); + break; + + default: + // Primitive value. (Note that the scope can't possibly matter since primitives are not + // generic.) + compileValue(source, type, typeScope.orDefault(Schema()), target, true); + break; + } +} + +void NodeTranslator::compileValue(Expression::Reader source, schema::Type::Reader type, + Schema typeScope, schema::Value::Builder target, + bool isBootstrap) { + class ResolverGlue: public ValueTranslator::Resolver { + public: + inline ResolverGlue(NodeTranslator& translator, bool isBootstrap) + : translator(translator), isBootstrap(isBootstrap) {} + + kj::Maybe resolveConstant(Expression::Reader name) override { + return translator.readConstant(name, isBootstrap); + } + + kj::Maybe> readEmbed(LocatedText::Reader filename) override { + return translator.readEmbed(filename); + } + + private: + NodeTranslator& translator; + bool isBootstrap; + }; + + ResolverGlue glue(*this, isBootstrap); + ValueTranslator valueTranslator(glue, errorReporter, orphanage); + + KJ_IF_MAYBE(typeSchema, resolver.resolveBootstrapType(type, typeScope)) { + kj::StringPtr fieldName = Schema::from() + .getUnionFields()[static_cast(typeSchema->which())].getProto().getName(); + + KJ_IF_MAYBE(value, valueTranslator.compileValue(source, *typeSchema)) { + if (typeSchema->isEnum()) { + target.setEnum(value->getReader().as().getRaw()); + } else { + toDynamic(target).adopt(fieldName, kj::mv(*value)); + } + } + } +} + +kj::Maybe> ValueTranslator::compileValue(Expression::Reader src, Type type) { + if (type.isAnyPointer()) { + if (type.getBrandParameter() != nullptr || type.getImplicitParameter() != nullptr) { + errorReporter.addErrorOn(src, + "Cannot interpret value because the type is a generic type parameter which is not " + "yet bound. We don't know what type to expect here."); + return nullptr; + } + } + + Orphan result = compileValueInner(src, type); + + if (result.getType() == DynamicValue::UNKNOWN) { + // Error already reported. + return nullptr; + } else if (matchesType(src, type, result)) { + return kj::mv(result); + } else { + // If the expected type is a struct, we try matching its first field. + if (type.isStruct()) { + auto structType = type.asStruct(); + auto fields = structType.getFields(); + if (fields.size() > 0) { + auto field = fields[0]; + if (matchesType(src, field.getType(), result)) { + // Success. Wrap in a struct. + auto outer = orphanage.newOrphan(type.asStruct()); + outer.get().adopt(field, kj::mv(result)); + return Orphan(kj::mv(outer)); + } + } + } + + // That didn't work, so this is just a type mismatch. + errorReporter.addErrorOn(src, kj::str("Type mismatch; expected ", makeTypeName(type), ".")); + return nullptr; + } +} + +bool ValueTranslator::matchesType(Expression::Reader src, Type type, Orphan& result) { + // compileValueInner() evaluated `src` and only used `type` as a hint in interpreting `src` if + // `src`'s type wasn't already obvious. So, now we need to check that the resulting value + // actually matches `type`. + + switch (result.getType()) { + case DynamicValue::UNKNOWN: + KJ_UNREACHABLE; + + case DynamicValue::VOID: + return type.isVoid(); + + case DynamicValue::BOOL: + return type.isBool(); + + case DynamicValue::INT: { + int64_t value = result.getReader().as(); + if (value < 0) { + int64_t minValue; + switch (type.which()) { + case schema::Type::INT8: minValue = (int8_t)kj::minValue; break; + case schema::Type::INT16: minValue = (int16_t)kj::minValue; break; + case schema::Type::INT32: minValue = (int32_t)kj::minValue; break; + case schema::Type::INT64: minValue = (int64_t)kj::minValue; break; + case schema::Type::UINT8: minValue = (uint8_t)kj::minValue; break; + case schema::Type::UINT16: minValue = (uint16_t)kj::minValue; break; + case schema::Type::UINT32: minValue = (uint32_t)kj::minValue; break; + case schema::Type::UINT64: minValue = (uint64_t)kj::minValue; break; + + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + // Any integer is acceptable. + minValue = (int64_t)kj::minValue; + break; + + default: return false; + } + + if (value < minValue) { + errorReporter.addErrorOn(src, "Integer value out of range."); + result = minValue; + } + return true; + } + + } KJ_FALLTHROUGH; // value is positive, so we can just go on to the uint case below. + + case DynamicValue::UINT: { + uint64_t maxValue; + switch (type.which()) { + case schema::Type::INT8: maxValue = (int8_t)kj::maxValue; break; + case schema::Type::INT16: maxValue = (int16_t)kj::maxValue; break; + case schema::Type::INT32: maxValue = (int32_t)kj::maxValue; break; + case schema::Type::INT64: maxValue = (int64_t)kj::maxValue; break; + case schema::Type::UINT8: maxValue = (uint8_t)kj::maxValue; break; + case schema::Type::UINT16: maxValue = (uint16_t)kj::maxValue; break; + case schema::Type::UINT32: maxValue = (uint32_t)kj::maxValue; break; + case schema::Type::UINT64: maxValue = (uint64_t)kj::maxValue; break; + + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + // Any integer is acceptable. + maxValue = (uint64_t)kj::maxValue; + break; + + default: return false; + } + + if (result.getReader().as() > maxValue) { + errorReporter.addErrorOn(src, "Integer value out of range."); + result = maxValue; + } + return true; + } + + case DynamicValue::FLOAT: + return type.isFloat32() || type.isFloat64(); + + case DynamicValue::TEXT: + return type.isText(); + + case DynamicValue::DATA: + return type.isData(); + + case DynamicValue::LIST: + if (type.isList()) { + return result.getReader().as().getSchema() == type.asList(); + } else if (type.isAnyPointer()) { + switch (type.whichAnyPointerKind()) { + case schema::Type::AnyPointer::Unconstrained::ANY_KIND: + case schema::Type::AnyPointer::Unconstrained::LIST: + return true; + case schema::Type::AnyPointer::Unconstrained::STRUCT: + case schema::Type::AnyPointer::Unconstrained::CAPABILITY: + return false; + } + KJ_UNREACHABLE; + } else { + return false; + } + + case DynamicValue::ENUM: + return type.isEnum() && + result.getReader().as().getSchema() == type.asEnum(); + + case DynamicValue::STRUCT: + if (type.isStruct()) { + return result.getReader().as().getSchema() == type.asStruct(); + } else if (type.isAnyPointer()) { + switch (type.whichAnyPointerKind()) { + case schema::Type::AnyPointer::Unconstrained::ANY_KIND: + case schema::Type::AnyPointer::Unconstrained::STRUCT: + return true; + case schema::Type::AnyPointer::Unconstrained::LIST: + case schema::Type::AnyPointer::Unconstrained::CAPABILITY: + return false; + } + KJ_UNREACHABLE; + } else { + return false; + } + + case DynamicValue::ANY_POINTER: + KJ_FAIL_ASSERT("AnyPointers can't have literal values."); + } + + KJ_UNREACHABLE; +} + +Orphan ValueTranslator::compileValueInner(Expression::Reader src, Type type) { + switch (src.which()) { + case Expression::RELATIVE_NAME: { + auto name = src.getRelativeName(); + + // The name is just a bare identifier. It may be a literal value or an enumerant. + kj::StringPtr id = name.getValue(); + + if (type.isEnum()) { + KJ_IF_MAYBE(enumerant, type.asEnum().findEnumerantByName(id)) { + return DynamicEnum(*enumerant); + } + } else { + // Interpret known constant values. + if (id == "void") { + return VOID; + } else if (id == "true") { + return true; + } else if (id == "false") { + return false; + } else if (id == "nan") { + return kj::nan(); + } else if (id == "inf") { + return kj::inf(); + } + } + + // Apparently not a literal. Try resolving it. + KJ_IF_MAYBE(constValue, resolver.resolveConstant(src)) { + return orphanage.newOrphanCopy(*constValue); + } else { + return nullptr; + } + } + + case Expression::ABSOLUTE_NAME: + case Expression::IMPORT: + case Expression::APPLICATION: + case Expression::MEMBER: + KJ_IF_MAYBE(constValue, resolver.resolveConstant(src)) { + return orphanage.newOrphanCopy(*constValue); + } else { + return nullptr; + } + + case Expression::EMBED: + KJ_IF_MAYBE(data, resolver.readEmbed(src.getEmbed())) { + switch (type.which()) { + case schema::Type::TEXT: { + // Sadly, we need to make a copy to add the NUL terminator. + auto text = orphanage.newOrphan(data->size()); + memcpy(text.get().begin(), data->begin(), data->size()); + return kj::mv(text); + } + case schema::Type::DATA: + return orphanage.newOrphanCopy(Data::Reader(*data)); + case schema::Type::STRUCT: { + // We will almost certainly + if (data->size() % sizeof(word) != 0) { + errorReporter.addErrorOn(src, + "Embedded file is not a valid Cap'n Proto message."); + return nullptr; + } + kj::Array copy; + kj::ArrayPtr words; + if (reinterpret_cast(data->begin()) % sizeof(void*) == 0) { + // Hooray, data is aligned. + words = kj::ArrayPtr( + reinterpret_cast(data->begin()), + data->size() / sizeof(word)); + } else { + // Ugh, data not aligned. Make a copy. + copy = kj::heapArray(data->size() / sizeof(word)); + memcpy(copy.begin(), data->begin(), data->size()); + words = copy; + } + ReaderOptions options; + options.traversalLimitInWords = kj::maxValue; + options.nestingLimit = kj::maxValue; + FlatArrayMessageReader reader(words, options); + return orphanage.newOrphanCopy(reader.getRoot(type.asStruct())); + } + default: + errorReporter.addErrorOn(src, + "Embeds can only be used when Text, Data, or a struct is expected."); + return nullptr; + } + } else { + return nullptr; + } + + case Expression::POSITIVE_INT: + return src.getPositiveInt(); + + case Expression::NEGATIVE_INT: { + uint64_t nValue = src.getNegativeInt(); + if (nValue > ((uint64_t)kj::maxValue >> 1) + 1) { + errorReporter.addErrorOn(src, "Integer is too big to be negative."); + return nullptr; + } else { + return kj::implicitCast(-nValue); + } + } + + case Expression::FLOAT: + return src.getFloat(); + break; + + case Expression::STRING: + if (type.isData()) { + Text::Reader text = src.getString(); + return orphanage.newOrphanCopy(Data::Reader(text.asBytes())); + } else { + return orphanage.newOrphanCopy(src.getString()); + } + break; + + case Expression::BINARY: + if (!type.isData()) { + errorReporter.addErrorOn(src, kj::str("Type mismatch; expected ", makeTypeName(type), ".")); + return nullptr; + } + return orphanage.newOrphanCopy(src.getBinary()); + + case Expression::LIST: { + if (!type.isList()) { + errorReporter.addErrorOn(src, kj::str("Type mismatch; expected ", makeTypeName(type), ".")); + return nullptr; + } + auto listSchema = type.asList(); + Type elementType = listSchema.getElementType(); + auto srcList = src.getList(); + Orphan result = orphanage.newOrphan(listSchema, srcList.size()); + auto dstList = result.get(); + for (uint i = 0; i < srcList.size(); i++) { + KJ_IF_MAYBE(value, compileValue(srcList[i], elementType)) { + dstList.adopt(i, kj::mv(*value)); + } + } + return kj::mv(result); + } + + case Expression::TUPLE: { + if (!type.isStruct()) { + errorReporter.addErrorOn(src, kj::str("Type mismatch; expected ", makeTypeName(type), ".")); + return nullptr; + } + auto structSchema = type.asStruct(); + Orphan result = orphanage.newOrphan(structSchema); + fillStructValue(result.get(), src.getTuple()); + return kj::mv(result); + } + + case Expression::UNKNOWN: + // Ignore earlier error. + return nullptr; + } + + KJ_UNREACHABLE; +} + +void ValueTranslator::fillStructValue(DynamicStruct::Builder builder, + List::Reader assignments) { + for (auto assignment: assignments) { + if (assignment.isNamed()) { + auto fieldName = assignment.getNamed(); + KJ_IF_MAYBE(field, builder.getSchema().findFieldByName(fieldName.getValue())) { + auto fieldProto = field->getProto(); + auto value = assignment.getValue(); + + switch (fieldProto.which()) { + case schema::Field::SLOT: + KJ_IF_MAYBE(compiledValue, compileValue(value, field->getType())) { + builder.adopt(*field, kj::mv(*compiledValue)); + } + break; + + case schema::Field::GROUP: + auto groupBuilder = builder.init(*field).as(); + if (value.isTuple()) { + fillStructValue(groupBuilder, value.getTuple()); + } else { + auto groupFields = groupBuilder.getSchema().getFields(); + if (groupFields.size() > 0) { + auto groupField = groupFields[0]; + + // Call compileValueInner() using the group's type as `type`. Since we already + // established `value` is not a tuple, this will only return a valid result if + // the value has unambiguous type. + auto result = compileValueInner(value, field->getType()); + + if (result.getType() == DynamicValue::UNKNOWN) { + // Error already reported. + break; + } + + // Does it match the first field? + if (matchesType(value, groupField.getType(), result)) { + groupBuilder.adopt(groupField, kj::mv(result)); + break; + } + } + + errorReporter.addErrorOn(value, "Type mismatch; expected group."); + } + break; + } + } else { + errorReporter.addErrorOn(fieldName, kj::str( + "Struct has no field named '", fieldName.getValue(), "'.")); + } + } else { + errorReporter.addErrorOn(assignment.getValue(), kj::str("Missing field name.")); + } + } +} + +kj::String ValueTranslator::makeNodeName(Schema schema) { + schema::Node::Reader proto = schema.getProto(); + return kj::str(proto.getDisplayName().slice(proto.getDisplayNamePrefixLength())); +} + +kj::String ValueTranslator::makeTypeName(Type type) { + switch (type.which()) { + case schema::Type::VOID: return kj::str("Void"); + case schema::Type::BOOL: return kj::str("Bool"); + case schema::Type::INT8: return kj::str("Int8"); + case schema::Type::INT16: return kj::str("Int16"); + case schema::Type::INT32: return kj::str("Int32"); + case schema::Type::INT64: return kj::str("Int64"); + case schema::Type::UINT8: return kj::str("UInt8"); + case schema::Type::UINT16: return kj::str("UInt16"); + case schema::Type::UINT32: return kj::str("UInt32"); + case schema::Type::UINT64: return kj::str("UInt64"); + case schema::Type::FLOAT32: return kj::str("Float32"); + case schema::Type::FLOAT64: return kj::str("Float64"); + case schema::Type::TEXT: return kj::str("Text"); + case schema::Type::DATA: return kj::str("Data"); + case schema::Type::LIST: + return kj::str("List(", makeTypeName(type.asList().getElementType()), ")"); + case schema::Type::ENUM: return makeNodeName(type.asEnum()); + case schema::Type::STRUCT: return makeNodeName(type.asStruct()); + case schema::Type::INTERFACE: return kj::str("unsupported interface"); + case schema::Type::ANY_POINTER: return kj::str("AnyPointer"); + } + KJ_UNREACHABLE; +} + +kj::Maybe NodeTranslator::readConstant( + Expression::Reader source, bool isBootstrap) { + // Look up the constant decl. + BrandedDecl constDecl = nullptr; + KJ_IF_MAYBE(decl, compileDeclExpression(source)) { + constDecl = *decl; + } else { + // Lookup will have reported an error. + return nullptr; + } + + // Is it a constant? + if(constDecl.getKind().orDefault(Declaration::FILE) != Declaration::CONST) { + errorReporter.addErrorOn(source, + kj::str("'", expressionString(source), "' does not refer to a constant.")); + return nullptr; + } + + // Extract the ID and brand. + MallocMessageBuilder builder(256); + auto constBrand = builder.getRoot(); + uint64_t id = constDecl.getIdAndFillBrand([&]() { return constBrand; }); + + // Look up the schema -- we'll need this to compile the constant's type. + Schema constSchema; + KJ_IF_MAYBE(s, resolver.resolveBootstrapSchema(id, constBrand)) { + constSchema = *s; + } else { + // The constant's schema is broken for reasons already reported. + return nullptr; + } + + // If we're bootstrapping, then we know we're expecting a primitive value, so if the + // constant turns out to be non-primitive, we'll error out anyway. If we're not + // bootstrapping, we may be compiling a non-primitive value and so we need the final + // version of the constant to make sure its value is filled in. + schema::Node::Reader proto = constSchema.getProto(); + if (!isBootstrap) { + KJ_IF_MAYBE(finalProto, resolver.resolveFinalSchema(id)) { + proto = *finalProto; + } else { + // The constant's final schema is broken for reasons already reported. + return nullptr; + } + } + + auto constReader = proto.getConst(); + auto dynamicConst = toDynamic(constReader.getValue()); + auto constValue = dynamicConst.get(KJ_ASSERT_NONNULL(dynamicConst.which())); + + if (constValue.getType() == DynamicValue::ANY_POINTER) { + // We need to assign an appropriate schema to this pointer. + AnyPointer::Reader objValue = constValue.as(); + + auto constType = constSchema.asConst().getType(); + switch (constType.which()) { + case schema::Type::STRUCT: + constValue = objValue.getAs(constType.asStruct()); + break; + case schema::Type::LIST: + constValue = objValue.getAs(constType.asList()); + break; + case schema::Type::ANY_POINTER: + // Fine as-is. + break; + default: + KJ_FAIL_ASSERT("Unrecognized AnyPointer-typed member of schema::Value."); + break; + } + } + + if (source.isRelativeName()) { + // A fully unqualified identifier looks like it might refer to a constant visible in the + // current scope, but if that's really what the user wanted, we want them to use a + // qualified name to make it more obvious. Report an error. + KJ_IF_MAYBE(scope, resolver.resolveBootstrapSchema(proto.getScopeId(), + schema::Brand::Reader())) { + auto scopeReader = scope->getProto(); + kj::StringPtr parent; + if (scopeReader.isFile()) { + parent = ""; + } else { + parent = scopeReader.getDisplayName().slice(scopeReader.getDisplayNamePrefixLength()); + } + kj::StringPtr id = source.getRelativeName().getValue(); + + errorReporter.addErrorOn(source, kj::str( + "Constant names must be qualified to avoid confusion. Please replace '", + expressionString(source), "' with '", parent, ".", id, + "', if that's what you intended.")); + } + } + + return constValue; +} + +kj::Maybe> NodeTranslator::readEmbed(LocatedText::Reader filename) { + KJ_IF_MAYBE(data, resolver.readEmbed(filename.getValue())) { + return kj::mv(*data); + } else { + errorReporter.addErrorOn(filename, + kj::str("Couldn't read file for embed: ", filename.getValue())); + return nullptr; + } +} + +Orphan> NodeTranslator::compileAnnotationApplications( + List::Reader annotations, + kj::StringPtr targetsFlagName) { + if (annotations.size() == 0) { + // Return null. + return Orphan>(); + } + + auto result = orphanage.newOrphan>(annotations.size()); + auto builder = result.get(); + + for (uint i = 0; i < annotations.size(); i++) { + Declaration::AnnotationApplication::Reader annotation = annotations[i]; + schema::Annotation::Builder annotationBuilder = builder[i]; + + // Set the annotation's value to void in case we fail to produce something better below. + annotationBuilder.initValue().setVoid(); + + auto name = annotation.getName(); + KJ_IF_MAYBE(decl, compileDeclExpression(name)) { + KJ_IF_MAYBE(kind, decl->getKind()) { + if (*kind != Declaration::ANNOTATION) { + errorReporter.addErrorOn(name, kj::str( + "'", expressionString(name), "' is not an annotation.")); + } else { + annotationBuilder.setId(decl->getIdAndFillBrand( + [&]() { return annotationBuilder.initBrand(); })); + KJ_IF_MAYBE(annotationSchema, + resolver.resolveBootstrapSchema(annotationBuilder.getId(), + annotationBuilder.getBrand())) { + auto node = annotationSchema->getProto().getAnnotation(); + if (!toDynamic(node).get(targetsFlagName).as()) { + errorReporter.addErrorOn(name, kj::str( + "'", expressionString(name), "' cannot be applied to this kind of declaration.")); + } + + // Interpret the value. + auto value = annotation.getValue(); + switch (value.which()) { + case Declaration::AnnotationApplication::Value::NONE: + // No value, i.e. void. + if (node.getType().isVoid()) { + annotationBuilder.getValue().setVoid(); + } else { + errorReporter.addErrorOn(name, kj::str( + "'", expressionString(name), "' requires a value.")); + compileDefaultDefaultValue(node.getType(), annotationBuilder.getValue()); + } + break; + + case Declaration::AnnotationApplication::Value::EXPRESSION: + compileBootstrapValue(value.getExpression(), node.getType(), + annotationBuilder.getValue(), + *annotationSchema); + break; + } + } + } + } else { + errorReporter.addErrorOn(name, kj::str( + "'", expressionString(name), "' is not an annotation.")); + } + } + } + + return result; +} + +} // namespace compiler +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/compiler/node-translator.h b/vendor/capnproto/src/capnp/compiler/node-translator.h new file mode 100644 index 0000000..94bdf49 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/node-translator.h @@ -0,0 +1,205 @@ +// 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. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include "error-reporter.h" +#include "resolver.h" +#include "generics.h" +#include + +CAPNP_BEGIN_HEADER + +namespace capnp { +namespace compiler { + +class NodeTranslator { + // Translates one node in the schema from AST form to final schema form. A "node" is anything + // that has a unique ID, such as structs, enums, constants, and annotations, but not fields, + // unions, enumerants, or methods (the latter set have 16-bit ordinals but not 64-bit global IDs). +public: + NodeTranslator(Resolver& resolver, ErrorReporter& errorReporter, + const Declaration::Reader& decl, Orphan wipNode); + // Construct a NodeTranslator to translate the given declaration. The wipNode starts out with + // `displayName`, `id`, `scopeId`, and `nestedNodes` already initialized. The `NodeTranslator` + // fills in the rest. + + ~NodeTranslator() noexcept(false); + + struct NodeSet { + schema::Node::Reader node; + // The main node. + + kj::Array auxNodes; + // Auxiliary nodes that were produced when translating this node and should be loaded along + // with it. In particular, structs that contain groups (or named unions) spawn extra nodes + // representing those. + + }; + + NodeSet getBootstrapNode(); + // Get an incomplete version of the node in which pointer-typed value expressions have not yet + // been translated. Instead, for all `schema.Value` objects representing pointer-type values, + // the value is set to an appropriate "empty" value. This version of the schema can be used to + // bootstrap the dynamic API which can then in turn be used to encode the missing complex values. + // + // If the final node has already been built, this will actually return the final node (in fact, + // it's the same node object). + + NodeSet finish(Schema selfUnboundBootstrap); + // Finish translating the node (including filling in all the pieces that are missing from the + // bootstrap node) and return it. + // + // `selfUnboundBootstrap` is a Schema build using the Node returned by getBootstrapNode(), and + // with generic parameters "unbound", i.e. it was returned by SchemaLoader::getUnbound(). + + static kj::Maybe compileDecl( + uint64_t scopeId, uint scopeParameterCount, Resolver& resolver, ErrorReporter& errorReporter, + Expression::Reader expression, schema::Brand::Builder brandBuilder); + // Compile a one-off declaration expression without building a NodeTranslator. Used for + // evaluating aliases. + // + // `brandBuilder` may be used to construct a message which will fill in ResolvedDecl::brand in + // the result. + +private: + class DuplicateNameDetector; + class DuplicateOrdinalDetector; + class StructLayout; + class StructTranslator; + + Resolver& resolver; + ErrorReporter& errorReporter; + Orphanage orphanage; + kj::Own localBrand; + + Orphan wipNode; + // The work-in-progress schema node. + + kj::Vector> groups; + // If this is a struct node and it contains groups, these are the nodes for those groups, which + // must be loaded together with the top-level node. + + + + struct UnfinishedValue { + Expression::Reader source; + schema::Type::Reader type; + kj::Maybe typeScope; + schema::Value::Builder target; + }; + kj::Vector unfinishedValues; + // List of values in `wipNode` which have not yet been interpreted, because they are structs + // or lists and as such interpreting them require using the types' schemas (to take advantage + // of the dynamic API). Once bootstrap schemas have been built, they can be used to interpret + // these values. + + void compileNode(Declaration::Reader decl, schema::Node::Builder builder); + + void compileConst(Declaration::Const::Reader decl, schema::Node::Const::Builder builder); + void compileAnnotation(Declaration::Annotation::Reader decl, + schema::Node::Annotation::Builder builder); + + void compileEnum(Void decl, List::Reader members, + schema::Node::Builder builder); + void compileStruct(Void decl, List::Reader members, + schema::Node::Builder builder); + // The `members` arrays contain only members with ordinal numbers, in code order. Other members + // are handled elsewhere. + + kj::Maybe compileDeclExpression( + Expression::Reader source); + // Compile an expression which is expected to resolve to a declaration or type expression. + + bool compileType(Expression::Reader source, schema::Type::Builder target); + // Returns false if there was a problem, in which case value expressions of this type should + // not be parsed. + + void compileDefaultDefaultValue(schema::Type::Reader type, schema::Value::Builder target); + // Initializes `target` to contain the "default default" value for `type`. + + void compileBootstrapValue( + Expression::Reader source, schema::Type::Reader type, schema::Value::Builder target, + kj::Maybe typeScope = nullptr); + // Calls compileValue() if this value should be interpreted at bootstrap time. Otherwise, + // adds the value to `unfinishedValues` for later evaluation. + // + // If `type` comes from some other node, `typeScope` is the schema for that node. Otherwise the + // scope of the type expression is assumed to be this node (meaning, in particular, that no + // generic type parameters are bound). + + void compileValue(Expression::Reader source, schema::Type::Reader type, + Schema typeScope, schema::Value::Builder target, bool isBootstrap); + // Interprets the value expression and initializes `target` with the result. + + kj::Maybe readConstant(Expression::Reader name, bool isBootstrap); + // Get the value of the given constant. May return null if some error occurs, which will already + // have been reported. + + kj::Maybe> readEmbed(LocatedText::Reader filename); + // Read a raw file for embedding. + + Orphan> compileAnnotationApplications( + List::Reader annotations, + kj::StringPtr targetsFlagName); +}; + +class ValueTranslator { +public: + class Resolver { + public: + virtual kj::Maybe resolveConstant(Expression::Reader name) = 0; + virtual kj::Maybe> readEmbed(LocatedText::Reader filename) = 0; + }; + + ValueTranslator(Resolver& resolver, ErrorReporter& errorReporter, Orphanage orphanage) + : resolver(resolver), errorReporter(errorReporter), orphanage(orphanage) {} + + kj::Maybe> compileValue(Expression::Reader src, Type type); + + void fillStructValue(DynamicStruct::Builder builder, + List::Reader assignments); + // Interprets the given assignments and uses them to fill in the given struct builder. + +private: + Resolver& resolver; + ErrorReporter& errorReporter; + Orphanage orphanage; + + Orphan compileValueInner(Expression::Reader src, Type type); + bool matchesType(Expression::Reader src, Type type, Orphan& result); + // Helpers for compileValue(). + + kj::String makeNodeName(Schema node); + kj::String makeTypeName(Type type); + +}; + +} // namespace compiler +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/compiler/parser.c++ b/vendor/capnproto/src/capnp/compiler/parser.c++ new file mode 100644 index 0000000..8d7ece3 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/parser.c++ @@ -0,0 +1,1160 @@ +// 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 "parser.h" +#include "type-id.h" +#include +#include +#include +#include +#include +#include +#include + + +namespace capnp { +namespace compiler { + +uint64_t generateRandomId() { + uint64_t result; + + int fd; + KJ_SYSCALL(fd = open("/dev/urandom", O_RDONLY)); + KJ_DEFER(close(fd)); + + ssize_t n; + KJ_SYSCALL(n = read(fd, &result, sizeof(result)), "/dev/urandom"); + KJ_ASSERT(n == sizeof(result), "Incomplete read from /dev/urandom.", n); + + return result | (1ull << 63); +} + +void parseFile(List::Reader statements, ParsedFile::Builder result, + ErrorReporter& errorReporter) { + CapnpParser parser(Orphanage::getForMessageContaining(result), errorReporter); + + kj::Vector> decls(statements.size()); + kj::Vector> annotations; + + auto fileDecl = result.getRoot(); + fileDecl.setFile(VOID); + + for (auto statement: statements) { + KJ_IF_MAYBE(decl, parser.parseStatement(statement, parser.getParsers().fileLevelDecl)) { + Declaration::Builder builder = decl->get(); + switch (builder.which()) { + case Declaration::NAKED_ID: + if (fileDecl.getId().isUid()) { + errorReporter.addError(builder.getStartByte(), builder.getEndByte(), + "File can only have one ID."); + } else { + fileDecl.getId().adoptUid(builder.disownNakedId()); + } + break; + case Declaration::NAKED_ANNOTATION: + annotations.add(builder.disownNakedAnnotation()); + break; + default: + decls.add(kj::mv(*decl)); + break; + } + } + } + + if (fileDecl.getId().which() != Declaration::Id::UID) { + // We didn't see an ID. Generate one randomly for now. + uint64_t id = generateRandomId(); + fileDecl.getId().initUid().setValue(id); + + // Don't report missing ID if there was a parse error, because quite often the parse error + // prevents us from parsing the ID even though it is actually there. + if (!errorReporter.hadErrors()) { + errorReporter.addError(0, 0, + kj::str("File does not declare an ID. I've generated one for you. Add this line to " + "your file: @0x", kj::hex(id), ";")); + } + } + + auto declsBuilder = fileDecl.initNestedDecls(decls.size()); + for (size_t i = 0; i < decls.size(); i++) { + declsBuilder.adoptWithCaveats(i, kj::mv(decls[i])); + } + + auto annotationsBuilder = fileDecl.initAnnotations(annotations.size()); + for (size_t i = 0; i < annotations.size(); i++) { + annotationsBuilder.adoptWithCaveats(i, kj::mv(annotations[i])); + } +} + +namespace p = kj::parse; + +namespace { + +// ======================================================================================= + +template +struct Located { + T value; + uint32_t startByte; + uint32_t endByte; + + template + void copyLocationTo(Builder builder) { + builder.setStartByte(startByte); + builder.setEndByte(endByte); + } + template + void copyTo(Builder builder) { + builder.setValue(value); + copyLocationTo(builder); + } + template + Orphan asProto(Orphanage orphanage) { + auto result = orphanage.newOrphan(); + copyTo(result.get()); + return result; + } + template + Located> rewrap(Other&& other) { + return Located(kj::fwd(other), startByte, endByte); + } + + Located(const T& value, uint32_t startByte, uint32_t endByte) + : value(value), startByte(startByte), endByte(endByte) {} + Located(T&& value, uint32_t startByte, uint32_t endByte) + : value(kj::mv(value)), startByte(startByte), endByte(endByte) {} +}; + +// ======================================================================================= + +template +struct MatchTokenType { + kj::Maybe> operator()(Token::Reader token) const { + if (token.which() == type) { + return Located((token.*get)(), token.getStartByte(), token.getEndByte()); + } else { + return nullptr; + } + } +}; + +#define TOKEN_TYPE_PARSER(type, discrim, getter) \ + p::transformOrReject(p::any, \ + MatchTokenType()) + +constexpr auto identifier = TOKEN_TYPE_PARSER(Text::Reader, IDENTIFIER, getIdentifier); +constexpr auto stringLiteral = TOKEN_TYPE_PARSER(Text::Reader, STRING_LITERAL, getStringLiteral); +constexpr auto binaryLiteral = TOKEN_TYPE_PARSER(Data::Reader, BINARY_LITERAL, getBinaryLiteral); +constexpr auto integerLiteral = TOKEN_TYPE_PARSER(uint64_t, INTEGER_LITERAL, getIntegerLiteral); +constexpr auto floatLiteral = TOKEN_TYPE_PARSER(double, FLOAT_LITERAL, getFloatLiteral); +constexpr auto operatorToken = TOKEN_TYPE_PARSER(Text::Reader, OPERATOR, getOperator); +constexpr auto rawParenthesizedList = + TOKEN_TYPE_PARSER(List>::Reader, PARENTHESIZED_LIST, getParenthesizedList); +constexpr auto rawBracketedList = + TOKEN_TYPE_PARSER(List>::Reader, BRACKETED_LIST, getBracketedList); + +// ======================================================================================= + +class ExactString { +public: + constexpr ExactString(const char* expected): expected(expected) {} + + kj::Maybe> operator()(Located&& text) const { + if (text.value == expected) { + return kj::Tuple<>(); + } else { + return nullptr; + } + } + +private: + const char* expected; +}; + +constexpr auto keyword(const char* expected) + -> decltype(p::transformOrReject(identifier, ExactString(expected))) { + return p::transformOrReject(identifier, ExactString(expected)); +} + +constexpr auto op(const char* expected) + -> decltype(p::transformOrReject(operatorToken, ExactString(expected))) { + return p::transformOrReject(operatorToken, ExactString(expected)); +} + +class LocatedExactString { +public: + constexpr LocatedExactString(const char* expected): expected(expected) {} + + kj::Maybe> operator()(Located&& text) const { + if (text.value == expected) { + return kj::mv(text); + } else { + return nullptr; + } + } + +private: + const char* expected; +}; + +constexpr auto locatedKeyword(const char* expected) + -> decltype(p::transformOrReject(identifier, LocatedExactString(expected))) { + return p::transformOrReject(identifier, LocatedExactString(expected)); +} + +// ======================================================================================= + +template +class ParseListItems { + // Transformer that parses all items in the input token sequence list using the given parser. + +public: + constexpr ParseListItems(ItemParser&& itemParser, ErrorReporter& errorReporter) + : itemParser(p::sequence(kj::fwd(itemParser), p::endOfInput)), + errorReporter(errorReporter) {} + + Located>>> operator()( + Located>::Reader>&& items) const { + auto result = kj::heapArray>>( + items.value.size()); + for (uint i = 0; i < items.value.size(); i++) { + auto item = items.value[i]; + CapnpParser::ParserInput input(item.begin(), item.end()); + result[i] = itemParser(input); + if (result[i] == nullptr) { + // Parsing failed. Report an error. + auto best = input.getBest(); + if (best < item.end()) { + // Report error from the point where parsing failed to the end of the item. + errorReporter.addError( + best->getStartByte(), (item.end() - 1)->getEndByte(), "Parse error."); + } else if (item.size() > 0) { + // The item is non-empty and the parser consumed all of it before failing. Report an + // error for the whole thing. + errorReporter.addError( + item.begin()->getStartByte(), (item.end() - 1)->getEndByte(), "Parse error."); + } else { + // The item has no content. + // TODO(cleanup): We don't actually know the item's location, so we can only report + // an error across the whole list. Fix this. + errorReporter.addError(items.startByte, items.endByte, "Parse error: Empty list item."); + } + } + } + return Located>>>( + kj::mv(result), items.startByte, items.endByte); + } + +private: + decltype(p::sequence(kj::instance(), p::endOfInput)) itemParser; + ErrorReporter& errorReporter; +}; + +template +constexpr auto parenthesizedList(ItemParser&& itemParser, ErrorReporter& errorReporter) -> decltype( + transform(rawParenthesizedList, ParseListItems( + kj::fwd(itemParser), errorReporter))) { + return transform(rawParenthesizedList, ParseListItems( + kj::fwd(itemParser), errorReporter)); +} + +template +constexpr auto bracketedList(ItemParser&& itemParser, ErrorReporter& errorReporter) -> decltype( + transform(rawBracketedList, ParseListItems( + kj::fwd(itemParser), errorReporter))) { + return transform(rawBracketedList, ParseListItems( + kj::fwd(itemParser), errorReporter)); +} + +// ======================================================================================= + +template +Orphan> arrayToList(Orphanage& orphanage, kj::Array>&& elements) { + auto result = orphanage.newOrphan>(elements.size()); + auto builder = result.get(); + for (size_t i = 0; i < elements.size(); i++) { + builder.adoptWithCaveats(i, kj::mv(elements[i])); + } + return kj::mv(result); +} + +static void initGenericParams(Declaration::Builder builder, + kj::Maybe>>>>&& genericParameters) { + KJ_IF_MAYBE(p, genericParameters) { + auto params = builder.initParameters(p->value.size()); + for (uint i: kj::indices(p->value)) { + KJ_IF_MAYBE(name, p->value[i]) { + auto param = params[i]; + param.setName(name->value); + name->copyLocationTo(param); + } + } + } +} + +static Declaration::Builder initDecl( + Declaration::Builder builder, Located&& name, + kj::Maybe>&& id, + kj::Maybe>>>>&& genericParameters, + kj::Array>&& annotations) { + name.copyTo(builder.initName()); + KJ_IF_MAYBE(i, id) { + builder.getId().adoptUid(kj::mv(*i)); + } + + initGenericParams(builder, kj::mv(genericParameters)); + + auto list = builder.initAnnotations(annotations.size()); + for (uint i = 0; i < annotations.size(); i++) { + list.adoptWithCaveats(i, kj::mv(annotations[i])); + } + return builder; +} + +static Declaration::Builder initMemberDecl( + Declaration::Builder builder, Located&& name, + Orphan&& ordinal, + kj::Array>&& annotations) { + name.copyTo(builder.initName()); + builder.getId().adoptOrdinal(kj::mv(ordinal)); + auto list = builder.initAnnotations(annotations.size()); + for (uint i = 0; i < annotations.size(); i++) { + list.adoptWithCaveats(i, kj::mv(annotations[i])); + } + return builder; +} + +template +void initLocation(kj::parse::Span::Reader::Iterator> location, + BuilderType builder) { + if (location.begin() < location.end()) { + builder.setStartByte(location.begin()->getStartByte()); + builder.setEndByte((location.end() - 1)->getEndByte()); + } +} + +} // namespace + +// ======================================================================================= + +CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterParam) + : orphanage(orphanageParam), errorReporter(errorReporterParam) { + auto& tupleElement = arena.copy(p::transform( + p::sequence(p::optional(p::sequence(identifier, op("="))), parsers.expression), + [this](kj::Maybe>&& fieldName, Orphan&& fieldValue) + -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + KJ_IF_MAYBE(fn, fieldName) { + fn->copyTo(builder.initNamed()); + } else { + builder.setUnnamed(); + } + builder.adoptValue(kj::mv(fieldValue)); + return kj::mv(result); + })); + + auto& tuple = arena.copy>>>>( + arena.copy(p::transform( + parenthesizedList(tupleElement, errorReporter), + [this](Located>>>&& elements) + -> Located>> { + auto result = orphanage.newOrphan>(elements.value.size()); + auto builder = result.get(); + for (uint i: kj::indices(elements.value)) { + KJ_IF_MAYBE(e, elements.value[i]) { + builder.adoptWithCaveats(i, kj::mv(*e)); + } else { + builder[i].initValue().setUnknown(); + } + } + return elements.rewrap(kj::mv(result)); + }))); + + parsers.expression = arena.copy(p::transform( + p::sequence( + // Base expression. + p::oneOf( + p::transform(integerLiteral, + [this](Located&& value) -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + builder.setPositiveInt(value.value); + value.copyLocationTo(builder); + return result; + }), + p::transform(p::sequence(op("-"), integerLiteral), + [this](Located&& value) -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + builder.setNegativeInt(value.value); + value.copyLocationTo(builder); + return result; + }), + p::transform(floatLiteral, + [this](Located&& value) -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + builder.setFloat(value.value); + value.copyLocationTo(builder); + return result; + }), + p::transform(p::sequence(op("-"), floatLiteral), + [this](Located&& value) -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + builder.setFloat(-value.value); + value.copyLocationTo(builder); + return result; + }), + p::transformWithLocation(p::sequence(op("-"), keyword("inf")), + [this](kj::parse::Span::Reader::Iterator> location) + -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + builder.setFloat(-kj::inf()); + initLocation(location, builder); + return result; + }), + p::transform(p::oneOrMore(stringLiteral), + [this](kj::Array>&& value) -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + builder.setString(kj::strArray( + KJ_MAP(part, value) { return part.value; }, "")); + builder.setStartByte(value.front().startByte); + builder.setEndByte(value.back().endByte); + return result; + }), + p::transform(binaryLiteral, + [this](Located&& value) -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + builder.setBinary(value.value); + value.copyLocationTo(builder); + return result; + }), + p::transform(bracketedList(parsers.expression, errorReporter), + [this](Located>>>&& value) + -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + auto listBuilder = builder.initList(value.value.size()); + for (uint i = 0; i < value.value.size(); i++) { + KJ_IF_MAYBE(element, value.value[i]) { + listBuilder.adoptWithCaveats(i, kj::mv(*element)); + } + } + value.copyLocationTo(builder); + return result; + }), + p::transform(tuple, + [this](Located>>&& value) + -> Orphan { + auto elements = value.value.get(); + + if (elements.size() == 1 && elements[0].isUnnamed()) { + // Single-value tuple is just a value. + return elements[0].disownValue(); + } else { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + builder.adoptTuple(kj::mv(value.value)); + value.copyLocationTo(builder); + return result; + } + }), + p::transformWithLocation(p::sequence(keyword("import"), stringLiteral), + [this](kj::parse::Span::Reader::Iterator> location, + Located&& filename) -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + initLocation(location, builder); + filename.copyTo(builder.initImport()); + return result; + }), + p::transformWithLocation(p::sequence(keyword("embed"), stringLiteral), + [this](kj::parse::Span::Reader::Iterator> location, + Located&& filename) -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + initLocation(location, builder); + filename.copyTo(builder.initEmbed()); + return result; + }), + p::transformWithLocation(p::sequence(op("."), identifier), + [this](kj::parse::Span::Reader::Iterator> location, + Located&& name) -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + initLocation(location, builder); + name.copyTo(builder.initAbsoluteName()); + return result; + }), + p::transform(identifier, + [this](Located&& name) -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + name.copyTo(builder.initRelativeName()); + name.copyLocationTo(builder); + return result; + })), + // Suffixes, e.g. ".member" or "(param1, param2)". + p::many(p::oneOf( + p::transformWithLocation(p::sequence(op("."), identifier), + [this](kj::parse::Span::Reader::Iterator> location, + Located&& name) -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + initLocation(location, builder); + name.copyTo(builder.initMember().initName()); + return result; + }), + p::transform(tuple, + [this](Located>>&& params) -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + params.copyLocationTo(builder); + builder.initApplication().adoptParams(kj::mv(params.value)); + return result; + })))), + [](Orphan&& base, kj::Array>&& suffixes) + -> Orphan { + // Apply all the suffixes to the base expression. + uint startByte = base.getReader().getStartByte(); + for (auto& suffix: suffixes) { + auto builder = suffix.get(); + if (builder.isApplication()) { + builder.getApplication().adoptFunction(kj::mv(base)); + } else if (builder.isMember()) { + builder.getMember().adoptParent(kj::mv(base)); + } else { + KJ_FAIL_ASSERT("Unknown suffix?", (uint)builder.which()); + } + builder.setStartByte(startByte); + base = kj::mv(suffix); + } + return kj::mv(base); + })); + + parsers.annotation = arena.copy(p::transform( + p::sequence(op("$"), parsers.expression), + [this](Orphan&& expression) + -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + + auto exp = expression.get(); + if (exp.isApplication()) { + // Oops, this annotation specifies the value, but we parsed it as an application on + // the preceding expression. Pull it back apart. + auto app = exp.getApplication(); + builder.adoptName(app.disownFunction()); + auto params = app.getParams(); + if (params.size() == 1 && params[0].isUnnamed()) { + // Params has a single unnamed element, so reduce it to a simple value rather than + // a tuple. + builder.getValue().adoptExpression(params[0].disownValue()); + } else { + // Params is not a single unnamed element, so it's a tuple. + builder.getValue().initExpression().adoptTuple(app.disownParams()); + } + } else { + // The annotation has no value. + builder.adoptName(kj::mv(expression)); + builder.getValue().setNone(); + } + + return result; + })); + + parsers.uid = arena.copy(p::transform( + p::sequence(op("@"), integerLiteral), + [this](Located&& value) { + if (value.value < (1ull << 63)) { + errorReporter.addError(value.startByte, value.endByte, + "Invalid ID. Please generate a new one with 'capnpc -i'."); + } + return value.asProto(orphanage); + })); + + parsers.ordinal = arena.copy(p::transform( + p::sequence(op("@"), integerLiteral), + [this](Located&& value) { + if (value.value >= 65536) { + errorReporter.addError(value.startByte, value.endByte, + "Ordinals cannot be greater than 65535."); + } + return value.asProto(orphanage); + })); + + // ----------------------------------------------------------------- + + parsers.usingDecl = arena.copy(p::transform( + p::sequence(keyword("using"), p::optional(p::sequence(identifier, op("="))), + parsers.expression), + [this](kj::Maybe>&& name, Orphan&& target) + -> DeclParserResult { + auto decl = orphanage.newOrphan(); + auto builder = decl.get(); + KJ_IF_MAYBE(n, name) { + n->copyTo(builder.initName()); + } else { + auto targetReader = target.getReader(); + if (targetReader.isMember()) { + builder.setName(targetReader.getMember().getName()); + } else { + errorReporter.addErrorOn(targetReader, + "'using' declaration without '=' must specify a named declaration from a " + "different scope."); + } + } + // no id, no annotations for using decl + builder.initUsing().adoptTarget(kj::mv(target)); + return DeclParserResult(kj::mv(decl)); + })); + + parsers.constDecl = arena.copy(p::transform( + p::sequence(keyword("const"), identifier, p::optional(parsers.uid), + op(":"), parsers.expression, + op("="), parsers.expression, + p::many(parsers.annotation)), + [this](Located&& name, kj::Maybe>&& id, + Orphan&& type, Orphan&& value, + kj::Array>&& annotations) + -> DeclParserResult { + auto decl = orphanage.newOrphan(); + auto builder = + initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr, + kj::mv(annotations)).initConst(); + builder.adoptType(kj::mv(type)); + builder.adoptValue(kj::mv(value)); + return DeclParserResult(kj::mv(decl)); + })); + + parsers.enumDecl = arena.copy(p::transform( + p::sequence(keyword("enum"), identifier, p::optional(parsers.uid), + p::many(parsers.annotation)), + [this](Located&& name, kj::Maybe>&& id, + kj::Array>&& annotations) + -> DeclParserResult { + auto decl = orphanage.newOrphan(); + initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr, kj::mv(annotations)).setEnum(); + return DeclParserResult(kj::mv(decl), parsers.enumLevelDecl); + })); + + parsers.enumerantDecl = arena.copy(p::transform( + p::sequence(identifier, parsers.ordinal, p::many(parsers.annotation)), + [this](Located&& name, Orphan&& ordinal, + kj::Array>&& annotations) + -> DeclParserResult { + auto decl = orphanage.newOrphan(); + initMemberDecl(decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations)) + .setEnumerant(); + return DeclParserResult(kj::mv(decl)); + })); + + parsers.structDecl = arena.copy(p::transform( + p::sequence(keyword("struct"), identifier, p::optional(parsers.uid), + p::optional(parenthesizedList(identifier, errorReporter)), + p::many(parsers.annotation)), + [this](Located&& name, kj::Maybe>&& id, + kj::Maybe>>>>&& genericParameters, + kj::Array>&& annotations) + -> DeclParserResult { + auto decl = orphanage.newOrphan(); + initDecl(decl.get(), kj::mv(name), kj::mv(id), kj::mv(genericParameters), + kj::mv(annotations)).setStruct(); + return DeclParserResult(kj::mv(decl), parsers.structLevelDecl); + })); + + parsers.fieldDecl = arena.copy(p::transform( + p::sequence(identifier, parsers.ordinal, op(":"), parsers.expression, + p::optional(p::sequence(op("="), parsers.expression)), + p::many(parsers.annotation)), + [this](Located&& name, Orphan&& ordinal, + Orphan&& type, kj::Maybe>&& defaultValue, + kj::Array>&& annotations) + -> DeclParserResult { + auto decl = orphanage.newOrphan(); + auto builder = + initMemberDecl(decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations)) + .initField(); + builder.adoptType(kj::mv(type)); + KJ_IF_MAYBE(val, defaultValue) { + builder.getDefaultValue().adoptValue(kj::mv(*val)); + } else { + builder.getDefaultValue().setNone(); + } + return DeclParserResult(kj::mv(decl)); + })); + + // Parse an ordinal followed by an optional colon, or no ordinal but require a colon. + auto& ordinalOrColon = arena.copy(p::oneOf( + p::transform(p::sequence(parsers.ordinal, p::optional(op("!")), p::optional(op(":"))), + [](Orphan&& ordinal, + kj::Maybe> exclamation, + kj::Maybe> colon) + -> kj::Tuple>, bool, bool> { + return kj::tuple(kj::mv(ordinal), exclamation == nullptr, colon == nullptr); + }), + p::transform(op(":"), + []() -> kj::Tuple>, bool, bool> { + return kj::tuple(nullptr, false, false); + }))); + + parsers.unionDecl = arena.copy(p::transform( + // The first branch of this oneOf() matches named unions. The second branch matches unnamed + // unions and generates dummy values for the parse results. + p::oneOf( + p::sequence( + identifier, ordinalOrColon, + keyword("union"), p::many(parsers.annotation)), + p::transformWithLocation(p::sequence(keyword("union"), p::endOfInput), + [](kj::parse::Span::Reader::Iterator> location) { + return kj::tuple( + Located("", location.begin()->getStartByte(), + location.begin()->getEndByte()), + kj::Maybe>(nullptr), + false, false, + kj::Array>(nullptr)); + })), + [this](Located&& name, + kj::Maybe>&& ordinal, + bool missingExclamation, bool missingColon, + kj::Array>&& annotations) + -> DeclParserResult { + if (missingExclamation) { + errorReporter.addErrorOn(KJ_ASSERT_NONNULL(ordinal).getReader(), + "As of Cap'n Proto v0.3, it is no longer necessary to assign numbers to " + "unions. However, removing the number will break binary compatibility. " + "If this is an old protocol and you need to retain compatibility, please " + "add an exclamation point after the number to indicate that it is really " + "needed, e.g. `foo @1! :union {`. If this is a new protocol or compatibility " + "doesn't matter, just remove the @n entirely. Sorry for the inconvenience, " + "and thanks for being an early adopter! :)"); + } + if (missingColon) { + errorReporter.addErrorOn(KJ_ASSERT_NONNULL(ordinal).getReader(), + "As of Cap'n Proto v0.3, the 'union' keyword should be prefixed with a colon " + "for named unions, e.g. `foo :union {`."); + } + + auto decl = orphanage.newOrphan(); + auto builder = decl.get(); + name.copyTo(builder.initName()); + KJ_IF_MAYBE(ord, ordinal) { + builder.getId().adoptOrdinal(kj::mv(*ord)); + } else { + builder.getId().setUnspecified(); + } + auto list = builder.initAnnotations(annotations.size()); + for (uint i = 0; i < annotations.size(); i++) { + list.adoptWithCaveats(i, kj::mv(annotations[i])); + } + builder.setUnion(); + return DeclParserResult(kj::mv(decl), parsers.structLevelDecl); + })); + + parsers.groupDecl = arena.copy(p::transform( + p::sequence(identifier, op(":"), keyword("group"), p::many(parsers.annotation)), + [this](Located&& name, + kj::Array>&& annotations) + -> DeclParserResult { + auto decl = orphanage.newOrphan(); + auto builder = decl.get(); + name.copyTo(builder.getName()); + builder.getId().setUnspecified(); + auto list = builder.initAnnotations(annotations.size()); + for (uint i = 0; i < annotations.size(); i++) { + list.adoptWithCaveats(i, kj::mv(annotations[i])); + } + builder.setGroup(); + return DeclParserResult(kj::mv(decl), parsers.structLevelDecl); + })); + + parsers.interfaceDecl = arena.copy(p::transform( + p::sequence(keyword("interface"), identifier, p::optional(parsers.uid), + p::optional(parenthesizedList(identifier, errorReporter)), + p::optional(p::sequence( + keyword("extends"), parenthesizedList(parsers.expression, errorReporter))), + p::many(parsers.annotation)), + [this](Located&& name, kj::Maybe>&& id, + kj::Maybe>>>>&& genericParameters, + kj::Maybe>>>>&& superclasses, + kj::Array>&& annotations) + -> DeclParserResult { + auto decl = orphanage.newOrphan(); + auto builder = initDecl( + decl.get(), kj::mv(name), kj::mv(id), kj::mv(genericParameters), + kj::mv(annotations)).initInterface(); + KJ_IF_MAYBE(s, superclasses) { + auto superclassesBuilder = builder.initSuperclasses(s->value.size()); + for (uint i: kj::indices(s->value)) { + KJ_IF_MAYBE(superclass, s->value[i]) { + superclassesBuilder.adoptWithCaveats(i, kj::mv(*superclass)); + } + } + } + return DeclParserResult(kj::mv(decl), parsers.interfaceLevelDecl); + })); + + parsers.param = arena.copy(p::transformWithLocation( + p::sequence(identifier, op(":"), parsers.expression, + p::optional(p::sequence(op("="), parsers.expression)), + p::many(parsers.annotation)), + [this](kj::parse::Span::Reader::Iterator> location, + Located&& name, Orphan&& type, + kj::Maybe>&& defaultValue, + kj::Array>&& annotations) + -> Orphan { + auto result = orphanage.newOrphan(); + auto builder = result.get(); + + initLocation(location, builder); + + name.copyTo(builder.initName()); + builder.adoptType(kj::mv(type)); + builder.adoptAnnotations(arrayToList(orphanage, kj::mv(annotations))); + KJ_IF_MAYBE(val, defaultValue) { + builder.getDefaultValue().adoptValue(kj::mv(*val)); + } else { + builder.getDefaultValue().setNone(); + } + + return kj::mv(result); + })); + + auto& paramList = arena.copy(p::oneOf( + p::transform(parenthesizedList(parsers.param, errorReporter), + [this](Located>>>&& params) + -> Orphan { + auto decl = orphanage.newOrphan(); + auto builder = decl.get(); + params.copyLocationTo(builder); + auto listBuilder = builder.initNamedList(params.value.size()); + for (uint i: kj::indices(params.value)) { + KJ_IF_MAYBE(param, params.value[i]) { + listBuilder.adoptWithCaveats(i, kj::mv(*param)); + } + } + return decl; + }), + p::transform(locatedKeyword("stream"), + [this](Located&& kw) -> Orphan { + auto decl = orphanage.newOrphan(); + auto builder = decl.get(); + kw.copyLocationTo(builder); + builder.setStream(); + return decl; + }), + p::transform(parsers.expression, + [this](Orphan&& name) -> Orphan { + auto decl = orphanage.newOrphan(); + auto builder = decl.get(); + auto nameReader = name.getReader(); + builder.setStartByte(nameReader.getStartByte()); + builder.setEndByte(nameReader.getEndByte()); + builder.adoptType(kj::mv(name)); + return decl; + }))); + + parsers.methodDecl = arena.copy(p::transform( + p::sequence(identifier, parsers.ordinal, + p::optional(bracketedList(identifier, errorReporter)), + paramList, + p::optional(p::sequence(op("->"), paramList)), + p::many(parsers.annotation)), + [this](Located&& name, Orphan&& ordinal, + kj::Maybe>>>>&& genericParams, + Orphan&& params, + kj::Maybe>&& results, + kj::Array>&& annotations) + -> DeclParserResult { + auto decl = orphanage.newOrphan(); + auto nodeBuilder = initMemberDecl( + decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations)); + + initGenericParams(nodeBuilder, kj::mv(genericParams)); + + auto builder = nodeBuilder.initMethod(); + + builder.adoptParams(kj::mv(params)); + + KJ_IF_MAYBE(r, results) { + builder.getResults().adoptExplicit(kj::mv(*r)); + } else { + builder.getResults().setNone(); + } + + return DeclParserResult(kj::mv(decl)); + })); + + auto& annotationTarget = arena.copy(p::oneOf( + identifier, + p::transformWithLocation(op("*"), + [](kj::parse::Span::Reader::Iterator> location) { + // Hacky... + return Located("*", + location.begin()->getStartByte(), + location.begin()->getEndByte()); + }))); + + parsers.annotationDecl = arena.copy(p::transform( + p::sequence(keyword("annotation"), identifier, p::optional(parsers.uid), + parenthesizedList(annotationTarget, errorReporter), + op(":"), parsers.expression, + p::many(parsers.annotation)), + [this](Located&& name, kj::Maybe>&& id, + Located>>>&& targets, + Orphan&& type, + kj::Array>&& annotations) + -> DeclParserResult { + auto decl = orphanage.newOrphan(); + auto builder = + initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr, + kj::mv(annotations)).initAnnotation(); + builder.adoptType(kj::mv(type)); + DynamicStruct::Builder dynamicBuilder = builder; + for (auto& maybeTarget: targets.value) { + KJ_IF_MAYBE(target, maybeTarget) { + if (target->value == "*") { + // Set all. + if (targets.value.size() > 1) { + errorReporter.addError(target->startByte, target->endByte, + "Wildcard should not be specified together with other targets."); + } + + for (auto field: dynamicBuilder.getSchema().getFields()) { + if (field.getProto().getName().startsWith("targets")) { + dynamicBuilder.set(field, true); + } + } + } else { + if (target->value.size() == 0 || target->value.size() >= 32 || + target->value[0] < 'a' || target->value[0] > 'z') { + errorReporter.addError(target->startByte, target->endByte, + "Not a valid annotation target."); + } else { + char buffer[64]; + strcpy(buffer, "targets"); + strcat(buffer, target->value.cStr()); + buffer[strlen("targets")] += 'A' - 'a'; + KJ_IF_MAYBE(field, dynamicBuilder.getSchema().findFieldByName(buffer)) { + if (dynamicBuilder.get(*field).as()) { + errorReporter.addError(target->startByte, target->endByte, + "Duplicate target specification."); + } + dynamicBuilder.set(*field, true); + } else { + errorReporter.addError(target->startByte, target->endByte, + "Not a valid annotation target."); + } + } + } + } + } + return DeclParserResult(kj::mv(decl)); + })); + + // ----------------------------------------------------------------- + + auto& nakedId = arena.copy(p::transform(parsers.uid, + [this](Orphan&& value) -> DeclParserResult { + auto decl = orphanage.newOrphan(); + decl.get().adoptNakedId(kj::mv(value)); + return DeclParserResult(kj::mv(decl)); + })); + + auto& nakedAnnotation = arena.copy(p::transform(parsers.annotation, + [this](Orphan&& value) -> DeclParserResult { + auto decl = orphanage.newOrphan(); + decl.get().adoptNakedAnnotation(kj::mv(value)); + return DeclParserResult(kj::mv(decl)); + })); + + // ----------------------------------------------------------------- + + parsers.genericDecl = arena.copy(p::oneOf( + parsers.usingDecl, parsers.constDecl, parsers.annotationDecl, + parsers.enumDecl, parsers.structDecl, parsers.interfaceDecl)); + parsers.fileLevelDecl = arena.copy(p::oneOf( + parsers.genericDecl, nakedId, nakedAnnotation)); + parsers.enumLevelDecl = arena.copy(p::oneOf(parsers.enumerantDecl)); + parsers.structLevelDecl = arena.copy(p::oneOf( + parsers.unionDecl, parsers.fieldDecl, parsers.groupDecl, parsers.genericDecl)); + parsers.interfaceLevelDecl = arena.copy(p::oneOf( + parsers.methodDecl, parsers.genericDecl)); +} + +CapnpParser::~CapnpParser() noexcept(false) {} + +kj::Maybe> CapnpParser::parseStatement( + Statement::Reader statement, const DeclParser& parser) { + auto fullParser = p::sequence(parser, p::endOfInput); + + auto tokens = statement.getTokens(); + ParserInput parserInput(tokens.begin(), tokens.end()); + + KJ_IF_MAYBE(output, fullParser(parserInput)) { + auto builder = output->decl.get(); + + builder.setStartByte(statement.getStartByte()); + builder.setEndByte(statement.getEndByte()); + + switch (statement.which()) { + case Statement::LINE: + if (output->memberParser != nullptr) { + errorReporter.addError(statement.getStartByte(), statement.getEndByte(), + "This statement should end with a block, not a semicolon."); + } + break; + + case Statement::BLOCK: + KJ_IF_MAYBE(memberParser, output->memberParser) { + auto memberStatements = statement.getBlock(); + kj::Vector> members(memberStatements.size()); + for (auto memberStatement: memberStatements) { + KJ_IF_MAYBE(member, parseStatement(memberStatement, *memberParser)) { + members.add(kj::mv(*member)); + } + } + builder.adoptNestedDecls(arrayToList(orphanage, members.releaseAsArray())); + } else { + errorReporter.addError(statement.getStartByte(), statement.getEndByte(), + "This statement should end with a semicolon, not a block."); + } + break; + } + + return kj::mv(output->decl); + + } else { + // Parse error. Figure out where to report it. + auto best = parserInput.getBest(); + uint32_t bestByte; + + if (best != tokens.end()) { + bestByte = best->getStartByte(); + } else if (tokens.end() != tokens.begin()) { + bestByte = (tokens.end() - 1)->getEndByte(); + } else { + bestByte = statement.getStartByte(); + } + + errorReporter.addError(bestByte, bestByte, "Parse error."); + return nullptr; + } +} + +// ======================================================================================= + +static const char HEXDIGITS[] = "0123456789abcdef"; + +static kj::StringTree stringLiteralStringTree(kj::StringPtr chars) { + return kj::strTree('"', kj::encodeCEscape(chars), '"'); +} + +static kj::StringTree binaryLiteralStringTree(Data::Reader data) { + kj::Vector escaped(data.size() * 3); + + for (byte b: data) { + escaped.add(HEXDIGITS[b % 16]); + escaped.add(HEXDIGITS[b / 16]); + escaped.add(' '); + } + + escaped.removeLast(); + return kj::strTree("0x\"", escaped, '"'); +} + +static kj::StringTree expressionStringTree(Expression::Reader exp); + +static kj::StringTree tupleLiteral(List::Reader params) { + auto parts = kj::heapArrayBuilder(params.size()); + for (auto param: params) { + auto part = expressionStringTree(param.getValue()); + if (param.isNamed()) { + part = kj::strTree(param.getNamed().getValue(), " = ", kj::mv(part)); + } + parts.add(kj::mv(part)); + } + return kj::strTree("( ", kj::StringTree(parts.finish(), ", "), " )"); +} + +static kj::StringTree expressionStringTree(Expression::Reader exp) { + switch (exp.which()) { + case Expression::UNKNOWN: + return kj::strTree(""); + case Expression::POSITIVE_INT: + return kj::strTree(exp.getPositiveInt()); + case Expression::NEGATIVE_INT: + return kj::strTree('-', exp.getNegativeInt()); + case Expression::FLOAT: + return kj::strTree(exp.getFloat()); + case Expression::STRING: + return stringLiteralStringTree(exp.getString()); + case Expression::BINARY: + return binaryLiteralStringTree(exp.getBinary()); + case Expression::RELATIVE_NAME: + return kj::strTree(exp.getRelativeName().getValue()); + case Expression::ABSOLUTE_NAME: + return kj::strTree('.', exp.getAbsoluteName().getValue()); + case Expression::IMPORT: + return kj::strTree("import ", stringLiteralStringTree(exp.getImport().getValue())); + case Expression::EMBED: + return kj::strTree("embed ", stringLiteralStringTree(exp.getEmbed().getValue())); + + case Expression::LIST: { + auto list = exp.getList(); + auto parts = kj::heapArrayBuilder(list.size()); + for (auto element: list) { + parts.add(expressionStringTree(element)); + } + return kj::strTree("[ ", kj::StringTree(parts.finish(), ", "), " ]"); + } + + case Expression::TUPLE: + return tupleLiteral(exp.getTuple()); + + case Expression::APPLICATION: { + auto app = exp.getApplication(); + return kj::strTree(expressionStringTree(app.getFunction()), + '(', tupleLiteral(app.getParams()), ')'); + } + + case Expression::MEMBER: { + auto member = exp.getMember(); + return kj::strTree(expressionStringTree(member.getParent()), '.', + member.getName().getValue()); + } + } + + KJ_UNREACHABLE; +} + +kj::String expressionString(Expression::Reader name) { + return expressionStringTree(name).flatten(); +} + +} // namespace compiler +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/compiler/parser.h b/vendor/capnproto/src/capnp/compiler/parser.h new file mode 100644 index 0000000..8dbe767 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/parser.h @@ -0,0 +1,146 @@ +// 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. + +#pragma once + +#include +#include +#include +#include +#include "error-reporter.h" + +CAPNP_BEGIN_HEADER + +namespace capnp { +namespace compiler { + +void parseFile(List::Reader statements, ParsedFile::Builder result, + ErrorReporter& errorReporter); +// Parse a list of statements to build a ParsedFile. +// +// If any errors are reported, then the output is not usable. However, it may be passed on through +// later stages of compilation in order to detect additional errors. + +uint64_t generateRandomId(); +// Generate a new random unique ID. This lives here mostly for lack of a better location. + +uint64_t generateChildId(uint64_t parentId, kj::StringPtr childName); +// Generate the ID for a child node given its parent ID and name. + +uint64_t generateGroupId(uint64_t parentId, uint16_t groupIndex); +// Generate the ID for a group within a struct. + +// TODO(cleanup): Move generate*Id() somewhere more sensible. + +class CapnpParser { + // Advanced parser interface. This interface exposes the inner parsers so that you can embed + // them into your own parsers. + +public: + CapnpParser(Orphanage orphanage, ErrorReporter& errorReporter); + // `orphanage` is used to allocate Cap'n Proto message objects in the result. `inputStart` is + // a pointer to the beginning of the input, used to compute byte offsets. + + ~CapnpParser() noexcept(false); + + KJ_DISALLOW_COPY_AND_MOVE(CapnpParser); + + using ParserInput = kj::parse::IteratorInput::Reader::Iterator>; + struct DeclParserResult; + template + using Parser = kj::parse::ParserRef; + using DeclParser = Parser; + + kj::Maybe> parseStatement( + Statement::Reader statement, const DeclParser& parser); + // Parse a statement using the given parser. In addition to parsing the token sequence itself, + // this takes care of parsing the block (if any). + + struct DeclParserResult { + // DeclParser parses a sequence of tokens representing just the "line" part of the statement -- + // i.e. everything up to the semicolon or opening curly brace. + // + // Use `parseStatement()` to avoid having to deal with this struct. + + Orphan decl; + // The declaration parsed so far, with nestedDecls still empty. + + kj::Maybe memberParser; + // If null, the statement should not have a block. If non-null, the statement should have a + // block containing statements parseable by this parser. + + DeclParserResult(Orphan&& decl, const DeclParser& memberParser) + : decl(kj::mv(decl)), memberParser(memberParser) {} + explicit DeclParserResult(Orphan&& decl) + : decl(kj::mv(decl)), memberParser(nullptr) {} + }; + + struct Parsers { + DeclParser genericDecl; + // Parser that matches any declaration type except those that have ordinals (since they are + // context-dependent). + + DeclParser fileLevelDecl; + DeclParser enumLevelDecl; + DeclParser structLevelDecl; + DeclParser interfaceLevelDecl; + // Parsers that match genericDecl *and* the ordinal-based declaration types valid in the given + // contexts. Note that these may match declarations that are not actually allowed in the given + // contexts, as long as the grammar is unambiguous. E.g. nested types are not allowed in + // enums, but they'll be accepted by enumLevelDecl. A later stage of compilation should report + // these as errors. + + Parser> expression; + Parser> annotation; + Parser> uid; + Parser> ordinal; + Parser> param; + + DeclParser usingDecl; + DeclParser constDecl; + DeclParser enumDecl; + DeclParser enumerantDecl; + DeclParser structDecl; + DeclParser fieldDecl; + DeclParser unionDecl; + DeclParser groupDecl; + DeclParser interfaceDecl; + DeclParser methodDecl; + DeclParser annotationDecl; + // Parsers for individual declaration types. + }; + + const Parsers& getParsers() { return parsers; } + +private: + Orphanage orphanage; + ErrorReporter& errorReporter; + kj::Arena arena; + Parsers parsers; +}; + +kj::String expressionString(Expression::Reader name); +// Stringify the expression as code. + +} // namespace compiler +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/compiler/resolver.h b/vendor/capnproto/src/capnp/compiler/resolver.h new file mode 100644 index 0000000..b4a3942 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/resolver.h @@ -0,0 +1,132 @@ +// Copyright (c) 2013-2020 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. + +#pragma once + +#include +#include +#include +#include + +CAPNP_BEGIN_HEADER + +namespace capnp { +namespace compiler { + +class Resolver { + // Callback class used to find other nodes relative to some existing node. + // + // `Resolver` is used when compiling one declaration requires inspecting the compiled versions + // of other declarations it depends on. For example, if struct type Foo contains a field of type + // Bar, and specifies a default value for that field, then to parse that default value we need + // the compiled version of `Bar`. Or, more commonly, if a struct type Foo refers to some other + // type `Bar.Baz`, this requires doing a lookup that depends on at least partial compilation of + // `Bar`, in order to discover its nested type `Baz`. + // + // Note that declarations are often compiled just-in-time the first time they are resolved. So, + // the methods of Resolver may recurse back into other parts of the compiler. It must detect when + // a dependency cycle occurs and report an error in order to prevent an infinite loop. + +public: + struct ResolvedDecl { + // Information about a resolved declaration. + + uint64_t id; + // Type ID / node ID of the resolved declaration. + + uint genericParamCount; + // If non-zero, the declaration is a generic with the given number of parameters. + + uint64_t scopeId; + // The ID of the parent scope of this declaration. + + Declaration::Which kind; + // What basic kind of declaration is this? E.g. struct, interface, const, etc. + + Resolver* resolver; + // `Resolver` instance that can be used to further resolve other declarations relative to this + // one. + + kj::Maybe brand; + // If present, then it is necessary to replace the brand scope with the given brand before + // using the target type. This happens when the decl resolved to an alias; all other fields + // of `ResolvedDecl` refer to the target of the alias, except for `scopeId` which is the + // scope that contained the alias. + }; + + struct ResolvedParameter { + uint64_t id; // ID of the node declaring the parameter. + uint index; // Index of the parameter. + }; + + typedef kj::OneOf ResolveResult; + + virtual kj::Maybe resolve(kj::StringPtr name) = 0; + // Look up the given name, relative to this node, and return basic information about the + // target. + + virtual kj::Maybe resolveMember(kj::StringPtr name) = 0; + // Look up a member of this node. + + virtual ResolvedDecl resolveBuiltin(Declaration::Which which) = 0; + virtual ResolvedDecl resolveId(uint64_t id) = 0; + + virtual kj::Maybe getParent() = 0; + // Returns the parent of this scope, or null if this is the top scope. + + virtual ResolvedDecl getTopScope() = 0; + // Get the top-level scope containing this node. + + virtual kj::Maybe resolveBootstrapSchema(uint64_t id, schema::Brand::Reader brand) = 0; + // Get the schema for the given ID. If a schema is returned, it must be safe to traverse its + // dependencies via the Schema API. A schema that is only at the bootstrap stage is + // acceptable. + // + // Throws an exception if the id is not one that was found by calling resolve() or by + // traversing other schemas. Returns null if the ID is recognized, but the corresponding + // schema node failed to be built for reasons that were already reported. + + virtual kj::Maybe resolveFinalSchema(uint64_t id) = 0; + // Get the final schema for the given ID. A bootstrap schema is not acceptable. A raw + // node reader is returned rather than a Schema object because using a Schema object built + // by the final schema loader could trigger lazy initialization of dependencies which could + // lead to a cycle and deadlock. + // + // Throws an exception if the id is not one that was found by calling resolve() or by + // traversing other schemas. Returns null if the ID is recognized, but the corresponding + // schema node failed to be built for reasons that were already reported. + + virtual kj::Maybe resolveImport(kj::StringPtr name) = 0; + // Get the ID of an imported file given the import path. + + virtual kj::Maybe> readEmbed(kj::StringPtr name) = 0; + // Read and return the contents of a file for an `embed` expression. + + virtual kj::Maybe resolveBootstrapType(schema::Type::Reader type, Schema scope) = 0; + // Compile a schema::Type into a Type whose dependencies may safely be traversed via the schema + // API. These dependencies may have only bootstrap schemas. Returns null if the type could not + // be constructed due to already-reported errors. +}; + +} // namespace compiler +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/compiler/type-id.c++ b/vendor/capnproto/src/capnp/compiler/type-id.c++ new file mode 100644 index 0000000..3cbbbc2 --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/type-id.c++ @@ -0,0 +1,414 @@ +// Copyright (c) 2013-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. + +#include "type-id.h" +#include +#include + +namespace capnp { +namespace compiler { + +class TypeIdGenerator { + // A non-cryptographic deterministic random number generator used to generate type IDs when the + // developer did not specify one themselves. + // + // The underlying algorithm is MD5. MD5 is safe to use here because this is not intended to be a + // cryptographic random number generator. In retrospect it would have been nice to use something + // else just to avoid people freaking out about it, but changing the algorithm now would break + // backwards-compatibility. + +public: + TypeIdGenerator(); + + void update(kj::ArrayPtr data); + inline void update(kj::ArrayPtr data) { + return update(data.asBytes()); + } + inline void update(kj::StringPtr data) { + return update(data.asArray()); + } + + kj::ArrayPtr finish(); + +private: + bool finished = false; + + struct { + uint lo, hi; + uint a, b, c, d; + kj::byte buffer[64]; + uint block[16]; + } ctx; + + const kj::byte* body(const kj::byte* ptr, size_t size); +}; + +uint64_t generateChildId(uint64_t parentId, kj::StringPtr childName) { + // Compute ID by hashing the concatenation of the parent ID and the declaration name, and + // then taking the first 8 bytes. + + kj::byte parentIdBytes[sizeof(uint64_t)]; + for (uint i = 0; i < sizeof(uint64_t); i++) { + parentIdBytes[i] = (parentId >> (i * 8)) & 0xff; + } + + TypeIdGenerator generator; + generator.update(kj::arrayPtr(parentIdBytes, kj::size(parentIdBytes))); + generator.update(childName); + + kj::ArrayPtr resultBytes = generator.finish(); + + uint64_t result = 0; + for (uint i = 0; i < sizeof(uint64_t); i++) { + result = (result << 8) | resultBytes[i]; + } + + return result | (1ull << 63); +} + +uint64_t generateGroupId(uint64_t parentId, uint16_t groupIndex) { + // Compute ID by hashing the concatenation of the parent ID and the group index, and + // then taking the first 8 bytes. + + kj::byte bytes[sizeof(uint64_t) + sizeof(uint16_t)]; + for (uint i = 0; i < sizeof(uint64_t); i++) { + bytes[i] = (parentId >> (i * 8)) & 0xff; + } + for (uint i = 0; i < sizeof(uint16_t); i++) { + bytes[sizeof(uint64_t) + i] = (groupIndex >> (i * 8)) & 0xff; + } + + TypeIdGenerator generator; + generator.update(bytes); + + kj::ArrayPtr resultBytes = generator.finish(); + + uint64_t result = 0; + for (uint i = 0; i < sizeof(uint64_t); i++) { + result = (result << 8) | resultBytes[i]; + } + + return result | (1ull << 63); +} + + + +// The remainder of this file was derived from code placed in the public domain. +// The original code bore the following notice: + +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +/* + * The basic MD5 functions. + * + * F and G are optimized compared to their RFC 1321 definitions for + * architectures that lack an AND-NOT instruction, just like in Colin Plumb's + * implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * The MD5 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(uint *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx.block[(n)] = \ + (uint)ptr[(n) * 4] | \ + ((uint)ptr[(n) * 4 + 1] << 8) | \ + ((uint)ptr[(n) * 4 + 2] << 16) | \ + ((uint)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx.block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There are no alignment requirements. + */ +const kj::byte* TypeIdGenerator::body(const kj::byte* ptr, size_t size) +{ + uint a, b, c, d; + uint saved_a, saved_b, saved_c, saved_d; + + a = ctx.a; + b = ctx.b; + c = ctx.c; + d = ctx.d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23) + +/* Round 4 */ + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while (size -= 64); + + ctx.a = a; + ctx.b = b; + ctx.c = c; + ctx.d = d; + + return ptr; +} + +TypeIdGenerator::TypeIdGenerator() +{ + ctx.a = 0x67452301; + ctx.b = 0xefcdab89; + ctx.c = 0x98badcfe; + ctx.d = 0x10325476; + + ctx.lo = 0; + ctx.hi = 0; +} + +void TypeIdGenerator::update(kj::ArrayPtr dataArray) +{ + KJ_REQUIRE(!finished, "already called TypeIdGenerator::finish()"); + + const kj::byte* data = dataArray.begin(); + unsigned long size = dataArray.size(); + + uint saved_lo; + unsigned long used, free; + + saved_lo = ctx.lo; + if ((ctx.lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx.hi++; + ctx.hi += size >> 29; + + used = saved_lo & 0x3f; + + if (used) { + free = 64 - used; + + if (size < free) { + memcpy(&ctx.buffer[used], data, size); + return; + } + + memcpy(&ctx.buffer[used], data, free); + data = data + free; + size -= free; + body(ctx.buffer, 64); + } + + if (size >= 64) { + data = body(data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx.buffer, data, size); +} + +kj::ArrayPtr TypeIdGenerator::finish() +{ + if (!finished) { + unsigned long used, free; + + used = ctx.lo & 0x3f; + + ctx.buffer[used++] = 0x80; + + free = 64 - used; + + if (free < 8) { + memset(&ctx.buffer[used], 0, free); + body(ctx.buffer, 64); + used = 0; + free = 64; + } + + memset(&ctx.buffer[used], 0, free - 8); + + ctx.lo <<= 3; + ctx.buffer[56] = ctx.lo; + ctx.buffer[57] = ctx.lo >> 8; + ctx.buffer[58] = ctx.lo >> 16; + ctx.buffer[59] = ctx.lo >> 24; + ctx.buffer[60] = ctx.hi; + ctx.buffer[61] = ctx.hi >> 8; + ctx.buffer[62] = ctx.hi >> 16; + ctx.buffer[63] = ctx.hi >> 24; + + body(ctx.buffer, 64); + + // Store final result into ctx.buffer. + ctx.buffer[0] = ctx.a; + ctx.buffer[1] = ctx.a >> 8; + ctx.buffer[2] = ctx.a >> 16; + ctx.buffer[3] = ctx.a >> 24; + ctx.buffer[4] = ctx.b; + ctx.buffer[5] = ctx.b >> 8; + ctx.buffer[6] = ctx.b >> 16; + ctx.buffer[7] = ctx.b >> 24; + ctx.buffer[8] = ctx.c; + ctx.buffer[9] = ctx.c >> 8; + ctx.buffer[10] = ctx.c >> 16; + ctx.buffer[11] = ctx.c >> 24; + ctx.buffer[12] = ctx.d; + ctx.buffer[13] = ctx.d >> 8; + ctx.buffer[14] = ctx.d >> 16; + ctx.buffer[15] = ctx.d >> 24; + + finished = true; + } + + return kj::arrayPtr(ctx.buffer, 16); +} + + +} // namespace compiler +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/compiler/type-id.h b/vendor/capnproto/src/capnp/compiler/type-id.h new file mode 100644 index 0000000..59d86db --- /dev/null +++ b/vendor/capnproto/src/capnp/compiler/type-id.h @@ -0,0 +1,45 @@ +// 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. + +#pragma once + +#include +#include +#include + +CAPNP_BEGIN_HEADER + +namespace capnp { +namespace compiler { + +uint64_t generateChildId(uint64_t parentId, kj::StringPtr childName); +uint64_t generateGroupId(uint64_t parentId, uint16_t groupIndex); +// Generate a default type ID for various symbols. These are used only if the developer did not +// specify an ID explicitly. +// +// The returned ID always has the most-significant bit set. The remaining bits are generated +// pseudo-randomly from the input using an algorithm that should produce a uniform distribution of +// IDs. + +} // namespace compiler +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/dynamic.c++ b/vendor/capnproto/src/capnp/dynamic.c++ new file mode 100644 index 0000000..904ab8e --- /dev/null +++ b/vendor/capnproto/src/capnp/dynamic.c++ @@ -0,0 +1,1830 @@ +// 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 "dynamic.h" +#include + +namespace capnp { + +namespace { + +bool hasDiscriminantValue(const schema::Field::Reader& reader) { + return reader.getDiscriminantValue() != schema::Field::NO_DISCRIMINANT; +} + +template +KJ_ALWAYS_INLINE(T bitCast(U value)); + +template +inline T bitCast(U value) { + static_assert(sizeof(T) == sizeof(U), "Size must match."); + return value; +} +template <> +inline float bitCast(uint32_t value) KJ_UNUSED; +template <> +inline float bitCast(uint32_t value) { + float result; + memcpy(&result, &value, sizeof(value)); + return result; +} +template <> +inline double bitCast(uint64_t value) KJ_UNUSED; +template <> +inline double bitCast(uint64_t value) { + double result; + memcpy(&result, &value, sizeof(value)); + return result; +} +template <> +inline uint32_t bitCast(float value) { + uint32_t result; + memcpy(&result, &value, sizeof(value)); + return result; +} +template <> +inline uint64_t bitCast(double value) { + uint64_t result; + memcpy(&result, &value, sizeof(value)); + return result; +} + +ElementSize elementSizeFor(schema::Type::Which elementType) { + switch (elementType) { + case schema::Type::VOID: return ElementSize::VOID; + case schema::Type::BOOL: return ElementSize::BIT; + case schema::Type::INT8: return ElementSize::BYTE; + case schema::Type::INT16: return ElementSize::TWO_BYTES; + case schema::Type::INT32: return ElementSize::FOUR_BYTES; + case schema::Type::INT64: return ElementSize::EIGHT_BYTES; + case schema::Type::UINT8: return ElementSize::BYTE; + case schema::Type::UINT16: return ElementSize::TWO_BYTES; + case schema::Type::UINT32: return ElementSize::FOUR_BYTES; + case schema::Type::UINT64: return ElementSize::EIGHT_BYTES; + case schema::Type::FLOAT32: return ElementSize::FOUR_BYTES; + case schema::Type::FLOAT64: return ElementSize::EIGHT_BYTES; + + case schema::Type::TEXT: return ElementSize::POINTER; + case schema::Type::DATA: return ElementSize::POINTER; + case schema::Type::LIST: return ElementSize::POINTER; + case schema::Type::ENUM: return ElementSize::TWO_BYTES; + case schema::Type::STRUCT: return ElementSize::INLINE_COMPOSITE; + case schema::Type::INTERFACE: return ElementSize::POINTER; + case schema::Type::ANY_POINTER: KJ_FAIL_ASSERT("List(AnyPointer) not supported."); break; + } + + // Unknown type. Treat it as zero-size. + return ElementSize::VOID; +} + +inline _::StructSize structSizeFromSchema(StructSchema schema) { + auto node = schema.getProto().getStruct(); + return _::StructSize( + bounded(node.getDataWordCount()) * WORDS, + bounded(node.getPointerCount()) * POINTERS); +} + +} // namespace + +// ======================================================================================= + +kj::Maybe DynamicEnum::getEnumerant() const { + auto enumerants = schema.getEnumerants(); + if (value < enumerants.size()) { + return enumerants[value]; + } else { + return nullptr; + } +} + +uint16_t DynamicEnum::asImpl(uint64_t requestedTypeId) const { + KJ_REQUIRE(requestedTypeId == schema.getProto().getId(), + "Type mismatch in DynamicEnum.as().") { + // use it anyway + break; + } + return value; +} + +// ======================================================================================= + +bool DynamicStruct::Reader::isSetInUnion(StructSchema::Field field) const { + auto proto = field.getProto(); + if (hasDiscriminantValue(proto)) { + uint16_t discrim = reader.getDataField( + assumeDataOffset(schema.getProto().getStruct().getDiscriminantOffset())); + return discrim == proto.getDiscriminantValue(); + } else { + return true; + } +} + +void DynamicStruct::Reader::verifySetInUnion(StructSchema::Field field) const { + KJ_REQUIRE(isSetInUnion(field), + "Tried to get() a union member which is not currently initialized.", + field.getProto().getName(), schema.getProto().getDisplayName()); +} + +bool DynamicStruct::Builder::isSetInUnion(StructSchema::Field field) { + auto proto = field.getProto(); + if (hasDiscriminantValue(proto)) { + uint16_t discrim = builder.getDataField( + assumeDataOffset(schema.getProto().getStruct().getDiscriminantOffset())); + return discrim == proto.getDiscriminantValue(); + } else { + return true; + } +} + +void DynamicStruct::Builder::verifySetInUnion(StructSchema::Field field) { + KJ_REQUIRE(isSetInUnion(field), + "Tried to get() a union member which is not currently initialized.", + field.getProto().getName(), schema.getProto().getDisplayName()); +} + +void DynamicStruct::Builder::setInUnion(StructSchema::Field field) { + // If a union member, set the discriminant to match. + auto proto = field.getProto(); + if (hasDiscriminantValue(proto)) { + builder.setDataField( + assumeDataOffset(schema.getProto().getStruct().getDiscriminantOffset()), + proto.getDiscriminantValue()); + } +} + +DynamicValue::Reader DynamicStruct::Reader::get(StructSchema::Field field) const { + KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); + verifySetInUnion(field); + + auto type = field.getType(); + auto proto = field.getProto(); + switch (proto.which()) { + case schema::Field::SLOT: { + auto slot = proto.getSlot(); + + // Note that the default value might be "anyPointer" even if the type is some pointer type + // *other than* anyPointer. This happens with generics -- the field is actually a generic + // parameter that has been bound, but the default value was of course compiled without any + // binding available. + auto dval = slot.getDefaultValue(); + + switch (type.which()) { + case schema::Type::VOID: + return reader.getDataField(assumeDataOffset(slot.getOffset())); + +#define HANDLE_TYPE(discrim, titleCase, type) \ + case schema::Type::discrim: \ + return reader.getDataField( \ + assumeDataOffset(slot.getOffset()), \ + bitCast<_::Mask>(dval.get##titleCase())); + + HANDLE_TYPE(BOOL, Bool, bool) + HANDLE_TYPE(INT8, Int8, int8_t) + HANDLE_TYPE(INT16, Int16, int16_t) + HANDLE_TYPE(INT32, Int32, int32_t) + HANDLE_TYPE(INT64, Int64, int64_t) + HANDLE_TYPE(UINT8, Uint8, uint8_t) + HANDLE_TYPE(UINT16, Uint16, uint16_t) + HANDLE_TYPE(UINT32, Uint32, uint32_t) + HANDLE_TYPE(UINT64, Uint64, uint64_t) + HANDLE_TYPE(FLOAT32, Float32, float) + HANDLE_TYPE(FLOAT64, Float64, double) + +#undef HANDLE_TYPE + + case schema::Type::ENUM: { + uint16_t typedDval = dval.getEnum(); + return DynamicEnum(type.asEnum(), + reader.getDataField(assumeDataOffset(slot.getOffset()), typedDval)); + } + + case schema::Type::TEXT: { + Text::Reader typedDval = dval.isAnyPointer() ? Text::Reader() : dval.getText(); + return reader.getPointerField(assumePointerOffset(slot.getOffset())) + .getBlob(typedDval.begin(), + assumeMax(typedDval.size()) * BYTES); + } + + case schema::Type::DATA: { + Data::Reader typedDval = dval.isAnyPointer() ? Data::Reader() : dval.getData(); + return reader.getPointerField(assumePointerOffset(slot.getOffset())) + .getBlob(typedDval.begin(), + assumeBits(typedDval.size()) * BYTES); + } + + case schema::Type::LIST: { + auto elementType = type.asList().getElementType(); + return DynamicList::Reader(type.asList(), + reader.getPointerField(assumePointerOffset(slot.getOffset())) + .getList(elementSizeFor(elementType.which()), dval.isAnyPointer() ? nullptr : + dval.getList().getAs<_::UncheckedMessage>())); + } + + case schema::Type::STRUCT: + return DynamicStruct::Reader(type.asStruct(), + reader.getPointerField(assumePointerOffset(slot.getOffset())) + .getStruct(dval.isAnyPointer() ? nullptr : + dval.getStruct().getAs<_::UncheckedMessage>())); + + case schema::Type::ANY_POINTER: + return AnyPointer::Reader(reader.getPointerField(assumePointerOffset(slot.getOffset()))); + + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interface values are not supported."); + } + + KJ_UNREACHABLE; + } + + case schema::Field::GROUP: + return DynamicStruct::Reader(type.asStruct(), reader); + } + + KJ_UNREACHABLE; +} + +DynamicValue::Builder DynamicStruct::Builder::get(StructSchema::Field field) { + KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); + verifySetInUnion(field); + + auto proto = field.getProto(); + auto type = field.getType(); + switch (proto.which()) { + case schema::Field::SLOT: { + auto slot = proto.getSlot(); + + // Note that the default value might be "anyPointer" even if the type is some pointer type + // *other than* anyPointer. This happens with generics -- the field is actually a generic + // parameter that has been bound, but the default value was of course compiled without any + // binding available. + auto dval = slot.getDefaultValue(); + + switch (type.which()) { + case schema::Type::VOID: + return builder.getDataField(assumeDataOffset(slot.getOffset())); + +#define HANDLE_TYPE(discrim, titleCase, type) \ + case schema::Type::discrim: \ + return builder.getDataField( \ + assumeDataOffset(slot.getOffset()), \ + bitCast<_::Mask>(dval.get##titleCase())); + + HANDLE_TYPE(BOOL, Bool, bool) + HANDLE_TYPE(INT8, Int8, int8_t) + HANDLE_TYPE(INT16, Int16, int16_t) + HANDLE_TYPE(INT32, Int32, int32_t) + HANDLE_TYPE(INT64, Int64, int64_t) + HANDLE_TYPE(UINT8, Uint8, uint8_t) + HANDLE_TYPE(UINT16, Uint16, uint16_t) + HANDLE_TYPE(UINT32, Uint32, uint32_t) + HANDLE_TYPE(UINT64, Uint64, uint64_t) + HANDLE_TYPE(FLOAT32, Float32, float) + HANDLE_TYPE(FLOAT64, Float64, double) + +#undef HANDLE_TYPE + + case schema::Type::ENUM: { + uint16_t typedDval = dval.getEnum(); + return DynamicEnum(type.asEnum(), + builder.getDataField(assumeDataOffset(slot.getOffset()), typedDval)); + } + + case schema::Type::TEXT: { + Text::Reader typedDval = dval.isAnyPointer() ? Text::Reader() : dval.getText(); + return builder.getPointerField(assumePointerOffset(slot.getOffset())) + .getBlob(typedDval.begin(), + assumeMax(typedDval.size()) * BYTES); + } + + case schema::Type::DATA: { + Data::Reader typedDval = dval.isAnyPointer() ? Data::Reader() : dval.getData(); + return builder.getPointerField(assumePointerOffset(slot.getOffset())) + .getBlob(typedDval.begin(), + assumeBits(typedDval.size()) * BYTES); + } + + case schema::Type::LIST: { + ListSchema listType = type.asList(); + if (listType.whichElementType() == schema::Type::STRUCT) { + return DynamicList::Builder(listType, + builder.getPointerField(assumePointerOffset(slot.getOffset())) + .getStructList(structSizeFromSchema(listType.getStructElementType()), + dval.isAnyPointer() ? nullptr : + dval.getList().getAs<_::UncheckedMessage>())); + } else { + return DynamicList::Builder(listType, + builder.getPointerField(assumePointerOffset(slot.getOffset())) + .getList(elementSizeFor(listType.whichElementType()), + dval.isAnyPointer() ? nullptr : + dval.getList().getAs<_::UncheckedMessage>())); + } + } + + case schema::Type::STRUCT: { + auto structSchema = type.asStruct(); + return DynamicStruct::Builder(structSchema, + builder.getPointerField(assumePointerOffset(slot.getOffset())) + .getStruct(structSizeFromSchema(structSchema), + dval.isAnyPointer() ? nullptr : + dval.getStruct().getAs<_::UncheckedMessage>())); + } + + case schema::Type::ANY_POINTER: + return AnyPointer::Builder( + builder.getPointerField(assumePointerOffset(slot.getOffset()))); + + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interface values are not supported."); + } + + KJ_UNREACHABLE; + } + + case schema::Field::GROUP: + return DynamicStruct::Builder(type.asStruct(), builder); + } + + KJ_UNREACHABLE; +} + +bool DynamicStruct::Reader::has(StructSchema::Field field, HasMode mode) const { + KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); + + auto proto = field.getProto(); + if (hasDiscriminantValue(proto)) { + uint16_t discrim = reader.getDataField( + assumeDataOffset(schema.getProto().getStruct().getDiscriminantOffset())); + if (discrim != proto.getDiscriminantValue()) { + // Field is not active in the union. + return false; + } + } + + switch (proto.which()) { + case schema::Field::SLOT: + // Continue to below. + break; + + case schema::Field::GROUP: + return true; + } + + auto slot = proto.getSlot(); + auto type = field.getType(); + + switch (type.which()) { + case schema::Type::VOID: + // Void is always equal to the default. + return mode == HasMode::NON_NULL; + + case schema::Type::BOOL: + return mode == HasMode::NON_NULL || + reader.getDataField(assumeDataOffset(slot.getOffset()), 0) != 0; + + case schema::Type::INT8: + case schema::Type::UINT8: + return mode == HasMode::NON_NULL || + reader.getDataField(assumeDataOffset(slot.getOffset()), 0) != 0; + + case schema::Type::INT16: + case schema::Type::UINT16: + case schema::Type::ENUM: + return mode == HasMode::NON_NULL || + reader.getDataField(assumeDataOffset(slot.getOffset()), 0) != 0; + + case schema::Type::INT32: + case schema::Type::UINT32: + case schema::Type::FLOAT32: + return mode == HasMode::NON_NULL || + reader.getDataField(assumeDataOffset(slot.getOffset()), 0) != 0; + + case schema::Type::INT64: + case schema::Type::UINT64: + case schema::Type::FLOAT64: + return mode == HasMode::NON_NULL || + reader.getDataField(assumeDataOffset(slot.getOffset()), 0) != 0; + + case schema::Type::TEXT: + case schema::Type::DATA: + case schema::Type::LIST: + case schema::Type::STRUCT: + case schema::Type::ANY_POINTER: + case schema::Type::INTERFACE: + return !reader.getPointerField(assumePointerOffset(slot.getOffset())).isNull(); + } + + // Unknown type. As far as we know, it isn't set. + return false; +} + +kj::Maybe DynamicStruct::Reader::which() const { + auto structProto = schema.getProto().getStruct(); + if (structProto.getDiscriminantCount() == 0) { + return nullptr; + } + + uint16_t discrim = reader.getDataField( + assumeDataOffset(structProto.getDiscriminantOffset())); + return schema.getFieldByDiscriminant(discrim); +} + +kj::Maybe DynamicStruct::Builder::which() { + auto structProto = schema.getProto().getStruct(); + if (structProto.getDiscriminantCount() == 0) { + return nullptr; + } + + uint16_t discrim = builder.getDataField( + assumeDataOffset(structProto.getDiscriminantOffset())); + return schema.getFieldByDiscriminant(discrim); +} + +void DynamicStruct::Builder::set(StructSchema::Field field, const DynamicValue::Reader& value) { + KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); + setInUnion(field); + + auto proto = field.getProto(); + auto type = field.getType(); + switch (proto.which()) { + case schema::Field::SLOT: { + auto slot = proto.getSlot(); + auto dval = slot.getDefaultValue(); + + switch (type.which()) { + case schema::Type::VOID: + builder.setDataField(assumeDataOffset(slot.getOffset()), value.as()); + return; + +#define HANDLE_TYPE(discrim, titleCase, type) \ + case schema::Type::discrim: \ + builder.setDataField( \ + assumeDataOffset(slot.getOffset()), value.as(), \ + bitCast<_::Mask >(dval.get##titleCase())); \ + return; + + HANDLE_TYPE(BOOL, Bool, bool) + HANDLE_TYPE(INT8, Int8, int8_t) + HANDLE_TYPE(INT16, Int16, int16_t) + HANDLE_TYPE(INT32, Int32, int32_t) + HANDLE_TYPE(INT64, Int64, int64_t) + HANDLE_TYPE(UINT8, Uint8, uint8_t) + HANDLE_TYPE(UINT16, Uint16, uint16_t) + HANDLE_TYPE(UINT32, Uint32, uint32_t) + HANDLE_TYPE(UINT64, Uint64, uint64_t) + HANDLE_TYPE(FLOAT32, Float32, float) + HANDLE_TYPE(FLOAT64, Float64, double) + +#undef HANDLE_TYPE + + case schema::Type::ENUM: { + uint16_t rawValue; + auto enumSchema = type.asEnum(); + if (value.getType() == DynamicValue::TEXT) { + // Convert from text. + rawValue = enumSchema.getEnumerantByName(value.as()).getOrdinal(); + } else if (value.getType() == DynamicValue::INT || + value.getType() == DynamicValue::UINT) { + rawValue = value.as(); + } else { + DynamicEnum enumValue = value.as(); + KJ_REQUIRE(enumValue.getSchema() == enumSchema, "Value type mismatch.") { + return; + } + rawValue = enumValue.getRaw(); + } + builder.setDataField(assumeDataOffset(slot.getOffset()), rawValue, + dval.getEnum()); + return; + } + + case schema::Type::TEXT: + builder.getPointerField(assumePointerOffset(slot.getOffset())) + .setBlob(value.as()); + return; + + case schema::Type::DATA: + builder.getPointerField(assumePointerOffset(slot.getOffset())) + .setBlob(value.as()); + return; + + case schema::Type::LIST: { + ListSchema listType = type.asList(); + auto listValue = value.as(); + KJ_REQUIRE(listValue.getSchema() == listType, "Value type mismatch.") { + return; + } + builder.getPointerField(assumePointerOffset(slot.getOffset())) + .setList(listValue.reader); + return; + } + + case schema::Type::STRUCT: { + auto structType = type.asStruct(); + auto structValue = value.as(); + KJ_REQUIRE(structValue.getSchema() == structType, "Value type mismatch.") { + return; + } + builder.getPointerField(assumePointerOffset(slot.getOffset())) + .setStruct(structValue.reader); + return; + } + + case schema::Type::ANY_POINTER: { + auto target = AnyPointer::Builder( + builder.getPointerField(assumePointerOffset(slot.getOffset()))); + + switch (value.getType()) { + case DynamicValue::Type::TEXT: + target.setAs(value.as()); + return; + case DynamicValue::Type::DATA: + target.setAs(value.as()); + return; + case DynamicValue::Type::LIST: + target.setAs(value.as()); + return; + case DynamicValue::Type::STRUCT: + target.setAs(value.as()); + return; + case DynamicValue::Type::ANY_POINTER: + target.set(value.as()); + return; + + case DynamicValue::Type::UNKNOWN: + case DynamicValue::Type::VOID: + case DynamicValue::Type::BOOL: + case DynamicValue::Type::INT: + case DynamicValue::Type::UINT: + case DynamicValue::Type::FLOAT: + case DynamicValue::Type::ENUM: + KJ_FAIL_ASSERT("Value type mismatch; expected AnyPointer"); + } + + KJ_UNREACHABLE; + } + + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interface values are not supported."); + } + + KJ_UNREACHABLE; + } + + case schema::Field::GROUP: { + auto src = value.as(); + auto dst = init(field).as(); + + KJ_IF_MAYBE(unionField, src.which()) { + dst.set(*unionField, src.get(*unionField)); + } + + for (auto field: src.schema.getNonUnionFields()) { + if (src.has(field)) { + dst.set(field, src.get(field)); + } + } + + return; + } + } + + KJ_UNREACHABLE; +} + +DynamicValue::Builder DynamicStruct::Builder::init(StructSchema::Field field) { + KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); + setInUnion(field); + + auto proto = field.getProto(); + auto type = field.getType(); + + switch (proto.which()) { + case schema::Field::SLOT: { + auto slot = proto.getSlot(); + switch (type.which()) { + case schema::Type::STRUCT: { + auto subSchema = type.asStruct(); + return DynamicStruct::Builder(subSchema, + builder.getPointerField(assumePointerOffset(slot.getOffset())) + .initStruct(structSizeFromSchema(subSchema))); + } + case schema::Type::ANY_POINTER: { + auto pointer = builder.getPointerField(assumePointerOffset(slot.getOffset())); + pointer.clear(); + return AnyPointer::Builder(pointer); + } + default: + KJ_FAIL_REQUIRE("init() without a size is only valid for struct and object fields."); + } + } + + case schema::Field::GROUP: { + clear(field); + return DynamicStruct::Builder(type.asStruct(), builder); + } + } + + KJ_UNREACHABLE; +} + +DynamicValue::Builder DynamicStruct::Builder::init(StructSchema::Field field, uint size) { + KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); + setInUnion(field); + + auto proto = field.getProto(); + auto type = field.getType(); + + switch (proto.which()) { + case schema::Field::SLOT: { + auto slot = proto.getSlot(); + switch (type.which()) { + case schema::Type::LIST: { + auto listType = type.asList(); + if (listType.whichElementType() == schema::Type::STRUCT) { + return DynamicList::Builder(listType, + builder.getPointerField(assumePointerOffset(slot.getOffset())) + .initStructList(bounded(size) * ELEMENTS, + structSizeFromSchema(listType.getStructElementType()))); + } else { + return DynamicList::Builder(listType, + builder.getPointerField(assumePointerOffset(slot.getOffset())) + .initList(elementSizeFor(listType.whichElementType()), + bounded(size) * ELEMENTS)); + } + } + case schema::Type::TEXT: + return builder.getPointerField(assumePointerOffset(slot.getOffset())) + .initBlob(bounded(size) * BYTES); + case schema::Type::DATA: + return builder.getPointerField(assumePointerOffset(slot.getOffset())) + .initBlob(bounded(size) * BYTES); + default: + KJ_FAIL_REQUIRE( + "init() with size is only valid for list, text, or data fields.", + (uint)type.which()); + break; + } + KJ_UNREACHABLE; + } + + case schema::Field::GROUP: + KJ_FAIL_REQUIRE("init() with size is only valid for list, text, or data fields."); + } + + KJ_UNREACHABLE; +} + +void DynamicStruct::Builder::adopt(StructSchema::Field field, Orphan&& orphan) { + KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); + setInUnion(field); + + auto proto = field.getProto(); + switch (proto.which()) { + case schema::Field::SLOT: { + auto slot = proto.getSlot(); + auto type = field.getType(); + + switch (type.which()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::ENUM: + set(field, orphan.getReader()); + return; + + case schema::Type::TEXT: + KJ_REQUIRE(orphan.getType() == DynamicValue::TEXT, "Value type mismatch."); + break; + + case schema::Type::DATA: + KJ_REQUIRE(orphan.getType() == DynamicValue::DATA, "Value type mismatch."); + break; + + case schema::Type::LIST: { + ListSchema listType = type.asList(); + KJ_REQUIRE(orphan.getType() == DynamicValue::LIST && orphan.listSchema == listType, + "Value type mismatch.") { + return; + } + break; + } + + case schema::Type::STRUCT: { + auto structType = type.asStruct(); + KJ_REQUIRE(orphan.getType() == DynamicValue::STRUCT && orphan.structSchema == structType, + "Value type mismatch.") { + return; + } + break; + } + + case schema::Type::ANY_POINTER: + KJ_REQUIRE(orphan.getType() == DynamicValue::STRUCT || + orphan.getType() == DynamicValue::LIST || + orphan.getType() == DynamicValue::TEXT || + orphan.getType() == DynamicValue::DATA || + orphan.getType() == DynamicValue::ANY_POINTER, + "Value type mismatch.") { + return; + } + break; + + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interface values are not supported."); + } + + builder.getPointerField(assumePointerOffset(slot.getOffset())).adopt(kj::mv(orphan.builder)); + return; + } + + case schema::Field::GROUP: + // Have to transfer fields. + auto src = orphan.get().as(); + auto dst = init(field).as(); + + KJ_REQUIRE(orphan.getType() == DynamicValue::STRUCT && orphan.structSchema == dst.getSchema(), + "Value type mismatch."); + + KJ_IF_MAYBE(unionField, src.which()) { + dst.adopt(*unionField, src.disown(*unionField)); + } + + for (auto field: src.schema.getNonUnionFields()) { + if (src.has(field)) { + dst.adopt(field, src.disown(field)); + } + } + + return; + } + + KJ_UNREACHABLE; +} + +Orphan DynamicStruct::Builder::disown(StructSchema::Field field) { + // We end up calling get(field) below, so we don't need to validate `field` here. + + auto proto = field.getProto(); + switch (proto.which()) { + case schema::Field::SLOT: { + auto slot = proto.getSlot(); + + switch (field.getType().which()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::ENUM: { + auto result = Orphan(get(field), _::OrphanBuilder()); + clear(field); + return kj::mv(result); + } + + case schema::Type::TEXT: + case schema::Type::DATA: + case schema::Type::LIST: + case schema::Type::STRUCT: + case schema::Type::ANY_POINTER: + case schema::Type::INTERFACE: { + auto value = get(field); + return Orphan( + value, builder.getPointerField(assumePointerOffset(slot.getOffset())).disown()); + } + } + KJ_UNREACHABLE; + } + + case schema::Field::GROUP: { + // We have to allocate new space for the group, unfortunately. + auto src = get(field).as(); + + Orphan result = + Orphanage::getForMessageContaining(*this).newOrphan(src.getSchema()); + auto dst = result.get(); + + KJ_IF_MAYBE(unionField, src.which()) { + dst.adopt(*unionField, src.disown(*unionField)); + } + + // We need to explicitly reset the union to its default field. + KJ_IF_MAYBE(unionField, src.schema.getFieldByDiscriminant(0)) { + src.clear(*unionField); + } + + for (auto field: src.schema.getNonUnionFields()) { + if (src.has(field)) { + dst.adopt(field, src.disown(field)); + } + } + + return kj::mv(result); + } + } + + KJ_UNREACHABLE; +} + +void DynamicStruct::Builder::clear(StructSchema::Field field) { + KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); + setInUnion(field); + + auto proto = field.getProto(); + auto type = field.getType(); + switch (proto.which()) { + case schema::Field::SLOT: { + auto slot = proto.getSlot(); + + switch (type.which()) { + case schema::Type::VOID: + builder.setDataField(assumeDataOffset(slot.getOffset()), VOID); + return; + +#define HANDLE_TYPE(discrim, type) \ + case schema::Type::discrim: \ + builder.setDataField(assumeDataOffset(slot.getOffset()), 0); \ + return; + + HANDLE_TYPE(BOOL, bool) + HANDLE_TYPE(INT8, uint8_t) + HANDLE_TYPE(INT16, uint16_t) + HANDLE_TYPE(INT32, uint32_t) + HANDLE_TYPE(INT64, uint64_t) + HANDLE_TYPE(UINT8, uint8_t) + HANDLE_TYPE(UINT16, uint16_t) + HANDLE_TYPE(UINT32, uint32_t) + HANDLE_TYPE(UINT64, uint64_t) + HANDLE_TYPE(FLOAT32, uint32_t) + HANDLE_TYPE(FLOAT64, uint64_t) + HANDLE_TYPE(ENUM, uint16_t) + +#undef HANDLE_TYPE + + case schema::Type::TEXT: + case schema::Type::DATA: + case schema::Type::LIST: + case schema::Type::STRUCT: + case schema::Type::ANY_POINTER: + case schema::Type::INTERFACE: + builder.getPointerField(assumePointerOffset(slot.getOffset())).clear(); + return; + } + + KJ_UNREACHABLE; + } + + case schema::Field::GROUP: { + DynamicStruct::Builder group(type.asStruct(), builder); + + // We clear the union field with discriminant 0 rather than the one that is set because + // we want the union to end up with its default field active. + KJ_IF_MAYBE(unionField, group.schema.getFieldByDiscriminant(0)) { + group.clear(*unionField); + } + + for (auto subField: group.schema.getNonUnionFields()) { + group.clear(subField); + } + return; + } + } + + KJ_UNREACHABLE; +} + +DynamicValue::Reader DynamicStruct::Reader::get(kj::StringPtr name) const { + return get(schema.getFieldByName(name)); +} +DynamicValue::Builder DynamicStruct::Builder::get(kj::StringPtr name) { + return get(schema.getFieldByName(name)); +} +bool DynamicStruct::Reader::has(kj::StringPtr name, HasMode mode) const { + return has(schema.getFieldByName(name), mode); +} +bool DynamicStruct::Builder::has(kj::StringPtr name, HasMode mode) { + return has(schema.getFieldByName(name), mode); +} +void DynamicStruct::Builder::set(kj::StringPtr name, const DynamicValue::Reader& value) { + set(schema.getFieldByName(name), value); +} +void DynamicStruct::Builder::set(kj::StringPtr name, + std::initializer_list value) { + auto list = init(name, value.size()).as(); + uint i = 0; + for (auto element: value) { + list.set(i++, element); + } +} +DynamicValue::Builder DynamicStruct::Builder::init(kj::StringPtr name) { + return init(schema.getFieldByName(name)); +} +DynamicValue::Builder DynamicStruct::Builder::init(kj::StringPtr name, uint size) { + return init(schema.getFieldByName(name), size); +} +void DynamicStruct::Builder::adopt(kj::StringPtr name, Orphan&& orphan) { + adopt(schema.getFieldByName(name), kj::mv(orphan)); +} +Orphan DynamicStruct::Builder::disown(kj::StringPtr name) { + return disown(schema.getFieldByName(name)); +} +void DynamicStruct::Builder::clear(kj::StringPtr name) { + clear(schema.getFieldByName(name)); +} + +// ======================================================================================= + +DynamicValue::Reader DynamicList::Reader::operator[](uint index) const { + KJ_REQUIRE(index < size(), "List index out-of-bounds."); + + switch (schema.whichElementType()) { +#define HANDLE_TYPE(name, discrim, typeName) \ + case schema::Type::discrim: \ + return reader.getDataElement(bounded(index) * ELEMENTS); + + HANDLE_TYPE(void, VOID, Void) + HANDLE_TYPE(bool, BOOL, bool) + HANDLE_TYPE(int8, INT8, int8_t) + HANDLE_TYPE(int16, INT16, int16_t) + HANDLE_TYPE(int32, INT32, int32_t) + HANDLE_TYPE(int64, INT64, int64_t) + HANDLE_TYPE(uint8, UINT8, uint8_t) + HANDLE_TYPE(uint16, UINT16, uint16_t) + HANDLE_TYPE(uint32, UINT32, uint32_t) + HANDLE_TYPE(uint64, UINT64, uint64_t) + HANDLE_TYPE(float32, FLOAT32, float) + HANDLE_TYPE(float64, FLOAT64, double) +#undef HANDLE_TYPE + + case schema::Type::TEXT: + return reader.getPointerElement(bounded(index) * ELEMENTS) + .getBlob(nullptr, ZERO * BYTES); + case schema::Type::DATA: + return reader.getPointerElement(bounded(index) * ELEMENTS) + .getBlob(nullptr, ZERO * BYTES); + + case schema::Type::LIST: { + auto elementType = schema.getListElementType(); + return DynamicList::Reader(elementType, + reader.getPointerElement(bounded(index) * ELEMENTS) + .getList(elementSizeFor(elementType.whichElementType()), nullptr)); + } + + case schema::Type::STRUCT: + return DynamicStruct::Reader(schema.getStructElementType(), + reader.getStructElement(bounded(index) * ELEMENTS)); + + case schema::Type::ENUM: + return DynamicEnum(schema.getEnumElementType(), + reader.getDataElement(bounded(index) * ELEMENTS)); + + case schema::Type::ANY_POINTER: + return AnyPointer::Reader(reader.getPointerElement(bounded(index) * ELEMENTS)); + + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interface values are not supported."); + } + + return nullptr; +} + +DynamicValue::Builder DynamicList::Builder::operator[](uint index) { + KJ_REQUIRE(index < size(), "List index out-of-bounds."); + + switch (schema.whichElementType()) { +#define HANDLE_TYPE(name, discrim, typeName) \ + case schema::Type::discrim: \ + return builder.getDataElement(bounded(index) * ELEMENTS); + + HANDLE_TYPE(void, VOID, Void) + HANDLE_TYPE(bool, BOOL, bool) + HANDLE_TYPE(int8, INT8, int8_t) + HANDLE_TYPE(int16, INT16, int16_t) + HANDLE_TYPE(int32, INT32, int32_t) + HANDLE_TYPE(int64, INT64, int64_t) + HANDLE_TYPE(uint8, UINT8, uint8_t) + HANDLE_TYPE(uint16, UINT16, uint16_t) + HANDLE_TYPE(uint32, UINT32, uint32_t) + HANDLE_TYPE(uint64, UINT64, uint64_t) + HANDLE_TYPE(float32, FLOAT32, float) + HANDLE_TYPE(float64, FLOAT64, double) +#undef HANDLE_TYPE + + case schema::Type::TEXT: + return builder.getPointerElement(bounded(index) * ELEMENTS) + .getBlob(nullptr, ZERO * BYTES); + case schema::Type::DATA: + return builder.getPointerElement(bounded(index) * ELEMENTS) + .getBlob(nullptr, ZERO * BYTES); + + case schema::Type::LIST: { + ListSchema elementType = schema.getListElementType(); + if (elementType.whichElementType() == schema::Type::STRUCT) { + return DynamicList::Builder(elementType, + builder.getPointerElement(bounded(index) * ELEMENTS) + .getStructList(structSizeFromSchema(elementType.getStructElementType()), + nullptr)); + } else { + return DynamicList::Builder(elementType, + builder.getPointerElement(bounded(index) * ELEMENTS) + .getList(elementSizeFor(elementType.whichElementType()), nullptr)); + } + } + + case schema::Type::STRUCT: + return DynamicStruct::Builder(schema.getStructElementType(), + builder.getStructElement(bounded(index) * ELEMENTS)); + + case schema::Type::ENUM: + return DynamicEnum(schema.getEnumElementType(), + builder.getDataElement(bounded(index) * ELEMENTS)); + + case schema::Type::ANY_POINTER: + KJ_FAIL_ASSERT("List(AnyPointer) not supported."); + return nullptr; + + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interface values are not supported."); + } + + return nullptr; +} + +void DynamicList::Builder::set(uint index, const DynamicValue::Reader& value) { + KJ_REQUIRE(index < size(), "List index out-of-bounds.") { + return; + } + + switch (schema.whichElementType()) { +#define HANDLE_TYPE(name, discrim, typeName) \ + case schema::Type::discrim: \ + builder.setDataElement(bounded(index) * ELEMENTS, value.as()); \ + return; + + HANDLE_TYPE(void, VOID, Void) + HANDLE_TYPE(bool, BOOL, bool) + HANDLE_TYPE(int8, INT8, int8_t) + HANDLE_TYPE(int16, INT16, int16_t) + HANDLE_TYPE(int32, INT32, int32_t) + HANDLE_TYPE(int64, INT64, int64_t) + HANDLE_TYPE(uint8, UINT8, uint8_t) + HANDLE_TYPE(uint16, UINT16, uint16_t) + HANDLE_TYPE(uint32, UINT32, uint32_t) + HANDLE_TYPE(uint64, UINT64, uint64_t) + HANDLE_TYPE(float32, FLOAT32, float) + HANDLE_TYPE(float64, FLOAT64, double) +#undef HANDLE_TYPE + + case schema::Type::TEXT: + builder.getPointerElement(bounded(index) * ELEMENTS).setBlob(value.as()); + return; + case schema::Type::DATA: + builder.getPointerElement(bounded(index) * ELEMENTS).setBlob(value.as()); + return; + + case schema::Type::LIST: { + auto listValue = value.as(); + KJ_REQUIRE(listValue.getSchema() == schema.getListElementType(), "Value type mismatch.") { + return; + } + builder.getPointerElement(bounded(index) * ELEMENTS).setList(listValue.reader); + return; + } + + case schema::Type::STRUCT: { + auto structValue = value.as(); + KJ_REQUIRE(structValue.getSchema() == schema.getStructElementType(), "Value type mismatch.") { + return; + } + builder.getStructElement(bounded(index) * ELEMENTS).copyContentFrom(structValue.reader); + return; + } + + case schema::Type::ENUM: { + uint16_t rawValue; + if (value.getType() == DynamicValue::TEXT) { + // Convert from text. + rawValue = schema.getEnumElementType().getEnumerantByName(value.as()).getOrdinal(); + } else { + DynamicEnum enumValue = value.as(); + KJ_REQUIRE(schema.getEnumElementType() == enumValue.getSchema(), + "Type mismatch when using DynamicList::Builder::set().") { + return; + } + rawValue = enumValue.getRaw(); + } + builder.setDataElement(bounded(index) * ELEMENTS, rawValue); + return; + } + + case schema::Type::ANY_POINTER: + KJ_FAIL_ASSERT("List(AnyPointer) not supported.") { + return; + } + + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interface values are not supported."); + } + + KJ_FAIL_REQUIRE("can't set element of unknown type", (uint)schema.whichElementType()) { + return; + } +} + +DynamicValue::Builder DynamicList::Builder::init(uint index, uint size) { + KJ_REQUIRE(index < this->size(), "List index out-of-bounds."); + + switch (schema.whichElementType()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::ENUM: + case schema::Type::STRUCT: + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Expected a list or blob."); + return nullptr; + + case schema::Type::TEXT: + return builder.getPointerElement(bounded(index) * ELEMENTS) + .initBlob(bounded(size) * BYTES); + + case schema::Type::DATA: + return builder.getPointerElement(bounded(index) * ELEMENTS) + .initBlob(bounded(size) * BYTES); + + case schema::Type::LIST: { + auto elementType = schema.getListElementType(); + + if (elementType.whichElementType() == schema::Type::STRUCT) { + return DynamicList::Builder(elementType, + builder.getPointerElement(bounded(index) * ELEMENTS) + .initStructList(bounded(size) * ELEMENTS, + structSizeFromSchema(elementType.getStructElementType()))); + } else { + return DynamicList::Builder(elementType, + builder.getPointerElement(bounded(index) * ELEMENTS) + .initList(elementSizeFor(elementType.whichElementType()), + bounded(size) * ELEMENTS)); + } + } + + case schema::Type::ANY_POINTER: { + KJ_FAIL_ASSERT("List(AnyPointer) not supported."); + return nullptr; + } + } + + return nullptr; +} + +void DynamicList::Builder::adopt(uint index, Orphan&& orphan) { + switch (schema.whichElementType()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::ENUM: + set(index, orphan.getReader()); + return; + + case schema::Type::TEXT: + KJ_REQUIRE(orphan.getType() == DynamicValue::TEXT, "Value type mismatch."); + builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(orphan.builder)); + return; + + case schema::Type::DATA: + KJ_REQUIRE(orphan.getType() == DynamicValue::DATA, "Value type mismatch."); + builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(orphan.builder)); + return; + + case schema::Type::LIST: { + ListSchema elementType = schema.getListElementType(); + KJ_REQUIRE(orphan.getType() == DynamicValue::LIST && orphan.listSchema == elementType, + "Value type mismatch."); + builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(orphan.builder)); + return; + } + + case schema::Type::STRUCT: { + auto elementType = schema.getStructElementType(); + KJ_REQUIRE(orphan.getType() == DynamicValue::STRUCT && orphan.structSchema == elementType, + "Value type mismatch."); + builder.getStructElement(bounded(index) * ELEMENTS).transferContentFrom( + orphan.builder.asStruct(structSizeFromSchema(elementType))); + return; + } + + case schema::Type::ANY_POINTER: + KJ_FAIL_ASSERT("List(AnyPointer) not supported."); + + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interface values are not supported."); + } + + KJ_UNREACHABLE; +} + +Orphan DynamicList::Builder::disown(uint index) { + switch (schema.whichElementType()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::ENUM: { + auto result = Orphan(operator[](index), _::OrphanBuilder()); + switch (elementSizeFor(schema.whichElementType())) { + case ElementSize::VOID: break; + case ElementSize::BIT: builder.setDataElement(bounded(index) * ELEMENTS, false); break; + case ElementSize::BYTE: builder.setDataElement(bounded(index) * ELEMENTS, 0); break; + case ElementSize::TWO_BYTES: builder.setDataElement(bounded(index) * ELEMENTS, 0); break; + case ElementSize::FOUR_BYTES: builder.setDataElement(bounded(index) * ELEMENTS, 0); break; + case ElementSize::EIGHT_BYTES: builder.setDataElement(bounded(index) * ELEMENTS, 0);break; + + case ElementSize::POINTER: + case ElementSize::INLINE_COMPOSITE: + KJ_UNREACHABLE; + } + return kj::mv(result); + } + + case schema::Type::TEXT: + case schema::Type::DATA: + case schema::Type::LIST: + case schema::Type::ANY_POINTER: + case schema::Type::INTERFACE: { + auto value = operator[](index); + return Orphan(value, builder.getPointerElement(bounded(index) * ELEMENTS).disown()); + } + + case schema::Type::STRUCT: { + // We have to make a copy. + Orphan result = + Orphanage::getForMessageContaining(*this).newOrphan(schema.getStructElementType()); + auto element = builder.getStructElement(bounded(index) * ELEMENTS); + result.get().builder.transferContentFrom(element); + element.clearAll(); + return kj::mv(result); + } + } + KJ_UNREACHABLE; +} + +void DynamicList::Builder::copyFrom(std::initializer_list value) { + KJ_REQUIRE(value.size() == size(), "DynamicList::copyFrom() argument had different size."); + uint i = 0; + for (auto element: value) { + set(i++, element); + } +} + +DynamicList::Reader DynamicList::Builder::asReader() const { + return DynamicList::Reader(schema, builder.asReader()); +} + +// ======================================================================================= + +DynamicValue::Reader::Reader(ConstSchema constant): type(VOID) { + auto type = constant.getType(); + auto value = constant.getProto().getConst().getValue(); + switch (type.which()) { + case schema::Type::VOID: *this = capnp::VOID; break; + case schema::Type::BOOL: *this = value.getBool(); break; + case schema::Type::INT8: *this = value.getInt8(); break; + case schema::Type::INT16: *this = value.getInt16(); break; + case schema::Type::INT32: *this = value.getInt32(); break; + case schema::Type::INT64: *this = value.getInt64(); break; + case schema::Type::UINT8: *this = value.getUint8(); break; + case schema::Type::UINT16: *this = value.getUint16(); break; + case schema::Type::UINT32: *this = value.getUint32(); break; + case schema::Type::UINT64: *this = value.getUint64(); break; + case schema::Type::FLOAT32: *this = value.getFloat32(); break; + case schema::Type::FLOAT64: *this = value.getFloat64(); break; + case schema::Type::TEXT: *this = value.getText(); break; + case schema::Type::DATA: *this = value.getData(); break; + + case schema::Type::ENUM: + *this = DynamicEnum(type.asEnum(), value.getEnum()); + break; + + case schema::Type::STRUCT: + *this = value.getStruct().getAs(type.asStruct()); + break; + + case schema::Type::LIST: + *this = value.getList().getAs(type.asList()); + break; + + case schema::Type::ANY_POINTER: + *this = value.getAnyPointer(); + break; + + case schema::Type::INTERFACE: + KJ_FAIL_ASSERT("Constants can't have interface type."); + } +} + +DynamicValue::Reader DynamicValue::Builder::asReader() const { + switch (type) { + case UNKNOWN: return Reader(); + case VOID: return Reader(voidValue); + case BOOL: return Reader(boolValue); + case INT: return Reader(intValue); + case UINT: return Reader(uintValue); + case FLOAT: return Reader(floatValue); + case TEXT: return Reader(textValue.asReader()); + case DATA: return Reader(dataValue.asReader()); + case LIST: return Reader(listValue.asReader()); + case ENUM: return Reader(enumValue); + case STRUCT: return Reader(structValue.asReader()); + case ANY_POINTER: return Reader(anyPointerValue.asReader()); + } + KJ_FAIL_ASSERT("Missing switch case."); + return Reader(); +} + +namespace { + +template +T signedToUnsigned(long long value) { + KJ_REQUIRE(value >= 0 && T(value) == value, "Value out-of-range for requested type.", value) { + // Use it anyway. + break; + } + return value; +} + +template <> +uint64_t signedToUnsigned(long long value) { + KJ_REQUIRE(value >= 0, "Value out-of-range for requested type.", value) { + // Use it anyway. + break; + } + return value; +} + +template +T unsignedToSigned(unsigned long long value) { + KJ_REQUIRE(T(value) >= 0 && (unsigned long long)T(value) == value, + "Value out-of-range for requested type.", value) { + // Use it anyway. + break; + } + return value; +} + +template <> +int64_t unsignedToSigned(unsigned long long value) { + KJ_REQUIRE(int64_t(value) >= 0, "Value out-of-range for requested type.", value) { + // Use it anyway. + break; + } + return value; +} + +template +T checkRoundTrip(U value) { + T result = value; + KJ_REQUIRE(U(result) == value, "Value out-of-range for requested type.", value) { + // Use it anyway. + break; + } + return result; +} + +template +T checkRoundTripFromFloat(U value) { + // When `U` is `float` or `double`, we have to use a different approach, because casting an + // out-of-range float to an integer is, surprisingly, UB. + constexpr T MIN = kj::minValue; + constexpr T MAX = kj::maxValue; + KJ_REQUIRE(value >= U(MIN), "Value out-of-range for requested type.", value) { + return MIN; + } + KJ_REQUIRE(value <= U(MAX), "Value out-of-range for requested type.", value) { + return MAX; + } + T result = value; + KJ_REQUIRE(U(result) == value, "Value out-of-range for requested type.", value) { + // Use it anyway. + break; + } + return result; +} + +} // namespace + +#define HANDLE_NUMERIC_TYPE(typeName, ifInt, ifUint, ifFloat) \ +typeName DynamicValue::Reader::AsImpl::apply(const Reader& reader) { \ + switch (reader.type) { \ + case INT: \ + return ifInt(reader.intValue); \ + case UINT: \ + return ifUint(reader.uintValue); \ + case FLOAT: \ + return ifFloat(reader.floatValue); \ + default: \ + KJ_FAIL_REQUIRE("Value type mismatch.") { \ + return 0; \ + } \ + } \ +} \ +typeName DynamicValue::Builder::AsImpl::apply(Builder& builder) { \ + switch (builder.type) { \ + case INT: \ + return ifInt(builder.intValue); \ + case UINT: \ + return ifUint(builder.uintValue); \ + case FLOAT: \ + return ifFloat(builder.floatValue); \ + default: \ + KJ_FAIL_REQUIRE("Value type mismatch.") { \ + return 0; \ + } \ + } \ +} + +HANDLE_NUMERIC_TYPE(int8_t, checkRoundTrip, unsignedToSigned, checkRoundTripFromFloat) +HANDLE_NUMERIC_TYPE(int16_t, checkRoundTrip, unsignedToSigned, checkRoundTripFromFloat) +HANDLE_NUMERIC_TYPE(int32_t, checkRoundTrip, unsignedToSigned, checkRoundTripFromFloat) +HANDLE_NUMERIC_TYPE(int64_t, kj::implicitCast, unsignedToSigned, checkRoundTripFromFloat) +HANDLE_NUMERIC_TYPE(uint8_t, signedToUnsigned, checkRoundTrip, checkRoundTripFromFloat) +HANDLE_NUMERIC_TYPE(uint16_t, signedToUnsigned, checkRoundTrip, checkRoundTripFromFloat) +HANDLE_NUMERIC_TYPE(uint32_t, signedToUnsigned, checkRoundTrip, checkRoundTripFromFloat) +HANDLE_NUMERIC_TYPE(uint64_t, signedToUnsigned, kj::implicitCast, checkRoundTripFromFloat) +HANDLE_NUMERIC_TYPE(float, kj::implicitCast, kj::implicitCast, kj::implicitCast) +HANDLE_NUMERIC_TYPE(double, kj::implicitCast, kj::implicitCast, kj::implicitCast) + +#undef HANDLE_NUMERIC_TYPE + +#define HANDLE_TYPE(name, discrim, typeName) \ +ReaderFor DynamicValue::Reader::AsImpl::apply(const Reader& reader) { \ + KJ_REQUIRE(reader.type == discrim, "Value type mismatch.") { \ + return ReaderFor(); \ + } \ + return reader.name##Value; \ +} \ +BuilderFor DynamicValue::Builder::AsImpl::apply(Builder& builder) { \ + KJ_REQUIRE(builder.type == discrim, "Value type mismatch."); \ + return builder.name##Value; \ +} + +//HANDLE_TYPE(void, VOID, Void) +HANDLE_TYPE(bool, BOOL, bool) + +HANDLE_TYPE(text, TEXT, Text) +HANDLE_TYPE(list, LIST, DynamicList) +HANDLE_TYPE(struct, STRUCT, DynamicStruct) +HANDLE_TYPE(enum, ENUM, DynamicEnum) +HANDLE_TYPE(anyPointer, ANY_POINTER, AnyPointer) + +#undef HANDLE_TYPE + +Data::Reader DynamicValue::Reader::AsImpl::apply(const Reader& reader) { + if (reader.type == TEXT) { + // Coerce text to data. + return reader.textValue.asBytes(); + } + KJ_REQUIRE(reader.type == DATA, "Value type mismatch.") { + return Data::Reader(); + } + return reader.dataValue; +} +Data::Builder DynamicValue::Builder::AsImpl::apply(Builder& builder) { + if (builder.type == TEXT) { + // Coerce text to data. + return builder.textValue.asBytes(); + } + KJ_REQUIRE(builder.type == DATA, "Value type mismatch.") { + return BuilderFor(); + } + return builder.dataValue; +} + +// As in the header, HANDLE_TYPE(void, VOID, Void) crashes GCC 4.7. +Void DynamicValue::Reader::AsImpl::apply(const Reader& reader) { + KJ_REQUIRE(reader.type == VOID, "Value type mismatch.") { + return Void(); + } + return reader.voidValue; +} +Void DynamicValue::Builder::AsImpl::apply(Builder& builder) { + KJ_REQUIRE(builder.type == VOID, "Value type mismatch.") { + return Void(); + } + return builder.voidValue; +} + +// ======================================================================================= + +namespace _ { // private + +DynamicStruct::Reader PointerHelpers::getDynamic( + PointerReader reader, StructSchema schema) { + KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(), + "Cannot form pointer to group type."); + return DynamicStruct::Reader(schema, reader.getStruct(nullptr)); +} +DynamicStruct::Builder PointerHelpers::getDynamic( + PointerBuilder builder, StructSchema schema) { + KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(), + "Cannot form pointer to group type."); + return DynamicStruct::Builder(schema, builder.getStruct( + structSizeFromSchema(schema), nullptr)); +} +void PointerHelpers::set( + PointerBuilder builder, const DynamicStruct::Reader& value) { + KJ_REQUIRE(!value.schema.getProto().getStruct().getIsGroup(), + "Cannot form pointer to group type."); + builder.setStruct(value.reader); +} +DynamicStruct::Builder PointerHelpers::init( + PointerBuilder builder, StructSchema schema) { + KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(), + "Cannot form pointer to group type."); + return DynamicStruct::Builder(schema, + builder.initStruct(structSizeFromSchema(schema))); +} + +DynamicList::Reader PointerHelpers::getDynamic( + PointerReader reader, ListSchema schema) { + return DynamicList::Reader(schema, + reader.getList(elementSizeFor(schema.whichElementType()), nullptr)); +} +DynamicList::Builder PointerHelpers::getDynamic( + PointerBuilder builder, ListSchema schema) { + if (schema.whichElementType() == schema::Type::STRUCT) { + return DynamicList::Builder(schema, + builder.getStructList( + structSizeFromSchema(schema.getStructElementType()), + nullptr)); + } else { + return DynamicList::Builder(schema, + builder.getList(elementSizeFor(schema.whichElementType()), nullptr)); + } +} +void PointerHelpers::set( + PointerBuilder builder, const DynamicList::Reader& value) { + builder.setList(value.reader); +} +DynamicList::Builder PointerHelpers::init( + PointerBuilder builder, ListSchema schema, uint size) { + if (schema.whichElementType() == schema::Type::STRUCT) { + return DynamicList::Builder(schema, + builder.initStructList(bounded(size) * ELEMENTS, + structSizeFromSchema(schema.getStructElementType()))); + } else { + return DynamicList::Builder(schema, + builder.initList(elementSizeFor(schema.whichElementType()), bounded(size) * ELEMENTS)); + } +} + +} // namespace _ (private) + +template <> +void AnyPointer::Builder::adopt(Orphan&& orphan) { + switch (orphan.getType()) { + case DynamicValue::UNKNOWN: + case DynamicValue::VOID: + case DynamicValue::BOOL: + case DynamicValue::INT: + case DynamicValue::UINT: + case DynamicValue::FLOAT: + case DynamicValue::ENUM: + KJ_FAIL_REQUIRE("AnyPointer cannot adopt primitive (non-object) value."); + + case DynamicValue::STRUCT: + case DynamicValue::LIST: + case DynamicValue::TEXT: + case DynamicValue::DATA: + case DynamicValue::ANY_POINTER: + builder.adopt(kj::mv(orphan.builder)); + break; + } +} + +DynamicStruct::Reader::Reader(StructSchema schema, const _::OrphanBuilder& orphan) + : schema(schema), reader(orphan.asStructReader(structSizeFromSchema(schema))) {} +DynamicStruct::Builder::Builder(StructSchema schema, _::OrphanBuilder& orphan) + : schema(schema), builder(orphan.asStruct(structSizeFromSchema(schema))) {} + +DynamicList::Reader::Reader(ListSchema schema, const _::OrphanBuilder& orphan) + : schema(schema), reader(orphan.asListReader(elementSizeFor(schema.whichElementType()))) {} +DynamicList::Builder::Builder(ListSchema schema, _::OrphanBuilder& orphan) + : schema(schema), builder(schema.whichElementType() == schema::Type::STRUCT + ? orphan.asStructList(structSizeFromSchema(schema.getStructElementType())) + : orphan.asList(elementSizeFor(schema.whichElementType()))) {} + +// ------------------------------------------------------------------- + +Orphan Orphanage::newOrphan(StructSchema schema) const { + return Orphan( + schema, _::OrphanBuilder::initStruct(arena, structSizeFromSchema(schema))); +} + +Orphan Orphanage::newOrphan(ListSchema schema, uint size) const { + if (schema.whichElementType() == schema::Type::STRUCT) { + return Orphan(schema, _::OrphanBuilder::initStructList( + arena, bounded(size) * ELEMENTS, + structSizeFromSchema(schema.getStructElementType()))); + } else { + return Orphan(schema, _::OrphanBuilder::initList( + arena, bounded(size) * ELEMENTS, + elementSizeFor(schema.whichElementType()))); + } +} + +DynamicStruct::Builder Orphan::get() { + return DynamicStruct::Builder(schema, builder.asStruct(structSizeFromSchema(schema))); +} + +DynamicStruct::Reader Orphan::getReader() const { + return DynamicStruct::Reader(schema, builder.asStructReader(structSizeFromSchema(schema))); +} + +DynamicList::Builder Orphan::get() { + if (schema.whichElementType() == schema::Type::STRUCT) { + return DynamicList::Builder( + schema, builder.asStructList(structSizeFromSchema(schema.getStructElementType()))); + } else { + return DynamicList::Builder( + schema, builder.asList(elementSizeFor(schema.whichElementType()))); + } +} + +DynamicList::Reader Orphan::getReader() const { + return DynamicList::Reader( + schema, builder.asListReader(elementSizeFor(schema.whichElementType()))); +} + +Orphan::Orphan(DynamicValue::Builder value, _::OrphanBuilder&& builder) + : type(value.getType()), builder(kj::mv(builder)) { + switch (type) { + case DynamicValue::UNKNOWN: break; + case DynamicValue::VOID: voidValue = value.voidValue; break; + case DynamicValue::BOOL: boolValue = value.boolValue; break; + case DynamicValue::INT: intValue = value.intValue; break; + case DynamicValue::UINT: uintValue = value.uintValue; break; + case DynamicValue::FLOAT: floatValue = value.floatValue; break; + case DynamicValue::ENUM: enumValue = value.enumValue; break; + + case DynamicValue::TEXT: break; + case DynamicValue::DATA: break; + case DynamicValue::LIST: listSchema = value.listValue.getSchema(); break; + case DynamicValue::STRUCT: structSchema = value.structValue.getSchema(); break; + case DynamicValue::ANY_POINTER: break; + } +} + +DynamicValue::Builder Orphan::get() { + switch (type) { + case DynamicValue::UNKNOWN: return nullptr; + case DynamicValue::VOID: return voidValue; + case DynamicValue::BOOL: return boolValue; + case DynamicValue::INT: return intValue; + case DynamicValue::UINT: return uintValue; + case DynamicValue::FLOAT: return floatValue; + case DynamicValue::ENUM: return enumValue; + + case DynamicValue::TEXT: return builder.asText(); + case DynamicValue::DATA: return builder.asData(); + case DynamicValue::LIST: + if (listSchema.whichElementType() == schema::Type::STRUCT) { + return DynamicList::Builder(listSchema, + builder.asStructList(structSizeFromSchema(listSchema.getStructElementType()))); + } else { + return DynamicList::Builder(listSchema, + builder.asList(elementSizeFor(listSchema.whichElementType()))); + } + case DynamicValue::STRUCT: + return DynamicStruct::Builder(structSchema, + builder.asStruct(structSizeFromSchema(structSchema))); + case DynamicValue::ANY_POINTER: + KJ_FAIL_REQUIRE("Can't get() an AnyPointer orphan; there is no underlying pointer to " + "wrap in an AnyPointer::Builder."); + } + KJ_UNREACHABLE; +} +DynamicValue::Reader Orphan::getReader() const { + switch (type) { + case DynamicValue::UNKNOWN: return nullptr; + case DynamicValue::VOID: return voidValue; + case DynamicValue::BOOL: return boolValue; + case DynamicValue::INT: return intValue; + case DynamicValue::UINT: return uintValue; + case DynamicValue::FLOAT: return floatValue; + case DynamicValue::ENUM: return enumValue; + + case DynamicValue::TEXT: return builder.asTextReader(); + case DynamicValue::DATA: return builder.asDataReader(); + case DynamicValue::LIST: + return DynamicList::Reader(listSchema, + builder.asListReader(elementSizeFor(listSchema.whichElementType()))); + case DynamicValue::STRUCT: + return DynamicStruct::Reader(structSchema, + builder.asStructReader(structSizeFromSchema(structSchema))); + case DynamicValue::ANY_POINTER: + KJ_FAIL_ASSERT("Can't get() an AnyPointer orphan; there is no underlying pointer to " + "wrap in an AnyPointer::Builder."); + } + KJ_UNREACHABLE; +} + +template <> +Orphan Orphan::releaseAs() { + KJ_REQUIRE(type == DynamicValue::ANY_POINTER, "Value type mismatch."); + type = DynamicValue::UNKNOWN; + return Orphan(kj::mv(builder)); +} +template <> +Orphan Orphan::releaseAs() { + KJ_REQUIRE(type == DynamicValue::STRUCT, "Value type mismatch."); + type = DynamicValue::UNKNOWN; + return Orphan(structSchema, kj::mv(builder)); +} +template <> +Orphan Orphan::releaseAs() { + KJ_REQUIRE(type == DynamicValue::LIST, "Value type mismatch."); + type = DynamicValue::UNKNOWN; + return Orphan(listSchema, kj::mv(builder)); +} + +template <> +Orphan Orphanage::newOrphanCopy( + DynamicValue::Reader copyFrom) const { + switch (copyFrom.getType()) { + case DynamicValue::UNKNOWN: return nullptr; + case DynamicValue::VOID: return copyFrom.voidValue; + case DynamicValue::BOOL: return copyFrom.boolValue; + case DynamicValue::INT: return copyFrom.intValue; + case DynamicValue::UINT: return copyFrom.uintValue; + case DynamicValue::FLOAT: return copyFrom.floatValue; + case DynamicValue::ENUM: return copyFrom.enumValue; + + case DynamicValue::TEXT: return newOrphanCopy(copyFrom.textValue); + case DynamicValue::DATA: return newOrphanCopy(copyFrom.dataValue); + case DynamicValue::LIST: return newOrphanCopy(copyFrom.listValue); + case DynamicValue::STRUCT: return newOrphanCopy(copyFrom.structValue); + case DynamicValue::ANY_POINTER: return newOrphanCopy(copyFrom.anyPointerValue); + } + KJ_UNREACHABLE; +} + +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/dynamic.h b/vendor/capnproto/src/capnp/dynamic.h new file mode 100644 index 0000000..dc4cfc2 --- /dev/null +++ b/vendor/capnproto/src/capnp/dynamic.h @@ -0,0 +1,1202 @@ +// 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 classes that can be used to manipulate messages based on schemas that are not +// known until runtime. This is also useful for writing generic code that uses schemas to handle +// arbitrary types in a generic way. +// +// Each of the classes defined here has a to() template method which converts an instance back to a +// native type. This method will throw an exception if the requested type does not match the +// schema. To convert native types to dynamic, use DynamicFactory. +// +// As always, underlying data is validated lazily, so you have to actually traverse the whole +// message if you want to validate all content. + +#pragma once + +#include "schema.h" +#include "layout.h" +#include "message.h" +#include "any.h" + +CAPNP_BEGIN_HEADER + +namespace capnp { + +class MessageReader; +class MessageBuilder; + +struct DynamicValue { + DynamicValue() = delete; + + enum Type { + UNKNOWN, + // Means that the value has unknown type and content because it comes from a newer version of + // the schema, or from a newer version of Cap'n Proto that has new features that this version + // doesn't understand. + + VOID, + BOOL, + INT, + UINT, + FLOAT, + TEXT, + DATA, + LIST, + ENUM, + STRUCT, + ANY_POINTER + }; + + class Reader; + class Builder; +}; +class DynamicEnum; +struct DynamicStruct { + DynamicStruct() = delete; + class Reader; + class Builder; +}; +struct DynamicList { + DynamicList() = delete; + class Reader; + class Builder; +}; +template <> class Orphan; + +template struct DynamicTypeFor_; +template <> struct DynamicTypeFor_ { typedef DynamicEnum Type; }; +template <> struct DynamicTypeFor_ { typedef DynamicStruct Type; }; +template <> struct DynamicTypeFor_ { typedef DynamicList Type; }; + +template +using DynamicTypeFor = typename DynamicTypeFor_()>::Type; + +template +ReaderFor>> toDynamic(T&& value); +template +BuilderFor>> toDynamic(T&& value); +template +DynamicTypeFor> toDynamic(T&& value); + +namespace _ { // private + +template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; +template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; + +} // namespace _ (private) + +template <> inline constexpr Style style() { return Style::POINTER; } +template <> inline constexpr Style style() { return Style::PRIMITIVE; } +template <> inline constexpr Style style() { return Style::STRUCT; } +template <> inline constexpr Style style() { return Style::POINTER; } + +// ------------------------------------------------------------------- + +class DynamicEnum { +public: + DynamicEnum() = default; + inline DynamicEnum(EnumSchema::Enumerant enumerant) + : schema(enumerant.getContainingEnum()), value(enumerant.getOrdinal()) {} + inline DynamicEnum(EnumSchema schema, uint16_t value) + : schema(schema), value(value) {} + + template () == Kind::ENUM>> + inline DynamicEnum(T&& value): DynamicEnum(toDynamic(value)) {} + + template + inline T as() const { return static_cast(asImpl(typeId())); } + // Cast to a native enum type. + + inline EnumSchema getSchema() const { return schema; } + + kj::Maybe getEnumerant() const; + // Get which enumerant this enum value represents. Returns nullptr if the numeric value does not + // correspond to any enumerant in the schema -- this can happen if the data was built using a + // newer schema that has more values defined. + + inline uint16_t getRaw() const { return value; } + // Returns the raw underlying enum value. + +private: + EnumSchema schema; + uint16_t value; + + uint16_t asImpl(uint64_t requestedTypeId) const; + + friend struct DynamicStruct; + friend struct DynamicList; + friend struct DynamicValue; + template + friend DynamicTypeFor> toDynamic(T&& value); +}; + +// ------------------------------------------------------------------- + +enum class HasMode: uint8_t { + // Specifies the meaning of "has(field)". + + NON_NULL, + // "has(field)" only returns false if the field is a pointer and the pointer is null. This is the + // default behavior. + + NON_DEFAULT + // "has(field)" returns false if the field is set to its default value. This differs from + // NON_NULL only in the handling of primitive values. + // + // "Equal to default value" is technically defined as the field value being encoded as all-zero + // on the wire (since primitive values are XORed by their defined default value when encoded). +}; + +class DynamicStruct::Reader { +public: + typedef DynamicStruct Reads; + + Reader() = default; + + template >() == Kind::STRUCT>> + inline Reader(T&& value): Reader(toDynamic(value)) {} + + inline operator AnyStruct::Reader() const { return AnyStruct::Reader(reader); } + + inline MessageSize totalSize() const { return reader.totalSize().asPublic(); } + + template + typename T::Reader as() const; + // Convert the dynamic struct to its compiled-in type. + + inline StructSchema getSchema() const { return schema; } + + DynamicValue::Reader get(StructSchema::Field field) const; + // Read the given field value. + + bool has(StructSchema::Field field, HasMode mode = HasMode::NON_NULL) const; + // Tests whether the given field is "present". If the field is a union member and is not the + // active member, this always returns false. Otherwise, the field's value is interpreted + // according to `mode`. + + kj::Maybe which() const; + // If the struct contains an (unnamed) union, and the currently-active field within that union + // is known, this returns that field. Otherwise, it returns null. In other words, this returns + // null if there is no union present _or_ if the union's discriminant is set to an unrecognized + // value. This could happen in particular when receiving a message from a sender who has a + // newer version of the protocol and is using a field of the union that you don't know about yet. + + DynamicValue::Reader get(kj::StringPtr name) const; + bool has(kj::StringPtr name, HasMode mode = HasMode::NON_NULL) const; + // Shortcuts to access fields by name. These throw exceptions if no such field exists. + +private: + StructSchema schema; + _::StructReader reader; + + inline Reader(StructSchema schema, _::StructReader reader) + : schema(schema), reader(reader) {} + Reader(StructSchema schema, const _::OrphanBuilder& orphan); + + bool isSetInUnion(StructSchema::Field field) const; + void verifySetInUnion(StructSchema::Field field) const; + static DynamicValue::Reader getImpl(_::StructReader reader, StructSchema::Field field); + + template + friend struct _::PointerHelpers; + friend class DynamicStruct::Builder; + friend struct DynamicList; + friend class MessageReader; + friend class MessageBuilder; + template + friend struct ::capnp::ToDynamic_; + friend kj::StringTree _::structString( + _::StructReader reader, const _::RawBrandedSchema& schema); + friend class Orphanage; + friend class Orphan; + friend class Orphan; + friend class Orphan; + friend class AnyStruct::Reader; +}; + +class DynamicStruct::Builder { +public: + typedef DynamicStruct Builds; + + Builder() = default; + inline Builder(decltype(nullptr)) {} + + template >() == Kind::STRUCT>> + inline Builder(T&& value): Builder(toDynamic(value)) {} + + inline operator AnyStruct::Builder() { return AnyStruct::Builder(builder); } + + inline MessageSize totalSize() const { return asReader().totalSize(); } + + template + typename T::Builder as(); + // Cast to a particular struct type. + + inline StructSchema getSchema() const { return schema; } + + DynamicValue::Builder get(StructSchema::Field field); + // Read the given field value. + + inline bool has(StructSchema::Field field, HasMode mode = HasMode::NON_NULL) + { return asReader().has(field, mode); } + // Tests whether the given field is "present". If the field is a union member and is not the + // active member, this always returns false. Otherwise, the field's value is interpreted + // according to `mode`. + + kj::Maybe which(); + // If the struct contains an (unnamed) union, and the currently-active field within that union + // is known, this returns that field. Otherwise, it returns null. In other words, this returns + // null if there is no union present _or_ if the union's discriminant is set to an unrecognized + // value. This could happen in particular when receiving a message from a sender who has a + // newer version of the protocol and is using a field of the union that you don't know about yet. + + void set(StructSchema::Field field, const DynamicValue::Reader& value); + // Set the given field value. + + DynamicValue::Builder init(StructSchema::Field field); + DynamicValue::Builder init(StructSchema::Field field, uint size); + // Init a struct, list, or blob field. + + void adopt(StructSchema::Field field, Orphan&& orphan); + Orphan disown(StructSchema::Field field); + // Adopt/disown. This works even for non-pointer fields: adopt() becomes equivalent to set() + // and disown() becomes like get() followed by clear(). + + void clear(StructSchema::Field field); + // Clear a field, setting it to its default value. For pointer fields, this actually makes the + // field null. + + DynamicValue::Builder get(kj::StringPtr name); + bool has(kj::StringPtr name, HasMode mode = HasMode::NON_NULL); + void set(kj::StringPtr name, const DynamicValue::Reader& value); + void set(kj::StringPtr name, std::initializer_list value); + DynamicValue::Builder init(kj::StringPtr name); + DynamicValue::Builder init(kj::StringPtr name, uint size); + void adopt(kj::StringPtr name, Orphan&& orphan); + Orphan disown(kj::StringPtr name); + void clear(kj::StringPtr name); + // Shortcuts to access fields by name. These throw exceptions if no such field exists. + + Reader asReader() const; + +private: + StructSchema schema; + _::StructBuilder builder; + + inline Builder(StructSchema schema, _::StructBuilder builder) + : schema(schema), builder(builder) {} + Builder(StructSchema schema, _::OrphanBuilder& orphan); + + bool isSetInUnion(StructSchema::Field field); + void verifySetInUnion(StructSchema::Field field); + void setInUnion(StructSchema::Field field); + + template + friend struct _::PointerHelpers; + friend struct DynamicList; + friend class MessageReader; + friend class MessageBuilder; + template + friend struct ::capnp::ToDynamic_; + friend class Orphanage; + friend class Orphan; + friend class Orphan; + friend class Orphan; + friend class AnyStruct::Builder; +}; + +// ------------------------------------------------------------------- + +class DynamicList::Reader { +public: + typedef DynamicList Reads; + + inline Reader(): reader(ElementSize::VOID) {} + + template >() == Kind::LIST>> + inline Reader(T&& value): Reader(toDynamic(value)) {} + + inline operator AnyList::Reader() const { return AnyList::Reader(reader); } + + template + typename T::Reader as() const; + // Try to convert to any List, Data, or Text. Throws an exception if the underlying data + // can't possibly represent the requested type. + + inline ListSchema getSchema() const { return schema; } + + inline uint size() const { return unbound(reader.size() / ELEMENTS); } + DynamicValue::Reader operator[](uint index) const; + + typedef _::IndexingIterator Iterator; + inline Iterator begin() const { return Iterator(this, 0); } + inline Iterator end() const { return Iterator(this, size()); } + +private: + ListSchema schema; + _::ListReader reader; + + Reader(ListSchema schema, _::ListReader reader): schema(schema), reader(reader) {} + Reader(ListSchema schema, const _::OrphanBuilder& orphan); + + template + friend struct _::PointerHelpers; + friend struct DynamicStruct; + friend class DynamicList::Builder; + template + friend struct ::capnp::ToDynamic_; + friend class Orphanage; + friend class Orphan; + friend class Orphan; + friend class Orphan; +}; + +class DynamicList::Builder { +public: + typedef DynamicList Builds; + + inline Builder(): builder(ElementSize::VOID) {} + inline Builder(decltype(nullptr)): builder(ElementSize::VOID) {} + + template >() == Kind::LIST>> + inline Builder(T&& value): Builder(toDynamic(value)) {} + + inline operator AnyList::Builder() { return AnyList::Builder(builder); } + + template + typename T::Builder as(); + // Try to convert to any List, Data, or Text. Throws an exception if the underlying data + // can't possibly represent the requested type. + + inline ListSchema getSchema() const { return schema; } + + inline uint size() const { return unbound(builder.size() / ELEMENTS); } + DynamicValue::Builder operator[](uint index); + void set(uint index, const DynamicValue::Reader& value); + DynamicValue::Builder init(uint index, uint size); + void adopt(uint index, Orphan&& orphan); + Orphan disown(uint index); + + typedef _::IndexingIterator Iterator; + inline Iterator begin() { return Iterator(this, 0); } + inline Iterator end() { return Iterator(this, size()); } + + void copyFrom(std::initializer_list value); + + Reader asReader() const; + +private: + ListSchema schema; + _::ListBuilder builder; + + Builder(ListSchema schema, _::ListBuilder builder): schema(schema), builder(builder) {} + Builder(ListSchema schema, _::OrphanBuilder& orphan); + + template + friend struct _::PointerHelpers; + friend struct DynamicStruct; + template + friend struct ::capnp::ToDynamic_; + friend class Orphanage; + template + friend struct _::OrphanGetImpl; + friend class Orphan; + friend class Orphan; + friend class Orphan; +}; + +// ------------------------------------------------------------------- + +// Make sure ReaderFor and BuilderFor work for DynamicEnum, DynamicStruct, and +// DynamicList, so that we can define DynamicValue::as(). + +template <> struct ReaderFor_ { typedef DynamicEnum Type; }; +template <> struct BuilderFor_ { typedef DynamicEnum Type; }; +template <> struct ReaderFor_ { typedef DynamicStruct::Reader Type; }; +template <> struct BuilderFor_ { typedef DynamicStruct::Builder Type; }; +template <> struct ReaderFor_ { typedef DynamicList::Reader Type; }; +template <> struct BuilderFor_ { typedef DynamicList::Builder Type; }; + +class DynamicValue::Reader { +public: + typedef DynamicValue Reads; + + inline Reader(decltype(nullptr) n = nullptr); // UNKNOWN + inline Reader(Void value); + inline Reader(bool value); + inline Reader(char value); + inline Reader(signed char value); + inline Reader(short value); + inline Reader(int value); + inline Reader(long value); + inline Reader(long long value); + inline Reader(unsigned char value); + inline Reader(unsigned short value); + inline Reader(unsigned int value); + inline Reader(unsigned long value); + inline Reader(unsigned long long value); + inline Reader(float value); + inline Reader(double value); + inline Reader(const char* value); // Text + inline Reader(const Text::Reader& value); + inline Reader(const Data::Reader& value); + inline Reader(const DynamicList::Reader& value); + inline Reader(DynamicEnum value); + inline Reader(const DynamicStruct::Reader& value); + inline Reader(const AnyPointer::Reader& value); + Reader(ConstSchema constant); + + template ()))> + inline Reader(T&& value): Reader(toDynamic(kj::mv(value))) {} + + Reader(const Reader& other) = default; + Reader(Reader&& other) noexcept = default; + ~Reader() noexcept(false) = default; + Reader& operator=(const Reader& other) = default; + Reader& operator=(Reader&& other) = default; + + template + inline ReaderFor as() const { return AsImpl::apply(*this); } + // Use to interpret the value as some Cap'n Proto type. Allowed types are: + // - Void, bool, [u]int{8,16,32,64}_t, float, double, any enum: Returns the raw value. + // - Text, Data, AnyPointer, any struct type: Returns the corresponding Reader. + // - List for any T listed above: Returns List::Reader. + // - DynamicEnum: Returns the corresponding type. + // - DynamicStruct, DynamicList: Returns the corresponding Reader. + // - DynamicValue: Returns an identical Reader. Useful to avoid special-casing in generic code. + // + // DynamicValue allows various implicit conversions, mostly just to make the interface friendlier. + // - Any integer can be converted to any other integer type so long as the actual value is within + // the new type's range. + // - Floating-point types can be converted to integers as long as no information would be lost + // in the conversion. + // - Integers can be converted to floating points. This may lose information, but won't throw. + // - Float32/Float64 can be converted between each other. Converting Float64 -> Float32 may lose + // information, but won't throw. + // - Text can be converted to an enum, if the Text matches one of the enumerant names (but not + // vice-versa). + // + // Any other conversion attempt will throw an exception. + + inline Type getType() const { return type; } + // Get the type of this value. + +private: + Type type; + + union { + Void voidValue; + bool boolValue; + int64_t intValue; + uint64_t uintValue; + double floatValue; + Text::Reader textValue; + Data::Reader dataValue; + DynamicList::Reader listValue; + DynamicEnum enumValue; + DynamicStruct::Reader structValue; + AnyPointer::Reader anyPointerValue; + }; + + template ()> struct AsImpl; + // Implementation backing the as() method. Needs to be a struct to allow partial + // specialization. Has a method apply() which does the work. + + friend class Orphanage; // to speed up newOrphanCopy(DynamicValue::Reader) +}; + +class DynamicValue::Builder { +public: + typedef DynamicValue Builds; + + inline Builder(decltype(nullptr) n = nullptr); // UNKNOWN + inline Builder(Void value); + inline Builder(bool value); + inline Builder(char value); + inline Builder(signed char value); + inline Builder(short value); + inline Builder(int value); + inline Builder(long value); + inline Builder(long long value); + inline Builder(unsigned char value); + inline Builder(unsigned short value); + inline Builder(unsigned int value); + inline Builder(unsigned long value); + inline Builder(unsigned long long value); + inline Builder(float value); + inline Builder(double value); + inline Builder(Text::Builder value); + inline Builder(Data::Builder value); + inline Builder(DynamicList::Builder value); + inline Builder(DynamicEnum value); + inline Builder(DynamicStruct::Builder value); + inline Builder(AnyPointer::Builder value); + + template ()))> + inline Builder(T value): Builder(toDynamic(value)) {} + + Builder(Builder& other) = default; + Builder(Builder&& other) noexcept = default; + ~Builder() noexcept(false) = default; + Builder& operator=(Builder& other) = default; + Builder& operator=(Builder&& other) = default; + + template + inline BuilderFor as() { return AsImpl::apply(*this); } + // See DynamicValue::Reader::as(). + + inline Type getType() { return type; } + // Get the type of this value. + + Reader asReader() const; + +private: + Type type; + + union { + Void voidValue; + bool boolValue; + int64_t intValue; + uint64_t uintValue; + double floatValue; + Text::Builder textValue; + Data::Builder dataValue; + DynamicList::Builder listValue; + DynamicEnum enumValue; + DynamicStruct::Builder structValue; + AnyPointer::Builder anyPointerValue; + }; + + template ()> struct AsImpl; + // Implementation backing the as() method. Needs to be a struct to allow partial + // specialization. Has a method apply() which does the work. + + friend class Orphan; +}; + +kj::StringTree KJ_STRINGIFY(const DynamicValue::Reader& value); +kj::StringTree KJ_STRINGIFY(const DynamicValue::Builder& value); +kj::StringTree KJ_STRINGIFY(DynamicEnum value); +kj::StringTree KJ_STRINGIFY(const DynamicStruct::Reader& value); +kj::StringTree KJ_STRINGIFY(const DynamicStruct::Builder& value); +kj::StringTree KJ_STRINGIFY(const DynamicList::Reader& value); +kj::StringTree KJ_STRINGIFY(const DynamicList::Builder& value); + +// ------------------------------------------------------------------- +// Orphan <-> Dynamic glue + +template <> +class Orphan { +public: + Orphan() = default; + KJ_DISALLOW_COPY(Orphan); + Orphan(Orphan&&) = default; + Orphan& operator=(Orphan&&) = default; + + template () == Kind::STRUCT>> + inline Orphan(Orphan&& other): schema(Schema::from()), builder(kj::mv(other.builder)) {} + + DynamicStruct::Builder get(); + DynamicStruct::Reader getReader() const; + + template + Orphan releaseAs(); + // Like DynamicStruct::Builder::as(), but coerces the Orphan type. Since Orphans are move-only, + // the original Orphan is no longer valid after this call; ownership is + // transferred to the returned Orphan. + + inline bool operator==(decltype(nullptr)) const { return builder == nullptr; } + inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; } + +private: + StructSchema schema; + _::OrphanBuilder builder; + + inline Orphan(StructSchema schema, _::OrphanBuilder&& builder) + : schema(schema), builder(kj::mv(builder)) {} + + template + friend struct _::PointerHelpers; + friend struct DynamicList; + friend class Orphanage; + friend class Orphan; + friend class Orphan; + friend class MessageBuilder; +}; + +template <> +class Orphan { +public: + Orphan() = default; + KJ_DISALLOW_COPY(Orphan); + Orphan(Orphan&&) = default; + Orphan& operator=(Orphan&&) = default; + + template () == Kind::LIST>> + inline Orphan(Orphan&& other): schema(Schema::from()), builder(kj::mv(other.builder)) {} + + DynamicList::Builder get(); + DynamicList::Reader getReader() const; + + template + Orphan releaseAs(); + // Like DynamicList::Builder::as(), but coerces the Orphan type. Since Orphans are move-only, + // the original Orphan is no longer valid after this call; ownership is + // transferred to the returned Orphan. + + // TODO(someday): Support truncate(). + + inline bool operator==(decltype(nullptr)) const { return builder == nullptr; } + inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; } + +private: + ListSchema schema; + _::OrphanBuilder builder; + + inline Orphan(ListSchema schema, _::OrphanBuilder&& builder) + : schema(schema), builder(kj::mv(builder)) {} + + template + friend struct _::PointerHelpers; + friend struct DynamicList; + friend class Orphanage; + friend class Orphan; + friend class Orphan; +}; + +template <> +class Orphan { +public: + inline Orphan(decltype(nullptr) n = nullptr): type(DynamicValue::UNKNOWN) {} + inline Orphan(Void value); + inline Orphan(bool value); + inline Orphan(char value); + inline Orphan(signed char value); + inline Orphan(short value); + inline Orphan(int value); + inline Orphan(long value); + inline Orphan(long long value); + inline Orphan(unsigned char value); + inline Orphan(unsigned short value); + inline Orphan(unsigned int value); + inline Orphan(unsigned long value); + inline Orphan(unsigned long long value); + inline Orphan(float value); + inline Orphan(double value); + inline Orphan(DynamicEnum value); + Orphan(Orphan&&) = default; + template + Orphan(Orphan&&); + Orphan(Orphan&&); + Orphan(void*) = delete; // So Orphan(bool) doesn't accept pointers. + KJ_DISALLOW_COPY(Orphan); + + Orphan& operator=(Orphan&&) = default; + + inline DynamicValue::Type getType() { return type; } + + DynamicValue::Builder get(); + DynamicValue::Reader getReader() const; + + template + Orphan releaseAs(); + // Like DynamicValue::Builder::as(), but coerces the Orphan type. Since Orphans are move-only, + // the original Orphan is no longer valid after this call; ownership is + // transferred to the returned Orphan. + +private: + DynamicValue::Type type; + union { + Void voidValue; + bool boolValue; + int64_t intValue; + uint64_t uintValue; + double floatValue; + DynamicEnum enumValue; + StructSchema structSchema; + ListSchema listSchema; + }; + + _::OrphanBuilder builder; + // Only used if `type` is a pointer type. + + Orphan(DynamicValue::Builder value, _::OrphanBuilder&& builder); + Orphan(DynamicValue::Type type, _::OrphanBuilder&& builder) + : type(type), builder(kj::mv(builder)) {} + Orphan(StructSchema structSchema, _::OrphanBuilder&& builder) + : type(DynamicValue::STRUCT), structSchema(structSchema), builder(kj::mv(builder)) {} + Orphan(ListSchema listSchema, _::OrphanBuilder&& builder) + : type(DynamicValue::LIST), listSchema(listSchema), builder(kj::mv(builder)) {} + + template + friend struct _::PointerHelpers; + friend struct DynamicStruct; + friend struct DynamicList; + friend struct AnyPointer; + friend class Orphanage; +}; + +template +inline Orphan::Orphan(Orphan&& other) + : Orphan(other.get(), kj::mv(other.builder)) {} + +inline Orphan::Orphan(Orphan&& other) + : type(DynamicValue::ANY_POINTER), builder(kj::mv(other.builder)) {} + +template +Orphan Orphan::releaseAs() { + get().as(); // type check + return Orphan(kj::mv(builder)); +} + +template +Orphan Orphan::releaseAs() { + get().as(); // type check + return Orphan(kj::mv(builder)); +} + +template +Orphan Orphan::releaseAs() { + get().as(); // type check + type = DynamicValue::UNKNOWN; + return Orphan(kj::mv(builder)); +} + +template <> +Orphan Orphan::releaseAs(); +template <> +Orphan Orphan::releaseAs(); +template <> +Orphan Orphan::releaseAs(); + +template <> +struct Orphanage::GetInnerBuilder { + static inline _::StructBuilder apply(DynamicStruct::Builder& t) { + return t.builder; + } +}; + +template <> +struct Orphanage::GetInnerBuilder { + static inline _::ListBuilder apply(DynamicList::Builder& t) { + return t.builder; + } +}; + +template <> +inline Orphan Orphanage::newOrphanCopy( + DynamicStruct::Reader copyFrom) const { + return Orphan( + copyFrom.getSchema(), _::OrphanBuilder::copy(arena, copyFrom.reader)); +} + +template <> +inline Orphan Orphanage::newOrphanCopy( + DynamicList::Reader copyFrom) const { + return Orphan(copyFrom.getSchema(), + _::OrphanBuilder::copy(arena, copyFrom.reader)); +} + +template <> +Orphan Orphanage::newOrphanCopy( + DynamicValue::Reader copyFrom) const; + +namespace _ { // private + +template <> +struct PointerHelpers { + // getDynamic() is used when an AnyPointer's get() accessor is passed arguments, because for + // non-dynamic types PointerHelpers::get() takes a default value as the third argument, and we + // don't want people to accidentally be able to provide their own default value. + static DynamicStruct::Reader getDynamic(PointerReader reader, StructSchema schema); + static DynamicStruct::Builder getDynamic(PointerBuilder builder, StructSchema schema); + static void set(PointerBuilder builder, const DynamicStruct::Reader& value); + static DynamicStruct::Builder init(PointerBuilder builder, StructSchema schema); + static inline void adopt(PointerBuilder builder, Orphan&& value) { + builder.adopt(kj::mv(value.builder)); + } + static inline Orphan disown(PointerBuilder builder, StructSchema schema) { + return Orphan(schema, builder.disown()); + } +}; + +template <> +struct PointerHelpers { + // getDynamic() is used when an AnyPointer's get() accessor is passed arguments, because for + // non-dynamic types PointerHelpers::get() takes a default value as the third argument, and we + // don't want people to accidentally be able to provide their own default value. + static DynamicList::Reader getDynamic(PointerReader reader, ListSchema schema); + static DynamicList::Builder getDynamic(PointerBuilder builder, ListSchema schema); + static void set(PointerBuilder builder, const DynamicList::Reader& value); + static DynamicList::Builder init(PointerBuilder builder, ListSchema schema, uint size); + static inline void adopt(PointerBuilder builder, Orphan&& value) { + builder.adopt(kj::mv(value.builder)); + } + static inline Orphan disown(PointerBuilder builder, ListSchema schema) { + return Orphan(schema, builder.disown()); + } +}; + +} // namespace _ (private) + +template +inline ReaderFor AnyPointer::Reader::getAs(StructSchema schema) const { + return _::PointerHelpers::getDynamic(reader, schema); +} +template +inline ReaderFor AnyPointer::Reader::getAs(ListSchema schema) const { + return _::PointerHelpers::getDynamic(reader, schema); +} +template +inline BuilderFor AnyPointer::Builder::getAs(StructSchema schema) { + return _::PointerHelpers::getDynamic(builder, schema); +} +template +inline BuilderFor AnyPointer::Builder::getAs(ListSchema schema) { + return _::PointerHelpers::getDynamic(builder, schema); +} +template +inline BuilderFor AnyPointer::Builder::initAs(StructSchema schema) { + return _::PointerHelpers::init(builder, schema); +} +template +inline BuilderFor AnyPointer::Builder::initAs(ListSchema schema, uint elementCount) { + return _::PointerHelpers::init(builder, schema, elementCount); +} +template <> +inline void AnyPointer::Builder::setAs(DynamicStruct::Reader value) { + return _::PointerHelpers::set(builder, value); +} +template <> +inline void AnyPointer::Builder::setAs(DynamicList::Reader value) { + return _::PointerHelpers::set(builder, value); +} +template <> +void AnyPointer::Builder::adopt(Orphan&& orphan); +template +inline Orphan AnyPointer::Builder::disownAs(StructSchema schema) { + return _::PointerHelpers::disown(builder, schema); +} +template +inline Orphan AnyPointer::Builder::disownAs(ListSchema schema) { + return _::PointerHelpers::disown(builder, schema); +} + +// We have to declare the methods below inline because Clang and GCC disagree about how to mangle +// their symbol names. +template <> +inline DynamicStruct::Builder Orphan::getAs(StructSchema schema) { + return DynamicStruct::Builder(schema, builder); +} +template <> +inline DynamicStruct::Reader Orphan::getAsReader( + StructSchema schema) const { + return DynamicStruct::Reader(schema, builder); +} +template <> +inline Orphan Orphan::releaseAs(StructSchema schema) { + return Orphan(schema, kj::mv(builder)); +} +template <> +inline DynamicList::Builder Orphan::getAs(ListSchema schema) { + return DynamicList::Builder(schema, builder); +} +template <> +inline DynamicList::Reader Orphan::getAsReader(ListSchema schema) const { + return DynamicList::Reader(schema, builder); +} +template <> +inline Orphan Orphan::releaseAs(ListSchema schema) { + return Orphan(schema, kj::mv(builder)); +} +// ======================================================================================= +// Inline implementation details. + +template +struct ToDynamic_ { + static inline DynamicStruct::Reader apply(const typename T::Reader& value) { + return DynamicStruct::Reader(Schema::from(), value._reader); + } + static inline DynamicStruct::Builder apply(typename T::Builder& value) { + return DynamicStruct::Builder(Schema::from(), value._builder); + } +}; + +template +struct ToDynamic_ { + static inline DynamicList::Reader apply(const typename T::Reader& value) { + return DynamicList::Reader(Schema::from(), value.reader); + } + static inline DynamicList::Builder apply(typename T::Builder& value) { + return DynamicList::Builder(Schema::from(), value.builder); + } +}; + +template +ReaderFor>> toDynamic(T&& value) { + return ToDynamic_>::apply(value); +} +template +BuilderFor>> toDynamic(T&& value) { + return ToDynamic_>::apply(value); +} +template +DynamicTypeFor> toDynamic(T&& value) { + return DynamicEnum(Schema::from>(), static_cast(value)); +} + +inline DynamicValue::Reader::Reader(std::nullptr_t n): type(UNKNOWN) {} +inline DynamicValue::Builder::Builder(std::nullptr_t n): type(UNKNOWN) {} + +#define CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \ +inline DynamicValue::Reader::Reader(cppType value) \ + : type(typeTag), fieldName##Value(value) {} \ +inline DynamicValue::Builder::Builder(cppType value) \ + : type(typeTag), fieldName##Value(value) {} \ +inline Orphan::Orphan(cppType value) \ + : type(DynamicValue::typeTag), fieldName##Value(value) {} + +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Void, VOID, void); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(bool, BOOL, bool); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(char, INT, int); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(signed char, INT, int); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(short, INT, int); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(int, INT, int); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(long, INT, int); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(long long, INT, int); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned char, UINT, uint); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned short, UINT, uint); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned int, UINT, uint); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned long, UINT, uint); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned long long, UINT, uint); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(float, FLOAT, float); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(double, FLOAT, float); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicEnum, ENUM, enum); +#undef CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR + +#define CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \ +inline DynamicValue::Reader::Reader(const cppType::Reader& value) \ + : type(typeTag), fieldName##Value(value) {} \ +inline DynamicValue::Builder::Builder(cppType::Builder value) \ + : type(typeTag), fieldName##Value(value) {} + +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Text, TEXT, text); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Data, DATA, data); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicList, LIST, list); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicStruct, STRUCT, struct); +CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(AnyPointer, ANY_POINTER, anyPointer); + +#undef CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR + +inline DynamicValue::Reader::Reader(const char* value): Reader(Text::Reader(value)) {} + +#define CAPNP_DECLARE_TYPE(discrim, typeName) \ +template <> \ +struct DynamicValue::Reader::AsImpl { \ + static ReaderFor apply(const Reader& reader); \ +}; \ +template <> \ +struct DynamicValue::Builder::AsImpl { \ + static BuilderFor apply(Builder& builder); \ +}; + +//CAPNP_DECLARE_TYPE(VOID, Void) +CAPNP_DECLARE_TYPE(BOOL, bool) +CAPNP_DECLARE_TYPE(INT8, int8_t) +CAPNP_DECLARE_TYPE(INT16, int16_t) +CAPNP_DECLARE_TYPE(INT32, int32_t) +CAPNP_DECLARE_TYPE(INT64, int64_t) +CAPNP_DECLARE_TYPE(UINT8, uint8_t) +CAPNP_DECLARE_TYPE(UINT16, uint16_t) +CAPNP_DECLARE_TYPE(UINT32, uint32_t) +CAPNP_DECLARE_TYPE(UINT64, uint64_t) +CAPNP_DECLARE_TYPE(FLOAT32, float) +CAPNP_DECLARE_TYPE(FLOAT64, double) + +CAPNP_DECLARE_TYPE(TEXT, Text) +CAPNP_DECLARE_TYPE(DATA, Data) +CAPNP_DECLARE_TYPE(LIST, DynamicList) +CAPNP_DECLARE_TYPE(STRUCT, DynamicStruct) +CAPNP_DECLARE_TYPE(ENUM, DynamicEnum) +CAPNP_DECLARE_TYPE(ANY_POINTER, AnyPointer) +#undef CAPNP_DECLARE_TYPE + +// CAPNP_DECLARE_TYPE(Void) causes gcc 4.7 to segfault. If I do it manually and remove the +// ReaderFor<> and BuilderFor<> wrappers, it works. +template <> +struct DynamicValue::Reader::AsImpl { + static Void apply(const Reader& reader); +}; +template <> +struct DynamicValue::Builder::AsImpl { + static Void apply(Builder& builder); +}; + +template +struct DynamicValue::Reader::AsImpl { + static T apply(const Reader& reader) { + return reader.as().as(); + } +}; +template +struct DynamicValue::Builder::AsImpl { + static T apply(Builder& builder) { + return builder.as().as(); + } +}; + +template +struct DynamicValue::Reader::AsImpl { + static typename T::Reader apply(const Reader& reader) { + return reader.as().as(); + } +}; +template +struct DynamicValue::Builder::AsImpl { + static typename T::Builder apply(Builder& builder) { + return builder.as().as(); + } +}; + +template +struct DynamicValue::Reader::AsImpl { + static typename T::Reader apply(const Reader& reader) { + return reader.as().as(); + } +}; +template +struct DynamicValue::Builder::AsImpl { + static typename T::Builder apply(Builder& builder) { + return builder.as().as(); + } +}; + +template <> +struct DynamicValue::Reader::AsImpl { + static DynamicValue::Reader apply(const Reader& reader) { + return reader; + } +}; +template <> +struct DynamicValue::Builder::AsImpl { + static DynamicValue::Builder apply(Builder& builder) { + return builder; + } +}; + +// ------------------------------------------------------------------- + +template +typename T::Reader DynamicStruct::Reader::as() const { + static_assert(kind() == Kind::STRUCT, + "DynamicStruct::Reader::as() can only convert to struct types."); + schema.requireUsableAs(); + return typename T::Reader(reader); +} + +template +typename T::Builder DynamicStruct::Builder::as() { + static_assert(kind() == Kind::STRUCT, + "DynamicStruct::Builder::as() can only convert to struct types."); + schema.requireUsableAs(); + return typename T::Builder(builder); +} + +template <> +inline DynamicStruct::Reader DynamicStruct::Reader::as() const { + return *this; +} +template <> +inline DynamicStruct::Builder DynamicStruct::Builder::as() { + return *this; +} + +inline DynamicStruct::Reader DynamicStruct::Builder::asReader() const { + return DynamicStruct::Reader(schema, builder.asReader()); +} + +template <> +inline AnyStruct::Reader DynamicStruct::Reader::as() const { + return AnyStruct::Reader(reader); +} + +template <> +inline AnyStruct::Builder DynamicStruct::Builder::as() { + return AnyStruct::Builder(builder); +} + +template <> +inline DynamicStruct::Reader AnyStruct::Reader::as(StructSchema schema) const { + return DynamicStruct::Reader(schema, _reader); +} + +template <> +inline DynamicStruct::Builder AnyStruct::Builder::as(StructSchema schema) { + return DynamicStruct::Builder(schema, _builder); +} + +template +typename T::Reader DynamicList::Reader::as() const { + static_assert(kind() == Kind::LIST, + "DynamicStruct::Reader::as() can only convert to list types."); + schema.requireUsableAs(); + return typename T::Reader(reader); +} +template +typename T::Builder DynamicList::Builder::as() { + static_assert(kind() == Kind::LIST, + "DynamicStruct::Builder::as() can only convert to list types."); + schema.requireUsableAs(); + return typename T::Builder(builder); +} + +template <> +inline DynamicList::Reader DynamicList::Reader::as() const { + return *this; +} +template <> +inline DynamicList::Builder DynamicList::Builder::as() { + return *this; +} + +template <> +inline AnyList::Reader DynamicList::Reader::as() const { + return AnyList::Reader(reader); +} + +template <> +inline AnyList::Builder DynamicList::Builder::as() { + return AnyList::Builder(builder); +} + +// ------------------------------------------------------------------- + +template +ReaderFor ConstSchema::as() const { + return DynamicValue::Reader(*this).as(); +} + +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/endian.h b/vendor/capnproto/src/capnp/endian.h new file mode 100644 index 0000000..f90063c --- /dev/null +++ b/vendor/capnproto/src/capnp/endian.h @@ -0,0 +1,284 @@ +// 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. + +#pragma once + +#include "common.h" +#include +#include // memcpy + +CAPNP_BEGIN_HEADER + +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 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 +class DirectWireValue { +public: + KJ_ALWAYS_INLINE(T get() const) { return value; } + KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; } + +private: + T value; +}; + +template +using WireValue = DirectWireValue; +// 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 +class SwappingWireValue; + +template +class SwappingWireValue { +public: + KJ_ALWAYS_INLINE(T get() const) { return value; } + KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; } + +private: + T value; +}; + +template +class SwappingWireValue { +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 +class SwappingWireValue { +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 +class SwappingWireValue { +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 +using WireValue = SwappingWireValue; +// 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 +#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 // !CAPNP_DISABLE_ENDIAN_DETECTION + +template +class ShiftingWireValue; + +template +class ShiftingWireValue { +public: + KJ_ALWAYS_INLINE(T get() const) { return value; } + KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; } + +private: + T value; +}; + +template +class ShiftingWireValue { +public: + KJ_ALWAYS_INLINE(T get() const) { + uint16_t raw = (static_cast(bytes[0]) ) | + (static_cast(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 +class ShiftingWireValue { +public: + KJ_ALWAYS_INLINE(T get() const) { + uint32_t raw = (static_cast(bytes[0]) ) | + (static_cast(bytes[1]) << 8) | + (static_cast(bytes[2]) << 16) | + (static_cast(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 +class ShiftingWireValue { +public: + KJ_ALWAYS_INLINE(T get() const) { + uint64_t raw = (static_cast(bytes[0]) ) | + (static_cast(bytes[1]) << 8) | + (static_cast(bytes[2]) << 16) | + (static_cast(bytes[3]) << 24) | + (static_cast(bytes[4]) << 32) | + (static_cast(bytes[5]) << 40) | + (static_cast(bytes[6]) << 48) | + (static_cast(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 +using WireValue = ShiftingWireValue; +// 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 + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/generated-header-support.h b/vendor/capnproto/src/capnp/generated-header-support.h new file mode 100644 index 0000000..a5a2042 --- /dev/null +++ b/vendor/capnproto/src/capnp/generated-header-support.h @@ -0,0 +1,337 @@ +// 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. + +#pragma once + +#include "raw-schema.h" +#include "layout.h" +#include "list.h" +#include "orphan.h" +#include "pointer-helpers.h" +#include "any.h" +#include +#include +#include + +CAPNP_BEGIN_HEADER + +namespace capnp { + +class MessageBuilder; // So that it can be declared a friend. + +template +struct ToDynamic_; // Defined in dynamic.h, needs to be declared as everyone's friend. + +struct DynamicStruct; // So that it can be declared a friend. + +namespace _ { // private + + +template +inline const RawSchema& rawSchema() { + return *CapnpPrivate::schema; +} +template ::typeId> +inline const RawSchema& rawSchema() { + return *schemas::EnumInfo::schema; +} + +template +inline const RawBrandedSchema& rawBrandedSchema() { + return *CapnpPrivate::brand(); +} +template ::typeId> +inline const RawBrandedSchema& rawBrandedSchema() { + return schemas::EnumInfo::schema->defaultBrand; +} + +template +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 +struct ChooseBrand { + // All params were AnyPointer. No specific brand needed. + static constexpr _::RawBrandedSchema const* brand() { return &TypeTag::schema->defaultBrand; } +}; + +template +struct ChooseBrand: public ChooseBrand {}; +// The first parameter is AnyPointer, so recurse to check the rest. + +template +struct ChooseBrand { + // At least one parameter is not AnyPointer, so use the specificBrand constant. + static constexpr _::RawBrandedSchema const* brand() { return &TypeTag::specificBrand; } +}; + +template ()> +struct BrandBindingFor_; + +#define HANDLE_TYPE(Type, which) \ + template <> \ + struct BrandBindingFor_ { \ + 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_ { + static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { + return { 12, listDepth, nullptr }; + } +}; + +template <> +struct BrandBindingFor_ { + static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { + return { 13, listDepth, nullptr }; + } +}; + +template +struct BrandBindingFor_, Kind::LIST> { + static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { + return BrandBindingFor_::get(listDepth + 1); + } +}; + +template +struct BrandBindingFor_ { + static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { + return { 15, listDepth, &rawSchema().defaultBrand }; + } +}; + +template +struct BrandBindingFor_ { + static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { + return { 16, listDepth, T::_capnpPrivate::brand() }; + } +}; + +template <> +struct BrandBindingFor_ { + static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { + return { 18, listDepth, 0, 0 }; + } +}; + +template <> +struct BrandBindingFor_ { + static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { + return { 18, listDepth, 0, 1 }; + } +}; + +template <> +struct BrandBindingFor_ { + static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { + return { 18, listDepth, 0, 2 }; + } +}; + +template +constexpr RawBrandedSchema::Binding brandBindingFor() { + return BrandBindingFor_::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 +inline kj::StringTree structString(StructReader reader) { + return structString(reader, rawBrandedSchema()); +} +template +inline kj::String enumString(T value) { + return enumString(static_cast(value), rawBrandedSchema()); +} + + +// TODO(cleanup): Unify ConstStruct and ConstList. +template +class ConstStruct { +public: + ConstStruct() = delete; + KJ_DISALLOW_COPY_AND_MOVE(ConstStruct); + inline explicit constexpr ConstStruct(const word* ptr): ptr(ptr) {} + + inline typename T::Reader get() const { + return AnyPointer::Reader(PointerReader::getRootUnchecked(ptr)).getAs(); + } + + inline operator typename T::Reader() const { return get(); } + inline typename T::Reader operator*() const { return get(); } + inline TemporaryPointer operator->() const { return get(); } + +private: + const word* ptr; +}; + +template +class ConstList { +public: + ConstList() = delete; + KJ_DISALLOW_COPY_AND_MOVE(ConstList); + inline explicit constexpr ConstList(const word* ptr): ptr(ptr) {} + + inline typename List::Reader get() const { + return AnyPointer::Reader(PointerReader::getRootUnchecked(ptr)).getAs>(); + } + + inline operator typename List::Reader() const { return get(); } + inline typename List::Reader operator*() const { return get(); } + inline TemporaryPointer::Reader> operator->() const { return get(); } + +private: + const word* ptr; +}; + +template +class ConstText { +public: + ConstText() = delete; + KJ_DISALLOW_COPY_AND_MOVE(ConstText); + inline explicit constexpr ConstText(const word* ptr): ptr(ptr) {} + + inline Text::Reader get() const { + return Text::Reader(reinterpret_cast(ptr), size); + } + + inline operator Text::Reader() const { return get(); } + inline Text::Reader operator*() const { return get(); } + inline TemporaryPointer operator->() const { return get(); } + + inline kj::StringPtr toString() const { + return get(); + } + +private: + const word* ptr; +}; + +template +inline kj::StringPtr KJ_STRINGIFY(const ConstText& s) { + return s.get(); +} + +template +class ConstData { +public: + ConstData() = delete; + KJ_DISALLOW_COPY_AND_MOVE(ConstData); + inline explicit constexpr ConstData(const word* ptr): ptr(ptr) {} + + inline Data::Reader get() const { + return Data::Reader(reinterpret_cast(ptr), size); + } + + inline operator Data::Reader() const { return get(); } + inline Data::Reader operator*() const { return get(); } + inline TemporaryPointer operator->() const { return get(); } + +private: + const word* ptr; +}; + +template +inline auto KJ_STRINGIFY(const ConstData& s) -> decltype(kj::toCharSequence(s.get())) { + return kj::toCharSequence(s.get()); +} + +} // namespace _ (private) + +template +inline constexpr uint64_t typeId() { return CapnpPrivate::typeId; } +template ::typeId> +inline constexpr uint64_t typeId() { return id; } +// typeId() returns the type ID as defined in the schema. Works with structs, enums, and +// interfaces. + +} // namespace capnp + +#define CAPNP_NON_INT_CONSTEXPR_DECL_INIT(value) = value +#define CAPNP_NON_INT_CONSTEXPR_DEF_INIT(value) + +#define CAPNP_AUTO_IF_MSVC(...) __VA_ARGS__ + +// TODO(msvc): MSVC does not even expect constexprs to have definitions below C++17. +#if (KJ_CPP_STD < 201703L) && !(defined(_MSC_VER) && !defined(__clang__)) +#define CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL 1 +#else +#define CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL 0 +#endif + + +#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 { \ + 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; \ + } + +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#define CAPNP_DEFINE_ENUM(type, id) \ + constexpr uint64_t EnumInfo::typeId; \ + constexpr ::capnp::_::RawSchema const* EnumInfo::schema +#else +#define CAPNP_DEFINE_ENUM(type, id) +#endif + +#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; + + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/layout.c++ b/vendor/capnproto/src/capnp/layout.c++ new file mode 100644 index 0000000..b6acb21 --- /dev/null +++ b/vendor/capnproto/src/capnp/layout.c++ @@ -0,0 +1,3073 @@ +// 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. + +#define CAPNP_PRIVATE +#include "layout.h" +#include +#include "arena.h" +#include +#include + +namespace capnp { +namespace _ { // private + +#if CAPNP_DEBUG_TYPES +#define G(n) bounded() +#else +#define G(n) n +#endif + +// ======================================================================================= + +#if __GNUC__ >= 8 && !__clang__ +// GCC 8 introduced a warning which complains whenever we try to memset() or memcpy() a +// WirePointer, because we deleted the regular copy constructor / assignment operator. Weirdly, if +// I remove those deletions, GCC *still* complains that WirePointer is non-trivial. I don't +// understand why -- maybe because WireValue has private members? We don't want to make WireValue's +// member public, but memset() and memcpy() on it are certainly valid and desirable, so we'll just +// have to disable the warning I guess. +#pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + +struct WirePointer { + // A pointer, in exactly the format in which it appears on the wire. + + // Copying and moving is not allowed because the offset would become wrong. + WirePointer(const WirePointer& other) = delete; + WirePointer(WirePointer&& other) = delete; + WirePointer& operator=(const WirePointer& other) = delete; + WirePointer& operator=(WirePointer&& other) = delete; + + // ----------------------------------------------------------------- + // Common part of all pointers: kind + offset + // + // Actually this is not terribly common. The "offset" could actually be different things + // depending on the context: + // - For a regular (e.g. struct/list) pointer, a signed word offset from the word immediately + // following the pointer pointer. (The off-by-one means the offset is more often zero, saving + // bytes on the wire when packed.) + // - For an inline composite list tag (not really a pointer, but structured similarly), an + // element count. + // - For a FAR pointer, an unsigned offset into the target segment. + // - For a FAR landing pad, zero indicates that the target value immediately follows the pad while + // 1 indicates that the pad is followed by another FAR pointer that actually points at the + // value. + + enum Kind { + STRUCT = 0, + // Reference points at / describes a struct. + + LIST = 1, + // Reference points at / describes a list. + + FAR = 2, + // Reference is a "far pointer", which points at data located in a different segment. The + // eventual target is one of the other kinds. + + OTHER = 3 + // Reference has type "other". If the next 30 bits are all zero (i.e. the lower 32 bits contain + // only the kind OTHER) then the pointer is a capability. All other values are reserved. + }; + + WireValue offsetAndKind; + + KJ_ALWAYS_INLINE(Kind kind() const) { + return static_cast(offsetAndKind.get() & 3); + } + KJ_ALWAYS_INLINE(bool isPositional() const) { + return (offsetAndKind.get() & 2) == 0; // match STRUCT and LIST but not FAR or OTHER + } + KJ_ALWAYS_INLINE(bool isCapability() const) { + return offsetAndKind.get() == OTHER; + } + + KJ_ALWAYS_INLINE(word* target()) { + return reinterpret_cast(this) + 1 + (static_cast(offsetAndKind.get()) >> 2); + } + KJ_ALWAYS_INLINE(const word* target(SegmentReader* segment) const) { + if (segment == nullptr) { + return reinterpret_cast(this + 1) + + (static_cast(offsetAndKind.get()) >> 2); + } else { + return segment->checkOffset(reinterpret_cast(this + 1), + static_cast(offsetAndKind.get()) >> 2); + } + } + KJ_ALWAYS_INLINE(void setKindAndTarget(Kind kind, word* target, SegmentBuilder* segment)) { + // Check that the target is really in the same segment, otherwise subtracting pointers is + // undefined behavior. As it turns out, it's undefined behavior that actually produces + // unexpected results in a real-world situation that actually happened: At one time, + // OrphanBuilder's "tag" (a WirePointer) was allowed to be initialized as if it lived in + // a particular segment when in fact it does not. On 32-bit systems, where words might + // only be 32-bit aligned, it's possible that the difference between `this` and `target` is + // not a whole number of words. But clang optimizes: + // (target - (word*)this - 1) << 2 + // to: + // (((ptrdiff_t)target - (ptrdiff_t)this - 8) >> 1) + // So now when the pointers are not aligned the same, we can end up corrupting the bottom + // two bits, where `kind` is stored. For example, this turns a struct into a far pointer. + // Ouch! + KJ_DREQUIRE(reinterpret_cast(this) >= + reinterpret_cast(segment->getStartPtr())); + KJ_DREQUIRE(reinterpret_cast(this) < + reinterpret_cast(segment->getStartPtr() + segment->getSize())); + KJ_DREQUIRE(reinterpret_cast(target) >= + reinterpret_cast(segment->getStartPtr())); + KJ_DREQUIRE(reinterpret_cast(target) <= + reinterpret_cast(segment->getStartPtr() + segment->getSize())); + offsetAndKind.set((static_cast(target - reinterpret_cast(this) - 1) << 2) | kind); + } + KJ_ALWAYS_INLINE(void setKindWithZeroOffset(Kind kind)) { + offsetAndKind.set(kind); + } + KJ_ALWAYS_INLINE(void setKindAndTargetForEmptyStruct()) { + // This pointer points at an empty struct. Assuming the WirePointer itself is in-bounds, we + // can set the target to point either at the WirePointer itself or immediately after it. The + // latter would cause the WirePointer to be "null" (since for an empty struct the upper 32 + // bits are going to be zero). So we set an offset of -1, as if the struct were allocated + // immediately before this pointer, to distinguish it from null. + offsetAndKind.set(0xfffffffc); + } + KJ_ALWAYS_INLINE(void setKindForOrphan(Kind kind)) { + // OrphanBuilder contains a WirePointer, but since it isn't located in a segment, it should + // not have a valid offset (unless it is a FAR or OTHER pointer). We set its offset to -1 + // because setting it to zero would mean a pointer to an empty struct would appear to be a null + // pointer. + KJ_DREQUIRE(isPositional()); + offsetAndKind.set(kind | 0xfffffffc); + } + + KJ_ALWAYS_INLINE(ListElementCount inlineCompositeListElementCount() const) { + return ((bounded(offsetAndKind.get()) >> G(2)) + & G(kj::maxValueForBits())) * ELEMENTS; + } + KJ_ALWAYS_INLINE(void setKindAndInlineCompositeListElementCount( + Kind kind, ListElementCount elementCount)) { + offsetAndKind.set(unboundAs((elementCount / ELEMENTS) << G(2)) | kind); + } + + KJ_ALWAYS_INLINE(const word* farTarget(SegmentReader* segment) const) { + KJ_DREQUIRE(kind() == FAR, + "farTarget() should only be called on FAR pointers."); + return segment->checkOffset(segment->getStartPtr(), offsetAndKind.get() >> 3); + } + KJ_ALWAYS_INLINE(word* farTarget(SegmentBuilder* segment) const) { + KJ_DREQUIRE(kind() == FAR, + "farTarget() should only be called on FAR pointers."); + return segment->getPtrUnchecked((bounded(offsetAndKind.get()) >> G(3)) * WORDS); + } + KJ_ALWAYS_INLINE(bool isDoubleFar() const) { + KJ_DREQUIRE(kind() == FAR, + "isDoubleFar() should only be called on FAR pointers."); + return (offsetAndKind.get() >> 2) & 1; + } + KJ_ALWAYS_INLINE(void setFar(bool isDoubleFar, WordCountN<29> pos)) { + offsetAndKind.set(unboundAs((pos / WORDS) << G(3)) | + (static_cast(isDoubleFar) << 2) | + static_cast(Kind::FAR)); + } + + // ----------------------------------------------------------------- + // Part of pointer that depends on the kind. + + // Note: Originally StructRef, ListRef, and FarRef were unnamed types, but this somehow + // tickled a bug in GCC: + // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58192 + struct StructRef { + WireValue dataSize; + WireValue ptrCount; + + inline WordCountN<17> wordSize() const { + return upgradeBound(dataSize.get()) + ptrCount.get() * WORDS_PER_POINTER; + } + + KJ_ALWAYS_INLINE(void set(WordCount16 ds, WirePointerCount16 rc)) { + dataSize.set(ds); + ptrCount.set(rc); + } + KJ_ALWAYS_INLINE(void set(StructSize size)) { + dataSize.set(size.data); + ptrCount.set(size.pointers); + } + }; + + struct ListRef { + WireValue elementSizeAndCount; + + KJ_ALWAYS_INLINE(ElementSize elementSize() const) { + return static_cast(elementSizeAndCount.get() & 7); + } + KJ_ALWAYS_INLINE(ElementCountN<29> elementCount() const) { + return (bounded(elementSizeAndCount.get()) >> G(3)) * ELEMENTS; + } + KJ_ALWAYS_INLINE(WordCountN<29> inlineCompositeWordCount() const) { + return elementCount() * (ONE * WORDS / ELEMENTS); + } + + KJ_ALWAYS_INLINE(void set(ElementSize es, ElementCountN<29> ec)) { + elementSizeAndCount.set(unboundAs((ec / ELEMENTS) << G(3)) | + static_cast(es)); + } + + KJ_ALWAYS_INLINE(void setInlineComposite(WordCountN<29> wc)) { + elementSizeAndCount.set(unboundAs((wc / WORDS) << G(3)) | + static_cast(ElementSize::INLINE_COMPOSITE)); + } + }; + + struct FarRef { + WireValue segmentId; + + KJ_ALWAYS_INLINE(void set(SegmentId si)) { + segmentId.set(si); + } + }; + + union { + uint32_t upper32Bits; + + StructRef structRef; + + ListRef listRef; + + FarRef farRef; + }; + + KJ_ALWAYS_INLINE(bool isNull() const) { + // If the upper 32 bits are zero, this is a pointer to an empty struct. We consider that to be + // our "null" value. + return (offsetAndKind.get() == 0) & (upper32Bits == 0); + } + +}; +static_assert(sizeof(WirePointer) == sizeof(word), + "capnp::WirePointer is not exactly one word. This will probably break everything."); +static_assert(unboundAs(POINTERS * WORDS_PER_POINTER * BYTES_PER_WORD / BYTES) == + sizeof(WirePointer), + "WORDS_PER_POINTER is wrong."); +static_assert(unboundAs(POINTERS * BYTES_PER_POINTER / BYTES) == sizeof(WirePointer), + "BYTES_PER_POINTER is wrong."); +static_assert(unboundAs(POINTERS * BITS_PER_POINTER / BITS_PER_BYTE / BYTES) == + sizeof(WirePointer), + "BITS_PER_POINTER is wrong."); + +#define OUT_OF_BOUNDS_ERROR_DETAIL \ + "This usually indicates that " \ + "the input data was corrupted, used a different encoding than specified (e.g. " \ + "packed vs. non-packed), or was not a Cap'n Proto message to begin with. Note " \ + "that this error is NOT due to a schema mismatch; the input is invalid " \ + "regardless of schema." + +namespace { + +static const union { + AlignedData word; + WirePointer pointer; +} zero = {{{0}}}; + +} // namespace + +// ======================================================================================= + +namespace { + +template +struct SegmentAnd { + SegmentBuilder* segment; + T value; +}; + +} // namespace + +struct WireHelpers { +#if CAPNP_DEBUG_TYPES + template + static KJ_ALWAYS_INLINE( + kj::Quantity, word> roundBytesUpToWords( + kj::Quantity, byte> bytes)) { + static_assert(sizeof(word) == 8, "This code assumes 64-bit words."); + return (bytes + G(7) * BYTES) / BYTES_PER_WORD; + } + + template + static KJ_ALWAYS_INLINE( + kj::Quantity, byte> roundBitsUpToBytes( + kj::Quantity, BitLabel> bits)) { + return (bits + G(7) * BITS) / BITS_PER_BYTE; + } + + template + static KJ_ALWAYS_INLINE( + kj::Quantity, word> roundBitsUpToWords( + kj::Quantity, BitLabel> bits)) { + static_assert(sizeof(word) == 8, "This code assumes 64-bit words."); + return (bits + G(63) * BITS) / BITS_PER_WORD; + } +#else + static KJ_ALWAYS_INLINE(WordCount roundBytesUpToWords(ByteCount bytes)) { + static_assert(sizeof(word) == 8, "This code assumes 64-bit words."); + return (bytes + G(7) * BYTES) / BYTES_PER_WORD; + } + + static KJ_ALWAYS_INLINE(ByteCount roundBitsUpToBytes(BitCount bits)) { + return (bits + G(7) * BITS) / BITS_PER_BYTE; + } + + static KJ_ALWAYS_INLINE(WordCount64 roundBitsUpToWords(BitCount64 bits)) { + static_assert(sizeof(word) == 8, "This code assumes 64-bit words."); + return (bits + G(63) * BITS) / BITS_PER_WORD; + } + + static KJ_ALWAYS_INLINE(ByteCount64 roundBitsUpToBytes(BitCount64 bits)) { + return (bits + G(7) * BITS) / BITS_PER_BYTE; + } +#endif + + static KJ_ALWAYS_INLINE(void zeroMemory(byte* ptr, ByteCount32 count)) { + if (count != ZERO * BYTES) memset(ptr, 0, unbound(count / BYTES)); + } + + static KJ_ALWAYS_INLINE(void zeroMemory(word* ptr, WordCountN<29> count)) { + if (count != ZERO * WORDS) memset(ptr, 0, unbound(count * BYTES_PER_WORD / BYTES)); + } + + static KJ_ALWAYS_INLINE(void zeroMemory(WirePointer* ptr, WirePointerCountN<29> count)) { + if (count != ZERO * POINTERS) memset(ptr, 0, unbound(count * BYTES_PER_POINTER / BYTES)); + } + + static KJ_ALWAYS_INLINE(void zeroMemory(WirePointer* ptr)) { + memset(ptr, 0, sizeof(*ptr)); + } + + template + static inline void zeroMemory(kj::ArrayPtr array) { + if (array.size() != 0u) memset(array.begin(), 0, array.size() * sizeof(array[0])); + } + + static KJ_ALWAYS_INLINE(void copyMemory(byte* to, const byte* from, ByteCount32 count)) { + if (count != ZERO * BYTES) memcpy(to, from, unbound(count / BYTES)); + } + + static KJ_ALWAYS_INLINE(void copyMemory(word* to, const word* from, WordCountN<29> count)) { + if (count != ZERO * WORDS) memcpy(to, from, unbound(count * BYTES_PER_WORD / BYTES)); + } + + static KJ_ALWAYS_INLINE(void copyMemory(WirePointer* to, const WirePointer* from, + WirePointerCountN<29> count)) { + if (count != ZERO * POINTERS) memcpy(to, from, unbound(count * BYTES_PER_POINTER / BYTES)); + } + + template + static inline void copyMemory(T* to, const T* from) { + memcpy(to, from, sizeof(*from)); + } + + // TODO(cleanup): Turn these into a .copyTo() method of ArrayPtr? + template + static inline void copyMemory(T* to, kj::ArrayPtr from) { + if (from.size() != 0u) memcpy(to, from.begin(), from.size() * sizeof(from[0])); + } + template + static inline void copyMemory(T* to, kj::ArrayPtr from) { + if (from.size() != 0u) memcpy(to, from.begin(), from.size() * sizeof(from[0])); + } + static KJ_ALWAYS_INLINE(void copyMemory(char* to, kj::StringPtr from)) { + if (from.size() != 0u) memcpy(to, from.begin(), from.size() * sizeof(from[0])); + } + + static KJ_ALWAYS_INLINE(bool boundsCheck( + SegmentReader* segment, const word* start, WordCountN<31> size)) { + // If segment is null, this is an unchecked message, so we don't do bounds checks. + return segment == nullptr || segment->checkObject(start, size); + } + + static KJ_ALWAYS_INLINE(bool amplifiedRead(SegmentReader* segment, WordCount virtualAmount)) { + // If segment is null, this is an unchecked message, so we don't do read limiter checks. + return segment == nullptr || segment->amplifiedRead(virtualAmount); + } + + static KJ_ALWAYS_INLINE(word* allocate( + WirePointer*& ref, SegmentBuilder*& segment, SegmentWordCount amount, WirePointer::Kind kind, BuilderArena* orphanArena)) { + // Allocate space in the message for a new object, creating far pointers if necessary. The + // space is guaranteed to be zero'd (because MessageBuilder implementations are required to + // return zero'd memory). + // + // * `ref` starts out being a reference to the pointer which shall be assigned to point at the + // new object. On return, `ref` points to a pointer which needs to be initialized with + // the object's type information. Normally this is the same pointer, but it can change if + // a far pointer was allocated -- in this case, `ref` will end up pointing to the far + // pointer's tag. Either way, `allocate()` takes care of making sure that the original + // pointer ends up leading to the new object. On return, only the upper 32 bit of `*ref` + // need to be filled in by the caller. + // * `segment` starts out pointing to the segment containing `ref`. On return, it points to + // the segment containing the allocated object, which is usually the same segment but could + // be a different one if the original segment was out of space. + // * `amount` is the number of words to allocate. + // * `kind` is the kind of object to allocate. It is used to initialize the pointer. It + // cannot be `FAR` -- far pointers are allocated automatically as needed. + // * `orphanArena` is usually null. If it is non-null, then we're allocating an orphan object. + // In this case, `segment` starts out null; the allocation takes place in an arbitrary + // segment belonging to the arena. `ref` will be initialized as a non-far pointer, but its + // target offset will be set to zero. + + if (orphanArena == nullptr) { + if (!ref->isNull()) zeroObject(segment, ref); + + if (amount == ZERO * WORDS && kind == WirePointer::STRUCT) { + // Note that the check for kind == WirePointer::STRUCT will hopefully cause this whole + // branch to be optimized away from all the call sites that are allocating non-structs. + ref->setKindAndTargetForEmptyStruct(); + return reinterpret_cast(ref); + } + + KJ_ASSUME(segment != nullptr); + word* ptr = segment->allocate(amount); + + if (ptr == nullptr) { + + // Need to allocate in a new segment. We'll need to allocate an extra pointer worth of + // space to act as the landing pad for a far pointer. + + WordCount amountPlusRef = amount + POINTER_SIZE_IN_WORDS; + auto allocation = segment->getArena()->allocate( + assertMaxBits(amountPlusRef, []() { + KJ_FAIL_REQUIRE("requested object size exceeds maximum segment size"); + })); + segment = allocation.segment; + ptr = allocation.words; + + // Set up the original pointer to be a far pointer to the new segment. + ref->setFar(false, segment->getOffsetTo(ptr)); + ref->farRef.set(segment->getSegmentId()); + + // Initialize the landing pad to indicate that the data immediately follows the pad. + ref = reinterpret_cast(ptr); + ref->setKindAndTarget(kind, ptr + POINTER_SIZE_IN_WORDS, segment); + + // Allocated space follows new pointer. + return ptr + POINTER_SIZE_IN_WORDS; + } else { + ref->setKindAndTarget(kind, ptr, segment); + return ptr; + } + } else { + // orphanArena is non-null. Allocate an orphan. + KJ_DASSERT(ref->isNull()); + auto allocation = orphanArena->allocate(amount); + segment = allocation.segment; + ref->setKindForOrphan(kind); + return allocation.words; + } + } + + static KJ_ALWAYS_INLINE(word* followFars( + WirePointer*& ref, word* refTarget, SegmentBuilder*& segment)) { + // If `ref` is a far pointer, follow it. On return, `ref` will have been updated to point at + // a WirePointer that contains the type information about the target object, and a pointer to + // the object contents is returned. The caller must NOT use `ref->target()` as this may or may + // not actually return a valid pointer. `segment` is also updated to point at the segment which + // actually contains the object. + // + // If `ref` is not a far pointer, this simply returns `refTarget`. Usually, `refTarget` should + // be the same as `ref->target()`, but may not be in cases where `ref` is only a tag. + + if (ref->kind() == WirePointer::FAR) { + segment = segment->getArena()->getSegment(ref->farRef.segmentId.get()); + WirePointer* pad = reinterpret_cast(ref->farTarget(segment)); + if (!ref->isDoubleFar()) { + ref = pad; + return pad->target(); + } + + // Landing pad is another far pointer. It is followed by a tag describing the pointed-to + // object. + ref = pad + 1; + + segment = segment->getArena()->getSegment(pad->farRef.segmentId.get()); + return pad->farTarget(segment); + } else { + return refTarget; + } + } + + static KJ_ALWAYS_INLINE(kj::Maybe followFars( + const WirePointer*& ref, const word* refTarget, SegmentReader*& segment)) + KJ_WARN_UNUSED_RESULT { + // Like the other followFars() but operates on readers. + + // If the segment is null, this is an unchecked message, so there are no FAR pointers. + if (segment != nullptr && ref->kind() == WirePointer::FAR) { + // Look up the segment containing the landing pad. + segment = segment->getArena()->tryGetSegment(ref->farRef.segmentId.get()); + KJ_REQUIRE(segment != nullptr, "Message contains far pointer to unknown segment.") { + return nullptr; + } + + // Find the landing pad and check that it is within bounds. + const word* ptr = ref->farTarget(segment); + auto padWords = (ONE + bounded(ref->isDoubleFar())) * POINTER_SIZE_IN_WORDS; + KJ_REQUIRE(boundsCheck(segment, ptr, padWords), + "Message contains out-of-bounds far pointer. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + return nullptr; + } + + const WirePointer* pad = reinterpret_cast(ptr); + + // If this is not a double-far then the landing pad is our final pointer. + if (!ref->isDoubleFar()) { + ref = pad; + return pad->target(segment); + } + + // Landing pad is another far pointer. It is followed by a tag describing the pointed-to + // object. + ref = pad + 1; + + SegmentReader* newSegment = segment->getArena()->tryGetSegment(pad->farRef.segmentId.get()); + KJ_REQUIRE(newSegment != nullptr, + "Message contains double-far pointer to unknown segment.") { + return nullptr; + } + KJ_REQUIRE(pad->kind() == WirePointer::FAR, + "Second word of double-far pad must be far pointer.") { + return nullptr; + } + + segment = newSegment; + return pad->farTarget(segment); + } else { + KJ_DASSERT(refTarget != nullptr); + return refTarget; + } + } + + // ----------------------------------------------------------------- + + static void zeroObject(SegmentBuilder* segment, WirePointer* ref) { + // Zero out the pointed-to object. Use when the pointer is about to be overwritten making the + // target object no longer reachable. + + switch (ref->kind()) { + case WirePointer::STRUCT: + case WirePointer::LIST: + zeroObject(segment, ref, ref->target()); + break; + case WirePointer::FAR: { + segment = segment->getArena()->getSegment(ref->farRef.segmentId.get()); + WirePointer* pad = reinterpret_cast(ref->farTarget(segment)); + + if (ref->isDoubleFar()) { + segment = segment->getArena()->getSegment(pad->farRef.segmentId.get()); + zeroObject(segment, pad + 1, pad->farTarget(segment)); + + zeroMemory(pad, G(2) * POINTERS); + } else { + zeroObject(segment, pad); + zeroMemory(pad); + } + + break; + } + case WirePointer::OTHER: + if (ref->isCapability()) { + KJ_FAIL_ASSERT("Capability pointers are unsupported.") { break; } + } else { + KJ_FAIL_REQUIRE("Unknown pointer type.") { break; } + } + break; + } + } + + static void zeroObject(SegmentBuilder* segment, WirePointer* tag, word* ptr) { + + switch (tag->kind()) { + case WirePointer::STRUCT: { + WirePointer* pointerSection = + reinterpret_cast(ptr + tag->structRef.dataSize.get()); + for (auto i: kj::zeroTo(tag->structRef.ptrCount.get())) { + zeroObject(segment, pointerSection + i); + } + zeroMemory(ptr, tag->structRef.wordSize()); + break; + } + case WirePointer::LIST: { + switch (tag->listRef.elementSize()) { + case ElementSize::VOID: + // Nothing. + break; + case ElementSize::BIT: + case ElementSize::BYTE: + case ElementSize::TWO_BYTES: + case ElementSize::FOUR_BYTES: + case ElementSize::EIGHT_BYTES: { + zeroMemory(ptr, roundBitsUpToWords( + upgradeBound(tag->listRef.elementCount()) * + dataBitsPerElement(tag->listRef.elementSize()))); + break; + } + case ElementSize::POINTER: { + WirePointer* typedPtr = reinterpret_cast(ptr); + auto count = tag->listRef.elementCount() * (ONE * POINTERS / ELEMENTS); + for (auto i: kj::zeroTo(count)) { + zeroObject(segment, typedPtr + i); + } + zeroMemory(typedPtr, count); + break; + } + case ElementSize::INLINE_COMPOSITE: { + WirePointer* elementTag = reinterpret_cast(ptr); + + KJ_ASSERT(elementTag->kind() == WirePointer::STRUCT, + "Don't know how to handle non-STRUCT inline composite."); + WordCount dataSize = elementTag->structRef.dataSize.get(); + WirePointerCount pointerCount = elementTag->structRef.ptrCount.get(); + + auto count = elementTag->inlineCompositeListElementCount(); + if (pointerCount > ZERO * POINTERS) { + word* pos = ptr + POINTER_SIZE_IN_WORDS; + for (auto i KJ_UNUSED: kj::zeroTo(count)) { + pos += dataSize; + + for (auto j KJ_UNUSED: kj::zeroTo(pointerCount)) { + zeroObject(segment, reinterpret_cast(pos)); + pos += POINTER_SIZE_IN_WORDS; + } + } + } + + auto wordsPerElement = elementTag->structRef.wordSize() / ELEMENTS; + zeroMemory(ptr, assertMaxBits(POINTER_SIZE_IN_WORDS + + upgradeBound(count) * wordsPerElement, []() { + KJ_FAIL_ASSERT("encountered list pointer in builder which is too large to " + "possibly fit in a segment. Bug in builder code?"); + })); + break; + } + } + break; + } + case WirePointer::FAR: + KJ_FAIL_ASSERT("Unexpected FAR pointer.") { + break; + } + break; + case WirePointer::OTHER: + KJ_FAIL_ASSERT("Unexpected OTHER pointer.") { + break; + } + break; + } + } + + static KJ_ALWAYS_INLINE( + void zeroPointerAndFars(SegmentBuilder* segment, WirePointer* ref)) { + // Zero out the pointer itself and, if it is a far pointer, zero the landing pad as well, but + // do not zero the object body. Used when upgrading. + + if (ref->kind() == WirePointer::FAR) { + SegmentBuilder* padSegment = segment->getArena()->getSegment(ref->farRef.segmentId.get()); + WirePointer* pad = reinterpret_cast(ref->farTarget(padSegment)); + if (ref->isDoubleFar()) { + zeroMemory(pad, G(2) * POINTERS); + } else { + zeroMemory(pad); + } + + } + + zeroMemory(ref); + } + + // ----------------------------------------------------------------- + + static MessageSizeCounts totalSize( + SegmentReader* segment, const WirePointer* ref, int nestingLimit) { + // Compute the total size of the object pointed to, not counting far pointer overhead. + + MessageSizeCounts result = { ZERO * WORDS, 0 }; + + if (ref->isNull()) { + return result; + } + + KJ_REQUIRE(nestingLimit > 0, "Message is too deeply-nested.") { + return result; + } + --nestingLimit; + + const word* ptr; + KJ_IF_MAYBE(p, followFars(ref, ref->target(segment), segment)) { + ptr = p; + } else { + return result; + } + + switch (ref->kind()) { + case WirePointer::STRUCT: { + KJ_REQUIRE(boundsCheck(segment, ptr, ref->structRef.wordSize()), + "Message contained out-of-bounds struct pointer. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + return result; + } + result.addWords(ref->structRef.wordSize()); + + const WirePointer* pointerSection = + reinterpret_cast(ptr + ref->structRef.dataSize.get()); + for (auto i: kj::zeroTo(ref->structRef.ptrCount.get())) { + result += totalSize(segment, pointerSection + i, nestingLimit); + } + break; + } + case WirePointer::LIST: { + switch (ref->listRef.elementSize()) { + case ElementSize::VOID: + // Nothing. + break; + case ElementSize::BIT: + case ElementSize::BYTE: + case ElementSize::TWO_BYTES: + case ElementSize::FOUR_BYTES: + case ElementSize::EIGHT_BYTES: { + auto totalWords = roundBitsUpToWords( + upgradeBound(ref->listRef.elementCount()) * + dataBitsPerElement(ref->listRef.elementSize())); + KJ_REQUIRE(boundsCheck(segment, ptr, totalWords), + "Message contained out-of-bounds list pointer. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + return result; + } + result.addWords(totalWords); + break; + } + case ElementSize::POINTER: { + auto count = ref->listRef.elementCount() * (POINTERS / ELEMENTS); + + KJ_REQUIRE(boundsCheck(segment, ptr, count * WORDS_PER_POINTER), + "Message contained out-of-bounds list pointer. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + return result; + } + + result.addWords(count * WORDS_PER_POINTER); + + for (auto i: kj::zeroTo(count)) { + result += totalSize(segment, reinterpret_cast(ptr) + i, + nestingLimit); + } + break; + } + case ElementSize::INLINE_COMPOSITE: { + auto wordCount = ref->listRef.inlineCompositeWordCount(); + KJ_REQUIRE(boundsCheck(segment, ptr, wordCount + POINTER_SIZE_IN_WORDS), + "Message contained out-of-bounds list pointer. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + return result; + } + + const WirePointer* elementTag = reinterpret_cast(ptr); + auto count = elementTag->inlineCompositeListElementCount(); + + KJ_REQUIRE(elementTag->kind() == WirePointer::STRUCT, + "Don't know how to handle non-STRUCT inline composite.") { + return result; + } + + auto actualSize = elementTag->structRef.wordSize() / ELEMENTS * + upgradeBound(count); + KJ_REQUIRE(actualSize <= wordCount, + "Struct list pointer's elements overran size. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + return result; + } + + // We count the actual size rather than the claimed word count because that's what + // we'll end up with if we make a copy. + result.addWords(actualSize + POINTER_SIZE_IN_WORDS); + + WordCount dataSize = elementTag->structRef.dataSize.get(); + WirePointerCount pointerCount = elementTag->structRef.ptrCount.get(); + + if (pointerCount > ZERO * POINTERS) { + const word* pos = ptr + POINTER_SIZE_IN_WORDS; + for (auto i KJ_UNUSED: kj::zeroTo(count)) { + pos += dataSize; + + for (auto j KJ_UNUSED: kj::zeroTo(pointerCount)) { + result += totalSize(segment, reinterpret_cast(pos), + nestingLimit); + pos += POINTER_SIZE_IN_WORDS; + } + } + } + break; + } + } + break; + } + case WirePointer::FAR: + KJ_FAIL_REQUIRE("Unexpected FAR pointer.") { + break; + } + break; + case WirePointer::OTHER: + if (ref->isCapability()) { + result.capCount++; + } else { + KJ_FAIL_REQUIRE("Unknown pointer type.") { break; } + } + break; + } + + return result; + } + + // ----------------------------------------------------------------- + // Copy from an unchecked message. + + static KJ_ALWAYS_INLINE( + void copyStruct(SegmentBuilder* segment, word* dst, const word* src, + StructDataWordCount dataSize, StructPointerCount pointerCount)) { + copyMemory(dst, src, dataSize); + + const WirePointer* srcRefs = reinterpret_cast(src + dataSize); + WirePointer* dstRefs = reinterpret_cast(dst + dataSize); + + for (auto i: kj::zeroTo(pointerCount)) { + SegmentBuilder* subSegment = segment; + WirePointer* dstRef = dstRefs + i; + copyMessage(subSegment, dstRef, srcRefs + i); + } + } + + static word* copyMessage( + SegmentBuilder*& segment, WirePointer*& dst, const WirePointer* src) { + // Not always-inline because it's recursive. + + switch (src->kind()) { + case WirePointer::STRUCT: { + if (src->isNull()) { + zeroMemory(dst); + return nullptr; + } else { + const word* srcPtr = src->target(nullptr); + word* dstPtr = allocate( + dst, segment, src->structRef.wordSize(), WirePointer::STRUCT, nullptr); + + copyStruct(segment, dstPtr, srcPtr, src->structRef.dataSize.get(), + src->structRef.ptrCount.get()); + + dst->structRef.set(src->structRef.dataSize.get(), src->structRef.ptrCount.get()); + return dstPtr; + } + } + case WirePointer::LIST: { + switch (src->listRef.elementSize()) { + case ElementSize::VOID: + case ElementSize::BIT: + case ElementSize::BYTE: + case ElementSize::TWO_BYTES: + case ElementSize::FOUR_BYTES: + case ElementSize::EIGHT_BYTES: { + auto wordCount = roundBitsUpToWords( + upgradeBound(src->listRef.elementCount()) * + dataBitsPerElement(src->listRef.elementSize())); + const word* srcPtr = src->target(nullptr); + word* dstPtr = allocate(dst, segment, wordCount, WirePointer::LIST, nullptr); + copyMemory(dstPtr, srcPtr, wordCount); + + dst->listRef.set(src->listRef.elementSize(), src->listRef.elementCount()); + return dstPtr; + } + + case ElementSize::POINTER: { + const WirePointer* srcRefs = reinterpret_cast(src->target(nullptr)); + WirePointer* dstRefs = reinterpret_cast( + allocate(dst, segment, src->listRef.elementCount() * + (ONE * POINTERS / ELEMENTS) * WORDS_PER_POINTER, + WirePointer::LIST, nullptr)); + + for (auto i: kj::zeroTo(src->listRef.elementCount() * (ONE * POINTERS / ELEMENTS))) { + SegmentBuilder* subSegment = segment; + WirePointer* dstRef = dstRefs + i; + copyMessage(subSegment, dstRef, srcRefs + i); + } + + dst->listRef.set(ElementSize::POINTER, src->listRef.elementCount()); + return reinterpret_cast(dstRefs); + } + + case ElementSize::INLINE_COMPOSITE: { + const word* srcPtr = src->target(nullptr); + word* dstPtr = allocate(dst, segment, assertMaxBits( + src->listRef.inlineCompositeWordCount() + POINTER_SIZE_IN_WORDS, + []() { KJ_FAIL_ASSERT("list too big to fit in a segment"); }), + WirePointer::LIST, nullptr); + + dst->listRef.setInlineComposite(src->listRef.inlineCompositeWordCount()); + + const WirePointer* srcTag = reinterpret_cast(srcPtr); + copyMemory(reinterpret_cast(dstPtr), srcTag); + + const word* srcElement = srcPtr + POINTER_SIZE_IN_WORDS; + word* dstElement = dstPtr + POINTER_SIZE_IN_WORDS; + + KJ_ASSERT(srcTag->kind() == WirePointer::STRUCT, + "INLINE_COMPOSITE of lists is not yet supported."); + + for (auto i KJ_UNUSED: kj::zeroTo(srcTag->inlineCompositeListElementCount())) { + copyStruct(segment, dstElement, srcElement, + srcTag->structRef.dataSize.get(), srcTag->structRef.ptrCount.get()); + srcElement += srcTag->structRef.wordSize(); + dstElement += srcTag->structRef.wordSize(); + } + return dstPtr; + } + } + break; + } + case WirePointer::OTHER: + KJ_FAIL_REQUIRE("Unchecked messages cannot contain OTHER pointers (e.g. capabilities)."); + break; + case WirePointer::FAR: + KJ_FAIL_REQUIRE("Unchecked messages cannot contain far pointers."); + break; + } + + return nullptr; + } + + static void transferPointer(SegmentBuilder* dstSegment, WirePointer* dst, + SegmentBuilder* srcSegment, WirePointer* src) { + // Make *dst point to the same object as *src. Both must reside in the same message, but can + // be in different segments. Not always-inline because this is rarely used. + // + // Caller MUST zero out the source pointer after calling this, to make sure no later code + // mistakenly thinks the source location still owns the object. transferPointer() doesn't do + // this zeroing itself because many callers transfer several pointers in a loop then zero out + // the whole section. + + KJ_DASSERT(dst->isNull()); + // We expect the caller to ensure the target is already null so won't leak. + + if (src->isNull()) { + zeroMemory(dst); + } else if (src->isPositional()) { + transferPointer(dstSegment, dst, srcSegment, src, src->target()); + } else { + // Far and other pointers are position-independent, so we can just copy. + copyMemory(dst, src); + } + } + + static void transferPointer(SegmentBuilder* dstSegment, WirePointer* dst, + SegmentBuilder* srcSegment, const WirePointer* srcTag, + word* srcPtr) { + // Like the other overload, but splits src into a tag and a target. Particularly useful for + // OrphanBuilder. + + if (dstSegment == srcSegment) { + // Same segment, so create a direct pointer. + + if (srcTag->kind() == WirePointer::STRUCT && srcTag->structRef.wordSize() == ZERO * WORDS) { + dst->setKindAndTargetForEmptyStruct(); + } else { + dst->setKindAndTarget(srcTag->kind(), srcPtr, dstSegment); + } + + // We can just copy the upper 32 bits. (Use memcpy() to comply with aliasing rules.) + copyMemory(&dst->upper32Bits, &srcTag->upper32Bits); + } else { + // Need to create a far pointer. Try to allocate it in the same segment as the source, so + // that it doesn't need to be a double-far. + + WirePointer* landingPad = + reinterpret_cast(srcSegment->allocate(G(1) * WORDS)); + if (landingPad == nullptr) { + // Darn, need a double-far. + auto allocation = srcSegment->getArena()->allocate(G(2) * WORDS); + SegmentBuilder* farSegment = allocation.segment; + landingPad = reinterpret_cast(allocation.words); + + landingPad[0].setFar(false, srcSegment->getOffsetTo(srcPtr)); + landingPad[0].farRef.segmentId.set(srcSegment->getSegmentId()); + + landingPad[1].setKindWithZeroOffset(srcTag->kind()); + copyMemory(&landingPad[1].upper32Bits, &srcTag->upper32Bits); + + dst->setFar(true, farSegment->getOffsetTo(reinterpret_cast(landingPad))); + dst->farRef.set(farSegment->getSegmentId()); + } else { + // Simple landing pad is just a pointer. + landingPad->setKindAndTarget(srcTag->kind(), srcPtr, srcSegment); + copyMemory(&landingPad->upper32Bits, &srcTag->upper32Bits); + + dst->setFar(false, srcSegment->getOffsetTo(reinterpret_cast(landingPad))); + dst->farRef.set(srcSegment->getSegmentId()); + } + } + } + + // ----------------------------------------------------------------- + + static KJ_ALWAYS_INLINE(StructBuilder initStructPointer( + WirePointer* ref, SegmentBuilder* segment, StructSize size, + BuilderArena* orphanArena = nullptr)) { + // Allocate space for the new struct. Newly-allocated space is automatically zeroed. + word* ptr = allocate(ref, segment, size.total(), WirePointer::STRUCT, orphanArena); + + // Initialize the pointer. + ref->structRef.set(size); + + // Build the StructBuilder. + return StructBuilder(segment, ptr, reinterpret_cast(ptr + size.data), + size.data * BITS_PER_WORD, size.pointers); + } + + static KJ_ALWAYS_INLINE(StructBuilder getWritableStructPointer( + WirePointer* ref, SegmentBuilder* segment, StructSize size, + const word* defaultValue)) { + return getWritableStructPointer(ref, ref->target(), segment, size, defaultValue); + } + + static KJ_ALWAYS_INLINE(StructBuilder getWritableStructPointer( + WirePointer* ref, word* refTarget, SegmentBuilder* segment, StructSize size, const word* defaultValue, BuilderArena* orphanArena = nullptr)) { + if (ref->isNull()) { + useDefault: + if (defaultValue == nullptr || + reinterpret_cast(defaultValue)->isNull()) { + return initStructPointer(ref, segment, size, orphanArena); + } + refTarget = copyMessage(segment, ref, + reinterpret_cast(defaultValue)); + defaultValue = nullptr; // If the default value is itself invalid, don't use it again. + } + + WirePointer* oldRef = ref; + SegmentBuilder* oldSegment = segment; + word* oldPtr = followFars(oldRef, refTarget, oldSegment); + + KJ_REQUIRE(oldRef->kind() == WirePointer::STRUCT, + "Schema mismatch: Message contains non-struct pointer where struct pointer was expected.") { + goto useDefault; + } + + auto oldDataSize = oldRef->structRef.dataSize.get(); + auto oldPointerCount = oldRef->structRef.ptrCount.get(); + WirePointer* oldPointerSection = + reinterpret_cast(oldPtr + oldDataSize); + + if (oldDataSize < size.data || oldPointerCount < size.pointers) { + // The space allocated for this struct is too small. Unlike with readers, we can't just + // run with it and do bounds checks at access time, because how would we handle writes? + // Instead, we have to copy the struct to a new space now. + + auto newDataSize = kj::max(oldDataSize, size.data); + auto newPointerCount = kj::max(oldPointerCount, size.pointers); + auto totalSize = newDataSize + newPointerCount * WORDS_PER_POINTER; + + // Don't let allocate() zero out the object just yet. + zeroPointerAndFars(segment, ref); + + word* ptr = allocate(ref, segment, totalSize, WirePointer::STRUCT, orphanArena); + ref->structRef.set(newDataSize, newPointerCount); + + // Copy data section. + copyMemory(ptr, oldPtr, oldDataSize); + + // Copy pointer section. + WirePointer* newPointerSection = reinterpret_cast(ptr + newDataSize); + for (auto i: kj::zeroTo(oldPointerCount)) { + transferPointer(segment, newPointerSection + i, oldSegment, oldPointerSection + i); + } + + // Zero out old location. This has two purposes: + // 1) We don't want to leak the original contents of the struct when the message is written + // out as it may contain secrets that the caller intends to remove from the new copy. + // 2) Zeros will be deflated by packing, making this dead memory almost-free if it ever + // hits the wire. + zeroMemory(oldPtr, oldDataSize + oldPointerCount * WORDS_PER_POINTER); + + return StructBuilder(segment, ptr, newPointerSection, newDataSize * BITS_PER_WORD, + newPointerCount); + } else { + return StructBuilder(oldSegment, oldPtr, oldPointerSection, + oldDataSize * BITS_PER_WORD, oldPointerCount); + } + } + + static KJ_ALWAYS_INLINE(ListBuilder initListPointer( + WirePointer* ref, SegmentBuilder* segment, ElementCount elementCount, ElementSize elementSize, BuilderArena* orphanArena = nullptr)) { + KJ_DREQUIRE(elementSize != ElementSize::INLINE_COMPOSITE, + "Should have called initStructListPointer() instead."); + + auto checkedElementCount = assertMaxBits(elementCount, + []() { KJ_FAIL_REQUIRE("tried to allocate list with too many elements"); }); + + auto dataSize = dataBitsPerElement(elementSize) * ELEMENTS; + auto pointerCount = pointersPerElement(elementSize) * ELEMENTS; + auto step = bitsPerElementIncludingPointers(elementSize); + KJ_DASSERT(step * ELEMENTS == (dataSize + pointerCount * BITS_PER_POINTER)); + + // Calculate size of the list. + auto wordCount = roundBitsUpToWords(upgradeBound(checkedElementCount) * step); + + // Allocate the list. + word* ptr = allocate(ref, segment, wordCount, WirePointer::LIST, orphanArena); + + // Initialize the pointer. + ref->listRef.set(elementSize, checkedElementCount); + + // Build the ListBuilder. + return ListBuilder(segment, ptr, step, checkedElementCount, + dataSize, pointerCount, elementSize); + } + + static KJ_ALWAYS_INLINE(ListBuilder initStructListPointer( + WirePointer* ref, SegmentBuilder* segment, ElementCount elementCount, StructSize elementSize, BuilderArena* orphanArena = nullptr)) { + auto checkedElementCount = assertMaxBits(elementCount, + []() { KJ_FAIL_REQUIRE("tried to allocate list with too many elements"); }); + + WordsPerElementN<17> wordsPerElement = elementSize.total() / ELEMENTS; + + // Allocate the list, prefixed by a single WirePointer. + auto wordCount = assertMax() - 1>( + upgradeBound(checkedElementCount) * wordsPerElement, + []() { KJ_FAIL_REQUIRE("total size of struct list is larger than max segment size"); }); + word* ptr = allocate(ref, segment, POINTER_SIZE_IN_WORDS + wordCount, + WirePointer::LIST, orphanArena); + + // Initialize the pointer. + // INLINE_COMPOSITE lists replace the element count with the word count. + ref->listRef.setInlineComposite(wordCount); + + // Initialize the list tag. + reinterpret_cast(ptr)->setKindAndInlineCompositeListElementCount( + WirePointer::STRUCT, checkedElementCount); + reinterpret_cast(ptr)->structRef.set(elementSize); + ptr += POINTER_SIZE_IN_WORDS; + + // Build the ListBuilder. + return ListBuilder(segment, ptr, wordsPerElement * BITS_PER_WORD, checkedElementCount, + elementSize.data * BITS_PER_WORD, elementSize.pointers, + ElementSize::INLINE_COMPOSITE); + } + + static KJ_ALWAYS_INLINE(ListBuilder getWritableListPointer( + WirePointer* origRef, SegmentBuilder* origSegment, ElementSize elementSize, const word* defaultValue)) { + return getWritableListPointer(origRef, origRef->target(), origSegment, elementSize, + defaultValue); + } + + static KJ_ALWAYS_INLINE(ListBuilder getWritableListPointer( + WirePointer* origRef, word* origRefTarget, + SegmentBuilder* origSegment, ElementSize elementSize, + const word* defaultValue, BuilderArena* orphanArena = nullptr)) { + KJ_DREQUIRE(elementSize != ElementSize::INLINE_COMPOSITE, + "Use getWritableStructListPointer() for struct lists."); + + if (origRef->isNull()) { + useDefault: + if (defaultValue == nullptr || + reinterpret_cast(defaultValue)->isNull()) { + return ListBuilder(elementSize); + } + origRefTarget = copyMessage( + origSegment, origRef, reinterpret_cast(defaultValue)); + defaultValue = nullptr; // If the default value is itself invalid, don't use it again. + } + + // We must verify that the pointer has the right size. Unlike in + // getWritableStructListPointer(), we never need to "upgrade" the data, because this + // method is called only for non-struct lists, and there is no allowed upgrade path *to* + // a non-struct list, only *from* them. + + WirePointer* ref = origRef; + SegmentBuilder* segment = origSegment; + word* ptr = followFars(ref, origRefTarget, segment); + + KJ_REQUIRE(ref->kind() == WirePointer::LIST, + "Schema mismatch: Called getWritableListPointer() but existing pointer is not a list.") { + goto useDefault; + } + + ElementSize oldSize = ref->listRef.elementSize(); + + if (oldSize == ElementSize::INLINE_COMPOSITE) { + // The existing element size is INLINE_COMPOSITE, though we expected a list of primitives. + // The existing data must have been written with a newer version of the protocol. We + // therefore never need to upgrade the data in this case, but we do need to validate that it + // is a valid upgrade from what we expected. + + // Read the tag to get the actual element count. + WirePointer* tag = reinterpret_cast(ptr); + KJ_REQUIRE(tag->kind() == WirePointer::STRUCT, + "INLINE_COMPOSITE list with non-STRUCT elements not supported."); + ptr += POINTER_SIZE_IN_WORDS; + + auto dataSize = tag->structRef.dataSize.get(); + auto pointerCount = tag->structRef.ptrCount.get(); + + switch (elementSize) { + case ElementSize::VOID: + // Anything is a valid upgrade from Void. + break; + + case ElementSize::BIT: + KJ_FAIL_REQUIRE( + "Schema mismatch: Found struct list where bit list was expected; upgrading boolean " + "lists to structs is no longer supported.") { + goto useDefault; + } + break; + + case ElementSize::BYTE: + case ElementSize::TWO_BYTES: + case ElementSize::FOUR_BYTES: + case ElementSize::EIGHT_BYTES: + KJ_REQUIRE(dataSize >= ONE * WORDS, + "Schema mismatch: Existing list value is incompatible with expected type.") { + goto useDefault; + } + break; + + case ElementSize::POINTER: + KJ_REQUIRE(pointerCount >= ONE * POINTERS, + "Schema mismatch: Existing list value is incompatible with expected type.") { + goto useDefault; + } + // Adjust the pointer to point at the reference segment. + ptr += dataSize; + break; + + case ElementSize::INLINE_COMPOSITE: + KJ_UNREACHABLE; + } + + // OK, looks valid. + + return ListBuilder(segment, ptr, + tag->structRef.wordSize() * BITS_PER_WORD / ELEMENTS, + tag->inlineCompositeListElementCount(), + dataSize * BITS_PER_WORD, pointerCount, ElementSize::INLINE_COMPOSITE); + } else { + auto dataSize = dataBitsPerElement(oldSize) * ELEMENTS; + auto pointerCount = pointersPerElement(oldSize) * ELEMENTS; + + if (elementSize == ElementSize::BIT) { + KJ_REQUIRE(oldSize == ElementSize::BIT, + "Schema mismatch: Found non-bit list where bit list was expected.") { + goto useDefault; + } + } else { + KJ_REQUIRE(oldSize != ElementSize::BIT, + "Schema mismatch: Found bit list where non-bit list was expected.") { + goto useDefault; + } + KJ_REQUIRE(dataSize >= dataBitsPerElement(elementSize) * ELEMENTS, + "Schema mismatch: Existing list value is incompatible with expected type.") { + goto useDefault; + } + KJ_REQUIRE(pointerCount >= pointersPerElement(elementSize) * ELEMENTS, + "Schema mismatch: Existing list value is incompatible with expected type.") { + goto useDefault; + } + } + + auto step = (dataSize + pointerCount * BITS_PER_POINTER) / ELEMENTS; + return ListBuilder(segment, ptr, step, ref->listRef.elementCount(), + dataSize, pointerCount, oldSize); + } + } + + static KJ_ALWAYS_INLINE(ListBuilder getWritableListPointerAnySize( + WirePointer* origRef, SegmentBuilder* origSegment, const word* defaultValue)) { + return getWritableListPointerAnySize(origRef, origRef->target(), origSegment, + defaultValue); + } + + static KJ_ALWAYS_INLINE(ListBuilder getWritableListPointerAnySize( + WirePointer* origRef, word* origRefTarget, + SegmentBuilder* origSegment, const word* defaultValue, BuilderArena* orphanArena = nullptr)) { + if (origRef->isNull()) { + useDefault: + if (defaultValue == nullptr || + reinterpret_cast(defaultValue)->isNull()) { + return ListBuilder(ElementSize::VOID); + } + origRefTarget = copyMessage( + origSegment, origRef, reinterpret_cast(defaultValue)); + defaultValue = nullptr; // If the default value is itself invalid, don't use it again. + } + + WirePointer* ref = origRef; + SegmentBuilder* segment = origSegment; + word* ptr = followFars(ref, origRefTarget, segment); + + KJ_REQUIRE(ref->kind() == WirePointer::LIST, + "Schema mismatch: Called getWritableListPointerAnySize() but existing pointer is not a " + "list.") { + goto useDefault; + } + + ElementSize elementSize = ref->listRef.elementSize(); + + if (elementSize == ElementSize::INLINE_COMPOSITE) { + // Read the tag to get the actual element count. + WirePointer* tag = reinterpret_cast(ptr); + KJ_REQUIRE(tag->kind() == WirePointer::STRUCT, + "INLINE_COMPOSITE list with non-STRUCT elements not supported."); + ptr += POINTER_SIZE_IN_WORDS; + + return ListBuilder(segment, ptr, + tag->structRef.wordSize() * BITS_PER_WORD / ELEMENTS, + tag->inlineCompositeListElementCount(), + tag->structRef.dataSize.get() * BITS_PER_WORD, + tag->structRef.ptrCount.get(), ElementSize::INLINE_COMPOSITE); + } else { + auto dataSize = dataBitsPerElement(elementSize) * ELEMENTS; + auto pointerCount = pointersPerElement(elementSize) * ELEMENTS; + + auto step = (dataSize + pointerCount * BITS_PER_POINTER) / ELEMENTS; + return ListBuilder(segment, ptr, step, ref->listRef.elementCount(), + dataSize, pointerCount, elementSize); + } + } + + static KJ_ALWAYS_INLINE(ListBuilder getWritableStructListPointer( + WirePointer* origRef, SegmentBuilder* origSegment, StructSize elementSize, const word* defaultValue)) { + return getWritableStructListPointer(origRef, origRef->target(), origSegment, elementSize, defaultValue); + } + static KJ_ALWAYS_INLINE(ListBuilder getWritableStructListPointer( + WirePointer* origRef, word* origRefTarget, + SegmentBuilder* origSegment, StructSize elementSize, const word* defaultValue, BuilderArena* orphanArena = nullptr)) { + if (origRef->isNull()) { + useDefault: + if (defaultValue == nullptr || + reinterpret_cast(defaultValue)->isNull()) { + return ListBuilder(ElementSize::INLINE_COMPOSITE); + } + origRefTarget = copyMessage( + origSegment, origRef, reinterpret_cast(defaultValue)); + defaultValue = nullptr; // If the default value is itself invalid, don't use it again. + } + + // We must verify that the pointer has the right size and potentially upgrade it if not. + + WirePointer* oldRef = origRef; + SegmentBuilder* oldSegment = origSegment; + word* oldPtr = followFars(oldRef, origRefTarget, oldSegment); + + KJ_REQUIRE(oldRef->kind() == WirePointer::LIST, + "Schema mismatch: Called getList{Field,Element}() but existing pointer is not a " + "list.") { + goto useDefault; + } + + ElementSize oldSize = oldRef->listRef.elementSize(); + + if (oldSize == ElementSize::INLINE_COMPOSITE) { + // Existing list is INLINE_COMPOSITE, but we need to verify that the sizes match. + + WirePointer* oldTag = reinterpret_cast(oldPtr); + oldPtr += POINTER_SIZE_IN_WORDS; + KJ_REQUIRE(oldTag->kind() == WirePointer::STRUCT, + "INLINE_COMPOSITE list with non-STRUCT elements not supported.") { + goto useDefault; + } + + auto oldDataSize = oldTag->structRef.dataSize.get(); + auto oldPointerCount = oldTag->structRef.ptrCount.get(); + auto oldStep = (oldDataSize + oldPointerCount * WORDS_PER_POINTER) / ELEMENTS; + + auto elementCount = oldTag->inlineCompositeListElementCount(); + + if (oldDataSize >= elementSize.data && oldPointerCount >= elementSize.pointers) { + // Old size is at least as large as we need. Ship it. + return ListBuilder(oldSegment, oldPtr, oldStep * BITS_PER_WORD, elementCount, + oldDataSize * BITS_PER_WORD, oldPointerCount, + ElementSize::INLINE_COMPOSITE); + } + + // The structs in this list are smaller than expected, probably written using an older + // version of the protocol. We need to make a copy and expand them. + + auto newDataSize = kj::max(oldDataSize, elementSize.data); + auto newPointerCount = kj::max(oldPointerCount, elementSize.pointers); + auto newStep = (newDataSize + newPointerCount * WORDS_PER_POINTER) / ELEMENTS; + + auto totalSize = assertMax() - 1>( + newStep * upgradeBound(elementCount), + []() { KJ_FAIL_REQUIRE("total size of struct list is larger than max segment size"); }); + + // Don't let allocate() zero out the object just yet. + zeroPointerAndFars(origSegment, origRef); + + word* newPtr = allocate(origRef, origSegment, totalSize + POINTER_SIZE_IN_WORDS, + WirePointer::LIST, orphanArena); + origRef->listRef.setInlineComposite(totalSize); + + WirePointer* newTag = reinterpret_cast(newPtr); + newTag->setKindAndInlineCompositeListElementCount(WirePointer::STRUCT, elementCount); + newTag->structRef.set(newDataSize, newPointerCount); + newPtr += POINTER_SIZE_IN_WORDS; + + word* src = oldPtr; + word* dst = newPtr; + for (auto i KJ_UNUSED: kj::zeroTo(elementCount)) { + // Copy data section. + copyMemory(dst, src, oldDataSize); + + // Copy pointer section. + WirePointer* newPointerSection = reinterpret_cast(dst + newDataSize); + WirePointer* oldPointerSection = reinterpret_cast(src + oldDataSize); + for (auto j: kj::zeroTo(oldPointerCount)) { + transferPointer(origSegment, newPointerSection + j, oldSegment, oldPointerSection + j); + } + + dst += newStep * (ONE * ELEMENTS); + src += oldStep * (ONE * ELEMENTS); + } + + auto oldSize = assertMax() - 1>( + oldStep * upgradeBound(elementCount), + []() { KJ_FAIL_ASSERT("old size overflows but new size doesn't?"); }); + + // Zero out old location. See explanation in getWritableStructPointer(). + // Make sure to include the tag word. + zeroMemory(oldPtr - POINTER_SIZE_IN_WORDS, oldSize + POINTER_SIZE_IN_WORDS); + + return ListBuilder(origSegment, newPtr, newStep * BITS_PER_WORD, elementCount, + newDataSize * BITS_PER_WORD, newPointerCount, + ElementSize::INLINE_COMPOSITE); + } else { + // We're upgrading from a non-struct list. + + auto oldDataSize = dataBitsPerElement(oldSize) * ELEMENTS; + auto oldPointerCount = pointersPerElement(oldSize) * ELEMENTS; + auto oldStep = (oldDataSize + oldPointerCount * BITS_PER_POINTER) / ELEMENTS; + auto elementCount = oldRef->listRef.elementCount(); + + if (oldSize == ElementSize::VOID) { + // Nothing to copy, just allocate a new list. + return initStructListPointer(origRef, origSegment, elementCount, elementSize); + } else { + // Upgrading to an inline composite list. + + KJ_REQUIRE(oldSize != ElementSize::BIT, + "Schema mismatch: Found bit list where struct list was expected; upgrading boolean " + "lists to structs is no longer supported.") { + goto useDefault; + } + + auto newDataSize = elementSize.data; + auto newPointerCount = elementSize.pointers; + + if (oldSize == ElementSize::POINTER) { + newPointerCount = kj::max(newPointerCount, ONE * POINTERS); + } else { + // Old list contains data elements, so we need at least 1 word of data. + newDataSize = kj::max(newDataSize, ONE * WORDS); + } + + auto newStep = (newDataSize + newPointerCount * WORDS_PER_POINTER) / ELEMENTS; + auto totalWords = assertMax() - 1>( + newStep * upgradeBound(elementCount), + []() {KJ_FAIL_REQUIRE("total size of struct list is larger than max segment size");}); + + // Don't let allocate() zero out the object just yet. + zeroPointerAndFars(origSegment, origRef); + + word* newPtr = allocate(origRef, origSegment, totalWords + POINTER_SIZE_IN_WORDS, + WirePointer::LIST, orphanArena); + origRef->listRef.setInlineComposite(totalWords); + + WirePointer* tag = reinterpret_cast(newPtr); + tag->setKindAndInlineCompositeListElementCount(WirePointer::STRUCT, elementCount); + tag->structRef.set(newDataSize, newPointerCount); + newPtr += POINTER_SIZE_IN_WORDS; + + if (oldSize == ElementSize::POINTER) { + WirePointer* dst = reinterpret_cast(newPtr + newDataSize); + WirePointer* src = reinterpret_cast(oldPtr); + for (auto i KJ_UNUSED: kj::zeroTo(elementCount)) { + transferPointer(origSegment, dst, oldSegment, src); + dst += newStep / WORDS_PER_POINTER * (ONE * ELEMENTS); + ++src; + } + } else { + byte* dst = reinterpret_cast(newPtr); + byte* src = reinterpret_cast(oldPtr); + auto newByteStep = newStep * (ONE * ELEMENTS) * BYTES_PER_WORD; + auto oldByteStep = oldDataSize / BITS_PER_BYTE; + for (auto i KJ_UNUSED: kj::zeroTo(elementCount)) { + copyMemory(dst, src, oldByteStep); + src += oldByteStep; + dst += newByteStep; + } + } + + auto oldSize = assertMax() - 1>( + roundBitsUpToWords(oldStep * upgradeBound(elementCount)), + []() { KJ_FAIL_ASSERT("old size overflows but new size doesn't?"); }); + + // Zero out old location. See explanation in getWritableStructPointer(). + zeroMemory(oldPtr, oldSize); + + return ListBuilder(origSegment, newPtr, newStep * BITS_PER_WORD, elementCount, + newDataSize * BITS_PER_WORD, newPointerCount, + ElementSize::INLINE_COMPOSITE); + } + } + } + + static KJ_ALWAYS_INLINE(SegmentAnd initTextPointer( + WirePointer* ref, SegmentBuilder* segment, TextSize size, + BuilderArena* orphanArena = nullptr)) { + // The byte list must include a NUL terminator. + auto byteSize = size + ONE * BYTES; + + // Allocate the space. + word* ptr = allocate( + ref, segment, roundBytesUpToWords(byteSize), WirePointer::LIST, orphanArena); + + // Initialize the pointer. + ref->listRef.set(ElementSize::BYTE, byteSize * (ONE * ELEMENTS / BYTES)); + + // Build the Text::Builder. Note that since allocate()ed memory is pre-zero'd, we don't need + // to initialize the NUL terminator. + return { segment, Text::Builder(reinterpret_cast(ptr), unbound(size / BYTES)) }; + } + + static KJ_ALWAYS_INLINE(SegmentAnd setTextPointer( + WirePointer* ref, SegmentBuilder* segment, Text::Reader value, + BuilderArena* orphanArena = nullptr)) { + TextSize size = assertMax(bounded(value.size()), + []() { KJ_FAIL_REQUIRE("text blob too big"); }) * BYTES; + + auto allocation = initTextPointer(ref, segment, size, orphanArena); + copyMemory(allocation.value.begin(), value); + return allocation; + } + + static KJ_ALWAYS_INLINE(Text::Builder getWritableTextPointer( + WirePointer* ref, SegmentBuilder* segment, const void* defaultValue, TextSize defaultSize)) { + return getWritableTextPointer(ref, ref->target(), segment,defaultValue, defaultSize); + } + + static KJ_ALWAYS_INLINE(Text::Builder getWritableTextPointer( + WirePointer* ref, word* refTarget, SegmentBuilder* segment, const void* defaultValue, TextSize defaultSize)) { + if (ref->isNull()) { + useDefault: + if (defaultSize == ZERO * BYTES) { + return nullptr; + } else { + Text::Builder builder = initTextPointer(ref, segment, defaultSize).value; + copyMemory(builder.asBytes().begin(), reinterpret_cast(defaultValue), + defaultSize); + return builder; + } + } else { + word* ptr = followFars(ref, refTarget, segment); + byte* bptr = reinterpret_cast(ptr); + + KJ_REQUIRE(ref->kind() == WirePointer::LIST, + "Schema mismatch: Called getText{Field,Element}() but existing pointer is not a list.") { + goto useDefault; + } + KJ_REQUIRE(ref->listRef.elementSize() == ElementSize::BYTE, + "Schema mismatch: Called getText{Field,Element}() but existing list pointer is not " + "byte-sized.") { + goto useDefault; + } + + auto maybeSize = trySubtract(ref->listRef.elementCount() * (ONE * BYTES / ELEMENTS), + ONE * BYTES); + KJ_IF_MAYBE(size, maybeSize) { + KJ_REQUIRE(*(bptr + *size) == '\0', "Text blob missing NUL terminator.") { + goto useDefault; + } + + return Text::Builder(reinterpret_cast(bptr), unbound(*size / BYTES)); + } else { + KJ_FAIL_REQUIRE("zero-size blob can't be text (need NUL terminator)") { + goto useDefault; + }; + } + } + } + + static KJ_ALWAYS_INLINE(SegmentAnd initDataPointer( + WirePointer* ref, SegmentBuilder* segment, BlobSize size, + BuilderArena* orphanArena = nullptr)) { + // Allocate the space. + word* ptr = allocate(ref, segment, roundBytesUpToWords(size), + WirePointer::LIST, orphanArena); + + // Initialize the pointer. + ref->listRef.set(ElementSize::BYTE, size * (ONE * ELEMENTS / BYTES)); + + // Build the Data::Builder. + return { segment, Data::Builder(reinterpret_cast(ptr), unbound(size / BYTES)) }; + } + + static KJ_ALWAYS_INLINE(SegmentAnd setDataPointer( + WirePointer* ref, SegmentBuilder* segment, Data::Reader value, + BuilderArena* orphanArena = nullptr)) { + BlobSize size = assertMaxBits(bounded(value.size()), + []() { KJ_FAIL_REQUIRE("text blob too big"); }) * BYTES; + + auto allocation = initDataPointer(ref, segment, size, orphanArena); + copyMemory(allocation.value.begin(), value); + return allocation; + } + + static KJ_ALWAYS_INLINE(Data::Builder getWritableDataPointer( + WirePointer* ref, SegmentBuilder* segment, const void* defaultValue, BlobSize defaultSize)) { + return getWritableDataPointer(ref, ref->target(), segment, defaultValue, defaultSize); + } + + static KJ_ALWAYS_INLINE(Data::Builder getWritableDataPointer( + WirePointer* ref, word* refTarget, SegmentBuilder* segment, const void* defaultValue, BlobSize defaultSize)) { + if (ref->isNull()) { + useDefault: + if (defaultSize == ZERO * BYTES) { + return nullptr; + } else { + Data::Builder builder = initDataPointer(ref, segment, defaultSize).value; + copyMemory(builder.begin(), reinterpret_cast(defaultValue), defaultSize); + return builder; + } + } else { + word* ptr = followFars(ref, refTarget, segment); + + KJ_REQUIRE(ref->kind() == WirePointer::LIST, + "Schema mismatch: Called getData{Field,Element}() but existing pointer is not a list.") { + goto useDefault; + } + KJ_REQUIRE(ref->listRef.elementSize() == ElementSize::BYTE, + "Schema mismatch: Called getData{Field,Element}() but existing list pointer is not " + "byte-sized.") { + goto useDefault; + } + + return Data::Builder(reinterpret_cast(ptr), + unbound(ref->listRef.elementCount() / ELEMENTS)); + } + } + + static SegmentAnd setStructPointer( + SegmentBuilder* segment, WirePointer* ref, StructReader value, + BuilderArena* orphanArena = nullptr) { + auto dataSize = roundBitsUpToBytes(value.dataSize); + auto ptrCount = value.pointerCount; + + auto dataWords = roundBytesUpToWords(dataSize); + + auto totalSize = dataWords + ptrCount * WORDS_PER_POINTER; + + word* ptr = allocate(ref, segment, totalSize, WirePointer::STRUCT, orphanArena); + ref->structRef.set(dataWords, ptrCount); + + if (value.dataSize == ONE * BITS) { + *reinterpret_cast(ptr) = value.getDataField(ZERO * ELEMENTS); + } else { + copyMemory(reinterpret_cast(ptr), + reinterpret_cast(value.data), + dataSize); + } + + WirePointer* pointerSection = reinterpret_cast(ptr + dataWords); + for (auto i: kj::zeroTo(ptrCount)) { + copyPointer(segment, pointerSection + i, + value.segment, value.pointers + i, + value.nestingLimit, nullptr); + } + + return { segment, ptr }; + } + + static SegmentAnd setListPointer( + SegmentBuilder* segment, WirePointer* ref, ListReader value, + BuilderArena* orphanArena = nullptr) { + auto totalSize = assertMax() - 1>( + roundBitsUpToWords(upgradeBound(value.elementCount) * value.step), + []() { KJ_FAIL_ASSERT("encountered impossibly long struct list ListReader"); }); + + if (value.elementSize != ElementSize::INLINE_COMPOSITE) { + // List of non-structs. + word* ptr = allocate(ref, segment, totalSize, WirePointer::LIST, orphanArena); + + if (value.elementSize == ElementSize::POINTER) { + // List of pointers. + ref->listRef.set(ElementSize::POINTER, value.elementCount); + for (auto i: kj::zeroTo(value.elementCount * (ONE * POINTERS / ELEMENTS))) { + copyPointer(segment, reinterpret_cast(ptr) + i, + value.segment, reinterpret_cast(value.ptr) + i, + value.nestingLimit, nullptr); + } + } else { + // List of data. + ref->listRef.set(value.elementSize, value.elementCount); + + auto wholeByteSize = + assertMax(MAX_SEGMENT_WORDS * BYTES_PER_WORD, + upgradeBound(value.elementCount) * value.step / BITS_PER_BYTE, + []() { KJ_FAIL_ASSERT("encountered impossibly long data ListReader"); }); + copyMemory(reinterpret_cast(ptr), value.ptr, wholeByteSize); + auto leftoverBits = + (upgradeBound(value.elementCount) * value.step) % BITS_PER_BYTE; + if (leftoverBits > ZERO * BITS) { + // We need to copy a partial byte. + uint8_t mask = (1 << unbound(leftoverBits / BITS)) - 1; + *((reinterpret_cast(ptr)) + wholeByteSize) = mask & *(value.ptr + wholeByteSize); + } + } + + return { segment, ptr }; + } else { + // List of structs. + auto dataSize = value.structDataSize / BITS_PER_WORD; + auto ptrCount = value.structPointerCount; + + KJ_DASSERT(value.structDataSize % BITS_PER_WORD == ZERO * BITS); + word* ptr = allocate(ref, segment, totalSize + POINTER_SIZE_IN_WORDS, + WirePointer::LIST, orphanArena); + ref->listRef.setInlineComposite(totalSize); + + WirePointer* tag = reinterpret_cast(ptr); + tag->setKindAndInlineCompositeListElementCount(WirePointer::STRUCT, value.elementCount); + tag->structRef.set(dataSize, ptrCount); + word* dst = ptr + POINTER_SIZE_IN_WORDS; + + const word* src = reinterpret_cast(value.ptr); + for (auto i KJ_UNUSED: kj::zeroTo(value.elementCount)) { + copyMemory(dst, src, dataSize); + dst += dataSize; + src += dataSize; + + for (auto j: kj::zeroTo(ptrCount)) { + copyPointer(segment, reinterpret_cast(dst) + j, + value.segment, reinterpret_cast(src) + j, + value.nestingLimit, nullptr); + } + dst += ptrCount * WORDS_PER_POINTER; + src += ptrCount * WORDS_PER_POINTER; + } + + return { segment, ptr }; + } + } + + static KJ_ALWAYS_INLINE(SegmentAnd copyPointer( + SegmentBuilder* dstSegment, WirePointer* dst, + SegmentReader* srcSegment, const WirePointer* src, + int nestingLimit, BuilderArena* orphanArena = nullptr)) { + return copyPointer(dstSegment, dst, + srcSegment, src, src->target(srcSegment), + nestingLimit, orphanArena); + } + + static SegmentAnd copyPointer( + SegmentBuilder* dstSegment, WirePointer* dst, + SegmentReader* srcSegment, const WirePointer* src, + const word* srcTarget, int nestingLimit, + BuilderArena* orphanArena = nullptr) { + // Deep-copy the object pointed to by src into dst. It turns out we can't reuse + // readStructPointer(), etc. because they do type checking whereas here we want to accept any + // valid pointer. + + if (src->isNull()) { + useDefault: + if (!dst->isNull()) { + zeroObject(dstSegment, dst); + zeroMemory(dst); + } + return { dstSegment, nullptr }; + } + + const word* ptr; + KJ_IF_MAYBE(p, WireHelpers::followFars(src, srcTarget, srcSegment)) { + ptr = p; + } else { + goto useDefault; + } + + switch (src->kind()) { + case WirePointer::STRUCT: + KJ_REQUIRE(nestingLimit > 0, + "Message is too deeply-nested or contains cycles. See capnp::ReaderOptions.") { + goto useDefault; + } + + KJ_REQUIRE(boundsCheck(srcSegment, ptr, src->structRef.wordSize()), + "Message contained out-of-bounds struct pointer. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + goto useDefault; + } + return setStructPointer(dstSegment, dst, + StructReader(srcSegment, ptr, + reinterpret_cast(ptr + src->structRef.dataSize.get()), + src->structRef.dataSize.get() * BITS_PER_WORD, + src->structRef.ptrCount.get(), + nestingLimit - 1), + orphanArena); + + case WirePointer::LIST: { + ElementSize elementSize = src->listRef.elementSize(); + + KJ_REQUIRE(nestingLimit > 0, + "Message is too deeply-nested or contains cycles. See capnp::ReaderOptions.") { + goto useDefault; + } + + if (elementSize == ElementSize::INLINE_COMPOSITE) { + auto wordCount = src->listRef.inlineCompositeWordCount(); + const WirePointer* tag = reinterpret_cast(ptr); + + KJ_REQUIRE(boundsCheck(srcSegment, ptr, wordCount + POINTER_SIZE_IN_WORDS), + "Message contains out-of-bounds list pointer. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + goto useDefault; + } + + ptr += POINTER_SIZE_IN_WORDS; + + KJ_REQUIRE(tag->kind() == WirePointer::STRUCT, + "INLINE_COMPOSITE lists of non-STRUCT type are not supported.") { + goto useDefault; + } + + auto elementCount = tag->inlineCompositeListElementCount(); + auto wordsPerElement = tag->structRef.wordSize() / ELEMENTS; + + KJ_REQUIRE(wordsPerElement * upgradeBound(elementCount) <= wordCount, + "INLINE_COMPOSITE list's elements overrun its word count.") { + goto useDefault; + } + + if (wordsPerElement * (ONE * ELEMENTS) == ZERO * WORDS) { + // Watch out for lists of zero-sized structs, which can claim to be arbitrarily large + // without having sent actual data. + KJ_REQUIRE(amplifiedRead(srcSegment, elementCount * (ONE * WORDS / ELEMENTS)), + "Message contains amplified list pointer.") { + goto useDefault; + } + } + + return setListPointer(dstSegment, dst, + ListReader(srcSegment, ptr, + elementCount, wordsPerElement * BITS_PER_WORD, + tag->structRef.dataSize.get() * BITS_PER_WORD, + tag->structRef.ptrCount.get(), ElementSize::INLINE_COMPOSITE, + nestingLimit - 1), + orphanArena); + } else { + auto dataSize = dataBitsPerElement(elementSize) * ELEMENTS; + auto pointerCount = pointersPerElement(elementSize) * ELEMENTS; + auto step = (dataSize + pointerCount * BITS_PER_POINTER) / ELEMENTS; + auto elementCount = src->listRef.elementCount(); + auto wordCount = roundBitsUpToWords(upgradeBound(elementCount) * step); + + KJ_REQUIRE(boundsCheck(srcSegment, ptr, wordCount), + "Message contains out-of-bounds list pointer. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + goto useDefault; + } + + if (elementSize == ElementSize::VOID) { + // Watch out for lists of void, which can claim to be arbitrarily large without having + // sent actual data. + KJ_REQUIRE(amplifiedRead(srcSegment, elementCount * (ONE * WORDS / ELEMENTS)), + "Message contains amplified list pointer.") { + goto useDefault; + } + } + + return setListPointer(dstSegment, dst, + ListReader(srcSegment, ptr, elementCount, step, dataSize, pointerCount, + elementSize, nestingLimit - 1), + orphanArena); + } + } + + case WirePointer::FAR: + KJ_FAIL_REQUIRE("Unexpected FAR pointer.") { + goto useDefault; + } + + case WirePointer::OTHER: { + KJ_REQUIRE(src->isCapability(), "Unknown pointer type.") { + goto useDefault; + } + + KJ_FAIL_REQUIRE("Message contained invalid capability pointer.") { + goto useDefault; + } + } + } + + KJ_UNREACHABLE; + } + + static void adopt(SegmentBuilder* segment, WirePointer* ref, OrphanBuilder&& value) { + KJ_REQUIRE(value.segment == nullptr || value.segment->getArena() == segment->getArena(), + "Adopted object must live in the same message."); + + if (!ref->isNull()) { + zeroObject(segment, ref); + } + + if (value == nullptr) { + // Set null. + zeroMemory(ref); + } else if (value.tagAsPtr()->isPositional()) { + WireHelpers::transferPointer(segment, ref, value.segment, value.tagAsPtr(), value.location); + } else { + // FAR and OTHER pointers are position-independent, so we can just copy. + copyMemory(ref, value.tagAsPtr()); + } + + // Take ownership away from the OrphanBuilder. + zeroMemory(value.tagAsPtr()); + value.location = nullptr; + value.segment = nullptr; + } + + static OrphanBuilder disown(SegmentBuilder* segment, WirePointer* ref) { + word* location; + + if (ref->isNull()) { + location = nullptr; + } else if (ref->kind() == WirePointer::OTHER) { + KJ_REQUIRE(ref->isCapability(), "Unknown pointer type.") { break; } + location = reinterpret_cast(1); // dummy so that it is non-null + } else { + WirePointer* refCopy = ref; + location = followFars(refCopy, ref->target(), segment); + } + + OrphanBuilder result(ref, segment, location); + + if (!ref->isNull() && ref->isPositional()) { + result.tagAsPtr()->setKindForOrphan(ref->kind()); + } + + // Zero out the pointer that was disowned. + zeroMemory(ref); + + return result; + } + + // ----------------------------------------------------------------- + + static KJ_ALWAYS_INLINE(StructReader readStructPointer( + SegmentReader* segment, const WirePointer* ref, const word* defaultValue, + int nestingLimit)) { + return readStructPointer(segment, ref, ref->target(segment), + defaultValue, nestingLimit); + } + + static KJ_ALWAYS_INLINE(StructReader readStructPointer( + SegmentReader* segment, const WirePointer* ref, const word* refTarget, + const word* defaultValue, int nestingLimit)) { + if (ref->isNull()) { + useDefault: + if (defaultValue == nullptr || + reinterpret_cast(defaultValue)->isNull()) { + return StructReader(); + } + segment = nullptr; + ref = reinterpret_cast(defaultValue); + refTarget = ref->target(segment); + defaultValue = nullptr; // If the default value is itself invalid, don't use it again. + } + + KJ_REQUIRE(nestingLimit > 0, + "Message is too deeply-nested or contains cycles. See capnp::ReaderOptions.") { + goto useDefault; + } + + const word* ptr; + KJ_IF_MAYBE(p, followFars(ref, refTarget, segment)) { + ptr = p; + } else { + goto useDefault; + } + + KJ_REQUIRE(ref->kind() == WirePointer::STRUCT, + "Schema mismatch: Message contains non-struct pointer where struct pointer" + "was expected.") { + goto useDefault; + } + + KJ_REQUIRE(boundsCheck(segment, ptr, ref->structRef.wordSize()), + "Message contained out-of-bounds struct pointer. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + goto useDefault; + } + + return StructReader( + segment, ptr, reinterpret_cast(ptr + ref->structRef.dataSize.get()), + ref->structRef.dataSize.get() * BITS_PER_WORD, + ref->structRef.ptrCount.get(), + nestingLimit - 1); + } + + static KJ_ALWAYS_INLINE(ListReader readListPointer( + SegmentReader* segment, const WirePointer* ref, const word* defaultValue, + ElementSize expectedElementSize, int nestingLimit, bool checkElementSize = true)) { + return readListPointer(segment, ref, ref->target(segment), defaultValue, + expectedElementSize, nestingLimit, checkElementSize); + } + + static KJ_ALWAYS_INLINE(ListReader readListPointer( + SegmentReader* segment, const WirePointer* ref, const word* refTarget, + const word* defaultValue, ElementSize expectedElementSize, int nestingLimit, + bool checkElementSize = true)) { + if (ref->isNull()) { + useDefault: + if (defaultValue == nullptr || + reinterpret_cast(defaultValue)->isNull()) { + return ListReader(expectedElementSize); + } + segment = nullptr; + ref = reinterpret_cast(defaultValue); + refTarget = ref->target(segment); + defaultValue = nullptr; // If the default value is itself invalid, don't use it again. + } + + KJ_REQUIRE(nestingLimit > 0, + "Message is too deeply-nested or contains cycles. See capnp::ReaderOptions.") { + goto useDefault; + } + + const word* ptr; + KJ_IF_MAYBE(p, followFars(ref, refTarget, segment)) { + ptr = p; + } else { + goto useDefault; + } + + KJ_REQUIRE(ref->kind() == WirePointer::LIST, + "Schema mismatch: Message contains non-list pointer where list pointer was " + "expected.") { + goto useDefault; + } + + ElementSize elementSize = ref->listRef.elementSize(); + if (elementSize == ElementSize::INLINE_COMPOSITE) { + auto wordCount = ref->listRef.inlineCompositeWordCount(); + + // An INLINE_COMPOSITE list points to a tag, which is formatted like a pointer. + const WirePointer* tag = reinterpret_cast(ptr); + + KJ_REQUIRE(boundsCheck(segment, ptr, wordCount + POINTER_SIZE_IN_WORDS), + "Message contains out-of-bounds list pointer. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + goto useDefault; + } + + ptr += POINTER_SIZE_IN_WORDS; + + KJ_REQUIRE(tag->kind() == WirePointer::STRUCT, + "INLINE_COMPOSITE lists of non-STRUCT type are not supported.") { + goto useDefault; + } + + auto size = tag->inlineCompositeListElementCount(); + auto wordsPerElement = tag->structRef.wordSize() / ELEMENTS; + + KJ_REQUIRE(upgradeBound(size) * wordsPerElement <= wordCount, + "INLINE_COMPOSITE list's elements overrun its word count.") { + goto useDefault; + } + + if (wordsPerElement * (ONE * ELEMENTS) == ZERO * WORDS) { + // Watch out for lists of zero-sized structs, which can claim to be arbitrarily large + // without having sent actual data. + KJ_REQUIRE(amplifiedRead(segment, size * (ONE * WORDS / ELEMENTS)), + "Message contains amplified list pointer.") { + goto useDefault; + } + } + + if (checkElementSize) { + // If a struct list was not expected, then presumably a non-struct list was upgraded to a + // struct list. We need to manipulate the pointer to point at the first field of the + // struct. Together with the `step` field, this will allow the struct list to be accessed + // as if it were a primitive list without branching. + + // Check whether the size is compatible. + switch (expectedElementSize) { + case ElementSize::VOID: + break; + + case ElementSize::BIT: + KJ_FAIL_REQUIRE( + "Found struct list where bit list was expected; upgrading boolean lists to structs " + "is no longer supported.") { + goto useDefault; + } + break; + + case ElementSize::BYTE: + case ElementSize::TWO_BYTES: + case ElementSize::FOUR_BYTES: + case ElementSize::EIGHT_BYTES: + KJ_REQUIRE(tag->structRef.dataSize.get() > ZERO * WORDS, + "Schema mismatch: Expected a primitive list, but got a list of pointer-only " + "structs.") { + goto useDefault; + } + break; + + case ElementSize::POINTER: + KJ_REQUIRE(tag->structRef.ptrCount.get() > ZERO * POINTERS, + "Schema mismatch: Expected a pointer list, but got a list of data-only " + "structs.") { + goto useDefault; + } + break; + + case ElementSize::INLINE_COMPOSITE: + break; + } + } + + return ListReader( + segment, ptr, size, wordsPerElement * BITS_PER_WORD, + tag->structRef.dataSize.get() * BITS_PER_WORD, + tag->structRef.ptrCount.get(), ElementSize::INLINE_COMPOSITE, + nestingLimit - 1); + + } else { + // This is a primitive or pointer list, but all such lists can also be interpreted as struct + // lists. We need to compute the data size and pointer count for such structs. + auto dataSize = dataBitsPerElement(ref->listRef.elementSize()) * ELEMENTS; + auto pointerCount = pointersPerElement(ref->listRef.elementSize()) * ELEMENTS; + auto elementCount = ref->listRef.elementCount(); + auto step = (dataSize + pointerCount * BITS_PER_POINTER) / ELEMENTS; + + auto wordCount = roundBitsUpToWords(upgradeBound(elementCount) * step); + KJ_REQUIRE(boundsCheck(segment, ptr, wordCount), + "Message contains out-of-bounds list pointer. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + goto useDefault; + } + + if (elementSize == ElementSize::VOID) { + // Watch out for lists of void, which can claim to be arbitrarily large without having sent + // actual data. + KJ_REQUIRE(amplifiedRead(segment, elementCount * (ONE * WORDS / ELEMENTS)), + "Message contains amplified list pointer.") { + goto useDefault; + } + } + + if (checkElementSize) { + if (elementSize == ElementSize::BIT && expectedElementSize != ElementSize::BIT) { + KJ_FAIL_REQUIRE( + "Found bit list where struct list was expected; upgrading boolean lists to structs " + "is no longer supported.") { + goto useDefault; + } + } + + // Verify that the elements are at least as large as the expected type. Note that if we + // expected INLINE_COMPOSITE, the expected sizes here will be zero, because bounds checking + // will be performed at field access time. So this check here is for the case where we + // expected a list of some primitive or pointer type. + + BitCount expectedDataBitsPerElement = + dataBitsPerElement(expectedElementSize) * ELEMENTS; + WirePointerCount expectedPointersPerElement = + pointersPerElement(expectedElementSize) * ELEMENTS; + + KJ_REQUIRE(expectedDataBitsPerElement <= dataSize, + "Schema mismatch: Message contained list with incompatible element type.") { + goto useDefault; + } + KJ_REQUIRE(expectedPointersPerElement <= pointerCount, + "Schema mismatch: Message contained list with incompatible element type.") { + goto useDefault; + } + } + + return ListReader(segment, ptr, elementCount, step, + dataSize, pointerCount, elementSize, nestingLimit - 1); + } + } + + static KJ_ALWAYS_INLINE(Text::Reader readTextPointer( + SegmentReader* segment, const WirePointer* ref, + const void* defaultValue, ByteCount defaultSize)) { + return readTextPointer(segment, ref, ref->target(segment), defaultValue, defaultSize); + } + + static KJ_ALWAYS_INLINE(Text::Reader readTextPointer( + SegmentReader* segment, const WirePointer* ref, const word* refTarget, + const void* defaultValue, ByteCount defaultSize)) { + if (ref->isNull()) { + useDefault: + if (defaultValue == nullptr) defaultValue = ""; + return Text::Reader(reinterpret_cast(defaultValue), + unbound(defaultSize / BYTES)); + } else { + const word* ptr; + KJ_IF_MAYBE(p, followFars(ref, refTarget, segment)) { + ptr = p; + } else { + goto useDefault; + } + + auto size = ref->listRef.elementCount() * (ONE * BYTES / ELEMENTS); + + KJ_REQUIRE(ref->kind() == WirePointer::LIST, + "Schema mismatch: Message contains non-list pointer where text was expected.") { + goto useDefault; + } + + KJ_REQUIRE(ref->listRef.elementSize() == ElementSize::BYTE, + "Schema mismatch: Message contains list pointer of non-bytes where text was " + "expected.") { + goto useDefault; + } + + KJ_REQUIRE(boundsCheck(segment, ptr, roundBytesUpToWords(size)), + "Message contained out-of-bounds text pointer. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + goto useDefault; + } + + KJ_REQUIRE(size > ZERO * BYTES, "Message contains text that is not NUL-terminated.") { + goto useDefault; + } + + const char* cptr = reinterpret_cast(ptr); + uint unboundedSize = unbound(size / BYTES) - 1; + + KJ_REQUIRE(cptr[unboundedSize] == '\0', "Message contains text that is not NUL-terminated.") { + goto useDefault; + } + + return Text::Reader(cptr, unboundedSize); + } + } + + static KJ_ALWAYS_INLINE(Data::Reader readDataPointer( + SegmentReader* segment, const WirePointer* ref, + const void* defaultValue, BlobSize defaultSize)) { + return readDataPointer(segment, ref, ref->target(segment), defaultValue, defaultSize); + } + + static KJ_ALWAYS_INLINE(Data::Reader readDataPointer( + SegmentReader* segment, const WirePointer* ref, const word* refTarget, + const void* defaultValue, BlobSize defaultSize)) { + if (ref->isNull()) { + useDefault: + return Data::Reader(reinterpret_cast(defaultValue), + unbound(defaultSize / BYTES)); + } else { + const word* ptr; + KJ_IF_MAYBE(p, followFars(ref, refTarget, segment)) { + ptr = p; + } else { + goto useDefault; + } + + if (KJ_UNLIKELY(ptr == nullptr)) { + // Already reported error. + goto useDefault; + } + + auto size = ref->listRef.elementCount() * (ONE * BYTES / ELEMENTS); + + KJ_REQUIRE(ref->kind() == WirePointer::LIST, + "Schema mismatch: Message contains non-list pointer where data was expected.") { + goto useDefault; + } + + KJ_REQUIRE(ref->listRef.elementSize() == ElementSize::BYTE, + "Schema mismatch: Message contains list pointer of non-bytes where data was " + "expected.") { + goto useDefault; + } + + KJ_REQUIRE(boundsCheck(segment, ptr, roundBytesUpToWords(size)), + "Message contained out-of-bounds data pointer. " + OUT_OF_BOUNDS_ERROR_DETAIL) { + goto useDefault; + } + + return Data::Reader(reinterpret_cast(ptr), unbound(size / BYTES)); + } + } +}; + +// ======================================================================================= +// PointerBuilder + +StructBuilder PointerBuilder::initStruct(StructSize size) { + return WireHelpers::initStructPointer(pointer, segment, size); +} + +StructBuilder PointerBuilder::getStruct(StructSize size, const word* defaultValue) { + return WireHelpers::getWritableStructPointer(pointer, segment, size, defaultValue); +} + +ListBuilder PointerBuilder::initList(ElementSize elementSize, ElementCount elementCount) { + return WireHelpers::initListPointer(pointer, segment, elementCount, elementSize); +} + +ListBuilder PointerBuilder::initStructList(ElementCount elementCount, StructSize elementSize) { + return WireHelpers::initStructListPointer(pointer, segment, elementCount, elementSize); +} + +ListBuilder PointerBuilder::getList(ElementSize elementSize, const word* defaultValue) { + return WireHelpers::getWritableListPointer(pointer, segment, elementSize, defaultValue); +} + +ListBuilder PointerBuilder::getStructList(StructSize elementSize, const word* defaultValue) { + return WireHelpers::getWritableStructListPointer( + pointer, segment, elementSize, defaultValue); +} + +ListBuilder PointerBuilder::getListAnySize(const word* defaultValue) { + return WireHelpers::getWritableListPointerAnySize(pointer, segment, defaultValue); +} + +template <> +Text::Builder PointerBuilder::initBlob(ByteCount size) { + return WireHelpers::initTextPointer(pointer, segment, assertMax(size, ThrowOverflow())).value; +} +template <> +void PointerBuilder::setBlob(Text::Reader value) { + WireHelpers::setTextPointer(pointer, segment, value); +} +template <> +Text::Builder PointerBuilder::getBlob(const void* defaultValue, ByteCount defaultSize) { + return WireHelpers::getWritableTextPointer(pointer, segment, defaultValue, + assertMax(defaultSize, ThrowOverflow())); +} + +template <> +Data::Builder PointerBuilder::initBlob(ByteCount size) { + return WireHelpers::initDataPointer(pointer, segment, assertMaxBits(size, ThrowOverflow())).value; +} +template <> +void PointerBuilder::setBlob(Data::Reader value) { + WireHelpers::setDataPointer(pointer, segment, value); +} +template <> +Data::Builder PointerBuilder::getBlob(const void* defaultValue, ByteCount defaultSize) { + return WireHelpers::getWritableDataPointer(pointer, segment, defaultValue, + assertMaxBits(defaultSize, ThrowOverflow())); +} + +void PointerBuilder::setStruct(const StructReader& value) { + WireHelpers::setStructPointer(segment, pointer, value, nullptr); +} + +void PointerBuilder::setList(const ListReader& value) { + WireHelpers::setListPointer(segment, pointer, value, nullptr); +} + +void PointerBuilder::adopt(OrphanBuilder&& value) { + WireHelpers::adopt(segment, pointer, kj::mv(value)); +} + +OrphanBuilder PointerBuilder::disown() { + return WireHelpers::disown(segment, pointer); +} + +void PointerBuilder::clear() { + WireHelpers::zeroObject(segment, pointer); + WireHelpers::zeroMemory(pointer); +} + +PointerType PointerBuilder::getPointerType() const { + if(pointer->isNull()) { + return PointerType::NULL_; + } else { + WirePointer* ptr = pointer; + SegmentBuilder* sgmt = segment; + WireHelpers::followFars(ptr, ptr->target(), sgmt); + switch(ptr->kind()) { + case WirePointer::FAR: + KJ_FAIL_ASSERT("far pointer not followed?"); + case WirePointer::STRUCT: + return PointerType::STRUCT; + case WirePointer::LIST: + return PointerType::LIST; + case WirePointer::OTHER: + KJ_REQUIRE(ptr->isCapability(), "unknown pointer type"); + return PointerType::CAPABILITY; + } + KJ_UNREACHABLE; + } +} + +void PointerBuilder::transferFrom(PointerBuilder other) { + if (!pointer->isNull()) { + WireHelpers::zeroObject(segment, pointer); + WireHelpers::zeroMemory(pointer); + } + WireHelpers::transferPointer(segment, pointer, other.segment, other.pointer); + WireHelpers::zeroMemory(other.pointer); +} + +void PointerBuilder::copyFrom(PointerReader other) { + if (other.pointer == nullptr) { + if (!pointer->isNull()) { + WireHelpers::zeroObject(segment, pointer); + WireHelpers::zeroMemory(pointer); + } + } else { + WireHelpers::copyPointer(segment, pointer, + other.segment, other.pointer, other.nestingLimit, + nullptr); + } +} + +PointerReader PointerBuilder::asReader() const { + return PointerReader(segment, pointer, kj::maxValue); +} + +BuilderArena* PointerBuilder::getArena() const { + return segment->getArena(); +} + +// ======================================================================================= +// PointerReader + +PointerReader PointerReader::getRoot(SegmentReader* segment, const word* location, int nestingLimit) { + KJ_REQUIRE(WireHelpers::boundsCheck(segment, location, POINTER_SIZE_IN_WORDS), + "Root location out-of-bounds.") { + location = nullptr; + } + + return PointerReader(segment, reinterpret_cast(location), nestingLimit); +} + +StructReader PointerReader::getStruct(const word* defaultValue) const { + const WirePointer* ref = pointer == nullptr ? &zero.pointer : pointer; + return WireHelpers::readStructPointer(segment, ref, defaultValue, nestingLimit); +} + +ListReader PointerReader::getList(ElementSize expectedElementSize, const word* defaultValue) const { + const WirePointer* ref = pointer == nullptr ? &zero.pointer : pointer; + return WireHelpers::readListPointer( + segment, ref, defaultValue, expectedElementSize, nestingLimit); +} + +ListReader PointerReader::getListAnySize(const word* defaultValue) const { + const WirePointer* ref = pointer == nullptr ? &zero.pointer : pointer; + return WireHelpers::readListPointer( + segment, ref, defaultValue, ElementSize::VOID /* dummy */, nestingLimit, false); +} + +template <> +Text::Reader PointerReader::getBlob(const void* defaultValue, ByteCount defaultSize) const { + const WirePointer* ref = pointer == nullptr ? &zero.pointer : pointer; + return WireHelpers::readTextPointer(segment, ref, defaultValue, defaultSize); +} + +template <> +Data::Reader PointerReader::getBlob(const void* defaultValue, ByteCount defaultSize) const { + const WirePointer* ref = pointer == nullptr ? &zero.pointer : pointer; + return WireHelpers::readDataPointer(segment, ref, defaultValue, + assertMaxBits(defaultSize, ThrowOverflow())); +} + +const word* PointerReader::getUnchecked() const { + KJ_REQUIRE(segment == nullptr, "getUncheckedPointer() only allowed on unchecked messages."); + return reinterpret_cast(pointer); +} + +MessageSizeCounts PointerReader::targetSize() const { + return pointer == nullptr ? MessageSizeCounts { ZERO * WORDS, 0 } + : WireHelpers::totalSize(segment, pointer, nestingLimit); +} + +PointerType PointerReader::getPointerType() const { + if(pointer == nullptr || pointer->isNull()) { + return PointerType::NULL_; + } else { + const WirePointer* ptr = pointer; + const word* refTarget = ptr->target(segment); + SegmentReader* sgmt = segment; + if (WireHelpers::followFars(ptr, refTarget, sgmt) == nullptr) return PointerType::NULL_; + switch(ptr->kind()) { + case WirePointer::FAR: + KJ_FAIL_ASSERT("far pointer not followed?") { return PointerType::NULL_; } + case WirePointer::STRUCT: + return PointerType::STRUCT; + case WirePointer::LIST: + return PointerType::LIST; + case WirePointer::OTHER: + KJ_REQUIRE(ptr->isCapability(), "unknown pointer type") { return PointerType::NULL_; } + return PointerType::CAPABILITY; + } + KJ_UNREACHABLE; + } +} + +// ======================================================================================= +// StructBuilder + +void StructBuilder::clearAll() { + if (dataSize == ONE * BITS) { + setDataField(ONE * ELEMENTS, false); + } else { + WireHelpers::zeroMemory(reinterpret_cast(data), dataSize / BITS_PER_BYTE); + } + + for (auto i: kj::zeroTo(pointerCount)) { + WireHelpers::zeroObject(segment, pointers + i); + } + WireHelpers::zeroMemory(pointers, pointerCount); +} + +void StructBuilder::transferContentFrom(StructBuilder other) { + // Determine the amount of data the builders have in common. + auto sharedDataSize = kj::min(dataSize, other.dataSize); + + if (dataSize > sharedDataSize) { + // Since the target is larger than the source, make sure to zero out the extra bits that the + // source doesn't have. + if (dataSize == ONE * BITS) { + setDataField(ZERO * ELEMENTS, false); + } else { + byte* unshared = reinterpret_cast(data) + sharedDataSize / BITS_PER_BYTE; + // Note: this subtraction can't fail due to the if() above + WireHelpers::zeroMemory(unshared, + subtractChecked(dataSize, sharedDataSize, []() {}) / BITS_PER_BYTE); + } + } + + // Copy over the shared part. + if (sharedDataSize == ONE * BITS) { + setDataField(ZERO * ELEMENTS, other.getDataField(ZERO * ELEMENTS)); + } else { + WireHelpers::copyMemory(reinterpret_cast(data), + reinterpret_cast(other.data), + sharedDataSize / BITS_PER_BYTE); + } + + // Zero out all pointers in the target. + for (auto i: kj::zeroTo(pointerCount)) { + WireHelpers::zeroObject(segment, pointers + i); + } + WireHelpers::zeroMemory(pointers, pointerCount); + + // Transfer the pointers. + auto sharedPointerCount = kj::min(pointerCount, other.pointerCount); + for (auto i: kj::zeroTo(sharedPointerCount)) { + WireHelpers::transferPointer(segment, pointers + i, other.segment, other.pointers + i); + } + + // Zero out the pointers that were transferred in the source because it no longer has ownership. + // If the source had any extra pointers that the destination didn't have space for, we + // intentionally leave them be, so that they'll be cleaned up later. + WireHelpers::zeroMemory(other.pointers, sharedPointerCount); +} + +void StructBuilder::copyContentFrom(StructReader other) { + // Determine the amount of data the builders have in common. + auto sharedDataSize = kj::min(dataSize, other.dataSize); + auto sharedPointerCount = kj::min(pointerCount, other.pointerCount); + + if ((sharedDataSize > ZERO * BITS && other.data == data) || + (sharedPointerCount > ZERO * POINTERS && other.pointers == pointers)) { + // At least one of the section pointers is pointing to ourself. Verify that the other is two + // (but ignore empty sections). + KJ_ASSERT((sharedDataSize == ZERO * BITS || other.data == data) && + (sharedPointerCount == ZERO * POINTERS || other.pointers == pointers)); + // So `other` appears to be a reader for this same struct. No coping is needed. + return; + } + + if (dataSize > sharedDataSize) { + // Since the target is larger than the source, make sure to zero out the extra bits that the + // source doesn't have. + if (dataSize == ONE * BITS) { + setDataField(ZERO * ELEMENTS, false); + } else { + byte* unshared = reinterpret_cast(data) + sharedDataSize / BITS_PER_BYTE; + WireHelpers::zeroMemory(unshared, + subtractChecked(dataSize, sharedDataSize, []() {}) / BITS_PER_BYTE); + } + } + + // Copy over the shared part. + if (sharedDataSize == ONE * BITS) { + setDataField(ZERO * ELEMENTS, other.getDataField(ZERO * ELEMENTS)); + } else { + WireHelpers::copyMemory(reinterpret_cast(data), + reinterpret_cast(other.data), + sharedDataSize / BITS_PER_BYTE); + } + + // Zero out all pointers in the target. + for (auto i: kj::zeroTo(pointerCount)) { + WireHelpers::zeroObject(segment, pointers + i); + } + WireHelpers::zeroMemory(pointers, pointerCount); + + // Copy the pointers. + for (auto i: kj::zeroTo(sharedPointerCount)) { + WireHelpers::copyPointer(segment, pointers + i, + other.segment, other.pointers + i, other.nestingLimit); + } +} + +StructReader StructBuilder::asReader() const { + return StructReader(segment, data, pointers, + dataSize, pointerCount, kj::maxValue); +} + +BuilderArena* StructBuilder::getArena() { + return segment->getArena(); +} + +// ======================================================================================= +// StructReader + +MessageSizeCounts StructReader::totalSize() const { + MessageSizeCounts result = { + WireHelpers::roundBitsUpToWords(dataSize) + pointerCount * WORDS_PER_POINTER, 0 }; + + for (auto i: kj::zeroTo(pointerCount)) { + result += WireHelpers::totalSize(segment, pointers + i, nestingLimit); + } + + if (segment != nullptr) { + // This traversal should not count against the read limit, because it's highly likely that + // the caller is going to traverse the object again, e.g. to copy it. + segment->unread(result.wordCount); + } + + return result; +} + +// ======================================================================================= +// ListBuilder + +Text::Builder ListBuilder::asText() { + KJ_REQUIRE(structDataSize == G(8) * BITS && structPointerCount == ZERO * POINTERS, + "Expected Text, got list of non-bytes.") { + return Text::Builder(); + } + + size_t size = unbound(elementCount / ELEMENTS); + + KJ_REQUIRE(size > 0, "Message contains text that is not NUL-terminated.") { + return Text::Builder(); + } + + char* cptr = reinterpret_cast(ptr); + --size; // NUL terminator + + KJ_REQUIRE(cptr[size] == '\0', "Message contains text that is not NUL-terminated.") { + return Text::Builder(); + } + + return Text::Builder(cptr, size); +} + +Data::Builder ListBuilder::asData() { + KJ_REQUIRE(structDataSize == G(8) * BITS && structPointerCount == ZERO * POINTERS, + "Expected Text, got list of non-bytes.") { + return Data::Builder(); + } + + return Data::Builder(reinterpret_cast(ptr), unbound(elementCount / ELEMENTS)); +} + +StructBuilder ListBuilder::getStructElement(ElementCount index) { + auto indexBit = upgradeBound(index) * step; + byte* structData = ptr + indexBit / BITS_PER_BYTE; + KJ_DASSERT(indexBit % BITS_PER_BYTE == ZERO * BITS); + return StructBuilder(segment, structData, + reinterpret_cast(structData + structDataSize / BITS_PER_BYTE), + structDataSize, structPointerCount); +} + +ListReader ListBuilder::asReader() const { + return ListReader(segment, ptr, elementCount, step, structDataSize, structPointerCount, + elementSize, kj::maxValue); +} + +BuilderArena* ListBuilder::getArena() { + return segment->getArena(); +} + +// ======================================================================================= +// ListReader + +Text::Reader ListReader::asText() { + KJ_REQUIRE(structDataSize == G(8) * BITS && structPointerCount == ZERO * POINTERS, + "Schema mismatch: Expected Text, got list of non-bytes.") { + return Text::Reader(); + } + + size_t size = unbound(elementCount / ELEMENTS); + + KJ_REQUIRE(size > 0, "Message contains text that is not NUL-terminated.") { + return Text::Reader(); + } + + const char* cptr = reinterpret_cast(ptr); + --size; // NUL terminator + + KJ_REQUIRE(cptr[size] == '\0', "Message contains text that is not NUL-terminated.") { + return Text::Reader(); + } + + return Text::Reader(cptr, size); +} + +Data::Reader ListReader::asData() { + KJ_REQUIRE(structDataSize == G(8) * BITS && structPointerCount == ZERO * POINTERS, + "Schema mismatch: Expected Text, got list of non-bytes.") { + return Data::Reader(); + } + + return Data::Reader(reinterpret_cast(ptr), unbound(elementCount / ELEMENTS)); +} + +kj::ArrayPtr ListReader::asRawBytes() const { + KJ_REQUIRE(structPointerCount == ZERO * POINTERS, + "Schema mismatch: Expected data only, got pointers.") { + return kj::ArrayPtr(); + } + + return arrayPtr(reinterpret_cast(ptr), + WireHelpers::roundBitsUpToBytes( + upgradeBound(elementCount) * (structDataSize / ELEMENTS))); +} + +StructReader ListReader::getStructElement(ElementCount index) const { + KJ_REQUIRE(nestingLimit > 0, + "Message is too deeply-nested or contains cycles. See capnp::ReaderOptions.") { + return StructReader(); + } + + auto indexBit = upgradeBound(index) * step; + const byte* structData = ptr + indexBit / BITS_PER_BYTE; + const WirePointer* structPointers = + reinterpret_cast(structData + structDataSize / BITS_PER_BYTE); + + KJ_DASSERT(indexBit % BITS_PER_BYTE == ZERO * BITS); + return StructReader( + segment, structData, structPointers, + structDataSize, structPointerCount, + nestingLimit - 1); +} + +MessageSizeCounts ListReader::totalSize() const { + // TODO(cleanup): This is kind of a lot of logic duplicated from WireHelpers::totalSize(), but + // it's unclear how to share it effectively. + + MessageSizeCounts result = { ZERO * WORDS, 0 }; + + switch (elementSize) { + case ElementSize::VOID: + // Nothing. + break; + case ElementSize::BIT: + case ElementSize::BYTE: + case ElementSize::TWO_BYTES: + case ElementSize::FOUR_BYTES: + case ElementSize::EIGHT_BYTES: + result.addWords(WireHelpers::roundBitsUpToWords( + upgradeBound(elementCount) * dataBitsPerElement(elementSize))); + break; + case ElementSize::POINTER: { + auto count = elementCount * (POINTERS / ELEMENTS); + result.addWords(count * WORDS_PER_POINTER); + + for (auto i: kj::zeroTo(count)) { + result += WireHelpers::totalSize(segment, reinterpret_cast(ptr) + i, + nestingLimit); + } + break; + } + case ElementSize::INLINE_COMPOSITE: { + // Don't forget to count the tag word. + auto wordSize = upgradeBound(elementCount) * step / BITS_PER_WORD; + result.addWords(wordSize + POINTER_SIZE_IN_WORDS); + + if (structPointerCount > ZERO * POINTERS) { + const word* pos = reinterpret_cast(ptr); + for (auto i KJ_UNUSED: kj::zeroTo(elementCount)) { + pos += structDataSize / BITS_PER_WORD; + + for (auto j KJ_UNUSED: kj::zeroTo(structPointerCount)) { + result += WireHelpers::totalSize(segment, reinterpret_cast(pos), + nestingLimit); + pos += POINTER_SIZE_IN_WORDS; + } + } + } + break; + } + } + + if (segment != nullptr) { + // This traversal should not count against the read limit, because it's highly likely that + // the caller is going to traverse the object again, e.g. to copy it. + segment->unread(result.wordCount); + } + + return result; +} + +// ======================================================================================= +// OrphanBuilder + +OrphanBuilder OrphanBuilder::initStruct( + BuilderArena* arena, StructSize size) { + OrphanBuilder result; + StructBuilder builder = WireHelpers::initStructPointer( + result.tagAsPtr(), nullptr, size, arena); + result.segment = builder.segment; + + result.location = builder.getLocation(); + return result; +} + +OrphanBuilder OrphanBuilder::initList( + BuilderArena* arena, ElementCount elementCount, ElementSize elementSize) { + OrphanBuilder result; + ListBuilder builder = WireHelpers::initListPointer( + result.tagAsPtr(), nullptr, elementCount, elementSize, arena); + result.segment = builder.segment; + + result.location = builder.getLocation(); + return result; +} + +OrphanBuilder OrphanBuilder::initStructList( + BuilderArena* arena, ElementCount elementCount, StructSize elementSize) { + OrphanBuilder result; + ListBuilder builder = WireHelpers::initStructListPointer( + result.tagAsPtr(), nullptr, elementCount, elementSize, arena); + result.segment = builder.segment; + + result.location = builder.getLocation(); + return result; +} + +OrphanBuilder OrphanBuilder::initText( + BuilderArena* arena, ByteCount size) { + OrphanBuilder result; + auto allocation = WireHelpers::initTextPointer(result.tagAsPtr(), nullptr, assertMax(size, ThrowOverflow()), arena); + result.segment = allocation.segment; + + result.location = reinterpret_cast(allocation.value.begin()); + return result; +} + +OrphanBuilder OrphanBuilder::initData( + BuilderArena* arena, ByteCount size) { + OrphanBuilder result; + auto allocation = WireHelpers::initDataPointer(result.tagAsPtr(), nullptr, assertMaxBits(size), arena); + result.segment = allocation.segment; + + result.location = reinterpret_cast(allocation.value.begin()); + return result; +} + +OrphanBuilder OrphanBuilder::copy( + BuilderArena* arena, StructReader copyFrom) { + OrphanBuilder result; + auto allocation = WireHelpers::setStructPointer( + nullptr, result.tagAsPtr(), copyFrom, arena); + result.segment = allocation.segment; + + result.location = reinterpret_cast(allocation.value); + return result; +} + +OrphanBuilder OrphanBuilder::copy( + BuilderArena* arena, ListReader copyFrom) { + OrphanBuilder result; + auto allocation = WireHelpers::setListPointer( + nullptr, result.tagAsPtr(), copyFrom, arena); + result.segment = allocation.segment; + + result.location = reinterpret_cast(allocation.value); + return result; +} + +OrphanBuilder OrphanBuilder::copy( + BuilderArena* arena, PointerReader copyFrom) { + OrphanBuilder result; + auto allocation = WireHelpers::copyPointer( + nullptr, result.tagAsPtr(), + copyFrom.segment, copyFrom.pointer, copyFrom.nestingLimit, arena); + result.segment = allocation.segment; + + result.location = reinterpret_cast(allocation.value); + return result; +} + +OrphanBuilder OrphanBuilder::copy( + BuilderArena* arena, Text::Reader copyFrom) { + OrphanBuilder result; + auto allocation = WireHelpers::setTextPointer( + result.tagAsPtr(), nullptr, copyFrom, arena); + result.segment = allocation.segment; + + result.location = reinterpret_cast(allocation.value.begin()); + return result; +} + +OrphanBuilder OrphanBuilder::copy( + BuilderArena* arena, Data::Reader copyFrom) { + OrphanBuilder result; + auto allocation = WireHelpers::setDataPointer( + result.tagAsPtr(), nullptr, copyFrom, arena); + result.segment = allocation.segment; + + result.location = reinterpret_cast(allocation.value.begin()); + return result; +} + +StructBuilder OrphanBuilder::asStruct(StructSize size) { + KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); + + StructBuilder result = WireHelpers::getWritableStructPointer( + tagAsPtr(), location, segment, size, nullptr, segment->getArena()); + + // Watch out, the pointer could have been updated if the object had to be relocated. + location = reinterpret_cast(result.data); + + return result; +} + +ListBuilder OrphanBuilder::asList(ElementSize elementSize) { + KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); + + ListBuilder result = WireHelpers::getWritableListPointer( + tagAsPtr(), location, segment, elementSize, nullptr, segment->getArena()); + + // Watch out, the pointer could have been updated if the object had to be relocated. + // (Actually, currently this is not true for primitive lists, but let's not turn into a bug if + // it changes!) + location = result.getLocation(); + + return result; +} + +ListBuilder OrphanBuilder::asStructList(StructSize elementSize) { + KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); + + ListBuilder result = WireHelpers::getWritableStructListPointer( + tagAsPtr(), location, segment, elementSize, nullptr, segment->getArena()); + + // Watch out, the pointer could have been updated if the object had to be relocated. + location = result.getLocation(); + + return result; +} + +ListBuilder OrphanBuilder::asListAnySize() { + KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); + + ListBuilder result = WireHelpers::getWritableListPointerAnySize( + tagAsPtr(), location, segment, nullptr, segment->getArena()); + + // Watch out, the pointer could have been updated if the object had to be relocated. + location = result.getLocation(); + + return result; +} + +Text::Builder OrphanBuilder::asText() { + KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); + + // Never relocates. + return WireHelpers::getWritableTextPointer( + tagAsPtr(), location, segment, nullptr, ZERO * BYTES); +} + +Data::Builder OrphanBuilder::asData() { + KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); + + // Never relocates. + return WireHelpers::getWritableDataPointer( + tagAsPtr(), location, segment, nullptr, ZERO * BYTES); +} + +StructReader OrphanBuilder::asStructReader(StructSize size) const { + KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); + return WireHelpers::readStructPointer( + segment, tagAsPtr(), location, nullptr, kj::maxValue); +} + +ListReader OrphanBuilder::asListReader(ElementSize elementSize) const { + KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); + return WireHelpers::readListPointer( + segment, tagAsPtr(), location, nullptr, elementSize, kj::maxValue); +} + +ListReader OrphanBuilder::asListReaderAnySize() const { + KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); + return WireHelpers::readListPointer( + segment, tagAsPtr(), location, nullptr, ElementSize::VOID /* dummy */, + kj::maxValue); +} + +Text::Reader OrphanBuilder::asTextReader() const { + KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); + return WireHelpers::readTextPointer(segment, tagAsPtr(), location, nullptr, ZERO * BYTES); +} + +Data::Reader OrphanBuilder::asDataReader() const { + KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); + return WireHelpers::readDataPointer(segment, tagAsPtr(), location, nullptr, ZERO * BYTES); +} + +void OrphanBuilder::euthanize() { + // Carefully catch any exceptions and rethrow them as recoverable exceptions since we may be in + // a destructor. + auto exception = kj::runCatchingExceptions([&]() { + if (tagAsPtr()->isPositional()) { + WireHelpers::zeroObject(segment, tagAsPtr(), location); + } else { + WireHelpers::zeroObject(segment, tagAsPtr()); + } + + WireHelpers::zeroMemory(&tag, ONE * WORDS); + segment = nullptr; + location = nullptr; + }); + + KJ_IF_MAYBE(e, exception) { + kj::getExceptionCallback().onRecoverableException(kj::mv(*e)); + } +} + +} // namespace _ (private) +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/layout.h b/vendor/capnproto/src/capnp/layout.h new file mode 100644 index 0000000..7ef8430 --- /dev/null +++ b/vendor/capnproto/src/capnp/layout.h @@ -0,0 +1,1105 @@ +// 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. + +// This file is NOT intended for use by clients, except in generated code. +// +// This file defines low-level, non-type-safe classes for traversing the Cap'n Proto memory layout +// (which is also its wire format). Code generated by the Cap'n Proto compiler uses these classes, +// as does other parts of the Cap'n proto library which provide a higher-level interface for +// dynamic introspection. + +#pragma once + +#include +#include +#include "common.h" +#include "blob.h" +#include "endian.h" + +CAPNP_BEGIN_HEADER + +#if (defined(__mips__) || defined(__hppa__)) && !defined(CAPNP_CANONICALIZE_NAN) +#define CAPNP_CANONICALIZE_NAN 1 +// Explicitly detect NaNs and canonicalize them to the quiet NaN value as would be returned by +// __builtin_nan("") on systems implementing the IEEE-754 recommended (but not required) NaN +// signalling/quiet differentiation (such as x86). Unfortunately, some architectures -- in +// particular, MIPS -- represent quiet vs. signalling nans differently than the rest of the world. +// Canonicalizing them makes output consistent (which is important!), but hurts performance +// slightly. +// +// Note that trying to convert MIPS NaNs to standard NaNs without losing data doesn't work. +// Signaling vs. quiet is indicated by a bit, with the meaning being the opposite on MIPS vs. +// everyone else. It would be great if we could just flip that bit, but we can't, because if the +// significand is all-zero, then the value is infinity rather than NaN. This means that on most +// machines, where the bit indicates quietness, there is one more quiet NaN value than signalling +// NaN value, whereas on MIPS there is one more sNaN than qNaN, and thus there is no isomorphic +// mapping that properly preserves quietness. Instead of doing something hacky, we just give up +// and blow away NaN payloads, because no one uses them anyway. +#endif + +namespace capnp { + +namespace _ { // private + +class PointerBuilder; +class PointerReader; +class StructBuilder; +class StructReader; +class ListBuilder; +class ListReader; +class OrphanBuilder; +struct WirePointer; +struct WireHelpers; +class SegmentReader; +class SegmentBuilder; +class Arena; +class BuilderArena; + +// ============================================================================= + +#if CAPNP_DEBUG_TYPES +typedef kj::UnitRatio, BitLabel, ElementLabel> BitsPerElementTableType; +#else +typedef uint BitsPerElementTableType; +#endif + +static constexpr BitsPerElementTableType BITS_PER_ELEMENT_TABLE[8] = { + bounded< 0>() * BITS / ELEMENTS, + bounded< 1>() * BITS / ELEMENTS, + bounded< 8>() * BITS / ELEMENTS, + bounded<16>() * BITS / ELEMENTS, + bounded<32>() * BITS / ELEMENTS, + bounded<64>() * BITS / ELEMENTS, + bounded< 0>() * BITS / ELEMENTS, + bounded< 0>() * BITS / ELEMENTS +}; + +inline KJ_CONSTEXPR() BitsPerElementTableType dataBitsPerElement(ElementSize size) { + return _::BITS_PER_ELEMENT_TABLE[static_cast(size)]; +} + +inline constexpr PointersPerElementN<1> pointersPerElement(ElementSize size) { + return size == ElementSize::POINTER + ? PointersPerElementN<1>(ONE * POINTERS / ELEMENTS) + : PointersPerElementN<1>(ZERO * POINTERS / ELEMENTS); +} + +static constexpr BitsPerElementTableType BITS_PER_ELEMENT_INCLUDING_PONITERS_TABLE[8] = { + bounded< 0>() * BITS / ELEMENTS, + bounded< 1>() * BITS / ELEMENTS, + bounded< 8>() * BITS / ELEMENTS, + bounded<16>() * BITS / ELEMENTS, + bounded<32>() * BITS / ELEMENTS, + bounded<64>() * BITS / ELEMENTS, + bounded<64>() * BITS / ELEMENTS, + bounded< 0>() * BITS / ELEMENTS +}; + +inline KJ_CONSTEXPR() BitsPerElementTableType bitsPerElementIncludingPointers(ElementSize size) { + return _::BITS_PER_ELEMENT_INCLUDING_PONITERS_TABLE[static_cast(size)]; +} + +template struct ElementSizeForByteSize; +template <> struct ElementSizeForByteSize<1> { static constexpr ElementSize value = ElementSize::BYTE; }; +template <> struct ElementSizeForByteSize<2> { static constexpr ElementSize value = ElementSize::TWO_BYTES; }; +template <> struct ElementSizeForByteSize<4> { static constexpr ElementSize value = ElementSize::FOUR_BYTES; }; +template <> struct ElementSizeForByteSize<8> { static constexpr ElementSize value = ElementSize::EIGHT_BYTES; }; + +template struct ElementSizeForType { + static constexpr ElementSize value = + // Primitive types that aren't special-cased below can be determined from sizeof(). + CAPNP_KIND(T) == Kind::PRIMITIVE ? ElementSizeForByteSize::value : + CAPNP_KIND(T) == Kind::ENUM ? ElementSize::TWO_BYTES : + CAPNP_KIND(T) == Kind::STRUCT ? ElementSize::INLINE_COMPOSITE : + + // Everything else is a pointer. + ElementSize::POINTER; +}; + +// Void and bool are special. +template <> struct ElementSizeForType { static constexpr ElementSize value = ElementSize::VOID; }; +template <> struct ElementSizeForType { static constexpr ElementSize value = ElementSize::BIT; }; + +// Lists and blobs are pointers, not structs. +template struct ElementSizeForType> { + static constexpr ElementSize value = ElementSize::POINTER; +}; +template <> struct ElementSizeForType { + static constexpr ElementSize value = ElementSize::POINTER; +}; +template <> struct ElementSizeForType { + static constexpr ElementSize value = ElementSize::POINTER; +}; + +template +inline constexpr ElementSize elementSizeForType() { + return ElementSizeForType::value; +} + +struct MessageSizeCounts { + WordCountN<61, uint64_t> wordCount; // 2^64 bytes + uint capCount; + + MessageSizeCounts& operator+=(const MessageSizeCounts& other) { + // OK to truncate unchecked because this class is used to count actual stuff in memory, and + // we couldn't possibly have anywhere near 2^61 words. + wordCount = assumeBits<61>(wordCount + other.wordCount); + capCount += other.capCount; + return *this; + } + + void addWords(WordCountN<61, uint64_t> other) { + wordCount = assumeBits<61>(wordCount + other); + } + + MessageSize asPublic() { + return MessageSize { unbound(wordCount / WORDS), capCount }; + } +}; + +// ============================================================================= + +template +union AlignedData { + // Useful for declaring static constant data blobs as an array of bytes, but forcing those + // bytes to be word-aligned. + + uint8_t bytes[wordCount * sizeof(word)]; + word words[wordCount]; +}; + +struct StructSize { + StructDataWordCount data; + StructPointerCount pointers; + + inline constexpr WordCountN<17> total() const { return data + pointers * WORDS_PER_POINTER; } + + StructSize() = default; + inline constexpr StructSize(StructDataWordCount data, StructPointerCount pointers) + : data(data), pointers(pointers) {} +}; + +template +inline constexpr StructSize structSize() { + return StructSize(bounded(CapnpPrivate::dataWordSize) * WORDS, + bounded(CapnpPrivate::pointerCount) * POINTERS); +} + +// ------------------------------------------------------------------- +// Masking of default values + +template struct Mask_; +template struct Mask_ { typedef T Type; }; +template struct Mask_ { typedef uint16_t Type; }; +template <> struct Mask_ { typedef uint32_t Type; }; +template <> struct Mask_ { typedef uint64_t Type; }; + +template struct Mask_ { + // Union discriminants end up here. + static_assert(sizeof(T) == 2, "Don't know how to mask this type."); + typedef uint16_t Type; +}; + +template +using Mask = typename Mask_::Type; + +template +KJ_ALWAYS_INLINE(Mask mask(T value, Mask mask)); +template +KJ_ALWAYS_INLINE(T unmask(Mask value, Mask mask)); + +template +inline Mask mask(T value, Mask mask) { + return static_cast >(value) ^ mask; +} + +template <> +inline uint32_t mask(float value, uint32_t mask) { +#if CAPNP_CANONICALIZE_NAN + if (value != value) { + return 0x7fc00000u ^ mask; + } +#endif + + uint32_t i; + static_assert(sizeof(i) == sizeof(value), "float is not 32 bits?"); + memcpy(&i, &value, sizeof(value)); + return i ^ mask; +} + +template <> +inline uint64_t mask(double value, uint64_t mask) { +#if CAPNP_CANONICALIZE_NAN + if (value != value) { + return 0x7ff8000000000000ull ^ mask; + } +#endif + + uint64_t i; + static_assert(sizeof(i) == sizeof(value), "double is not 64 bits?"); + memcpy(&i, &value, sizeof(value)); + return i ^ mask; +} + +template +inline T unmask(Mask value, Mask mask) { + return static_cast(value ^ mask); +} + +template <> +inline float unmask(uint32_t value, uint32_t mask) { + value ^= mask; + float result; + static_assert(sizeof(result) == sizeof(value), "float is not 32 bits?"); + memcpy(&result, &value, sizeof(value)); + return result; +} + +template <> +inline double unmask(uint64_t value, uint64_t mask) { + value ^= mask; + double result; + static_assert(sizeof(result) == sizeof(value), "double is not 64 bits?"); + memcpy(&result, &value, sizeof(value)); + return result; +} + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +class PointerBuilder: public kj::DisallowConstCopy { + // Represents a single pointer, usually embedded in a struct or a list. + +public: + inline PointerBuilder(): segment(nullptr), pointer(nullptr) {} + + static inline PointerBuilder getRoot( + SegmentBuilder* segment, word* location); + // Get a PointerBuilder representing a message root located in the given segment at the given + // location. + + inline bool isNull() { return getPointerType() == PointerType::NULL_; } + PointerType getPointerType() const; + + StructBuilder getStruct(StructSize size, const word* defaultValue); + ListBuilder getList(ElementSize elementSize, const word* defaultValue); + ListBuilder getStructList(StructSize elementSize, const word* defaultValue); + ListBuilder getListAnySize(const word* defaultValue); + template typename T::Builder getBlob( + const void* defaultValue, ByteCount defaultSize); + // Get methods: Get the value. If it is null, initialize it to a copy of the default value. + // The default value is encoded as an "unchecked message" for structs, lists, and objects, or a + // simple byte array for blobs. + + StructBuilder initStruct(StructSize size); + ListBuilder initList(ElementSize elementSize, ElementCount elementCount); + ListBuilder initStructList(ElementCount elementCount, StructSize size); + template typename T::Builder initBlob(ByteCount size); + // Init methods: Initialize the pointer to a newly-allocated object, discarding the existing + // object. + + void setStruct(const StructReader& value); + void setList(const ListReader& value); + template void setBlob(typename T::Reader value); + // Set methods: Initialize the pointer to a newly-allocated copy of the given value, discarding + // the existing object. + + void adopt(OrphanBuilder&& orphan); + // Set the pointer to point at the given orphaned value. + + OrphanBuilder disown(); + // Set the pointer to null and return its previous value as an orphan. + + void clear(); + // Clear the pointer to null, discarding its previous value. + + void transferFrom(PointerBuilder other); + // Equivalent to `adopt(other.disown())`. + + void copyFrom(PointerReader other); + // Equivalent to `set(other.get())`. + + PointerReader asReader() const; + + BuilderArena* getArena() const; + // Get the arena containing this pointer. + +private: + SegmentBuilder* segment; // Memory segment in which the pointer resides. + WirePointer* pointer; // Pointer to the pointer. + + inline PointerBuilder(SegmentBuilder* segment, WirePointer* pointer) + : segment(segment), pointer(pointer) {} + + friend class StructBuilder; + friend class ListBuilder; + friend class OrphanBuilder; +}; + +class PointerReader { +public: + inline PointerReader() + : segment(nullptr), pointer(nullptr), nestingLimit(0x7fffffff) {} + + static PointerReader getRoot(SegmentReader* segment, const word* location, int nestingLimit); + // Get a PointerReader representing a message root located in the given segment at the given + // location. + + static inline PointerReader getRootUnchecked(const word* location); + // Get a PointerReader for an unchecked message. + + MessageSizeCounts targetSize() const; + // Return the total size of the target object and everything to which it points. Does not count + // far pointer overhead. This is useful for deciding how much space is needed to copy the object + // into a flat array. However, the caller is advised NOT to treat this value as secure. Instead, + // use the result as a hint for allocating the first segment, do the copy, and then throw an + // exception if it overruns. + + inline bool isNull() const { return getPointerType() == PointerType::NULL_; } + PointerType getPointerType() const; + + StructReader getStruct(const word* defaultValue) const; + ListReader getList(ElementSize expectedElementSize, const word* defaultValue) const; + ListReader getListAnySize(const word* defaultValue) const; + template + typename T::Reader getBlob(const void* defaultValue, ByteCount defaultSize) const; + // Get methods: Get the value. If it is null, return the default value instead. + // The default value is encoded as an "unchecked message" for structs, lists, and objects, or a + // simple byte array for blobs. + + const word* getUnchecked() const; + // If this is an unchecked message, get a word* pointing at the location of the pointer. This + // word* can actually be passed to readUnchecked() to read the designated sub-object later. If + // this isn't an unchecked message, throws an exception. + +private: + SegmentReader* segment; // Memory segment in which the pointer resides. + const WirePointer* pointer; // Pointer to the pointer. null = treat as null pointer. + + int nestingLimit; + // Limits the depth of message structures to guard against stack-overflow-based DoS attacks. + // Once this reaches zero, further pointers will be pruned. + + inline PointerReader(SegmentReader* segment, const WirePointer* pointer, int nestingLimit) + : segment(segment), pointer(pointer), nestingLimit(nestingLimit) {} + + friend class StructReader; + friend class ListReader; + friend class PointerBuilder; + friend class OrphanBuilder; +}; + +// ------------------------------------------------------------------- + +class StructBuilder: public kj::DisallowConstCopy { +public: + inline StructBuilder(): segment(nullptr), data(nullptr), pointers(nullptr) {} + + inline word* getLocation() { return reinterpret_cast(data); } + // Get the object's location. Only valid for independently-allocated objects (i.e. not list + // elements). + + inline kj::ArrayPtr getDataSectionAsBlob(); + inline _::ListBuilder getPointerSectionAsList(); + + template + KJ_ALWAYS_INLINE(bool hasDataField(StructDataOffset offset)); + // Return true if the field is set to something other than its default value. + + template + KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset)); + // Gets the data field value of the given type at the given offset. The offset is measured in + // multiples of the field size, determined by the type. + + template + KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset, Mask mask)); + // Like getDataField() but applies the given XOR mask to the data on load. Used for reading + // fields with non-zero default values. + + template + KJ_ALWAYS_INLINE(void setDataField(StructDataOffset offset, kj::NoInfer value)); + // Sets the data field value at the given offset. + + template + KJ_ALWAYS_INLINE(void setDataField(StructDataOffset offset, + kj::NoInfer value, Mask mask)); + // Like setDataField() but applies the given XOR mask before storing. Used for writing fields + // with non-zero default values. + + KJ_ALWAYS_INLINE(PointerBuilder getPointerField(StructPointerOffset ptrIndex)); + // Get a builder for a pointer field given the index within the pointer section. + + void clearAll(); + // Clear all pointers and data. + + void transferContentFrom(StructBuilder other); + // Adopt all pointers from `other`, and also copy all data. If `other`'s sections are larger + // than this, the extra data is not transferred, meaning there is a risk of data loss when + // transferring from messages built with future versions of the protocol. + + void copyContentFrom(StructReader other); + // Copy content from `other`. If `other`'s sections are larger than this, the extra data is not + // copied, meaning there is a risk of data loss when copying from messages built with future + // versions of the protocol. + + StructReader asReader() const; + // Gets a StructReader pointing at the same memory. + + BuilderArena* getArena(); + // Gets the arena in which this object is allocated. + +private: + SegmentBuilder* segment; // Memory segment in which the struct resides. + void* data; // Pointer to the encoded data. + WirePointer* pointers; // Pointer to the encoded pointers. + + StructDataBitCount dataSize; + // Size of data section. We use a bit count rather than a word count to more easily handle the + // case of struct lists encoded with less than a word per element. + + StructPointerCount pointerCount; // Size of the pointer section. + + inline StructBuilder(SegmentBuilder* segment, void* data, WirePointer* pointers, + StructDataBitCount dataSize, StructPointerCount pointerCount) + : segment(segment), data(data), pointers(pointers), + dataSize(dataSize), pointerCount(pointerCount) {} + + friend class ListBuilder; + friend struct WireHelpers; + friend class OrphanBuilder; +}; + +class StructReader { +public: + inline StructReader() + : segment(nullptr), data(nullptr), pointers(nullptr), + dataSize(ZERO * BITS), pointerCount(ZERO * POINTERS), nestingLimit(0x7fffffff) {} + inline StructReader(kj::ArrayPtr data) + : segment(nullptr), data(data.begin()), pointers(nullptr), + dataSize(assumeBits(data.size()) * WORDS * BITS_PER_WORD), + pointerCount(ZERO * POINTERS), nestingLimit(0x7fffffff) {} + + inline kj::ArrayPtr getDataSectionAsBlob() const; + inline _::ListReader getPointerSectionAsList() const; + + template + KJ_ALWAYS_INLINE(bool hasDataField(StructDataOffset offset) const); + // Return true if the field is set to something other than its default value. + + template + KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset) const); + // Get the data field value of the given type at the given offset. The offset is measured in + // multiples of the field size, determined by the type. Returns zero if the offset is past the + // end of the struct's data section. + + template + KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset, Mask mask) const); + // Like getDataField(offset), but applies the given XOR mask to the result. Used for reading + // fields with non-zero default values. + + KJ_ALWAYS_INLINE(PointerReader getPointerField(StructPointerOffset ptrIndex) const); + // Get a reader for a pointer field given the index within the pointer section. If the index + // is out-of-bounds, returns a null pointer. + + MessageSizeCounts totalSize() const; + // Return the total size of the struct and everything to which it points. Does not count far + // pointer overhead. This is useful for deciding how much space is needed to copy the struct + // into a flat array. + +private: + SegmentReader* segment; // Memory segment in which the struct resides. + + const void* data; + const WirePointer* pointers; + + StructDataBitCount dataSize; + // Size of data section. We use a bit count rather than a word count to more easily handle the + // case of struct lists encoded with less than a word per element. + + StructPointerCount pointerCount; // Size of the pointer section. + + int nestingLimit; + // Limits the depth of message structures to guard against stack-overflow-based DoS attacks. + // Once this reaches zero, further pointers will be pruned. + // TODO(perf): Limit to 16 bits for better packing? + + inline StructReader(SegmentReader* segment, const void* data, const WirePointer* pointers, + StructDataBitCount dataSize, StructPointerCount pointerCount, + int nestingLimit) + : segment(segment), data(data), pointers(pointers), + dataSize(dataSize), pointerCount(pointerCount), + nestingLimit(nestingLimit) {} + + friend class ListReader; + friend class StructBuilder; + friend struct WireHelpers; +}; + +// ------------------------------------------------------------------- + +class ListBuilder: public kj::DisallowConstCopy { +public: + inline explicit ListBuilder(ElementSize elementSize) + : segment(nullptr), ptr(nullptr), elementCount(ZERO * ELEMENTS), + step(ZERO * BITS / ELEMENTS), structDataSize(ZERO * BITS), + structPointerCount(ZERO * POINTERS), elementSize(elementSize) {} + + inline word* getLocation() { + // Get the object's location. + + if (elementSize == ElementSize::INLINE_COMPOSITE && ptr != nullptr) { + return reinterpret_cast(ptr) - POINTER_SIZE_IN_WORDS; + } else { + return reinterpret_cast(ptr); + } + } + + inline ElementSize getElementSize() const { return elementSize; } + + inline ListElementCount size() const; + // The number of elements in the list. + + Text::Builder asText(); + Data::Builder asData(); + // Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized. + + template + KJ_ALWAYS_INLINE(T getDataElement(ElementCount index)); + // Get the element of the given type at the given index. + + template + KJ_ALWAYS_INLINE(void setDataElement(ElementCount index, kj::NoInfer value)); + // Set the element at the given index. + + KJ_ALWAYS_INLINE(PointerBuilder getPointerElement(ElementCount index)); + + StructBuilder getStructElement(ElementCount index); + + ListReader asReader() const; + // Get a ListReader pointing at the same memory. + + BuilderArena* getArena(); + // Gets the arena in which this object is allocated. + +private: + SegmentBuilder* segment; // Memory segment in which the list resides. + + byte* ptr; // Pointer to list content. + + ListElementCount elementCount; // Number of elements in the list. + + BitsPerElementN<23> step; + // The distance between elements. The maximum value occurs when a struct contains 2^16-1 data + // words and 2^16-1 pointers, i.e. 2^17 - 2 words, or 2^23 - 128 bits. + + StructDataBitCount structDataSize; + StructPointerCount structPointerCount; + // The struct properties to use when interpreting the elements as structs. All lists can be + // interpreted as struct lists, so these are always filled in. + + ElementSize elementSize; + // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE + // from other types when the overall size is exactly zero or one words. + + inline ListBuilder(SegmentBuilder* segment, void* ptr, + BitsPerElementN<23> step, ListElementCount size, + StructDataBitCount structDataSize, StructPointerCount structPointerCount, + ElementSize elementSize) + : segment(segment), ptr(reinterpret_cast(ptr)), + elementCount(size), step(step), structDataSize(structDataSize), + structPointerCount(structPointerCount), elementSize(elementSize) {} + + friend class StructBuilder; + friend struct WireHelpers; + friend class OrphanBuilder; +}; + +class ListReader { +public: + inline explicit ListReader(ElementSize elementSize) + : segment(nullptr), ptr(nullptr), elementCount(ZERO * ELEMENTS), + step(ZERO * BITS / ELEMENTS), structDataSize(ZERO * BITS), + structPointerCount(ZERO * POINTERS), elementSize(elementSize), nestingLimit(0x7fffffff) {} + + inline ListElementCount size() const; + // The number of elements in the list. + + inline ElementSize getElementSize() const { return elementSize; } + + Text::Reader asText(); + Data::Reader asData(); + // Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized. + + kj::ArrayPtr asRawBytes() const; + + template + KJ_ALWAYS_INLINE(T getDataElement(ElementCount index) const); + // Get the element of the given type at the given index. + + KJ_ALWAYS_INLINE(PointerReader getPointerElement(ElementCount index) const); + + StructReader getStructElement(ElementCount index) const; + + MessageSizeCounts totalSize() const; + // Like StructReader::totalSize(). Note that for struct lists, the size includes the list tag. + +private: + SegmentReader* segment; // Memory segment in which the list resides. + + const byte* ptr; // Pointer to list content. + + ListElementCount elementCount; // Number of elements in the list. + + BitsPerElementN<23> step; + // The distance between elements. The maximum value occurs when a struct contains 2^16-1 data + // words and 2^16-1 pointers, i.e. 2^17 - 2 words, or 2^23 - 2 bits. + + StructDataBitCount structDataSize; + StructPointerCount structPointerCount; + // The struct properties to use when interpreting the elements as structs. All lists can be + // interpreted as struct lists, so these are always filled in. + + ElementSize elementSize; + // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE + // from other types when the overall size is exactly zero or one words. + + int nestingLimit; + // Limits the depth of message structures to guard against stack-overflow-based DoS attacks. + // Once this reaches zero, further pointers will be pruned. + + inline ListReader(SegmentReader* segment, const void* ptr, + ListElementCount elementCount, BitsPerElementN<23> step, + StructDataBitCount structDataSize, StructPointerCount structPointerCount, + ElementSize elementSize, int nestingLimit) + : segment(segment), ptr(reinterpret_cast(ptr)), + elementCount(elementCount), step(step), structDataSize(structDataSize), + structPointerCount(structPointerCount), elementSize(elementSize), + nestingLimit(nestingLimit) {} + + friend class StructReader; + friend class ListBuilder; + friend struct WireHelpers; + friend class OrphanBuilder; +}; + +// ------------------------------------------------------------------- + +class OrphanBuilder { +public: + inline OrphanBuilder(): segment(nullptr), location(nullptr) { + memset(&tag, 0, sizeof(tag)); + } + OrphanBuilder(const OrphanBuilder& other) = delete; + inline OrphanBuilder(OrphanBuilder&& other) noexcept; + inline ~OrphanBuilder() noexcept(false); + + static OrphanBuilder initStruct(BuilderArena* arena, StructSize size); + static OrphanBuilder initList(BuilderArena* arena, ElementCount elementCount, ElementSize elementSize); + static OrphanBuilder initStructList(BuilderArena* arena, ElementCount elementCount, StructSize elementSize); + static OrphanBuilder initText(BuilderArena* arena, ByteCount size); + static OrphanBuilder initData(BuilderArena* arena, ByteCount size); + + static OrphanBuilder copy(BuilderArena* arena, StructReader copyFrom); + static OrphanBuilder copy(BuilderArena* arena, ListReader copyFrom); + static OrphanBuilder copy(BuilderArena* arena, PointerReader copyFrom); + static OrphanBuilder copy(BuilderArena* arena, Text::Reader copyFrom); + static OrphanBuilder copy(BuilderArena* arena, Data::Reader copyFrom); + + OrphanBuilder& operator=(const OrphanBuilder& other) = delete; + inline OrphanBuilder& operator=(OrphanBuilder&& other); + + inline bool operator==(decltype(nullptr)) const { return location == nullptr; } + inline bool operator!=(decltype(nullptr)) const { return location != nullptr; } + + StructBuilder asStruct(StructSize size); + // Interpret as a struct, or throw an exception if not a struct. + + ListBuilder asList(ElementSize elementSize); + // Interpret as a list, or throw an exception if not a list. elementSize cannot be + // INLINE_COMPOSITE -- use asStructList() instead. + + ListBuilder asStructList(StructSize elementSize); + // Interpret as a struct list, or throw an exception if not a list. + + ListBuilder asListAnySize(); + // For AnyList. + + Text::Builder asText(); + Data::Builder asData(); + // Interpret as a blob, or throw an exception if not a blob. + + StructReader asStructReader(StructSize size) const; + ListReader asListReader(ElementSize elementSize) const; + ListReader asListReaderAnySize() const; + Text::Reader asTextReader() const; + Data::Reader asDataReader() const; + +private: + static_assert(ONE * POINTERS * WORDS_PER_POINTER == ONE * WORDS, + "This struct assumes a pointer is one word."); + word tag; + // Contains an encoded WirePointer representing this object. WirePointer is defined in + // layout.c++, but fits in a word. + // + // This may be a FAR pointer. Even in that case, `location` points to the eventual destination + // of that far pointer. The reason we keep the far pointer around rather than just making `tag` + // represent the final destination is because if the eventual adopter of the pointer is not in + // the target's segment then it may be useful to reuse the far pointer landing pad. + // + // If `tag` is not a far pointer, its offset is garbage; only `location` points to the actual + // target. + + SegmentBuilder* segment; + // Segment in which the object resides. + + word* location; + // Pointer to the object, or nullptr if the pointer is null. + + inline OrphanBuilder(const void* tagPtr, SegmentBuilder* segment, + word* location) + : segment(segment), location(location) { + memcpy(&tag, tagPtr, sizeof(tag)); + } + + inline WirePointer* tagAsPtr() { return reinterpret_cast(&tag); } + inline const WirePointer* tagAsPtr() const { return reinterpret_cast(&tag); } + + void euthanize(); + // Erase the target object, zeroing it out and possibly reclaiming the memory. Called when + // the OrphanBuilder is being destroyed or overwritten and it is non-null. + + friend struct WireHelpers; +}; + +// ======================================================================================= +// Internal implementation details... + +// These are defined in the source file. +template <> typename Text::Builder PointerBuilder::initBlob(ByteCount size); +template <> void PointerBuilder::setBlob(typename Text::Reader value); +template <> typename Text::Builder PointerBuilder::getBlob( + const void* defaultValue, ByteCount defaultSize); +template <> typename Text::Reader PointerReader::getBlob( + const void* defaultValue, ByteCount defaultSize) const; + +template <> typename Data::Builder PointerBuilder::initBlob(ByteCount size); +template <> void PointerBuilder::setBlob(typename Data::Reader value); +template <> typename Data::Builder PointerBuilder::getBlob( + const void* defaultValue, ByteCount defaultSize); +template <> typename Data::Reader PointerReader::getBlob( + const void* defaultValue, ByteCount defaultSize) const; + +inline PointerBuilder PointerBuilder::getRoot( + SegmentBuilder* segment, word* location) { + return PointerBuilder(segment, reinterpret_cast(location)); +} + +inline PointerReader PointerReader::getRootUnchecked(const word* location) { + return PointerReader(nullptr, + reinterpret_cast(location), 0x7fffffff); +} + +// ------------------------------------------------------------------- + +inline kj::ArrayPtr StructBuilder::getDataSectionAsBlob() { + return kj::ArrayPtr(reinterpret_cast(data), + unbound(dataSize / BITS_PER_BYTE / BYTES)); +} + +inline _::ListBuilder StructBuilder::getPointerSectionAsList() { + return _::ListBuilder(segment, pointers, ONE * POINTERS * BITS_PER_POINTER / ELEMENTS, + pointerCount * (ONE * ELEMENTS / POINTERS), + ZERO * BITS, ONE * POINTERS, ElementSize::POINTER); +} + +template +inline bool StructBuilder::hasDataField(StructDataOffset offset) { + return getDataField>(offset) != 0; +} + +template <> +inline bool StructBuilder::hasDataField(StructDataOffset offset) { + return false; +} + +template +inline T StructBuilder::getDataField(StructDataOffset offset) { + return reinterpret_cast*>(data)[unbound(offset / ELEMENTS)].get(); +} + +template <> +inline bool StructBuilder::getDataField(StructDataOffset offset) { + BitCount32 boffset = offset * (ONE * BITS / ELEMENTS); + byte* b = reinterpret_cast(data) + boffset / BITS_PER_BYTE; + return (*reinterpret_cast(b) & + unbound(ONE << (boffset % BITS_PER_BYTE / BITS))) != 0; +} + +template <> +inline Void StructBuilder::getDataField(StructDataOffset offset) { + return VOID; +} + +template +inline T StructBuilder::getDataField(StructDataOffset offset, Mask mask) { + return unmask(getDataField >(offset), mask); +} + +template +inline void StructBuilder::setDataField(StructDataOffset offset, kj::NoInfer value) { + reinterpret_cast*>(data)[unbound(offset / ELEMENTS)].set(value); +} + +#if CAPNP_CANONICALIZE_NAN +// Use mask() on floats and doubles to make sure we canonicalize NaNs. +template <> +inline void StructBuilder::setDataField(StructDataOffset offset, float value) { + setDataField(offset, mask(value, 0)); +} +template <> +inline void StructBuilder::setDataField(StructDataOffset offset, double value) { + setDataField(offset, mask(value, 0)); +} +#endif + +template <> +inline void StructBuilder::setDataField(StructDataOffset offset, bool value) { + auto boffset = offset * (ONE * BITS / ELEMENTS); + byte* b = reinterpret_cast(data) + boffset / BITS_PER_BYTE; + uint bitnum = unboundMaxBits<3>(boffset % BITS_PER_BYTE / BITS); + *reinterpret_cast(b) = (*reinterpret_cast(b) & ~(1 << bitnum)) + | (static_cast(value) << bitnum); +} + +template <> +inline void StructBuilder::setDataField(StructDataOffset offset, Void value) {} + +template +inline void StructBuilder::setDataField(StructDataOffset offset, + kj::NoInfer value, Mask m) { + setDataField >(offset, mask(value, m)); +} + +inline PointerBuilder StructBuilder::getPointerField(StructPointerOffset ptrIndex) { + // Hacky because WirePointer is defined in the .c++ file (so is incomplete here). + return PointerBuilder(segment, reinterpret_cast( + reinterpret_cast(pointers) + ptrIndex * WORDS_PER_POINTER)); +} + +// ------------------------------------------------------------------- + +inline kj::ArrayPtr StructReader::getDataSectionAsBlob() const { + return kj::ArrayPtr(reinterpret_cast(data), + unbound(dataSize / BITS_PER_BYTE / BYTES)); +} + +inline _::ListReader StructReader::getPointerSectionAsList() const { + return _::ListReader(segment, pointers, pointerCount * (ONE * ELEMENTS / POINTERS), + ONE * POINTERS * BITS_PER_POINTER / ELEMENTS, ZERO * BITS, ONE * POINTERS, + ElementSize::POINTER, nestingLimit); +} + +template +inline bool StructReader::hasDataField(StructDataOffset offset) const { + return getDataField>(offset) != 0; +} + +template <> +inline bool StructReader::hasDataField(StructDataOffset offset) const { + return false; +} + +template +inline T StructReader::getDataField(StructDataOffset offset) const { + if ((offset + ONE * ELEMENTS) * capnp::bitsPerElement() <= dataSize) { + return reinterpret_cast*>(data)[unbound(offset / ELEMENTS)].get(); + } else { + return static_cast(0); + } +} + +template <> +inline bool StructReader::getDataField(StructDataOffset offset) const { + auto boffset = offset * (ONE * BITS / ELEMENTS); + if (boffset < dataSize) { + const byte* b = reinterpret_cast(data) + boffset / BITS_PER_BYTE; + return (*reinterpret_cast(b) & + unbound(ONE << (boffset % BITS_PER_BYTE / BITS))) != 0; + } else { + return false; + } +} + +template <> +inline Void StructReader::getDataField(StructDataOffset offset) const { + return VOID; +} + +template +T StructReader::getDataField(StructDataOffset offset, Mask mask) const { + return unmask(getDataField >(offset), mask); +} + +inline PointerReader StructReader::getPointerField(StructPointerOffset ptrIndex) const { + if (ptrIndex < pointerCount) { + // Hacky because WirePointer is defined in the .c++ file (so is incomplete here). + return PointerReader(segment, reinterpret_cast( + reinterpret_cast(pointers) + ptrIndex * WORDS_PER_POINTER), nestingLimit); + } else{ + return PointerReader(); + } +} + +// ------------------------------------------------------------------- + +inline ListElementCount ListBuilder::size() const { return elementCount; } + +template +inline T ListBuilder::getDataElement(ElementCount index) { + return reinterpret_cast*>( + ptr + upgradeBound(index) * step / BITS_PER_BYTE)->get(); + + // TODO(perf): Benchmark this alternate implementation, which I suspect may make better use of + // the x86 SIB byte. Also use it for all the other getData/setData implementations below, and + // the various non-inline methods that look up pointers. + // Also if using this, consider changing ptr back to void* instead of byte*. +// return reinterpret_cast*>(ptr)[ +// index / ELEMENTS * (step / capnp::bitsPerElement())].get(); +} + +template <> +inline bool ListBuilder::getDataElement(ElementCount index) { + // Ignore step for bit lists because bit lists cannot be upgraded to struct lists. + auto bindex = index * (ONE * BITS / ELEMENTS); + byte* b = ptr + bindex / BITS_PER_BYTE; + return (*reinterpret_cast(b) & + unbound(ONE << (bindex % BITS_PER_BYTE / BITS))) != 0; +} + +template <> +inline Void ListBuilder::getDataElement(ElementCount index) { + return VOID; +} + +template +inline void ListBuilder::setDataElement(ElementCount index, kj::NoInfer value) { + reinterpret_cast*>( + ptr + upgradeBound(index) * step / BITS_PER_BYTE)->set(value); +} + +#if CAPNP_CANONICALIZE_NAN +// Use mask() on floats and doubles to make sure we canonicalize NaNs. +template <> +inline void ListBuilder::setDataElement(ElementCount index, float value) { + setDataElement(index, mask(value, 0)); +} +template <> +inline void ListBuilder::setDataElement(ElementCount index, double value) { + setDataElement(index, mask(value, 0)); +} +#endif + +template <> +inline void ListBuilder::setDataElement(ElementCount index, bool value) { + // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists. + auto bindex = index * (ONE * BITS / ELEMENTS); + byte* b = ptr + bindex / BITS_PER_BYTE; + auto bitnum = bindex % BITS_PER_BYTE / BITS; + *reinterpret_cast(b) = (*reinterpret_cast(b) & ~(1 << unbound(bitnum))) + | (static_cast(value) << unbound(bitnum)); +} + +template <> +inline void ListBuilder::setDataElement(ElementCount index, Void value) {} + +inline PointerBuilder ListBuilder::getPointerElement(ElementCount index) { + return PointerBuilder(segment, reinterpret_cast(ptr + + upgradeBound(index) * step / BITS_PER_BYTE)); +} + +// ------------------------------------------------------------------- + +inline ListElementCount ListReader::size() const { return elementCount; } + +template +inline T ListReader::getDataElement(ElementCount index) const { + return reinterpret_cast*>( + ptr + upgradeBound(index) * step / BITS_PER_BYTE)->get(); +} + +template <> +inline bool ListReader::getDataElement(ElementCount index) const { + // Ignore step for bit lists because bit lists cannot be upgraded to struct lists. + auto bindex = index * (ONE * BITS / ELEMENTS); + const byte* b = ptr + bindex / BITS_PER_BYTE; + return (*reinterpret_cast(b) & + unbound(ONE << (bindex % BITS_PER_BYTE / BITS))) != 0; +} + +template <> +inline Void ListReader::getDataElement(ElementCount index) const { + return VOID; +} + +inline PointerReader ListReader::getPointerElement(ElementCount index) const { + // If the list elements have data sections we need to skip those. Note that for pointers to be + // present at all (which already must be true if we get here), then `structDataSize` must be a + // whole number of words, so we don't have to worry about unaligned reads here. + auto offset = structDataSize / BITS_PER_BYTE; + return PointerReader(segment, reinterpret_cast( + ptr + offset + upgradeBound(index) * step / BITS_PER_BYTE), nestingLimit); +} + +// ------------------------------------------------------------------- + +inline OrphanBuilder::OrphanBuilder(OrphanBuilder&& other) noexcept + : segment(other.segment), location(other.location) { + memcpy(&tag, &other.tag, sizeof(tag)); // Needs memcpy to comply with aliasing rules. + other.segment = nullptr; + other.location = nullptr; +} + +inline OrphanBuilder::~OrphanBuilder() noexcept(false) { + if (segment != nullptr) euthanize(); +} + +inline OrphanBuilder& OrphanBuilder::operator=(OrphanBuilder&& other) { + // With normal smart pointers, it's important to handle the case where the incoming pointer + // is actually transitively owned by this one. In this case, euthanize() would destroy `other` + // before we copied it. This isn't possible in the case of `OrphanBuilder` because it only + // owns message objects, and `other` is not itself a message object, therefore cannot possibly + // be transitively owned by `this`. + + if (segment != nullptr) euthanize(); + segment = other.segment; + + location = other.location; + memcpy(&tag, &other.tag, sizeof(tag)); // Needs memcpy to comply with aliasing rules. + other.segment = nullptr; + other.location = nullptr; + return *this; +} + +} // namespace _ (private) +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/list.h b/vendor/capnproto/src/capnp/list.h new file mode 100644 index 0000000..4a317fc --- /dev/null +++ b/vendor/capnproto/src/capnp/list.h @@ -0,0 +1,548 @@ +// 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. + +#pragma once + +#include "layout.h" +#include "orphan.h" +#include + +CAPNP_BEGIN_HEADER + +namespace capnp { +namespace _ { // private + +template +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; +}; + +// By default this isn't compatible with STL algorithms. To add STL support either define +// KJ_STD_COMPAT at the top of your compilation unit or include capnp/compat/std-iterator.h. +template +class IndexingIterator { +public: + IndexingIterator() = default; + + inline Element operator*() const { return (*container)[index]; } + inline TemporaryPointer operator->() const { + return TemporaryPointer((*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 +struct List { + // List of primitives. + + List() = delete; + + class Reader { + public: + typedef List Reads; + + inline Reader(): reader(_::elementSizeForType()) {} + 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(bounded(index) * ELEMENTS); + } + + typedef _::IndexingIterator Iterator; + inline Iterator begin() const { return Iterator(this, 0); } + inline Iterator end() const { return Iterator(this, size()); } + + inline MessageSize totalSize() const { + return reader.totalSize().asPublic(); + } + + private: + _::ListReader reader; + template + friend struct _::PointerHelpers; + template + friend struct List; + friend class Orphanage; + template + friend struct ToDynamic_; + }; + + class Builder { + public: + typedef List Builds; + + inline Builder(): builder(_::elementSizeForType()) {} + 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(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(bounded(index) * ELEMENTS, value); + } + + typedef _::IndexingIterator Iterator; + inline Iterator begin() { return Iterator(this, 0); } + inline Iterator end() { return Iterator(this, size()); } + + private: + _::ListBuilder builder; + template + friend struct _::PointerHelpers; + friend class Orphanage; + template + friend struct ToDynamic_; + }; + + class Pipeline {}; + +private: + inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) { + return builder.initList(_::elementSizeForType(), bounded(size) * ELEMENTS); + } + inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) { + return builder.getList(_::elementSizeForType(), defaultValue); + } + inline static _::ListReader getFromPointer( + const _::PointerReader& reader, const word* defaultValue) { + return reader.getList(_::elementSizeForType(), defaultValue); + } + + template + friend struct List; + template + friend struct _::PointerHelpers; +}; + +template +struct List: public List {}; + +template +struct List { + // List of structs. + + List() = delete; + + class Reader { + public: + typedef List 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 Iterator; + inline Iterator begin() const { return Iterator(this, 0); } + inline Iterator end() const { return Iterator(this, size()); } + + inline MessageSize totalSize() const { + return reader.totalSize().asPublic(); + } + + private: + _::ListReader reader; + template + friend struct _::PointerHelpers; + template + friend struct List; + friend class Orphanage; + template + friend struct ToDynamic_; + }; + + class Builder { + public: + typedef List 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&& 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. + + 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 Iterator; + inline Iterator begin() { return Iterator(this, 0); } + inline Iterator end() { return Iterator(this, size()); } + + private: + _::ListBuilder builder; + template + friend struct _::PointerHelpers; + friend class Orphanage; + template + friend struct ToDynamic_; + }; + + class Pipeline {}; + +private: + inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) { + return builder.initStructList(bounded(size) * ELEMENTS, _::structSize()); + } + inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) { + return builder.getStructList(_::structSize(), defaultValue); + } + inline static _::ListReader getFromPointer( + const _::PointerReader& reader, const word* defaultValue) { + return reader.getList(ElementSize::INLINE_COMPOSITE, defaultValue); + } + + template + friend struct List; + template + friend struct _::PointerHelpers; +}; + +template +struct List, Kind::LIST> { + // List of lists. + + List() = delete; + + class Reader { + public: + typedef List> 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::Reader operator[](uint index) const { + KJ_IREQUIRE(index < size()); + return typename List::Reader(_::PointerHelpers>::get( + reader.getPointerElement(bounded(index) * ELEMENTS))); + } + + typedef _::IndexingIterator::Reader> Iterator; + inline Iterator begin() const { return Iterator(this, 0); } + inline Iterator end() const { return Iterator(this, size()); } + + inline MessageSize totalSize() const { + return reader.totalSize().asPublic(); + } + + private: + _::ListReader reader; + template + friend struct _::PointerHelpers; + template + friend struct List; + friend class Orphanage; + template + friend struct ToDynamic_; + }; + + class Builder { + public: + typedef List> 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::Builder operator[](uint index) { + KJ_IREQUIRE(index < size()); + return typename List::Builder(_::PointerHelpers>::get( + builder.getPointerElement(bounded(index) * ELEMENTS))); + } + inline typename List::Builder init(uint index, uint size) { + KJ_IREQUIRE(index < this->size()); + return typename List::Builder(_::PointerHelpers>::init( + builder.getPointerElement(bounded(index) * ELEMENTS), size)); + } + inline void set(uint index, typename List::Reader value) { + KJ_IREQUIRE(index < size()); + builder.getPointerElement(bounded(index) * ELEMENTS).setList(value.reader); + } + void set(uint index, std::initializer_list> 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>&& value) { + KJ_IREQUIRE(index < size()); + builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder)); + } + inline Orphan> disown(uint index) { + KJ_IREQUIRE(index < size()); + return Orphan>(builder.getPointerElement(bounded(index) * ELEMENTS).disown()); + } + + typedef _::IndexingIterator::Builder> Iterator; + inline Iterator begin() { return Iterator(this, 0); } + inline Iterator end() { return Iterator(this, size()); } + + private: + _::ListBuilder builder; + template + friend struct _::PointerHelpers; + friend class Orphanage; + template + 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 + friend struct List; + template + friend struct _::PointerHelpers; +}; + +template +struct List { + List() = delete; + + class Reader { + public: + typedef List 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(nullptr, ZERO * BYTES); + } + + typedef _::IndexingIterator Iterator; + inline Iterator begin() const { return Iterator(this, 0); } + inline Iterator end() const { return Iterator(this, size()); } + + inline MessageSize totalSize() const { + return reader.totalSize().asPublic(); + } + + private: + _::ListReader reader; + template + friend struct _::PointerHelpers; + template + friend struct List; + friend class Orphanage; + template + friend struct ToDynamic_; + }; + + class Builder { + public: + typedef List 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(nullptr, ZERO * BYTES); + } + inline void set(uint index, typename T::Reader value) { + KJ_IREQUIRE(index < size()); + builder.getPointerElement(bounded(index) * ELEMENTS).template setBlob(value); + } + inline typename T::Builder init(uint index, uint size) { + KJ_IREQUIRE(index < this->size()); + return builder.getPointerElement(bounded(index) * ELEMENTS) + .template initBlob(bounded(size) * BYTES); + } + inline void adopt(uint index, Orphan&& value) { + KJ_IREQUIRE(index < size()); + builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder)); + } + inline Orphan disown(uint index) { + KJ_IREQUIRE(index < size()); + return Orphan(builder.getPointerElement(bounded(index) * ELEMENTS).disown()); + } + + typedef _::IndexingIterator Iterator; + inline Iterator begin() { return Iterator(this, 0); } + inline Iterator end() { return Iterator(this, size()); } + + private: + _::ListBuilder builder; + template + friend struct _::PointerHelpers; + friend class Orphanage; + template + 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 + friend struct List; + template + friend struct _::PointerHelpers; +}; + +} // namespace capnp + +#ifdef KJ_STD_COMPAT +#include "compat/std-iterator.h" +#endif // KJ_STD_COMPAT + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/message.c++ b/vendor/capnproto/src/capnp/message.c++ new file mode 100644 index 0000000..7c6b7ed --- /dev/null +++ b/vendor/capnproto/src/capnp/message.c++ @@ -0,0 +1,211 @@ +// 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. + +#define CAPNP_PRIVATE +#include "message.h" +#include +#include "arena.h" +#include "orphan.h" +#include +#include + +namespace capnp { + +MessageReader::MessageReader(ReaderOptions options): options(options), allocatedArena(false) {} +MessageReader::~MessageReader() noexcept(false) { + if (allocatedArena) { + arena()->~ReaderArena(); + } +} + +AnyPointer::Reader MessageReader::getRootInternal() { + if (!allocatedArena) { + static_assert(sizeof(_::ReaderArena) <= sizeof(arenaSpace), + "arenaSpace is too small to hold a ReaderArena. Please increase it. This will break " + "ABI compatibility."); + kj::ctor(*arena(), this); + allocatedArena = true; + } + + _::SegmentReader* segment = arena()->tryGetSegment(_::SegmentId(0)); + KJ_REQUIRE(segment != nullptr && + segment->checkObject(segment->getStartPtr(), ONE * WORDS), + "Message did not contain a root pointer.") { + return AnyPointer::Reader(); + } + + return AnyPointer::Reader(_::PointerReader::getRoot( + segment, + segment->getStartPtr(), options.nestingLimit)); +} + +// ------------------------------------------------------------------- + +MessageBuilder::MessageBuilder(): allocatedArena(false) {} + +MessageBuilder::~MessageBuilder() noexcept(false) { + if (allocatedArena) { + kj::dtor(*arena()); + } +} + +_::SegmentBuilder* MessageBuilder::getRootSegment() { + if (allocatedArena) { + return arena()->getSegment(_::SegmentId(0)); + } else { + static_assert(sizeof(_::BuilderArena) <= sizeof(arenaSpace), + "arenaSpace is too small to hold a BuilderArena. Please increase it."); + kj::ctor(*arena(), this); + allocatedArena = true; + + auto allocation = arena()->allocate(POINTER_SIZE_IN_WORDS); + + KJ_ASSERT(allocation.segment->getSegmentId() == _::SegmentId(0), + "First allocated word of new arena was not in segment ID 0."); + KJ_ASSERT(allocation.words == allocation.segment->getPtrUnchecked(ZERO * WORDS), + "First allocated word of new arena was not the first word in its segment."); + return allocation.segment; + } +} + +AnyPointer::Builder MessageBuilder::getRootInternal() { + _::SegmentBuilder* rootSegment = getRootSegment(); + return AnyPointer::Builder(_::PointerBuilder::getRoot( + rootSegment, rootSegment->getPtrUnchecked(ZERO * WORDS))); +} + +kj::ArrayPtr> MessageBuilder::getSegmentsForOutput() { + if (allocatedArena) { + return arena()->getSegmentsForOutput(); + } else { + return nullptr; + } +} + +Orphanage MessageBuilder::getOrphanage() { + // We must ensure that the arena and root pointer have been allocated before the Orphanage + // can be used. + if (!allocatedArena) getRootSegment(); + + return Orphanage(arena()); +} + +// ======================================================================================= + +// ------------------------------------------------------------------- + +MallocMessageBuilder::MallocMessageBuilder( + uint firstSegmentWords, AllocationStrategy allocationStrategy) + : nextSize(firstSegmentWords), allocationStrategy(allocationStrategy), + ownFirstSegment(true), returnedFirstSegment(false), firstSegment(nullptr) {} + +MallocMessageBuilder::MallocMessageBuilder( + kj::ArrayPtr firstSegment, AllocationStrategy allocationStrategy) + : nextSize(firstSegment.size()), allocationStrategy(allocationStrategy), + ownFirstSegment(false), returnedFirstSegment(false), firstSegment(firstSegment.begin()) { + KJ_REQUIRE(firstSegment.size() > 0, "First segment size must be non-zero."); + + // Checking just the first word should catch most cases of failing to zero the segment. + KJ_REQUIRE(*reinterpret_cast(firstSegment.begin()) == 0, + "First segment must be zeroed."); +} + +MallocMessageBuilder::~MallocMessageBuilder() noexcept(false) { + if (returnedFirstSegment) { + if (ownFirstSegment) { + free(firstSegment); + } else { + // Must zero first segment. + kj::ArrayPtr> segments = getSegmentsForOutput(); + if (segments.size() > 0) { + KJ_ASSERT(segments[0].begin() == firstSegment, + "First segment in getSegmentsForOutput() is not the first segment allocated?"); + memset(firstSegment, 0, segments[0].size() * sizeof(word)); + } + } + + for (void* ptr: moreSegments) { + free(ptr); + } + } +} + +kj::ArrayPtr MallocMessageBuilder::allocateSegment(uint minimumSize) { + KJ_REQUIRE(bounded(minimumSize) * WORDS <= MAX_SEGMENT_WORDS, + "MallocMessageBuilder asked to allocate segment above maximum serializable size."); + KJ_ASSERT(bounded(nextSize) * WORDS <= MAX_SEGMENT_WORDS, + "MallocMessageBuilder nextSize out of bounds."); + + if (!returnedFirstSegment && !ownFirstSegment) { + kj::ArrayPtr result = kj::arrayPtr(reinterpret_cast(firstSegment), nextSize); + if (result.size() >= minimumSize) { + returnedFirstSegment = true; + return result; + } + // If the provided first segment wasn't big enough, we discard it and proceed to allocate + // our own. This never happens in practice since minimumSize is always 1 for the first + // segment. + ownFirstSegment = true; + } + + uint size = kj::max(minimumSize, nextSize); + + void* result = calloc(size, sizeof(word)); + if (result == nullptr) { + KJ_FAIL_SYSCALL("calloc(size, sizeof(word))", ENOMEM, size); + } + + if (!returnedFirstSegment) { + firstSegment = result; + returnedFirstSegment = true; + + // After the first segment, we want nextSize to equal the total size allocated so far. + if (allocationStrategy == AllocationStrategy::GROW_HEURISTICALLY) nextSize = size; + } else { + moreSegments.add(result); + if (allocationStrategy == AllocationStrategy::GROW_HEURISTICALLY) { + // set nextSize = min(nextSize+size, MAX_SEGMENT_WORDS) + // while protecting against possible overflow of (nextSize+size) + nextSize = (size <= unbound(MAX_SEGMENT_WORDS / WORDS) - nextSize) + ? nextSize + size : unbound(MAX_SEGMENT_WORDS / WORDS); + } + } + + return kj::arrayPtr(reinterpret_cast(result), size); +} + +// ------------------------------------------------------------------- + +FlatMessageBuilder::FlatMessageBuilder(kj::ArrayPtr array): array(array), allocated(false) {} +FlatMessageBuilder::~FlatMessageBuilder() noexcept(false) {} + +void FlatMessageBuilder::requireFilled() { + KJ_REQUIRE(getSegmentsForOutput()[0].end() == array.end(), + "FlatMessageBuilder's buffer was too large."); +} + +kj::ArrayPtr FlatMessageBuilder::allocateSegment(uint minimumSize) { + KJ_REQUIRE(!allocated, "FlatMessageBuilder's buffer was not large enough."); + allocated = true; + return array; +} + +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/message.h b/vendor/capnproto/src/capnp/message.h new file mode 100644 index 0000000..8df1bd8 --- /dev/null +++ b/vendor/capnproto/src/capnp/message.h @@ -0,0 +1,464 @@ +// 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. + +#pragma once + +#include +#include +#include +#include +#include +#include "common.h" +#include "layout.h" +#include "any.h" + +CAPNP_BEGIN_HEADER + +namespace capnp { + +namespace _ { // private + class ReaderArena; + class BuilderArena; +} + +class StructSchema; +class Orphanage; +template +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()` to get a `MyStructType::Reader` + // representing the root of the message, then use that to traverse the message content. + // + // A message reader obtains segments through getSegment(). + +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 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::Reader getRoot(); + // Get the root struct of the message, interpreting it as the given struct type. + + template + 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 to + // use this. + +private: + ReaderOptions options; + +#if defined(__EMSCRIPTEN__) || (defined(__APPLE__) && (defined(__ppc__) || defined(__i386__))) + static constexpr size_t arenaSpacePadding = 19; +#else + static constexpr size_t arenaSpacePadding = 18; +#endif + + // 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 + // other 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. + alignas(8) void* arenaSpace[arenaSpacePadding + sizeof(kj::MutexGuarded) / 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()` 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_AND_MOVE(MessageBuilder); + + virtual kj::ArrayPtr allocateSegment(uint minimumSize) = 0; + // Allocates an array of at least the given number of zero'd 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. + // + // allocateSegment() is responsible for zeroing the memory before returning. This is required + // because otherwise the Cap'n Proto implementation would have to zero the memory anyway, and + // many allocators are able to provide already-zero'd memory more efficiently. + + template + typename RootType::Builder initRoot(); + // Initialize the root struct of the message as the given struct type. + + template + void setRoot(Reader&& value); + // Set the root struct to a deep copy of the given struct. + + template + typename RootType::Builder getRoot(); + // Get the root struct of the message, interpreting it as the given struct type. + + template + 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 to + // use this. + + template + 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 to + // use this. + + template + void adoptRoot(Orphan&& orphan); + // Like setRoot() but adopts the orphan without copying. + + kj::ArrayPtr> getSegmentsForOutput(); + // Get the raw data that makes up the message. + + Orphanage getOrphanage(); + +private: + alignas(8) 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::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::readMessageUnchecked(MyMessage::DEFAULT.words); +// +// To sanitize a message from an untrusted source such that it can be safely passed to +// readMessageUnchecked(), use copyToUnchecked(). + +template +void copyToUnchecked(Reader&& reader, kj::ArrayPtr 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::Reader readDataStruct(kj::ArrayPtr 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(bytes.begin()), +// reinterpret_cast(bytes.end())) + +template +typename kj::ArrayPtr 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`. + +template +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? + +template > +kj::Own> clone(Reader&& reader); +// Make a deep copy of the given Reader on the heap, producing an owned pointer. + +// ======================================================================================= + +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 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_AND_MOVE(MallocMessageBuilder); + virtual ~MallocMessageBuilder() noexcept(false); + + virtual kj::ArrayPtr allocateSegment(uint minimumSize) override; + +private: + uint nextSize; + AllocationStrategy allocationStrategy; + + bool ownFirstSegment; + bool returnedFirstSegment; + + void* firstSegment; + kj::Vector 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 array); + KJ_DISALLOW_COPY_AND_MOVE(FlatMessageBuilder); + virtual ~FlatMessageBuilder() noexcept(false); + + void requireFilled(); + // Throws an exception if the flat array is not exactly full. + + virtual kj::ArrayPtr allocateSegment(uint minimumSize) override; + +private: + kj::ArrayPtr array; + bool allocated; +}; + +// ======================================================================================= +// implementation details + +inline const ReaderOptions& MessageReader::getOptions() { + return options; +} + +template +inline typename RootType::Reader MessageReader::getRoot() { + return getRootInternal().getAs(); +} + +template +inline typename RootType::Builder MessageBuilder::initRoot() { + return getRootInternal().initAs(); +} + +template +inline void MessageBuilder::setRoot(Reader&& value) { + getRootInternal().setAs>(value); +} + +template +inline typename RootType::Builder MessageBuilder::getRoot() { + return getRootInternal().getAs(); +} + +template +void MessageBuilder::adoptRoot(Orphan&& orphan) { + return getRootInternal().adopt(kj::mv(orphan)); +} + +template +typename RootType::Reader MessageReader::getRoot(SchemaType schema) { + return getRootInternal().getAs(schema); +} + +template +typename RootType::Builder MessageBuilder::getRoot(SchemaType schema) { + return getRootInternal().getAs(schema); +} + +template +typename RootType::Builder MessageBuilder::initRoot(SchemaType schema) { + return getRootInternal().initAs(schema); +} + +template +typename RootType::Reader readMessageUnchecked(const word* data) { + return AnyPointer::Reader(_::PointerReader::getRootUnchecked(data)).getAs(); +} + +template +void copyToUnchecked(Reader&& reader, kj::ArrayPtr uncheckedBuffer) { + FlatMessageBuilder builder(uncheckedBuffer); + builder.setRoot(kj::fwd(reader)); + builder.requireFilled(); +} + +template +typename RootType::Reader readDataStruct(kj::ArrayPtr data) { + return typename RootType::Reader(_::StructReader(data)); +} + +template +typename kj::ArrayPtr writeDataStruct(BuilderType builder) { + auto bytes = _::PointerHelpers>::getInternalBuilder(kj::mv(builder)) + .getDataSectionAsBlob(); + return kj::arrayPtr(reinterpret_cast(bytes.begin()), + reinterpret_cast(bytes.end())); +} + +template +static typename Type::Reader defaultValue() { + return typename Type::Reader(_::StructReader()); +} + +template +kj::Own> clone(Reader&& reader) { + auto size = reader.totalSize(); + auto buffer = kj::heapArray(size.wordCount + 1); + memset(buffer.asBytes().begin(), 0, buffer.asBytes().size()); + copyToUnchecked(reader, buffer); + auto result = readMessageUnchecked>(buffer.begin()); + return kj::attachVal(result, kj::mv(buffer)); +} + +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/orphan.h b/vendor/capnproto/src/capnp/orphan.h new file mode 100644 index 0000000..a07ad97 --- /dev/null +++ b/vendor/capnproto/src/capnp/orphan.h @@ -0,0 +1,308 @@ +// 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. + +#pragma once + +#include "layout.h" + +CAPNP_BEGIN_HEADER + +namespace capnp { + +class StructSchema; +class ListSchema; +struct DynamicStruct; +struct DynamicList; + +template +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)` and `Orphan disownFoo()`. + // Orphans can also be created independently of any parent using an Orphanage. + // + // `Orphan` can be moved but not copied, like `Own`, 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 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 getReader() const; + + inline bool operator==(decltype(nullptr)) const { return builder == nullptr; } + inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; } + +private: + _::OrphanBuilder builder; + + template + friend struct _::PointerHelpers; + template + friend struct List; + template + 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 + 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 + Orphan newOrphan() const; + // Allocate a new orphaned struct. + + template + Orphan newOrphan(uint size) const; + // Allocate a new orphaned list or blob. + + Orphan newOrphan(StructSchema schema) const; + // Dynamically create an orphan struct with the given schema. You must + // #include to use this. + + Orphan newOrphan(ListSchema schema, uint size) const; + // Dynamically create an orphan list with the given schema. You must #include + // to use this. + + template + Orphan> newOrphanCopy(Reader copyFrom) const; + // Allocate a new orphaned object (struct, list, or blob) and initialize it as a copy of the + // given object. + +private: + _::BuilderArena* arena; + + inline explicit Orphanage(_::BuilderArena* arena) + : arena(arena) {} + + template + struct GetInnerBuilder; + template + struct GetInnerReader; + template + struct NewOrphanListImpl; + + friend class MessageBuilder; +}; + +// ======================================================================================= +// Inline implementation details. + +namespace _ { // private + +template +struct OrphanGetImpl; + +template +struct OrphanGetImpl { + +}; + +template +struct OrphanGetImpl { + static inline typename T::Builder apply(_::OrphanBuilder& builder) { + return typename T::Builder(builder.asStruct(_::structSize())); + } + static inline typename T::Reader applyReader(const _::OrphanBuilder& builder) { + return typename T::Reader(builder.asStructReader(_::structSize())); + } + +}; + +template +struct OrphanGetImpl, Kind::LIST> { + static inline typename List::Builder apply(_::OrphanBuilder& builder) { + return typename List::Builder(builder.asList(_::ElementSizeForType::value)); + } + static inline typename List::Reader applyReader(const _::OrphanBuilder& builder) { + return typename List::Reader(builder.asListReader(_::ElementSizeForType::value)); + } + +}; + +template +struct OrphanGetImpl, Kind::LIST> { + static inline typename List::Builder apply(_::OrphanBuilder& builder) { + return typename List::Builder(builder.asStructList(_::structSize())); + } + static inline typename List::Reader applyReader(const _::OrphanBuilder& builder) { + return typename List::Reader(builder.asListReader(_::ElementSizeForType::value)); + } + +}; + +template <> +struct OrphanGetImpl { + 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()); + } + +}; + +template <> +struct OrphanGetImpl { + 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()); + } + +}; + +} // namespace _ (private) + +template +inline BuilderFor Orphan::get() { + return _::OrphanGetImpl::apply(builder); +} + +template +inline ReaderFor Orphan::getReader() const { + return _::OrphanGetImpl::applyReader(builder); +} + +template +struct Orphanage::GetInnerBuilder { + static inline _::StructBuilder apply(typename T::Builder& t) { + return t._builder; + } +}; + +template +struct Orphanage::GetInnerBuilder { + static inline _::ListBuilder apply(typename T::Builder& t) { + return t.builder; + } +}; + +template +Orphanage Orphanage::getForMessageContaining(BuilderType builder) { + auto inner = GetInnerBuilder>::apply(builder); + return Orphanage(inner.getArena()); +} + +template +Orphan Orphanage::newOrphan() const { + return Orphan(_::OrphanBuilder::initStruct(arena, _::structSize())); +} + +template +struct Orphanage::NewOrphanListImpl> { + static inline _::OrphanBuilder apply( + _::BuilderArena* arena, uint size) { + return _::OrphanBuilder::initList( + arena, bounded(size) * ELEMENTS, _::ElementSizeForType::value); + } +}; + +template +struct Orphanage::NewOrphanListImpl> { + static inline _::OrphanBuilder apply( + _::BuilderArena* arena, uint size) { + return _::OrphanBuilder::initStructList( + arena, bounded(size) * ELEMENTS, _::structSize()); + } +}; + +template <> +struct Orphanage::NewOrphanListImpl { + static inline _::OrphanBuilder apply( + _::BuilderArena* arena, uint size) { + return _::OrphanBuilder::initText(arena, bounded(size) * BYTES); + } +}; + +template <> +struct Orphanage::NewOrphanListImpl { + static inline _::OrphanBuilder apply( + _::BuilderArena* arena, uint size) { + return _::OrphanBuilder::initData(arena, bounded(size) * BYTES); + } +}; + +template +Orphan Orphanage::newOrphan(uint size) const { + return Orphan(NewOrphanListImpl::apply(arena, size)); +} + +template +struct Orphanage::GetInnerReader { + static inline _::StructReader apply(const typename T::Reader& t) { + return t._reader; + } +}; + +template +struct Orphanage::GetInnerReader { + static inline _::ListReader apply(const typename T::Reader& t) { + return t.reader; + } +}; + +template +struct Orphanage::GetInnerReader { + static inline const typename T::Reader& apply(const typename T::Reader& t) { + return t; + } +}; + +template +inline Orphan> Orphanage::newOrphanCopy(Reader copyFrom) const { + return Orphan>(_::OrphanBuilder::copy( + arena, GetInnerReader>::apply(copyFrom))); +} + +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/pointer-helpers.h b/vendor/capnproto/src/capnp/pointer-helpers.h new file mode 100644 index 0000000..c747d22 --- /dev/null +++ b/vendor/capnproto/src/capnp/pointer-helpers.h @@ -0,0 +1,151 @@ +// 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. + +#pragma once + +#include "layout.h" +#include "list.h" + +CAPNP_BEGIN_HEADER + +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 +struct PointerHelpers { + 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(), defaultValue)); + } + static inline void set(PointerBuilder builder, typename T::Reader value) { + builder.setStruct(value._reader); + } + + static inline typename T::Builder init(PointerBuilder builder) { + return typename T::Builder(builder.initStruct(structSize())); + } + static inline void adopt(PointerBuilder builder, Orphan&& value) { + builder.adopt(kj::mv(value.builder)); + } + static inline Orphan disown(PointerBuilder builder) { + return Orphan(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 +struct PointerHelpers, Kind::LIST> { + static inline typename List::Reader get(PointerReader reader, + const word* defaultValue = nullptr) { + return typename List::Reader(List::getFromPointer(reader, defaultValue)); + } + static inline typename List::Builder get(PointerBuilder builder, + const word* defaultValue = nullptr) { + return typename List::Builder(List::getFromPointer(builder, defaultValue)); + } + static inline void set(PointerBuilder builder, typename List::Reader value) { + builder.setList(value.reader); + } + + static void set(PointerBuilder builder, kj::ArrayPtr> value) { + auto l = init(builder, value.size()); + uint i = 0; + for (auto& element: value) { + l.set(i++, element); + } + } + static inline typename List::Builder init(PointerBuilder builder, uint size) { + return typename List::Builder(List::initPointer(builder, size)); + } + static inline void adopt(PointerBuilder builder, Orphan>&& value) { + builder.adopt(kj::mv(value.builder)); + } + static inline Orphan> disown(PointerBuilder builder) { + return Orphan>(builder.disown()); + } + static inline _::ListReader getInternalReader(const typename List::Reader& reader) { + return reader.reader; + } + static inline _::ListBuilder getInternalBuilder(typename List::Builder&& builder) { + return builder.builder; + } +}; + +template +struct PointerHelpers { + static inline typename T::Reader get(PointerReader reader, + const void* defaultValue = nullptr, + uint defaultBytes = 0) { + return reader.getBlob(defaultValue, bounded(defaultBytes) * BYTES); + } + static inline typename T::Builder get(PointerBuilder builder, + const void* defaultValue = nullptr, + uint defaultBytes = 0) { + return builder.getBlob(defaultValue, bounded(defaultBytes) * BYTES); + } + static inline void set(PointerBuilder builder, typename T::Reader value) { + builder.setBlob(value); + } + + static inline typename T::Builder init(PointerBuilder builder, uint size) { + return builder.initBlob(bounded(size) * BYTES); + } + static inline void adopt(PointerBuilder builder, Orphan&& value) { + builder.adopt(kj::mv(value.builder)); + } + static inline Orphan disown(PointerBuilder builder) { + return Orphan(builder.disown()); + } +}; + +struct UncheckedMessage { + typedef const word* Reader; +}; + +template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; + +template <> +struct PointerHelpers { + // 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 + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/pretty-print.h b/vendor/capnproto/src/capnp/pretty-print.h new file mode 100644 index 0000000..f3c6ced --- /dev/null +++ b/vendor/capnproto/src/capnp/pretty-print.h @@ -0,0 +1,44 @@ +// 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. + +#pragma once + +#include "dynamic.h" +#include + +CAPNP_BEGIN_HEADER + +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 + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/raw-schema.h b/vendor/capnproto/src/capnp/raw-schema.h new file mode 100644 index 0000000..6f31fbc --- /dev/null +++ b/vendor/capnproto/src/capnp/raw-schema.h @@ -0,0 +1,223 @@ +// 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. + +#pragma once + +#include "common.h" // for uint and friends + + +CAPNP_BEGIN_HEADER + +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!). + + CONST_TYPE = 5 + // 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(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__ || defined(__clang__) + const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_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(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__ || defined(__clang__) + const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_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`. + + bool mayContainCapabilities = true; + // See StructSchema::mayContainCapabilities. +}; + +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 + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/schema-loader.c++ b/vendor/capnproto/src/capnp/schema-loader.c++ new file mode 100644 index 0000000..87a8e0c --- /dev/null +++ b/vendor/capnproto/src/capnp/schema-loader.c++ @@ -0,0 +1,2099 @@ +// 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. + +#define CAPNP_PRIVATE +#include "schema-loader.h" +#include "message.h" +#include "arena.h" +#include +#include +#include +#include +#include +#include + + +namespace capnp { + +namespace { + +struct SchemaBindingsPair { + const _::RawSchema* schema; + const _::RawBrandedSchema::Scope* scopeBindings; + + inline bool operator==(const SchemaBindingsPair& other) const { + return schema == other.schema && scopeBindings == other.scopeBindings; + } + inline uint hashCode() const { + return kj::hashCode(schema, scopeBindings); + } +}; + +} // namespace + +bool hasDiscriminantValue(const schema::Field::Reader& reader) { + return reader.getDiscriminantValue() != schema::Field::NO_DISCRIMINANT; +} + +class SchemaLoader::InitializerImpl: public _::RawSchema::Initializer { +public: + inline explicit InitializerImpl(const SchemaLoader& loader): loader(loader), callback(nullptr) {} + inline InitializerImpl(const SchemaLoader& loader, const LazyLoadCallback& callback) + : loader(loader), callback(callback) {} + + inline kj::Maybe getCallback() const { return callback; } + + void init(const _::RawSchema* schema) const override; + + inline bool operator==(decltype(nullptr)) const { return callback == nullptr; } + +private: + const SchemaLoader& loader; + kj::Maybe callback; +}; + +class SchemaLoader::BrandedInitializerImpl: public _::RawBrandedSchema::Initializer { +public: + inline explicit BrandedInitializerImpl(const SchemaLoader& loader): loader(loader) {} + + void init(const _::RawBrandedSchema* schema) const override; + +private: + const SchemaLoader& loader; +}; + +class SchemaLoader::Impl { +public: + inline explicit Impl(const SchemaLoader& loader) + : initializer(loader), brandedInitializer(loader) {} + inline Impl(const SchemaLoader& loader, const LazyLoadCallback& callback) + : initializer(loader, callback), brandedInitializer(loader) {} + + _::RawSchema* load(const schema::Node::Reader& reader, bool isPlaceholder); + + _::RawSchema* loadNative(const _::RawSchema* nativeSchema); + + _::RawSchema* loadEmpty(uint64_t id, kj::StringPtr name, schema::Node::Which kind, + bool isPlaceholder); + // Create a dummy empty schema of the given kind for the given id and load it. + + const _::RawBrandedSchema* makeBranded( + const _::RawSchema* schema, schema::Brand::Reader proto, + kj::Maybe> clientBrand); + + struct TryGetResult { + _::RawSchema* schema; + kj::Maybe callback; + }; + + TryGetResult tryGet(uint64_t typeId) const; + + const _::RawBrandedSchema* getUnbound(const _::RawSchema* schema); + + kj::Array getAllLoaded() const; + + void computeOptimizationHints(); + + void requireStructSize(uint64_t id, uint dataWordCount, uint pointerCount); + // Require any struct nodes loaded with this ID -- in the past and in the future -- to have at + // least the given sizes. Struct nodes that don't comply will simply be rewritten to comply. + // This is used to ensure that parents of group nodes have at least the size of the group node, + // so that allocating a struct that contains a group then getting the group node and setting + // its fields can't possibly write outside of the allocated space. + + kj::Arena arena; + +private: + kj::HashSet> dedupTable; + // Records raw segments of memory in the arena against which we my want to de-dupe later + // additions. Specifically, RawBrandedSchema binding tables are de-duped. + + kj::HashMap schemas; + kj::HashMap brands; + kj::HashMap unboundBrands; + + struct RequiredSize { + uint16_t dataWordCount; + uint16_t pointerCount; + }; + kj::HashMap structSizeRequirements; + + InitializerImpl initializer; + BrandedInitializerImpl brandedInitializer; + + kj::ArrayPtr makeUncheckedNode(schema::Node::Reader node); + // Construct a copy of the given schema node, allocated as a single-segment ("unchecked") node + // within the loader's arena. + + kj::ArrayPtr makeUncheckedNodeEnforcingSizeRequirements(schema::Node::Reader node); + // Like makeUncheckedNode() but if structSizeRequirements has a requirement for this node which + // is larger than the node claims to be, the size will be edited to comply. This should be rare. + // If the incoming node is not a struct, any struct size requirements will be ignored, but if + // such requirements exist, this indicates an inconsistency that could cause exceptions later on + // (but at least can't cause memory corruption). + + kj::ArrayPtr rewriteStructNodeWithSizes( + schema::Node::Reader node, uint dataWordCount, uint pointerCount); + // Make a copy of the given node (which must be a struct node) and set its sizes to be the max + // of what it said already and the given sizes. + + // If the encoded node does not meet the given struct size requirements, make a new copy that + // does. + void applyStructSizeRequirement(_::RawSchema* raw, uint dataWordCount, uint pointerCount); + + const _::RawBrandedSchema* makeBranded(const _::RawSchema* schema, + kj::ArrayPtr scopes); + + kj::ArrayPtr makeBrandedDependencies( + const _::RawSchema* schema, + kj::Maybe> bindings); + + void makeDep(_::RawBrandedSchema::Binding& result, + schema::Type::Reader type, kj::StringPtr scopeName, + kj::Maybe> brandBindings); + void makeDep(_::RawBrandedSchema::Binding& result, + uint64_t typeId, schema::Type::Which whichType, schema::Node::Which expectedKind, + schema::Brand::Reader brand, kj::StringPtr scopeName, + kj::Maybe> brandBindings); + // Looks up the schema and brand for a dependency, or creates lazily-evaluated placeholders if + // they don't already exist, and fills in `result`. `scopeName` is a human-readable name of the + // place where the type appeared. + // + // Note that we don't simply return a Binding because we need to be careful about initialization + // to ensure that our byte-based de-duplification works. If we constructed a Binding on the stack + // and returned it, padding bytes in that Binding could go uninitialized, causing it to appear + // unique when it's not. It is expected that `result` has been zero'd via memset() before these + // methods are called. + + const _::RawBrandedSchema* makeDepSchema( + schema::Type::Reader type, kj::StringPtr scopeName, + kj::Maybe> brandBindings); + // Invoke makeDep() then return the result's schema, or nullptr if it's a primitive type. + + template + kj::ArrayPtr copyDeduped(kj::ArrayPtr values); + template + kj::ArrayPtr copyDeduped(kj::ArrayPtr values); + // Copy the given array into the arena and return the copy -- unless an identical array + // was copied previously, in which case the existing copy is returned. + + friend class SchemaLoader::BrandedInitializerImpl; +}; + +// ======================================================================================= + +inline static void verifyVoid(Void value) {} +// Calls to this will break if the parameter type changes to non-void. We use this to detect +// when the code needs updating. + +class SchemaLoader::Validator { +public: + Validator(SchemaLoader::Impl& loader): loader(loader) {} + + bool validate(const schema::Node::Reader& node) { + isValid = true; + nodeName = node.getDisplayName(); + dependencies.clear(); + + KJ_CONTEXT("validating schema node", nodeName, (uint)node.which()); + + if (node.getParameters().size() > 0) { + KJ_REQUIRE(node.getIsGeneric(), "if parameter list is non-empty, isGeneric must be true") { + isValid = false; + return false; + } + } + + switch (node.which()) { + case schema::Node::FILE: + verifyVoid(node.getFile()); + break; + case schema::Node::STRUCT: + validate(node.getStruct(), node.getScopeId()); + break; + case schema::Node::ENUM: + validate(node.getEnum()); + break; + case schema::Node::INTERFACE: + KJ_FAIL_REQUIRE("Interfaces are not supported."); + case schema::Node::CONST: + validate(node.getConst()); + break; + case schema::Node::ANNOTATION: + validate(node.getAnnotation()); + break; + } + + // We accept and pass through node types we don't recognize. + return isValid; + } + + const _::RawSchema** makeDependencyArray(uint32_t* count) { + *count = dependencies.size(); + kj::ArrayPtr result = + loader.arena.allocateArray(*count); + uint pos = 0; + for (auto& dep: dependencies) { + result[pos++] = dep.value; + } + KJ_DASSERT(pos == *count); + return result.begin(); + } + + const uint16_t* makeMemberInfoArray(uint32_t* count) { + *count = members.size(); + kj::ArrayPtr result = loader.arena.allocateArray(*count); + uint pos = 0; + for (auto& member: members) { + result[pos++] = member.value; + } + KJ_DASSERT(pos == *count); + return result.begin(); + } + + const uint16_t* makeMembersByDiscriminantArray() { + return membersByDiscriminant.begin(); + } + +private: + SchemaLoader::Impl& loader; + Text::Reader nodeName; + bool isValid; + + // Maps type IDs -> compiled schemas for each dependency. + // Order is important because makeDependencyArray() compiles a sorted array. + kj::TreeMap dependencies; + + // Maps name -> index for each member. + // Order is important because makeMemberInfoArray() compiles a sorted array. + kj::TreeMap members; + + kj::ArrayPtr membersByDiscriminant; + +#define VALIDATE_SCHEMA(condition, ...) \ + KJ_REQUIRE(condition, ##__VA_ARGS__) { isValid = false; return; } +#define FAIL_VALIDATE_SCHEMA(...) \ + KJ_FAIL_REQUIRE(__VA_ARGS__) { isValid = false; return; } + + void validateMemberName(kj::StringPtr name, uint index) { + members.upsert(name, index, [&](auto&, auto&&) { + FAIL_VALIDATE_SCHEMA("duplicate name", name); + }); + } + + void validate(const schema::Node::Struct::Reader& structNode, uint64_t scopeId) { + uint dataSizeInBits = structNode.getDataWordCount() * 64; + uint pointerCount = structNode.getPointerCount(); + + auto fields = structNode.getFields(); + + KJ_STACK_ARRAY(bool, sawCodeOrder, fields.size(), 32, 256); + memset(sawCodeOrder.begin(), 0, sawCodeOrder.size() * sizeof(sawCodeOrder[0])); + + KJ_STACK_ARRAY(bool, sawDiscriminantValue, structNode.getDiscriminantCount(), 32, 256); + memset(sawDiscriminantValue.begin(), 0, + sawDiscriminantValue.size() * sizeof(sawDiscriminantValue[0])); + + if (structNode.getDiscriminantCount() > 0) { + VALIDATE_SCHEMA(structNode.getDiscriminantCount() != 1, + "union must have at least two members"); + VALIDATE_SCHEMA(structNode.getDiscriminantCount() <= fields.size(), + "struct can't have more union fields than total fields"); + + VALIDATE_SCHEMA((structNode.getDiscriminantOffset() + 1) * 16 <= dataSizeInBits, + "union discriminant is out-of-bounds"); + } + + membersByDiscriminant = loader.arena.allocateArray(fields.size()); + uint discriminantPos = 0; + uint nonDiscriminantPos = structNode.getDiscriminantCount(); + + uint index = 0; + uint nextOrdinal = 0; + for (auto field: fields) { + KJ_CONTEXT("validating struct field", field.getName()); + + validateMemberName(field.getName(), index); + VALIDATE_SCHEMA(field.getCodeOrder() < sawCodeOrder.size() && + !sawCodeOrder[field.getCodeOrder()], + "invalid codeOrder"); + sawCodeOrder[field.getCodeOrder()] = true; + + auto ordinal = field.getOrdinal(); + if (ordinal.isExplicit()) { + VALIDATE_SCHEMA(ordinal.getExplicit() >= nextOrdinal, + "fields were not ordered by ordinal"); + nextOrdinal = ordinal.getExplicit() + 1; + } + + if (hasDiscriminantValue(field)) { + VALIDATE_SCHEMA(field.getDiscriminantValue() < sawDiscriminantValue.size() && + !sawDiscriminantValue[field.getDiscriminantValue()], + "invalid discriminantValue"); + sawDiscriminantValue[field.getDiscriminantValue()] = true; + + membersByDiscriminant[discriminantPos++] = index; + } else { + VALIDATE_SCHEMA(nonDiscriminantPos <= fields.size(), + "discriminantCount did not match fields"); + membersByDiscriminant[nonDiscriminantPos++] = index; + } + + switch (field.which()) { + case schema::Field::SLOT: { + auto slot = field.getSlot(); + + uint fieldBits = 0; + bool fieldIsPointer = false; + validate(slot.getType(), slot.getDefaultValue(), &fieldBits, &fieldIsPointer); + VALIDATE_SCHEMA(fieldBits * (slot.getOffset() + 1) <= dataSizeInBits && + fieldIsPointer * (slot.getOffset() + 1) <= pointerCount, + "field offset out-of-bounds", + slot.getOffset(), dataSizeInBits, pointerCount); + + break; + } + + case schema::Field::GROUP: + // Require that the group is a struct node. + validateTypeId(field.getGroup().getTypeId(), schema::Node::STRUCT); + break; + } + + ++index; + } + + // If the above code is correct, these should pass. + KJ_ASSERT(discriminantPos == structNode.getDiscriminantCount()); + KJ_ASSERT(nonDiscriminantPos == fields.size()); + + if (structNode.getIsGroup()) { + VALIDATE_SCHEMA(scopeId != 0, "group node missing scopeId"); + + // Require that the group's scope has at least the same size as the group, so that anyone + // constructing an instance of the outer scope can safely read/write the group. + loader.requireStructSize(scopeId, structNode.getDataWordCount(), + structNode.getPointerCount()); + + // Require that the parent type is a struct. + validateTypeId(scopeId, schema::Node::STRUCT); + } + } + + void validate(const schema::Node::Enum::Reader& enumNode) { + auto enumerants = enumNode.getEnumerants(); + KJ_STACK_ARRAY(bool, sawCodeOrder, enumerants.size(), 32, 256); + memset(sawCodeOrder.begin(), 0, sawCodeOrder.size() * sizeof(sawCodeOrder[0])); + + uint index = 0; + for (auto enumerant: enumerants) { + validateMemberName(enumerant.getName(), index++); + + VALIDATE_SCHEMA(enumerant.getCodeOrder() < enumerants.size() && + !sawCodeOrder[enumerant.getCodeOrder()], + "invalid codeOrder", enumerant.getName()); + sawCodeOrder[enumerant.getCodeOrder()] = true; + } + } + + + + void validate(const schema::Node::Const::Reader& constNode) { + uint dummy1; + bool dummy2; + validate(constNode.getType(), constNode.getValue(), &dummy1, &dummy2); + } + + void validate(const schema::Node::Annotation::Reader& annotationNode) { + validate(annotationNode.getType()); + } + + void validate(const schema::Type::Reader& type, const schema::Value::Reader& value, + uint* dataSizeInBits, bool* isPointer) { + validate(type); + + schema::Value::Which expectedValueType = schema::Value::VOID; + bool hadCase = false; + switch (type.which()) { +#define HANDLE_TYPE(name, bits, ptr) \ + case schema::Type::name: \ + expectedValueType = schema::Value::name; \ + *dataSizeInBits = bits; *isPointer = ptr; \ + hadCase = true; \ + break; + HANDLE_TYPE(VOID, 0, false) + HANDLE_TYPE(BOOL, 1, false) + HANDLE_TYPE(INT8, 8, false) + HANDLE_TYPE(INT16, 16, false) + HANDLE_TYPE(INT32, 32, false) + HANDLE_TYPE(INT64, 64, false) + HANDLE_TYPE(UINT8, 8, false) + HANDLE_TYPE(UINT16, 16, false) + HANDLE_TYPE(UINT32, 32, false) + HANDLE_TYPE(UINT64, 64, false) + HANDLE_TYPE(FLOAT32, 32, false) + HANDLE_TYPE(FLOAT64, 64, false) + HANDLE_TYPE(TEXT, 0, true) + HANDLE_TYPE(DATA, 0, true) + HANDLE_TYPE(LIST, 0, true) + HANDLE_TYPE(ENUM, 16, false) + HANDLE_TYPE(STRUCT, 0, true) + HANDLE_TYPE(INTERFACE, 0, true) + HANDLE_TYPE(ANY_POINTER, 0, true) +#undef HANDLE_TYPE + } + + if (hadCase) { + VALIDATE_SCHEMA(value.which() == expectedValueType, "Value did not match type.", + (uint)value.which(), (uint)expectedValueType); + } + } + + void validate(const schema::Type::Reader& type) { + switch (type.which()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::TEXT: + case schema::Type::DATA: + case schema::Type::ANY_POINTER: + break; + + case schema::Type::STRUCT: { + auto structType = type.getStruct(); + validateTypeId(structType.getTypeId(), schema::Node::STRUCT); + validate(structType.getBrand()); + break; + } + case schema::Type::ENUM: { + auto enumType = type.getEnum(); + validateTypeId(enumType.getTypeId(), schema::Node::ENUM); + validate(enumType.getBrand()); + break; + } + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interfaces are not supported."); + + case schema::Type::LIST: + validate(type.getList().getElementType()); + break; + } + + // We intentionally allow unknown types. + } + + void validate(const schema::Brand::Reader& brand) { + for (auto scope: brand.getScopes()) { + switch (scope.which()) { + case schema::Brand::Scope::BIND: + for (auto binding: scope.getBind()) { + switch (binding.which()) { + case schema::Brand::Binding::UNBOUND: + break; + case schema::Brand::Binding::TYPE: { + auto type = binding.getType(); + validate(type); + bool isPointer = true; + switch (type.which()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::ENUM: + isPointer = false; + break; + + case schema::Type::TEXT: + case schema::Type::DATA: + case schema::Type::ANY_POINTER: + case schema::Type::STRUCT: + case schema::Type::INTERFACE: + case schema::Type::LIST: + isPointer = true; + break; + } + VALIDATE_SCHEMA(isPointer, + "generic type parameter must be a pointer type", type); + + break; + } + } + } + break; + case schema::Brand::Scope::INHERIT: + break; + } + } + } + + void validateTypeId(uint64_t id, schema::Node::Which expectedKind) { + _::RawSchema* existing = loader.tryGet(id).schema; + if (existing != nullptr) { + auto node = readMessageUnchecked(existing->encodedNode); + VALIDATE_SCHEMA(node.which() == expectedKind, + "expected a different kind of node for this ID", + id, (uint)expectedKind, (uint)node.which(), node.getDisplayName()); + dependencies.upsert(id, existing, [](auto&,auto&&) { /* ignore dupe */ }); + return; + } + + dependencies.upsert(id, loader.loadEmpty( + id, kj::str("(unknown type used by ", nodeName , ")"), expectedKind, true), + [](auto&,auto&&) { /* ignore dupe */ }); + } + +#undef VALIDATE_SCHEMA +#undef FAIL_VALIDATE_SCHEMA +}; + +// ======================================================================================= + +class SchemaLoader::CompatibilityChecker { +public: + CompatibilityChecker(SchemaLoader::Impl& loader): loader(loader) {} + + bool shouldReplace(const schema::Node::Reader& existingNode, + const schema::Node::Reader& replacement, + bool preferReplacementIfEquivalent) { + this->existingNode = existingNode; + this->replacementNode = replacement; + + KJ_CONTEXT("checking compatibility with previously-loaded node of the same id", + existingNode.getDisplayName()); + + KJ_DREQUIRE(existingNode.getId() == replacement.getId()); + + nodeName = existingNode.getDisplayName(); + compatibility = EQUIVALENT; + + checkCompatibility(existingNode, replacement); + + // Prefer the newer schema. + return preferReplacementIfEquivalent ? compatibility != OLDER : compatibility == NEWER; + } + +private: + SchemaLoader::Impl& loader; + Text::Reader nodeName; + schema::Node::Reader existingNode; + schema::Node::Reader replacementNode; + + enum Compatibility { + EQUIVALENT, + OLDER, + NEWER, + INCOMPATIBLE + }; + Compatibility compatibility; + +#define VALIDATE_SCHEMA(condition, ...) \ + KJ_REQUIRE(condition, ##__VA_ARGS__) { compatibility = INCOMPATIBLE; return; } +#define FAIL_VALIDATE_SCHEMA(...) \ + KJ_FAIL_REQUIRE(__VA_ARGS__) { compatibility = INCOMPATIBLE; return; } + + void replacementIsNewer() { + switch (compatibility) { + case EQUIVALENT: + compatibility = NEWER; + break; + case OLDER: + FAIL_VALIDATE_SCHEMA("Schema node contains some changes that are upgrades and some " + "that are downgrades. All changes must be in the same direction for compatibility."); + break; + case NEWER: + break; + case INCOMPATIBLE: + break; + } + } + + void replacementIsOlder() { + switch (compatibility) { + case EQUIVALENT: + compatibility = OLDER; + break; + case OLDER: + break; + case NEWER: + FAIL_VALIDATE_SCHEMA("Schema node contains some changes that are upgrades and some " + "that are downgrades. All changes must be in the same direction for compatibility."); + break; + case INCOMPATIBLE: + break; + } + } + + void checkCompatibility(const schema::Node::Reader& node, + const schema::Node::Reader& replacement) { + // Returns whether `replacement` is equivalent, older than, newer than, or incompatible with + // `node`. If exceptions are enabled, this will throw an exception on INCOMPATIBLE. + + VALIDATE_SCHEMA(node.which() == replacement.which(), + "kind of declaration changed"); + + // No need to check compatibility of most of the non-body parts of the node: + // - Arbitrary renaming and moving between scopes is allowed. + // - Annotations are ignored for compatibility purposes. + + if (replacement.getParameters().size() > node.getParameters().size()) { + replacementIsNewer(); + } else if (replacement.getParameters().size() < node.getParameters().size()) { + replacementIsOlder(); + } + + switch (node.which()) { + case schema::Node::FILE: + verifyVoid(node.getFile()); + break; + case schema::Node::STRUCT: + checkCompatibility(node.getStruct(), replacement.getStruct(), + node.getScopeId(), replacement.getScopeId()); + break; + case schema::Node::ENUM: + checkCompatibility(node.getEnum(), replacement.getEnum()); + break; + case schema::Node::INTERFACE: + KJ_FAIL_REQUIRE("Interfaces are not supported."); + case schema::Node::CONST: + checkCompatibility(node.getConst(), replacement.getConst()); + break; + case schema::Node::ANNOTATION: + checkCompatibility(node.getAnnotation(), replacement.getAnnotation()); + break; + } + } + + void checkCompatibility(const schema::Node::Struct::Reader& structNode, + const schema::Node::Struct::Reader& replacement, + uint64_t scopeId, uint64_t replacementScopeId) { + if (replacement.getDataWordCount() > structNode.getDataWordCount()) { + replacementIsNewer(); + } else if (replacement.getDataWordCount() < structNode.getDataWordCount()) { + replacementIsOlder(); + } + if (replacement.getPointerCount() > structNode.getPointerCount()) { + replacementIsNewer(); + } else if (replacement.getPointerCount() < structNode.getPointerCount()) { + replacementIsOlder(); + } + if (replacement.getDiscriminantCount() > structNode.getDiscriminantCount()) { + replacementIsNewer(); + } else if (replacement.getDiscriminantCount() < structNode.getDiscriminantCount()) { + replacementIsOlder(); + } + + if (replacement.getDiscriminantCount() > 0 && structNode.getDiscriminantCount() > 0) { + VALIDATE_SCHEMA(replacement.getDiscriminantOffset() == structNode.getDiscriminantOffset(), + "union discriminant position changed"); + } + + // The shared members should occupy corresponding positions in the member lists, since the + // lists are sorted by ordinal. + auto fields = structNode.getFields(); + auto replacementFields = replacement.getFields(); + uint count = std::min(fields.size(), replacementFields.size()); + + if (replacementFields.size() > fields.size()) { + replacementIsNewer(); + } else if (replacementFields.size() < fields.size()) { + replacementIsOlder(); + } + + for (uint i = 0; i < count; i++) { + checkCompatibility(fields[i], replacementFields[i]); + } + + // For the moment, we allow "upgrading" from non-group to group, mainly so that the + // placeholders we generate for group parents (which in the absence of more info, we assume to + // be non-groups) can be replaced with groups. + // + // TODO(cleanup): The placeholder approach is really breaking down. Maybe we need to maintain + // a list of expectations for nodes we haven't loaded yet. + if (structNode.getIsGroup()) { + if (replacement.getIsGroup()) { + VALIDATE_SCHEMA(replacementScopeId == scopeId, "group node's scope changed"); + } else { + replacementIsOlder(); + } + } else { + if (replacement.getIsGroup()) { + replacementIsNewer(); + } + } + } + + void checkCompatibility(const schema::Field::Reader& field, + const schema::Field::Reader& replacement) { + KJ_CONTEXT("comparing struct field", field.getName()); + + // A field that is initially not in a union can be upgraded to be in one, as long as it has + // discriminant 0. + uint discriminant = hasDiscriminantValue(field) ? field.getDiscriminantValue() : 0; + uint replacementDiscriminant = + hasDiscriminantValue(replacement) ? replacement.getDiscriminantValue() : 0; + VALIDATE_SCHEMA(discriminant == replacementDiscriminant, "Field discriminant changed."); + + switch (field.which()) { + case schema::Field::SLOT: { + auto slot = field.getSlot(); + + switch (replacement.which()) { + case schema::Field::SLOT: { + auto replacementSlot = replacement.getSlot(); + + checkCompatibility(slot.getType(), replacementSlot.getType(), + NO_UPGRADE_TO_STRUCT); + checkDefaultCompatibility(slot.getDefaultValue(), + replacementSlot.getDefaultValue()); + + VALIDATE_SCHEMA(slot.getOffset() == replacementSlot.getOffset(), + "field position changed"); + break; + } + case schema::Field::GROUP: + checkUpgradeToStruct(slot.getType(), replacement.getGroup().getTypeId(), + existingNode, field); + break; + } + + break; + } + + case schema::Field::GROUP: + switch (replacement.which()) { + case schema::Field::SLOT: + checkUpgradeToStruct(replacement.getSlot().getType(), field.getGroup().getTypeId(), + replacementNode, replacement); + break; + case schema::Field::GROUP: + VALIDATE_SCHEMA(field.getGroup().getTypeId() == replacement.getGroup().getTypeId(), + "group id changed"); + break; + } + break; + } + } + + void checkCompatibility(const schema::Node::Enum::Reader& enumNode, + const schema::Node::Enum::Reader& replacement) { + uint size = enumNode.getEnumerants().size(); + uint replacementSize = replacement.getEnumerants().size(); + if (replacementSize > size) { + replacementIsNewer(); + } else if (replacementSize < size) { + replacementIsOlder(); + } + } + + + + + + void checkCompatibility(const schema::Node::Const::Reader& constNode, + const schema::Node::Const::Reader& replacement) { + // Who cares? These don't appear on the wire. + } + + void checkCompatibility(const schema::Node::Annotation::Reader& annotationNode, + const schema::Node::Annotation::Reader& replacement) { + // Who cares? These don't appear on the wire. + } + + enum UpgradeToStructMode { + ALLOW_UPGRADE_TO_STRUCT, + NO_UPGRADE_TO_STRUCT + }; + + void checkCompatibility(const schema::Type::Reader& type, + const schema::Type::Reader& replacement, + UpgradeToStructMode upgradeToStructMode) { + if (replacement.which() != type.which()) { + // Check for allowed "upgrade" to Data or AnyPointer. + if (replacement.isData() && canUpgradeToData(type)) { + replacementIsNewer(); + return; + } else if (type.isData() && canUpgradeToData(replacement)) { + replacementIsOlder(); + return; + } else if (replacement.isAnyPointer() && canUpgradeToAnyPointer(type)) { + replacementIsNewer(); + return; + } else if (type.isAnyPointer() && canUpgradeToAnyPointer(replacement)) { + replacementIsOlder(); + return; + } + + if (upgradeToStructMode == ALLOW_UPGRADE_TO_STRUCT) { + if (type.isStruct()) { + checkUpgradeToStruct(replacement, type.getStruct().getTypeId()); + return; + } else if (replacement.isStruct()) { + checkUpgradeToStruct(type, replacement.getStruct().getTypeId()); + return; + } + } + + FAIL_VALIDATE_SCHEMA("a type was changed"); + } + + switch (type.which()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::TEXT: + case schema::Type::DATA: + case schema::Type::ANY_POINTER: + return; + + case schema::Type::LIST: + checkCompatibility(type.getList().getElementType(), replacement.getList().getElementType(), + ALLOW_UPGRADE_TO_STRUCT); + return; + + case schema::Type::ENUM: + VALIDATE_SCHEMA(replacement.getEnum().getTypeId() == type.getEnum().getTypeId(), + "type changed enum type"); + return; + + case schema::Type::STRUCT: + // TODO(someday): If the IDs don't match, we should compare the two structs for + // compatibility. This is tricky, though, because the new type's target may not yet be + // loaded. In that case we could take the old type, make a copy of it, assign the new + // ID to the copy, and load() that. That forces any struct type loaded for that ID to + // be compatible. However, that has another problem, which is that it could be that the + // whole reason the type was replaced was to fork that type, and so an incompatibility + // could be very much expected. This could be a rat hole... + VALIDATE_SCHEMA(replacement.getStruct().getTypeId() == type.getStruct().getTypeId(), + "type changed to incompatible struct type"); + return; + + case schema::Type::INTERFACE: + VALIDATE_SCHEMA(replacement.getInterface().getTypeId() == type.getInterface().getTypeId(), + "type changed to incompatible interface type"); + return; + } + + // We assume unknown types (from newer versions of Cap'n Proto?) are equivalent. + } + + void checkUpgradeToStruct(const schema::Type::Reader& type, uint64_t structTypeId, + kj::Maybe matchSize = nullptr, + kj::Maybe matchPosition = nullptr) { + // We can't just look up the target struct and check it because it may not have been loaded + // yet. Instead, we contrive a struct that looks like what we want and load() that, which + // guarantees that any incompatibility will be caught either now or when the real version of + // that struct is loaded. + + word scratch[32]; + memset(scratch, 0, sizeof(scratch)); + MallocMessageBuilder builder(scratch); + auto node = builder.initRoot(); + node.setId(structTypeId); + node.setDisplayName(kj::str("(unknown type used in ", nodeName, ")")); + auto structNode = node.initStruct(); + + switch (type.which()) { + case schema::Type::VOID: + structNode.setDataWordCount(0); + structNode.setPointerCount(0); + break; + + case schema::Type::BOOL: + structNode.setDataWordCount(1); + structNode.setPointerCount(0); + break; + + case schema::Type::INT8: + case schema::Type::UINT8: + structNode.setDataWordCount(1); + structNode.setPointerCount(0); + break; + + case schema::Type::INT16: + case schema::Type::UINT16: + case schema::Type::ENUM: + structNode.setDataWordCount(1); + structNode.setPointerCount(0); + break; + + case schema::Type::INT32: + case schema::Type::UINT32: + case schema::Type::FLOAT32: + structNode.setDataWordCount(1); + structNode.setPointerCount(0); + break; + + case schema::Type::INT64: + case schema::Type::UINT64: + case schema::Type::FLOAT64: + structNode.setDataWordCount(1); + structNode.setPointerCount(0); + break; + + case schema::Type::TEXT: + case schema::Type::DATA: + case schema::Type::LIST: + case schema::Type::STRUCT: + case schema::Type::INTERFACE: + case schema::Type::ANY_POINTER: + structNode.setDataWordCount(0); + structNode.setPointerCount(1); + break; + } + + KJ_IF_MAYBE(s, matchSize) { + auto match = s->getStruct(); + structNode.setDataWordCount(match.getDataWordCount()); + structNode.setPointerCount(match.getPointerCount()); + } + + auto field = structNode.initFields(1)[0]; + field.setName("member0"); + field.setCodeOrder(0); + auto slot = field.initSlot(); + slot.setType(type); + + KJ_IF_MAYBE(p, matchPosition) { + if (p->getOrdinal().isExplicit()) { + field.getOrdinal().setExplicit(p->getOrdinal().getExplicit()); + } else { + field.getOrdinal().setImplicit(); + } + auto matchSlot = p->getSlot(); + slot.setOffset(matchSlot.getOffset()); + slot.setDefaultValue(matchSlot.getDefaultValue()); + } else { + field.getOrdinal().setExplicit(0); + slot.setOffset(0); + + schema::Value::Builder value = slot.initDefaultValue(); + switch (type.which()) { + case schema::Type::VOID: value.setVoid(); break; + case schema::Type::BOOL: value.setBool(false); break; + case schema::Type::INT8: value.setInt8(0); break; + case schema::Type::INT16: value.setInt16(0); break; + case schema::Type::INT32: value.setInt32(0); break; + case schema::Type::INT64: value.setInt64(0); break; + case schema::Type::UINT8: value.setUint8(0); break; + case schema::Type::UINT16: value.setUint16(0); break; + case schema::Type::UINT32: value.setUint32(0); break; + case schema::Type::UINT64: value.setUint64(0); break; + case schema::Type::FLOAT32: value.setFloat32(0); break; + case schema::Type::FLOAT64: value.setFloat64(0); break; + case schema::Type::ENUM: value.setEnum(0); break; + case schema::Type::TEXT: value.adoptText(Orphan()); break; + case schema::Type::DATA: value.adoptData(Orphan()); break; + case schema::Type::LIST: value.initList(); break; + case schema::Type::STRUCT: value.initStruct(); break; + case schema::Type::INTERFACE: value.setInterface(); break; + case schema::Type::ANY_POINTER: value.initAnyPointer(); break; + } + } + + loader.load(node, true); + } + + bool canUpgradeToData(const schema::Type::Reader& type) { + if (type.isText()) { + return true; + } else if (type.isList()) { + switch (type.getList().getElementType().which()) { + case schema::Type::INT8: + case schema::Type::UINT8: + return true; + default: + return false; + } + } else { + return false; + } + } + + bool canUpgradeToAnyPointer(const schema::Type::Reader& type) { + switch (type.which()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::ENUM: + return false; + + case schema::Type::TEXT: + case schema::Type::DATA: + case schema::Type::LIST: + case schema::Type::STRUCT: + case schema::Type::INTERFACE: + case schema::Type::ANY_POINTER: + return true; + } + + // Be lenient with unknown types. + return true; + } + + void checkDefaultCompatibility(const schema::Value::Reader& value, + const schema::Value::Reader& replacement) { + // Note that we test default compatibility only after testing type compatibility, and default + // values have already been validated as matching their types, so this should pass. + KJ_ASSERT(value.which() == replacement.which()) { + compatibility = INCOMPATIBLE; + return; + } + + switch (value.which()) { +#define HANDLE_TYPE(discrim, name) \ + case schema::Value::discrim: \ + VALIDATE_SCHEMA(value.get##name() == replacement.get##name(), "default value changed"); \ + break; + HANDLE_TYPE(VOID, Void); + HANDLE_TYPE(BOOL, Bool); + HANDLE_TYPE(INT8, Int8); + HANDLE_TYPE(INT16, Int16); + HANDLE_TYPE(INT32, Int32); + HANDLE_TYPE(INT64, Int64); + HANDLE_TYPE(UINT8, Uint8); + HANDLE_TYPE(UINT16, Uint16); + HANDLE_TYPE(UINT32, Uint32); + HANDLE_TYPE(UINT64, Uint64); + HANDLE_TYPE(FLOAT32, Float32); + HANDLE_TYPE(FLOAT64, Float64); + HANDLE_TYPE(ENUM, Enum); +#undef HANDLE_TYPE + + case schema::Value::TEXT: + case schema::Value::DATA: + case schema::Value::LIST: + case schema::Value::STRUCT: + case schema::Value::INTERFACE: + case schema::Value::ANY_POINTER: + // It's not a big deal if default values for pointers change, and it would be difficult for + // us to compare these defaults here, so just let it slide. + break; + } + } +}; + +// ======================================================================================= + +_::RawSchema* SchemaLoader::Impl::load(const schema::Node::Reader& reader, bool isPlaceholder) { + // Make a copy of the node which can be used unchecked. + kj::ArrayPtr validated = makeUncheckedNodeEnforcingSizeRequirements(reader); + + // Validate the copy. + Validator validator(*this); + auto validatedReader = readMessageUnchecked(validated.begin()); + + if (!validator.validate(validatedReader)) { + // Not valid. Construct an empty schema of the same type and return that. + return loadEmpty(validatedReader.getId(), + validatedReader.getDisplayName(), + validatedReader.which(), + false); + } + + // Check if we already have a schema for this ID. + _::RawSchema* schema; + bool shouldReplace; + bool shouldClearInitializer; + KJ_IF_MAYBE(match, schemas.find(validatedReader.getId())) { + // Yes, check if it is compatible and figure out which schema is newer. + + schema = *match; + + // If the existing schema is a placeholder, but we're upgrading it to a non-placeholder, we + // need to clear the initializer later. + shouldClearInitializer = schema->lazyInitializer != nullptr && !isPlaceholder; + + auto existing = readMessageUnchecked(schema->encodedNode); + CompatibilityChecker checker(*this); + + // Prefer to replace the existing schema if the existing schema is a placeholder. Otherwise, + // prefer to keep the existing schema. + shouldReplace = checker.shouldReplace( + existing, validatedReader, schema->lazyInitializer != nullptr); + } else { + // Nope, allocate a new RawSchema. + schema = &arena.allocate<_::RawSchema>(); + memset(&schema->defaultBrand, 0, sizeof(schema->defaultBrand)); + schema->id = validatedReader.getId(); + schema->canCastTo = nullptr; + schema->defaultBrand.generic = schema; + schema->lazyInitializer = isPlaceholder ? &initializer : nullptr; + schema->defaultBrand.lazyInitializer = isPlaceholder ? &brandedInitializer : nullptr; + shouldReplace = true; + shouldClearInitializer = false; + schemas.insert(validatedReader.getId(), schema); + } + + if (shouldReplace) { + // Initialize the RawSchema. + schema->encodedNode = validated.begin(); + schema->encodedSize = validated.size(); + schema->dependencies = validator.makeDependencyArray(&schema->dependencyCount); + schema->membersByName = validator.makeMemberInfoArray(&schema->memberCount); + schema->membersByDiscriminant = validator.makeMembersByDiscriminantArray(); + + // Even though this schema isn't itself branded, it may have dependencies that are. So, we + // need to set up the "dependencies" map under defaultBrand. + auto deps = makeBrandedDependencies(schema, kj::ArrayPtr()); + schema->defaultBrand.dependencies = deps.begin(); + schema->defaultBrand.dependencyCount = deps.size(); + } + + if (shouldClearInitializer) { + // If this schema is not newly-allocated, it may already be in the wild, specifically in the + // dependency list of other schemas. Once the initializer is null, it is live, so we must do + // a release-store here. +#if __GNUC__ || defined(__clang__) + __atomic_store_n(&schema->lazyInitializer, nullptr, __ATOMIC_RELEASE); + __atomic_store_n(&schema->defaultBrand.lazyInitializer, nullptr, __ATOMIC_RELEASE); +#else +#error "Platform not supported" +#endif + } + + return schema; +} + +_::RawSchema* SchemaLoader::Impl::loadNative(const _::RawSchema* nativeSchema) { + _::RawSchema* schema; + bool shouldReplace; + bool shouldClearInitializer; + KJ_IF_MAYBE(match, schemas.find(nativeSchema->id)) { + schema = *match; + if (schema->canCastTo != nullptr) { + // Already loaded natively, or we're currently in the process of loading natively and there + // was a dependency cycle. + KJ_REQUIRE(schema->canCastTo == nativeSchema, + "two different compiled-in type have the same type ID", + nativeSchema->id, + readMessageUnchecked(nativeSchema->encodedNode).getDisplayName(), + readMessageUnchecked(schema->canCastTo->encodedNode).getDisplayName()); + return schema; + } else { + auto existing = readMessageUnchecked(schema->encodedNode); + auto native = readMessageUnchecked(nativeSchema->encodedNode); + CompatibilityChecker checker(*this); + shouldReplace = checker.shouldReplace(existing, native, true); + shouldClearInitializer = schema->lazyInitializer != nullptr; + } + } else { + schema = &arena.allocate<_::RawSchema>(); + memset(&schema->defaultBrand, 0, sizeof(schema->defaultBrand)); + schema->defaultBrand.generic = schema; + schema->lazyInitializer = nullptr; + schema->defaultBrand.lazyInitializer = nullptr; + shouldReplace = true; + shouldClearInitializer = false; // already cleared above + schemas.insert(nativeSchema->id, schema); + } + + if (shouldReplace) { + // Set the schema to a copy of the native schema, but make sure not to null out lazyInitializer + // yet. + _::RawSchema temp = *nativeSchema; + temp.lazyInitializer = schema->lazyInitializer; + *schema = temp; + + schema->defaultBrand.generic = schema; + + // Indicate that casting is safe. Note that it's important to set this before recursively + // loading dependencies, so that cycles don't cause infinite loops! + schema->canCastTo = nativeSchema; + + // We need to set the dependency list to point at other loader-owned RawSchemas. + kj::ArrayPtr dependencies = + arena.allocateArray(schema->dependencyCount); + for (uint i = 0; i < nativeSchema->dependencyCount; i++) { + dependencies[i] = loadNative(nativeSchema->dependencies[i]); + } + schema->dependencies = dependencies.begin(); + + // Also need to re-do the branded dependencies. + auto deps = makeBrandedDependencies(schema, kj::ArrayPtr()); + schema->defaultBrand.dependencies = deps.begin(); + schema->defaultBrand.dependencyCount = deps.size(); + + // If there is a struct size requirement, we need to make sure that it is satisfied. + KJ_IF_MAYBE(sizeReq, structSizeRequirements.find(nativeSchema->id)) { + applyStructSizeRequirement(schema, sizeReq->dataWordCount, + sizeReq->pointerCount); + } + } else { + // The existing schema is newer. + + // Indicate that casting is safe. Note that it's important to set this before recursively + // loading dependencies, so that cycles don't cause infinite loops! + schema->canCastTo = nativeSchema; + + // Make sure the dependencies are loaded and compatible. + for (uint i = 0; i < nativeSchema->dependencyCount; i++) { + loadNative(nativeSchema->dependencies[i]); + } + } + + if (shouldClearInitializer) { + // If this schema is not newly-allocated, it may already be in the wild, specifically in the + // dependency list of other schemas. Once the initializer is null, it is live, so we must do + // a release-store here. +#if __GNUC__ || defined(__clang__) + __atomic_store_n(&schema->lazyInitializer, nullptr, __ATOMIC_RELEASE); + __atomic_store_n(&schema->defaultBrand.lazyInitializer, nullptr, __ATOMIC_RELEASE); +#else +#error "Platform not supported" +#endif + } + + return schema; +} + +_::RawSchema* SchemaLoader::Impl::loadEmpty( + uint64_t id, kj::StringPtr name, schema::Node::Which kind, bool isPlaceholder) { + word scratch[32]; + memset(scratch, 0, sizeof(scratch)); + MallocMessageBuilder builder(scratch); + auto node = builder.initRoot(); + node.setId(id); + node.setDisplayName(name); + switch (kind) { + case schema::Node::STRUCT: node.initStruct(); break; + case schema::Node::ENUM: node.initEnum(); break; + case schema::Node::INTERFACE: KJ_FAIL_REQUIRE("Interfaces are not supported."); + + case schema::Node::FILE: + case schema::Node::CONST: + case schema::Node::ANNOTATION: + KJ_FAIL_REQUIRE("Not a type."); + break; + } + + return load(node, isPlaceholder); +} + +const _::RawBrandedSchema* SchemaLoader::Impl::makeBranded( + const _::RawSchema* schema, schema::Brand::Reader proto, + kj::Maybe> clientBrand) { + kj::StringPtr scopeName = + readMessageUnchecked(schema->encodedNode).getDisplayName(); + + auto srcScopes = proto.getScopes(); + + KJ_STACK_ARRAY(_::RawBrandedSchema::Scope, dstScopes, srcScopes.size(), 16, 32); + memset(dstScopes.begin(), 0, dstScopes.size() * sizeof(dstScopes[0])); + + uint dstScopeCount = 0; + for (auto srcScope: srcScopes) { + switch (srcScope.which()) { + case schema::Brand::Scope::BIND: { + auto srcBindings = srcScope.getBind(); + KJ_STACK_ARRAY(_::RawBrandedSchema::Binding, dstBindings, srcBindings.size(), 16, 32); + memset(dstBindings.begin(), 0, dstBindings.size() * sizeof(dstBindings[0])); + + for (auto j: kj::indices(srcBindings)) { + auto srcBinding = srcBindings[j]; + auto& dstBinding = dstBindings[j]; + + memset(&dstBinding, 0, sizeof(dstBinding)); + dstBinding.which = schema::Type::ANY_POINTER; + + switch (srcBinding.which()) { + case schema::Brand::Binding::UNBOUND: + break; + case schema::Brand::Binding::TYPE: { + makeDep(dstBinding, srcBinding.getType(), scopeName, clientBrand); + break; + } + } + } + + auto& dstScope = dstScopes[dstScopeCount++]; + dstScope.typeId = srcScope.getScopeId(); + dstScope.bindingCount = dstBindings.size(); + dstScope.bindings = copyDeduped(dstBindings).begin(); + break; + } + case schema::Brand::Scope::INHERIT: { + // Inherit the whole scope from the client -- or if the client doesn't have it, at least + // include an empty dstScope in the list just to show that this scope was specified as + // inherited, as opposed to being unspecified (which would be treated as all AnyPointer). + auto& dstScope = dstScopes[dstScopeCount++]; + dstScope.typeId = srcScope.getScopeId(); + + KJ_IF_MAYBE(b, clientBrand) { + for (auto& clientScope: *b) { + if (clientScope.typeId == dstScope.typeId) { + // Overwrite the whole thing. + dstScope = clientScope; + break; + } + } + } else { + dstScope.isUnbound = true; + } + break; + } + } + } + + dstScopes = dstScopes.slice(0, dstScopeCount); + + std::sort(dstScopes.begin(), dstScopes.end(), + [](const _::RawBrandedSchema::Scope& a, const _::RawBrandedSchema::Scope& b) { + return a.typeId < b.typeId; + }); + + return makeBranded(schema, copyDeduped(dstScopes)); +} + +const _::RawBrandedSchema* SchemaLoader::Impl::makeBranded( + const _::RawSchema* schema, kj::ArrayPtr bindings) { + if (bindings.size() == 0) { + // `defaultBrand` is the version where all type parameters are bound to `AnyPointer`. + return &schema->defaultBrand; + } + + SchemaBindingsPair key { schema, bindings.begin() }; + KJ_IF_MAYBE(existing, brands.find(key)) { + return *existing; + } else { + auto& brand = arena.allocate<_::RawBrandedSchema>(); + memset(&brand, 0, sizeof(brand)); + brands.insert(key, &brand); + + brand.generic = schema; + brand.scopes = bindings.begin(); + brand.scopeCount = bindings.size(); + brand.lazyInitializer = &brandedInitializer; + return &brand; + } +} + +kj::ArrayPtr +SchemaLoader::Impl::makeBrandedDependencies( + const _::RawSchema* schema, + kj::Maybe> bindings) { + kj::StringPtr scopeName = + readMessageUnchecked(schema->encodedNode).getDisplayName(); + + kj::Vector<_::RawBrandedSchema::Dependency> deps; + + schema::Node::Reader node = readMessageUnchecked(schema->encodedNode); + +#define ADD_ENTRY(kind, index, make) \ + if (const _::RawBrandedSchema* dep = make) { \ + auto& slot = deps.add(); \ + memset(&slot, 0, sizeof(slot)); \ + slot.location = _::RawBrandedSchema::makeDepLocation( \ + _::RawBrandedSchema::DepKind::kind, index); \ + slot.schema = dep; \ + } + + switch (node.which()) { + case schema::Node::FILE: + case schema::Node::ENUM: + case schema::Node::ANNOTATION: + break; + + case schema::Node::CONST: + ADD_ENTRY(CONST_TYPE, 0, makeDepSchema( + node.getConst().getType(), scopeName, bindings)); + break; + + case schema::Node::STRUCT: { + auto fields = node.getStruct().getFields(); + for (auto i: kj::indices(fields)) { + auto field = fields[i]; + switch (field.which()) { + case schema::Field::SLOT: + ADD_ENTRY(FIELD, i, makeDepSchema( + field.getSlot().getType(), scopeName, bindings)) + break; + case schema::Field::GROUP: { + const _::RawSchema* group = loadEmpty( + field.getGroup().getTypeId(), + "(unknown group type)", schema::Node::STRUCT, true); + KJ_IF_MAYBE(b, bindings) { + ADD_ENTRY(FIELD, i, makeBranded(group, *b)); + } else { + ADD_ENTRY(FIELD, i, getUnbound(group)); + } + break; + } + } + } + break; + } + + case schema::Node::INTERFACE: + KJ_FAIL_REQUIRE("Interfaces are not supported."); + } + +#undef ADD_ENTRY + + std::sort(deps.begin(), deps.end(), + [](const _::RawBrandedSchema::Dependency& a, const _::RawBrandedSchema::Dependency& b) { + return a.location < b.location; + }); + + return copyDeduped(deps.asPtr()); +} + +void SchemaLoader::Impl::makeDep(_::RawBrandedSchema::Binding& result, + schema::Type::Reader type, kj::StringPtr scopeName, + kj::Maybe> brandBindings) { + switch (type.which()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::TEXT: + case schema::Type::DATA: + result.which = static_cast(type.which()); + return; + + case schema::Type::STRUCT: { + auto structType = type.getStruct(); + makeDep(result, structType.getTypeId(), schema::Type::STRUCT, schema::Node::STRUCT, + structType.getBrand(), scopeName, brandBindings); + return; + } + case schema::Type::ENUM: { + auto enumType = type.getEnum(); + makeDep(result, enumType.getTypeId(), schema::Type::ENUM, schema::Node::ENUM, + enumType.getBrand(), scopeName, brandBindings); + return; + } + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interfaces are not supported."); + + case schema::Type::LIST: { + makeDep(result, type.getList().getElementType(), scopeName, brandBindings); + ++result.listDepth; + return; + } + + case schema::Type::ANY_POINTER: { + result.which = static_cast(schema::Type::ANY_POINTER); + auto anyPointer = type.getAnyPointer(); + switch (anyPointer.which()) { + case schema::Type::AnyPointer::UNCONSTRAINED: + return; + case schema::Type::AnyPointer::PARAMETER: { + auto param = anyPointer.getParameter(); + uint64_t id = param.getScopeId(); + uint16_t index = param.getParameterIndex(); + + KJ_IF_MAYBE(b, brandBindings) { + // TODO(perf): We could binary search here, but... bleh. + for (auto& scope: *b) { + if (scope.typeId == id) { + if (scope.isUnbound) { + // Unbound brand parameter. + result.scopeId = id; + result.paramIndex = index; + return; + } else if (index >= scope.bindingCount) { + // Binding index out-of-range. Treat as AnyPointer. This is important to allow + // new type parameters to be added to existing types without breaking dependent + // schemas. + return; + } else { + result = scope.bindings[index]; + return; + } + } + } + return; + } else { + // Unbound brand parameter. + result.scopeId = id; + result.paramIndex = index; + return; + } + } + case schema::Type::AnyPointer::IMPLICIT_METHOD_PARAMETER: + result.isImplicitParameter = true; + result.paramIndex = anyPointer.getImplicitMethodParameter().getParameterIndex(); + return; + } + KJ_UNREACHABLE; + } + } + + KJ_UNREACHABLE; +} + +void SchemaLoader::Impl::makeDep(_::RawBrandedSchema::Binding& result, + uint64_t typeId, schema::Type::Which whichType, schema::Node::Which expectedKind, + schema::Brand::Reader brand, kj::StringPtr scopeName, + kj::Maybe> brandBindings) { + const _::RawSchema* schema = loadEmpty(typeId, + kj::str("(unknown type; seen as dependency of ", scopeName, ")"), + expectedKind, true); + result.which = static_cast(whichType); + result.schema = makeBranded(schema, brand, brandBindings); +} + +const _::RawBrandedSchema* SchemaLoader::Impl::makeDepSchema( + schema::Type::Reader type, kj::StringPtr scopeName, + kj::Maybe> brandBindings) { + _::RawBrandedSchema::Binding binding; + memset(&binding, 0, sizeof(binding)); + makeDep(binding, type, scopeName, brandBindings); + return binding.schema; +} + +template +kj::ArrayPtr SchemaLoader::Impl::copyDeduped(kj::ArrayPtr values) { + if (values.size() == 0) { + return kj::arrayPtr(kj::implicitCast(nullptr), 0); + } + + auto bytes = values.asBytes(); + + KJ_IF_MAYBE(dupe, dedupTable.find(bytes)) { + return kj::arrayPtr(reinterpret_cast(dupe->begin()), values.size()); + } + + // Need to make a new copy. + auto copy = arena.allocateArray(values.size()); + memcpy(copy.begin(), values.begin(), values.size() * sizeof(T)); + + dedupTable.insert(copy.asBytes()); + + return copy; +} + +template +kj::ArrayPtr SchemaLoader::Impl::copyDeduped(kj::ArrayPtr values) { + return copyDeduped(kj::ArrayPtr(values)); +} + +SchemaLoader::Impl::TryGetResult SchemaLoader::Impl::tryGet(uint64_t typeId) const { + KJ_IF_MAYBE(schema, schemas.find(typeId)) { + return {*schema, initializer.getCallback()}; + } else { + return {nullptr, initializer.getCallback()}; + } +} + +const _::RawBrandedSchema* SchemaLoader::Impl::getUnbound(const _::RawSchema* schema) { + if (!readMessageUnchecked(schema->encodedNode).getIsGeneric()) { + // Not a generic type, so just return the default brand. + return &schema->defaultBrand; + } + + KJ_IF_MAYBE(existing, unboundBrands.find(schema)) { + return *existing; + } else { + auto slot = &arena.allocate<_::RawBrandedSchema>(); + memset(slot, 0, sizeof(*slot)); + slot->generic = schema; + auto deps = makeBrandedDependencies(schema, nullptr); + slot->dependencies = deps.begin(); + slot->dependencyCount = deps.size(); + unboundBrands.insert(schema, slot); + return slot; + } +} + +kj::Array SchemaLoader::Impl::getAllLoaded() const { + size_t count = 0; + for (auto& schema: schemas) { + if (schema.value->lazyInitializer == nullptr) ++count; + } + + kj::Array result = kj::heapArray(count); + size_t i = 0; + for (auto& schema: schemas) { + if (schema.value->lazyInitializer == nullptr) { + result[i++] = Schema(&schema.value->defaultBrand); + } + } + return result; +} + +void SchemaLoader::Impl::computeOptimizationHints() { + kj::HashMap<_::RawSchema*, kj::Vector<_::RawSchema*>> undecided; + // This map contains schemas for which we haven't yet decided if they might have capabilities. + // They at least do not directly contain capabilities, but they can't be fully decided until + // the dependents are decided. + // + // Each entry maps to a list of other schemas whose decisions depend on this schema. When a + // schema in the map is discovered to contain capabilities, then all these dependents must also + // be presumed to contain capabilities. + + // First pass: Decide on the easy cases and populate the `undecided` map with hard cases. + for (auto& entry: schemas) { + _::RawSchema* schema = entry.value; + + // Default to assuming everything could contain caps. + schema->mayContainCapabilities = true; + + if (schema->lazyInitializer != nullptr) { + // Not initialized yet, so we have to be conservative and assume there could be capabilities. + continue; + } + + auto node = readMessageUnchecked(schema->encodedNode); + + if (!node.isStruct()) { + // Non-structs are irrelevant. + continue; + } + + auto structSchema = node.getStruct(); + + bool foundAnyCaps = false; + bool foundAnyStructs = false; + for (auto field: structSchema.getFields()) { + switch (field.which()) { + case schema::Field::GROUP: + foundAnyStructs = true; + break; + case schema::Field::SLOT: { + auto type = field.getSlot().getType(); + while (type.isList()) { + type = type.getList().getElementType(); + } + + switch (type.which()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::TEXT: + case schema::Type::DATA: + case schema::Type::ENUM: + // Not a capability. + break; + + case schema::Type::STRUCT: + foundAnyStructs = true; + break; + + case schema::Type::ANY_POINTER: // could be a capability, or transitively contain one + case schema::Type::INTERFACE: // definitely a capability + foundAnyCaps = true; + break; + + case schema::Type::LIST: + KJ_UNREACHABLE; // handled above + } + break; + } + } + + if (foundAnyCaps) break; // no point continuing + } + + if (foundAnyCaps) { + // Definitely has capabilities, don't add to `undecided`. + } else if (!foundAnyStructs) { + // Definitely does NOT have capabilities. Go ahead and set the hint and don't add to + // `undecided`. + schema->mayContainCapabilities = false; + } else { + // Don't know yet. Mark as no-capabilities for now, but place in `undecided` set to review + // later. + schema->mayContainCapabilities = false; + undecided.insert(schema, {}); + } + } + + // Second pass: For all undecided schemas, check dependencies and register as dependents where + // needed. + kj::Vector<_::RawSchema*> decisions; // Schemas that have become decided. + for (auto& entry: undecided) { + auto schema = entry.key; + + auto node = readMessageUnchecked(schema->encodedNode).getStruct(); + + for (auto field: node.getFields()) { + kj::Maybe depId; + + switch (field.which()) { + case schema::Field::GROUP: + depId = field.getGroup().getTypeId(); + break; + case schema::Field::SLOT: { + auto type = field.getSlot().getType(); + while (type.isList()) { + type = type.getList().getElementType(); + } + if (type.isStruct()) { + depId = type.getStruct().getTypeId(); + } + break; + } + } + + KJ_IF_MAYBE(d, depId) { + _::RawSchema* dep = KJ_ASSERT_NONNULL(schemas.find(*d)); + + if (dep->mayContainCapabilities) { + // Oops, this dependency is already known to have capabilities. So that means the current + // schema also has capabilities, transitively. Mark it as such. + schema->mayContainCapabilities = true; + + // Schedule this schema for removal later. + decisions.add(schema); + + // Might as well end the loop early. + break; + } else KJ_IF_MAYBE(undecidedEntry, undecided.find(dep)) { + // This dependency is in the undecided set. Register interest in it. + undecidedEntry->add(schema); + } else { + // This dependency is decided, and the decision is that it has no capabilities. So it + // has no impact on the dependent. + } + } + } + } + + // Third pass: For each decision we made, remove it and propagate to its dependents. + while (!decisions.empty()) { + _::RawSchema* decision = decisions.back(); + decisions.removeLast(); + + auto& entry = KJ_ASSERT_NONNULL(undecided.findEntry(decision)); + for (auto& dependent: entry.value) { + if (!dependent->mayContainCapabilities) { + // The dependent was not previously decided. But, we now know it has a dependency which has + // capabilities, therefore we can decide the dependent. + dependent->mayContainCapabilities = true; + decisions.add(dependent); + } + } + undecided.erase(entry); + } + + // Everything that is left in `undecided` must only be waiting on other undecided schemas. We + // can therefore decide that none of them have any capabilities. We marked them as such + // earlier so now we're all done. +} + +void SchemaLoader::Impl::requireStructSize(uint64_t id, uint dataWordCount, uint pointerCount) { + structSizeRequirements.upsert(id, { uint16_t(dataWordCount), uint16_t(pointerCount) }, + [&](RequiredSize& existingValue, RequiredSize&& newValue) { + existingValue.dataWordCount = kj::max(existingValue.dataWordCount, newValue.dataWordCount); + existingValue.pointerCount = kj::max(existingValue.pointerCount, newValue.pointerCount); + }); + + KJ_IF_MAYBE(schema, schemas.find(id)) { + applyStructSizeRequirement(*schema, dataWordCount, pointerCount); + } +} + +kj::ArrayPtr SchemaLoader::Impl::makeUncheckedNode(schema::Node::Reader node) { + size_t size = node.totalSize().wordCount + 1; + kj::ArrayPtr result = arena.allocateArray(size); + memset(result.begin(), 0, size * sizeof(word)); + copyToUnchecked(node, result); + return result; +} + +kj::ArrayPtr SchemaLoader::Impl::makeUncheckedNodeEnforcingSizeRequirements( + schema::Node::Reader node) { + if (node.isStruct()) { + KJ_IF_MAYBE(requirement, structSizeRequirements.find(node.getId())) { + auto structNode = node.getStruct(); + if (structNode.getDataWordCount() < requirement->dataWordCount || + structNode.getPointerCount() < requirement->pointerCount) { + return rewriteStructNodeWithSizes(node, requirement->dataWordCount, + requirement->pointerCount); + } + } + } + + return makeUncheckedNode(node); +} + +kj::ArrayPtr SchemaLoader::Impl::rewriteStructNodeWithSizes( + schema::Node::Reader node, uint dataWordCount, uint pointerCount) { + MallocMessageBuilder builder; + builder.setRoot(node); + + auto root = builder.getRoot(); + auto newStruct = root.getStruct(); + newStruct.setDataWordCount(kj::max(newStruct.getDataWordCount(), dataWordCount)); + newStruct.setPointerCount(kj::max(newStruct.getPointerCount(), pointerCount)); + + return makeUncheckedNode(root); +} + +void SchemaLoader::Impl::applyStructSizeRequirement( + _::RawSchema* raw, uint dataWordCount, uint pointerCount) { + auto node = readMessageUnchecked(raw->encodedNode); + + auto structNode = node.getStruct(); + if (structNode.getDataWordCount() < dataWordCount || + structNode.getPointerCount() < pointerCount) { + // Sizes need to be increased. Must rewrite. + kj::ArrayPtr words = rewriteStructNodeWithSizes(node, dataWordCount, pointerCount); + + // We don't need to re-validate the node because we know this change could not possibly have + // invalidated it. Just remake the unchecked message. + raw->encodedNode = words.begin(); + raw->encodedSize = words.size(); + } +} + +void SchemaLoader::InitializerImpl::init(const _::RawSchema* schema) const { + KJ_IF_MAYBE(c, callback) { + c->load(loader, schema->id); + } + + if (schema->lazyInitializer != nullptr) { + // The callback declined to load a schema. We need to disable the initializer so that it + // doesn't get invoked again later, as we can no longer modify this schema once it is in use. + + // Lock the loader for read to make sure no one is concurrently loading a replacement for this + // schema node. + auto lock = loader.impl.lockShared(); + + // Get the mutable version of the schema. + _::RawSchema* mutableSchema = lock->get()->tryGet(schema->id).schema; + KJ_ASSERT(mutableSchema == schema, + "A schema not belonging to this loader used its initializer."); + + // Disable the initializer. +#if __GNUC__ || defined(__clang__) + __atomic_store_n(&mutableSchema->lazyInitializer, nullptr, __ATOMIC_RELEASE); + __atomic_store_n(&mutableSchema->defaultBrand.lazyInitializer, nullptr, __ATOMIC_RELEASE); +#else +#error "Platform not supported" +#endif + } +} + +void SchemaLoader::BrandedInitializerImpl::init(const _::RawBrandedSchema* schema) const { + schema->generic->ensureInitialized(); + + auto lock = loader.impl.lockExclusive(); + + if (schema->lazyInitializer == nullptr) { + // Never mind, someone beat us to it. + return; + } + + // Get the mutable version. + _::RawBrandedSchema* mutableSchema = KJ_ASSERT_NONNULL( + lock->get()->brands.find(SchemaBindingsPair { schema->generic, schema->scopes })); + KJ_ASSERT(mutableSchema == schema); + + // Construct its dependency map. + auto deps = lock->get()->makeBrandedDependencies(mutableSchema->generic, + kj::arrayPtr(mutableSchema->scopes, mutableSchema->scopeCount)); + mutableSchema->dependencies = deps.begin(); + mutableSchema->dependencyCount = deps.size(); + + // It's initialized now, so disable the initializer. +#if __GNUC__ || defined(__clang__) + __atomic_store_n(&mutableSchema->lazyInitializer, nullptr, __ATOMIC_RELEASE); +#else +#error "Platform not supported" +#endif +} + +// ======================================================================================= + +SchemaLoader::SchemaLoader(): impl(kj::heap(*this)) {} +SchemaLoader::SchemaLoader(const LazyLoadCallback& callback) + : impl(kj::heap(*this, callback)) {} +SchemaLoader::~SchemaLoader() noexcept(false) {} + +Schema SchemaLoader::get(uint64_t id, schema::Brand::Reader brand, Schema scope) const { + KJ_IF_MAYBE(result, tryGet(id, brand, scope)) { + return *result; + } else { + KJ_FAIL_REQUIRE("no schema node loaded for id", kj::hex(id)); + } +} + +kj::Maybe SchemaLoader::tryGet( + uint64_t id, schema::Brand::Reader brand, Schema scope) const { + auto getResult = impl.lockShared()->get()->tryGet(id); + if (getResult.schema == nullptr || getResult.schema->lazyInitializer != nullptr) { + // This schema couldn't be found or has yet to be lazily loaded. If we have a lazy loader + // callback, invoke it now to try to get it to load this schema. + KJ_IF_MAYBE(c, getResult.callback) { + c->load(*this, id); + } + getResult = impl.lockShared()->get()->tryGet(id); + } + if (getResult.schema != nullptr && getResult.schema->lazyInitializer == nullptr) { + if (brand.getScopes().size() > 0) { + auto brandedSchema = impl.lockExclusive()->get()->makeBranded( + getResult.schema, brand, + scope.raw->isUnbound() + ? kj::Maybe>(nullptr) + : kj::arrayPtr(scope.raw->scopes, scope.raw->scopeCount)); + brandedSchema->ensureInitialized(); + return Schema(brandedSchema); + } else { + return Schema(&getResult.schema->defaultBrand); + } + } else { + return nullptr; + } +} + +Schema SchemaLoader::getUnbound(uint64_t id) const { + auto schema = get(id); + return Schema(impl.lockExclusive()->get()->getUnbound(schema.raw->generic)); +} + +Type SchemaLoader::getType(schema::Type::Reader proto, Schema scope) const { + switch (proto.which()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::TEXT: + case schema::Type::DATA: + return proto.which(); + + case schema::Type::STRUCT: { + auto structType = proto.getStruct(); + return get(structType.getTypeId(), structType.getBrand(), scope).asStruct(); + } + + case schema::Type::ENUM: { + auto enumType = proto.getEnum(); + return get(enumType.getTypeId(), enumType.getBrand(), scope).asEnum(); + } + + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interfaces are not supported."); + + case schema::Type::LIST: + return ListSchema::of(getType(proto.getList().getElementType(), scope)); + + case schema::Type::ANY_POINTER: { + auto anyPointer = proto.getAnyPointer(); + switch (anyPointer.which()) { + case schema::Type::AnyPointer::UNCONSTRAINED: + return schema::Type::ANY_POINTER; + case schema::Type::AnyPointer::PARAMETER: { + auto param = anyPointer.getParameter(); + return scope.getBrandBinding(param.getScopeId(), param.getParameterIndex()); + } + case schema::Type::AnyPointer::IMPLICIT_METHOD_PARAMETER: + // We don't support binding implicit method params here. + return schema::Type::ANY_POINTER; + } + + KJ_UNREACHABLE; + } + } + + KJ_UNREACHABLE; +} + +Schema SchemaLoader::load(const schema::Node::Reader& reader) { + return Schema(&impl.lockExclusive()->get()->load(reader, false)->defaultBrand); +} + +Schema SchemaLoader::loadOnce(const schema::Node::Reader& reader) const { + auto locked = impl.lockExclusive(); + auto getResult = locked->get()->tryGet(reader.getId()); + if (getResult.schema == nullptr || getResult.schema->lazyInitializer != nullptr) { + // Doesn't exist yet, or the existing schema is a placeholder and therefore has not yet been + // seen publicly. Go ahead and load the incoming reader. + return Schema(&locked->get()->load(reader, false)->defaultBrand); + } else { + return Schema(&getResult.schema->defaultBrand); + } +} + +kj::Array SchemaLoader::getAllLoaded() const { + return impl.lockShared()->get()->getAllLoaded(); +} + +void SchemaLoader::computeOptimizationHints() { + impl.lockExclusive()->get()->computeOptimizationHints(); +} + +void SchemaLoader::loadNative(const _::RawSchema* nativeSchema) { + impl.lockExclusive()->get()->loadNative(nativeSchema); +} + +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/schema-loader.h b/vendor/capnproto/src/capnp/schema-loader.h new file mode 100644 index 0000000..5db8364 --- /dev/null +++ b/vendor/capnproto/src/capnp/schema-loader.h @@ -0,0 +1,183 @@ +// 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. + +#pragma once + +#include "schema.h" +#include +#include + +CAPNP_BEGIN_HEADER + +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_AND_MOVE(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 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 + 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(), you must call this method before constructing the DynamicValue. Otherwise, + // as() will throw an exception complaining about type mismatch. + + kj::Array getAllLoaded() const; + // Get a complete list of all loaded schema nodes. It is particularly useful to call this after + // loadCompiledTypeAndDependencies() in order to get a flat list of all of T's transitive + // dependencies. + + void computeOptimizationHints(); + // Call after all interesting schemas have been loaded to compute optimization hints. In + // particular, this initializes `hasNoCapabilities` for every struct type. Before this is called, + // that value is initialized to false for all types (which ensures correct behavior but does not + // allow the optimization). + // + // If any loaded struct types contain fields of types for which no schema has been loaded, they + // will be presumed to possibly contain capabilities. `LazyLoadCallback` will NOT be invoked to + // load any types that haven't been loaded yet. + // + // TODO(someday): Perhaps we could dynamically initialize the hints on-demand, but it would be + // much more work to implement. + +private: + class Validator; + class CompatibilityChecker; + class Impl; + class InitializerImpl; + class BrandedInitializerImpl; + kj::MutexGuarded> impl; + + void loadNative(const _::RawSchema* nativeSchema); +}; + +template +inline void SchemaLoader::loadCompiledTypeAndDependencies() { + loadNative(&_::rawSchema()); +} + +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/schema-parser.c++ b/vendor/capnproto/src/capnp/schema-parser.c++ new file mode 100644 index 0000000..0edebff --- /dev/null +++ b/vendor/capnproto/src/capnp/schema-parser.c++ @@ -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. + +#include "schema-parser.h" +#include "message.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace capnp { + +namespace { + +template +size_t findLargestElementBefore(const kj::Vector& vec, const T& key) { + KJ_REQUIRE(vec.size() > 0 && vec[0] <= key); + + size_t lower = 0; + size_t upper = vec.size(); + + while (upper - lower > 1) { + size_t mid = (lower + upper) / 2; + if (vec[mid] > key) { + upper = mid; + } else { + lower = mid; + } + } + + return lower; +} + +} // namespace + +// ======================================================================================= + +class SchemaParser::ModuleImpl final: public compiler::Module { +public: + ModuleImpl(const SchemaParser& parser, kj::Own&& file) + : parser(parser), file(kj::mv(file)) {} + + kj::StringPtr getSourceName() override { + return file->getDisplayName(); + } + + Orphan loadContent(Orphanage orphanage) override { + kj::Array content = file->readContent(); + + lineBreaks.get([&](kj::SpaceFor>& space) { + auto vec = space.construct(content.size() / 40); + vec->add(0); + for (const char* pos = content.begin(); pos < content.end(); ++pos) { + if (*pos == '\n') { + vec->add(pos + 1 - content.begin()); + } + } + return vec; + }); + + MallocMessageBuilder lexedBuilder; + auto statements = lexedBuilder.initRoot(); + compiler::lex(content, statements, *this); + + auto parsed = orphanage.newOrphan(); + compiler::parseFile(statements.getStatements(), parsed.get(), *this); + return parsed; + } + + kj::Maybe importRelative(kj::StringPtr importPath) override { + KJ_IF_MAYBE(importedFile, file->import(importPath)) { + return parser.getModuleImpl(kj::mv(*importedFile)); + } else { + return nullptr; + } + } + + kj::Maybe> embedRelative(kj::StringPtr embedPath) override { + KJ_IF_MAYBE(importedFile, file->import(embedPath)) { + return importedFile->get()->readContent().releaseAsBytes(); + } else { + return nullptr; + } + } + + void addError(uint32_t startByte, uint32_t endByte, kj::StringPtr message) override { + auto& lines = lineBreaks.get( + [](kj::SpaceFor>& space) { + KJ_FAIL_REQUIRE("Can't report errors until loadContent() is called."); + return space.construct(); + }); + + // TODO(someday): This counts tabs as single characters. Do we care? + uint startLine = findLargestElementBefore(lines, startByte); + uint startCol = startByte - lines[startLine]; + uint endLine = findLargestElementBefore(lines, endByte); + uint endCol = endByte - lines[endLine]; + + file->reportError( + SchemaFile::SourcePos { startByte, startLine, startCol }, + SchemaFile::SourcePos { endByte, endLine, endCol }, + message); + + // We intentionally only set hadErrors true if reportError() didn't throw. + parser.hadErrors = true; + } + + bool hadErrors() override { + return parser.hadErrors; + } + +private: + const SchemaParser& parser; + kj::Own file; + + kj::Lazy> lineBreaks; + // Byte offsets of the first byte in each source line. The first element is always zero. + // Initialized the first time the module is loaded. +}; + +// ======================================================================================= + +namespace { + +struct SchemaFileHash { + inline size_t operator()(const SchemaFile* f) const { + return f->hashCode(); + } +}; + +struct SchemaFileEq { + inline bool operator()(const SchemaFile* a, const SchemaFile* b) const { + return *a == *b; + } +}; + +} // namespace + +struct SchemaParser::DiskFileCompat { + // Stuff we only create if parseDiskFile() is ever called, in order to translate that call into + // KJ filesystem API calls. + + kj::Own ownFs; + kj::Filesystem& fs; + + struct ImportDir { + kj::String pathStr; + kj::Path path; + kj::Own dir; + }; + std::map cachedImportDirs; + + std::map, kj::Array> + cachedImportPaths; + + DiskFileCompat(): ownFs(kj::newDiskFilesystem()), fs(*ownFs) {} +}; + +struct SchemaParser::Impl { + typedef std::unordered_map< + const SchemaFile*, kj::Own, SchemaFileHash, SchemaFileEq> FileMap; + kj::MutexGuarded fileMap; + compiler::Compiler compiler; + + kj::MutexGuarded> compat; +}; + +SchemaParser::SchemaParser(): impl(kj::heap()) {} +SchemaParser::~SchemaParser() noexcept(false) {} + +ParsedSchema SchemaParser::parseDiskFile( + kj::StringPtr displayName, kj::StringPtr diskPath, + kj::ArrayPtr importPath) const { + auto lock = impl->compat.lockExclusive(); + DiskFileCompat* compat; + KJ_IF_MAYBE(c, *lock) { + compat = c; + } else { + compat = &lock->emplace(); + } + + auto& root = compat->fs.getRoot(); + auto cwd = compat->fs.getCurrentPath(); + + const kj::ReadableDirectory* baseDir = &root; + kj::Path path = cwd.evalNative(diskPath); + + kj::ArrayPtr translatedImportPath = nullptr; + + if (importPath.size() > 0) { + auto importPathKey = std::make_pair(importPath.begin(), importPath.size()); + auto& slot = compat->cachedImportPaths[importPathKey]; + + if (slot == nullptr) { + slot = KJ_MAP(path, importPath) -> const kj::ReadableDirectory* { + auto iter = compat->cachedImportDirs.find(path); + if (iter != compat->cachedImportDirs.end()) { + return iter->second.dir; + } + + auto parsed = cwd.evalNative(path); + kj::Own dir; + KJ_IF_MAYBE(d, root.tryOpenSubdir(parsed)) { + dir = kj::mv(*d); + } else { + // Ignore paths that don't exist. + dir = kj::newInMemoryDirectory(kj::nullClock()); + } + + const kj::ReadableDirectory* result = dir; + + kj::StringPtr pathRef = path; + KJ_ASSERT(compat->cachedImportDirs.insert(std::make_pair(pathRef, + DiskFileCompat::ImportDir { kj::str(path), kj::mv(parsed), kj::mv(dir) })).second); + + return result; + }; + } + + translatedImportPath = slot; + + // Check if `path` appears to be inside any of the import path directories. If so, adjust + // to be relative to that directory rather than absolute. + kj::Maybe matchedImportDir; + size_t bestMatchLength = 0; + for (auto importDir: importPath) { + auto iter = compat->cachedImportDirs.find(importDir); + KJ_ASSERT(iter != compat->cachedImportDirs.end()); + + if (path.startsWith(iter->second.path)) { + // Looks like we're trying to load a file from inside this import path. Treat the import + // path as the base directory. + if (iter->second.path.size() > bestMatchLength) { + bestMatchLength = iter->second.path.size(); + matchedImportDir = iter->second; + } + } + } + + KJ_IF_MAYBE(match, matchedImportDir) { + baseDir = match->dir; + path = path.slice(match->path.size(), path.size()).clone(); + } + } + + return parseFile(SchemaFile::newFromDirectory( + *baseDir, kj::mv(path), translatedImportPath, kj::str(displayName))); +} + +ParsedSchema SchemaParser::parseFile(kj::Own&& file) const { + KJ_DEFER(impl->compiler.clearWorkspace()); + uint64_t id = impl->compiler.add(getModuleImpl(kj::mv(file))).getId(); + impl->compiler.eagerlyCompile(id, + compiler::Compiler::NODE | compiler::Compiler::CHILDREN | + compiler::Compiler::DEPENDENCIES | compiler::Compiler::DEPENDENCY_DEPENDENCIES); + return ParsedSchema(impl->compiler.getLoader().get(id), *this); +} + +SchemaParser::ModuleImpl& SchemaParser::getModuleImpl(kj::Own&& file) const { + auto lock = impl->fileMap.lockExclusive(); + + auto insertResult = lock->insert(std::make_pair(file.get(), kj::Own())); + if (insertResult.second) { + // This is a newly-inserted entry. Construct the ModuleImpl. + insertResult.first->second = kj::heap(*this, kj::mv(file)); + } + return *insertResult.first->second; +} + +kj::Maybe ParsedSchema::findNested(kj::StringPtr name) const { + return parser->impl->compiler.lookup(getProto().getId(), name).map( + [this](uint64_t childId) { + return ParsedSchema(parser->impl->compiler.getLoader().get(childId), *parser); + }); +} + +ParsedSchema ParsedSchema::getNested(kj::StringPtr nestedName) const { + KJ_IF_MAYBE(nested, findNested(nestedName)) { + return *nested; + } else { + KJ_FAIL_REQUIRE("no such nested declaration", getProto().getDisplayName(), nestedName); + } +} + +class SchemaFile::DiskSchemaFile final: public SchemaFile { +public: + DiskSchemaFile(const kj::ReadableDirectory& baseDir, kj::Path pathParam, + kj::ArrayPtr importPath, + kj::Own file, + kj::Maybe displayNameOverride) + : baseDir(baseDir), path(kj::mv(pathParam)), importPath(importPath), file(kj::mv(file)) { + KJ_IF_MAYBE(dn, displayNameOverride) { + displayName = kj::mv(*dn); + displayNameOverridden = true; + } else { + displayName = path.toString(); + displayNameOverridden = false; + } + } + + kj::StringPtr getDisplayName() const override { + return displayName; + } + + kj::Array readContent() const override { + return file->mmap(0, file->stat().size).releaseAsChars(); + } + + kj::Maybe> import(kj::StringPtr target) const override { + if (target.startsWith("/")) { + auto parsed = kj::Path::parse(target.slice(1)); + for (auto candidate: importPath) { + KJ_IF_MAYBE(newFile, candidate->tryOpenFile(parsed)) { + return kj::implicitCast>(kj::heap( + *candidate, kj::mv(parsed), importPath, kj::mv(*newFile), nullptr)); + } + } + return nullptr; + } else { + auto parsed = path.parent().eval(target); + + kj::Maybe displayNameOverride; + if (displayNameOverridden) { + // Try to create a consistent display name override for the imported file. This is for + // backwards-compatibility only -- display names are only overridden when using the + // deprecated parseDiskFile() interface. + kj::runCatchingExceptions([&]() { + displayNameOverride = kj::Path::parse(displayName).parent().eval(target).toString(); + }); + } + + KJ_IF_MAYBE(newFile, baseDir.tryOpenFile(parsed)) { + return kj::implicitCast>(kj::heap( + baseDir, kj::mv(parsed), importPath, kj::mv(*newFile), kj::mv(displayNameOverride))); + } else { + return nullptr; + } + } + } + + bool operator==(const SchemaFile& other) const override { + auto& other2 = kj::downcast(other); + return &baseDir == &other2.baseDir && path == other2.path; + } + size_t hashCode() const override { + // djb hash with xor + // TODO(someday): Add hashing library to KJ. + size_t result = reinterpret_cast(&baseDir); + for (auto& part: path) { + for (char c: part) { + result = (result * 33) ^ c; + } + result = (result * 33) ^ '/'; + } + return result; + } + + void reportError(SourcePos start, SourcePos end, kj::StringPtr message) const override { + kj::getExceptionCallback().onRecoverableException(kj::Exception( + kj::Exception::Type::FAILED, path.toString(), start.line, + kj::heapString(message))); + } + +private: + const kj::ReadableDirectory& baseDir; + kj::Path path; + kj::ArrayPtr importPath; + kj::Own file; + kj::String displayName; + bool displayNameOverridden; +}; + +kj::Own SchemaFile::newFromDirectory( + const kj::ReadableDirectory& baseDir, kj::Path path, + kj::ArrayPtr importPath, + kj::Maybe displayNameOverride) { + return kj::heap(baseDir, kj::mv(path), importPath, baseDir.openFile(path), + kj::mv(displayNameOverride)); +} + +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/schema-parser.h b/vendor/capnproto/src/capnp/schema-parser.h new file mode 100644 index 0000000..2ff72b9 --- /dev/null +++ b/vendor/capnproto/src/capnp/schema-parser.h @@ -0,0 +1,153 @@ +// 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. + +#pragma once + +#include "schema-loader.h" +#include +#include + +CAPNP_BEGIN_HEADER + +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 importPath) const; + // Parse a file from disk. Relative imports and embeds can access paths outside its directory. + // Absolute schema imports are searched in importPath. + + ParsedSchema parseFile(kj::Own&& file) const; + // Advanced interface for parsing a file that may or may not be located in any global namespace. + // + // 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. + +private: + struct Impl; + struct DiskFileCompat; + class ModuleImpl; + kj::Own impl; + mutable bool hadErrors = false; + + ModuleImpl& getModuleImpl(kj::Own&& file) const; + + 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 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; +}; + +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: + // Note: Cap'n Proto 0.6.x and below had classes FileReader and DiskFileReader and a method + // newDiskFile() defined here. These were removed when SchemaParser was transitioned to use the + // KJ filesystem API. You should be able to get the same effect by subclassing + // kj::ReadableDirectory, or using kj::newInMemoryDirectory(). + + static kj::Own newFromDirectory( + const kj::ReadableDirectory& baseDir, kj::Path path, + kj::ArrayPtr importPath, + kj::Maybe displayNameOverride = nullptr); + // Construct a SchemaFile representing a file in a kj::ReadableDirectory. This is used to + // resolve imports relative to a filesystem directory. + // + // The SchemaFile compares equal to any other SchemaFile that has exactly the same `baseDir` + // object (by identity) and `path` (by value). + + // ----------------------------------------------------------------- + // 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 readContent() const = 0; + // Read the file's entire content and return it as a byte array. + + virtual kj::Maybe> 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 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 + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/schema.c++ b/vendor/capnproto/src/capnp/schema.c++ new file mode 100644 index 0000000..bf89146 --- /dev/null +++ b/vendor/capnproto/src/capnp/schema.c++ @@ -0,0 +1,796 @@ +// 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 "schema.h" +#include "message.h" +#include + +namespace capnp { + +namespace schema { + uint KJ_HASHCODE(Type::Which w) { return kj::hashCode(static_cast(w)); } + // TODO(cleanup): Cap'n Proto does not declare stringifiers nor hashers for `Which` enums, unlike + // all other enums. Fix that and remove this. +} + +namespace _ { // private + +// Null schemas generated using the below schema file with: +// +// capnp eval -Isrc null-schemas.capnp node --flat | +// hexdump -v -e '8/1 "0x%02x, "' -e '1/8 "\n"'; echo +// +// I totally don't understand hexdump format strings and came up with this command based on trial +// and error. +// +// @0x879863d4b2cc4a1e; +// +// using Node = import "/capnp/schema.capnp".Node; +// +// const node :Node = ( +// id = 0x0000000000000000, +// displayName = "(null schema)"); +// +// const struct :Node = ( +// id = 0x0000000000000001, +// displayName = "(null struct schema)", +// struct = ( +// dataWordCount = 0, +// pointerCount = 0, +// preferredListEncoding = empty)); +// +// const enum :Node = ( +// id = 0x0000000000000002, +// displayName = "(null enum schema)", +// enum = ()); +// +// const interface :Node = ( +// id = 0x0000000000000003, +// displayName = "(null interface schema)", +// interface = ()); +// +// const const :Node = ( +// id = 0x0000000000000004, +// displayName = "(null const schema)", +// const = (type = (void = void), value = (void = void))); + +static const AlignedData<13> NULL_SCHEMA_BYTES = {{ + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, // union discriminant intentionally mangled + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x73, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x29, 0x00, 0x00, 0x00, +}}; +const RawSchema NULL_SCHEMA = { + 0x0000000000000000, NULL_SCHEMA_BYTES.words, 13, + nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, + { &NULL_SCHEMA, nullptr, nullptr, 0, 0, nullptr } +}; + +static const AlignedData<14> NULL_STRUCT_SCHEMA_BYTES = {{ + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x73, 0x74, + 0x72, 0x75, 0x63, 0x74, 0x20, 0x73, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x29, 0x00, 0x00, 0x00, 0x00, +}}; +const RawSchema NULL_STRUCT_SCHEMA = { + 0x0000000000000001, NULL_STRUCT_SCHEMA_BYTES.words, 14, + nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, + { &NULL_STRUCT_SCHEMA, nullptr, nullptr, 0, 0, nullptr } +}; + +static const AlignedData<14> NULL_ENUM_SCHEMA_BYTES = {{ + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x65, 0x6e, + 0x75, 0x6d, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}}; +const RawSchema NULL_ENUM_SCHEMA = { + 0x0000000000000002, NULL_ENUM_SCHEMA_BYTES.words, 14, + nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, + { &NULL_ENUM_SCHEMA, nullptr, nullptr, 0, 0, nullptr } +}; + +static const AlignedData<20> NULL_CONST_SCHEMA_BYTES = {{ + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x20, 0x73, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}}; +const RawSchema NULL_CONST_SCHEMA = { + 0x0000000000000004, NULL_CONST_SCHEMA_BYTES.words, 20, + nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, + { &NULL_CONST_SCHEMA, nullptr, nullptr, 0, 0, nullptr } +}; + +} // namespace _ (private) + +// ======================================================================================= + +schema::Node::Reader Schema::getProto() const { + return readMessageUnchecked(raw->generic->encodedNode); +} + +kj::ArrayPtr Schema::asUncheckedMessage() const { + return kj::arrayPtr(raw->generic->encodedNode, raw->generic->encodedSize); +} + +Schema Schema::getDependency(uint64_t id, uint location) const { + { + // Binary search dependency list. + uint lower = 0; + uint upper = raw->dependencyCount; + + while (lower < upper) { + uint mid = (lower + upper) / 2; + + auto candidate = raw->dependencies[mid]; + if (candidate.location == location) { + candidate.schema->ensureInitialized(); + return Schema(candidate.schema); + } else if (candidate.location < location) { + lower = mid + 1; + } else { + upper = mid; + } + } + } + + { + uint lower = 0; + uint upper = raw->generic->dependencyCount; + + while (lower < upper) { + uint mid = (lower + upper) / 2; + + const _::RawSchema* candidate = raw->generic->dependencies[mid]; + + uint64_t candidateId = candidate->id; + if (candidateId == id) { + candidate->ensureInitialized(); + return Schema(&candidate->defaultBrand); + } else if (candidateId < id) { + lower = mid + 1; + } else { + upper = mid; + } + } + } + + KJ_FAIL_REQUIRE("Requested ID not found in dependency table.", kj::hex(id)) { + return Schema(); + } +} + +Schema::BrandArgumentList Schema::getBrandArgumentsAtScope(uint64_t scopeId) const { + KJ_REQUIRE(getProto().getIsGeneric(), "Not a generic type.", getProto().getDisplayName()); + + for (auto scope: kj::range(raw->scopes, raw->scopes + raw->scopeCount)) { + if (scope->typeId == scopeId) { + // OK, this scope matches the scope we're looking for. + if (scope->isUnbound) { + return BrandArgumentList(scopeId, true); + } else { + return BrandArgumentList(scopeId, scope->bindingCount, scope->bindings); + } + } + } + + // This scope is not listed in the scopes list. + return BrandArgumentList(scopeId, raw->isUnbound()); +} + +kj::Array Schema::getGenericScopeIds() const { + if (!getProto().getIsGeneric()) + return nullptr; + + auto result = kj::heapArray(raw->scopeCount); + for (auto iScope: kj::indices(result)) { + result[iScope] = raw->scopes[iScope].typeId; + } + + return result; +} + + +StructSchema Schema::asStruct() const { + KJ_REQUIRE(getProto().isStruct(), "Tried to use non-struct schema as a struct.", + getProto().getDisplayName()) { + return StructSchema(); + } + return StructSchema(*this); +} + +EnumSchema Schema::asEnum() const { + KJ_REQUIRE(getProto().isEnum(), "Tried to use non-enum schema as an enum.", + getProto().getDisplayName()) { + return EnumSchema(); + } + return EnumSchema(*this); +} + + + +ConstSchema Schema::asConst() const { + KJ_REQUIRE(getProto().isConst(), "Tried to use non-constant schema as a constant.", + getProto().getDisplayName()) { + return ConstSchema(); + } + return ConstSchema(*this); +} + +kj::StringPtr Schema::getShortDisplayName() const { + auto proto = getProto(); + return proto.getDisplayName().slice(proto.getDisplayNamePrefixLength()); +} + +const kj::StringPtr Schema::getUnqualifiedName() const { + auto proto = getProto(); + return proto.getDisplayName().slice(proto.getDisplayNamePrefixLength()); +} + +void Schema::requireUsableAs(const _::RawSchema* expected) const { + KJ_REQUIRE(raw->generic == expected || + (expected != nullptr && raw->generic->canCastTo == expected), + "This schema is not compatible with the requested native type."); +} + +uint32_t Schema::getSchemaOffset(const schema::Value::Reader& value) const { + const word* ptr; + + switch (value.which()) { + case schema::Value::TEXT: + ptr = reinterpret_cast(value.getText().begin()); + break; + case schema::Value::DATA: + ptr = reinterpret_cast(value.getData().begin()); + break; + case schema::Value::STRUCT: + ptr = value.getStruct().getAs<_::UncheckedMessage>(); + break; + case schema::Value::LIST: + ptr = value.getList().getAs<_::UncheckedMessage>(); + break; + case schema::Value::ANY_POINTER: + ptr = value.getAnyPointer().getAs<_::UncheckedMessage>(); + break; + default: + KJ_FAIL_ASSERT("getDefaultValueSchemaOffset() can only be called on struct, list, " + "and any-pointer fields."); + } + + return ptr - raw->generic->encodedNode; +} + +Type Schema::getBrandBinding(uint64_t scopeId, uint index) const { + return getBrandArgumentsAtScope(scopeId)[index]; +} + +Type Schema::interpretType(schema::Type::Reader proto, uint location) const { + switch (proto.which()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::TEXT: + case schema::Type::DATA: + return proto.which(); + + case schema::Type::STRUCT: { + auto structType = proto.getStruct(); + return getDependency(structType.getTypeId(), location).asStruct(); + } + + case schema::Type::ENUM: { + auto enumType = proto.getEnum(); + return getDependency(enumType.getTypeId(), location).asEnum(); + } + + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interfaces are not supported."); + + case schema::Type::LIST: + return ListSchema::of(interpretType(proto.getList().getElementType(), location)); + + case schema::Type::ANY_POINTER: { + auto anyPointer = proto.getAnyPointer(); + switch (anyPointer.which()) { + case schema::Type::AnyPointer::UNCONSTRAINED: + return anyPointer.getUnconstrained().which(); + case schema::Type::AnyPointer::PARAMETER: { + auto param = anyPointer.getParameter(); + return getBrandBinding(param.getScopeId(), param.getParameterIndex()); + } + case schema::Type::AnyPointer::IMPLICIT_METHOD_PARAMETER: + return Type(Type::ImplicitParameter { + anyPointer.getImplicitMethodParameter().getParameterIndex() }); + } + + KJ_UNREACHABLE; + } + } + + KJ_UNREACHABLE; +} + +Type Schema::BrandArgumentList::operator[](uint index) const { + if (isUnbound) { + return Type::BrandParameter { scopeId, index }; + } + + if (index >= size_) { + // Binding index out-of-range. Treat as AnyPointer. This is important to allow new + // type parameters to be added to existing types without breaking dependent + // schemas. + return schema::Type::ANY_POINTER; + } + + auto& binding = bindings[index]; + Type result; + if (binding.which == (uint)schema::Type::ANY_POINTER) { + if (binding.scopeId != 0) { + result = Type::BrandParameter { binding.scopeId, binding.paramIndex }; + } else if (binding.isImplicitParameter) { + result = Type::ImplicitParameter { binding.paramIndex }; + } else { + result = static_cast(binding.paramIndex); + } + } else if (binding.schema == nullptr) { + // Builtin / primitive type. + result = static_cast(binding.which); + } else { + binding.schema->ensureInitialized(); + result = Type(static_cast(binding.which), binding.schema); + } + + return result.wrapInList(binding.listDepth); +} + +kj::StringPtr KJ_STRINGIFY(const Schema& schema) { + return schema.getProto().getDisplayName(); +} + +// ======================================================================================= + +namespace { + +template +auto findSchemaMemberByName(const _::RawSchema* raw, kj::StringPtr name, List&& list) + -> kj::Maybe { + uint lower = 0; + uint upper = raw->memberCount; + + while (lower < upper) { + uint mid = (lower + upper) / 2; + + uint16_t memberIndex = raw->membersByName[mid]; + + auto candidate = list[memberIndex]; + kj::StringPtr candidateName = candidate.getProto().getName(); + if (candidateName == name) { + return candidate; + } else if (candidateName < name) { + lower = mid + 1; + } else { + upper = mid; + } + } + + return nullptr; +} + +} // namespace + +StructSchema::FieldList StructSchema::getFields() const { + return FieldList(*this, getProto().getStruct().getFields()); +} + +StructSchema::FieldSubset StructSchema::getUnionFields() const { + auto proto = getProto().getStruct(); + return FieldSubset(*this, proto.getFields(), + raw->generic->membersByDiscriminant, proto.getDiscriminantCount()); +} + +StructSchema::FieldSubset StructSchema::getNonUnionFields() const { + auto proto = getProto().getStruct(); + auto fields = proto.getFields(); + auto offset = proto.getDiscriminantCount(); + auto size = fields.size() - offset; + return FieldSubset(*this, fields, raw->generic->membersByDiscriminant + offset, size); +} + +kj::Maybe StructSchema::findFieldByName(kj::StringPtr name) const { + return findSchemaMemberByName(raw->generic, name, getFields()); +} + +StructSchema::Field StructSchema::getFieldByName(kj::StringPtr name) const { + KJ_IF_MAYBE(member, findFieldByName(name)) { + return *member; + } else { + KJ_FAIL_REQUIRE("struct has no such member", name); + } +} + +kj::Maybe StructSchema::getFieldByDiscriminant(uint16_t discriminant) const { + auto unionFields = getUnionFields(); + + if (discriminant >= unionFields.size()) { + return nullptr; + } else { + return unionFields[discriminant]; + } +} + +Type StructSchema::Field::getType() const { + auto proto = getProto(); + uint location = _::RawBrandedSchema::makeDepLocation(_::RawBrandedSchema::DepKind::FIELD, index); + + switch (proto.which()) { + case schema::Field::SLOT: + return parent.interpretType(proto.getSlot().getType(), location); + + case schema::Field::GROUP: + return parent.getDependency(proto.getGroup().getTypeId(), location).asStruct(); + } + KJ_UNREACHABLE; +} + +uint32_t StructSchema::Field::getDefaultValueSchemaOffset() const { + return parent.getSchemaOffset(proto.getSlot().getDefaultValue()); +} + +kj::StringPtr KJ_STRINGIFY(const StructSchema::Field& field) { + return field.getProto().getName(); +} + +// ------------------------------------------------------------------- + +EnumSchema::EnumerantList EnumSchema::getEnumerants() const { + return EnumerantList(*this, getProto().getEnum().getEnumerants()); +} + +kj::Maybe EnumSchema::findEnumerantByName(kj::StringPtr name) const { + return findSchemaMemberByName(raw->generic, name, getEnumerants()); +} + +EnumSchema::Enumerant EnumSchema::getEnumerantByName(kj::StringPtr name) const { + KJ_IF_MAYBE(enumerant, findEnumerantByName(name)) { + return *enumerant; + } else { + KJ_FAIL_REQUIRE("enum has no such enumerant", name); + } +} + +// ------------------------------------------------------------------- + +uint32_t ConstSchema::getValueSchemaOffset() const { + return getSchemaOffset(getProto().getConst().getValue()); +} + +Type ConstSchema::getType() const { + return interpretType(getProto().getConst().getType(), + _::RawBrandedSchema::makeDepLocation(_::RawBrandedSchema::DepKind::CONST_TYPE, 0)); +} + +// ======================================================================================= + +ListSchema ListSchema::of(schema::Type::Which primitiveType) { + switch (primitiveType) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::TEXT: + case schema::Type::DATA: + break; + + case schema::Type::STRUCT: + case schema::Type::ENUM: + case schema::Type::INTERFACE: + case schema::Type::LIST: + KJ_FAIL_REQUIRE("Must use one of the other ListSchema::of() overloads for complex types."); + break; + + case schema::Type::ANY_POINTER: + KJ_FAIL_REQUIRE("List(AnyPointer) not supported."); + break; + } + + return ListSchema(primitiveType); +} + +ListSchema ListSchema::of(schema::Type::Reader elementType, Schema context) { + // This method is deprecated because it can only be implemented in terms of other deprecated + // methods. Temporarily disable warnings for those other deprecated methods. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + switch (elementType.which()) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::TEXT: + case schema::Type::DATA: + return of(elementType.which()); + + case schema::Type::STRUCT: + return of(context.getDependency(elementType.getStruct().getTypeId()).asStruct()); + + case schema::Type::ENUM: + return of(context.getDependency(elementType.getEnum().getTypeId()).asEnum()); + + case schema::Type::INTERFACE: + KJ_FAIL_REQUIRE("Interfaces are not supported."); + + case schema::Type::LIST: + return of(of(elementType.getList().getElementType(), context)); + + case schema::Type::ANY_POINTER: + KJ_FAIL_REQUIRE("List(AnyPointer) not supported."); + return ListSchema(); + } + + // Unknown type is acceptable. + return ListSchema(elementType.which()); +#pragma GCC diagnostic pop +} + +// ======================================================================================= + +StructSchema Type::asStruct() const { + KJ_REQUIRE(isStruct(), "Tried to interpret a non-struct type as a struct.") { + return StructSchema(); + } + KJ_ASSERT(schema != nullptr); + return StructSchema(Schema(schema)); +} +EnumSchema Type::asEnum() const { + KJ_REQUIRE(isEnum(), "Tried to interpret a non-enum type as an enum.") { + return EnumSchema(); + } + KJ_ASSERT(schema != nullptr); + return EnumSchema(Schema(schema)); +} + +ListSchema Type::asList() const { + KJ_REQUIRE(isList(), "Type::asList(): Not a list.") { + return ListSchema::of(schema::Type::VOID); + } + Type elementType = *this; + --elementType.listDepth; + return ListSchema::of(elementType); +} + +kj::Maybe Type::getBrandParameter() const { + KJ_REQUIRE(isAnyPointer(), "Type::getBrandParameter() can only be called on AnyPointer types."); + + if (scopeId == 0) { + return nullptr; + } else { + return BrandParameter { scopeId, paramIndex }; + } +} + +kj::Maybe Type::getImplicitParameter() const { + KJ_REQUIRE(isAnyPointer(), + "Type::getImplicitParameter() can only be called on AnyPointer types."); + + if (isImplicitParam) { + return ImplicitParameter { paramIndex }; + } else { + return nullptr; + } +} + +bool Type::operator==(const Type& other) const { + if (baseType != other.baseType || listDepth != other.listDepth) { + return false; + } + + switch (baseType) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::TEXT: + case schema::Type::DATA: + return true; + + case schema::Type::STRUCT: + case schema::Type::ENUM: + case schema::Type::INTERFACE: + return schema == other.schema; + + case schema::Type::LIST: + KJ_UNREACHABLE; + + case schema::Type::ANY_POINTER: + return scopeId == other.scopeId && isImplicitParam == other.isImplicitParam && + // Trying to comply with strict aliasing rules. Hopefully the compiler realizes that + // both branches compile to the same instructions and can optimize it away. + (scopeId != 0 || isImplicitParam ? paramIndex == other.paramIndex + : anyPointerKind == other.anyPointerKind); + } + + KJ_UNREACHABLE; +} + +uint Type::hashCode() const { + switch (baseType) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::TEXT: + case schema::Type::DATA: + if (listDepth == 0) { + // Make sure that hashCode(Type(baseType)) == hashCode(baseType), otherwise HashMap lookups + // keyed by `Type` won't work when the caller passes `baseType` as the key. + return kj::hashCode(baseType); + } else { + return kj::hashCode(baseType, listDepth); + } + + case schema::Type::STRUCT: + case schema::Type::ENUM: + case schema::Type::INTERFACE: + if (listDepth == 0) { + // Make sure that hashCode(Type(schema)) == hashCode(schema), otherwise HashMap lookups + // keyed by `Type` won't work when the caller passes `schema` as the key. + return kj::hashCode(schema); + } else { + return kj::hashCode(schema, listDepth); + } + + case schema::Type::LIST: + KJ_UNREACHABLE; + + case schema::Type::ANY_POINTER: { + // Trying to comply with strict aliasing rules. Hopefully the compiler realizes that + // both branches compile to the same instructions and can optimize it away. + uint16_t val = scopeId != 0 || isImplicitParam ? + paramIndex : static_cast(anyPointerKind); + return kj::hashCode(val, isImplicitParam, scopeId, listDepth); + } + } + + KJ_UNREACHABLE; +} + +void Type::requireUsableAs(Type expected) const { + KJ_REQUIRE(baseType == expected.baseType && listDepth == expected.listDepth, + "This type is not compatible with the requested native type."); + + switch (baseType) { + case schema::Type::VOID: + case schema::Type::BOOL: + case schema::Type::INT8: + case schema::Type::INT16: + case schema::Type::INT32: + case schema::Type::INT64: + case schema::Type::UINT8: + case schema::Type::UINT16: + case schema::Type::UINT32: + case schema::Type::UINT64: + case schema::Type::FLOAT32: + case schema::Type::FLOAT64: + case schema::Type::TEXT: + case schema::Type::DATA: + case schema::Type::ANY_POINTER: + break; + + case schema::Type::STRUCT: + case schema::Type::ENUM: + case schema::Type::INTERFACE: + Schema(schema).requireUsableAs(expected.schema->generic); + break; + + case schema::Type::LIST: + KJ_UNREACHABLE; + } +} + +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/schema.capnp b/vendor/capnproto/src/capnp/schema.capnp new file mode 100644 index 0000000..982e69f --- /dev/null +++ b/vendor/capnproto/src/capnp/schema.capnp @@ -0,0 +1,468 @@ +# 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; + } + } + + startByte @34 :UInt32; + endByte @35 :UInt32; + + +} + +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 is always either the + # current scope's type ID or one of its ancestors' IDs. + + 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 the Brand appears is within this scope or a sub-scope, and bindings + # for this scope are deferred to later Brand applications. This is equivalent to a + # pass-through binding list, where each of this scope's parameters is bound to itself. + # For example: + # + # struct Outer(T) { + # struct Inner { + # value @0 :T; + # } + # innerInherit @0 :Inner; # Outer Brand.Scope is `inherit`. + # innerBindSelf @1 :Outer(T).Inner; # Outer Brand.Scope explicitly binds T to T. + # } + # + # The innerInherit and innerBindSelf fields have equivalent types, but different Brand + # styles. + } + } + + 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; +} diff --git a/vendor/capnproto/src/capnp/schema.capnp.c++ b/vendor/capnproto/src/capnp/schema.capnp.c++ new file mode 100644 index 0000000..31fb251 --- /dev/null +++ b/vendor/capnproto/src/capnp/schema.capnp.c++ @@ -0,0 +1,3357 @@ +// Generated by Cap'n Proto compiler, DO NOT EDIT +// source: schema.capnp + +#include "schema.capnp.h" + +namespace capnp { +namespace schemas { +static const ::capnp::_::AlignedData<253> b_e682ab4cf923a417 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 23, 164, 35, 249, 76, 171, 130, 230, + 13, 0, 0, 0, 1, 0, 6, 0, + 217, 114, 76, 98, 9, 197, 63, 169, + 6, 0, 7, 0, 0, 0, 6, 0, + 6, 0, 0, 0, 0, 0, 0, 0, + 61, 5, 0, 0, 177, 27, 0, 0, + 21, 0, 0, 0, 146, 0, 0, 0, + 29, 0, 0, 0, 39, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 57, 0, 0, 0, 135, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 78, 111, 100, + 101, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 1, 0, 1, 0, + 177, 163, 15, 241, 204, 27, 82, 185, + 9, 0, 0, 0, 82, 0, 0, 0, + 66, 194, 15, 250, 187, 85, 191, 222, + 9, 0, 0, 0, 90, 0, 0, 0, + 80, 97, 114, 97, 109, 101, 116, 101, + 114, 0, 0, 0, 0, 0, 0, 0, + 78, 101, 115, 116, 101, 100, 78, 111, + 100, 101, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 177, 1, 0, 0, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 172, 1, 0, 0, 3, 0, 1, 0, + 184, 1, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 181, 1, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 180, 1, 0, 0, 3, 0, 1, 0, + 192, 1, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 189, 1, 0, 0, 194, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 192, 1, 0, 0, 3, 0, 1, 0, + 204, 1, 0, 0, 2, 0, 1, 0, + 3, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 201, 1, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 196, 1, 0, 0, 3, 0, 1, 0, + 208, 1, 0, 0, 2, 0, 1, 0, + 6, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 205, 1, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 204, 1, 0, 0, 3, 0, 1, 0, + 232, 1, 0, 0, 2, 0, 1, 0, + 7, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 229, 1, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 228, 1, 0, 0, 3, 0, 1, 0, + 0, 2, 0, 0, 2, 0, 1, 0, + 8, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 253, 1, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 248, 1, 0, 0, 3, 0, 1, 0, + 4, 2, 0, 0, 2, 0, 1, 0, + 9, 0, 254, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 53, 68, 251, 55, 155, 177, 160, 158, + 1, 2, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 0, 253, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 152, 245, 51, 67, 54, 179, 74, 181, + 233, 1, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 11, 0, 252, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 143, 33, 194, 240, 207, 83, 39, 232, + 209, 1, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 251, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 32, 148, 13, 122, 172, 165, 138, 177, + 189, 1, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 250, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 144, 2, 10, 64, 212, 25, 22, 236, + 165, 1, 0, 0, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 1, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 145, 1, 0, 0, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 144, 1, 0, 0, 3, 0, 1, 0, + 172, 1, 0, 0, 2, 0, 1, 0, + 5, 0, 0, 0, 32, 1, 0, 0, + 0, 0, 1, 0, 33, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 169, 1, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 168, 1, 0, 0, 3, 0, 1, 0, + 180, 1, 0, 0, 2, 0, 1, 0, + 14, 0, 0, 0, 10, 0, 0, 0, + 0, 0, 1, 0, 34, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 177, 1, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 176, 1, 0, 0, 3, 0, 1, 0, + 188, 1, 0, 0, 2, 0, 1, 0, + 15, 0, 0, 0, 11, 0, 0, 0, + 0, 0, 1, 0, 35, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 185, 1, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 180, 1, 0, 0, 3, 0, 1, 0, + 192, 1, 0, 0, 2, 0, 1, 0, + 105, 100, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 105, 115, 112, 108, 97, 121, 78, + 97, 109, 101, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 105, 115, 112, 108, 97, 121, 78, + 97, 109, 101, 80, 114, 101, 102, 105, + 120, 76, 101, 110, 103, 116, 104, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 111, 112, 101, 73, 100, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 110, 101, 115, 116, 101, 100, 78, 111, + 100, 101, 115, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 66, 194, 15, 250, 187, 85, 191, 222, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 110, 110, 111, 116, 97, 116, 105, + 111, 110, 115, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 66, 117, 37, 171, 13, 149, 200, 241, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 102, 105, 108, 101, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 114, 117, 99, 116, 0, 0, + 101, 110, 117, 109, 0, 0, 0, 0, + 105, 110, 116, 101, 114, 102, 97, 99, + 101, 0, 0, 0, 0, 0, 0, 0, + 99, 111, 110, 115, 116, 0, 0, 0, + 97, 110, 110, 111, 116, 97, 116, 105, + 111, 110, 0, 0, 0, 0, 0, 0, + 112, 97, 114, 97, 109, 101, 116, 101, + 114, 115, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 177, 163, 15, 241, 204, 27, 82, 185, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 115, 71, 101, 110, 101, 114, 105, + 99, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 97, 114, 116, 66, 121, 116, + 101, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 110, 100, 66, 121, 116, 101, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_e682ab4cf923a417 = b_e682ab4cf923a417.words; +static const ::capnp::_::RawSchema* const d_e682ab4cf923a417[] = { + &s_9ea0b19b37fb4435, + &s_b18aa5ac7a0d9420, + &s_b54ab3364333f598, + &s_b9521bccf10fa3b1, + &s_debf55bbfa0fc242, + &s_e82753cff0c2218f, + &s_ec1619d4400a0290, + &s_f1c8950dab257542, +}; +static const uint16_t m_e682ab4cf923a417[] = {11, 5, 10, 1, 2, 15, 8, 6, 0, 9, 13, 4, 12, 3, 14, 7}; +static const uint16_t i_e682ab4cf923a417[] = {6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 12, 13, 14, 15}; +const ::capnp::_::RawSchema s_e682ab4cf923a417 = { + 0xe682ab4cf923a417, b_e682ab4cf923a417.words, 253, d_e682ab4cf923a417, m_e682ab4cf923a417, + 8, 16, i_e682ab4cf923a417, nullptr, nullptr, { &s_e682ab4cf923a417, nullptr, nullptr, 0, 0, nullptr }, true +}; +static const ::capnp::_::AlignedData<34> b_b9521bccf10fa3b1 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 177, 163, 15, 241, 204, 27, 82, 185, + 18, 0, 0, 0, 1, 0, 0, 0, + 23, 164, 35, 249, 76, 171, 130, 230, + 1, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 33, 10, 0, 0, 129, 10, 0, 0, + 21, 0, 0, 0, 226, 0, 0, 0, + 33, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 29, 0, 0, 0, 63, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 78, 111, 100, + 101, 46, 80, 97, 114, 97, 109, 101, + 116, 101, 114, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 4, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 3, 0, 1, 0, + 20, 0, 0, 0, 2, 0, 1, 0, + 110, 97, 109, 101, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_b9521bccf10fa3b1 = b_b9521bccf10fa3b1.words; +static const uint16_t m_b9521bccf10fa3b1[] = {0}; +static const uint16_t i_b9521bccf10fa3b1[] = {0}; +const ::capnp::_::RawSchema s_b9521bccf10fa3b1 = { + 0xb9521bccf10fa3b1, b_b9521bccf10fa3b1.words, 34, nullptr, m_b9521bccf10fa3b1, + 0, 1, i_b9521bccf10fa3b1, nullptr, nullptr, { &s_b9521bccf10fa3b1, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<49> b_debf55bbfa0fc242 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 66, 194, 15, 250, 187, 85, 191, 222, + 18, 0, 0, 0, 1, 0, 1, 0, + 23, 164, 35, 249, 76, 171, 130, 230, + 1, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 11, 0, 0, 144, 12, 0, 0, + 21, 0, 0, 0, 234, 0, 0, 0, + 33, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 29, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 78, 111, 100, + 101, 46, 78, 101, 115, 116, 101, 100, + 78, 111, 100, 101, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 52, 0, 0, 0, 2, 0, 1, 0, + 110, 97, 109, 101, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 100, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_debf55bbfa0fc242 = b_debf55bbfa0fc242.words; +static const uint16_t m_debf55bbfa0fc242[] = {1, 0}; +static const uint16_t i_debf55bbfa0fc242[] = {0, 1}; +const ::capnp::_::RawSchema s_debf55bbfa0fc242 = { + 0xdebf55bbfa0fc242, b_debf55bbfa0fc242.words, 49, nullptr, m_debf55bbfa0fc242, + 0, 2, i_debf55bbfa0fc242, nullptr, nullptr, { &s_debf55bbfa0fc242, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<135> b_9ea0b19b37fb4435 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 53, 68, 251, 55, 155, 177, 160, 158, + 18, 0, 0, 0, 1, 0, 6, 0, + 23, 164, 35, 249, 76, 171, 130, 230, + 6, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 202, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 143, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 78, 111, 100, + 101, 46, 115, 116, 114, 117, 99, 116, + 0, 0, 0, 0, 0, 0, 0, 0, + 28, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 1, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 181, 0, 0, 0, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 180, 0, 0, 0, 3, 0, 1, 0, + 192, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 12, 0, 0, 0, + 0, 0, 1, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 189, 0, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 188, 0, 0, 0, 3, 0, 1, 0, + 200, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 13, 0, 0, 0, + 0, 0, 1, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 197, 0, 0, 0, 178, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 200, 0, 0, 0, 3, 0, 1, 0, + 212, 0, 0, 0, 2, 0, 1, 0, + 3, 0, 0, 0, 224, 0, 0, 0, + 0, 0, 1, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 209, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 204, 0, 0, 0, 3, 0, 1, 0, + 216, 0, 0, 0, 2, 0, 1, 0, + 4, 0, 0, 0, 15, 0, 0, 0, + 0, 0, 1, 0, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 213, 0, 0, 0, 146, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 216, 0, 0, 0, 3, 0, 1, 0, + 228, 0, 0, 0, 2, 0, 1, 0, + 5, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 1, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 225, 0, 0, 0, 154, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 228, 0, 0, 0, 3, 0, 1, 0, + 240, 0, 0, 0, 2, 0, 1, 0, + 6, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 1, 0, 13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 237, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 232, 0, 0, 0, 3, 0, 1, 0, + 4, 1, 0, 0, 2, 0, 1, 0, + 100, 97, 116, 97, 87, 111, 114, 100, + 67, 111, 117, 110, 116, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 111, 105, 110, 116, 101, 114, 67, + 111, 117, 110, 116, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 114, 101, 102, 101, 114, 114, 101, + 100, 76, 105, 115, 116, 69, 110, 99, + 111, 100, 105, 110, 103, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, + 38, 25, 82, 186, 125, 143, 149, 209, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 115, 71, 114, 111, 117, 112, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 105, 115, 99, 114, 105, 109, 105, + 110, 97, 110, 116, 67, 111, 117, 110, + 116, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 105, 115, 99, 114, 105, 109, 105, + 110, 97, 110, 116, 79, 102, 102, 115, + 101, 116, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 102, 105, 101, 108, 100, 115, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 95, 244, 74, 31, 164, 80, 173, 154, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_9ea0b19b37fb4435 = b_9ea0b19b37fb4435.words; +static const ::capnp::_::RawSchema* const d_9ea0b19b37fb4435[] = { + &s_9aad50a41f4af45f, + &s_d1958f7dba521926, + &s_e682ab4cf923a417, +}; +static const uint16_t m_9ea0b19b37fb4435[] = {0, 4, 5, 6, 3, 1, 2}; +static const uint16_t i_9ea0b19b37fb4435[] = {0, 1, 2, 3, 4, 5, 6}; +const ::capnp::_::RawSchema s_9ea0b19b37fb4435 = { + 0x9ea0b19b37fb4435, b_9ea0b19b37fb4435.words, 135, d_9ea0b19b37fb4435, m_9ea0b19b37fb4435, + 3, 7, i_9ea0b19b37fb4435, nullptr, nullptr, { &s_9ea0b19b37fb4435, nullptr, nullptr, 0, 0, nullptr }, true +}; +static const ::capnp::_::AlignedData<37> b_b54ab3364333f598 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 152, 245, 51, 67, 54, 179, 74, 181, + 18, 0, 0, 0, 1, 0, 6, 0, + 23, 164, 35, 249, 76, 171, 130, 230, + 6, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 186, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 63, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 78, 111, 100, + 101, 46, 101, 110, 117, 109, 0, 0, + 4, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 1, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 3, 0, 1, 0, + 40, 0, 0, 0, 2, 0, 1, 0, + 101, 110, 117, 109, 101, 114, 97, 110, + 116, 115, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 77, 154, 84, 220, 235, 124, 138, 151, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_b54ab3364333f598 = b_b54ab3364333f598.words; +static const ::capnp::_::RawSchema* const d_b54ab3364333f598[] = { + &s_978a7cebdc549a4d, + &s_e682ab4cf923a417, +}; +static const uint16_t m_b54ab3364333f598[] = {0}; +static const uint16_t i_b54ab3364333f598[] = {0}; +const ::capnp::_::RawSchema s_b54ab3364333f598 = { + 0xb54ab3364333f598, b_b54ab3364333f598.words, 37, d_b54ab3364333f598, m_b54ab3364333f598, + 2, 1, i_b54ab3364333f598, nullptr, nullptr, { &s_b54ab3364333f598, nullptr, nullptr, 0, 0, nullptr }, true +}; +static const ::capnp::_::AlignedData<57> b_e82753cff0c2218f = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 143, 33, 194, 240, 207, 83, 39, 232, + 18, 0, 0, 0, 1, 0, 6, 0, + 23, 164, 35, 249, 76, 171, 130, 230, + 6, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 226, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 78, 111, 100, + 101, 46, 105, 110, 116, 101, 114, 102, + 97, 99, 101, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 1, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 64, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 1, 0, 31, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 61, 0, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 60, 0, 0, 0, 3, 0, 1, 0, + 88, 0, 0, 0, 2, 0, 1, 0, + 109, 101, 116, 104, 111, 100, 115, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 128, 77, 51, 59, 226, 204, 0, 149, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 117, 112, 101, 114, 99, 108, 97, + 115, 115, 101, 115, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 248, 215, 164, 208, 158, 42, 150, 169, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_e82753cff0c2218f = b_e82753cff0c2218f.words; +static const ::capnp::_::RawSchema* const d_e82753cff0c2218f[] = { + &s_9500cce23b334d80, + &s_a9962a9ed0a4d7f8, + &s_e682ab4cf923a417, +}; +static const uint16_t m_e82753cff0c2218f[] = {0, 1}; +static const uint16_t i_e82753cff0c2218f[] = {0, 1}; +const ::capnp::_::RawSchema s_e82753cff0c2218f = { + 0xe82753cff0c2218f, b_e82753cff0c2218f.words, 57, d_e82753cff0c2218f, m_e82753cff0c2218f, + 3, 2, i_e82753cff0c2218f, nullptr, nullptr, { &s_e82753cff0c2218f, nullptr, nullptr, 0, 0, nullptr }, true +}; +static const ::capnp::_::AlignedData<47> b_b18aa5ac7a0d9420 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 32, 148, 13, 122, 172, 165, 138, 177, + 18, 0, 0, 0, 1, 0, 6, 0, + 23, 164, 35, 249, 76, 171, 130, 230, + 6, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 194, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 78, 111, 100, + 101, 46, 99, 111, 110, 115, 116, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 1, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 1, 0, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 52, 0, 0, 0, 2, 0, 1, 0, + 116, 121, 112, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 96, 204, 249, 225, 237, 120, 115, 208, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 118, 97, 108, 117, 101, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 155, 12, 176, 215, 210, 220, 35, 206, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_b18aa5ac7a0d9420 = b_b18aa5ac7a0d9420.words; +static const ::capnp::_::RawSchema* const d_b18aa5ac7a0d9420[] = { + &s_ce23dcd2d7b00c9b, + &s_d07378ede1f9cc60, + &s_e682ab4cf923a417, +}; +static const uint16_t m_b18aa5ac7a0d9420[] = {0, 1}; +static const uint16_t i_b18aa5ac7a0d9420[] = {0, 1}; +const ::capnp::_::RawSchema s_b18aa5ac7a0d9420 = { + 0xb18aa5ac7a0d9420, b_b18aa5ac7a0d9420.words, 47, d_b18aa5ac7a0d9420, m_b18aa5ac7a0d9420, + 3, 2, i_b18aa5ac7a0d9420, nullptr, nullptr, { &s_b18aa5ac7a0d9420, nullptr, nullptr, 0, 0, nullptr }, true +}; +static const ::capnp::_::AlignedData<228> b_ec1619d4400a0290 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 144, 2, 10, 64, 212, 25, 22, 236, + 18, 0, 0, 0, 1, 0, 6, 0, + 23, 164, 35, 249, 76, 171, 130, 230, + 6, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 234, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 223, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 78, 111, 100, + 101, 46, 97, 110, 110, 111, 116, 97, + 116, 105, 111, 110, 0, 0, 0, 0, + 52, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 1, 0, 18, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 93, 1, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 88, 1, 0, 0, 3, 0, 1, 0, + 100, 1, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 112, 0, 0, 0, + 0, 0, 1, 0, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 1, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 96, 1, 0, 0, 3, 0, 1, 0, + 108, 1, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 113, 0, 0, 0, + 0, 0, 1, 0, 20, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 1, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 104, 1, 0, 0, 3, 0, 1, 0, + 116, 1, 0, 0, 2, 0, 1, 0, + 3, 0, 0, 0, 114, 0, 0, 0, + 0, 0, 1, 0, 21, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 113, 1, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 1, 0, 0, 3, 0, 1, 0, + 124, 1, 0, 0, 2, 0, 1, 0, + 4, 0, 0, 0, 115, 0, 0, 0, + 0, 0, 1, 0, 22, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 121, 1, 0, 0, 138, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 124, 1, 0, 0, 3, 0, 1, 0, + 136, 1, 0, 0, 2, 0, 1, 0, + 5, 0, 0, 0, 116, 0, 0, 0, + 0, 0, 1, 0, 23, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 133, 1, 0, 0, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 132, 1, 0, 0, 3, 0, 1, 0, + 144, 1, 0, 0, 2, 0, 1, 0, + 6, 0, 0, 0, 117, 0, 0, 0, + 0, 0, 1, 0, 24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 141, 1, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 140, 1, 0, 0, 3, 0, 1, 0, + 152, 1, 0, 0, 2, 0, 1, 0, + 7, 0, 0, 0, 118, 0, 0, 0, + 0, 0, 1, 0, 25, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 149, 1, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 148, 1, 0, 0, 3, 0, 1, 0, + 160, 1, 0, 0, 2, 0, 1, 0, + 8, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 1, 0, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 157, 1, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 156, 1, 0, 0, 3, 0, 1, 0, + 168, 1, 0, 0, 2, 0, 1, 0, + 9, 0, 0, 0, 120, 0, 0, 0, + 0, 0, 1, 0, 27, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 165, 1, 0, 0, 138, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 168, 1, 0, 0, 3, 0, 1, 0, + 180, 1, 0, 0, 2, 0, 1, 0, + 10, 0, 0, 0, 121, 0, 0, 0, + 0, 0, 1, 0, 28, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 177, 1, 0, 0, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 176, 1, 0, 0, 3, 0, 1, 0, + 188, 1, 0, 0, 2, 0, 1, 0, + 11, 0, 0, 0, 122, 0, 0, 0, + 0, 0, 1, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 185, 1, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 184, 1, 0, 0, 3, 0, 1, 0, + 196, 1, 0, 0, 2, 0, 1, 0, + 12, 0, 0, 0, 123, 0, 0, 0, + 0, 0, 1, 0, 30, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 193, 1, 0, 0, 146, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 196, 1, 0, 0, 3, 0, 1, 0, + 208, 1, 0, 0, 2, 0, 1, 0, + 116, 121, 112, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 96, 204, 249, 225, 237, 120, 115, 208, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 70, + 105, 108, 101, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 67, + 111, 110, 115, 116, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 69, + 110, 117, 109, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 69, + 110, 117, 109, 101, 114, 97, 110, 116, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 83, + 116, 114, 117, 99, 116, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 70, + 105, 101, 108, 100, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 85, + 110, 105, 111, 110, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 71, + 114, 111, 117, 112, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 73, + 110, 116, 101, 114, 102, 97, 99, 101, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 77, + 101, 116, 104, 111, 100, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 80, + 97, 114, 97, 109, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 97, 114, 103, 101, 116, 115, 65, + 110, 110, 111, 116, 97, 116, 105, 111, + 110, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_ec1619d4400a0290 = b_ec1619d4400a0290.words; +static const ::capnp::_::RawSchema* const d_ec1619d4400a0290[] = { + &s_d07378ede1f9cc60, + &s_e682ab4cf923a417, +}; +static const uint16_t m_ec1619d4400a0290[] = {12, 2, 3, 4, 6, 1, 8, 9, 10, 11, 5, 7, 0}; +static const uint16_t i_ec1619d4400a0290[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; +const ::capnp::_::RawSchema s_ec1619d4400a0290 = { + 0xec1619d4400a0290, b_ec1619d4400a0290.words, 228, d_ec1619d4400a0290, m_ec1619d4400a0290, + 2, 13, i_ec1619d4400a0290, nullptr, nullptr, { &s_ec1619d4400a0290, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<114> b_9aad50a41f4af45f = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 95, 244, 74, 31, 164, 80, 173, 154, + 13, 0, 0, 0, 1, 0, 3, 0, + 217, 114, 76, 98, 9, 197, 63, 169, + 4, 0, 7, 0, 0, 0, 2, 0, + 4, 0, 0, 0, 0, 0, 0, 0, + 179, 27, 0, 0, 196, 36, 0, 0, + 21, 0, 0, 0, 154, 0, 0, 0, + 29, 0, 0, 0, 23, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 143, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 70, 105, 101, + 108, 100, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 1, 0, 1, 0, + 18, 199, 254, 124, 190, 76, 177, 151, + 1, 0, 0, 0, 122, 0, 0, 0, + 110, 111, 68, 105, 115, 99, 114, 105, + 109, 105, 110, 97, 110, 116, 0, 0, + 28, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 181, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 176, 0, 0, 0, 3, 0, 1, 0, + 188, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 185, 0, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 184, 0, 0, 0, 3, 0, 1, 0, + 196, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 193, 0, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 192, 0, 0, 0, 3, 0, 1, 0, + 220, 0, 0, 0, 2, 0, 1, 0, + 3, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 217, 0, 0, 0, 146, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 3, 0, 1, 0, + 232, 0, 0, 0, 2, 0, 1, 0, + 4, 0, 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 111, 116, 180, 107, 71, 5, 35, 196, + 229, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 254, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 17, 29, 219, 104, 219, 205, 252, 202, + 205, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 230, 11, 135, 135, 194, 213, 144, 187, + 181, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 110, 97, 109, 101, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 111, 100, 101, 79, 114, 100, 101, + 114, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 110, 110, 111, 116, 97, 116, 105, + 111, 110, 115, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 66, 117, 37, 171, 13, 149, 200, 241, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 105, 115, 99, 114, 105, 109, 105, + 110, 97, 110, 116, 86, 97, 108, 117, + 101, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 108, 111, 116, 0, 0, 0, 0, + 103, 114, 111, 117, 112, 0, 0, 0, + 111, 114, 100, 105, 110, 97, 108, 0, } +}; +::capnp::word const* const bp_9aad50a41f4af45f = b_9aad50a41f4af45f.words; +static const ::capnp::_::RawSchema* const d_9aad50a41f4af45f[] = { + &s_bb90d5c287870be6, + &s_c42305476bb4746f, + &s_cafccddb68db1d11, + &s_f1c8950dab257542, +}; +static const uint16_t m_9aad50a41f4af45f[] = {2, 1, 3, 5, 0, 6, 4}; +static const uint16_t i_9aad50a41f4af45f[] = {4, 5, 0, 1, 2, 3, 6}; +const ::capnp::_::RawSchema s_9aad50a41f4af45f = { + 0x9aad50a41f4af45f, b_9aad50a41f4af45f.words, 114, d_9aad50a41f4af45f, m_9aad50a41f4af45f, + 4, 7, i_9aad50a41f4af45f, nullptr, nullptr, { &s_9aad50a41f4af45f, nullptr, nullptr, 0, 0, nullptr }, true +}; +static const ::capnp::_::AlignedData<26> b_97b14cbe7cfec712 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 18, 199, 254, 124, 190, 76, 177, 151, + 19, 0, 0, 0, 4, 0, 0, 0, + 95, 244, 74, 31, 164, 80, 173, 154, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 95, 30, 0, 0, 133, 30, 0, 0, + 21, 0, 0, 0, 18, 1, 0, 0, + 37, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 32, 0, 0, 0, 3, 0, 1, 0, + 44, 0, 0, 0, 2, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 70, 105, 101, + 108, 100, 46, 110, 111, 68, 105, 115, + 99, 114, 105, 109, 105, 110, 97, 110, + 116, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_97b14cbe7cfec712 = b_97b14cbe7cfec712.words; +const ::capnp::_::RawSchema s_97b14cbe7cfec712 = { + 0x97b14cbe7cfec712, b_97b14cbe7cfec712.words, 26, nullptr, nullptr, + 0, 0, nullptr, nullptr, nullptr, { &s_97b14cbe7cfec712, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<80> b_c42305476bb4746f = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 111, 116, 180, 107, 71, 5, 35, 196, + 19, 0, 0, 0, 1, 0, 3, 0, + 95, 244, 74, 31, 164, 80, 173, 154, + 4, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 194, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 231, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 70, 105, 101, + 108, 100, 46, 115, 108, 111, 116, 0, + 16, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 92, 0, 0, 0, 3, 0, 1, 0, + 104, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 96, 0, 0, 0, 3, 0, 1, 0, + 108, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 1, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 0, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 104, 0, 0, 0, 3, 0, 1, 0, + 116, 0, 0, 0, 2, 0, 1, 0, + 3, 0, 0, 0, 128, 0, 0, 0, + 0, 0, 1, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 113, 0, 0, 0, 154, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 0, 0, 0, 3, 0, 1, 0, + 128, 0, 0, 0, 2, 0, 1, 0, + 111, 102, 102, 115, 101, 116, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 121, 112, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 96, 204, 249, 225, 237, 120, 115, 208, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 101, 102, 97, 117, 108, 116, 86, + 97, 108, 117, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 155, 12, 176, 215, 210, 220, 35, 206, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 104, 97, 100, 69, 120, 112, 108, 105, + 99, 105, 116, 68, 101, 102, 97, 117, + 108, 116, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_c42305476bb4746f = b_c42305476bb4746f.words; +static const ::capnp::_::RawSchema* const d_c42305476bb4746f[] = { + &s_9aad50a41f4af45f, + &s_ce23dcd2d7b00c9b, + &s_d07378ede1f9cc60, +}; +static const uint16_t m_c42305476bb4746f[] = {2, 3, 0, 1}; +static const uint16_t i_c42305476bb4746f[] = {0, 1, 2, 3}; +const ::capnp::_::RawSchema s_c42305476bb4746f = { + 0xc42305476bb4746f, b_c42305476bb4746f.words, 80, d_c42305476bb4746f, m_c42305476bb4746f, + 3, 4, i_c42305476bb4746f, nullptr, nullptr, { &s_c42305476bb4746f, nullptr, nullptr, 0, 0, nullptr }, true +}; +static const ::capnp::_::AlignedData<33> b_cafccddb68db1d11 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 17, 29, 219, 104, 219, 205, 252, 202, + 19, 0, 0, 0, 1, 0, 3, 0, + 95, 244, 74, 31, 164, 80, 173, 154, + 4, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 202, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 63, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 70, 105, 101, + 108, 100, 46, 103, 114, 111, 117, 112, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 3, 0, 1, 0, + 20, 0, 0, 0, 2, 0, 1, 0, + 116, 121, 112, 101, 73, 100, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_cafccddb68db1d11 = b_cafccddb68db1d11.words; +static const ::capnp::_::RawSchema* const d_cafccddb68db1d11[] = { + &s_9aad50a41f4af45f, +}; +static const uint16_t m_cafccddb68db1d11[] = {0}; +static const uint16_t i_cafccddb68db1d11[] = {0}; +const ::capnp::_::RawSchema s_cafccddb68db1d11 = { + 0xcafccddb68db1d11, b_cafccddb68db1d11.words, 33, d_cafccddb68db1d11, m_cafccddb68db1d11, + 1, 1, i_cafccddb68db1d11, nullptr, nullptr, { &s_cafccddb68db1d11, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<50> b_bb90d5c287870be6 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 230, 11, 135, 135, 194, 213, 144, 187, + 19, 0, 0, 0, 1, 0, 3, 0, + 95, 244, 74, 31, 164, 80, 173, 154, + 4, 0, 7, 0, 1, 0, 2, 0, + 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 218, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 70, 105, 101, + 108, 100, 46, 111, 114, 100, 105, 110, + 97, 108, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 74, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 52, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 254, 255, 6, 0, 0, 0, + 0, 0, 1, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 49, 0, 0, 0, 74, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 3, 0, 1, 0, + 60, 0, 0, 0, 2, 0, 1, 0, + 105, 109, 112, 108, 105, 99, 105, 116, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 120, 112, 108, 105, 99, 105, 116, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_bb90d5c287870be6 = b_bb90d5c287870be6.words; +static const ::capnp::_::RawSchema* const d_bb90d5c287870be6[] = { + &s_9aad50a41f4af45f, +}; +static const uint16_t m_bb90d5c287870be6[] = {1, 0}; +static const uint16_t i_bb90d5c287870be6[] = {0, 1}; +const ::capnp::_::RawSchema s_bb90d5c287870be6 = { + 0xbb90d5c287870be6, b_bb90d5c287870be6.words, 50, d_bb90d5c287870be6, m_bb90d5c287870be6, + 1, 2, i_bb90d5c287870be6, nullptr, nullptr, { &s_bb90d5c287870be6, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<69> b_978a7cebdc549a4d = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 77, 154, 84, 220, 235, 124, 138, 151, + 13, 0, 0, 0, 1, 0, 1, 0, + 217, 114, 76, 98, 9, 197, 63, 169, + 2, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 198, 36, 0, 0, 180, 37, 0, 0, + 21, 0, 0, 0, 186, 0, 0, 0, + 29, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 69, 110, 117, + 109, 101, 114, 97, 110, 116, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 12, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 69, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 3, 0, 1, 0, + 76, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 73, 0, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 72, 0, 0, 0, 3, 0, 1, 0, + 84, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 81, 0, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 80, 0, 0, 0, 3, 0, 1, 0, + 108, 0, 0, 0, 2, 0, 1, 0, + 110, 97, 109, 101, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 111, 100, 101, 79, 114, 100, 101, + 114, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 110, 110, 111, 116, 97, 116, 105, + 111, 110, 115, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 66, 117, 37, 171, 13, 149, 200, 241, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_978a7cebdc549a4d = b_978a7cebdc549a4d.words; +static const ::capnp::_::RawSchema* const d_978a7cebdc549a4d[] = { + &s_f1c8950dab257542, +}; +static const uint16_t m_978a7cebdc549a4d[] = {2, 1, 0}; +static const uint16_t i_978a7cebdc549a4d[] = {0, 1, 2}; +const ::capnp::_::RawSchema s_978a7cebdc549a4d = { + 0x978a7cebdc549a4d, b_978a7cebdc549a4d.words, 69, d_978a7cebdc549a4d, m_978a7cebdc549a4d, + 1, 3, i_978a7cebdc549a4d, nullptr, nullptr, { &s_978a7cebdc549a4d, nullptr, nullptr, 0, 0, nullptr }, true +}; +static const ::capnp::_::AlignedData<48> b_a9962a9ed0a4d7f8 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 248, 215, 164, 208, 158, 42, 150, 169, + 13, 0, 0, 0, 1, 0, 1, 0, + 217, 114, 76, 98, 9, 197, 63, 169, + 1, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 182, 37, 0, 0, 235, 37, 0, 0, + 21, 0, 0, 0, 194, 0, 0, 0, + 29, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 83, 117, 112, + 101, 114, 99, 108, 97, 115, 115, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 52, 0, 0, 0, 2, 0, 1, 0, + 105, 100, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 114, 97, 110, 100, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 43, 66, 101, 96, 240, 85, 52, 144, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_a9962a9ed0a4d7f8 = b_a9962a9ed0a4d7f8.words; +static const ::capnp::_::RawSchema* const d_a9962a9ed0a4d7f8[] = { + &s_903455f06065422b, +}; +static const uint16_t m_a9962a9ed0a4d7f8[] = {1, 0}; +static const uint16_t i_a9962a9ed0a4d7f8[] = {0, 1}; +const ::capnp::_::RawSchema s_a9962a9ed0a4d7f8 = { + 0xa9962a9ed0a4d7f8, b_a9962a9ed0a4d7f8.words, 48, d_a9962a9ed0a4d7f8, m_a9962a9ed0a4d7f8, + 1, 2, i_a9962a9ed0a4d7f8, nullptr, nullptr, { &s_a9962a9ed0a4d7f8, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<155> b_9500cce23b334d80 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 128, 77, 51, 59, 226, 204, 0, 149, + 13, 0, 0, 0, 1, 0, 3, 0, + 217, 114, 76, 98, 9, 197, 63, 169, + 5, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 237, 37, 0, 0, 58, 43, 0, 0, + 21, 0, 0, 0, 162, 0, 0, 0, + 29, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 199, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 77, 101, 116, + 104, 111, 100, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 32, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 209, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 204, 0, 0, 0, 3, 0, 1, 0, + 216, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 213, 0, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 212, 0, 0, 0, 3, 0, 1, 0, + 224, 0, 0, 0, 2, 0, 1, 0, + 3, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 221, 0, 0, 0, 130, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 3, 0, 1, 0, + 232, 0, 0, 0, 2, 0, 1, 0, + 5, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 229, 0, 0, 0, 138, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 232, 0, 0, 0, 3, 0, 1, 0, + 244, 0, 0, 0, 2, 0, 1, 0, + 7, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 241, 0, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 240, 0, 0, 0, 3, 0, 1, 0, + 12, 1, 0, 0, 2, 0, 1, 0, + 4, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 1, 0, 0, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 1, 0, 0, 3, 0, 1, 0, + 20, 1, 0, 0, 2, 0, 1, 0, + 6, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 1, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 1, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 1, 0, 0, 3, 0, 1, 0, + 28, 1, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 1, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 1, 0, 0, 154, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 28, 1, 0, 0, 3, 0, 1, 0, + 56, 1, 0, 0, 2, 0, 1, 0, + 110, 97, 109, 101, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 111, 100, 101, 79, 114, 100, 101, + 114, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 97, 114, 97, 109, 83, 116, 114, + 117, 99, 116, 84, 121, 112, 101, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 114, 101, 115, 117, 108, 116, 83, 116, + 114, 117, 99, 116, 84, 121, 112, 101, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 110, 110, 111, 116, 97, 116, 105, + 111, 110, 115, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 66, 117, 37, 171, 13, 149, 200, 241, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 97, 114, 97, 109, 66, 114, 97, + 110, 100, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 43, 66, 101, 96, 240, 85, 52, 144, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 114, 101, 115, 117, 108, 116, 66, 114, + 97, 110, 100, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 43, 66, 101, 96, 240, 85, 52, 144, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 109, 112, 108, 105, 99, 105, 116, + 80, 97, 114, 97, 109, 101, 116, 101, + 114, 115, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 177, 163, 15, 241, 204, 27, 82, 185, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_9500cce23b334d80 = b_9500cce23b334d80.words; +static const ::capnp::_::RawSchema* const d_9500cce23b334d80[] = { + &s_903455f06065422b, + &s_b9521bccf10fa3b1, + &s_f1c8950dab257542, +}; +static const uint16_t m_9500cce23b334d80[] = {4, 1, 7, 0, 5, 2, 6, 3}; +static const uint16_t i_9500cce23b334d80[] = {0, 1, 2, 3, 4, 5, 6, 7}; +const ::capnp::_::RawSchema s_9500cce23b334d80 = { + 0x9500cce23b334d80, b_9500cce23b334d80.words, 155, d_9500cce23b334d80, m_9500cce23b334d80, + 3, 8, i_9500cce23b334d80, nullptr, nullptr, { &s_9500cce23b334d80, nullptr, nullptr, 0, 0, nullptr }, true +}; +static const ::capnp::_::AlignedData<270> b_d07378ede1f9cc60 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 96, 204, 249, 225, 237, 120, 115, 208, + 13, 0, 0, 0, 1, 0, 3, 0, + 217, 114, 76, 98, 9, 197, 63, 169, + 1, 0, 7, 0, 0, 0, 19, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 60, 43, 0, 0, 183, 50, 0, 0, + 21, 0, 0, 0, 146, 0, 0, 0, + 29, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 47, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 84, 121, 112, + 101, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 76, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 3, 0, 1, 0, + 12, 2, 0, 0, 2, 0, 1, 0, + 1, 0, 254, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 2, 0, 0, 3, 0, 1, 0, + 16, 2, 0, 0, 2, 0, 1, 0, + 2, 0, 253, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 2, 0, 0, 3, 0, 1, 0, + 20, 2, 0, 0, 2, 0, 1, 0, + 3, 0, 252, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 2, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 2, 0, 0, 3, 0, 1, 0, + 24, 2, 0, 0, 2, 0, 1, 0, + 4, 0, 251, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 2, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 2, 0, 0, 3, 0, 1, 0, + 28, 2, 0, 0, 2, 0, 1, 0, + 5, 0, 250, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 2, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 20, 2, 0, 0, 3, 0, 1, 0, + 32, 2, 0, 0, 2, 0, 1, 0, + 6, 0, 249, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 29, 2, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 24, 2, 0, 0, 3, 0, 1, 0, + 36, 2, 0, 0, 2, 0, 1, 0, + 7, 0, 248, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 33, 2, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 28, 2, 0, 0, 3, 0, 1, 0, + 40, 2, 0, 0, 2, 0, 1, 0, + 8, 0, 247, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 37, 2, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 32, 2, 0, 0, 3, 0, 1, 0, + 44, 2, 0, 0, 2, 0, 1, 0, + 9, 0, 246, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 2, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 2, 0, 0, 3, 0, 1, 0, + 48, 2, 0, 0, 2, 0, 1, 0, + 10, 0, 245, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 2, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 2, 0, 0, 3, 0, 1, 0, + 52, 2, 0, 0, 2, 0, 1, 0, + 11, 0, 244, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 49, 2, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 44, 2, 0, 0, 3, 0, 1, 0, + 56, 2, 0, 0, 2, 0, 1, 0, + 12, 0, 243, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 53, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 48, 2, 0, 0, 3, 0, 1, 0, + 60, 2, 0, 0, 2, 0, 1, 0, + 13, 0, 242, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 57, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 52, 2, 0, 0, 3, 0, 1, 0, + 64, 2, 0, 0, 2, 0, 1, 0, + 14, 0, 241, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 151, 234, 96, 10, 37, 57, 231, 135, + 61, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 15, 0, 240, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 169, 135, 127, 26, 113, 120, 14, 158, + 37, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 239, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 211, 198, 76, 239, 96, 111, 58, 172, + 13, 2, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 0, 238, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 191, 12, 251, 247, 105, 202, 139, 237, + 245, 1, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 18, 0, 237, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 241, 73, 62, 162, 232, 63, 87, 194, + 225, 1, 0, 0, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 118, 111, 105, 100, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 111, 111, 108, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 110, 116, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 110, 116, 49, 54, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 110, 116, 51, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 110, 116, 54, 52, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 117, 105, 110, 116, 56, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 117, 105, 110, 116, 49, 54, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 117, 105, 110, 116, 51, 50, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 117, 105, 110, 116, 54, 52, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 102, 108, 111, 97, 116, 51, 50, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 102, 108, 111, 97, 116, 54, 52, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 101, 120, 116, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 97, 116, 97, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 108, 105, 115, 116, 0, 0, 0, 0, + 101, 110, 117, 109, 0, 0, 0, 0, + 115, 116, 114, 117, 99, 116, 0, 0, + 105, 110, 116, 101, 114, 102, 97, 99, + 101, 0, 0, 0, 0, 0, 0, 0, + 97, 110, 121, 80, 111, 105, 110, 116, + 101, 114, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_d07378ede1f9cc60 = b_d07378ede1f9cc60.words; +static const ::capnp::_::RawSchema* const d_d07378ede1f9cc60[] = { + &s_87e739250a60ea97, + &s_9e0e78711a7f87a9, + &s_ac3a6f60ef4cc6d3, + &s_c2573fe8a23e49f1, + &s_ed8bca69f7fb0cbf, +}; +static const uint16_t m_d07378ede1f9cc60[] = {18, 1, 13, 15, 10, 11, 3, 4, 5, 2, 17, 14, 16, 12, 7, 8, 9, 6, 0}; +static const uint16_t i_d07378ede1f9cc60[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}; +const ::capnp::_::RawSchema s_d07378ede1f9cc60 = { + 0xd07378ede1f9cc60, b_d07378ede1f9cc60.words, 270, d_d07378ede1f9cc60, m_d07378ede1f9cc60, + 5, 19, i_d07378ede1f9cc60, nullptr, nullptr, { &s_d07378ede1f9cc60, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<33> b_87e739250a60ea97 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 151, 234, 96, 10, 37, 57, 231, 135, + 18, 0, 0, 0, 1, 0, 3, 0, + 96, 204, 249, 225, 237, 120, 115, 208, + 1, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 186, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 63, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 84, 121, 112, + 101, 46, 108, 105, 115, 116, 0, 0, + 4, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 3, 0, 1, 0, + 24, 0, 0, 0, 2, 0, 1, 0, + 101, 108, 101, 109, 101, 110, 116, 84, + 121, 112, 101, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 96, 204, 249, 225, 237, 120, 115, 208, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_87e739250a60ea97 = b_87e739250a60ea97.words; +static const ::capnp::_::RawSchema* const d_87e739250a60ea97[] = { + &s_d07378ede1f9cc60, +}; +static const uint16_t m_87e739250a60ea97[] = {0}; +static const uint16_t i_87e739250a60ea97[] = {0}; +const ::capnp::_::RawSchema s_87e739250a60ea97 = { + 0x87e739250a60ea97, b_87e739250a60ea97.words, 33, d_87e739250a60ea97, m_87e739250a60ea97, + 1, 1, i_87e739250a60ea97, nullptr, nullptr, { &s_87e739250a60ea97, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<47> b_9e0e78711a7f87a9 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 169, 135, 127, 26, 113, 120, 14, 158, + 18, 0, 0, 0, 1, 0, 3, 0, + 96, 204, 249, 225, 237, 120, 115, 208, + 1, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 186, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 84, 121, 112, + 101, 46, 101, 110, 117, 109, 0, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 21, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 52, 0, 0, 0, 2, 0, 1, 0, + 116, 121, 112, 101, 73, 100, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 114, 97, 110, 100, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 43, 66, 101, 96, 240, 85, 52, 144, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_9e0e78711a7f87a9 = b_9e0e78711a7f87a9.words; +static const ::capnp::_::RawSchema* const d_9e0e78711a7f87a9[] = { + &s_903455f06065422b, + &s_d07378ede1f9cc60, +}; +static const uint16_t m_9e0e78711a7f87a9[] = {1, 0}; +static const uint16_t i_9e0e78711a7f87a9[] = {0, 1}; +const ::capnp::_::RawSchema s_9e0e78711a7f87a9 = { + 0x9e0e78711a7f87a9, b_9e0e78711a7f87a9.words, 47, d_9e0e78711a7f87a9, m_9e0e78711a7f87a9, + 2, 2, i_9e0e78711a7f87a9, nullptr, nullptr, { &s_9e0e78711a7f87a9, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<48> b_ac3a6f60ef4cc6d3 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 211, 198, 76, 239, 96, 111, 58, 172, + 18, 0, 0, 0, 1, 0, 3, 0, + 96, 204, 249, 225, 237, 120, 115, 208, + 1, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 202, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 84, 121, 112, + 101, 46, 115, 116, 114, 117, 99, 116, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 22, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 52, 0, 0, 0, 2, 0, 1, 0, + 116, 121, 112, 101, 73, 100, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 114, 97, 110, 100, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 43, 66, 101, 96, 240, 85, 52, 144, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_ac3a6f60ef4cc6d3 = b_ac3a6f60ef4cc6d3.words; +static const ::capnp::_::RawSchema* const d_ac3a6f60ef4cc6d3[] = { + &s_903455f06065422b, + &s_d07378ede1f9cc60, +}; +static const uint16_t m_ac3a6f60ef4cc6d3[] = {1, 0}; +static const uint16_t i_ac3a6f60ef4cc6d3[] = {0, 1}; +const ::capnp::_::RawSchema s_ac3a6f60ef4cc6d3 = { + 0xac3a6f60ef4cc6d3, b_ac3a6f60ef4cc6d3.words, 48, d_ac3a6f60ef4cc6d3, m_ac3a6f60ef4cc6d3, + 2, 2, i_ac3a6f60ef4cc6d3, nullptr, nullptr, { &s_ac3a6f60ef4cc6d3, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<48> b_ed8bca69f7fb0cbf = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 191, 12, 251, 247, 105, 202, 139, 237, + 18, 0, 0, 0, 1, 0, 3, 0, + 96, 204, 249, 225, 237, 120, 115, 208, + 1, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 226, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 84, 121, 112, + 101, 46, 105, 110, 116, 101, 114, 102, + 97, 99, 101, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 23, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 52, 0, 0, 0, 2, 0, 1, 0, + 116, 121, 112, 101, 73, 100, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 114, 97, 110, 100, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 43, 66, 101, 96, 240, 85, 52, 144, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_ed8bca69f7fb0cbf = b_ed8bca69f7fb0cbf.words; +static const ::capnp::_::RawSchema* const d_ed8bca69f7fb0cbf[] = { + &s_903455f06065422b, + &s_d07378ede1f9cc60, +}; +static const uint16_t m_ed8bca69f7fb0cbf[] = {1, 0}; +static const uint16_t i_ed8bca69f7fb0cbf[] = {0, 1}; +const ::capnp::_::RawSchema s_ed8bca69f7fb0cbf = { + 0xed8bca69f7fb0cbf, b_ed8bca69f7fb0cbf.words, 48, d_ed8bca69f7fb0cbf, m_ed8bca69f7fb0cbf, + 2, 2, i_ed8bca69f7fb0cbf, nullptr, nullptr, { &s_ed8bca69f7fb0cbf, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<46> b_c2573fe8a23e49f1 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 241, 73, 62, 162, 232, 63, 87, 194, + 18, 0, 0, 0, 1, 0, 3, 0, + 96, 204, 249, 225, 237, 120, 115, 208, + 1, 0, 7, 0, 1, 0, 3, 0, + 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 234, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 84, 121, 112, + 101, 46, 97, 110, 121, 80, 111, 105, + 110, 116, 101, 114, 0, 0, 0, 0, + 12, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 86, 54, 89, 254, 121, 95, 59, 142, + 69, 0, 0, 0, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 254, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 133, 74, 97, 244, 36, 247, 209, 157, + 49, 0, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 253, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 116, 226, 86, 12, 18, 201, 239, 186, + 29, 0, 0, 0, 194, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 117, 110, 99, 111, 110, 115, 116, 114, + 97, 105, 110, 101, 100, 0, 0, 0, + 112, 97, 114, 97, 109, 101, 116, 101, + 114, 0, 0, 0, 0, 0, 0, 0, + 105, 109, 112, 108, 105, 99, 105, 116, + 77, 101, 116, 104, 111, 100, 80, 97, + 114, 97, 109, 101, 116, 101, 114, 0, } +}; +::capnp::word const* const bp_c2573fe8a23e49f1 = b_c2573fe8a23e49f1.words; +static const ::capnp::_::RawSchema* const d_c2573fe8a23e49f1[] = { + &s_8e3b5f79fe593656, + &s_9dd1f724f4614a85, + &s_baefc9120c56e274, + &s_d07378ede1f9cc60, +}; +static const uint16_t m_c2573fe8a23e49f1[] = {2, 1, 0}; +static const uint16_t i_c2573fe8a23e49f1[] = {0, 1, 2}; +const ::capnp::_::RawSchema s_c2573fe8a23e49f1 = { + 0xc2573fe8a23e49f1, b_c2573fe8a23e49f1.words, 46, d_c2573fe8a23e49f1, m_c2573fe8a23e49f1, + 4, 3, i_c2573fe8a23e49f1, nullptr, nullptr, { &s_c2573fe8a23e49f1, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<81> b_8e3b5f79fe593656 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 86, 54, 89, 254, 121, 95, 59, 142, + 29, 0, 0, 0, 1, 0, 3, 0, + 241, 73, 62, 162, 232, 63, 87, 194, + 1, 0, 7, 0, 1, 0, 4, 0, + 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 90, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 231, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 84, 121, 112, + 101, 46, 97, 110, 121, 80, 111, 105, + 110, 116, 101, 114, 46, 117, 110, 99, + 111, 110, 115, 116, 114, 97, 105, 110, + 101, 100, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 18, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 92, 0, 0, 0, 3, 0, 1, 0, + 104, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 254, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 25, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 96, 0, 0, 0, 3, 0, 1, 0, + 108, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 253, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 0, 0, 0, 3, 0, 1, 0, + 112, 0, 0, 0, 2, 0, 1, 0, + 3, 0, 252, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 27, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 109, 0, 0, 0, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 108, 0, 0, 0, 3, 0, 1, 0, + 120, 0, 0, 0, 2, 0, 1, 0, + 97, 110, 121, 75, 105, 110, 100, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 114, 117, 99, 116, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 108, 105, 115, 116, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 97, 112, 97, 98, 105, 108, 105, + 116, 121, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_8e3b5f79fe593656 = b_8e3b5f79fe593656.words; +static const ::capnp::_::RawSchema* const d_8e3b5f79fe593656[] = { + &s_c2573fe8a23e49f1, +}; +static const uint16_t m_8e3b5f79fe593656[] = {0, 3, 2, 1}; +static const uint16_t i_8e3b5f79fe593656[] = {0, 1, 2, 3}; +const ::capnp::_::RawSchema s_8e3b5f79fe593656 = { + 0x8e3b5f79fe593656, b_8e3b5f79fe593656.words, 81, d_8e3b5f79fe593656, m_8e3b5f79fe593656, + 1, 4, i_8e3b5f79fe593656, nullptr, nullptr, { &s_8e3b5f79fe593656, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<50> b_9dd1f724f4614a85 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 133, 74, 97, 244, 36, 247, 209, 157, + 29, 0, 0, 0, 1, 0, 3, 0, + 241, 73, 62, 162, 232, 63, 87, 194, + 1, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 58, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 29, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 84, 121, 112, + 101, 46, 97, 110, 121, 80, 111, 105, + 110, 116, 101, 114, 46, 112, 97, 114, + 97, 109, 101, 116, 101, 114, 0, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 1, 0, 20, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 122, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 44, 0, 0, 0, 3, 0, 1, 0, + 56, 0, 0, 0, 2, 0, 1, 0, + 115, 99, 111, 112, 101, 73, 100, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 97, 114, 97, 109, 101, 116, 101, + 114, 73, 110, 100, 101, 120, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_9dd1f724f4614a85 = b_9dd1f724f4614a85.words; +static const ::capnp::_::RawSchema* const d_9dd1f724f4614a85[] = { + &s_c2573fe8a23e49f1, +}; +static const uint16_t m_9dd1f724f4614a85[] = {1, 0}; +static const uint16_t i_9dd1f724f4614a85[] = {0, 1}; +const ::capnp::_::RawSchema s_9dd1f724f4614a85 = { + 0x9dd1f724f4614a85, b_9dd1f724f4614a85.words, 50, d_9dd1f724f4614a85, m_9dd1f724f4614a85, + 1, 2, i_9dd1f724f4614a85, nullptr, nullptr, { &s_9dd1f724f4614a85, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<37> b_baefc9120c56e274 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 116, 226, 86, 12, 18, 201, 239, 186, + 29, 0, 0, 0, 1, 0, 3, 0, + 241, 73, 62, 162, 232, 63, 87, 194, + 1, 0, 7, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 170, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 37, 0, 0, 0, 63, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 84, 121, 112, + 101, 46, 97, 110, 121, 80, 111, 105, + 110, 116, 101, 114, 46, 105, 109, 112, + 108, 105, 99, 105, 116, 77, 101, 116, + 104, 111, 100, 80, 97, 114, 97, 109, + 101, 116, 101, 114, 0, 0, 0, 0, + 4, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 1, 0, 24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 122, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 3, 0, 1, 0, + 24, 0, 0, 0, 2, 0, 1, 0, + 112, 97, 114, 97, 109, 101, 116, 101, + 114, 73, 110, 100, 101, 120, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_baefc9120c56e274 = b_baefc9120c56e274.words; +static const ::capnp::_::RawSchema* const d_baefc9120c56e274[] = { + &s_c2573fe8a23e49f1, +}; +static const uint16_t m_baefc9120c56e274[] = {0}; +static const uint16_t i_baefc9120c56e274[] = {0}; +const ::capnp::_::RawSchema s_baefc9120c56e274 = { + 0xbaefc9120c56e274, b_baefc9120c56e274.words, 37, d_baefc9120c56e274, m_baefc9120c56e274, + 1, 1, i_baefc9120c56e274, nullptr, nullptr, { &s_baefc9120c56e274, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<43> b_903455f06065422b = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 43, 66, 101, 96, 240, 85, 52, 144, + 13, 0, 0, 0, 1, 0, 0, 0, + 217, 114, 76, 98, 9, 197, 63, 169, + 1, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 185, 50, 0, 0, 175, 56, 0, 0, + 21, 0, 0, 0, 154, 0, 0, 0, + 29, 0, 0, 0, 39, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 49, 0, 0, 0, 63, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 66, 114, 97, + 110, 100, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 1, 0, 1, 0, + 201, 107, 99, 169, 133, 52, 215, 171, + 9, 0, 0, 0, 50, 0, 0, 0, + 252, 231, 158, 150, 22, 205, 99, 200, + 5, 0, 0, 0, 66, 0, 0, 0, + 83, 99, 111, 112, 101, 0, 0, 0, + 66, 105, 110, 100, 105, 110, 103, 0, + 4, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 3, 0, 1, 0, + 36, 0, 0, 0, 2, 0, 1, 0, + 115, 99, 111, 112, 101, 115, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 201, 107, 99, 169, 133, 52, 215, 171, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_903455f06065422b = b_903455f06065422b.words; +static const ::capnp::_::RawSchema* const d_903455f06065422b[] = { + &s_abd73485a9636bc9, +}; +static const uint16_t m_903455f06065422b[] = {0}; +static const uint16_t i_903455f06065422b[] = {0}; +const ::capnp::_::RawSchema s_903455f06065422b = { + 0x903455f06065422b, b_903455f06065422b.words, 43, d_903455f06065422b, m_903455f06065422b, + 1, 1, i_903455f06065422b, nullptr, nullptr, { &s_903455f06065422b, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<68> b_abd73485a9636bc9 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 201, 107, 99, 169, 133, 52, 215, 171, + 19, 0, 0, 0, 1, 0, 2, 0, + 43, 66, 101, 96, 240, 85, 52, 144, + 1, 0, 7, 0, 0, 0, 2, 0, + 4, 0, 0, 0, 0, 0, 0, 0, + 141, 52, 0, 0, 17, 56, 0, 0, + 21, 0, 0, 0, 202, 0, 0, 0, + 33, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 29, 0, 0, 0, 175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 66, 114, 97, + 110, 100, 46, 83, 99, 111, 112, 101, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 12, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 69, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 3, 0, 1, 0, + 76, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 73, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 68, 0, 0, 0, 3, 0, 1, 0, + 96, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 254, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 93, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 88, 0, 0, 0, 3, 0, 1, 0, + 100, 0, 0, 0, 2, 0, 1, 0, + 115, 99, 111, 112, 101, 73, 100, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 105, 110, 100, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 252, 231, 158, 150, 22, 205, 99, 200, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 110, 104, 101, 114, 105, 116, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_abd73485a9636bc9 = b_abd73485a9636bc9.words; +static const ::capnp::_::RawSchema* const d_abd73485a9636bc9[] = { + &s_c863cd16969ee7fc, +}; +static const uint16_t m_abd73485a9636bc9[] = {1, 2, 0}; +static const uint16_t i_abd73485a9636bc9[] = {1, 2, 0}; +const ::capnp::_::RawSchema s_abd73485a9636bc9 = { + 0xabd73485a9636bc9, b_abd73485a9636bc9.words, 68, d_abd73485a9636bc9, m_abd73485a9636bc9, + 1, 3, i_abd73485a9636bc9, nullptr, nullptr, { &s_abd73485a9636bc9, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<49> b_c863cd16969ee7fc = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 252, 231, 158, 150, 22, 205, 99, 200, + 19, 0, 0, 0, 1, 0, 1, 0, + 43, 66, 101, 96, 240, 85, 52, 144, + 1, 0, 7, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 56, 0, 0, 173, 56, 0, 0, + 21, 0, 0, 0, 218, 0, 0, 0, + 33, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 29, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 66, 114, 97, + 110, 100, 46, 66, 105, 110, 100, 105, + 110, 103, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 254, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 3, 0, 1, 0, + 52, 0, 0, 0, 2, 0, 1, 0, + 117, 110, 98, 111, 117, 110, 100, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 121, 112, 101, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 96, 204, 249, 225, 237, 120, 115, 208, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_c863cd16969ee7fc = b_c863cd16969ee7fc.words; +static const ::capnp::_::RawSchema* const d_c863cd16969ee7fc[] = { + &s_d07378ede1f9cc60, +}; +static const uint16_t m_c863cd16969ee7fc[] = {1, 0}; +static const uint16_t i_c863cd16969ee7fc[] = {0, 1}; +const ::capnp::_::RawSchema s_c863cd16969ee7fc = { + 0xc863cd16969ee7fc, b_c863cd16969ee7fc.words, 49, d_c863cd16969ee7fc, m_c863cd16969ee7fc, + 1, 2, i_c863cd16969ee7fc, nullptr, nullptr, { &s_c863cd16969ee7fc, nullptr, nullptr, 0, 0, nullptr }, false +}; +static const ::capnp::_::AlignedData<305> b_ce23dcd2d7b00c9b = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 155, 12, 176, 215, 210, 220, 35, 206, + 13, 0, 0, 0, 1, 0, 2, 0, + 217, 114, 76, 98, 9, 197, 63, 169, + 1, 0, 7, 0, 0, 0, 19, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 177, 56, 0, 0, 145, 59, 0, 0, + 21, 0, 0, 0, 154, 0, 0, 0, + 29, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 47, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 86, 97, 108, + 117, 101, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 76, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 3, 0, 1, 0, + 12, 2, 0, 0, 2, 0, 1, 0, + 1, 0, 254, 255, 16, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 2, 0, 0, 3, 0, 1, 0, + 16, 2, 0, 0, 2, 0, 1, 0, + 2, 0, 253, 255, 2, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 2, 0, 0, 3, 0, 1, 0, + 20, 2, 0, 0, 2, 0, 1, 0, + 3, 0, 252, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 2, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 2, 0, 0, 3, 0, 1, 0, + 24, 2, 0, 0, 2, 0, 1, 0, + 4, 0, 251, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 2, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 2, 0, 0, 3, 0, 1, 0, + 28, 2, 0, 0, 2, 0, 1, 0, + 5, 0, 250, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 2, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 20, 2, 0, 0, 3, 0, 1, 0, + 32, 2, 0, 0, 2, 0, 1, 0, + 6, 0, 249, 255, 2, 0, 0, 0, + 0, 0, 1, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 29, 2, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 24, 2, 0, 0, 3, 0, 1, 0, + 36, 2, 0, 0, 2, 0, 1, 0, + 7, 0, 248, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 33, 2, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 28, 2, 0, 0, 3, 0, 1, 0, + 40, 2, 0, 0, 2, 0, 1, 0, + 8, 0, 247, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 37, 2, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 32, 2, 0, 0, 3, 0, 1, 0, + 44, 2, 0, 0, 2, 0, 1, 0, + 9, 0, 246, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 2, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 2, 0, 0, 3, 0, 1, 0, + 48, 2, 0, 0, 2, 0, 1, 0, + 10, 0, 245, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 2, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 40, 2, 0, 0, 3, 0, 1, 0, + 52, 2, 0, 0, 2, 0, 1, 0, + 11, 0, 244, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 49, 2, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 44, 2, 0, 0, 3, 0, 1, 0, + 56, 2, 0, 0, 2, 0, 1, 0, + 12, 0, 243, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 53, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 48, 2, 0, 0, 3, 0, 1, 0, + 60, 2, 0, 0, 2, 0, 1, 0, + 13, 0, 242, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 57, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 52, 2, 0, 0, 3, 0, 1, 0, + 64, 2, 0, 0, 2, 0, 1, 0, + 14, 0, 241, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 61, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 56, 2, 0, 0, 3, 0, 1, 0, + 68, 2, 0, 0, 2, 0, 1, 0, + 15, 0, 240, 255, 1, 0, 0, 0, + 0, 0, 1, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 65, 2, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 60, 2, 0, 0, 3, 0, 1, 0, + 72, 2, 0, 0, 2, 0, 1, 0, + 16, 0, 239, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 69, 2, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 64, 2, 0, 0, 3, 0, 1, 0, + 76, 2, 0, 0, 2, 0, 1, 0, + 17, 0, 238, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 73, 2, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 72, 2, 0, 0, 3, 0, 1, 0, + 84, 2, 0, 0, 2, 0, 1, 0, + 18, 0, 237, 255, 0, 0, 0, 0, + 0, 0, 1, 0, 18, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 81, 2, 0, 0, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 80, 2, 0, 0, 3, 0, 1, 0, + 92, 2, 0, 0, 2, 0, 1, 0, + 118, 111, 105, 100, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 111, 111, 108, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 110, 116, 56, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 110, 116, 49, 54, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 110, 116, 51, 50, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 110, 116, 54, 52, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 117, 105, 110, 116, 56, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 117, 105, 110, 116, 49, 54, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 117, 105, 110, 116, 51, 50, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 117, 105, 110, 116, 54, 52, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 102, 108, 111, 97, 116, 51, 50, 0, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 102, 108, 111, 97, 116, 54, 52, 0, + 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 101, 120, 116, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 97, 116, 97, 0, 0, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 108, 105, 115, 116, 0, 0, 0, 0, + 18, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 18, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 110, 117, 109, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 116, 114, 117, 99, 116, 0, 0, + 18, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 18, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 110, 116, 101, 114, 102, 97, 99, + 101, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 110, 121, 80, 111, 105, 110, 116, + 101, 114, 0, 0, 0, 0, 0, 0, + 18, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 18, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_ce23dcd2d7b00c9b = b_ce23dcd2d7b00c9b.words; +static const uint16_t m_ce23dcd2d7b00c9b[] = {18, 1, 13, 15, 10, 11, 3, 4, 5, 2, 17, 14, 16, 12, 7, 8, 9, 6, 0}; +static const uint16_t i_ce23dcd2d7b00c9b[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}; +const ::capnp::_::RawSchema s_ce23dcd2d7b00c9b = { + 0xce23dcd2d7b00c9b, b_ce23dcd2d7b00c9b.words, 305, nullptr, m_ce23dcd2d7b00c9b, + 0, 19, i_ce23dcd2d7b00c9b, nullptr, nullptr, { &s_ce23dcd2d7b00c9b, nullptr, nullptr, 0, 0, nullptr }, true +}; +static const ::capnp::_::AlignedData<63> b_f1c8950dab257542 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 66, 117, 37, 171, 13, 149, 200, 241, + 13, 0, 0, 0, 1, 0, 1, 0, + 217, 114, 76, 98, 9, 197, 63, 169, + 2, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 147, 59, 0, 0, 35, 61, 0, 0, + 21, 0, 0, 0, 194, 0, 0, 0, + 29, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 65, 110, 110, + 111, 116, 97, 116, 105, 111, 110, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 12, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 69, 0, 0, 0, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 3, 0, 1, 0, + 76, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 73, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 68, 0, 0, 0, 3, 0, 1, 0, + 80, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 77, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 72, 0, 0, 0, 3, 0, 1, 0, + 84, 0, 0, 0, 2, 0, 1, 0, + 105, 100, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 118, 97, 108, 117, 101, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 155, 12, 176, 215, 210, 220, 35, 206, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 98, 114, 97, 110, 100, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 43, 66, 101, 96, 240, 85, 52, 144, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_f1c8950dab257542 = b_f1c8950dab257542.words; +static const ::capnp::_::RawSchema* const d_f1c8950dab257542[] = { + &s_903455f06065422b, + &s_ce23dcd2d7b00c9b, +}; +static const uint16_t m_f1c8950dab257542[] = {2, 0, 1}; +static const uint16_t i_f1c8950dab257542[] = {0, 1, 2}; +const ::capnp::_::RawSchema s_f1c8950dab257542 = { + 0xf1c8950dab257542, b_f1c8950dab257542.words, 63, d_f1c8950dab257542, m_f1c8950dab257542, + 2, 3, i_f1c8950dab257542, nullptr, nullptr, { &s_f1c8950dab257542, nullptr, nullptr, 0, 0, nullptr }, true +}; +static const ::capnp::_::AlignedData<55> b_d1958f7dba521926 = { + { 0, 0, 0, 0, 6, 0, 6, 0, + 38, 25, 82, 186, 125, 143, 149, 209, + 13, 0, 0, 0, 2, 0, 0, 0, + 217, 114, 76, 98, 9, 197, 63, 169, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 37, 61, 0, 0, 112, 62, 0, 0, + 21, 0, 0, 0, 202, 0, 0, 0, + 33, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 29, 0, 0, 0, 199, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 115, 99, 104, 101, 109, 97, 46, 99, + 97, 112, 110, 112, 58, 69, 108, 101, + 109, 101, 110, 116, 83, 105, 122, 101, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 32, 0, 0, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 89, 0, 0, 0, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 81, 0, 0, 0, 34, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, + 73, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, + 65, 0, 0, 0, 74, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, + 61, 0, 0, 0, 82, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, + 57, 0, 0, 0, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, + 53, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 130, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 109, 112, 116, 121, 0, 0, 0, + 98, 105, 116, 0, 0, 0, 0, 0, + 98, 121, 116, 101, 0, 0, 0, 0, + 116, 119, 111, 66, 121, 116, 101, 115, + 0, 0, 0, 0, 0, 0, 0, 0, + 102, 111, 117, 114, 66, 121, 116, 101, + 115, 0, 0, 0, 0, 0, 0, 0, + 101, 105, 103, 104, 116, 66, 121, 116, + 101, 115, 0, 0, 0, 0, 0, 0, + 112, 111, 105, 110, 116, 101, 114, 0, + 105, 110, 108, 105, 110, 101, 67, 111, + 109, 112, 111, 115, 105, 116, 101, 0, } +}; +::capnp::word const* const bp_d1958f7dba521926 = b_d1958f7dba521926.words; +static const uint16_t m_d1958f7dba521926[] = {1, 2, 5, 0, 4, 7, 6, 3}; +const ::capnp::_::RawSchema s_d1958f7dba521926 = { + 0xd1958f7dba521926, b_d1958f7dba521926.words, 55, nullptr, m_d1958f7dba521926, + 0, 8, nullptr, nullptr, nullptr, { &s_d1958f7dba521926, nullptr, nullptr, 0, 0, nullptr }, false +}; +CAPNP_DEFINE_ENUM(ElementSize_d1958f7dba521926, d1958f7dba521926); +} // namespace schemas +} // namespace capnp + +// ======================================================================================= + +namespace capnp { +namespace schema { + +// Node +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Node::_capnpPrivate::dataWordSize; +constexpr uint16_t Node::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Node::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Node::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Node::Parameter +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Node::Parameter::_capnpPrivate::dataWordSize; +constexpr uint16_t Node::Parameter::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Node::Parameter::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Node::Parameter::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Node::NestedNode +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Node::NestedNode::_capnpPrivate::dataWordSize; +constexpr uint16_t Node::NestedNode::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Node::NestedNode::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Node::NestedNode::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Node::Struct +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Node::Struct::_capnpPrivate::dataWordSize; +constexpr uint16_t Node::Struct::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Node::Struct::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Node::Struct::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Node::Enum +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Node::Enum::_capnpPrivate::dataWordSize; +constexpr uint16_t Node::Enum::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Node::Enum::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Node::Enum::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Node::Interface +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Node::Interface::_capnpPrivate::dataWordSize; +constexpr uint16_t Node::Interface::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Node::Interface::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Node::Interface::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Node::Const +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Node::Const::_capnpPrivate::dataWordSize; +constexpr uint16_t Node::Const::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Node::Const::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Node::Const::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Node::Annotation +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Node::Annotation::_capnpPrivate::dataWordSize; +constexpr uint16_t Node::Annotation::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Node::Annotation::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Node::Annotation::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Field +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Field::_capnpPrivate::dataWordSize; +constexpr uint16_t Field::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Field::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Field::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::uint16_t Field::NO_DISCRIMINANT; +#endif +// Field::Slot +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Field::Slot::_capnpPrivate::dataWordSize; +constexpr uint16_t Field::Slot::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Field::Slot::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Field::Slot::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Field::Group +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Field::Group::_capnpPrivate::dataWordSize; +constexpr uint16_t Field::Group::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Field::Group::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Field::Group::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Field::Ordinal +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Field::Ordinal::_capnpPrivate::dataWordSize; +constexpr uint16_t Field::Ordinal::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Field::Ordinal::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Field::Ordinal::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Enumerant +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Enumerant::_capnpPrivate::dataWordSize; +constexpr uint16_t Enumerant::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Enumerant::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Enumerant::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Superclass +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Superclass::_capnpPrivate::dataWordSize; +constexpr uint16_t Superclass::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Superclass::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Superclass::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Method +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Method::_capnpPrivate::dataWordSize; +constexpr uint16_t Method::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Method::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Method::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Type +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Type::_capnpPrivate::dataWordSize; +constexpr uint16_t Type::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Type::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Type::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Type::List +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Type::List::_capnpPrivate::dataWordSize; +constexpr uint16_t Type::List::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Type::List::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Type::List::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Type::Enum +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Type::Enum::_capnpPrivate::dataWordSize; +constexpr uint16_t Type::Enum::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Type::Enum::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Type::Enum::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Type::Struct +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Type::Struct::_capnpPrivate::dataWordSize; +constexpr uint16_t Type::Struct::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Type::Struct::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Type::Struct::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Type::Interface +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Type::Interface::_capnpPrivate::dataWordSize; +constexpr uint16_t Type::Interface::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Type::Interface::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Type::Interface::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Type::AnyPointer +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Type::AnyPointer::_capnpPrivate::dataWordSize; +constexpr uint16_t Type::AnyPointer::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Type::AnyPointer::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Type::AnyPointer::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Type::AnyPointer::Unconstrained +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Type::AnyPointer::Unconstrained::_capnpPrivate::dataWordSize; +constexpr uint16_t Type::AnyPointer::Unconstrained::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Type::AnyPointer::Unconstrained::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Type::AnyPointer::Unconstrained::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Type::AnyPointer::Parameter +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Type::AnyPointer::Parameter::_capnpPrivate::dataWordSize; +constexpr uint16_t Type::AnyPointer::Parameter::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Type::AnyPointer::Parameter::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Type::AnyPointer::Parameter::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Type::AnyPointer::ImplicitMethodParameter +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Type::AnyPointer::ImplicitMethodParameter::_capnpPrivate::dataWordSize; +constexpr uint16_t Type::AnyPointer::ImplicitMethodParameter::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Type::AnyPointer::ImplicitMethodParameter::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Type::AnyPointer::ImplicitMethodParameter::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Brand +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Brand::_capnpPrivate::dataWordSize; +constexpr uint16_t Brand::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Brand::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Brand::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Brand::Scope +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Brand::Scope::_capnpPrivate::dataWordSize; +constexpr uint16_t Brand::Scope::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Brand::Scope::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Brand::Scope::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Brand::Binding +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Brand::Binding::_capnpPrivate::dataWordSize; +constexpr uint16_t Brand::Binding::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Brand::Binding::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Brand::Binding::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Value +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Value::_capnpPrivate::dataWordSize; +constexpr uint16_t Value::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Value::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Value::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + +// Annotation +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Annotation::_capnpPrivate::dataWordSize; +constexpr uint16_t Annotation::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Annotation::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Annotation::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL + + +} // namespace +} // namespace diff --git a/vendor/capnproto/src/capnp/schema.capnp.h b/vendor/capnproto/src/capnp/schema.capnp.h new file mode 100644 index 0000000..fc4ce4f --- /dev/null +++ b/vendor/capnproto/src/capnp/schema.capnp.h @@ -0,0 +1,6430 @@ +// Generated by Cap'n Proto compiler, DO NOT EDIT +// source: schema.capnp + +#pragma once + +#include + +#ifndef CAPNP_VERSION +#error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?" +#elif CAPNP_VERSION != 1004000 +#error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." +#endif + + +CAPNP_BEGIN_HEADER + +namespace capnp { +namespace schemas { + +CAPNP_DECLARE_SCHEMA(e682ab4cf923a417); +CAPNP_DECLARE_SCHEMA(b9521bccf10fa3b1); +CAPNP_DECLARE_SCHEMA(debf55bbfa0fc242); +CAPNP_DECLARE_SCHEMA(9ea0b19b37fb4435); +CAPNP_DECLARE_SCHEMA(b54ab3364333f598); +CAPNP_DECLARE_SCHEMA(e82753cff0c2218f); +CAPNP_DECLARE_SCHEMA(b18aa5ac7a0d9420); +CAPNP_DECLARE_SCHEMA(ec1619d4400a0290); +CAPNP_DECLARE_SCHEMA(9aad50a41f4af45f); +CAPNP_DECLARE_SCHEMA(97b14cbe7cfec712); +CAPNP_DECLARE_SCHEMA(c42305476bb4746f); +CAPNP_DECLARE_SCHEMA(cafccddb68db1d11); +CAPNP_DECLARE_SCHEMA(bb90d5c287870be6); +CAPNP_DECLARE_SCHEMA(978a7cebdc549a4d); +CAPNP_DECLARE_SCHEMA(a9962a9ed0a4d7f8); +CAPNP_DECLARE_SCHEMA(9500cce23b334d80); +CAPNP_DECLARE_SCHEMA(d07378ede1f9cc60); +CAPNP_DECLARE_SCHEMA(87e739250a60ea97); +CAPNP_DECLARE_SCHEMA(9e0e78711a7f87a9); +CAPNP_DECLARE_SCHEMA(ac3a6f60ef4cc6d3); +CAPNP_DECLARE_SCHEMA(ed8bca69f7fb0cbf); +CAPNP_DECLARE_SCHEMA(c2573fe8a23e49f1); +CAPNP_DECLARE_SCHEMA(8e3b5f79fe593656); +CAPNP_DECLARE_SCHEMA(9dd1f724f4614a85); +CAPNP_DECLARE_SCHEMA(baefc9120c56e274); +CAPNP_DECLARE_SCHEMA(903455f06065422b); +CAPNP_DECLARE_SCHEMA(abd73485a9636bc9); +CAPNP_DECLARE_SCHEMA(c863cd16969ee7fc); +CAPNP_DECLARE_SCHEMA(ce23dcd2d7b00c9b); +CAPNP_DECLARE_SCHEMA(f1c8950dab257542); +CAPNP_DECLARE_SCHEMA(d1958f7dba521926); +enum class ElementSize_d1958f7dba521926: uint16_t { + EMPTY, + BIT, + BYTE, + TWO_BYTES, + FOUR_BYTES, + EIGHT_BYTES, + POINTER, + INLINE_COMPOSITE, +}; +CAPNP_DECLARE_ENUM(ElementSize, d1958f7dba521926); + +} // namespace schemas +} // namespace capnp + +namespace capnp { +namespace schema { + +struct Node { + Node() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + FILE, + STRUCT, + ENUM, + INTERFACE, + CONST, + ANNOTATION, + }; + struct Parameter; + struct NestedNode; + struct Struct; + struct Enum; + struct Interface; + struct Const; + struct Annotation; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(e682ab4cf923a417, 6, 6) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Node::Parameter { + Parameter() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(b9521bccf10fa3b1, 0, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Node::NestedNode { + NestedNode() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(debf55bbfa0fc242, 1, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Node::Struct { + Struct() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(9ea0b19b37fb4435, 6, 6) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Node::Enum { + Enum() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(b54ab3364333f598, 6, 6) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Node::Interface { + Interface() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(e82753cff0c2218f, 6, 6) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Node::Const { + Const() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(b18aa5ac7a0d9420, 6, 6) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Node::Annotation { + Annotation() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(ec1619d4400a0290, 6, 6) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Field { + Field() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + SLOT, + GROUP, + }; + static constexpr ::uint16_t NO_DISCRIMINANT = 65535u; + struct Slot; + struct Group; + struct Ordinal; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(9aad50a41f4af45f, 3, 4) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Field::Slot { + Slot() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(c42305476bb4746f, 3, 4) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Field::Group { + Group() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(cafccddb68db1d11, 3, 4) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Field::Ordinal { + Ordinal() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + IMPLICIT, + EXPLICIT, + }; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(bb90d5c287870be6, 3, 4) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Enumerant { + Enumerant() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(978a7cebdc549a4d, 1, 2) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Superclass { + Superclass() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(a9962a9ed0a4d7f8, 1, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Method { + Method() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(9500cce23b334d80, 3, 5) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Type { + Type() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + VOID, + BOOL, + INT8, + INT16, + INT32, + INT64, + UINT8, + UINT16, + UINT32, + UINT64, + FLOAT32, + FLOAT64, + TEXT, + DATA, + LIST, + ENUM, + STRUCT, + INTERFACE, + ANY_POINTER, + }; + struct List; + struct Enum; + struct Struct; + struct Interface; + struct AnyPointer; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(d07378ede1f9cc60, 3, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Type::List { + List() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(87e739250a60ea97, 3, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Type::Enum { + Enum() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(9e0e78711a7f87a9, 3, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Type::Struct { + Struct() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(ac3a6f60ef4cc6d3, 3, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Type::Interface { + Interface() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(ed8bca69f7fb0cbf, 3, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Type::AnyPointer { + AnyPointer() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + UNCONSTRAINED, + PARAMETER, + IMPLICIT_METHOD_PARAMETER, + }; + struct Unconstrained; + struct Parameter; + struct ImplicitMethodParameter; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(c2573fe8a23e49f1, 3, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Type::AnyPointer::Unconstrained { + Unconstrained() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + ANY_KIND, + STRUCT, + LIST, + CAPABILITY, + }; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(8e3b5f79fe593656, 3, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Type::AnyPointer::Parameter { + Parameter() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(9dd1f724f4614a85, 3, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Type::AnyPointer::ImplicitMethodParameter { + ImplicitMethodParameter() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(baefc9120c56e274, 3, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Brand { + Brand() = delete; + + class Reader; + class Builder; + struct Scope; + struct Binding; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(903455f06065422b, 0, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Brand::Scope { + Scope() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + BIND, + INHERIT, + }; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(abd73485a9636bc9, 2, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Brand::Binding { + Binding() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + UNBOUND, + TYPE, + }; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(c863cd16969ee7fc, 1, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Value { + Value() = delete; + + class Reader; + class Builder; + enum Which: uint16_t { + VOID, + BOOL, + INT8, + INT16, + INT32, + INT64, + UINT8, + UINT16, + UINT32, + UINT64, + FLOAT32, + FLOAT64, + TEXT, + DATA, + LIST, + ENUM, + STRUCT, + INTERFACE, + ANY_POINTER, + }; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(ce23dcd2d7b00c9b, 2, 1) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +struct Annotation { + Annotation() = delete; + + class Reader; + class Builder; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(f1c8950dab257542, 1, 2) + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + }; +}; + +typedef ::capnp::schemas::ElementSize_d1958f7dba521926 ElementSize; + +// ======================================================================================= + +class Node::Reader { +public: + typedef Node Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline ::uint64_t getId() const; + + inline bool hasDisplayName() const; + inline ::capnp::Text::Reader getDisplayName() const; + + inline ::uint32_t getDisplayNamePrefixLength() const; + + inline ::uint64_t getScopeId() const; + + inline bool hasNestedNodes() const; + inline ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Reader getNestedNodes() const; + + inline bool hasAnnotations() const; + inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader getAnnotations() const; + + inline bool isFile() const; + inline ::capnp::Void getFile() const; + + inline bool isStruct() const; + inline typename Struct::Reader getStruct() const; + + inline bool isEnum() const; + inline typename Enum::Reader getEnum() const; + + inline bool isInterface() const; + inline typename Interface::Reader getInterface() const; + + inline bool isConst() const; + inline typename Const::Reader getConst() const; + + inline bool isAnnotation() const; + inline typename Annotation::Reader getAnnotation() const; + + inline bool hasParameters() const; + inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader getParameters() const; + + inline bool getIsGeneric() const; + + inline ::uint32_t getStartByte() const; + + inline ::uint32_t getEndByte() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Node::Builder { +public: + typedef Node 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline ::uint64_t getId(); + inline void setId( ::uint64_t value); + + inline bool hasDisplayName(); + inline ::capnp::Text::Builder getDisplayName(); + inline void setDisplayName( ::capnp::Text::Reader value); + inline ::capnp::Text::Builder initDisplayName(unsigned int size); + inline void adoptDisplayName(::capnp::Orphan< ::capnp::Text>&& value); + inline ::capnp::Orphan< ::capnp::Text> disownDisplayName(); + + inline ::uint32_t getDisplayNamePrefixLength(); + inline void setDisplayNamePrefixLength( ::uint32_t value); + + inline ::uint64_t getScopeId(); + inline void setScopeId( ::uint64_t value); + + inline bool hasNestedNodes(); + inline ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Builder getNestedNodes(); + inline void setNestedNodes( ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Builder initNestedNodes(unsigned int size); + inline void adoptNestedNodes(::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>> disownNestedNodes(); + + inline bool hasAnnotations(); + inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder getAnnotations(); + inline void setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder initAnnotations(unsigned int size); + inline void adoptAnnotations(::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> disownAnnotations(); + + inline bool isFile(); + inline ::capnp::Void getFile(); + inline void setFile( ::capnp::Void value = ::capnp::VOID); + + inline bool isStruct(); + inline typename Struct::Builder getStruct(); + inline typename Struct::Builder initStruct(); + + inline bool isEnum(); + inline typename Enum::Builder getEnum(); + inline typename Enum::Builder initEnum(); + + inline bool isInterface(); + inline typename Interface::Builder getInterface(); + inline typename Interface::Builder initInterface(); + + inline bool isConst(); + inline typename Const::Builder getConst(); + inline typename Const::Builder initConst(); + + inline bool isAnnotation(); + inline typename Annotation::Builder getAnnotation(); + inline typename Annotation::Builder initAnnotation(); + + inline bool hasParameters(); + inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder getParameters(); + inline void setParameters( ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder initParameters(unsigned int size); + inline void adoptParameters(::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>> disownParameters(); + + inline bool getIsGeneric(); + inline void setIsGeneric(bool value); + + inline ::uint32_t getStartByte(); + inline void setStartByte( ::uint32_t value); + + inline ::uint32_t getEndByte(); + inline void setEndByte( ::uint32_t value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Node::Parameter::Reader { +public: + typedef Parameter Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasName() const; + inline ::capnp::Text::Reader getName() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Node::Parameter::Builder { +public: + typedef Parameter 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + 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(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Node::NestedNode::Reader { +public: + typedef NestedNode Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasName() const; + inline ::capnp::Text::Reader getName() const; + + inline ::uint64_t getId() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Node::NestedNode::Builder { +public: + typedef NestedNode 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + 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 ::uint64_t getId(); + inline void setId( ::uint64_t value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Node::Struct::Reader { +public: + typedef Struct Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline ::uint16_t getDataWordCount() const; + + inline ::uint16_t getPointerCount() const; + + inline ::capnp::schema::ElementSize getPreferredListEncoding() const; + + inline bool getIsGroup() const; + + inline ::uint16_t getDiscriminantCount() const; + + inline ::uint32_t getDiscriminantOffset() const; + + inline bool hasFields() const; + inline ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Reader getFields() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Node::Struct::Builder { +public: + typedef Struct 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline ::uint16_t getDataWordCount(); + inline void setDataWordCount( ::uint16_t value); + + inline ::uint16_t getPointerCount(); + inline void setPointerCount( ::uint16_t value); + + inline ::capnp::schema::ElementSize getPreferredListEncoding(); + inline void setPreferredListEncoding( ::capnp::schema::ElementSize value); + + inline bool getIsGroup(); + inline void setIsGroup(bool value); + + inline ::uint16_t getDiscriminantCount(); + inline void setDiscriminantCount( ::uint16_t value); + + inline ::uint32_t getDiscriminantOffset(); + inline void setDiscriminantOffset( ::uint32_t value); + + inline bool hasFields(); + inline ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Builder getFields(); + inline void setFields( ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Builder initFields(unsigned int size); + inline void adoptFields(::capnp::Orphan< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>> disownFields(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Node::Enum::Reader { +public: + typedef Enum Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasEnumerants() const; + inline ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Reader getEnumerants() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Node::Enum::Builder { +public: + typedef Enum 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasEnumerants(); + inline ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Builder getEnumerants(); + inline void setEnumerants( ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Builder initEnumerants(unsigned int size); + inline void adoptEnumerants(::capnp::Orphan< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>> disownEnumerants(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Node::Interface::Reader { +public: + typedef Interface Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasMethods() const; + inline ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Reader getMethods() const; + + inline bool hasSuperclasses() const; + inline ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Reader getSuperclasses() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Node::Interface::Builder { +public: + typedef Interface 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasMethods(); + inline ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Builder getMethods(); + inline void setMethods( ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Builder initMethods(unsigned int size); + inline void adoptMethods(::capnp::Orphan< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>> disownMethods(); + + inline bool hasSuperclasses(); + inline ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Builder getSuperclasses(); + inline void setSuperclasses( ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Builder initSuperclasses(unsigned int size); + inline void adoptSuperclasses(::capnp::Orphan< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>> disownSuperclasses(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Node::Const::Reader { +public: + typedef Const Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasType() const; + inline ::capnp::schema::Type::Reader getType() const; + + inline bool hasValue() const; + inline ::capnp::schema::Value::Reader getValue() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Node::Const::Builder { +public: + typedef Const 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasType(); + inline ::capnp::schema::Type::Builder getType(); + inline void setType( ::capnp::schema::Type::Reader value); + inline ::capnp::schema::Type::Builder initType(); + inline void adoptType(::capnp::Orphan< ::capnp::schema::Type>&& value); + inline ::capnp::Orphan< ::capnp::schema::Type> disownType(); + + inline bool hasValue(); + inline ::capnp::schema::Value::Builder getValue(); + inline void setValue( ::capnp::schema::Value::Reader value); + inline ::capnp::schema::Value::Builder initValue(); + inline void adoptValue(::capnp::Orphan< ::capnp::schema::Value>&& value); + inline ::capnp::Orphan< ::capnp::schema::Value> disownValue(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Node::Annotation::Reader { +public: + typedef Annotation Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasType() const; + inline ::capnp::schema::Type::Reader getType() const; + + inline bool getTargetsFile() const; + + inline bool getTargetsConst() const; + + inline bool getTargetsEnum() const; + + inline bool getTargetsEnumerant() const; + + inline bool getTargetsStruct() const; + + inline bool getTargetsField() const; + + inline bool getTargetsUnion() const; + + inline bool getTargetsGroup() const; + + inline bool getTargetsInterface() const; + + inline bool getTargetsMethod() const; + + inline bool getTargetsParam() const; + + inline bool getTargetsAnnotation() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Node::Annotation::Builder { +public: + typedef Annotation 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasType(); + inline ::capnp::schema::Type::Builder getType(); + inline void setType( ::capnp::schema::Type::Reader value); + inline ::capnp::schema::Type::Builder initType(); + inline void adoptType(::capnp::Orphan< ::capnp::schema::Type>&& value); + inline ::capnp::Orphan< ::capnp::schema::Type> disownType(); + + inline bool getTargetsFile(); + inline void setTargetsFile(bool value); + + inline bool getTargetsConst(); + inline void setTargetsConst(bool value); + + inline bool getTargetsEnum(); + inline void setTargetsEnum(bool value); + + inline bool getTargetsEnumerant(); + inline void setTargetsEnumerant(bool value); + + inline bool getTargetsStruct(); + inline void setTargetsStruct(bool value); + + inline bool getTargetsField(); + inline void setTargetsField(bool value); + + inline bool getTargetsUnion(); + inline void setTargetsUnion(bool value); + + inline bool getTargetsGroup(); + inline void setTargetsGroup(bool value); + + inline bool getTargetsInterface(); + inline void setTargetsInterface(bool value); + + inline bool getTargetsMethod(); + inline void setTargetsMethod(bool value); + + inline bool getTargetsParam(); + inline void setTargetsParam(bool value); + + inline bool getTargetsAnnotation(); + inline void setTargetsAnnotation(bool value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class 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(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool hasName() const; + inline ::capnp::Text::Reader getName() const; + + inline ::uint16_t getCodeOrder() const; + + inline bool hasAnnotations() const; + inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader getAnnotations() const; + + inline ::uint16_t getDiscriminantValue() const; + + inline bool isSlot() const; + inline typename Slot::Reader getSlot() const; + + inline bool isGroup() const; + inline typename Group::Reader getGroup() const; + + inline typename Ordinal::Reader getOrdinal() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + 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 ::uint16_t getCodeOrder(); + inline void setCodeOrder( ::uint16_t value); + + inline bool hasAnnotations(); + inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder getAnnotations(); + inline void setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder initAnnotations(unsigned int size); + inline void adoptAnnotations(::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> disownAnnotations(); + + inline ::uint16_t getDiscriminantValue(); + inline void setDiscriminantValue( ::uint16_t value); + + inline bool isSlot(); + inline typename Slot::Builder getSlot(); + inline typename Slot::Builder initSlot(); + + inline bool isGroup(); + inline typename Group::Builder getGroup(); + inline typename Group::Builder initGroup(); + + inline typename Ordinal::Builder getOrdinal(); + inline typename Ordinal::Builder initOrdinal(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Field::Slot::Reader { +public: + typedef Slot Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline ::uint32_t getOffset() const; + + inline bool hasType() const; + inline ::capnp::schema::Type::Reader getType() const; + + inline bool hasDefaultValue() const; + inline ::capnp::schema::Value::Reader getDefaultValue() const; + + inline bool getHadExplicitDefault() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Field::Slot::Builder { +public: + typedef Slot 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline ::uint32_t getOffset(); + inline void setOffset( ::uint32_t value); + + inline bool hasType(); + inline ::capnp::schema::Type::Builder getType(); + inline void setType( ::capnp::schema::Type::Reader value); + inline ::capnp::schema::Type::Builder initType(); + inline void adoptType(::capnp::Orphan< ::capnp::schema::Type>&& value); + inline ::capnp::Orphan< ::capnp::schema::Type> disownType(); + + inline bool hasDefaultValue(); + inline ::capnp::schema::Value::Builder getDefaultValue(); + inline void setDefaultValue( ::capnp::schema::Value::Reader value); + inline ::capnp::schema::Value::Builder initDefaultValue(); + inline void adoptDefaultValue(::capnp::Orphan< ::capnp::schema::Value>&& value); + inline ::capnp::Orphan< ::capnp::schema::Value> disownDefaultValue(); + + inline bool getHadExplicitDefault(); + inline void setHadExplicitDefault(bool value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Field::Group::Reader { +public: + typedef Group Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline ::uint64_t getTypeId() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Field::Group::Builder { +public: + typedef Group 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline ::uint64_t getTypeId(); + inline void setTypeId( ::uint64_t value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Field::Ordinal::Reader { +public: + typedef Ordinal Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isImplicit() const; + inline ::capnp::Void getImplicit() const; + + inline bool isExplicit() const; + inline ::uint16_t getExplicit() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Field::Ordinal::Builder { +public: + typedef Ordinal 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isImplicit(); + inline ::capnp::Void getImplicit(); + inline void setImplicit( ::capnp::Void value = ::capnp::VOID); + + inline bool isExplicit(); + inline ::uint16_t getExplicit(); + inline void setExplicit( ::uint16_t value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Enumerant::Reader { +public: + typedef Enumerant Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasName() const; + inline ::capnp::Text::Reader getName() const; + + inline ::uint16_t getCodeOrder() const; + + inline bool hasAnnotations() const; + inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader getAnnotations() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Enumerant::Builder { +public: + typedef Enumerant 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + 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 ::uint16_t getCodeOrder(); + inline void setCodeOrder( ::uint16_t value); + + inline bool hasAnnotations(); + inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder getAnnotations(); + inline void setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder initAnnotations(unsigned int size); + inline void adoptAnnotations(::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> disownAnnotations(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Superclass::Reader { +public: + typedef Superclass Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline ::uint64_t getId() const; + + inline bool hasBrand() const; + inline ::capnp::schema::Brand::Reader getBrand() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Superclass::Builder { +public: + typedef Superclass 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline ::uint64_t getId(); + inline void setId( ::uint64_t value); + + inline bool hasBrand(); + inline ::capnp::schema::Brand::Builder getBrand(); + inline void setBrand( ::capnp::schema::Brand::Reader value); + inline ::capnp::schema::Brand::Builder initBrand(); + inline void adoptBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); + inline ::capnp::Orphan< ::capnp::schema::Brand> disownBrand(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Method::Reader { +public: + typedef Method Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasName() const; + inline ::capnp::Text::Reader getName() const; + + inline ::uint16_t getCodeOrder() const; + + inline ::uint64_t getParamStructType() const; + + inline ::uint64_t getResultStructType() const; + + inline bool hasAnnotations() const; + inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader getAnnotations() const; + + inline bool hasParamBrand() const; + inline ::capnp::schema::Brand::Reader getParamBrand() const; + + inline bool hasResultBrand() const; + inline ::capnp::schema::Brand::Reader getResultBrand() const; + + inline bool hasImplicitParameters() const; + inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader getImplicitParameters() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Method::Builder { +public: + typedef Method 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + 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 ::uint16_t getCodeOrder(); + inline void setCodeOrder( ::uint16_t value); + + inline ::uint64_t getParamStructType(); + inline void setParamStructType( ::uint64_t value); + + inline ::uint64_t getResultStructType(); + inline void setResultStructType( ::uint64_t value); + + inline bool hasAnnotations(); + inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder getAnnotations(); + inline void setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder initAnnotations(unsigned int size); + inline void adoptAnnotations(::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> disownAnnotations(); + + inline bool hasParamBrand(); + inline ::capnp::schema::Brand::Builder getParamBrand(); + inline void setParamBrand( ::capnp::schema::Brand::Reader value); + inline ::capnp::schema::Brand::Builder initParamBrand(); + inline void adoptParamBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); + inline ::capnp::Orphan< ::capnp::schema::Brand> disownParamBrand(); + + inline bool hasResultBrand(); + inline ::capnp::schema::Brand::Builder getResultBrand(); + inline void setResultBrand( ::capnp::schema::Brand::Reader value); + inline ::capnp::schema::Brand::Builder initResultBrand(); + inline void adoptResultBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); + inline ::capnp::Orphan< ::capnp::schema::Brand> disownResultBrand(); + + inline bool hasImplicitParameters(); + inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder getImplicitParameters(); + inline void setImplicitParameters( ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder initImplicitParameters(unsigned int size); + inline void adoptImplicitParameters(::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>> disownImplicitParameters(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Type::Reader { +public: + typedef Type Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isVoid() const; + inline ::capnp::Void getVoid() const; + + inline bool isBool() const; + inline ::capnp::Void getBool() const; + + inline bool isInt8() const; + inline ::capnp::Void getInt8() const; + + inline bool isInt16() const; + inline ::capnp::Void getInt16() const; + + inline bool isInt32() const; + inline ::capnp::Void getInt32() const; + + inline bool isInt64() const; + inline ::capnp::Void getInt64() const; + + inline bool isUint8() const; + inline ::capnp::Void getUint8() const; + + inline bool isUint16() const; + inline ::capnp::Void getUint16() const; + + inline bool isUint32() const; + inline ::capnp::Void getUint32() const; + + inline bool isUint64() const; + inline ::capnp::Void getUint64() const; + + inline bool isFloat32() const; + inline ::capnp::Void getFloat32() const; + + inline bool isFloat64() const; + inline ::capnp::Void getFloat64() const; + + inline bool isText() const; + inline ::capnp::Void getText() const; + + inline bool isData() const; + inline ::capnp::Void getData() const; + + inline bool isList() const; + inline typename List::Reader getList() const; + + inline bool isEnum() const; + inline typename Enum::Reader getEnum() const; + + inline bool isStruct() const; + inline typename Struct::Reader getStruct() const; + + inline bool isInterface() const; + inline typename Interface::Reader getInterface() const; + + inline bool isAnyPointer() const; + inline typename AnyPointer::Reader getAnyPointer() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Type::Builder { +public: + typedef Type 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isVoid(); + inline ::capnp::Void getVoid(); + inline void setVoid( ::capnp::Void value = ::capnp::VOID); + + inline bool isBool(); + inline ::capnp::Void getBool(); + inline void setBool( ::capnp::Void value = ::capnp::VOID); + + inline bool isInt8(); + inline ::capnp::Void getInt8(); + inline void setInt8( ::capnp::Void value = ::capnp::VOID); + + inline bool isInt16(); + inline ::capnp::Void getInt16(); + inline void setInt16( ::capnp::Void value = ::capnp::VOID); + + inline bool isInt32(); + inline ::capnp::Void getInt32(); + inline void setInt32( ::capnp::Void value = ::capnp::VOID); + + inline bool isInt64(); + inline ::capnp::Void getInt64(); + inline void setInt64( ::capnp::Void value = ::capnp::VOID); + + inline bool isUint8(); + inline ::capnp::Void getUint8(); + inline void setUint8( ::capnp::Void value = ::capnp::VOID); + + inline bool isUint16(); + inline ::capnp::Void getUint16(); + inline void setUint16( ::capnp::Void value = ::capnp::VOID); + + inline bool isUint32(); + inline ::capnp::Void getUint32(); + inline void setUint32( ::capnp::Void value = ::capnp::VOID); + + inline bool isUint64(); + inline ::capnp::Void getUint64(); + inline void setUint64( ::capnp::Void value = ::capnp::VOID); + + inline bool isFloat32(); + inline ::capnp::Void getFloat32(); + inline void setFloat32( ::capnp::Void value = ::capnp::VOID); + + inline bool isFloat64(); + inline ::capnp::Void getFloat64(); + inline void setFloat64( ::capnp::Void value = ::capnp::VOID); + + inline bool isText(); + inline ::capnp::Void getText(); + inline void setText( ::capnp::Void value = ::capnp::VOID); + + inline bool isData(); + inline ::capnp::Void getData(); + inline void setData( ::capnp::Void value = ::capnp::VOID); + + inline bool isList(); + inline typename List::Builder getList(); + inline typename List::Builder initList(); + + inline bool isEnum(); + inline typename Enum::Builder getEnum(); + inline typename Enum::Builder initEnum(); + + inline bool isStruct(); + inline typename Struct::Builder getStruct(); + inline typename Struct::Builder initStruct(); + + inline bool isInterface(); + inline typename Interface::Builder getInterface(); + inline typename Interface::Builder initInterface(); + + inline bool isAnyPointer(); + inline typename AnyPointer::Builder getAnyPointer(); + inline typename AnyPointer::Builder initAnyPointer(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Type::List::Reader { +public: + typedef List Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasElementType() const; + inline ::capnp::schema::Type::Reader getElementType() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Type::List::Builder { +public: + typedef List 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasElementType(); + inline ::capnp::schema::Type::Builder getElementType(); + inline void setElementType( ::capnp::schema::Type::Reader value); + inline ::capnp::schema::Type::Builder initElementType(); + inline void adoptElementType(::capnp::Orphan< ::capnp::schema::Type>&& value); + inline ::capnp::Orphan< ::capnp::schema::Type> disownElementType(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Type::Enum::Reader { +public: + typedef Enum Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline ::uint64_t getTypeId() const; + + inline bool hasBrand() const; + inline ::capnp::schema::Brand::Reader getBrand() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Type::Enum::Builder { +public: + typedef Enum 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline ::uint64_t getTypeId(); + inline void setTypeId( ::uint64_t value); + + inline bool hasBrand(); + inline ::capnp::schema::Brand::Builder getBrand(); + inline void setBrand( ::capnp::schema::Brand::Reader value); + inline ::capnp::schema::Brand::Builder initBrand(); + inline void adoptBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); + inline ::capnp::Orphan< ::capnp::schema::Brand> disownBrand(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Type::Struct::Reader { +public: + typedef Struct Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline ::uint64_t getTypeId() const; + + inline bool hasBrand() const; + inline ::capnp::schema::Brand::Reader getBrand() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Type::Struct::Builder { +public: + typedef Struct 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline ::uint64_t getTypeId(); + inline void setTypeId( ::uint64_t value); + + inline bool hasBrand(); + inline ::capnp::schema::Brand::Builder getBrand(); + inline void setBrand( ::capnp::schema::Brand::Reader value); + inline ::capnp::schema::Brand::Builder initBrand(); + inline void adoptBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); + inline ::capnp::Orphan< ::capnp::schema::Brand> disownBrand(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Type::Interface::Reader { +public: + typedef Interface Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline ::uint64_t getTypeId() const; + + inline bool hasBrand() const; + inline ::capnp::schema::Brand::Reader getBrand() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Type::Interface::Builder { +public: + typedef Interface 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline ::uint64_t getTypeId(); + inline void setTypeId( ::uint64_t value); + + inline bool hasBrand(); + inline ::capnp::schema::Brand::Builder getBrand(); + inline void setBrand( ::capnp::schema::Brand::Reader value); + inline ::capnp::schema::Brand::Builder initBrand(); + inline void adoptBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); + inline ::capnp::Orphan< ::capnp::schema::Brand> disownBrand(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Type::AnyPointer::Reader { +public: + typedef AnyPointer Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isUnconstrained() const; + inline typename Unconstrained::Reader getUnconstrained() const; + + inline bool isParameter() const; + inline typename Parameter::Reader getParameter() const; + + inline bool isImplicitMethodParameter() const; + inline typename ImplicitMethodParameter::Reader getImplicitMethodParameter() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Type::AnyPointer::Builder { +public: + typedef AnyPointer 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isUnconstrained(); + inline typename Unconstrained::Builder getUnconstrained(); + inline typename Unconstrained::Builder initUnconstrained(); + + inline bool isParameter(); + inline typename Parameter::Builder getParameter(); + inline typename Parameter::Builder initParameter(); + + inline bool isImplicitMethodParameter(); + inline typename ImplicitMethodParameter::Builder getImplicitMethodParameter(); + inline typename ImplicitMethodParameter::Builder initImplicitMethodParameter(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Type::AnyPointer::Unconstrained::Reader { +public: + typedef Unconstrained Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isAnyKind() const; + inline ::capnp::Void getAnyKind() const; + + inline bool isStruct() const; + inline ::capnp::Void getStruct() const; + + inline bool isList() const; + inline ::capnp::Void getList() const; + + inline bool isCapability() const; + inline ::capnp::Void getCapability() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Type::AnyPointer::Unconstrained::Builder { +public: + typedef Unconstrained 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isAnyKind(); + inline ::capnp::Void getAnyKind(); + inline void setAnyKind( ::capnp::Void value = ::capnp::VOID); + + inline bool isStruct(); + inline ::capnp::Void getStruct(); + inline void setStruct( ::capnp::Void value = ::capnp::VOID); + + inline bool isList(); + inline ::capnp::Void getList(); + inline void setList( ::capnp::Void value = ::capnp::VOID); + + inline bool isCapability(); + inline ::capnp::Void getCapability(); + inline void setCapability( ::capnp::Void value = ::capnp::VOID); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Type::AnyPointer::Parameter::Reader { +public: + typedef Parameter Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline ::uint64_t getScopeId() const; + + inline ::uint16_t getParameterIndex() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Type::AnyPointer::Parameter::Builder { +public: + typedef Parameter 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline ::uint64_t getScopeId(); + inline void setScopeId( ::uint64_t value); + + inline ::uint16_t getParameterIndex(); + inline void setParameterIndex( ::uint16_t value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Type::AnyPointer::ImplicitMethodParameter::Reader { +public: + typedef ImplicitMethodParameter Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline ::uint16_t getParameterIndex() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Type::AnyPointer::ImplicitMethodParameter::Builder { +public: + typedef ImplicitMethodParameter 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline ::uint16_t getParameterIndex(); + inline void setParameterIndex( ::uint16_t value); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Brand::Reader { +public: + typedef Brand Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline bool hasScopes() const; + inline ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Reader getScopes() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Brand::Builder { +public: + typedef Brand 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline bool hasScopes(); + inline ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Builder getScopes(); + inline void setScopes( ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Builder initScopes(unsigned int size); + inline void adoptScopes(::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>> disownScopes(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Brand::Scope::Reader { +public: + typedef Scope Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline ::uint64_t getScopeId() const; + + inline bool isBind() const; + inline bool hasBind() const; + inline ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Reader getBind() const; + + inline bool isInherit() const; + inline ::capnp::Void getInherit() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Brand::Scope::Builder { +public: + typedef Scope 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline ::uint64_t getScopeId(); + inline void setScopeId( ::uint64_t value); + + inline bool isBind(); + inline bool hasBind(); + inline ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Builder getBind(); + inline void setBind( ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Builder initBind(unsigned int size); + inline void adoptBind(::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>> disownBind(); + + inline bool isInherit(); + inline ::capnp::Void getInherit(); + inline void setInherit( ::capnp::Void value = ::capnp::VOID); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Brand::Binding::Reader { +public: + typedef Binding Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isUnbound() const; + inline ::capnp::Void getUnbound() const; + + inline bool isType() const; + inline bool hasType() const; + inline ::capnp::schema::Type::Reader getType() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Brand::Binding::Builder { +public: + typedef Binding 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isUnbound(); + inline ::capnp::Void getUnbound(); + inline void setUnbound( ::capnp::Void value = ::capnp::VOID); + + inline bool isType(); + inline bool hasType(); + inline ::capnp::schema::Type::Builder getType(); + inline void setType( ::capnp::schema::Type::Reader value); + inline ::capnp::schema::Type::Builder initType(); + inline void adoptType(::capnp::Orphan< ::capnp::schema::Type>&& value); + inline ::capnp::Orphan< ::capnp::schema::Type> disownType(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Value::Reader { +public: + typedef Value Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline Which which() const; + inline bool isVoid() const; + inline ::capnp::Void getVoid() const; + + inline bool isBool() const; + inline bool getBool() const; + + inline bool isInt8() const; + inline ::int8_t getInt8() const; + + inline bool isInt16() const; + inline ::int16_t getInt16() const; + + inline bool isInt32() const; + inline ::int32_t getInt32() const; + + inline bool isInt64() const; + inline ::int64_t getInt64() const; + + inline bool isUint8() const; + inline ::uint8_t getUint8() const; + + inline bool isUint16() const; + inline ::uint16_t getUint16() const; + + inline bool isUint32() const; + inline ::uint32_t getUint32() const; + + inline bool isUint64() const; + inline ::uint64_t getUint64() const; + + inline bool isFloat32() const; + inline float getFloat32() const; + + inline bool isFloat64() const; + inline double getFloat64() const; + + inline bool isText() const; + inline bool hasText() const; + inline ::capnp::Text::Reader getText() const; + + inline bool isData() const; + inline bool hasData() const; + inline ::capnp::Data::Reader getData() const; + + inline bool isList() const; + inline bool hasList() const; + inline ::capnp::AnyPointer::Reader getList() const; + + inline bool isEnum() const; + inline ::uint16_t getEnum() const; + + inline bool isStruct() const; + inline bool hasStruct() const; + inline ::capnp::AnyPointer::Reader getStruct() const; + + inline bool isInterface() const; + inline ::capnp::Void getInterface() const; + + inline bool isAnyPointer() const; + inline bool hasAnyPointer() const; + inline ::capnp::AnyPointer::Reader getAnyPointer() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Value::Builder { +public: + typedef Value 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline Which which(); + inline bool isVoid(); + inline ::capnp::Void getVoid(); + inline void setVoid( ::capnp::Void value = ::capnp::VOID); + + inline bool isBool(); + inline bool getBool(); + inline void setBool(bool value); + + inline bool isInt8(); + inline ::int8_t getInt8(); + inline void setInt8( ::int8_t value); + + inline bool isInt16(); + inline ::int16_t getInt16(); + inline void setInt16( ::int16_t value); + + inline bool isInt32(); + inline ::int32_t getInt32(); + inline void setInt32( ::int32_t value); + + inline bool isInt64(); + inline ::int64_t getInt64(); + inline void setInt64( ::int64_t value); + + inline bool isUint8(); + inline ::uint8_t getUint8(); + inline void setUint8( ::uint8_t value); + + inline bool isUint16(); + inline ::uint16_t getUint16(); + inline void setUint16( ::uint16_t value); + + inline bool isUint32(); + inline ::uint32_t getUint32(); + inline void setUint32( ::uint32_t value); + + inline bool isUint64(); + inline ::uint64_t getUint64(); + inline void setUint64( ::uint64_t value); + + inline bool isFloat32(); + inline float getFloat32(); + inline void setFloat32(float value); + + inline bool isFloat64(); + inline double getFloat64(); + inline void setFloat64(double value); + + inline bool isText(); + inline bool hasText(); + inline ::capnp::Text::Builder getText(); + inline void setText( ::capnp::Text::Reader value); + inline ::capnp::Text::Builder initText(unsigned int size); + inline void adoptText(::capnp::Orphan< ::capnp::Text>&& value); + inline ::capnp::Orphan< ::capnp::Text> disownText(); + + inline bool isData(); + inline bool hasData(); + inline ::capnp::Data::Builder getData(); + inline void setData( ::capnp::Data::Reader value); + inline ::capnp::Data::Builder initData(unsigned int size); + inline void adoptData(::capnp::Orphan< ::capnp::Data>&& value); + inline ::capnp::Orphan< ::capnp::Data> disownData(); + + inline bool isList(); + inline bool hasList(); + inline ::capnp::AnyPointer::Builder getList(); + inline ::capnp::AnyPointer::Builder initList(); + + inline bool isEnum(); + inline ::uint16_t getEnum(); + inline void setEnum( ::uint16_t value); + + inline bool isStruct(); + inline bool hasStruct(); + inline ::capnp::AnyPointer::Builder getStruct(); + inline ::capnp::AnyPointer::Builder initStruct(); + + inline bool isInterface(); + inline ::capnp::Void getInterface(); + inline void setInterface( ::capnp::Void value = ::capnp::VOID); + + inline bool isAnyPointer(); + inline bool hasAnyPointer(); + inline ::capnp::AnyPointer::Builder getAnyPointer(); + inline ::capnp::AnyPointer::Builder initAnyPointer(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +class Annotation::Reader { +public: + typedef Annotation Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } + + inline ::uint64_t getId() const; + + inline bool hasValue() const; + inline ::capnp::schema::Value::Reader getValue() const; + + inline bool hasBrand() const; + inline ::capnp::schema::Brand::Reader getBrand() const; + +private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Annotation::Builder { +public: + typedef Annotation 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(); } + inline ::kj::StringTree toString() const { return asReader().toString(); } + + inline ::uint64_t getId(); + inline void setId( ::uint64_t value); + + inline bool hasValue(); + inline ::capnp::schema::Value::Builder getValue(); + inline void setValue( ::capnp::schema::Value::Reader value); + inline ::capnp::schema::Value::Builder initValue(); + inline void adoptValue(::capnp::Orphan< ::capnp::schema::Value>&& value); + inline ::capnp::Orphan< ::capnp::schema::Value> disownValue(); + + inline bool hasBrand(); + inline ::capnp::schema::Brand::Builder getBrand(); + inline void setBrand( ::capnp::schema::Brand::Reader value); + inline ::capnp::schema::Brand::Builder initBrand(); + inline void adoptBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); + inline ::capnp::Orphan< ::capnp::schema::Brand> disownBrand(); + +private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + + +// ======================================================================================= + +inline ::capnp::schema::Node::Which Node::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS); +} +inline ::capnp::schema::Node::Which Node::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Node::Reader::getId() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Node::Builder::getId() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Node::Builder::setId( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Reader::hasDisplayName() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Node::Builder::hasDisplayName() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Node::Reader::getDisplayName() const { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::Text::Builder Node::Builder::getDisplayName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Node::Builder::setDisplayName( ::capnp::Text::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Node::Builder::initDisplayName(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Node::Builder::adoptDisplayName( + ::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> Node::Builder::disownDisplayName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::uint32_t Node::Reader::getDisplayNamePrefixLength() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Node::Builder::getDisplayNamePrefixLength() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} +inline void Node::Builder::setDisplayNamePrefixLength( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); +} + +inline ::uint64_t Node::Reader::getScopeId() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Node::Builder::getScopeId() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} +inline void Node::Builder::setScopeId( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Reader::hasNestedNodes() const { + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool Node::Builder::hasNestedNodes() { + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Reader Node::Reader::getNestedNodes() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Builder Node::Builder::getNestedNodes() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Node::Builder::setNestedNodes( ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Builder Node::Builder::initNestedNodes(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), size); +} +inline void Node::Builder::adoptNestedNodes( + ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>> Node::Builder::disownNestedNodes() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +inline bool Node::Reader::hasAnnotations() const { + return !_reader.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); +} +inline bool Node::Builder::hasAnnotations() { + return !_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader Node::Reader::getAnnotations() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Node::Builder::getAnnotations() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline void Node::Builder::setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Node::Builder::initAnnotations(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), size); +} +inline void Node::Builder::adoptAnnotations( + ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> Node::Builder::disownAnnotations() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} + +inline bool Node::Reader::isFile() const { + return which() == Node::FILE; +} +inline bool Node::Builder::isFile() { + return which() == Node::FILE; +} +inline ::capnp::Void Node::Reader::getFile() const { + KJ_IREQUIRE((which() == Node::FILE), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Node::Builder::getFile() { + KJ_IREQUIRE((which() == Node::FILE), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Node::Builder::setFile( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Node::FILE); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Reader::isStruct() const { + return which() == Node::STRUCT; +} +inline bool Node::Builder::isStruct() { + return which() == Node::STRUCT; +} +inline typename Node::Struct::Reader Node::Reader::getStruct() const { + KJ_IREQUIRE((which() == Node::STRUCT), + "Must check which() before get()ing a union member."); + return typename Node::Struct::Reader(_reader); +} +inline typename Node::Struct::Builder Node::Builder::getStruct() { + KJ_IREQUIRE((which() == Node::STRUCT), + "Must check which() before get()ing a union member."); + return typename Node::Struct::Builder(_builder); +} +inline typename Node::Struct::Builder Node::Builder::initStruct() { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Node::STRUCT); + _builder.setDataField< ::uint16_t>(::capnp::bounded<7>() * ::capnp::ELEMENTS, 0); + _builder.setDataField< ::uint16_t>(::capnp::bounded<12>() * ::capnp::ELEMENTS, 0); + _builder.setDataField< ::uint16_t>(::capnp::bounded<13>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<224>() * ::capnp::ELEMENTS, 0); + _builder.setDataField< ::uint16_t>(::capnp::bounded<15>() * ::capnp::ELEMENTS, 0); + _builder.setDataField< ::uint32_t>(::capnp::bounded<8>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); + return typename Node::Struct::Builder(_builder); +} +inline bool Node::Reader::isEnum() const { + return which() == Node::ENUM; +} +inline bool Node::Builder::isEnum() { + return which() == Node::ENUM; +} +inline typename Node::Enum::Reader Node::Reader::getEnum() const { + KJ_IREQUIRE((which() == Node::ENUM), + "Must check which() before get()ing a union member."); + return typename Node::Enum::Reader(_reader); +} +inline typename Node::Enum::Builder Node::Builder::getEnum() { + KJ_IREQUIRE((which() == Node::ENUM), + "Must check which() before get()ing a union member."); + return typename Node::Enum::Builder(_builder); +} +inline typename Node::Enum::Builder Node::Builder::initEnum() { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Node::ENUM); + _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); + return typename Node::Enum::Builder(_builder); +} +inline bool Node::Reader::isInterface() const { + return which() == Node::INTERFACE; +} +inline bool Node::Builder::isInterface() { + return which() == Node::INTERFACE; +} +inline typename Node::Interface::Reader Node::Reader::getInterface() const { + KJ_IREQUIRE((which() == Node::INTERFACE), + "Must check which() before get()ing a union member."); + return typename Node::Interface::Reader(_reader); +} +inline typename Node::Interface::Builder Node::Builder::getInterface() { + KJ_IREQUIRE((which() == Node::INTERFACE), + "Must check which() before get()ing a union member."); + return typename Node::Interface::Builder(_builder); +} +inline typename Node::Interface::Builder Node::Builder::initInterface() { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Node::INTERFACE); + _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); + _builder.getPointerField(::capnp::bounded<4>() * ::capnp::POINTERS).clear(); + return typename Node::Interface::Builder(_builder); +} +inline bool Node::Reader::isConst() const { + return which() == Node::CONST; +} +inline bool Node::Builder::isConst() { + return which() == Node::CONST; +} +inline typename Node::Const::Reader Node::Reader::getConst() const { + KJ_IREQUIRE((which() == Node::CONST), + "Must check which() before get()ing a union member."); + return typename Node::Const::Reader(_reader); +} +inline typename Node::Const::Builder Node::Builder::getConst() { + KJ_IREQUIRE((which() == Node::CONST), + "Must check which() before get()ing a union member."); + return typename Node::Const::Builder(_builder); +} +inline typename Node::Const::Builder Node::Builder::initConst() { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Node::CONST); + _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); + _builder.getPointerField(::capnp::bounded<4>() * ::capnp::POINTERS).clear(); + return typename Node::Const::Builder(_builder); +} +inline bool Node::Reader::isAnnotation() const { + return which() == Node::ANNOTATION; +} +inline bool Node::Builder::isAnnotation() { + return which() == Node::ANNOTATION; +} +inline typename Node::Annotation::Reader Node::Reader::getAnnotation() const { + KJ_IREQUIRE((which() == Node::ANNOTATION), + "Must check which() before get()ing a union member."); + return typename Node::Annotation::Reader(_reader); +} +inline typename Node::Annotation::Builder Node::Builder::getAnnotation() { + KJ_IREQUIRE((which() == Node::ANNOTATION), + "Must check which() before get()ing a union member."); + return typename Node::Annotation::Builder(_builder); +} +inline typename Node::Annotation::Builder Node::Builder::initAnnotation() { + _builder.setDataField( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, Node::ANNOTATION); + _builder.setDataField(::capnp::bounded<112>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<113>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<114>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<115>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<116>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<117>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<118>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<119>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<120>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<121>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<122>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<123>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); + return typename Node::Annotation::Builder(_builder); +} +inline bool Node::Reader::hasParameters() const { + return !_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline bool Node::Builder::hasParameters() { + return !_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader Node::Reader::getParameters() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder Node::Builder::getParameters() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} +inline void Node::Builder::setParameters( ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder Node::Builder::initParameters(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), size); +} +inline void Node::Builder::adoptParameters( + ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>> Node::Builder::disownParameters() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<5>() * ::capnp::POINTERS)); +} + +inline bool Node::Reader::getIsGeneric() const { + return _reader.getDataField( + ::capnp::bounded<288>() * ::capnp::ELEMENTS); +} + +inline bool Node::Builder::getIsGeneric() { + return _builder.getDataField( + ::capnp::bounded<288>() * ::capnp::ELEMENTS); +} +inline void Node::Builder::setIsGeneric(bool value) { + _builder.setDataField( + ::capnp::bounded<288>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t Node::Reader::getStartByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<10>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Node::Builder::getStartByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<10>() * ::capnp::ELEMENTS); +} +inline void Node::Builder::setStartByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<10>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t Node::Reader::getEndByte() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<11>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Node::Builder::getEndByte() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<11>() * ::capnp::ELEMENTS); +} +inline void Node::Builder::setEndByte( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<11>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Parameter::Reader::hasName() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Node::Parameter::Builder::hasName() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Node::Parameter::Reader::getName() const { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::Text::Builder Node::Parameter::Builder::getName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Node::Parameter::Builder::setName( ::capnp::Text::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Node::Parameter::Builder::initName(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Node::Parameter::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> Node::Parameter::Builder::disownName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Node::NestedNode::Reader::hasName() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Node::NestedNode::Builder::hasName() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Node::NestedNode::Reader::getName() const { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::Text::Builder Node::NestedNode::Builder::getName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Node::NestedNode::Builder::setName( ::capnp::Text::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Node::NestedNode::Builder::initName(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Node::NestedNode::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> Node::NestedNode::Builder::disownName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::uint64_t Node::NestedNode::Reader::getId() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Node::NestedNode::Builder::getId() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Node::NestedNode::Builder::setId( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline ::uint16_t Node::Struct::Reader::getDataWordCount() const { + return _reader.getDataField< ::uint16_t>( + ::capnp::bounded<7>() * ::capnp::ELEMENTS); +} + +inline ::uint16_t Node::Struct::Builder::getDataWordCount() { + return _builder.getDataField< ::uint16_t>( + ::capnp::bounded<7>() * ::capnp::ELEMENTS); +} +inline void Node::Struct::Builder::setDataWordCount( ::uint16_t value) { + _builder.setDataField< ::uint16_t>( + ::capnp::bounded<7>() * ::capnp::ELEMENTS, value); +} + +inline ::uint16_t Node::Struct::Reader::getPointerCount() const { + return _reader.getDataField< ::uint16_t>( + ::capnp::bounded<12>() * ::capnp::ELEMENTS); +} + +inline ::uint16_t Node::Struct::Builder::getPointerCount() { + return _builder.getDataField< ::uint16_t>( + ::capnp::bounded<12>() * ::capnp::ELEMENTS); +} +inline void Node::Struct::Builder::setPointerCount( ::uint16_t value) { + _builder.setDataField< ::uint16_t>( + ::capnp::bounded<12>() * ::capnp::ELEMENTS, value); +} + +inline ::capnp::schema::ElementSize Node::Struct::Reader::getPreferredListEncoding() const { + return _reader.getDataField< ::capnp::schema::ElementSize>( + ::capnp::bounded<13>() * ::capnp::ELEMENTS); +} + +inline ::capnp::schema::ElementSize Node::Struct::Builder::getPreferredListEncoding() { + return _builder.getDataField< ::capnp::schema::ElementSize>( + ::capnp::bounded<13>() * ::capnp::ELEMENTS); +} +inline void Node::Struct::Builder::setPreferredListEncoding( ::capnp::schema::ElementSize value) { + _builder.setDataField< ::capnp::schema::ElementSize>( + ::capnp::bounded<13>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Struct::Reader::getIsGroup() const { + return _reader.getDataField( + ::capnp::bounded<224>() * ::capnp::ELEMENTS); +} + +inline bool Node::Struct::Builder::getIsGroup() { + return _builder.getDataField( + ::capnp::bounded<224>() * ::capnp::ELEMENTS); +} +inline void Node::Struct::Builder::setIsGroup(bool value) { + _builder.setDataField( + ::capnp::bounded<224>() * ::capnp::ELEMENTS, value); +} + +inline ::uint16_t Node::Struct::Reader::getDiscriminantCount() const { + return _reader.getDataField< ::uint16_t>( + ::capnp::bounded<15>() * ::capnp::ELEMENTS); +} + +inline ::uint16_t Node::Struct::Builder::getDiscriminantCount() { + return _builder.getDataField< ::uint16_t>( + ::capnp::bounded<15>() * ::capnp::ELEMENTS); +} +inline void Node::Struct::Builder::setDiscriminantCount( ::uint16_t value) { + _builder.setDataField< ::uint16_t>( + ::capnp::bounded<15>() * ::capnp::ELEMENTS, value); +} + +inline ::uint32_t Node::Struct::Reader::getDiscriminantOffset() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<8>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Node::Struct::Builder::getDiscriminantOffset() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<8>() * ::capnp::ELEMENTS); +} +inline void Node::Struct::Builder::setDiscriminantOffset( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<8>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Struct::Reader::hasFields() const { + return !_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline bool Node::Struct::Builder::hasFields() { + return !_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Reader Node::Struct::Reader::getFields() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Builder Node::Struct::Builder::getFields() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Node::Struct::Builder::setFields( ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Builder Node::Struct::Builder::initFields(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), size); +} +inline void Node::Struct::Builder::adoptFields( + ::capnp::Orphan< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>> Node::Struct::Builder::disownFields() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} + +inline bool Node::Enum::Reader::hasEnumerants() const { + return !_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline bool Node::Enum::Builder::hasEnumerants() { + return !_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Reader Node::Enum::Reader::getEnumerants() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Builder Node::Enum::Builder::getEnumerants() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Node::Enum::Builder::setEnumerants( ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Builder Node::Enum::Builder::initEnumerants(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), size); +} +inline void Node::Enum::Builder::adoptEnumerants( + ::capnp::Orphan< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>> Node::Enum::Builder::disownEnumerants() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} + +inline bool Node::Interface::Reader::hasMethods() const { + return !_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline bool Node::Interface::Builder::hasMethods() { + return !_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Reader Node::Interface::Reader::getMethods() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Builder Node::Interface::Builder::getMethods() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Node::Interface::Builder::setMethods( ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Builder Node::Interface::Builder::initMethods(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), size); +} +inline void Node::Interface::Builder::adoptMethods( + ::capnp::Orphan< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>> Node::Interface::Builder::disownMethods() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} + +inline bool Node::Interface::Reader::hasSuperclasses() const { + return !_reader.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); +} +inline bool Node::Interface::Builder::hasSuperclasses() { + return !_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Reader Node::Interface::Reader::getSuperclasses() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Builder Node::Interface::Builder::getSuperclasses() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS)); +} +inline void Node::Interface::Builder::setSuperclasses( ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Builder Node::Interface::Builder::initSuperclasses(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS), size); +} +inline void Node::Interface::Builder::adoptSuperclasses( + ::capnp::Orphan< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>> Node::Interface::Builder::disownSuperclasses() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS)); +} + +inline bool Node::Const::Reader::hasType() const { + return !_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline bool Node::Const::Builder::hasType() { + return !_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Type::Reader Node::Const::Reader::getType() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Type::Builder Node::Const::Builder::getType() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Node::Const::Builder::setType( ::capnp::schema::Type::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Type>::set(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Type::Builder Node::Const::Builder::initType() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::init(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Node::Const::Builder::adoptType( + ::capnp::Orphan< ::capnp::schema::Type>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Type>::adopt(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Type> Node::Const::Builder::disownType() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::disown(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} + +inline bool Node::Const::Reader::hasValue() const { + return !_reader.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); +} +inline bool Node::Const::Builder::hasValue() { + return !_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Value::Reader Node::Const::Reader::getValue() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::get(_reader.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Value::Builder Node::Const::Builder::getValue() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::get(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS)); +} +inline void Node::Const::Builder::setValue( ::capnp::schema::Value::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Value>::set(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Value::Builder Node::Const::Builder::initValue() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::init(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS)); +} +inline void Node::Const::Builder::adoptValue( + ::capnp::Orphan< ::capnp::schema::Value>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Value>::adopt(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Value> Node::Const::Builder::disownValue() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::disown(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS)); +} + +inline bool Node::Annotation::Reader::hasType() const { + return !_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline bool Node::Annotation::Builder::hasType() { + return !_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Type::Reader Node::Annotation::Reader::getType() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Type::Builder Node::Annotation::Builder::getType() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Node::Annotation::Builder::setType( ::capnp::schema::Type::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Type>::set(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Type::Builder Node::Annotation::Builder::initType() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::init(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Node::Annotation::Builder::adoptType( + ::capnp::Orphan< ::capnp::schema::Type>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Type>::adopt(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Type> Node::Annotation::Builder::disownType() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::disown(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} + +inline bool Node::Annotation::Reader::getTargetsFile() const { + return _reader.getDataField( + ::capnp::bounded<112>() * ::capnp::ELEMENTS); +} + +inline bool Node::Annotation::Builder::getTargetsFile() { + return _builder.getDataField( + ::capnp::bounded<112>() * ::capnp::ELEMENTS); +} +inline void Node::Annotation::Builder::setTargetsFile(bool value) { + _builder.setDataField( + ::capnp::bounded<112>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Annotation::Reader::getTargetsConst() const { + return _reader.getDataField( + ::capnp::bounded<113>() * ::capnp::ELEMENTS); +} + +inline bool Node::Annotation::Builder::getTargetsConst() { + return _builder.getDataField( + ::capnp::bounded<113>() * ::capnp::ELEMENTS); +} +inline void Node::Annotation::Builder::setTargetsConst(bool value) { + _builder.setDataField( + ::capnp::bounded<113>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Annotation::Reader::getTargetsEnum() const { + return _reader.getDataField( + ::capnp::bounded<114>() * ::capnp::ELEMENTS); +} + +inline bool Node::Annotation::Builder::getTargetsEnum() { + return _builder.getDataField( + ::capnp::bounded<114>() * ::capnp::ELEMENTS); +} +inline void Node::Annotation::Builder::setTargetsEnum(bool value) { + _builder.setDataField( + ::capnp::bounded<114>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Annotation::Reader::getTargetsEnumerant() const { + return _reader.getDataField( + ::capnp::bounded<115>() * ::capnp::ELEMENTS); +} + +inline bool Node::Annotation::Builder::getTargetsEnumerant() { + return _builder.getDataField( + ::capnp::bounded<115>() * ::capnp::ELEMENTS); +} +inline void Node::Annotation::Builder::setTargetsEnumerant(bool value) { + _builder.setDataField( + ::capnp::bounded<115>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Annotation::Reader::getTargetsStruct() const { + return _reader.getDataField( + ::capnp::bounded<116>() * ::capnp::ELEMENTS); +} + +inline bool Node::Annotation::Builder::getTargetsStruct() { + return _builder.getDataField( + ::capnp::bounded<116>() * ::capnp::ELEMENTS); +} +inline void Node::Annotation::Builder::setTargetsStruct(bool value) { + _builder.setDataField( + ::capnp::bounded<116>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Annotation::Reader::getTargetsField() const { + return _reader.getDataField( + ::capnp::bounded<117>() * ::capnp::ELEMENTS); +} + +inline bool Node::Annotation::Builder::getTargetsField() { + return _builder.getDataField( + ::capnp::bounded<117>() * ::capnp::ELEMENTS); +} +inline void Node::Annotation::Builder::setTargetsField(bool value) { + _builder.setDataField( + ::capnp::bounded<117>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Annotation::Reader::getTargetsUnion() const { + return _reader.getDataField( + ::capnp::bounded<118>() * ::capnp::ELEMENTS); +} + +inline bool Node::Annotation::Builder::getTargetsUnion() { + return _builder.getDataField( + ::capnp::bounded<118>() * ::capnp::ELEMENTS); +} +inline void Node::Annotation::Builder::setTargetsUnion(bool value) { + _builder.setDataField( + ::capnp::bounded<118>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Annotation::Reader::getTargetsGroup() const { + return _reader.getDataField( + ::capnp::bounded<119>() * ::capnp::ELEMENTS); +} + +inline bool Node::Annotation::Builder::getTargetsGroup() { + return _builder.getDataField( + ::capnp::bounded<119>() * ::capnp::ELEMENTS); +} +inline void Node::Annotation::Builder::setTargetsGroup(bool value) { + _builder.setDataField( + ::capnp::bounded<119>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Annotation::Reader::getTargetsInterface() const { + return _reader.getDataField( + ::capnp::bounded<120>() * ::capnp::ELEMENTS); +} + +inline bool Node::Annotation::Builder::getTargetsInterface() { + return _builder.getDataField( + ::capnp::bounded<120>() * ::capnp::ELEMENTS); +} +inline void Node::Annotation::Builder::setTargetsInterface(bool value) { + _builder.setDataField( + ::capnp::bounded<120>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Annotation::Reader::getTargetsMethod() const { + return _reader.getDataField( + ::capnp::bounded<121>() * ::capnp::ELEMENTS); +} + +inline bool Node::Annotation::Builder::getTargetsMethod() { + return _builder.getDataField( + ::capnp::bounded<121>() * ::capnp::ELEMENTS); +} +inline void Node::Annotation::Builder::setTargetsMethod(bool value) { + _builder.setDataField( + ::capnp::bounded<121>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Annotation::Reader::getTargetsParam() const { + return _reader.getDataField( + ::capnp::bounded<122>() * ::capnp::ELEMENTS); +} + +inline bool Node::Annotation::Builder::getTargetsParam() { + return _builder.getDataField( + ::capnp::bounded<122>() * ::capnp::ELEMENTS); +} +inline void Node::Annotation::Builder::setTargetsParam(bool value) { + _builder.setDataField( + ::capnp::bounded<122>() * ::capnp::ELEMENTS, value); +} + +inline bool Node::Annotation::Reader::getTargetsAnnotation() const { + return _reader.getDataField( + ::capnp::bounded<123>() * ::capnp::ELEMENTS); +} + +inline bool Node::Annotation::Builder::getTargetsAnnotation() { + return _builder.getDataField( + ::capnp::bounded<123>() * ::capnp::ELEMENTS); +} +inline void Node::Annotation::Builder::setTargetsAnnotation(bool value) { + _builder.setDataField( + ::capnp::bounded<123>() * ::capnp::ELEMENTS, value); +} + +inline ::capnp::schema::Field::Which Field::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS); +} +inline ::capnp::schema::Field::Which Field::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS); +} + +inline bool Field::Reader::hasName() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Field::Builder::hasName() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Field::Reader::getName() const { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::Text::Builder Field::Builder::getName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Field::Builder::setName( ::capnp::Text::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Field::Builder::initName(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void 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> Field::Builder::disownName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::uint16_t Field::Reader::getCodeOrder() const { + return _reader.getDataField< ::uint16_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::uint16_t Field::Builder::getCodeOrder() { + return _builder.getDataField< ::uint16_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Field::Builder::setCodeOrder( ::uint16_t value) { + _builder.setDataField< ::uint16_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Field::Reader::hasAnnotations() const { + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool Field::Builder::hasAnnotations() { + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader Field::Reader::getAnnotations() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Field::Builder::getAnnotations() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Field::Builder::setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Field::Builder::initAnnotations(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), size); +} +inline void Field::Builder::adoptAnnotations( + ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> Field::Builder::disownAnnotations() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +inline ::uint16_t Field::Reader::getDiscriminantValue() const { + return _reader.getDataField< ::uint16_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, 65535u); +} + +inline ::uint16_t Field::Builder::getDiscriminantValue() { + return _builder.getDataField< ::uint16_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, 65535u); +} +inline void Field::Builder::setDiscriminantValue( ::uint16_t value) { + _builder.setDataField< ::uint16_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value, 65535u); +} + +inline bool Field::Reader::isSlot() const { + return which() == Field::SLOT; +} +inline bool Field::Builder::isSlot() { + return which() == Field::SLOT; +} +inline typename Field::Slot::Reader Field::Reader::getSlot() const { + KJ_IREQUIRE((which() == Field::SLOT), + "Must check which() before get()ing a union member."); + return typename Field::Slot::Reader(_reader); +} +inline typename Field::Slot::Builder Field::Builder::getSlot() { + KJ_IREQUIRE((which() == Field::SLOT), + "Must check which() before get()ing a union member."); + return typename Field::Slot::Builder(_builder); +} +inline typename Field::Slot::Builder Field::Builder::initSlot() { + _builder.setDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS, Field::SLOT); + _builder.setDataField< ::uint32_t>(::capnp::bounded<1>() * ::capnp::ELEMENTS, 0); + _builder.setDataField(::capnp::bounded<128>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<2>() * ::capnp::POINTERS).clear(); + _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); + return typename Field::Slot::Builder(_builder); +} +inline bool Field::Reader::isGroup() const { + return which() == Field::GROUP; +} +inline bool Field::Builder::isGroup() { + return which() == Field::GROUP; +} +inline typename Field::Group::Reader Field::Reader::getGroup() const { + KJ_IREQUIRE((which() == Field::GROUP), + "Must check which() before get()ing a union member."); + return typename Field::Group::Reader(_reader); +} +inline typename Field::Group::Builder Field::Builder::getGroup() { + KJ_IREQUIRE((which() == Field::GROUP), + "Must check which() before get()ing a union member."); + return typename Field::Group::Builder(_builder); +} +inline typename Field::Group::Builder Field::Builder::initGroup() { + _builder.setDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS, Field::GROUP); + _builder.setDataField< ::uint64_t>(::capnp::bounded<2>() * ::capnp::ELEMENTS, 0); + return typename Field::Group::Builder(_builder); +} +inline typename Field::Ordinal::Reader Field::Reader::getOrdinal() const { + return typename Field::Ordinal::Reader(_reader); +} +inline typename Field::Ordinal::Builder Field::Builder::getOrdinal() { + return typename Field::Ordinal::Builder(_builder); +} +inline typename Field::Ordinal::Builder Field::Builder::initOrdinal() { + _builder.setDataField< ::uint16_t>(::capnp::bounded<5>() * ::capnp::ELEMENTS, 0); + _builder.setDataField< ::uint16_t>(::capnp::bounded<6>() * ::capnp::ELEMENTS, 0); + return typename Field::Ordinal::Builder(_builder); +} +inline ::uint32_t Field::Slot::Reader::getOffset() const { + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Field::Slot::Builder::getOffset() { + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Field::Slot::Builder::setOffset( ::uint32_t value) { + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Field::Slot::Reader::hasType() const { + return !_reader.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); +} +inline bool Field::Slot::Builder::hasType() { + return !_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Type::Reader Field::Slot::Reader::getType() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_reader.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Type::Builder Field::Slot::Builder::getType() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline void Field::Slot::Builder::setType( ::capnp::schema::Type::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Type>::set(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Type::Builder Field::Slot::Builder::initType() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::init(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline void Field::Slot::Builder::adoptType( + ::capnp::Orphan< ::capnp::schema::Type>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Type>::adopt(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Type> Field::Slot::Builder::disownType() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::disown(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} + +inline bool Field::Slot::Reader::hasDefaultValue() const { + return !_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline bool Field::Slot::Builder::hasDefaultValue() { + return !_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Value::Reader Field::Slot::Reader::getDefaultValue() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::get(_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Value::Builder Field::Slot::Builder::getDefaultValue() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::get(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Field::Slot::Builder::setDefaultValue( ::capnp::schema::Value::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Value>::set(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Value::Builder Field::Slot::Builder::initDefaultValue() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::init(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Field::Slot::Builder::adoptDefaultValue( + ::capnp::Orphan< ::capnp::schema::Value>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Value>::adopt(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Value> Field::Slot::Builder::disownDefaultValue() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::disown(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} + +inline bool Field::Slot::Reader::getHadExplicitDefault() const { + return _reader.getDataField( + ::capnp::bounded<128>() * ::capnp::ELEMENTS); +} + +inline bool Field::Slot::Builder::getHadExplicitDefault() { + return _builder.getDataField( + ::capnp::bounded<128>() * ::capnp::ELEMENTS); +} +inline void Field::Slot::Builder::setHadExplicitDefault(bool value) { + _builder.setDataField( + ::capnp::bounded<128>() * ::capnp::ELEMENTS, value); +} + +inline ::uint64_t Field::Group::Reader::getTypeId() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Field::Group::Builder::getTypeId() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} +inline void Field::Group::Builder::setTypeId( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); +} + +inline ::capnp::schema::Field::Ordinal::Which Field::Ordinal::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<5>() * ::capnp::ELEMENTS); +} +inline ::capnp::schema::Field::Ordinal::Which Field::Ordinal::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<5>() * ::capnp::ELEMENTS); +} + +inline bool Field::Ordinal::Reader::isImplicit() const { + return which() == Field::Ordinal::IMPLICIT; +} +inline bool Field::Ordinal::Builder::isImplicit() { + return which() == Field::Ordinal::IMPLICIT; +} +inline ::capnp::Void Field::Ordinal::Reader::getImplicit() const { + KJ_IREQUIRE((which() == Field::Ordinal::IMPLICIT), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Field::Ordinal::Builder::getImplicit() { + KJ_IREQUIRE((which() == Field::Ordinal::IMPLICIT), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Field::Ordinal::Builder::setImplicit( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<5>() * ::capnp::ELEMENTS, Field::Ordinal::IMPLICIT); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Field::Ordinal::Reader::isExplicit() const { + return which() == Field::Ordinal::EXPLICIT; +} +inline bool Field::Ordinal::Builder::isExplicit() { + return which() == Field::Ordinal::EXPLICIT; +} +inline ::uint16_t Field::Ordinal::Reader::getExplicit() const { + KJ_IREQUIRE((which() == Field::Ordinal::EXPLICIT), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::uint16_t>( + ::capnp::bounded<6>() * ::capnp::ELEMENTS); +} + +inline ::uint16_t Field::Ordinal::Builder::getExplicit() { + KJ_IREQUIRE((which() == Field::Ordinal::EXPLICIT), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::uint16_t>( + ::capnp::bounded<6>() * ::capnp::ELEMENTS); +} +inline void Field::Ordinal::Builder::setExplicit( ::uint16_t value) { + _builder.setDataField( + ::capnp::bounded<5>() * ::capnp::ELEMENTS, Field::Ordinal::EXPLICIT); + _builder.setDataField< ::uint16_t>( + ::capnp::bounded<6>() * ::capnp::ELEMENTS, value); +} + +inline bool Enumerant::Reader::hasName() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Enumerant::Builder::hasName() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Enumerant::Reader::getName() const { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::Text::Builder Enumerant::Builder::getName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Enumerant::Builder::setName( ::capnp::Text::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Enumerant::Builder::initName(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Enumerant::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> Enumerant::Builder::disownName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::uint16_t Enumerant::Reader::getCodeOrder() const { + return _reader.getDataField< ::uint16_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::uint16_t Enumerant::Builder::getCodeOrder() { + return _builder.getDataField< ::uint16_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Enumerant::Builder::setCodeOrder( ::uint16_t value) { + _builder.setDataField< ::uint16_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Enumerant::Reader::hasAnnotations() const { + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool Enumerant::Builder::hasAnnotations() { + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader Enumerant::Reader::getAnnotations() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Enumerant::Builder::getAnnotations() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Enumerant::Builder::setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Enumerant::Builder::initAnnotations(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), size); +} +inline void Enumerant::Builder::adoptAnnotations( + ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> Enumerant::Builder::disownAnnotations() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +inline ::uint64_t Superclass::Reader::getId() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Superclass::Builder::getId() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Superclass::Builder::setId( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Superclass::Reader::hasBrand() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Superclass::Builder::hasBrand() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Brand::Reader Superclass::Reader::getBrand() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Brand::Builder Superclass::Builder::getBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Superclass::Builder::setBrand( ::capnp::schema::Brand::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Brand::Builder Superclass::Builder::initBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Superclass::Builder::adoptBrand( + ::capnp::Orphan< ::capnp::schema::Brand>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Brand> Superclass::Builder::disownBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Method::Reader::hasName() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Method::Builder::hasName() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Method::Reader::getName() const { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::Text::Builder Method::Builder::getName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Method::Builder::setName( ::capnp::Text::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Method::Builder::initName(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Method::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> Method::Builder::disownName() { + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::uint16_t Method::Reader::getCodeOrder() const { + return _reader.getDataField< ::uint16_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::uint16_t Method::Builder::getCodeOrder() { + return _builder.getDataField< ::uint16_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Method::Builder::setCodeOrder( ::uint16_t value) { + _builder.setDataField< ::uint16_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline ::uint64_t Method::Reader::getParamStructType() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Method::Builder::getParamStructType() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Method::Builder::setParamStructType( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline ::uint64_t Method::Reader::getResultStructType() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Method::Builder::getResultStructType() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} +inline void Method::Builder::setResultStructType( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); +} + +inline bool Method::Reader::hasAnnotations() const { + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool Method::Builder::hasAnnotations() { + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader Method::Reader::getAnnotations() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Method::Builder::getAnnotations() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Method::Builder::setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Method::Builder::initAnnotations(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), size); +} +inline void Method::Builder::adoptAnnotations( + ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> Method::Builder::disownAnnotations() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +inline bool Method::Reader::hasParamBrand() const { + return !_reader.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); +} +inline bool Method::Builder::hasParamBrand() { + return !_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Brand::Reader Method::Reader::getParamBrand() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Brand::Builder Method::Builder::getParamBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline void Method::Builder::setParamBrand( ::capnp::schema::Brand::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Brand::Builder Method::Builder::initParamBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline void Method::Builder::adoptParamBrand( + ::capnp::Orphan< ::capnp::schema::Brand>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Brand> Method::Builder::disownParamBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( + ::capnp::bounded<2>() * ::capnp::POINTERS)); +} + +inline bool Method::Reader::hasResultBrand() const { + return !_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline bool Method::Builder::hasResultBrand() { + return !_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Brand::Reader Method::Reader::getResultBrand() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Brand::Builder Method::Builder::getResultBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Method::Builder::setResultBrand( ::capnp::schema::Brand::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Brand::Builder Method::Builder::initResultBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void Method::Builder::adoptResultBrand( + ::capnp::Orphan< ::capnp::schema::Brand>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Brand> Method::Builder::disownResultBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} + +inline bool Method::Reader::hasImplicitParameters() const { + return !_reader.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); +} +inline bool Method::Builder::hasImplicitParameters() { + return !_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader Method::Reader::getImplicitParameters() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder Method::Builder::getImplicitParameters() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS)); +} +inline void Method::Builder::setImplicitParameters( ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder Method::Builder::initImplicitParameters(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS), size); +} +inline void Method::Builder::adoptImplicitParameters( + ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>> Method::Builder::disownImplicitParameters() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<4>() * ::capnp::POINTERS)); +} + +inline ::capnp::schema::Type::Which Type::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline ::capnp::schema::Type::Which Type::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline bool Type::Reader::isVoid() const { + return which() == Type::VOID; +} +inline bool Type::Builder::isVoid() { + return which() == Type::VOID; +} +inline ::capnp::Void Type::Reader::getVoid() const { + KJ_IREQUIRE((which() == Type::VOID), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getVoid() { + KJ_IREQUIRE((which() == Type::VOID), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setVoid( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::VOID); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isBool() const { + return which() == Type::BOOL; +} +inline bool Type::Builder::isBool() { + return which() == Type::BOOL; +} +inline ::capnp::Void Type::Reader::getBool() const { + KJ_IREQUIRE((which() == Type::BOOL), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getBool() { + KJ_IREQUIRE((which() == Type::BOOL), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setBool( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::BOOL); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isInt8() const { + return which() == Type::INT8; +} +inline bool Type::Builder::isInt8() { + return which() == Type::INT8; +} +inline ::capnp::Void Type::Reader::getInt8() const { + KJ_IREQUIRE((which() == Type::INT8), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getInt8() { + KJ_IREQUIRE((which() == Type::INT8), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setInt8( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::INT8); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isInt16() const { + return which() == Type::INT16; +} +inline bool Type::Builder::isInt16() { + return which() == Type::INT16; +} +inline ::capnp::Void Type::Reader::getInt16() const { + KJ_IREQUIRE((which() == Type::INT16), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getInt16() { + KJ_IREQUIRE((which() == Type::INT16), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setInt16( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::INT16); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isInt32() const { + return which() == Type::INT32; +} +inline bool Type::Builder::isInt32() { + return which() == Type::INT32; +} +inline ::capnp::Void Type::Reader::getInt32() const { + KJ_IREQUIRE((which() == Type::INT32), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getInt32() { + KJ_IREQUIRE((which() == Type::INT32), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setInt32( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::INT32); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isInt64() const { + return which() == Type::INT64; +} +inline bool Type::Builder::isInt64() { + return which() == Type::INT64; +} +inline ::capnp::Void Type::Reader::getInt64() const { + KJ_IREQUIRE((which() == Type::INT64), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getInt64() { + KJ_IREQUIRE((which() == Type::INT64), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setInt64( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::INT64); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isUint8() const { + return which() == Type::UINT8; +} +inline bool Type::Builder::isUint8() { + return which() == Type::UINT8; +} +inline ::capnp::Void Type::Reader::getUint8() const { + KJ_IREQUIRE((which() == Type::UINT8), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getUint8() { + KJ_IREQUIRE((which() == Type::UINT8), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setUint8( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::UINT8); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isUint16() const { + return which() == Type::UINT16; +} +inline bool Type::Builder::isUint16() { + return which() == Type::UINT16; +} +inline ::capnp::Void Type::Reader::getUint16() const { + KJ_IREQUIRE((which() == Type::UINT16), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getUint16() { + KJ_IREQUIRE((which() == Type::UINT16), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setUint16( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::UINT16); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isUint32() const { + return which() == Type::UINT32; +} +inline bool Type::Builder::isUint32() { + return which() == Type::UINT32; +} +inline ::capnp::Void Type::Reader::getUint32() const { + KJ_IREQUIRE((which() == Type::UINT32), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getUint32() { + KJ_IREQUIRE((which() == Type::UINT32), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setUint32( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::UINT32); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isUint64() const { + return which() == Type::UINT64; +} +inline bool Type::Builder::isUint64() { + return which() == Type::UINT64; +} +inline ::capnp::Void Type::Reader::getUint64() const { + KJ_IREQUIRE((which() == Type::UINT64), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getUint64() { + KJ_IREQUIRE((which() == Type::UINT64), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setUint64( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::UINT64); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isFloat32() const { + return which() == Type::FLOAT32; +} +inline bool Type::Builder::isFloat32() { + return which() == Type::FLOAT32; +} +inline ::capnp::Void Type::Reader::getFloat32() const { + KJ_IREQUIRE((which() == Type::FLOAT32), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getFloat32() { + KJ_IREQUIRE((which() == Type::FLOAT32), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setFloat32( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::FLOAT32); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isFloat64() const { + return which() == Type::FLOAT64; +} +inline bool Type::Builder::isFloat64() { + return which() == Type::FLOAT64; +} +inline ::capnp::Void Type::Reader::getFloat64() const { + KJ_IREQUIRE((which() == Type::FLOAT64), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getFloat64() { + KJ_IREQUIRE((which() == Type::FLOAT64), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setFloat64( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::FLOAT64); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isText() const { + return which() == Type::TEXT; +} +inline bool Type::Builder::isText() { + return which() == Type::TEXT; +} +inline ::capnp::Void Type::Reader::getText() const { + KJ_IREQUIRE((which() == Type::TEXT), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getText() { + KJ_IREQUIRE((which() == Type::TEXT), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setText( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::TEXT); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isData() const { + return which() == Type::DATA; +} +inline bool Type::Builder::isData() { + return which() == Type::DATA; +} +inline ::capnp::Void Type::Reader::getData() const { + KJ_IREQUIRE((which() == Type::DATA), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::Builder::getData() { + KJ_IREQUIRE((which() == Type::DATA), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::Builder::setData( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::DATA); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Reader::isList() const { + return which() == Type::LIST; +} +inline bool Type::Builder::isList() { + return which() == Type::LIST; +} +inline typename Type::List::Reader Type::Reader::getList() const { + KJ_IREQUIRE((which() == Type::LIST), + "Must check which() before get()ing a union member."); + return typename Type::List::Reader(_reader); +} +inline typename Type::List::Builder Type::Builder::getList() { + KJ_IREQUIRE((which() == Type::LIST), + "Must check which() before get()ing a union member."); + return typename Type::List::Builder(_builder); +} +inline typename Type::List::Builder Type::Builder::initList() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::LIST); + _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS).clear(); + return typename Type::List::Builder(_builder); +} +inline bool Type::Reader::isEnum() const { + return which() == Type::ENUM; +} +inline bool Type::Builder::isEnum() { + return which() == Type::ENUM; +} +inline typename Type::Enum::Reader Type::Reader::getEnum() const { + KJ_IREQUIRE((which() == Type::ENUM), + "Must check which() before get()ing a union member."); + return typename Type::Enum::Reader(_reader); +} +inline typename Type::Enum::Builder Type::Builder::getEnum() { + KJ_IREQUIRE((which() == Type::ENUM), + "Must check which() before get()ing a union member."); + return typename Type::Enum::Builder(_builder); +} +inline typename Type::Enum::Builder Type::Builder::initEnum() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::ENUM); + _builder.setDataField< ::uint64_t>(::capnp::bounded<1>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS).clear(); + return typename Type::Enum::Builder(_builder); +} +inline bool Type::Reader::isStruct() const { + return which() == Type::STRUCT; +} +inline bool Type::Builder::isStruct() { + return which() == Type::STRUCT; +} +inline typename Type::Struct::Reader Type::Reader::getStruct() const { + KJ_IREQUIRE((which() == Type::STRUCT), + "Must check which() before get()ing a union member."); + return typename Type::Struct::Reader(_reader); +} +inline typename Type::Struct::Builder Type::Builder::getStruct() { + KJ_IREQUIRE((which() == Type::STRUCT), + "Must check which() before get()ing a union member."); + return typename Type::Struct::Builder(_builder); +} +inline typename Type::Struct::Builder Type::Builder::initStruct() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::STRUCT); + _builder.setDataField< ::uint64_t>(::capnp::bounded<1>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS).clear(); + return typename Type::Struct::Builder(_builder); +} +inline bool Type::Reader::isInterface() const { + return which() == Type::INTERFACE; +} +inline bool Type::Builder::isInterface() { + return which() == Type::INTERFACE; +} +inline typename Type::Interface::Reader Type::Reader::getInterface() const { + KJ_IREQUIRE((which() == Type::INTERFACE), + "Must check which() before get()ing a union member."); + return typename Type::Interface::Reader(_reader); +} +inline typename Type::Interface::Builder Type::Builder::getInterface() { + KJ_IREQUIRE((which() == Type::INTERFACE), + "Must check which() before get()ing a union member."); + return typename Type::Interface::Builder(_builder); +} +inline typename Type::Interface::Builder Type::Builder::initInterface() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::INTERFACE); + _builder.setDataField< ::uint64_t>(::capnp::bounded<1>() * ::capnp::ELEMENTS, 0); + _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS).clear(); + return typename Type::Interface::Builder(_builder); +} +inline bool Type::Reader::isAnyPointer() const { + return which() == Type::ANY_POINTER; +} +inline bool Type::Builder::isAnyPointer() { + return which() == Type::ANY_POINTER; +} +inline typename Type::AnyPointer::Reader Type::Reader::getAnyPointer() const { + KJ_IREQUIRE((which() == Type::ANY_POINTER), + "Must check which() before get()ing a union member."); + return typename Type::AnyPointer::Reader(_reader); +} +inline typename Type::AnyPointer::Builder Type::Builder::getAnyPointer() { + KJ_IREQUIRE((which() == Type::ANY_POINTER), + "Must check which() before get()ing a union member."); + return typename Type::AnyPointer::Builder(_builder); +} +inline typename Type::AnyPointer::Builder Type::Builder::initAnyPointer() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::ANY_POINTER); + _builder.setDataField< ::uint16_t>(::capnp::bounded<4>() * ::capnp::ELEMENTS, 0); + _builder.setDataField< ::uint16_t>(::capnp::bounded<5>() * ::capnp::ELEMENTS, 0); + _builder.setDataField< ::uint64_t>(::capnp::bounded<2>() * ::capnp::ELEMENTS, 0); + return typename Type::AnyPointer::Builder(_builder); +} +inline bool Type::List::Reader::hasElementType() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Type::List::Builder::hasElementType() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Type::Reader Type::List::Reader::getElementType() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Type::Builder Type::List::Builder::getElementType() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Type::List::Builder::setElementType( ::capnp::schema::Type::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Type>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Type::Builder Type::List::Builder::initElementType() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Type::List::Builder::adoptElementType( + ::capnp::Orphan< ::capnp::schema::Type>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Type>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Type> Type::List::Builder::disownElementType() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::uint64_t Type::Enum::Reader::getTypeId() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Type::Enum::Builder::getTypeId() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Type::Enum::Builder::setTypeId( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Enum::Reader::hasBrand() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Type::Enum::Builder::hasBrand() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Brand::Reader Type::Enum::Reader::getBrand() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Brand::Builder Type::Enum::Builder::getBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Type::Enum::Builder::setBrand( ::capnp::schema::Brand::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Brand::Builder Type::Enum::Builder::initBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Type::Enum::Builder::adoptBrand( + ::capnp::Orphan< ::capnp::schema::Brand>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Brand> Type::Enum::Builder::disownBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::uint64_t Type::Struct::Reader::getTypeId() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Type::Struct::Builder::getTypeId() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Type::Struct::Builder::setTypeId( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Struct::Reader::hasBrand() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Type::Struct::Builder::hasBrand() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Brand::Reader Type::Struct::Reader::getBrand() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Brand::Builder Type::Struct::Builder::getBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Type::Struct::Builder::setBrand( ::capnp::schema::Brand::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Brand::Builder Type::Struct::Builder::initBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Type::Struct::Builder::adoptBrand( + ::capnp::Orphan< ::capnp::schema::Brand>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Brand> Type::Struct::Builder::disownBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::uint64_t Type::Interface::Reader::getTypeId() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Type::Interface::Builder::getTypeId() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Type::Interface::Builder::setTypeId( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::Interface::Reader::hasBrand() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Type::Interface::Builder::hasBrand() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Brand::Reader Type::Interface::Reader::getBrand() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Brand::Builder Type::Interface::Builder::getBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Type::Interface::Builder::setBrand( ::capnp::schema::Brand::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Brand::Builder Type::Interface::Builder::initBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Type::Interface::Builder::adoptBrand( + ::capnp::Orphan< ::capnp::schema::Brand>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Brand> Type::Interface::Builder::disownBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::capnp::schema::Type::AnyPointer::Which Type::AnyPointer::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS); +} +inline ::capnp::schema::Type::AnyPointer::Which Type::AnyPointer::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS); +} + +inline bool Type::AnyPointer::Reader::isUnconstrained() const { + return which() == Type::AnyPointer::UNCONSTRAINED; +} +inline bool Type::AnyPointer::Builder::isUnconstrained() { + return which() == Type::AnyPointer::UNCONSTRAINED; +} +inline typename Type::AnyPointer::Unconstrained::Reader Type::AnyPointer::Reader::getUnconstrained() const { + KJ_IREQUIRE((which() == Type::AnyPointer::UNCONSTRAINED), + "Must check which() before get()ing a union member."); + return typename Type::AnyPointer::Unconstrained::Reader(_reader); +} +inline typename Type::AnyPointer::Unconstrained::Builder Type::AnyPointer::Builder::getUnconstrained() { + KJ_IREQUIRE((which() == Type::AnyPointer::UNCONSTRAINED), + "Must check which() before get()ing a union member."); + return typename Type::AnyPointer::Unconstrained::Builder(_builder); +} +inline typename Type::AnyPointer::Unconstrained::Builder Type::AnyPointer::Builder::initUnconstrained() { + _builder.setDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS, Type::AnyPointer::UNCONSTRAINED); + _builder.setDataField< ::uint16_t>(::capnp::bounded<5>() * ::capnp::ELEMENTS, 0); + return typename Type::AnyPointer::Unconstrained::Builder(_builder); +} +inline bool Type::AnyPointer::Reader::isParameter() const { + return which() == Type::AnyPointer::PARAMETER; +} +inline bool Type::AnyPointer::Builder::isParameter() { + return which() == Type::AnyPointer::PARAMETER; +} +inline typename Type::AnyPointer::Parameter::Reader Type::AnyPointer::Reader::getParameter() const { + KJ_IREQUIRE((which() == Type::AnyPointer::PARAMETER), + "Must check which() before get()ing a union member."); + return typename Type::AnyPointer::Parameter::Reader(_reader); +} +inline typename Type::AnyPointer::Parameter::Builder Type::AnyPointer::Builder::getParameter() { + KJ_IREQUIRE((which() == Type::AnyPointer::PARAMETER), + "Must check which() before get()ing a union member."); + return typename Type::AnyPointer::Parameter::Builder(_builder); +} +inline typename Type::AnyPointer::Parameter::Builder Type::AnyPointer::Builder::initParameter() { + _builder.setDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS, Type::AnyPointer::PARAMETER); + _builder.setDataField< ::uint16_t>(::capnp::bounded<5>() * ::capnp::ELEMENTS, 0); + _builder.setDataField< ::uint64_t>(::capnp::bounded<2>() * ::capnp::ELEMENTS, 0); + return typename Type::AnyPointer::Parameter::Builder(_builder); +} +inline bool Type::AnyPointer::Reader::isImplicitMethodParameter() const { + return which() == Type::AnyPointer::IMPLICIT_METHOD_PARAMETER; +} +inline bool Type::AnyPointer::Builder::isImplicitMethodParameter() { + return which() == Type::AnyPointer::IMPLICIT_METHOD_PARAMETER; +} +inline typename Type::AnyPointer::ImplicitMethodParameter::Reader Type::AnyPointer::Reader::getImplicitMethodParameter() const { + KJ_IREQUIRE((which() == Type::AnyPointer::IMPLICIT_METHOD_PARAMETER), + "Must check which() before get()ing a union member."); + return typename Type::AnyPointer::ImplicitMethodParameter::Reader(_reader); +} +inline typename Type::AnyPointer::ImplicitMethodParameter::Builder Type::AnyPointer::Builder::getImplicitMethodParameter() { + KJ_IREQUIRE((which() == Type::AnyPointer::IMPLICIT_METHOD_PARAMETER), + "Must check which() before get()ing a union member."); + return typename Type::AnyPointer::ImplicitMethodParameter::Builder(_builder); +} +inline typename Type::AnyPointer::ImplicitMethodParameter::Builder Type::AnyPointer::Builder::initImplicitMethodParameter() { + _builder.setDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS, Type::AnyPointer::IMPLICIT_METHOD_PARAMETER); + _builder.setDataField< ::uint16_t>(::capnp::bounded<5>() * ::capnp::ELEMENTS, 0); + return typename Type::AnyPointer::ImplicitMethodParameter::Builder(_builder); +} +inline ::capnp::schema::Type::AnyPointer::Unconstrained::Which Type::AnyPointer::Unconstrained::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<5>() * ::capnp::ELEMENTS); +} +inline ::capnp::schema::Type::AnyPointer::Unconstrained::Which Type::AnyPointer::Unconstrained::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<5>() * ::capnp::ELEMENTS); +} + +inline bool Type::AnyPointer::Unconstrained::Reader::isAnyKind() const { + return which() == Type::AnyPointer::Unconstrained::ANY_KIND; +} +inline bool Type::AnyPointer::Unconstrained::Builder::isAnyKind() { + return which() == Type::AnyPointer::Unconstrained::ANY_KIND; +} +inline ::capnp::Void Type::AnyPointer::Unconstrained::Reader::getAnyKind() const { + KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::ANY_KIND), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::AnyPointer::Unconstrained::Builder::getAnyKind() { + KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::ANY_KIND), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::AnyPointer::Unconstrained::Builder::setAnyKind( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<5>() * ::capnp::ELEMENTS, Type::AnyPointer::Unconstrained::ANY_KIND); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::AnyPointer::Unconstrained::Reader::isStruct() const { + return which() == Type::AnyPointer::Unconstrained::STRUCT; +} +inline bool Type::AnyPointer::Unconstrained::Builder::isStruct() { + return which() == Type::AnyPointer::Unconstrained::STRUCT; +} +inline ::capnp::Void Type::AnyPointer::Unconstrained::Reader::getStruct() const { + KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::STRUCT), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::AnyPointer::Unconstrained::Builder::getStruct() { + KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::STRUCT), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::AnyPointer::Unconstrained::Builder::setStruct( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<5>() * ::capnp::ELEMENTS, Type::AnyPointer::Unconstrained::STRUCT); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::AnyPointer::Unconstrained::Reader::isList() const { + return which() == Type::AnyPointer::Unconstrained::LIST; +} +inline bool Type::AnyPointer::Unconstrained::Builder::isList() { + return which() == Type::AnyPointer::Unconstrained::LIST; +} +inline ::capnp::Void Type::AnyPointer::Unconstrained::Reader::getList() const { + KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::LIST), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::AnyPointer::Unconstrained::Builder::getList() { + KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::LIST), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::AnyPointer::Unconstrained::Builder::setList( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<5>() * ::capnp::ELEMENTS, Type::AnyPointer::Unconstrained::LIST); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Type::AnyPointer::Unconstrained::Reader::isCapability() const { + return which() == Type::AnyPointer::Unconstrained::CAPABILITY; +} +inline bool Type::AnyPointer::Unconstrained::Builder::isCapability() { + return which() == Type::AnyPointer::Unconstrained::CAPABILITY; +} +inline ::capnp::Void Type::AnyPointer::Unconstrained::Reader::getCapability() const { + KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::CAPABILITY), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Type::AnyPointer::Unconstrained::Builder::getCapability() { + KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::CAPABILITY), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Type::AnyPointer::Unconstrained::Builder::setCapability( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<5>() * ::capnp::ELEMENTS, Type::AnyPointer::Unconstrained::CAPABILITY); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline ::uint64_t Type::AnyPointer::Parameter::Reader::getScopeId() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Type::AnyPointer::Parameter::Builder::getScopeId() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} +inline void Type::AnyPointer::Parameter::Builder::setScopeId( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); +} + +inline ::uint16_t Type::AnyPointer::Parameter::Reader::getParameterIndex() const { + return _reader.getDataField< ::uint16_t>( + ::capnp::bounded<5>() * ::capnp::ELEMENTS); +} + +inline ::uint16_t Type::AnyPointer::Parameter::Builder::getParameterIndex() { + return _builder.getDataField< ::uint16_t>( + ::capnp::bounded<5>() * ::capnp::ELEMENTS); +} +inline void Type::AnyPointer::Parameter::Builder::setParameterIndex( ::uint16_t value) { + _builder.setDataField< ::uint16_t>( + ::capnp::bounded<5>() * ::capnp::ELEMENTS, value); +} + +inline ::uint16_t Type::AnyPointer::ImplicitMethodParameter::Reader::getParameterIndex() const { + return _reader.getDataField< ::uint16_t>( + ::capnp::bounded<5>() * ::capnp::ELEMENTS); +} + +inline ::uint16_t Type::AnyPointer::ImplicitMethodParameter::Builder::getParameterIndex() { + return _builder.getDataField< ::uint16_t>( + ::capnp::bounded<5>() * ::capnp::ELEMENTS); +} +inline void Type::AnyPointer::ImplicitMethodParameter::Builder::setParameterIndex( ::uint16_t value) { + _builder.setDataField< ::uint16_t>( + ::capnp::bounded<5>() * ::capnp::ELEMENTS, value); +} + +inline bool Brand::Reader::hasScopes() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Brand::Builder::hasScopes() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Reader Brand::Reader::getScopes() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Builder Brand::Builder::getScopes() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Brand::Builder::setScopes( ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Builder Brand::Builder::initScopes(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Brand::Builder::adoptScopes( + ::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>> Brand::Builder::disownScopes() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::capnp::schema::Brand::Scope::Which Brand::Scope::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS); +} +inline ::capnp::schema::Brand::Scope::Which Brand::Scope::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Brand::Scope::Reader::getScopeId() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Brand::Scope::Builder::getScopeId() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Brand::Scope::Builder::setScopeId( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Brand::Scope::Reader::isBind() const { + return which() == Brand::Scope::BIND; +} +inline bool Brand::Scope::Builder::isBind() { + return which() == Brand::Scope::BIND; +} +inline bool Brand::Scope::Reader::hasBind() const { + if (which() != Brand::Scope::BIND) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Brand::Scope::Builder::hasBind() { + if (which() != Brand::Scope::BIND) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Reader Brand::Scope::Reader::getBind() const { + KJ_IREQUIRE((which() == Brand::Scope::BIND), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Builder Brand::Scope::Builder::getBind() { + KJ_IREQUIRE((which() == Brand::Scope::BIND), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Brand::Scope::Builder::setBind( ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Reader value) { + _builder.setDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS, Brand::Scope::BIND); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Builder Brand::Scope::Builder::initBind(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS, Brand::Scope::BIND); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Brand::Scope::Builder::adoptBind( + ::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>&& value) { + _builder.setDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS, Brand::Scope::BIND); + ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>> Brand::Scope::Builder::disownBind() { + KJ_IREQUIRE((which() == Brand::Scope::BIND), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Brand::Scope::Reader::isInherit() const { + return which() == Brand::Scope::INHERIT; +} +inline bool Brand::Scope::Builder::isInherit() { + return which() == Brand::Scope::INHERIT; +} +inline ::capnp::Void Brand::Scope::Reader::getInherit() const { + KJ_IREQUIRE((which() == Brand::Scope::INHERIT), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Brand::Scope::Builder::getInherit() { + KJ_IREQUIRE((which() == Brand::Scope::INHERIT), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Brand::Scope::Builder::setInherit( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<4>() * ::capnp::ELEMENTS, Brand::Scope::INHERIT); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline ::capnp::schema::Brand::Binding::Which Brand::Binding::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline ::capnp::schema::Brand::Binding::Which Brand::Binding::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline bool Brand::Binding::Reader::isUnbound() const { + return which() == Brand::Binding::UNBOUND; +} +inline bool Brand::Binding::Builder::isUnbound() { + return which() == Brand::Binding::UNBOUND; +} +inline ::capnp::Void Brand::Binding::Reader::getUnbound() const { + KJ_IREQUIRE((which() == Brand::Binding::UNBOUND), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Brand::Binding::Builder::getUnbound() { + KJ_IREQUIRE((which() == Brand::Binding::UNBOUND), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Brand::Binding::Builder::setUnbound( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Brand::Binding::UNBOUND); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Brand::Binding::Reader::isType() const { + return which() == Brand::Binding::TYPE; +} +inline bool Brand::Binding::Builder::isType() { + return which() == Brand::Binding::TYPE; +} +inline bool Brand::Binding::Reader::hasType() const { + if (which() != Brand::Binding::TYPE) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Brand::Binding::Builder::hasType() { + if (which() != Brand::Binding::TYPE) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Type::Reader Brand::Binding::Reader::getType() const { + KJ_IREQUIRE((which() == Brand::Binding::TYPE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Type::Builder Brand::Binding::Builder::getType() { + KJ_IREQUIRE((which() == Brand::Binding::TYPE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Brand::Binding::Builder::setType( ::capnp::schema::Type::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Brand::Binding::TYPE); + ::capnp::_::PointerHelpers< ::capnp::schema::Type>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Type::Builder Brand::Binding::Builder::initType() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Brand::Binding::TYPE); + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Brand::Binding::Builder::adoptType( + ::capnp::Orphan< ::capnp::schema::Type>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Brand::Binding::TYPE); + ::capnp::_::PointerHelpers< ::capnp::schema::Type>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Type> Brand::Binding::Builder::disownType() { + KJ_IREQUIRE((which() == Brand::Binding::TYPE), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline ::capnp::schema::Value::Which Value::Reader::which() const { + return _reader.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline ::capnp::schema::Value::Which Value::Builder::which() { + return _builder.getDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline bool Value::Reader::isVoid() const { + return which() == Value::VOID; +} +inline bool Value::Builder::isVoid() { + return which() == Value::VOID; +} +inline ::capnp::Void Value::Reader::getVoid() const { + KJ_IREQUIRE((which() == Value::VOID), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Value::Builder::getVoid() { + KJ_IREQUIRE((which() == Value::VOID), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setVoid( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::VOID); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isBool() const { + return which() == Value::BOOL; +} +inline bool Value::Builder::isBool() { + return which() == Value::BOOL; +} +inline bool Value::Reader::getBool() const { + KJ_IREQUIRE((which() == Value::BOOL), + "Must check which() before get()ing a union member."); + return _reader.getDataField( + ::capnp::bounded<16>() * ::capnp::ELEMENTS); +} + +inline bool Value::Builder::getBool() { + KJ_IREQUIRE((which() == Value::BOOL), + "Must check which() before get()ing a union member."); + return _builder.getDataField( + ::capnp::bounded<16>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setBool(bool value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::BOOL); + _builder.setDataField( + ::capnp::bounded<16>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isInt8() const { + return which() == Value::INT8; +} +inline bool Value::Builder::isInt8() { + return which() == Value::INT8; +} +inline ::int8_t Value::Reader::getInt8() const { + KJ_IREQUIRE((which() == Value::INT8), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::int8_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} + +inline ::int8_t Value::Builder::getInt8() { + KJ_IREQUIRE((which() == Value::INT8), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::int8_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setInt8( ::int8_t value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::INT8); + _builder.setDataField< ::int8_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isInt16() const { + return which() == Value::INT16; +} +inline bool Value::Builder::isInt16() { + return which() == Value::INT16; +} +inline ::int16_t Value::Reader::getInt16() const { + KJ_IREQUIRE((which() == Value::INT16), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::int16_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::int16_t Value::Builder::getInt16() { + KJ_IREQUIRE((which() == Value::INT16), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::int16_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setInt16( ::int16_t value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::INT16); + _builder.setDataField< ::int16_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isInt32() const { + return which() == Value::INT32; +} +inline bool Value::Builder::isInt32() { + return which() == Value::INT32; +} +inline ::int32_t Value::Reader::getInt32() const { + KJ_IREQUIRE((which() == Value::INT32), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::int32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::int32_t Value::Builder::getInt32() { + KJ_IREQUIRE((which() == Value::INT32), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::int32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setInt32( ::int32_t value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::INT32); + _builder.setDataField< ::int32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isInt64() const { + return which() == Value::INT64; +} +inline bool Value::Builder::isInt64() { + return which() == Value::INT64; +} +inline ::int64_t Value::Reader::getInt64() const { + KJ_IREQUIRE((which() == Value::INT64), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::int64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::int64_t Value::Builder::getInt64() { + KJ_IREQUIRE((which() == Value::INT64), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::int64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setInt64( ::int64_t value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::INT64); + _builder.setDataField< ::int64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isUint8() const { + return which() == Value::UINT8; +} +inline bool Value::Builder::isUint8() { + return which() == Value::UINT8; +} +inline ::uint8_t Value::Reader::getUint8() const { + KJ_IREQUIRE((which() == Value::UINT8), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::uint8_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} + +inline ::uint8_t Value::Builder::getUint8() { + KJ_IREQUIRE((which() == Value::UINT8), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::uint8_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setUint8( ::uint8_t value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::UINT8); + _builder.setDataField< ::uint8_t>( + ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isUint16() const { + return which() == Value::UINT16; +} +inline bool Value::Builder::isUint16() { + return which() == Value::UINT16; +} +inline ::uint16_t Value::Reader::getUint16() const { + KJ_IREQUIRE((which() == Value::UINT16), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::uint16_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint16_t Value::Builder::getUint16() { + KJ_IREQUIRE((which() == Value::UINT16), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::uint16_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setUint16( ::uint16_t value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::UINT16); + _builder.setDataField< ::uint16_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isUint32() const { + return which() == Value::UINT32; +} +inline bool Value::Builder::isUint32() { + return which() == Value::UINT32; +} +inline ::uint32_t Value::Reader::getUint32() const { + KJ_IREQUIRE((which() == Value::UINT32), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint32_t Value::Builder::getUint32() { + KJ_IREQUIRE((which() == Value::UINT32), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setUint32( ::uint32_t value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::UINT32); + _builder.setDataField< ::uint32_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isUint64() const { + return which() == Value::UINT64; +} +inline bool Value::Builder::isUint64() { + return which() == Value::UINT64; +} +inline ::uint64_t Value::Reader::getUint64() const { + KJ_IREQUIRE((which() == Value::UINT64), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Value::Builder::getUint64() { + KJ_IREQUIRE((which() == Value::UINT64), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setUint64( ::uint64_t value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::UINT64); + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isFloat32() const { + return which() == Value::FLOAT32; +} +inline bool Value::Builder::isFloat32() { + return which() == Value::FLOAT32; +} +inline float Value::Reader::getFloat32() const { + KJ_IREQUIRE((which() == Value::FLOAT32), + "Must check which() before get()ing a union member."); + return _reader.getDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline float Value::Builder::getFloat32() { + KJ_IREQUIRE((which() == Value::FLOAT32), + "Must check which() before get()ing a union member."); + return _builder.getDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setFloat32(float value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::FLOAT32); + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isFloat64() const { + return which() == Value::FLOAT64; +} +inline bool Value::Builder::isFloat64() { + return which() == Value::FLOAT64; +} +inline double Value::Reader::getFloat64() const { + KJ_IREQUIRE((which() == Value::FLOAT64), + "Must check which() before get()ing a union member."); + return _reader.getDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline double Value::Builder::getFloat64() { + KJ_IREQUIRE((which() == Value::FLOAT64), + "Must check which() before get()ing a union member."); + return _builder.getDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setFloat64(double value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::FLOAT64); + _builder.setDataField( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isText() const { + return which() == Value::TEXT; +} +inline bool Value::Builder::isText() { + return which() == Value::TEXT; +} +inline bool Value::Reader::hasText() const { + if (which() != Value::TEXT) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Value::Builder::hasText() { + if (which() != Value::TEXT) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Text::Reader Value::Reader::getText() const { + KJ_IREQUIRE((which() == Value::TEXT), + "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 Value::Builder::getText() { + KJ_IREQUIRE((which() == Value::TEXT), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Value::Builder::setText( ::capnp::Text::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::TEXT); + ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Text::Builder Value::Builder::initText(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::TEXT); + return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Value::Builder::adoptText( + ::capnp::Orphan< ::capnp::Text>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::TEXT); + ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::Text> Value::Builder::disownText() { + KJ_IREQUIRE((which() == Value::TEXT), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Value::Reader::isData() const { + return which() == Value::DATA; +} +inline bool Value::Builder::isData() { + return which() == Value::DATA; +} +inline bool Value::Reader::hasData() const { + if (which() != Value::DATA) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Value::Builder::hasData() { + if (which() != Value::DATA) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::Data::Reader Value::Reader::getData() const { + KJ_IREQUIRE((which() == Value::DATA), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Data>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::Data::Builder Value::Builder::getData() { + KJ_IREQUIRE((which() == Value::DATA), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Data>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Value::Builder::setData( ::capnp::Data::Reader value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::DATA); + ::capnp::_::PointerHelpers< ::capnp::Data>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::Data::Builder Value::Builder::initData(unsigned int size) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::DATA); + return ::capnp::_::PointerHelpers< ::capnp::Data>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void Value::Builder::adoptData( + ::capnp::Orphan< ::capnp::Data>&& value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::DATA); + ::capnp::_::PointerHelpers< ::capnp::Data>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::Data> Value::Builder::disownData() { + KJ_IREQUIRE((which() == Value::DATA), + "Must check which() before get()ing a union member."); + return ::capnp::_::PointerHelpers< ::capnp::Data>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Value::Reader::isList() const { + return which() == Value::LIST; +} +inline bool Value::Builder::isList() { + return which() == Value::LIST; +} +inline bool Value::Reader::hasList() const { + if (which() != Value::LIST) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Value::Builder::hasList() { + if (which() != Value::LIST) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::AnyPointer::Reader Value::Reader::getList() const { + KJ_IREQUIRE((which() == Value::LIST), + "Must check which() before get()ing a union member."); + return ::capnp::AnyPointer::Reader(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::AnyPointer::Builder Value::Builder::getList() { + KJ_IREQUIRE((which() == Value::LIST), + "Must check which() before get()ing a union member."); + return ::capnp::AnyPointer::Builder(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::AnyPointer::Builder Value::Builder::initList() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::LIST); + auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); + result.clear(); + return result; +} + +inline bool Value::Reader::isEnum() const { + return which() == Value::ENUM; +} +inline bool Value::Builder::isEnum() { + return which() == Value::ENUM; +} +inline ::uint16_t Value::Reader::getEnum() const { + KJ_IREQUIRE((which() == Value::ENUM), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::uint16_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::uint16_t Value::Builder::getEnum() { + KJ_IREQUIRE((which() == Value::ENUM), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::uint16_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setEnum( ::uint16_t value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::ENUM); + _builder.setDataField< ::uint16_t>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isStruct() const { + return which() == Value::STRUCT; +} +inline bool Value::Builder::isStruct() { + return which() == Value::STRUCT; +} +inline bool Value::Reader::hasStruct() const { + if (which() != Value::STRUCT) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Value::Builder::hasStruct() { + if (which() != Value::STRUCT) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::AnyPointer::Reader Value::Reader::getStruct() const { + KJ_IREQUIRE((which() == Value::STRUCT), + "Must check which() before get()ing a union member."); + return ::capnp::AnyPointer::Reader(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::AnyPointer::Builder Value::Builder::getStruct() { + KJ_IREQUIRE((which() == Value::STRUCT), + "Must check which() before get()ing a union member."); + return ::capnp::AnyPointer::Builder(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::AnyPointer::Builder Value::Builder::initStruct() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::STRUCT); + auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); + result.clear(); + return result; +} + +inline bool Value::Reader::isInterface() const { + return which() == Value::INTERFACE; +} +inline bool Value::Builder::isInterface() { + return which() == Value::INTERFACE; +} +inline ::capnp::Void Value::Reader::getInterface() const { + KJ_IREQUIRE((which() == Value::INTERFACE), + "Must check which() before get()ing a union member."); + return _reader.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::capnp::Void Value::Builder::getInterface() { + KJ_IREQUIRE((which() == Value::INTERFACE), + "Must check which() before get()ing a union member."); + return _builder.getDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Value::Builder::setInterface( ::capnp::Void value) { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::INTERFACE); + _builder.setDataField< ::capnp::Void>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Value::Reader::isAnyPointer() const { + return which() == Value::ANY_POINTER; +} +inline bool Value::Builder::isAnyPointer() { + return which() == Value::ANY_POINTER; +} +inline bool Value::Reader::hasAnyPointer() const { + if (which() != Value::ANY_POINTER) return false; + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Value::Builder::hasAnyPointer() { + if (which() != Value::ANY_POINTER) return false; + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::AnyPointer::Reader Value::Reader::getAnyPointer() const { + KJ_IREQUIRE((which() == Value::ANY_POINTER), + "Must check which() before get()ing a union member."); + return ::capnp::AnyPointer::Reader(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::AnyPointer::Builder Value::Builder::getAnyPointer() { + KJ_IREQUIRE((which() == Value::ANY_POINTER), + "Must check which() before get()ing a union member."); + return ::capnp::AnyPointer::Builder(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::AnyPointer::Builder Value::Builder::initAnyPointer() { + _builder.setDataField( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::ANY_POINTER); + auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); + result.clear(); + return result; +} + +inline ::uint64_t Annotation::Reader::getId() const { + return _reader.getDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::uint64_t Annotation::Builder::getId() { + return _builder.getDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void Annotation::Builder::setId( ::uint64_t value) { + _builder.setDataField< ::uint64_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool Annotation::Reader::hasValue() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool Annotation::Builder::hasValue() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Value::Reader Annotation::Reader::getValue() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Value::Builder Annotation::Builder::getValue() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Annotation::Builder::setValue( ::capnp::schema::Value::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Value>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Value::Builder Annotation::Builder::initValue() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Annotation::Builder::adoptValue( + ::capnp::Orphan< ::capnp::schema::Value>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Value>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Value> Annotation::Builder::disownValue() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Annotation::Reader::hasBrand() const { + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool Annotation::Builder::hasBrand() { + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::schema::Brand::Reader Annotation::Reader::getBrand() const { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::schema::Brand::Builder Annotation::Builder::getBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Annotation::Builder::setBrand( ::capnp::schema::Brand::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::schema::Brand::Builder Annotation::Builder::initBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Annotation::Builder::adoptBrand( + ::capnp::Orphan< ::capnp::schema::Brand>&& value) { + ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::schema::Brand> Annotation::Builder::disownBrand() { + return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +} // namespace +} // namespace + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/schema.h b/vendor/capnproto/src/capnp/schema.h new file mode 100644 index 0000000..6491cfd --- /dev/null +++ b/vendor/capnproto/src/capnp/schema.h @@ -0,0 +1,877 @@ +// 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. + +#pragma once + + +#undef CONST +// For some ridiculous reason, Windows defines CONST to const. We have an enum value called CONST +// in schema.capnp.h, so if this is defined, compilation is gonna fail. So we undef it because +// that seems strictly better than failing entirely. But this could cause trouble for people later +// on if they, say, include windows.h, then include schema.h, then include another windows API +// header that uses CONST. I suppose they may have to re-#define CONST in between, or change the +// header ordering. Sorry. +// +// Please don't file a bug report telling us to change our enum naming style. You are at least +// seven years too late. + +#include +#include + +CAPNP_BEGIN_HEADER + +namespace capnp { + +class Schema; +class StructSchema; +class EnumSchema; +class ConstSchema; +class ListSchema; +class Type; + +template ()> struct SchemaType_ { typedef Schema Type; }; +template struct SchemaType_ { typedef schema::Type::Which Type; }; +template struct SchemaType_ { typedef schema::Type::Which Type; }; +template struct SchemaType_ { typedef EnumSchema Type; }; +template struct SchemaType_ { typedef StructSchema Type; }; +template struct SchemaType_ { typedef ListSchema Type; }; + +template +using SchemaType = typename SchemaType_::Type; +// SchemaType 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_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 + static inline SchemaType from() { return SchemaType::template fromImpl(); } + // 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 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 CAPNP_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. + + kj::Array getGenericScopeIds() const; + // Returns the type IDs of all parent scopes that have generic parameters, to which this type is + // subject. + + StructSchema asStruct() const; + EnumSchema asEnum() 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. + + inline uint hashCode() const { return kj::hashCode(raw); } + + template + 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() + // - This schema was loaded with SchemaLoader, the type ID matches typeId(), and + // loadCompiledTypeAndDependencies() was called on the SchemaLoader. + + kj::StringPtr getShortDisplayName() const; + // Get the short version of the node's display name. + + const kj::StringPtr getUnqualifiedName() const; + // Get the display name "nickname" of this node minus the prefix + +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 static inline Schema fromImpl() { + return Schema(&_::rawSchema()); + } + + 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 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 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 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 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.) + + + bool mayContainCapabilities() const { return raw->generic->mayContainCapabilities; } + // Returns true if a struct of this type may transitively contain any capabilities. I.e., are + // any of the fields an interface type, or a struct type that may in turn contain capabilities? + // + // This is meant for optimizations where various bookkeeping can possibly be skipped if it is + // known in advance that there are no capabilities. Note that this may conservatively return true + // spuriously, e.g. if it would be inconvenient to compute the correct answer. A false positive + // should never cause incorrect behavior, just potentially hurt performance. + // + // It's important to keep in mind that even if a schema has no capability-typed fields today, + // they could always be added in future versions of the schema. So, just because the schema + // doesn't contain capabilities does NOT necessarily mean that an instance of the struct can't + // contain capabilities. However, it is a pretty good hint that the application won't plan to + // use such capabilities -- for example, if there are no caps in an RPC call's response type + // according to the client's version of the schema, then the client clearly isn't going to try + // to make any pipelined calls. The server could be operating with a new version of the schema + // and could actually return capabilities, but for the client to make a pipelined call, the + // client would have to know in advance that capabilities could be returned. + +private: + StructSchema(Schema base): Schema(base) {} + template static inline StructSchema fromImpl() { + return StructSchema(Schema(&_::rawBrandedSchema())); + } + 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); } + inline uint hashCode() const; + +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 Iterator; + inline Iterator begin() const { return Iterator(this, 0); } + inline Iterator end() const { return Iterator(this, size()); } + +private: + StructSchema parent; + List::Reader list; + + inline FieldList(StructSchema parent, List::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 Iterator; + inline Iterator begin() const { return Iterator(this, 0); } + inline Iterator end() const { return Iterator(this, size()); } + +private: + StructSchema parent; + List::Reader list; + const uint16_t* indices; + uint size_; + + inline FieldSubset(StructSchema parent, List::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 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 static inline EnumSchema fromImpl() { + return EnumSchema(Schema(&_::rawBrandedSchema())); + } + 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); } + inline uint hashCode() const; + +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 Iterator; + inline Iterator begin() const { return Iterator(this, 0); } + inline Iterator end() const { return Iterator(this, size()); } + +private: + EnumSchema parent; + List::Reader list; + + inline EnumerantList(EnumSchema parent, List::Reader list) + : parent(parent), list(list) {} + + friend class EnumSchema; +}; + +// ------------------------------------------------------------------- + +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 + ReaderFor 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()` method. For dependency reasons, this method + // is defined in , 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(ListSchema schema); + inline Type(schema::Type::AnyPointer::Unconstrained::Which anyPointerKind); + inline Type(BrandParameter param); + inline Type(ImplicitParameter param); + + template + inline static Type from(); + template + inline static Type from(T&& value); + + inline schema::Type::Which which() const; + + StructSchema asStruct() const; + EnumSchema asEnum() const; + ListSchema asList() const; + // Each of these methods may only be called if which() returns the corresponding type. + + kj::Maybe 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 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); } + + uint 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; + + template + struct FromValueImpl; + + 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(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) + CAPNP_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; + 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 + void requireUsableAs() const; + +private: + Type elementType; + + inline explicit ListSchema(Type elementType): elementType(elementType) {} + + template + struct FromImpl; + template static inline ListSchema fromImpl() { + return FromImpl::get(); + } + + void requireUsableAs(ListSchema expected) const; + + friend class Schema; +}; + +// ======================================================================================= +// inline implementation + +template <> inline schema::Type::Which Schema::from() { return schema::Type::VOID; } +template <> inline schema::Type::Which Schema::from() { return schema::Type::BOOL; } +template <> inline schema::Type::Which Schema::from() { return schema::Type::INT8; } +template <> inline schema::Type::Which Schema::from() { return schema::Type::INT16; } +template <> inline schema::Type::Which Schema::from() { return schema::Type::INT32; } +template <> inline schema::Type::Which Schema::from() { return schema::Type::INT64; } +template <> inline schema::Type::Which Schema::from() { return schema::Type::UINT8; } +template <> inline schema::Type::Which Schema::from() { return schema::Type::UINT16; } +template <> inline schema::Type::Which Schema::from() { return schema::Type::UINT32; } +template <> inline schema::Type::Which Schema::from() { return schema::Type::UINT64; } +template <> inline schema::Type::Which Schema::from() { return schema::Type::FLOAT32; } +template <> inline schema::Type::Which Schema::from() { return schema::Type::FLOAT64; } +template <> inline schema::Type::Which Schema::from() { return schema::Type::TEXT; } +template <> inline schema::Type::Which Schema::from() { 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 +inline void Schema::requireUsableAs() const { + requireUsableAs(&_::rawSchema()); +} + +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 uint StructSchema::Field::hashCode() const { + return kj::hashCode(parent, index); +} +inline uint EnumSchema::Enumerant::hashCode() const { + return kj::hashCode(parent, 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(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 ListSchema ListSchema::getListElementType() const { + return elementType.asList(); +} + +template +inline void ListSchema::requireUsableAs() const { + static_assert(kind() == Kind::LIST, + "ListSchema::requireUsableAs() requires T is a list type."); + requireUsableAs(Schema::from()); +} + +inline void ListSchema::requireUsableAs(ListSchema expected) const { + elementType.requireUsableAs(expected.elementType); +} + +template +struct ListSchema::FromImpl> { + static inline ListSchema get() { return of(Schema::from()); } +}; + +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(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 +inline Type Type::from() { return Type(Schema::from()); } + +template +struct Type::FromValueImpl { + template + static inline Type type(U&& value) { + return Type::from(); + } +}; + +template +struct Type::FromValueImpl { + template + static inline Type type(U&& value) { + // All dynamic types have getSchema(). + return value.getSchema(); + } +}; + +template +inline Type Type::from(T&& value) { + typedef FromAny> Base; + return Type::FromValueImpl()>::type(kj::fwd(value)); +} + +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 + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/serialize.c++ b/vendor/capnproto/src/capnp/serialize.c++ new file mode 100644 index 0000000..ba3e702 --- /dev/null +++ b/vendor/capnproto/src/capnp/serialize.c++ @@ -0,0 +1,135 @@ +// 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 "serialize.h" +#include "layout.h" +#include + +namespace capnp { + +FlatArrayMessageReader::FlatArrayMessageReader( + kj::ArrayPtr array, ReaderOptions options) + : MessageReader(options), end(array.end()) { + if (array.size() < 1) { + // Assume empty message. + return; + } + + const _::WireValue* table = + reinterpret_cast*>(array.begin()); + + uint segmentCount = table[0].get() + 1; + size_t offset = segmentCount / 2u + 1u; + + KJ_REQUIRE(segmentCount != 0, "Message segment count too large, caused overflow.") { + return; + } + + KJ_REQUIRE(array.size() >= offset, "Message ends prematurely in segment table.") { + return; + } + + { + uint segmentSize = table[1].get(); + + KJ_REQUIRE(array.size() >= offset + segmentSize, + "Message ends prematurely in first segment.") { + return; + } + + segment0 = array.slice(offset, offset + segmentSize); + offset += segmentSize; + } + + if (segmentCount > 1) { + moreSegments = kj::heapArray>(segmentCount - 1); + + for (uint i = 1; i < segmentCount; i++) { + uint segmentSize = table[i + 1].get(); + + KJ_REQUIRE(array.size() >= offset + segmentSize, "Message ends prematurely.") { + moreSegments = nullptr; + return; + } + + moreSegments[i - 1] = array.slice(offset, offset + segmentSize); + offset += segmentSize; + } + } + + end = array.begin() + offset; +} + +kj::ArrayPtr FlatArrayMessageReader::getSegment(uint id) { + if (id == 0) { + return segment0; + } else if (id <= moreSegments.size()) { + return moreSegments[id - 1]; + } else { + return nullptr; + } +} + +kj::Array messageToFlatArray(kj::ArrayPtr> segments) { + kj::Array result = kj::heapArray(computeSerializedSizeInWords(segments)); + + _::WireValue* table = + reinterpret_cast<_::WireValue*>(result.begin()); + + // We write the segment count - 1 because this makes the first word zero for single-segment + // messages, improving compression. We don't bother doing this with segment sizes because + // one-word segments are rare anyway. + table[0].set(segments.size() - 1); + + for (uint i = 0; i < segments.size(); i++) { + table[i + 1].set(segments[i].size()); + } + + if (segments.size() % 2 == 0) { + // Set padding byte. + table[segments.size() + 1].set(0); + } + + word* dst = result.begin() + segments.size() / 2 + 1; + + for (auto& segment: segments) { + memcpy(dst, segment.begin(), segment.size() * sizeof(word)); + dst += segment.size(); + } + + KJ_DASSERT(dst == result.end(), "Buffer overrun/underrun bug in code above."); + + return kj::mv(result); +} + +size_t computeSerializedSizeInWords(kj::ArrayPtr> segments) { + KJ_REQUIRE(segments.size() > 0, "Tried to serialize uninitialized message."); + + size_t totalSize = segments.size() / 2 + 1; + + for (auto& segment: segments) { + totalSize += segment.size(); + } + + return totalSize; +} + +} // namespace capnp diff --git a/vendor/capnproto/src/capnp/serialize.h b/vendor/capnproto/src/capnp/serialize.h new file mode 100644 index 0000000..6954d30 --- /dev/null +++ b/vendor/capnproto/src/capnp/serialize.h @@ -0,0 +1,95 @@ +// 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. + +#pragma once + +#include "message.h" + +CAPNP_BEGIN_HEADER + +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 array, ReaderOptions options = ReaderOptions()); + // The array must remain valid until the MessageReader is destroyed. + + kj::ArrayPtr 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 segment0; + kj::Array> moreSegments; + const word* end; +}; + +kj::Array 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 words = messageToFlatArray(myMessage); +// kj::ArrayPtr bytes = words.asBytes(); +// write(fd, bytes.begin(), bytes.size()); + +kj::Array messageToFlatArray(kj::ArrayPtr> segments); +// Version of messageToFlatArray that takes a raw segment array. + +size_t computeSerializedSizeInWords(kj::ArrayPtr> segments); +// Version of computeSerializedSizeInWords that takes a raw segment array. + +inline kj::Array messageToFlatArray(MessageBuilder& builder) { + return messageToFlatArray(builder.getSegmentsForOutput()); +} + +} // namespace capnp + +CAPNP_END_HEADER diff --git a/vendor/capnproto/src/capnp/stringify.c++ b/vendor/capnproto/src/capnp/stringify.c++ new file mode 100644 index 0000000..820e63c --- /dev/null +++ b/vendor/capnproto/src/capnp/stringify.c++ @@ -0,0 +1,267 @@ +// 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 "dynamic.h" +#include +#include +#include + +namespace capnp { + +namespace { + +enum PrintMode { + BARE, + // The value is planned to be printed on its own line, unless it is very short and contains + // no inner newlines. + + PREFIXED, + // The value is planned to be printed with a prefix, like "memberName = " (a struct field). + + PARENTHESIZED + // The value is printed in parenthesized (a union value). +}; + +enum class PrintKind { + LIST, + RECORD +}; + +class Indent { +public: + explicit Indent(bool enable): amount(enable ? 1 : 0) {} + + Indent next() { + return Indent(amount == 0 ? 0 : amount + 1); + } + + kj::StringTree delimit(kj::Array items, PrintMode mode, PrintKind kind) { + if (amount == 0 || canPrintAllInline(items, kind)) { + return kj::StringTree(kj::mv(items), ", "); + } else { + KJ_STACK_ARRAY(char, delimArrayPtr, amount * 2 + 3, 32, 256); + auto delim = delimArrayPtr.begin(); + delim[0] = ','; + delim[1] = '\n'; + memset(delim + 2, ' ', amount * 2); + delim[amount * 2 + 2] = '\0'; + + // If the outer value isn't being printed on its own line, we need to add a newline/indent + // before the first item, otherwise we only add a space on the assumption that it is preceded + // by an open bracket or parenthesis. + return kj::strTree(mode == BARE ? " " : delim + 1, + kj::StringTree(kj::mv(items), kj::StringPtr(delim, amount * 2 + 2)), ' '); + } + } + +private: + uint amount; + + explicit Indent(uint amount): amount(amount) {} + + static constexpr size_t maxInlineValueSize = 24; + static constexpr size_t maxInlineRecordSize = 64; + + static bool canPrintInline(const kj::StringTree& text) { + if (text.size() > maxInlineValueSize) { + return false; + } + + char flat[maxInlineValueSize + 1]; + text.flattenTo(flat); + flat[text.size()] = '\0'; + if (strchr(flat, '\n') != nullptr) { + return false; + } + + return true; + } + + static bool canPrintAllInline(const kj::Array& items, PrintKind kind) { + size_t totalSize = 0; + for (auto& item: items) { + if (!canPrintInline(item)) return false; + if (kind == PrintKind::RECORD) { + totalSize += item.size(); + if (totalSize > maxInlineRecordSize) return false; + } + } + return true; + } +}; + +static schema::Type::Which whichFieldType(const StructSchema::Field& field) { + auto proto = field.getProto(); + switch (proto.which()) { + case schema::Field::SLOT: + return proto.getSlot().getType().which(); + case schema::Field::GROUP: + return schema::Type::STRUCT; + } + KJ_UNREACHABLE; +} + +static kj::StringTree print(const DynamicValue::Reader& value, + schema::Type::Which which, Indent indent, + PrintMode mode) { + switch (value.getType()) { + case DynamicValue::UNKNOWN: + return kj::strTree("?"); + case DynamicValue::VOID: + return kj::strTree("void"); + case DynamicValue::BOOL: + return kj::strTree(value.as() ? "true" : "false"); + case DynamicValue::INT: + return kj::strTree(value.as()); + case DynamicValue::UINT: + return kj::strTree(value.as()); + case DynamicValue::FLOAT: + if (which == schema::Type::FLOAT32) { + return kj::strTree(value.as()); + } else { + return kj::strTree(value.as()); + } + case DynamicValue::TEXT: { + kj::ArrayPtr chars = value.as(); + return kj::strTree('"', kj::encodeCEscape(chars), '"'); + } + case DynamicValue::DATA: { + // TODO(someday): Maybe data should be printed as binary literal. + kj::ArrayPtr bytes = value.as().asBytes(); + return kj::strTree('"', kj::encodeCEscape(bytes), '"'); + } + case DynamicValue::LIST: { + auto listValue = value.as(); + auto which = listValue.getSchema().whichElementType(); + kj::Array elements = KJ_MAP(element, listValue) { + return print(element, which, indent.next(), BARE); + }; + return kj::strTree('[', indent.delimit(kj::mv(elements), mode, PrintKind::LIST), ']'); + } + case DynamicValue::ENUM: { + auto enumValue = value.as(); + KJ_IF_MAYBE(enumerant, enumValue.getEnumerant()) { + return kj::strTree(enumerant->getProto().getName()); + } else { + // Unknown enum value; output raw number. + return kj::strTree('(', enumValue.getRaw(), ')'); + } + break; + } + case DynamicValue::STRUCT: { + auto structValue = value.as(); + auto unionFields = structValue.getSchema().getUnionFields(); + auto nonUnionFields = structValue.getSchema().getNonUnionFields(); + + kj::Vector printedFields(nonUnionFields.size() + (unionFields.size() != 0)); + + // We try to write the union field, if any, in proper order with the rest. + auto which = structValue.which(); + + kj::StringTree unionValue; + KJ_IF_MAYBE(field, which) { + // Even if the union field has its default value, if it is not the default field of the + // union then we have to print it anyway. + auto fieldProto = field->getProto(); + if (fieldProto.getDiscriminantValue() != 0 || structValue.has(*field)) { + unionValue = kj::strTree( + fieldProto.getName(), " = ", + print(structValue.get(*field), whichFieldType(*field), indent.next(), PREFIXED)); + } else { + which = nullptr; + } + } + + for (auto field: nonUnionFields) { + KJ_IF_MAYBE(unionField, which) { + if (unionField->getIndex() < field.getIndex()) { + printedFields.add(kj::mv(unionValue)); + which = nullptr; + } + } + if (structValue.has(field)) { + printedFields.add(kj::strTree( + field.getProto().getName(), " = ", + print(structValue.get(field), whichFieldType(field), indent.next(), PREFIXED))); + } + } + if (which != nullptr) { + // Union value is last. + printedFields.add(kj::mv(unionValue)); + } + + if (mode == PARENTHESIZED) { + return indent.delimit(printedFields.releaseAsArray(), mode, PrintKind::RECORD); + } else { + return kj::strTree( + '(', indent.delimit(printedFields.releaseAsArray(), mode, PrintKind::RECORD), ')'); + } + } + case DynamicValue::ANY_POINTER: + return kj::strTree(""); + } + + KJ_UNREACHABLE; +} + +kj::StringTree stringify(DynamicValue::Reader value) { + return print(value, schema::Type::STRUCT, Indent(false), BARE); +} + +} // namespace + +kj::StringTree prettyPrint(DynamicStruct::Reader value) { + return print(value, schema::Type::STRUCT, Indent(true), BARE); +} + +kj::StringTree prettyPrint(DynamicList::Reader value) { + return print(value, schema::Type::LIST, Indent(true), BARE); +} + +kj::StringTree prettyPrint(DynamicStruct::Builder value) { return prettyPrint(value.asReader()); } +kj::StringTree prettyPrint(DynamicList::Builder value) { return prettyPrint(value.asReader()); } + +kj::StringTree KJ_STRINGIFY(const DynamicValue::Reader& value) { return stringify(value); } +kj::StringTree KJ_STRINGIFY(const DynamicValue::Builder& value) { return stringify(value.asReader()); } +kj::StringTree KJ_STRINGIFY(DynamicEnum value) { return stringify(value); } +kj::StringTree KJ_STRINGIFY(const DynamicStruct::Reader& value) { return stringify(value); } +kj::StringTree KJ_STRINGIFY(const DynamicStruct::Builder& value) { return stringify(value.asReader()); } +kj::StringTree KJ_STRINGIFY(const DynamicList::Reader& value) { return stringify(value); } +kj::StringTree KJ_STRINGIFY(const DynamicList::Builder& value) { return stringify(value.asReader()); } + +namespace _ { // private + +kj::StringTree structString(StructReader reader, const RawBrandedSchema& schema) { + return stringify(DynamicStruct::Reader(Schema(&schema).asStruct(), reader)); +} + +kj::String enumString(uint16_t value, const RawBrandedSchema& schema) { + auto enumerants = Schema(&schema).asEnum().getEnumerants(); + if (value < enumerants.size()) { + return kj::heapString(enumerants[value].getProto().getName()); + } else { + return kj::str(value); + } +} + +} // namespace _ (private) + +} // namespace capnp diff --git a/vendor/capnproto/src/kj/arena.c++ b/vendor/capnproto/src/kj/arena.c++ new file mode 100644 index 0000000..06dc060 --- /dev/null +++ b/vendor/capnproto/src/kj/arena.c++ @@ -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. + +#include "arena.h" +#include "debug.h" +#include + +namespace kj { + +Arena::Arena(size_t chunkSizeHint): nextChunkSize(kj::max(sizeof(ChunkHeader), chunkSizeHint)) {} + +Arena::Arena(ArrayPtr scratch) + : nextChunkSize(kj::max(sizeof(ChunkHeader), scratch.size())) { + if (scratch.size() > sizeof(ChunkHeader)) { + ChunkHeader* chunk = reinterpret_cast(scratch.begin()); + chunk->end = scratch.end(); + chunk->pos = reinterpret_cast(chunk + 1); + chunk->next = nullptr; // Never actually observed. + + // Don't place the chunk in the chunk list because it's not ours to delete. Just make it the + // current chunk so that we'll allocate from it until it is empty. + currentChunk = chunk; + } +} + +Arena::~Arena() noexcept(false) { + // Run cleanup() explicitly, but if it throws an exception, make sure to run it again as part of + // unwind. The second call will not throw because destructors are required to guard against + // exceptions when already unwinding. + KJ_ON_SCOPE_FAILURE(cleanup()); + cleanup(); +} + +void Arena::cleanup() { + while (objectList != nullptr) { + void* ptr = objectList + 1; + auto destructor = objectList->destructor; + objectList = objectList->next; + destructor(ptr); + } + + while (chunkList != nullptr) { + void* ptr = chunkList; + chunkList = chunkList->next; + operator delete(ptr); + } +} + +namespace { + +constexpr bool KJ_UNUSED isPowerOfTwo(size_t value) { + return (value & (value - 1)) == 0; +} + +inline byte* alignTo(byte* p, uint alignment) { + // Round the pointer up to the next aligned value. + + KJ_DASSERT(isPowerOfTwo(alignment), alignment); + uintptr_t mask = alignment - 1; + uintptr_t i = reinterpret_cast(p); + return reinterpret_cast((i + mask) & ~mask); +} + +inline size_t alignTo(size_t s, uint alignment) { + // Round the pointer up to the next aligned value. + + KJ_DASSERT(isPowerOfTwo(alignment), alignment); + size_t mask = alignment - 1; + return (s + mask) & ~mask; +} + +} // namespace + +void* Arena::allocateBytes(size_t amount, uint alignment, bool hasDisposer) { + if (hasDisposer) { + alignment = kj::max(alignment, alignof(ObjectHeader)); + amount += alignTo(sizeof(ObjectHeader), alignment); + } + + void* result = allocateBytesInternal(amount, alignment); + + if (hasDisposer) { + // Reserve space for the ObjectHeader, but don't add it to the object list yet. + result = alignTo(reinterpret_cast(result) + sizeof(ObjectHeader), alignment); + } + + KJ_DASSERT(reinterpret_cast(result) % alignment == 0); + return result; +} + +void* Arena::allocateBytesInternal(size_t amount, uint alignment) { + if (currentChunk != nullptr) { + ChunkHeader* chunk = currentChunk; + byte* alignedPos = alignTo(chunk->pos, alignment); + + // Careful about overflow here. + if (amount + (alignedPos - chunk->pos) <= chunk->end - chunk->pos) { + // There's enough space in this chunk. + chunk->pos = alignedPos + amount; + return alignedPos; + } + } + + // Not enough space in the current chunk. Allocate a new one. + + // We need to allocate at least enough space for the ChunkHeader and the requested allocation. + + // If the alignment is less than that of the chunk header, we'll need to increase it. + alignment = kj::max(alignment, alignof(ChunkHeader)); + + // If the ChunkHeader size does not match the alignment, we'll need to pad it up. + amount += alignTo(sizeof(ChunkHeader), alignment); + + // Make sure we're going to allocate enough space. + while (nextChunkSize < amount) { + nextChunkSize *= 2; + } + + // Allocate. + byte* bytes = reinterpret_cast(operator new(nextChunkSize)); + + // Set up the ChunkHeader at the beginning of the allocation. + ChunkHeader* newChunk = reinterpret_cast(bytes); + newChunk->next = chunkList; + newChunk->pos = bytes + amount; + newChunk->end = bytes + nextChunkSize; + currentChunk = newChunk; + chunkList = newChunk; + nextChunkSize *= 2; + + // Move past the ChunkHeader to find the position of the allocated object. + return alignTo(bytes + sizeof(ChunkHeader), alignment); +} + +StringPtr Arena::copyString(StringPtr content) { + char* data = reinterpret_cast(allocateBytes(content.size() + 1, 1, false)); + memcpy(data, content.cStr(), content.size() + 1); + return StringPtr(data, content.size()); +} + +void Arena::setDestructor(void* ptr, void (*destructor)(void*)) { + ObjectHeader* header = reinterpret_cast(ptr) - 1; + KJ_DASSERT(reinterpret_cast(header) % alignof(ObjectHeader) == 0); + header->destructor = destructor; + header->next = objectList; + objectList = header; +} + +} // namespace kj diff --git a/vendor/capnproto/src/kj/arena.h b/vendor/capnproto/src/kj/arena.h new file mode 100644 index 0000000..a16b291 --- /dev/null +++ b/vendor/capnproto/src/kj/arena.h @@ -0,0 +1,210 @@ +// 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. + +#pragma once + +#include "memory.h" +#include "array.h" +#include "string.h" + +KJ_BEGIN_HEADER + +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 scratch); + // Allocates from the given scratch space first, only resorting to the heap when it runs out. + + KJ_DISALLOW_COPY_AND_MOVE(Arena); + ~Arena() noexcept(false); + + template + T& allocate(Params&&... params); + template + ArrayPtr 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 + Own allocateOwn(Params&&... params); + template + Array allocateOwnArray(size_t size); + template + ArrayBuilder allocateOwnArrayBuilder(size_t capacity); + // Allocate an object or array of type T. Destructors are executed when the returned Own + // or Array 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 + inline T& copy(T&& value) { return allocate>(kj::fwd(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 + static void destroyArray(void* pointer) { + size_t elementCount = *reinterpret_cast(pointer); + constexpr size_t prefixSize = kj::max(alignof(T), sizeof(size_t)); + DestructorOnlyArrayDisposer::instance.disposeImpl( + reinterpret_cast(pointer) + prefixSize, + sizeof(T), elementCount, elementCount, &destroyObject); + } + + template + static void destroyObject(void* pointer) { + dtor(*reinterpret_cast(pointer)); + } +}; + +// ======================================================================================= +// Inline implementation details + +template +T& Arena::allocate(Params&&... params) { + T& result = *reinterpret_cast(allocateBytes( + sizeof(T), alignof(T), !KJ_HAS_TRIVIAL_DESTRUCTOR(T))); + if (!KJ_HAS_TRIVIAL_CONSTRUCTOR(T) || sizeof...(Params) > 0) { + ctor(result, kj::fwd(params)...); + } + if (!KJ_HAS_TRIVIAL_DESTRUCTOR(T)) { + setDestructor(&result, &destroyObject); + } + return result; +} + +template +ArrayPtr Arena::allocateArray(size_t size) { + if (KJ_HAS_TRIVIAL_DESTRUCTOR(T)) { + ArrayPtr result = + arrayPtr(reinterpret_cast(allocateBytes( + sizeof(T) * size, alignof(T), false)), size); + if (!KJ_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(base); + ArrayPtr result = + arrayPtr(reinterpret_cast(reinterpret_cast(base) + prefixSize), size); + setDestructor(base, &destroyArray); + + if (KJ_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 +Own Arena::allocateOwn(Params&&... params) { + T& result = *reinterpret_cast(allocateBytes(sizeof(T), alignof(T), false)); + if (!KJ_HAS_TRIVIAL_CONSTRUCTOR(T) || sizeof...(Params) > 0) { + ctor(result, kj::fwd(params)...); + } + return Own(&result, DestructorOnlyDisposer::instance); +} + +template +Array Arena::allocateOwnArray(size_t size) { + ArrayBuilder result = allocateOwnArrayBuilder(size); + for (size_t i = 0; i < size; i++) { + result.add(); + } + return result.finish(); +} + +template +ArrayBuilder Arena::allocateOwnArrayBuilder(size_t capacity) { + return ArrayBuilder( + reinterpret_cast(allocateBytes(sizeof(T) * capacity, alignof(T), false)), + capacity, DestructorOnlyArrayDisposer::instance); +} + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/array.c++ b/vendor/capnproto/src/kj/array.c++ new file mode 100644 index 0000000..3ac3d48 --- /dev/null +++ b/vendor/capnproto/src/kj/array.c++ @@ -0,0 +1,109 @@ +// 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 "array.h" +#include "exception.h" + +namespace kj { + +void ExceptionSafeArrayUtil::construct(size_t count, void (*constructElement)(void*)) { + while (count > 0) { + constructElement(pos); + pos += elementSize; + ++constructedElementCount; + --count; + } +} + +void ExceptionSafeArrayUtil::destroyAll() { + while (constructedElementCount > 0) { + pos -= elementSize; + --constructedElementCount; + destroyElement(pos); + } +} + +const DestructorOnlyArrayDisposer DestructorOnlyArrayDisposer::instance = + DestructorOnlyArrayDisposer(); + +void DestructorOnlyArrayDisposer::disposeImpl( + void* firstElement, size_t elementSize, size_t elementCount, + size_t capacity, void (*destroyElement)(void*)) const { + if (destroyElement != nullptr) { + ExceptionSafeArrayUtil guard(firstElement, elementSize, elementCount, destroyElement); + guard.destroyAll(); + } +} + +const NullArrayDisposer NullArrayDisposer::instance = NullArrayDisposer(); + +void NullArrayDisposer::disposeImpl( + void* firstElement, size_t elementSize, size_t elementCount, + size_t capacity, void (*destroyElement)(void*)) const {} + +namespace _ { // private + +struct AutoDeleter { + void* ptr; + inline void* release() { void* result = ptr; ptr = nullptr; return result; } + inline AutoDeleter(void* ptr): ptr(ptr) {} + inline ~AutoDeleter() { operator delete(ptr); } +}; + +void* HeapArrayDisposer::allocateImpl(size_t elementSize, size_t elementCount, size_t capacity, + void (*constructElement)(void*), + void (*destroyElement)(void*)) { + AutoDeleter result(operator new(elementSize * capacity)); + + if (constructElement == nullptr) { + // Nothing to do. + } else if (destroyElement == nullptr) { + byte* pos = reinterpret_cast(result.ptr); + while (elementCount > 0) { + constructElement(pos); + pos += elementSize; + --elementCount; + } + } else { + ExceptionSafeArrayUtil guard(result.ptr, elementSize, 0, destroyElement); + guard.construct(elementCount, constructElement); + guard.release(); + } + + return result.release(); +} + +void HeapArrayDisposer::disposeImpl( + void* firstElement, size_t elementSize, size_t elementCount, size_t capacity, + void (*destroyElement)(void*)) const { + // Note that capacity is ignored since operator delete() doesn't care about it. + AutoDeleter deleter(firstElement); + + if (destroyElement != nullptr) { + ExceptionSafeArrayUtil guard(firstElement, elementSize, elementCount, destroyElement); + guard.destroyAll(); + } +} + +const HeapArrayDisposer HeapArrayDisposer::instance = HeapArrayDisposer(); + +} // namespace _ (private) +} // namespace kj diff --git a/vendor/capnproto/src/kj/array.h b/vendor/capnproto/src/kj/array.h new file mode 100644 index 0000000..3932f9f --- /dev/null +++ b/vendor/capnproto/src/kj/array.h @@ -0,0 +1,913 @@ +// 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. + +#pragma once + +#include "memory.h" +#include +#include + +KJ_BEGIN_HEADER + +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 but may be different when using ArrayBuilder. + +public: + + template + 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 + 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(ptr) + elementSize * constructedElementCount), + elementSize(elementSize), constructedElementCount(constructedElementCount), + destroyElement(destroyElement) {} + KJ_DISALLOW_COPY_AND_MOVE(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 +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, 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>&& other) noexcept + : ptr(other.ptr), size_(other.size_), disposer(other.disposer) { + other.ptr = nullptr; + other.size_ = 0; + } + inline Array(T* firstElement KJ_LIFETIMEBOUND, size_t size, const ArrayDisposer& disposer) + : ptr(firstElement), size_(size), disposer(&disposer) {} + + KJ_DISALLOW_COPY(Array); + inline ~Array() noexcept { dispose(); } + + inline operator ArrayPtr() KJ_LIFETIMEBOUND { + return ArrayPtr(ptr, size_); + } + inline operator ArrayPtr() const KJ_LIFETIMEBOUND { + return ArrayPtr(ptr, size_); + } + inline ArrayPtr asPtr() KJ_LIFETIMEBOUND { + return ArrayPtr(ptr, size_); + } + inline ArrayPtr asPtr() const KJ_LIFETIMEBOUND { + return ArrayPtr(ptr, size_); + } + + inline size_t size() const { return size_; } + inline T& operator[](size_t index) KJ_LIFETIMEBOUND { + KJ_IREQUIRE(index < size_, "Out-of-bounds Array access."); + return ptr[index]; + } + inline const T& operator[](size_t index) const KJ_LIFETIMEBOUND { + KJ_IREQUIRE(index < size_, "Out-of-bounds Array access."); + return ptr[index]; + } + + inline const T* begin() const KJ_LIFETIMEBOUND { return ptr; } + inline const T* end() const KJ_LIFETIMEBOUND { return ptr + size_; } + inline const T& front() const KJ_LIFETIMEBOUND { return *ptr; } + inline const T& back() const KJ_LIFETIMEBOUND { return *(ptr + size_ - 1); } + inline T* begin() KJ_LIFETIMEBOUND { return ptr; } + inline T* end() KJ_LIFETIMEBOUND { return ptr + size_; } + inline T& front() KJ_LIFETIMEBOUND { return *ptr; } + inline T& back() KJ_LIFETIMEBOUND { return *(ptr + size_ - 1); } + + template + inline bool operator==(const U& other) const { return asPtr() == other; } + template + inline bool operator!=(const U& other) const { return asPtr() != other; } + + inline ArrayPtr slice(size_t start, size_t end) KJ_LIFETIMEBOUND { + KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds Array::slice()."); + return ArrayPtr(ptr + start, end - start); + } + inline ArrayPtr slice(size_t start, size_t end) const KJ_LIFETIMEBOUND { + KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds Array::slice()."); + return ArrayPtr(ptr + start, end - start); + } + + inline ArrayPtr asBytes() const KJ_LIFETIMEBOUND { return asPtr().asBytes(); } + inline ArrayPtr> asBytes() KJ_LIFETIMEBOUND { return asPtr().asBytes(); } + inline ArrayPtr asChars() const KJ_LIFETIMEBOUND { return asPtr().asChars(); } + inline ArrayPtr> asChars() KJ_LIFETIMEBOUND { return asPtr().asChars(); } + + inline Array> 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> result( + reinterpret_cast*>(ptr), size_, *disposer); + ptr = nullptr; + size_ = 0; + return result; + } + inline Array> releaseAsChars() { + // Like asChars() but transfers ownership. + static_assert(sizeof(T) == sizeof(PropagateConst), + "releaseAsChars() only possible on arrays with char-size elements (e.g. bytes)."); + Array> result( + reinterpret_cast*>(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; + } + + template + Array attach(Attachments&&... attachments) KJ_WARN_UNUSED_RESULT; + // Like Own::attach(), but attaches to an Array. + +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 + friend class Array; + template + friend class ArrayBuilder; +}; + +static_assert(!canMemcpy>(), "canMemcpy<>() is broken"); + +namespace _ { // private + +class HeapArrayDisposer final: public ArrayDisposer { +public: + template + static T* allocate(size_t count); + template + 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 + struct Allocate_; +}; + +} // namespace _ (private) + +template +inline Array heapArray(size_t size) { + // Much like `heap()` from memory.h, allocates a new array on the heap. + + return Array(_::HeapArrayDisposer::allocate(size), size, + _::HeapArrayDisposer::instance); +} + +template Array heapArray(const T* content, size_t size); +template Array heapArray(ArrayPtr content); +template Array heapArray(ArrayPtr content); +template Array heapArray(Iterator begin, Iterator end); +template Array heapArray(std::initializer_list init); +// Allocate a heap array containing a copy of the given content. + +template +Array heapArrayFromIterable(Container&& a) { return heapArray(a.begin(), a.end()); } +template +Array heapArrayFromIterable(Array&& a) { return mv(a); } + +// ======================================================================================= +// ArrayBuilder + +template +class ArrayBuilder { + // Class which lets you build an Array 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* 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; + } + ArrayBuilder(Array&& other) + : ptr(other.ptr), pos(other.ptr + other.size_), endPtr(pos), disposer(other.disposer) { + // Create an already-full ArrayBuilder from an Array of the same type. This constructor + // primarily exists to enable Vector to be constructed from Array. + other.ptr = nullptr; + other.size_ = 0; + } + KJ_DISALLOW_COPY(ArrayBuilder); + inline ~ArrayBuilder() noexcept(false) { dispose(); } + + inline operator ArrayPtr() KJ_LIFETIMEBOUND { + return arrayPtr(ptr, pos); + } + inline operator ArrayPtr() const KJ_LIFETIMEBOUND { + return arrayPtr(ptr, pos); + } + inline ArrayPtr asPtr() KJ_LIFETIMEBOUND { + return arrayPtr(ptr, pos); + } + inline ArrayPtr asPtr() const KJ_LIFETIMEBOUND { + 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) KJ_LIFETIMEBOUND { + KJ_IREQUIRE(index < implicitCast(pos - ptr), "Out-of-bounds Array access."); + return ptr[index]; + } + inline const T& operator[](size_t index) const KJ_LIFETIMEBOUND { + KJ_IREQUIRE(index < implicitCast(pos - ptr), "Out-of-bounds Array access."); + return ptr[index]; + } + + inline const T* begin() const KJ_LIFETIMEBOUND { return ptr; } + inline const T* end() const KJ_LIFETIMEBOUND { return pos; } + inline const T& front() const KJ_LIFETIMEBOUND { return *ptr; } + inline const T& back() const KJ_LIFETIMEBOUND { return *(pos - 1); } + inline T* begin() KJ_LIFETIMEBOUND { return ptr; } + inline T* end() KJ_LIFETIMEBOUND { return pos; } + inline T& front() KJ_LIFETIMEBOUND { return *ptr; } + inline T& back() KJ_LIFETIMEBOUND { 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 + T& add(Params&&... params) KJ_LIFETIMEBOUND { + KJ_IREQUIRE(pos < endPtr, "Added too many elements to ArrayBuilder."); + ctor(*pos, kj::fwd(params)...); + return *pos++; + } + + template + void addAll(Container&& container) { + addAll()>( + container.begin(), container.end()); + } + + template + 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 (KJ_HAS_TRIVIAL_DESTRUCTOR(T)) { + pos = target; + } else { + while (pos > target) { + kj::dtor(*--pos); + } + } + } + + void clear() { + if (KJ_HAS_TRIVIAL_DESTRUCTOR(T)) { + pos = ptr; + } else { + while (pos > ptr) { + 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 (KJ_HAS_TRIVIAL_CONSTRUCTOR(T)) { + pos = target; + } else { + while (pos < target) { + kj::ctor(*pos++); + } + } + } else { + // truncate + if (KJ_HAS_TRIVIAL_DESTRUCTOR(T)) { + pos = target; + } else { + while (pos > target) { + kj::dtor(*--pos); + } + } + } + } + + Array finish() { + // We could safely remove this check if we assume that the disposer implementation doesn't + // need to know the original capacity, as is the 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 result(reinterpret_cast(ptr), pos - ptr, *disposer); + ptr = nullptr; + pos = nullptr; + endPtr = nullptr; + return result; + } + + inline bool isFull() const { + return pos == endPtr; + } + +private: + T* ptr; + RemoveConst* pos; + T* endPtr; + const ArrayDisposer* disposer = &NullArrayDisposer::instance; + + 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 +inline ArrayBuilder heapArrayBuilder(size_t size) { + // Like `heapArray()` but does not default-construct the elements. You must construct them + // manually by calling `add()`. + + return ArrayBuilder(_::HeapArrayDisposer::allocateUninitialized>(size), + size, _::HeapArrayDisposer::instance); +} + +// ======================================================================================= +// Inline Arrays + +template +class FixedArray { + // A fixed-width array whose storage is allocated inline rather than on the heap. + +public: + inline constexpr size_t size() const { return fixedSize; } + inline constexpr T* begin() KJ_LIFETIMEBOUND { return content; } + inline constexpr T* end() KJ_LIFETIMEBOUND { return content + fixedSize; } + inline constexpr const T* begin() const KJ_LIFETIMEBOUND { return content; } + inline constexpr const T* end() const KJ_LIFETIMEBOUND { return content + fixedSize; } + + inline constexpr operator ArrayPtr() KJ_LIFETIMEBOUND { + return arrayPtr(content, fixedSize); + } + inline constexpr operator ArrayPtr() const KJ_LIFETIMEBOUND { + return arrayPtr(content, fixedSize); + } + + inline constexpr T& operator[](size_t index) KJ_LIFETIMEBOUND { return content[index]; } + inline constexpr const T& operator[](size_t index) const KJ_LIFETIMEBOUND { + return content[index]; + } + +private: + T content[fixedSize]; +}; + +template +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() KJ_LIFETIMEBOUND { return content; } + inline T* end() KJ_LIFETIMEBOUND { return content + currentSize; } + inline const T* begin() const KJ_LIFETIMEBOUND { return content; } + inline const T* end() const KJ_LIFETIMEBOUND { return content + currentSize; } + + inline operator ArrayPtr() KJ_LIFETIMEBOUND { + return arrayPtr(content, currentSize); + } + inline operator ArrayPtr() const KJ_LIFETIMEBOUND { + return arrayPtr(content, currentSize); + } + + inline T& operator[](size_t index) KJ_LIFETIMEBOUND { return content[index]; } + inline const T& operator[](size_t index) const KJ_LIFETIMEBOUND { return content[index]; } + +private: + size_t currentSize; + T content[fixedSize]; +}; + +// ======================================================================================= +// KJ_MAP + +#define KJ_MAP(elementName, array) \ + ::kj::_::Mapper(array) * \ + [&](typename ::kj::_::Mapper::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 bar = KJ_MAP(c, foo) -> char { return c + 1; }; +// KJ_ASSERT(str(bar) == "bcde"); + +namespace _ { // private + +template +struct Mapper { + T array; + Mapper(T&& array): array(kj::fwd(array)) {} + template + auto operator*(Func&& func) -> Array { + auto builder = heapArrayBuilder(array.size()); + for (auto iter = array.begin(); iter != array.end(); ++iter) { + builder.add(func(*iter)); + } + return builder.finish(); + } + typedef decltype(*kj::instance().begin()) Element; +}; + +template +struct Mapper { + T* array; + Mapper(T* array): array(array) {} + template + auto operator*(Func&& func) -> Array { + auto builder = heapArrayBuilder(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 +struct ArrayDisposer::Dispose_ { + static void dispose(T* firstElement, size_t elementCount, size_t capacity, + const ArrayDisposer& disposer) { + disposer.disposeImpl(const_cast*>(firstElement), + sizeof(T), elementCount, capacity, nullptr); + } +}; +template +struct ArrayDisposer::Dispose_ { + static void destruct(void* ptr) { + kj::dtor(*reinterpret_cast(ptr)); + } + + static void dispose(T* firstElement, size_t elementCount, size_t capacity, + const ArrayDisposer& disposer) { + disposer.disposeImpl(const_cast*>(firstElement), + sizeof(T), elementCount, capacity, &destruct); + } +}; + +template +void ArrayDisposer::dispose(T* firstElement, size_t elementCount, size_t capacity) const { + Dispose_::dispose(firstElement, elementCount, capacity, *this); +} + +namespace _ { // private + +template +struct HeapArrayDisposer::Allocate_ { + static T* allocate(size_t elementCount, size_t capacity) { + return reinterpret_cast(allocateImpl( + sizeof(T), elementCount, capacity, nullptr, nullptr)); + } +}; +template +struct HeapArrayDisposer::Allocate_ { + static void construct(void* ptr) { + kj::ctor(*reinterpret_cast(ptr)); + } + static T* allocate(size_t elementCount, size_t capacity) { + return reinterpret_cast(allocateImpl( + sizeof(T), elementCount, capacity, &construct, nullptr)); + } +}; +template +struct HeapArrayDisposer::Allocate_ { + static void construct(void* ptr) { + kj::ctor(*reinterpret_cast(ptr)); + } + static void destruct(void* ptr) { + kj::dtor(*reinterpret_cast(ptr)); + } + static T* allocate(size_t elementCount, size_t capacity) { + return reinterpret_cast(allocateImpl( + sizeof(T), elementCount, capacity, &construct, &destruct)); + } +}; + +template +T* HeapArrayDisposer::allocate(size_t count) { + return Allocate_::allocate(count, count); +} + +template +T* HeapArrayDisposer::allocateUninitialized(size_t count) { + return Allocate_::allocate(0, count); +} + +template ()> +struct CopyConstructArray_; + +template +struct CopyConstructArray_ { + static inline T* apply(T* __restrict__ pos, T* start, T* end) { + if (end != start) { + memcpy(pos, start, reinterpret_cast(end) - reinterpret_cast(start)); + } + return pos + (end - start); + } +}; + +template +struct CopyConstructArray_ { + static inline T* apply(T* __restrict__ pos, const T* start, const T* end) { + if (end != start) { + memcpy(pos, start, reinterpret_cast(end) - reinterpret_cast(start)); + } + return pos + (end - start); + } +}; + +template +struct CopyConstructArray_ { + 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 +struct CopyConstructArray_ { + 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(*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 +struct CopyConstructArray_ { + // 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(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 +template +void ArrayBuilder::addAll(Iterator start, Iterator end) { + pos = _::CopyConstructArray_, Decay, move>::apply(pos, start, end); +} + +template +Array heapArray(const T* content, size_t size) { + ArrayBuilder builder = heapArrayBuilder(size); + builder.addAll(content, content + size); + return builder.finish(); +} + +template +Array heapArray(T* content, size_t size) { + ArrayBuilder builder = heapArrayBuilder(size); + builder.addAll(content, content + size); + return builder.finish(); +} + +template +Array heapArray(ArrayPtr content) { + ArrayBuilder builder = heapArrayBuilder(content.size()); + builder.addAll(content); + return builder.finish(); +} + +template +Array heapArray(ArrayPtr content) { + ArrayBuilder builder = heapArrayBuilder(content.size()); + builder.addAll(content); + return builder.finish(); +} + +template Array +heapArray(Iterator begin, Iterator end) { + ArrayBuilder builder = heapArrayBuilder(end - begin); + builder.addAll(begin, end); + return builder.finish(); +} + +template +inline Array heapArray(std::initializer_list init) { + return heapArray(init.begin(), init.end()); +} + +#if KJ_CPP_STD > 201402L +template +inline Array> arr(T&& param1, Params&&... params) { + ArrayBuilder> builder = heapArrayBuilder>(sizeof...(params) + 1); + (builder.add(kj::fwd(param1)), ... , builder.add(kj::fwd(params))); + return builder.finish(); +} +template +inline Array> arrOf(Params&&... params) { + ArrayBuilder> builder = heapArrayBuilder>(sizeof...(params)); + (... , builder.add(kj::fwd(params))); + return builder.finish(); +} +#endif + +namespace _ { // private + +template +struct ArrayDisposableOwnedBundle final: public ArrayDisposer, public OwnedBundle { + ArrayDisposableOwnedBundle(T&&... values): OwnedBundle(kj::fwd(values)...) {} + void disposeImpl(void*, size_t, size_t, size_t, void (*)(void*)) const override { delete this; } +}; + +} // namespace _ (private) + +template +template +Array Array::attach(Attachments&&... attachments) { + T* ptrCopy = ptr; + auto sizeCopy = size_; + + KJ_IREQUIRE(ptrCopy != nullptr, "cannot attach to null pointer"); + + // HACK: If someone accidentally calls .attach() on a null pointer in opt mode, try our best to + // accomplish reasonable behavior: We turn the pointer non-null but still invalid, so that the + // disposer will still be called when the pointer goes out of scope. + if (ptrCopy == nullptr) ptrCopy = reinterpret_cast(1); + + auto bundle = new _::ArrayDisposableOwnedBundle, Attachments...>( + kj::mv(*this), kj::fwd(attachments)...); + return Array(ptrCopy, sizeCopy, *bundle); +} + +template +template +Array ArrayPtr::attach(Attachments&&... attachments) const { + T* ptrCopy = ptr; + + KJ_IREQUIRE(ptrCopy != nullptr, "cannot attach to null pointer"); + + // HACK: If someone accidentally calls .attach() on a null pointer in opt mode, try our best to + // accomplish reasonable behavior: We turn the pointer non-null but still invalid, so that the + // disposer will still be called when the pointer goes out of scope. + if (ptrCopy == nullptr) ptrCopy = reinterpret_cast(1); + + auto bundle = new _::ArrayDisposableOwnedBundle( + kj::fwd(attachments)...); + return Array(ptrCopy, size_, *bundle); +} + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/common.c++ b/vendor/capnproto/src/kj/common.c++ new file mode 100644 index 0000000..8960b23 --- /dev/null +++ b/vendor/capnproto/src/kj/common.c++ @@ -0,0 +1,49 @@ +// 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 "common.h" +#include "debug.h" +#include + +namespace kj { +namespace _ { // private + +void inlineRequireFailure(const char* file, int line, const char* expectation, + const char* macroArgs, const char* message) { + if (message == nullptr) { + Debug::Fault f(file, line, kj::Exception::Type::FAILED, expectation, macroArgs); + f.fatal(); + } else { + Debug::Fault f(file, line, kj::Exception::Type::FAILED, expectation, macroArgs, message); + f.fatal(); + } +} + +void unreachable() { + KJ_FAIL_ASSERT("Supposedly-unreachable branch executed."); + + // Really make sure we abort. + KJ_KNOWN_UNREACHABLE(abort()); +} + +} // namespace _ (private) + +} // namespace kj diff --git a/vendor/capnproto/src/kj/common.h b/vendor/capnproto/src/kj/common.h new file mode 100644 index 0000000..6160015 --- /dev/null +++ b/vendor/capnproto/src/kj/common.h @@ -0,0 +1,1929 @@ +// 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. + +// Header that should be #included by everyone. +// +// This defines very simple utilities that are widely applicable. + +#pragma once + +#if defined(__GNUC__) || defined(__clang__) +#define KJ_BEGIN_SYSTEM_HEADER _Pragma("GCC system_header") +#endif + +#ifndef KJ_BEGIN_SYSTEM_HEADER +#define KJ_BEGIN_SYSTEM_HEADER +#endif + +#ifndef KJ_END_SYSTEM_HEADER +#define KJ_END_SYSTEM_HEADER +#endif + +#if !defined(KJ_HEADER_WARNINGS) || !KJ_HEADER_WARNINGS +#define KJ_BEGIN_HEADER KJ_BEGIN_SYSTEM_HEADER +#define KJ_END_HEADER KJ_END_SYSTEM_HEADER +#else +#define KJ_BEGIN_HEADER +#define KJ_END_HEADER +#endif + +#ifdef __has_cpp_attribute +#define KJ_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +#define KJ_HAS_CPP_ATTRIBUTE(x) 0 +#endif + +#ifdef __has_feature +#define KJ_HAS_COMPILER_FEATURE(x) __has_feature(x) +#else +#define KJ_HAS_COMPILER_FEATURE(x) 0 +#endif + +#define KJ_CPP_STD __cplusplus + +KJ_BEGIN_HEADER + +#ifndef KJ_NO_COMPILER_CHECK +// Technically, __cplusplus should be 201402L for C++14, but GCC 4.9 -- which is supported -- still +// had it defined to 201300L even with -std=c++14. +#if KJ_CPP_STD < 201300L && !__CDT_PARSER__ + #error "This code requires C++14. Either your compiler does not support it or it is not enabled." + #ifdef __GNUC__ + // Compiler claims compatibility with GCC, so presumably supports -std. + #error "Pass -std=c++14 on the compiler command line to enable C++14." + #endif +#endif + +#ifdef __GNUC__ + #if __clang__ + #if __clang_major__ < 5 + #warning "This library requires at least Clang 5.0." + #elif KJ_CPP_STD >= 201402L && !__has_include() + #warning "Your compiler supports C++14 but your C++ standard library does not. If your "\ + "system has libc++ installed (as should be the case on e.g. Mac OSX), try adding "\ + "-stdlib=libc++ to your CXXFLAGS." + #endif + #else + #if __GNUC__ < 5 + #warning "This library requires at least GCC 5.0." + #endif + #endif +#else + #warning "I don't recognize your compiler. As of this writing, Clang, GCC, and Visual Studio "\ + "are the only known compilers with enough C++14 support for this library. "\ + "#define KJ_NO_COMPILER_CHECK to make this warning go away." +#endif +#endif + +#include +#include +#include +#include + +#if __linux__ && KJ_CPP_STD > 201200L +// Hack around stdlib bug with C++14 that exists on some Linux systems. +// Apparently in this mode the C library decides not to define gets() but the C++ library still +// tries to import it into the std namespace. This bug has been fixed at the source but is still +// widely present in the wild e.g. on Ubuntu 14.04. +#undef _GLIBCXX_HAVE_GETS +#endif + + + +// ======================================================================================= + +namespace kj { + +typedef unsigned int uint; +typedef unsigned char byte; + +// ======================================================================================= +// Common macros, especially for common yet compiler-specific features. + +// Detect whether RTTI and exceptions are enabled, assuming they are unless we have specific +// evidence to the contrary. Clients can always define KJ_NO_RTTI or KJ_NO_EXCEPTIONS explicitly +// to override these checks. + +// TODO: Ideally we'd use __cpp_exceptions/__cpp_rtti not being defined as the first pass since +// that is the standard compliant way. However, it's unclear how to use those macros (or any +// others) to distinguish between the compiler supporting feature detection and the feature being +// disabled vs the compiler not supporting feature detection at all. +#if defined(__has_feature) + #if !defined(KJ_NO_RTTI) && !__has_feature(cxx_rtti) + #define KJ_NO_RTTI 1 + #endif + #if !defined(KJ_NO_EXCEPTIONS) && !__has_feature(cxx_exceptions) + #define KJ_NO_EXCEPTIONS 1 + #endif +#elif defined(__GNUC__) + #if !defined(KJ_NO_RTTI) && !__GXX_RTTI + #define KJ_NO_RTTI 1 + #endif + #if !defined(KJ_NO_EXCEPTIONS) && !__EXCEPTIONS + #define KJ_NO_EXCEPTIONS 1 + #endif +#endif + +#if !defined(KJ_DEBUG) && !defined(KJ_NDEBUG) +// Heuristically decide whether to enable debug mode. If DEBUG or NDEBUG is defined, use that. +// Otherwise, fall back to checking whether optimization is enabled. +#if defined(DEBUG) || defined(_DEBUG) +#define KJ_DEBUG +#elif defined(NDEBUG) +#define KJ_NDEBUG +#elif __OPTIMIZE__ +#define KJ_NDEBUG +#else +#define KJ_DEBUG +#endif +#endif + +#define KJ_DISALLOW_COPY(classname) \ + classname(const classname&) = delete; \ + classname& operator=(const classname&) = delete +// Deletes the implicit copy constructor and assignment operator. This inhibits the compiler from +// generating the implicit move constructor and assignment operator for this class, but allows the +// code author to supply them, if they make sense to implement. +// +// This macro should not be your first choice. Instead, prefer using KJ_DISALLOW_COPY_AND_MOVE, and only use +// this macro when you have determined that you must implement move semantics for your type. + +#define KJ_DISALLOW_COPY_AND_MOVE(classname) \ + classname(const classname&) = delete; \ + classname& operator=(const classname&) = delete; \ + classname(classname&&) = delete; \ + classname& operator=(classname&&) = delete +// Deletes the implicit copy and move constructors and assignment operators. This is useful in cases +// where the code author wants to provide an additional compile-time guard against subsequent +// maintainers casually adding move operations. This is particularly useful when implementing RAII +// classes that are intended to be completely immobile. + +#ifdef __GNUC__ +#define KJ_LIKELY(condition) __builtin_expect(condition, true) +#define KJ_UNLIKELY(condition) __builtin_expect(condition, false) +// Branch prediction macros. Evaluates to the condition given, but also tells the compiler that we +// expect the condition to be true/false enough of the time that it's worth hard-coding branch +// prediction. +#else +#define KJ_LIKELY(condition) (condition) +#define KJ_UNLIKELY(condition) (condition) +#endif + +#if defined(KJ_DEBUG) || __NO_INLINE__ +#define KJ_ALWAYS_INLINE(...) inline __VA_ARGS__ +// Don't force inline in debug mode. +#else +#define KJ_ALWAYS_INLINE(...) inline __VA_ARGS__ __attribute__((always_inline)) +// Force a function to always be inlined. Apply only to the prototype, not to the definition. +#endif + +#define KJ_NOINLINE __attribute__((noinline)) + +#define KJ_NORETURN(prototype) prototype __attribute__((noreturn)) +#define KJ_UNUSED __attribute__((unused)) +#define KJ_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) + +#if KJ_HAS_CPP_ATTRIBUTE(clang::lifetimebound) +// If this is generating too many false-positives, the user is responsible for disabling the +// problematic warning at the compiler switch level or by suppressing the place where the +// false-positive is reported through compiler-specific pragmas if available. +#define KJ_LIFETIMEBOUND [[clang::lifetimebound]] +#else +#define KJ_LIFETIMEBOUND +#endif +// Annotation that indicates the returned value is referencing a resource owned by this type (e.g. +// cStr() on a std::string). Unfortunately this lifetime can only be superficial currently & cannot +// track further. For example, there's no way to get `array.asPtr().slice(5, 6))` to warn if the +// last slice exceeds the lifetime of `array`. That's because in the general case `ArrayPtr::slice` +// can't have the lifetime bound annotation since it's not wrong to do something like: +// ArrayPtr doSomething(ArrayPtr foo) { +// ... +// return foo.slice(5, 6); +// } +// If `ArrayPtr::slice` had a lifetime bound then the compiler would warn about this perfectly +// legitimate method. Really there needs to be 2 more annotations. One to inherit the lifetime bound +// and another to inherit the lifetime bound from a parameter (which really could be the same thing +// by allowing a syntax like `[[clang::lifetimebound(*this)]]`. +// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound + +#if __clang__ +#define KJ_UNUSED_MEMBER __attribute__((unused)) +// Inhibits "unused" warning for member variables. Only Clang produces such a warning, while GCC +// complains if the attribute is set on members. +#else +#define KJ_UNUSED_MEMBER +#endif + +#if KJ_CPP_STD > 201703L || (__clang__ && __clang_major__ >= 9 && KJ_CPP_STD >= 201103L) +// Technically this was only added to C++20 but Clang allows it for >= C++11 and spelunking the +// attributes manual indicates it first came in with Clang 9. +#define KJ_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else +#define KJ_NO_UNIQUE_ADDRESS +#endif + +#if KJ_HAS_COMPILER_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__) +#define KJ_DISABLE_TSAN __attribute__((no_sanitize("thread"), noinline)) +#else +#define KJ_DISABLE_TSAN +#endif + +#if __clang__ +#define KJ_DEPRECATED(reason) \ + __attribute__((deprecated(reason))) +#define KJ_UNAVAILABLE(reason) \ + __attribute__((unavailable(reason))) +#elif __GNUC__ +#define KJ_DEPRECATED(reason) \ + __attribute__((deprecated)) +#define KJ_UNAVAILABLE(reason) = delete +// If the `unavailable` attribute is not supproted, just mark the method deleted, which at least +// makes it a compile-time error to try to call it. Note that on Clang, marking a method deleted +// *and* unavailable unfortunately defeats the purpose of the unavailable annotation, as the +// generic "deleted" error is reported instead. +#else +#define KJ_DEPRECATED(reason) +#define KJ_UNAVAILABLE(reason) = delete +// TODO(msvc): Again, here, MSVC prefers a prefix, __declspec(deprecated). +#endif + +#if KJ_TESTING_KJ // defined in KJ's own unit tests; others should not define this +#undef KJ_DEPRECATED +#define KJ_DEPRECATED(reason) +#endif + +namespace _ { // private + +KJ_NORETURN(void inlineRequireFailure( + const char* file, int line, const char* expectation, const char* macroArgs, + const char* message = nullptr)); + +KJ_NORETURN(void unreachable()); + +} // namespace _ (private) + + +#ifdef KJ_DEBUG +#define KJ_IREQUIRE(condition, ...) \ + if (KJ_LIKELY(condition)); else ::kj::_::inlineRequireFailure( \ + __FILE__, __LINE__, #condition, #__VA_ARGS__, ##__VA_ARGS__) +// Version of KJ_DREQUIRE() which is safe to use in headers that are #included by users. Used to +// check preconditions inside inline methods. KJ_IREQUIRE is particularly useful in that +// it will be enabled depending on whether the application is compiled in debug mode rather than +// whether libkj is. +#else +#define KJ_IREQUIRE(condition, ...) +#endif + +#define KJ_IASSERT KJ_IREQUIRE + +#define KJ_UNREACHABLE ::kj::_::unreachable(); +// Put this on code paths that cannot be reached to suppress compiler warnings about missing +// returns. + +#if __clang__ +#define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT +#else +#define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT KJ_UNREACHABLE +#endif + +#if __clang__ +#define KJ_KNOWN_UNREACHABLE(code) \ + do { \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wunreachable-code\"") \ + code; \ + _Pragma("clang diagnostic pop") \ + } while (false) +// Suppress "unreachable code" warnings on intentionally unreachable code. +#else +// TODO(someday): Add support for non-clang compilers. +#define KJ_KNOWN_UNREACHABLE(code) do {code;} while(false) +#endif + +#if KJ_HAS_CPP_ATTRIBUTE(fallthrough) +#define KJ_FALLTHROUGH [[fallthrough]] +#else +#define KJ_FALLTHROUGH +#endif + +// #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) +// +// Allocate an array, preferably on the stack, unless it is too big. On GCC this will use +// variable-sized arrays. For other compilers we could just use a fixed-size array. `minStack` +// is the stack array size to use if variable-width arrays are not supported. `maxStack` is the +// maximum stack array size if variable-width arrays *are* supported. +#if __GNUC__ && !__clang__ +#define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) \ + size_t name##_size = (size); \ + bool name##_isOnStack = name##_size <= (maxStack); \ + type name##_stack[kj::max(1, name##_isOnStack ? name##_size : 0)]; \ + ::kj::Array name##_heap = name##_isOnStack ? \ + nullptr : kj::heapArray(name##_size); \ + ::kj::ArrayPtr name = name##_isOnStack ? \ + kj::arrayPtr(name##_stack, name##_size) : name##_heap +#else +#define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) \ + size_t name##_size = (size); \ + bool name##_isOnStack = name##_size <= (minStack); \ + type name##_stack[minStack]; \ + ::kj::Array name##_heap = name##_isOnStack ? \ + nullptr : kj::heapArray(name##_size); \ + ::kj::ArrayPtr name = name##_isOnStack ? \ + kj::arrayPtr(name##_stack, name##_size) : name##_heap +#endif + +#define KJ_CONCAT_(x, y) x##y +#define KJ_CONCAT(x, y) KJ_CONCAT_(x, y) +#define KJ_UNIQUE_NAME(prefix) KJ_CONCAT(prefix, __LINE__) +// Create a unique identifier name. We use concatenate __LINE__ rather than __COUNTER__ so that +// the name can be used multiple times in the same macro. + +#define KJ_CONSTEXPR(...) constexpr + +// ======================================================================================= +// Template metaprogramming helpers. + +#define KJ_HAS_TRIVIAL_CONSTRUCTOR __is_trivially_constructible +#if __GNUC__ && !__clang__ +#define KJ_HAS_NOTHROW_CONSTRUCTOR __has_nothrow_constructor +#define KJ_HAS_TRIVIAL_DESTRUCTOR __has_trivial_destructor +#else +#define KJ_HAS_NOTHROW_CONSTRUCTOR __is_nothrow_constructible +#define KJ_HAS_TRIVIAL_DESTRUCTOR __is_trivially_destructible +#endif + +template struct NoInfer_ { typedef T Type; }; +template using NoInfer = typename NoInfer_::Type; +// Use NoInfer::Type in place of T for a template function parameter to prevent inference of +// the type based on the parameter value. + +template struct RemoveConst_ { typedef T Type; }; +template struct RemoveConst_ { typedef T Type; }; +template using RemoveConst = typename RemoveConst_::Type; + +template struct IsLvalueReference_ { static constexpr bool value = false; }; +template struct IsLvalueReference_ { static constexpr bool value = true; }; +template +inline constexpr bool isLvalueReference() { return IsLvalueReference_::value; } + +template struct Decay_ { typedef T Type; }; +template struct Decay_ { typedef typename Decay_::Type Type; }; +template struct Decay_ { typedef typename Decay_::Type Type; }; +template struct Decay_ { typedef typename Decay_::Type Type; }; +template struct Decay_ { typedef typename Decay_::Type Type; }; +template struct Decay_ { typedef typename Decay_::Type Type; }; +template struct Decay_ { typedef typename Decay_::Type Type; }; +template struct Decay_ { typedef typename Decay_::Type Type; }; +template struct Decay_ { typedef typename Decay_::Type Type; }; +template using Decay = typename Decay_::Type; + +template struct EnableIf_; +template <> struct EnableIf_ { typedef void Type; }; +template using EnableIf = typename EnableIf_::Type; +// Use like: +// +// template ()>> +// void func(T&& t); + +template struct VoidSfinae_ { using Type = void; }; +template using VoidSfinae = typename VoidSfinae_::Type; +// Note: VoidSfinae is std::void_t from C++17. + +template +T instance() noexcept; +// Like std::declval, but doesn't transform T into an rvalue reference. If you want that, specify +// instance(). + +struct DisallowConstCopy { + // Inherit from this, or declare a member variable of this type, to prevent the class from being + // copyable from a const reference -- instead, it will only be copyable from non-const references. + // This is useful for enforcing transitive constness of contained pointers. + // + // For example, say you have a type T which contains a pointer. T has non-const methods which + // modify the value at that pointer, but T's const methods are designed to allow reading only. + // Unfortunately, if T has a regular copy constructor, someone can simply make a copy of T and + // then use it to modify the pointed-to value. However, if T inherits DisallowConstCopy, then + // callers will only be able to copy non-const instances of T. Ideally, there is some + // parallel type ImmutableT which is like a version of T that only has const methods, and can + // be copied from a const T. + // + // Note that due to C++ rules about implicit copy constructors and assignment operators, any + // type that contains or inherits from a type that disallows const copies will also automatically + // disallow const copies. Hey, cool, that's exactly what we want. + +#if CAPNP_DEBUG_TYPES + // Alas! Declaring a defaulted non-const copy constructor tickles a bug which causes GCC and + // Clang to disagree on ABI, using different calling conventions to pass this type, leading to + // immediate segfaults. See: + // https://bugs.llvm.org/show_bug.cgi?id=23764 + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58074 + // + // Because of this, we can't use this technique. We guard it by CAPNP_DEBUG_TYPES so that it + // still applies to the Cap'n Proto developers during internal testing. + + DisallowConstCopy() = default; + DisallowConstCopy(DisallowConstCopy&) = default; + DisallowConstCopy(DisallowConstCopy&&) = default; + DisallowConstCopy& operator=(DisallowConstCopy&) = default; + DisallowConstCopy& operator=(DisallowConstCopy&&) = default; +#endif +}; + + +#define KJ_CPCAP(obj) obj +// Clang and gcc both already perform copy capturing correctly with non-const copy constructors. + + +template +struct DisallowConstCopyIfNotConst: public DisallowConstCopy { + // Inherit from this when implementing a template that contains a pointer to T and which should + // enforce transitive constness. If T is a const type, this has no effect. Otherwise, it is + // an alias for DisallowConstCopy. +}; + +template +struct DisallowConstCopyIfNotConst {}; + +template struct IsConst_ { static constexpr bool value = false; }; +template struct IsConst_ { static constexpr bool value = true; }; +template constexpr bool isConst() { return IsConst_::value; } + +template struct EnableIfNotConst_ { typedef T Type; }; +template struct EnableIfNotConst_; +template using EnableIfNotConst = typename EnableIfNotConst_::Type; + +template struct EnableIfConst_; +template struct EnableIfConst_ { typedef T Type; }; +template using EnableIfConst = typename EnableIfConst_::Type; + +template struct RemoveConstOrDisable_ { struct Type; }; +template struct RemoveConstOrDisable_ { typedef T Type; }; +template using RemoveConstOrDisable = typename RemoveConstOrDisable_::Type; + +template struct IsReference_ { static constexpr bool value = false; }; +template struct IsReference_ { static constexpr bool value = true; }; +template constexpr bool isReference() { return IsReference_::value; } + +template +struct PropagateConst_ { typedef To Type; }; +template +struct PropagateConst_ { typedef const To Type; }; +template +using PropagateConst = typename PropagateConst_::Type; + +namespace _ { // private + +template +T refIfLvalue(T&&); + +} // namespace _ (private) + +#define KJ_DECLTYPE_REF(exp) decltype(::kj::_::refIfLvalue(exp)) +// Like decltype(exp), but if exp is an lvalue, produces a reference type. +// +// int i; +// decltype(i) i1(i); // i1 has type int. +// KJ_DECLTYPE_REF(i + 1) i2(i + 1); // i2 has type int. +// KJ_DECLTYPE_REF(i) i3(i); // i3 has type int&. +// KJ_DECLTYPE_REF(kj::mv(i)) i4(kj::mv(i)); // i4 has type int. + +template struct IsSameType_ { static constexpr bool value = false; }; +template struct IsSameType_ { static constexpr bool value = true; }; +template constexpr bool isSameType() { return IsSameType_::value; } + +template constexpr bool isIntegral() { return false; } +template <> constexpr bool isIntegral() { return true; } +template <> constexpr bool isIntegral() { return true; } +template <> constexpr bool isIntegral() { return true; } +template <> constexpr bool isIntegral() { return true; } +template <> constexpr bool isIntegral() { return true; } +template <> constexpr bool isIntegral() { return true; } +template <> constexpr bool isIntegral() { return true; } +template <> constexpr bool isIntegral() { return true; } +template <> constexpr bool isIntegral() { return true; } +template <> constexpr bool isIntegral() { return true; } +template <> constexpr bool isIntegral() { return true; } + +template +struct CanConvert_ { + static int sfinae(T); + static char sfinae(...); +}; + +template +constexpr bool canConvert() { + return sizeof(CanConvert_::sfinae(instance())) == sizeof(int); +} + +#if __GNUC__ && !__clang__ && __GNUC__ < 5 +template +constexpr bool canMemcpy() { + // Returns true if T can be copied using memcpy instead of using the copy constructor or + // assignment operator. + + // GCC 4 does not have __is_trivially_constructible and friends, and there doesn't seem to be + // any reliable alternative. __has_trivial_copy() and __has_trivial_assign() return the right + // thing at one point but later on they changed such that a deleted copy constructor was + // considered "trivial" (apparently technically correct, though useless). So, on GCC 4 we give up + // and assume we can't memcpy() at all, and must explicitly copy-construct everything. + return false; +} +#define KJ_ASSERT_CAN_MEMCPY(T) +#else +template +constexpr bool canMemcpy() { + // Returns true if T can be copied using memcpy instead of using the copy constructor or + // assignment operator. + + return __is_trivially_constructible(T, const T&) && __is_trivially_assignable(T&, const T&); +} +#define KJ_ASSERT_CAN_MEMCPY(T) \ + static_assert(kj::canMemcpy(), "this code expects this type to be memcpy()-able"); +#endif + +template +class Badge { + // A pattern for marking individual methods such that they can only be called from a specific + // caller class: Make the method public but give it a parameter of type `Badge`. Only + // `Caller` can construct one, so only `Caller` can call the method. + // + // // We only allow calls from the class `Bar`. + // void foo(Badge) + // + // The call site looks like: + // + // foo({}); + // + // This pattern also works well for declaring private constructors, but still being able to use + // them with `kj::heap()`, etc. + // + // Idea from: https://awesomekling.github.io/Serenity-C++-patterns-The-Badge/ + // + // Note that some forms of this idea make the copy constructor private as well, in order to + // prohibit `Badge(*(Badge*)nullptr)`. However, that would prevent badges from + // being passed through forwarding functions like `kj::heap()`, which would ruin one of the main + // use cases for this pattern in KJ. In any case, dereferencing a null pointer is UB; there are + // plenty of other ways to get access to private members if you're willing to go UB. For one-off + // debugging purposes, you might as well use `#define private public` at the top of the file. +private: + Badge() {} + friend T; +}; + +// ======================================================================================= +// Equivalents to std::move() and std::forward(), since these are very commonly needed and the +// std header pulls in lots of other stuff. +// +// We use abbreviated names mv and fwd because these helpers (especially mv) are so commonly used +// that the cost of typing more letters outweighs the cost of being slightly harder to understand +// when first encountered. + +template constexpr T&& mv(T& t) noexcept { return static_cast(t); } +template constexpr T&& fwd(NoInfer& t) noexcept { return static_cast(t); } + +template constexpr T cp(T& t) noexcept { return t; } +template constexpr T cp(const T& t) noexcept { return t; } +// Useful to force a copy, particularly to pass into a function that expects T&&. + +template struct ChooseType_; +template struct ChooseType_ { typedef T Type; }; +template struct ChooseType_ { typedef T Type; }; +template struct ChooseType_ { typedef U Type; }; + +template +using WiderType = typename ChooseType_= sizeof(U)>::Type; + +template +inline constexpr auto min(T&& a, U&& b) -> WiderType, Decay> { + return a < b ? WiderType, Decay>(a) : WiderType, Decay>(b); +} + +template +inline constexpr auto max(T&& a, U&& b) -> WiderType, Decay> { + return a > b ? WiderType, Decay>(a) : WiderType, Decay>(b); +} + +template +inline constexpr size_t size(T (&arr)[s]) { return s; } +template +inline constexpr size_t size(T&& arr) { return arr.size(); } +// Returns the size of the parameter, whether the parameter is a regular C array or a container +// with a `.size()` method. + +class MaxValue_ { +private: + template + inline constexpr T maxSigned() const { + return (1ull << (sizeof(T) * 8 - 1)) - 1; + } + template + inline constexpr T maxUnsigned() const { + return ~static_cast(0u); + } + +public: +#define _kJ_HANDLE_TYPE(T) \ + inline constexpr operator signed T() const { return MaxValue_::maxSigned < signed T>(); } \ + inline constexpr operator unsigned T() const { return MaxValue_::maxUnsigned(); } + _kJ_HANDLE_TYPE(char) + _kJ_HANDLE_TYPE(short) + _kJ_HANDLE_TYPE(int) + _kJ_HANDLE_TYPE(long) + _kJ_HANDLE_TYPE(long long) +#undef _kJ_HANDLE_TYPE + + inline constexpr operator char() const { + // `char` is different from both `signed char` and `unsigned char`, and may be signed or + // unsigned on different platforms. Ugh. + return char(-1) < 0 ? MaxValue_::maxSigned() + : MaxValue_::maxUnsigned(); + } +}; + +class MinValue_ { +private: + template + inline constexpr T minSigned() const { + return 1ull << (sizeof(T) * 8 - 1); + } + template + inline constexpr T minUnsigned() const { + return 0u; + } + +public: +#define _kJ_HANDLE_TYPE(T) \ + inline constexpr operator signed T() const { return MinValue_::minSigned < signed T>(); } \ + inline constexpr operator unsigned T() const { return MinValue_::minUnsigned(); } + _kJ_HANDLE_TYPE(char) + _kJ_HANDLE_TYPE(short) + _kJ_HANDLE_TYPE(int) + _kJ_HANDLE_TYPE(long) + _kJ_HANDLE_TYPE(long long) +#undef _kJ_HANDLE_TYPE + + inline constexpr operator char() const { + // `char` is different from both `signed char` and `unsigned char`, and may be signed or + // unsigned on different platforms. Ugh. + return char(-1) < 0 ? MinValue_::minSigned() + : MinValue_::minUnsigned(); + } +}; + +static KJ_CONSTEXPR(const) MaxValue_ maxValue = MaxValue_(); +// A special constant which, when cast to an integer type, takes on the maximum possible value of +// that type. This is useful to use as e.g. a parameter to a function because it will be robust +// in the face of changes to the parameter's type. +// +// `char` is not supported, but `signed char` and `unsigned char` are. + +static KJ_CONSTEXPR(const) MinValue_ minValue = MinValue_(); +// A special constant which, when cast to an integer type, takes on the minimum possible value +// of that type. This is useful to use as e.g. a parameter to a function because it will be robust +// in the face of changes to the parameter's type. +// +// `char` is not supported, but `signed char` and `unsigned char` are. + +template +inline bool operator==(T t, MaxValue_) { return t == Decay(maxValue); } +template +inline bool operator==(T t, MinValue_) { return t == Decay(minValue); } + +template +inline constexpr unsigned long long maxValueForBits() { + // Get the maximum integer representable in the given number of bits. + + // 1ull << 64 is unfortunately undefined. + return (bits == 64 ? 0 : (1ull << bits)) - 1; +} + +struct ThrowOverflow { + // Functor which throws an exception complaining about integer overflow. Usually this is used + // with the interfaces in units.h, but is defined here because Cap'n Proto wants to avoid + // including units.h when not using CAPNP_DEBUG_TYPES. + [[noreturn]] void operator()() const; +}; + +#if __GNUC__ || __clang__ +inline constexpr float inf() { return __builtin_huge_valf(); } +inline constexpr float nan() { return __builtin_nanf(""); } + +#else +#error "Not sure how to support your compiler." +#endif + +inline constexpr bool isNaN(float f) { return f != f; } +inline constexpr bool isNaN(double f) { return f != f; } + +inline int popCount(unsigned int x) { + return __builtin_popcount(x); +} + +// ======================================================================================= +// Useful fake containers + +template +class Range { +public: + inline constexpr Range(const T& begin, const T& end): begin_(begin), end_(end) {} + inline explicit constexpr Range(const T& end): begin_(0), end_(end) {} + + class Iterator { + public: + Iterator() = default; + inline Iterator(const T& value): value(value) {} + + inline const T& operator* () const { return value; } + inline const T& operator[](size_t index) const { return value + index; } + inline Iterator& operator++() { ++value; return *this; } + inline Iterator operator++(int) { return Iterator(value++); } + inline Iterator& operator--() { --value; return *this; } + inline Iterator operator--(int) { return Iterator(value--); } + inline Iterator& operator+=(ptrdiff_t amount) { value += amount; return *this; } + inline Iterator& operator-=(ptrdiff_t amount) { value -= amount; return *this; } + inline Iterator operator+ (ptrdiff_t amount) const { return Iterator(value + amount); } + inline Iterator operator- (ptrdiff_t amount) const { return Iterator(value - amount); } + inline ptrdiff_t operator- (const Iterator& other) const { return value - other.value; } + + inline bool operator==(const Iterator& other) const { return value == other.value; } + inline bool operator!=(const Iterator& other) const { return value != other.value; } + inline bool operator<=(const Iterator& other) const { return value <= other.value; } + inline bool operator>=(const Iterator& other) const { return value >= other.value; } + inline bool operator< (const Iterator& other) const { return value < other.value; } + inline bool operator> (const Iterator& other) const { return value > other.value; } + + private: + T value; + }; + + inline Iterator begin() const { return Iterator(begin_); } + inline Iterator end() const { return Iterator(end_); } + + inline auto size() const -> decltype(instance() - instance()) { return end_ - begin_; } + +private: + T begin_; + T end_; +}; + +template +inline constexpr Range, Decay>> range(T begin, U end) { + return Range, Decay>>(begin, end); +} + +template +inline constexpr Range> range(T begin, T end) { return Range>(begin, end); } +// Returns a fake iterable container containing all values of T from `begin` (inclusive) to `end` +// (exclusive). Example: +// +// // Prints 1, 2, 3, 4, 5, 6, 7, 8, 9. +// for (int i: kj::range(1, 10)) { print(i); } + +template +inline constexpr Range> zeroTo(T end) { return Range>(end); } +// Returns a fake iterable container containing all values of T from zero (inclusive) to `end` +// (exclusive). Example: +// +// // Prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. +// for (int i: kj::zeroTo(10)) { print(i); } + +template +inline constexpr Range indices(T&& container) { + // Shortcut for iterating over the indices of a container: + // + // for (size_t i: kj::indices(myArray)) { handle(myArray[i]); } + + return range(0, kj::size(container)); +} + +template +class Repeat { +public: + inline constexpr Repeat(const T& value, size_t count): value(value), count(count) {} + + class Iterator { + public: + Iterator() = default; + inline Iterator(const T& value, size_t index): value(value), index(index) {} + + inline const T& operator* () const { return value; } + inline const T& operator[](ptrdiff_t index) const { return value; } + inline Iterator& operator++() { ++index; return *this; } + inline Iterator operator++(int) { return Iterator(value, index++); } + inline Iterator& operator--() { --index; return *this; } + inline Iterator operator--(int) { return Iterator(value, index--); } + inline Iterator& operator+=(ptrdiff_t amount) { index += amount; return *this; } + inline Iterator& operator-=(ptrdiff_t amount) { index -= amount; return *this; } + inline Iterator operator+ (ptrdiff_t amount) const { return Iterator(value, index + amount); } + inline Iterator operator- (ptrdiff_t amount) const { return Iterator(value, index - amount); } + inline ptrdiff_t operator- (const Iterator& other) const { return index - other.index; } + + inline bool operator==(const Iterator& other) const { return index == other.index; } + inline bool operator!=(const Iterator& other) const { return index != other.index; } + inline bool operator<=(const Iterator& other) const { return index <= other.index; } + inline bool operator>=(const Iterator& other) const { return index >= other.index; } + inline bool operator< (const Iterator& other) const { return index < other.index; } + inline bool operator> (const Iterator& other) const { return index > other.index; } + + private: + T value; + size_t index; + }; + + inline Iterator begin() const { return Iterator(value, 0); } + inline Iterator end() const { return Iterator(value, count); } + + inline size_t size() const { return count; } + inline const T& operator[](ptrdiff_t) const { return value; } + +private: + T value; + size_t count; +}; + +template +inline constexpr Repeat> repeat(T&& value, size_t count) { + // Returns a fake iterable which contains `count` repeats of `value`. Useful for e.g. creating + // a bunch of spaces: `kj::repeat(' ', indent * 2)` + + return Repeat>(value, count); +} + +template +class MappedIterator: private Mapping { + // An iterator that wraps some other iterator and maps the values through a mapping function. + // The type `Mapping` must define a method `map()` which performs this mapping. + +public: + template + MappedIterator(Inner inner, Params&&... params) + : Mapping(kj::fwd(params)...), inner(inner) {} + + inline auto operator->() const { return &Mapping::map(*inner); } + inline decltype(auto) operator* () const { return Mapping::map(*inner); } + inline decltype(auto) operator[](size_t index) const { return Mapping::map(inner[index]); } + inline MappedIterator& operator++() { ++inner; return *this; } + inline MappedIterator operator++(int) { return MappedIterator(inner++, *this); } + inline MappedIterator& operator--() { --inner; return *this; } + inline MappedIterator operator--(int) { return MappedIterator(inner--, *this); } + inline MappedIterator& operator+=(ptrdiff_t amount) { inner += amount; return *this; } + inline MappedIterator& operator-=(ptrdiff_t amount) { inner -= amount; return *this; } + inline MappedIterator operator+ (ptrdiff_t amount) const { + return MappedIterator(inner + amount, *this); + } + inline MappedIterator operator- (ptrdiff_t amount) const { + return MappedIterator(inner - amount, *this); + } + inline ptrdiff_t operator- (const MappedIterator& other) const { return inner - other.inner; } + + inline bool operator==(const MappedIterator& other) const { return inner == other.inner; } + inline bool operator!=(const MappedIterator& other) const { return inner != other.inner; } + inline bool operator<=(const MappedIterator& other) const { return inner <= other.inner; } + inline bool operator>=(const MappedIterator& other) const { return inner >= other.inner; } + inline bool operator< (const MappedIterator& other) const { return inner < other.inner; } + inline bool operator> (const MappedIterator& other) const { return inner > other.inner; } + +private: + Inner inner; +}; + +template +class MappedIterable: private Mapping { + // An iterable that wraps some other iterable and maps the values through a mapping function. + // The type `Mapping` must define a method `map()` which performs this mapping. + +public: + template + MappedIterable(Inner inner, Params&&... params) + : Mapping(kj::fwd(params)...), inner(inner) {} + + typedef Decay().begin())> InnerIterator; + typedef MappedIterator Iterator; + typedef Decay().begin())> InnerConstIterator; + typedef MappedIterator ConstIterator; + + inline Iterator begin() { return { inner.begin(), (Mapping&)*this }; } + inline Iterator end() { return { inner.end(), (Mapping&)*this }; } + inline ConstIterator begin() const { return { inner.begin(), (const Mapping&)*this }; } + inline ConstIterator end() const { return { inner.end(), (const Mapping&)*this }; } + +private: + Inner inner; +}; + +// ======================================================================================= +// Manually invoking constructors and destructors +// +// ctor(x, ...) and dtor(x) invoke x's constructor or destructor, respectively. + +// We want placement new, but we don't want to #include . operator new cannot be defined in +// a namespace, and defining it globally conflicts with the definition in . So we have to +// define a dummy type and an operator new that uses it. The dummy type is intentionally passed +// as the last parameter so clang and GCC ABI calling conventions for empty struct struct parameters +// are compatible, and there are not segfaults trying to call clang operator new/delete from GCC or +// vice versa. + +namespace _ { // private +struct PlacementNew {}; +} // namespace _ (private) +} // namespace kj + +inline void* operator new(size_t, void* __p, kj::_::PlacementNew) noexcept { + return __p; +} + +inline void operator delete(void*, void* __p, kj::_::PlacementNew) noexcept {} + +namespace kj { + +template +inline void ctor(T& location, Params&&... params) { + new (&location, _::PlacementNew()) T(kj::fwd(params)...); +} + +template +inline void dtor(T& location) { + location.~T(); +} + +// ======================================================================================= +// Maybe +// +// Use in cases where you want to indicate that a value may be null. Using Maybe instead of T* +// forces the caller to handle the null case in order to satisfy the compiler, thus reliably +// preventing null pointer dereferences at runtime. +// +// Maybe can be implicitly constructed from T and from nullptr. +// To read the value of a Maybe, do: +// +// KJ_IF_MAYBE(value, someFuncReturningMaybe()) { +// doSomething(*value); +// } else { +// maybeWasNull(); +// } +// +// KJ_IF_MAYBE's first parameter is a variable name which will be defined within the following +// block. The variable will behave like a (guaranteed non-null) pointer to the Maybe's value, +// though it may or may not actually be a pointer. +// +// Note that Maybe actually just wraps a pointer, whereas Maybe wraps a T and a boolean +// indicating nullness. + +template +class Maybe; + +namespace _ { // private + +template +class NullableValue { + // Class whose interface behaves much like T*, but actually contains an instance of T and a + // boolean flag indicating nullness. + +public: + inline NullableValue(NullableValue&& other) + : isSet(other.isSet) { + if (isSet) { + ctor(value, kj::mv(other.value)); + } + } + inline NullableValue(const NullableValue& other) + : isSet(other.isSet) { + if (isSet) { + ctor(value, other.value); + } + } + inline NullableValue(NullableValue& other) + : isSet(other.isSet) { + if (isSet) { + ctor(value, other.value); + } + } + inline ~NullableValue() + noexcept(noexcept(instance().~T())) + { + if (isSet) { + dtor(value); + } + } + + inline T& operator*() & { return value; } + inline const T& operator*() const & { return value; } + inline T&& operator*() && { return kj::mv(value); } + inline const T&& operator*() const && { return kj::mv(value); } + inline T* operator->() { return &value; } + inline const T* operator->() const { return &value; } + inline operator T*() { return isSet ? &value : nullptr; } + inline operator const T*() const { return isSet ? &value : nullptr; } + + template + inline T& emplace(Params&&... params) { + if (isSet) { + isSet = false; + dtor(value); + } + ctor(value, kj::fwd(params)...); + isSet = true; + return value; + } + + inline NullableValue(): isSet(false) {} + inline NullableValue(T&& t) + : isSet(true) { + ctor(value, kj::mv(t)); + } + inline NullableValue(T& t) + : isSet(true) { + ctor(value, t); + } + inline NullableValue(const T& t) + : isSet(true) { + ctor(value, t); + } + template + inline NullableValue(NullableValue&& other) + : isSet(other.isSet) { + if (isSet) { + ctor(value, kj::mv(other.value)); + } + } + template + inline NullableValue(const NullableValue& other) + : isSet(other.isSet) { + if (isSet) { + ctor(value, other.value); + } + } + template + inline NullableValue(const NullableValue& other) + : isSet(other.isSet) { + if (isSet) { + ctor(value, *other.ptr); + } + } + inline NullableValue(decltype(nullptr)): isSet(false) {} + + inline NullableValue& operator=(NullableValue&& other) { + if (&other != this) { + // Careful about throwing destructors/constructors here. + if (isSet) { + isSet = false; + dtor(value); + } + if (other.isSet) { + ctor(value, kj::mv(other.value)); + isSet = true; + } + } + return *this; + } + + inline NullableValue& operator=(NullableValue& other) { + if (&other != this) { + // Careful about throwing destructors/constructors here. + if (isSet) { + isSet = false; + dtor(value); + } + if (other.isSet) { + ctor(value, other.value); + isSet = true; + } + } + return *this; + } + + inline NullableValue& operator=(const NullableValue& other) { + if (&other != this) { + // Careful about throwing destructors/constructors here. + if (isSet) { + isSet = false; + dtor(value); + } + if (other.isSet) { + ctor(value, other.value); + isSet = true; + } + } + return *this; + } + + inline NullableValue& operator=(T&& other) { emplace(kj::mv(other)); return *this; } + inline NullableValue& operator=(T& other) { emplace(other); return *this; } + inline NullableValue& operator=(const T& other) { emplace(other); return *this; } + template + inline NullableValue& operator=(NullableValue&& other) { + if (other.isSet) { + emplace(kj::mv(other.value)); + } else { + *this = nullptr; + } + return *this; + } + template + inline NullableValue& operator=(const NullableValue& other) { + if (other.isSet) { + emplace(other.value); + } else { + *this = nullptr; + } + return *this; + } + template + inline NullableValue& operator=(const NullableValue& other) { + if (other.isSet) { + emplace(other.value); + } else { + *this = nullptr; + } + return *this; + } + inline NullableValue& operator=(decltype(nullptr)) { + if (isSet) { + isSet = false; + dtor(value); + } + return *this; + } + + inline bool operator==(decltype(nullptr)) const { return !isSet; } + inline bool operator!=(decltype(nullptr)) const { return isSet; } + + NullableValue(const T* t) = delete; + NullableValue& operator=(const T* other) = delete; + // We used to permit assigning a Maybe directly from a T*, and the assignment would check for + // nullness. This turned out never to be useful, and sometimes to be dangerous. + +private: + bool isSet; + + + union { + T value; + }; + + + friend class kj::Maybe; + template + friend NullableValue&& readMaybe(Maybe&& maybe); +}; + +template +inline NullableValue&& readMaybe(Maybe&& maybe) { return kj::mv(maybe.ptr); } +template +inline T* readMaybe(Maybe& maybe) { return maybe.ptr; } +template +inline const T* readMaybe(const Maybe& maybe) { return maybe.ptr; } +template +inline T* readMaybe(Maybe&& maybe) { return maybe.ptr; } +template +inline T* readMaybe(const Maybe& maybe) { return maybe.ptr; } + +template +inline T* readMaybe(T* ptr) { return ptr; } +// Allow KJ_IF_MAYBE to work on regular pointers. + +} // namespace _ (private) + +#define KJ_IF_MAYBE(name, exp) if (auto name = ::kj::_::readMaybe(exp)) + +#if __GNUC__ || __clang__ +// These two macros provide a friendly syntax to extract the value of a Maybe or return early. +// +// Use KJ_UNWRAP_OR_RETURN if you just want to return a simple value when the Maybe is null: +// +// int foo(Maybe maybe) { +// int value = KJ_UNWRAP_OR_RETURN(maybe, -1); +// // ... use value ... +// } +// +// For functions returning void, omit the second parameter to KJ_UNWRAP_OR_RETURN: +// +// void foo(Maybe maybe) { +// int value = KJ_UNWRAP_OR_RETURN(maybe); +// // ... use value ... +// } +// +// Use KJ_UNWRAP_OR if you want to execute a block with multiple statements. +// +// int foo(Maybe maybe) { +// int value = KJ_UNWRAP_OR(maybe, { +// KJ_LOG(ERROR, "problem!!!"); +// return -1; +// }); +// // ... use value ... +// } +// +// The block MUST return at the end or you will get a compiler error +// +// Unfortunately, these macros seem impossible to express without using GCC's non-standard +// "statement expressions" extension. IIFEs don't do the trick here because a lambda cannot +// return out of the parent scope. These macros should therefore only be used in projects that +// target GCC or GCC-compatible compilers. +// +// `__GNUC__` is not defined when using LLVM's MSVC-compatible compiler driver `clang-cl` (even +// though clang supports the required extension), hence the additional `|| __clang__`. + +#define KJ_UNWRAP_OR_RETURN(value, ...) \ + (*({ \ + auto _kj_result = ::kj::_::readMaybe(value); \ + if (!_kj_result) { \ + return __VA_ARGS__; \ + } \ + kj::mv(_kj_result); \ + })) + +#define KJ_UNWRAP_OR(value, block) \ + (*({ \ + auto _kj_result = ::kj::_::readMaybe(value); \ + if (!_kj_result) { \ + block; \ + asm("KJ_UNWRAP_OR_block_is_missing_return_statement\n"); \ + } \ + kj::mv(_kj_result); \ + })) +#endif + +template +class Maybe { + // A T, or nullptr. + + // IF YOU CHANGE THIS CLASS: Note that there is a specialization of it in memory.h. + +public: + Maybe(): ptr(nullptr) {} + Maybe(T&& t): ptr(kj::mv(t)) {} + Maybe(T& t): ptr(t) {} + Maybe(const T& t): ptr(t) {} + Maybe(Maybe&& other): ptr(kj::mv(other.ptr)) { other = nullptr; } + Maybe(const Maybe& other): ptr(other.ptr) {} + Maybe(Maybe& other): ptr(other.ptr) {} + + template + Maybe(Maybe&& other) { + KJ_IF_MAYBE(val, kj::mv(other)) { + ptr.emplace(kj::mv(*val)); + other = nullptr; + } + } + template + Maybe(Maybe&& other) { + KJ_IF_MAYBE(val, other) { + ptr.emplace(*val); + other = nullptr; + } + } + template + Maybe(const Maybe& other) { + KJ_IF_MAYBE(val, other) { + ptr.emplace(*val); + } + } + + Maybe(decltype(nullptr)): ptr(nullptr) {} + + template + inline T& emplace(Params&&... params) { + // Replace this Maybe's content with a new value constructed by passing the given parameters to + // T's constructor. This can be used to initialize a Maybe without copying or even moving a T. + // Returns a reference to the newly-constructed value. + + return ptr.emplace(kj::fwd(params)...); + } + + inline Maybe& operator=(T&& other) { ptr = kj::mv(other); return *this; } + inline Maybe& operator=(T& other) { ptr = other; return *this; } + inline Maybe& operator=(const T& other) { ptr = other; return *this; } + + inline Maybe& operator=(Maybe&& other) { ptr = kj::mv(other.ptr); other = nullptr; return *this; } + inline Maybe& operator=(Maybe& other) { ptr = other.ptr; return *this; } + inline Maybe& operator=(const Maybe& other) { ptr = other.ptr; return *this; } + + template + Maybe& operator=(Maybe&& other) { + KJ_IF_MAYBE(val, kj::mv(other)) { + ptr.emplace(kj::mv(*val)); + other = nullptr; + } else { + ptr = nullptr; + } + return *this; + } + template + Maybe& operator=(const Maybe& other) { + KJ_IF_MAYBE(val, other) { + ptr.emplace(*val); + } else { + ptr = nullptr; + } + return *this; + } + + inline Maybe& operator=(decltype(nullptr)) { ptr = nullptr; return *this; } + + inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; } + inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; } + + inline bool operator==(const Maybe& other) const { + if (ptr == nullptr) { + return other == nullptr; + } else { + return other.ptr != nullptr && *ptr == *other.ptr; + } + } + inline bool operator!=(const Maybe& other) const { return !(*this == other); } + + Maybe(const T* t) = delete; + Maybe& operator=(const T* other) = delete; + // We used to permit assigning a Maybe directly from a T*, and the assignment would check for + // nullness. This turned out never to be useful, and sometimes to be dangerous. + + T& orDefault(T& defaultValue) & { + if (ptr == nullptr) { + return defaultValue; + } else { + return *ptr; + } + } + const T& orDefault(const T& defaultValue) const & { + if (ptr == nullptr) { + return defaultValue; + } else { + return *ptr; + } + } + T&& orDefault(T&& defaultValue) && { + if (ptr == nullptr) { + return kj::mv(defaultValue); + } else { + return kj::mv(*ptr); + } + } + const T&& orDefault(const T&& defaultValue) const && { + if (ptr == nullptr) { + return kj::mv(defaultValue); + } else { + return kj::mv(*ptr); + } + } + + template () ? instance() : instance()())> + Result orDefault(F&& lazyDefaultValue) & { + if (ptr == nullptr) { + return lazyDefaultValue(); + } else { + return *ptr; + } + } + + template () ? instance() : instance()())> + Result orDefault(F&& lazyDefaultValue) const & { + if (ptr == nullptr) { + return lazyDefaultValue(); + } else { + return *ptr; + } + } + + template () ? instance() : instance()())> + Result orDefault(F&& lazyDefaultValue) && { + if (ptr == nullptr) { + return lazyDefaultValue(); + } else { + return kj::mv(*ptr); + } + } + + template () ? instance() : instance()())> + Result orDefault(F&& lazyDefaultValue) const && { + if (ptr == nullptr) { + return lazyDefaultValue(); + } else { + return kj::mv(*ptr); + } + } + + template + auto map(Func&& f) & -> Maybe()))> { + if (ptr == nullptr) { + return nullptr; + } else { + return f(*ptr); + } + } + + template + auto map(Func&& f) const & -> Maybe()))> { + if (ptr == nullptr) { + return nullptr; + } else { + return f(*ptr); + } + } + + template + auto map(Func&& f) && -> Maybe()))> { + if (ptr == nullptr) { + return nullptr; + } else { + return f(kj::mv(*ptr)); + } + } + + template + auto map(Func&& f) const && -> Maybe()))> { + if (ptr == nullptr) { + return nullptr; + } else { + return f(kj::mv(*ptr)); + } + } + +private: + _::NullableValue ptr; + + template + friend class Maybe; + template + friend _::NullableValue&& _::readMaybe(Maybe&& maybe); + template + friend U* _::readMaybe(Maybe& maybe); + template + friend const U* _::readMaybe(const Maybe& maybe); +}; + +template +class Maybe { +public: + constexpr Maybe(): ptr(nullptr) {} + constexpr Maybe(T& t): ptr(&t) {} + constexpr Maybe(T* t): ptr(t) {} + + inline constexpr Maybe(PropagateConst& other): ptr(other.ptr) {} + // Allow const copy only if `T` itself is const. Otherwise allow only non-const copy, to + // protect transitive constness. Clang is happy for this constructor to be declared `= default` + // since, after evaluation of `PropagateConst`, it does end up being a default-able constructor. + // But, GCC and MSVC both complain about that, claiming this constructor cannot be declared + // default. I don't know who is correct, but whatever, we'll write out an implementation, fine. + // + // Note that we can't solve this by inheriting DisallowConstCopyIfNotConst because we want + // to override the move constructor, and if we override the move constructor then we must define + // the copy constructor here. + + inline constexpr Maybe(Maybe&& other): ptr(other.ptr) { other.ptr = nullptr; } + + template + inline constexpr Maybe(Maybe& other): ptr(other.ptr) {} + template + inline constexpr Maybe(const Maybe& other): ptr(const_cast(other.ptr)) {} + template + inline constexpr Maybe(Maybe&& other): ptr(other.ptr) { other.ptr = nullptr; } + template + inline constexpr Maybe(const Maybe&& other) = delete; + template ()>> + constexpr Maybe(Maybe& other): ptr(other.ptr.operator U*()) {} + template ()>> + constexpr Maybe(const Maybe& other): ptr(other.ptr.operator const U*()) {} + inline constexpr Maybe(decltype(nullptr)): ptr(nullptr) {} + + inline Maybe& operator=(T& other) { ptr = &other; return *this; } + inline Maybe& operator=(T* other) { ptr = other; return *this; } + inline Maybe& operator=(PropagateConst& other) { ptr = other.ptr; return *this; } + inline Maybe& operator=(Maybe&& other) { ptr = other.ptr; other.ptr = nullptr; return *this; } + template + inline Maybe& operator=(Maybe& other) { ptr = other.ptr; return *this; } + template + inline Maybe& operator=(const Maybe& other) { ptr = other.ptr; return *this; } + template + inline Maybe& operator=(Maybe&& other) { ptr = other.ptr; other.ptr = nullptr; return *this; } + template + inline Maybe& operator=(const Maybe&& other) = delete; + + inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; } + inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; } + + T& orDefault(T& defaultValue) { + if (ptr == nullptr) { + return defaultValue; + } else { + return *ptr; + } + } + const T& orDefault(const T& defaultValue) const { + if (ptr == nullptr) { + return defaultValue; + } else { + return *ptr; + } + } + + template + auto map(Func&& f) -> Maybe()))> { + if (ptr == nullptr) { + return nullptr; + } else { + return f(*ptr); + } + } + + template + auto map(Func&& f) const -> Maybe()))> { + if (ptr == nullptr) { + return nullptr; + } else { + const T& ref = *ptr; + return f(ref); + } + } + +private: + T* ptr; + + template + friend class Maybe; + template + friend U* _::readMaybe(Maybe&& maybe); + template + friend U* _::readMaybe(const Maybe& maybe); +}; + +// ======================================================================================= +// ArrayPtr +// +// So common that we put it in common.h rather than array.h. + +template +class Array; + +template +class ArrayPtr: public DisallowConstCopyIfNotConst { + // A pointer to an array. Includes a size. Like any pointer, it doesn't own the target data, + // and passing by value only copies the pointer, not the target. + +public: + inline constexpr ArrayPtr(): ptr(nullptr), size_(0) {} + inline constexpr ArrayPtr(decltype(nullptr)): ptr(nullptr), size_(0) {} + inline constexpr ArrayPtr(T* ptr KJ_LIFETIMEBOUND, size_t size): ptr(ptr), size_(size) {} + inline constexpr ArrayPtr(T* begin KJ_LIFETIMEBOUND, T* end KJ_LIFETIMEBOUND) + : ptr(begin), size_(end - begin) {} + ArrayPtr& operator=(Array&&) = delete; + ArrayPtr& operator=(decltype(nullptr)) { + ptr = nullptr; + size_ = 0; + return *this; + } + +#if __GNUC__ && !__clang__ && __GNUC__ >= 9 +// GCC 9 added a warning when we take an initializer_list as a constructor parameter and save a +// pointer to its content in a class member. GCC apparently imagines we're going to do something +// dumb like this: +// ArrayPtr ptr = { 1, 2, 3 }; +// foo(ptr[1]); // undefined behavior! +// Any KJ programmer should be able to recognize that this is UB, because an ArrayPtr does not own +// its content. That's not what this constructor is for, tohugh. This constructor is meant to allow +// code like this: +// int foo(ArrayPtr p); +// // ... later ... +// foo({1, 2, 3}); +// In this case, the initializer_list's backing array, like any temporary, lives until the end of +// the statement `foo({1, 2, 3});`. Therefore, it lives at least until the call to foo() has +// returned, which is exactly what we care about. This usage is fine! GCC is wrong to warn. +// +// Amusingly, Clang's implementation has a similar type that they call ArrayRef which apparently +// triggers this same GCC warning. My guess is that Clang will not introduce a similar warning +// given that it triggers on their own, legitimate code. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-list-lifetime" +#endif + inline KJ_CONSTEXPR() ArrayPtr( + ::std::initializer_list> init KJ_LIFETIMEBOUND) + : ptr(init.begin()), size_(init.size()) {} +#if __GNUC__ && !__clang__ && __GNUC__ >= 9 +#pragma GCC diagnostic pop +#endif + + template + inline constexpr ArrayPtr(KJ_LIFETIMEBOUND T (&native)[size]): ptr(native), size_(size) { + // Construct an ArrayPtr from a native C-style array. + // + // We disable this constructor for const char arrays because otherwise you would be able to + // implicitly convert a character literal to ArrayPtr, which sounds really great, + // except that the NUL terminator would be included, which probably isn't what you intended. + // + // TODO(someday): Maybe we should support character literals but explicitly chop off the NUL + // terminator. This could do the wrong thing if someone tries to construct an + // ArrayPtr from a non-NUL-terminated char array, but evidence suggests that all + // real use cases are in fact intending to remove the NUL terminator. It's convenient to be + // able to specify ArrayPtr as a parameter type and be able to accept strings + // as input in addition to arrays. Currently, you'll need overloading to support string + // literals in this case, but if you overload StringPtr, then you'll find that several + // conversions (e.g. from String and from a literal char array) become ambiguous! You end up + // having to overload for literal char arrays specifically which is cumbersome. + + static_assert(!isSameType(), + "Can't implicitly convert literal char array to ArrayPtr because we don't know if " + "you meant to include the NUL terminator. We may change this in the future to " + "automatically drop the NUL terminator. For now, try explicitly converting to StringPtr, " + "which can in turn implicitly convert to ArrayPtr."); + static_assert(!isSameType(), "see above"); + static_assert(!isSameType(), "see above"); + } + + inline operator ArrayPtr() const { + return ArrayPtr(ptr, size_); + } + inline ArrayPtr asConst() const { + return ArrayPtr(ptr, size_); + } + + inline constexpr size_t size() const { return size_; } + inline const T& operator[](size_t index) const { + KJ_IREQUIRE(index < size_, "Out-of-bounds ArrayPtr access."); + return ptr[index]; + } + inline T& operator[](size_t index) { + KJ_IREQUIRE(index < size_, "Out-of-bounds ArrayPtr access."); + return ptr[index]; + } + + inline T* begin() { return ptr; } + inline T* end() { return ptr + size_; } + inline T& front() { return *ptr; } + inline T& back() { return *(ptr + size_ - 1); } + inline constexpr const T* begin() const { return ptr; } + inline constexpr const T* end() const { return ptr + size_; } + inline const T& front() const { return *ptr; } + inline const T& back() const { return *(ptr + size_ - 1); } + + inline ArrayPtr slice(size_t start, size_t end) const { + KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice()."); + return ArrayPtr(ptr + start, end - start); + } + inline ArrayPtr slice(size_t start, size_t end) { + KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice()."); + return ArrayPtr(ptr + start, end - start); + } + inline bool startsWith(const ArrayPtr& other) const { + return other.size() <= size_ && slice(0, other.size()) == other; + } + inline bool endsWith(const ArrayPtr& other) const { + return other.size() <= size_ && slice(size_ - other.size(), size_) == other; + } + + inline Maybe findFirst(const T& match) const { + for (size_t i = 0; i < size_; i++) { + if (ptr[i] == match) { + return i; + } + } + return nullptr; + } + inline Maybe findLast(const T& match) const { + for (size_t i = size_; i--;) { + if (ptr[i] == match) { + return i; + } + } + return nullptr; + } + + inline ArrayPtr> asBytes() const { + // Reinterpret the array as a byte array. This is explicitly legal under C++ aliasing + // rules. + return { reinterpret_cast*>(ptr), size_ * sizeof(T) }; + } + inline ArrayPtr> asChars() const { + // Reinterpret the array as a char array. This is explicitly legal under C++ aliasing + // rules. + return { reinterpret_cast*>(ptr), size_ * sizeof(T) }; + } + + inline bool operator==(decltype(nullptr)) const { return size_ == 0; } + inline bool operator!=(decltype(nullptr)) const { return size_ != 0; } + + inline bool operator==(const ArrayPtr& other) const { + if (size_ != other.size_) return false; + if (isIntegral>()) { + if (size_ == 0) return true; + return memcmp(ptr, other.ptr, size_ * sizeof(T)) == 0; + } + for (size_t i = 0; i < size_; i++) { + if (ptr[i] != other[i]) return false; + } + return true; + } +#if !__cpp_impl_three_way_comparison + inline bool operator!=(const ArrayPtr& other) const { return !(*this == other); } +#endif + + template + inline bool operator==(const ArrayPtr& other) const { + if (size_ != other.size()) return false; + for (size_t i = 0; i < size_; i++) { + if (ptr[i] != other[i]) return false; + } + return true; + } +#if !__cpp_impl_three_way_comparison + template + inline bool operator!=(const ArrayPtr& other) const { return !(*this == other); } +#endif + + template + Array attach(Attachments&&... attachments) const KJ_WARN_UNUSED_RESULT; + // Like Array::attach(), but also promotes an ArrayPtr to an Array. Generally the attachment + // should be an object that actually owns the array that the ArrayPtr is pointing at. + // + // You must include kj/array.h to call this. + +private: + T* ptr; + size_t size_; +}; + +template <> +inline Maybe ArrayPtr::findFirst(const char& c) const { + const char* pos = reinterpret_cast(memchr(ptr, c, size_)); + if (pos == nullptr) { + return nullptr; + } else { + return pos - ptr; + } +} + +template <> +inline Maybe ArrayPtr::findFirst(const char& c) const { + char* pos = reinterpret_cast(memchr(ptr, c, size_)); + if (pos == nullptr) { + return nullptr; + } else { + return pos - ptr; + } +} + +template <> +inline Maybe ArrayPtr::findFirst(const byte& c) const { + const byte* pos = reinterpret_cast(memchr(ptr, c, size_)); + if (pos == nullptr) { + return nullptr; + } else { + return pos - ptr; + } +} + +template <> +inline Maybe ArrayPtr::findFirst(const byte& c) const { + byte* pos = reinterpret_cast(memchr(ptr, c, size_)); + if (pos == nullptr) { + return nullptr; + } else { + return pos - ptr; + } +} + +// glibc has a memrchr() for reverse search but it's non-standard, so we don't bother optimizing +// findLast(), which isn't used much anyway. + +template +inline constexpr ArrayPtr arrayPtr(T* ptr KJ_LIFETIMEBOUND, size_t size) { + // Use this function to construct ArrayPtrs without writing out the type name. + return ArrayPtr(ptr, size); +} + +template +inline constexpr ArrayPtr arrayPtr(T* begin KJ_LIFETIMEBOUND, T* end KJ_LIFETIMEBOUND) { + // Use this function to construct ArrayPtrs without writing out the type name. + return ArrayPtr(begin, end); +} + +// ======================================================================================= +// Casts + +template +To implicitCast(From&& from) { + // `implicitCast(value)` casts `value` to type `T` only if the conversion is implicit. Useful + // for e.g. resolving ambiguous overloads without sacrificing type-safety. + return kj::fwd(from); +} + +template +Maybe dynamicDowncastIfAvailable(From& from) { + // If RTTI is disabled, always returns nullptr. Otherwise, works like dynamic_cast. Useful + // in situations where dynamic_cast could allow an optimization, but isn't strictly necessary + // for correctness. It is highly recommended that you try to arrange all your dynamic_casts + // this way, as a dynamic_cast that is necessary for correctness implies a flaw in the interface + // design. + + // Force a compile error if To is not a subtype of From. Cross-casting is rare; if it is needed + // we should have a separate cast function like dynamicCrosscastIfAvailable(). + if (false) { + kj::implicitCast(kj::implicitCast(nullptr)); + } + +#if KJ_NO_RTTI + return nullptr; +#else + return dynamic_cast(&from); +#endif +} + +template +To& downcast(From& from) { + // Down-cast a value to a sub-type, asserting that the cast is valid. In opt mode this is a + // static_cast, but in debug mode (when RTTI is enabled) a dynamic_cast will be used to verify + // that the value really has the requested type. + + // Force a compile error if To is not a subtype of From. + if (false) { + kj::implicitCast(kj::implicitCast(nullptr)); + } + +#if !KJ_NO_RTTI + KJ_IREQUIRE(dynamic_cast(&from) != nullptr, "Value cannot be downcast() to requested type."); +#endif + + return static_cast(from); +} + +// ======================================================================================= +// Defer + +namespace _ { // private + +template +class Deferred { +public: + Deferred(Func&& func): maybeFunc(kj::fwd(func)) {} + ~Deferred() noexcept(false) { + run(); + } + KJ_DISALLOW_COPY(Deferred); + + Deferred(Deferred&&) = default; + // Since we use a kj::Maybe, the default move constructor does exactly what we want it to do. + + void run() { + // Move `maybeFunc` to the local scope so that even if we throw, we destroy the functor we had. + auto maybeLocalFunc = kj::mv(maybeFunc); + KJ_IF_MAYBE(func, maybeLocalFunc) { + (*func)(); + } + } + + void cancel() { + maybeFunc = nullptr; + } + +private: + kj::Maybe maybeFunc; + // Note that `Func` may actually be an lvalue reference because `kj::defer` takes its argument via + // universal reference. `kj::Maybe` has specializations for lvalue reference types, so this works + // out. +}; + +} // namespace _ (private) + +template +_::Deferred defer(Func&& func) { + // Returns an object which will invoke the given functor in its destructor. The object is not + // copyable but is move-constructable with the semantics you'd expect. Since the return type is + // private, you need to assign to an `auto` variable. + // + // The KJ_DEFER macro provides slightly more convenient syntax for the common case where you + // want some code to run at current scope exit. + // + // KJ_DEFER does not support move-assignment for its returned objects. If you need to reuse the + // variable for your deferred function object, then you will want to write your own class for that + // purpose. + + return _::Deferred(kj::fwd(func)); +} + +#define KJ_DEFER(code) auto KJ_UNIQUE_NAME(_kjDefer) = ::kj::defer([&](){code;}) +// Run the given code when the function exits, whether by return or exception. + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/debug.c++ b/vendor/capnproto/src/kj/debug.c++ new file mode 100644 index 0000000..490e4a6 --- /dev/null +++ b/vendor/capnproto/src/kj/debug.c++ @@ -0,0 +1,397 @@ +// 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 "debug.h" +#include +#include +#include +#include + + +namespace kj { +namespace _ { // private + +LogSeverity Debug::minSeverity = LogSeverity::WARNING; + +namespace { + +Exception::Type typeOfErrno(int error) { + switch (error) { +#ifdef EDQUOT + case EDQUOT: +#endif +#ifdef EMFILE + case EMFILE: +#endif +#ifdef ENFILE + case ENFILE: +#endif +#ifdef ENOBUFS + case ENOBUFS: +#endif +#ifdef ENOLCK + case ENOLCK: +#endif +#ifdef ENOMEM + case ENOMEM: +#endif +#ifdef ENOSPC + case ENOSPC: +#endif +#ifdef ETIMEDOUT + case ETIMEDOUT: +#endif +#ifdef EUSERS + case EUSERS: +#endif + return Exception::Type::OVERLOADED; + +#ifdef ENOTCONN + case ENOTCONN: +#endif +#ifdef ECONNABORTED + case ECONNABORTED: +#endif +#ifdef ECONNREFUSED + case ECONNREFUSED: +#endif +#ifdef ECONNRESET + case ECONNRESET: +#endif +#ifdef EHOSTDOWN + case EHOSTDOWN: +#endif +#ifdef EHOSTUNREACH + case EHOSTUNREACH: +#endif +#ifdef ENETDOWN + case ENETDOWN: +#endif +#ifdef ENETRESET + case ENETRESET: +#endif +#ifdef ENETUNREACH + case ENETUNREACH: +#endif +#ifdef ENONET + case ENONET: +#endif +#ifdef EPIPE + case EPIPE: +#endif + return Exception::Type::DISCONNECTED; + +#ifdef ENOSYS + case ENOSYS: +#endif +#ifdef ENOTSUP + case ENOTSUP: +#endif +#if defined(EOPNOTSUPP) && EOPNOTSUPP != ENOTSUP + case EOPNOTSUPP: +#endif +#ifdef ENOPROTOOPT + case ENOPROTOOPT: +#endif +#ifdef ENOTSOCK + // This is really saying "syscall not implemented for non-sockets". + case ENOTSOCK: +#endif + return Exception::Type::UNIMPLEMENTED; + + default: + return Exception::Type::FAILED; + } +} + + +enum DescriptionStyle { + LOG, + ASSERTION, + SYSCALL +}; + +static String makeDescriptionImpl(DescriptionStyle style, const char* code, int errorNumber, + const char* sysErrorString, const char* macroArgs, + ArrayPtr argValues) { + KJ_STACK_ARRAY(ArrayPtr, argNames, argValues.size(), 8, 64); + + if (argValues.size() > 0) { + size_t index = 0; + const char* start = macroArgs; + while (isspace(*start)) ++start; + const char* pos = start; + uint depth = 0; + bool quoted = false; + while (char c = *pos++) { + if (quoted) { + if (c == '\\' && *pos != '\0') { + ++pos; + } else if (c == '\"') { + quoted = false; + } + } else { + if (c == '(') { + ++depth; + } else if (c == ')') { + --depth; + } else if (c == '\"') { + quoted = true; + } else if (c == ',' && depth == 0) { + if (index < argValues.size()) { + argNames[index++] = arrayPtr(start, pos - 1); + } + while (isspace(*pos)) ++pos; + start = pos; + if (*pos == '\0') { + // ignore trailing comma + break; + } + } + } + } + if (index < argValues.size()) { + argNames[index++] = arrayPtr(start, pos - 1); + } + + if (index != argValues.size()) { + getExceptionCallback().logMessage(LogSeverity::ERROR, __FILE__, __LINE__, 0, + str("Failed to parse logging macro args into ", + argValues.size(), " names: ", macroArgs, '\n')); + } + } + + if (style == SYSCALL) { + // Strip off leading "foo = " from code, since callers will sometimes write things like: + // ssize_t n; + // RECOVERABLE_SYSCALL(n = read(fd, buffer, sizeof(buffer))) { return ""; } + // return std::string(buffer, n); + const char* equalsPos = strchr(code, '='); + if (equalsPos != nullptr && equalsPos[1] != '=') { + code = equalsPos + 1; + while (isspace(*code)) ++code; + } + } + + if (style == ASSERTION && code == nullptr) { + style = LOG; + } + + { + StringPtr expected = "expected "; + StringPtr codeArray = style == LOG ? nullptr : StringPtr(code); + StringPtr sep = " = "; + StringPtr delim = "; "; + StringPtr colon = ": "; + StringPtr openBracket = " ["; + StringPtr closeBracket = "]"; + + StringPtr sysErrorArray; +// On android before marshmallow only the posix version of stderror_r was +// available, even with __USE_GNU. +#if __USE_GNU && !(defined(__ANDROID_API__) && __ANDROID_API__ < 23) + char buffer[256]; + if (style == SYSCALL) { + if (sysErrorString == nullptr) { + sysErrorArray = strerror_r(errorNumber, buffer, sizeof(buffer)); + } else { + sysErrorArray = sysErrorString; + } + } +#else + char buffer[256]; + if (style == SYSCALL) { + if (sysErrorString == nullptr) { + strerror_r(errorNumber, buffer, sizeof(buffer)); + sysErrorArray = buffer; + } else { + sysErrorArray = sysErrorString; + } + } +#endif + + size_t totalSize = 0; + switch (style) { + case LOG: + break; + case ASSERTION: + totalSize += expected.size() + codeArray.size(); + break; + case SYSCALL: + totalSize += codeArray.size() + colon.size() + sysErrorArray.size(); + break; + } + + auto needsLabel = [](ArrayPtr &argName) -> bool { + return (argName.size() > 0 && argName[0] != '\"' && + !(argName.size() >= 8 && memcmp(argName.begin(), "kj::str(", 8) == 0)); + }; + + for (size_t i = 0; i < argValues.size(); i++) { + if (argNames[i] == "_kjCondition"_kj) { + // Special handling: don't output delimiter, we want to append this to the previous item, + // in brackets. Also, if it's just "[false]" (meaning we didn't manage to extract a + // comparison), don't add it at all. + if (argValues[i] != "false") { + totalSize += openBracket.size() + argValues[i].size() + closeBracket.size(); + } + continue; + } + + if (i > 0 || style != LOG) { + totalSize += delim.size(); + } + if (needsLabel(argNames[i])) { + totalSize += argNames[i].size() + sep.size(); + } + totalSize += argValues[i].size(); + } + + String result = heapString(totalSize); + char* pos = result.begin(); + + switch (style) { + case LOG: + break; + case ASSERTION: + pos = _::fill(pos, expected, codeArray); + break; + case SYSCALL: + pos = _::fill(pos, codeArray, colon, sysErrorArray); + break; + } + + for (size_t i = 0; i < argValues.size(); i++) { + if (argNames[i] == "_kjCondition"_kj) { + // Special handling: don't output delimiter, we want to append this to the previous item, + // in brackets. Also, if it's just "[false]" (meaning we didn't manage to extract a + // comparison), don't add it at all. + if (argValues[i] != "false") { + pos = _::fill(pos, openBracket, argValues[i], closeBracket); + } + continue; + } + + if (i > 0 || style != LOG) { + pos = _::fill(pos, delim); + } + if (needsLabel(argNames[i])) { + pos = _::fill(pos, argNames[i], sep); + } + pos = _::fill(pos, argValues[i]); + } + + return result; + } +} + +} // namespace + +void Debug::logInternal(const char* file, int line, LogSeverity severity, const char* macroArgs, + ArrayPtr argValues) { + getExceptionCallback().logMessage(severity, trimSourceFilename(file).cStr(), line, 0, + makeDescriptionImpl(LOG, nullptr, 0, nullptr, macroArgs, argValues)); +} + +Debug::Fault::~Fault() noexcept(false) { + if (exception != nullptr) { + Exception copy = mv(*exception); + delete exception; + throwRecoverableException(mv(copy), 1); + } +} + +void Debug::Fault::fatal() { + Exception copy = mv(*exception); + delete exception; + exception = nullptr; + throwFatalException(mv(copy), 1); + KJ_KNOWN_UNREACHABLE(abort()); +} + +void Debug::Fault::init( + const char* file, int line, Exception::Type type, + const char* condition, const char* macroArgs, ArrayPtr argValues) { + exception = new Exception(type, file, line, + makeDescriptionImpl(ASSERTION, condition, 0, nullptr, macroArgs, argValues)); +} + +void Debug::Fault::init( + const char* file, int line, int osErrorNumber, + const char* condition, const char* macroArgs, ArrayPtr argValues) { + exception = new Exception(typeOfErrno(osErrorNumber), file, line, + makeDescriptionImpl(SYSCALL, condition, osErrorNumber, nullptr, macroArgs, argValues)); +} + + +String Debug::makeDescriptionInternal(const char* macroArgs, ArrayPtr argValues) { + return makeDescriptionImpl(LOG, nullptr, 0, nullptr, macroArgs, argValues); +} + +int Debug::getOsErrorNumber(bool nonblocking) { + int result = errno; + + // On many systems, EAGAIN and EWOULDBLOCK have the same value, but this is not strictly required + // by POSIX, so we need to check both. + return result == EINTR ? -1 + : nonblocking && (result == EAGAIN || result == EWOULDBLOCK) ? 0 + : result; +} + + +Debug::Context::Context(): logged(false) {} +Debug::Context::~Context() noexcept(false) {} + +Debug::Context::Value Debug::Context::ensureInitialized() { + KJ_IF_MAYBE(v, value) { + return Value(v->file, v->line, heapString(v->description)); + } else { + Value result = evaluate(); + value = Value(result.file, result.line, heapString(result.description)); + return result; + } +} + +void Debug::Context::onRecoverableException(Exception&& exception) { + Value v = ensureInitialized(); + exception.wrapContext(v.file, v.line, mv(v.description)); + next.onRecoverableException(kj::mv(exception)); +} +void Debug::Context::onFatalException(Exception&& exception) { + Value v = ensureInitialized(); + exception.wrapContext(v.file, v.line, mv(v.description)); + next.onFatalException(kj::mv(exception)); +} +void Debug::Context::logMessage(LogSeverity severity, const char* file, int line, int contextDepth, + String&& text) { + if (!logged) { + Value v = ensureInitialized(); + next.logMessage(LogSeverity::INFO, trimSourceFilename(v.file).cStr(), v.line, 0, + str("context: ", mv(v.description), '\n')); + logged = true; + } + + next.logMessage(severity, file, line, contextDepth + 1, mv(text)); +} + +} // namespace _ (private) +} // namespace kj diff --git a/vendor/capnproto/src/kj/debug.h b/vendor/capnproto/src/kj/debug.h new file mode 100644 index 0000000..79edd78 --- /dev/null +++ b/vendor/capnproto/src/kj/debug.h @@ -0,0 +1,542 @@ +// 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_ASSUME(condition, ...)`: Like `KJ_ASSERT`, but in release mode (if KJ_DEBUG is not +// defined; see below) instead warrants to the compiler that the condition can be assumed to +// hold, allowing it to optimize accordingly. This can result in undefined behavior, so use +// this macro *only* if you can prove to your satisfaction that the condition is guaranteed by +// surrounding code, and if the condition failing to hold would in any case result in undefined +// behavior in its dependencies. +// +// * `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 except `ASSUME`, 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. + +#pragma once + +#include "string.h" +#include "exception.h" + +KJ_BEGIN_HEADER + +namespace kj { + + +#define KJ_LOG(severity, ...) \ + for (bool _kj_shouldLog = ::kj::_::Debug::shouldLog(::kj::LogSeverity::severity); \ + _kj_shouldLog; _kj_shouldLog = false) \ + ::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 (auto _kjCondition = ::kj::_::MAGIC_ASSERT << cond) {} else \ + for (::kj::_::Debug::Fault f(__FILE__, __LINE__, ::kj::Exception::Type::FAILED, \ + #cond, "_kjCondition," #__VA_ARGS__, _kjCondition, ##__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()) + + +#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 \ + 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__)) + + +#define KJ_SYSCALL_HANDLE_ERRORS(call) \ + if (int _kjSyscallError = ::kj::_::Debug::syscallError([&](){return (call);}, false)) \ + switch (int error KJ_UNUSED = _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 +#define KJ_ASSUME KJ_ASSERT +#else +#define KJ_DLOG(...) do {} while (false) +#define KJ_DASSERT(...) do {} while (false) +#define KJ_DREQUIRE(...) do {} while (false) +#if defined(__GNUC__) +#define KJ_ASSUME(cond, ...) do { if (cond) {} else __builtin_unreachable(); } while (false) +#elif defined(__clang__) +#define KJ_ASSUME(cond, ...) __builtin_assume(cond) +#else +#define KJ_ASSUME(...) do {} while (false) +#endif + +#endif + +namespace _ { // private + +class Debug { +public: + Debug() = delete; + + typedef LogSeverity Severity; // backwards-compatibility + + + 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 + static void log(const char* file, int line, LogSeverity severity, const char* macroArgs, + Params&&... params); + + class Fault { + public: + template + 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); + ~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 argValues); + void init(const char* file, int line, int osErrorNumber, + const char* condition, const char* macroArgs, ArrayPtr argValues); + + 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 + static SyscallResult syscall(Call&& call, bool nonblocking); + template + static int syscallError(Call&& call, bool nonblocking); + + + class Context: public ExceptionCallback { + public: + Context(); + KJ_DISALLOW_COPY_AND_MOVE(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 ensureInitialized(); + }; + + template + class ContextImpl: public Context { + public: + inline ContextImpl(Func& func): func(func) {} + KJ_DISALLOW_COPY_AND_MOVE(ContextImpl); + + Value evaluate() override { + return func(); + } + private: + Func& func; + }; + + template + 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 argValues); + static String makeDescriptionInternal(const char* macroArgs, ArrayPtr argValues); + + static int getOsErrorNumber(bool nonblocking); + // Get the error code of the last error (e.g. from errno). Returns -1 on EINTR. +}; + +template +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 +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); +} + + +template +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 +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 +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); +} + +// ======================================================================================= +// Magic Asserts! +// +// When KJ_ASSERT(foo == bar) fails, `foo` and `bar`'s actual values will be stringified in the +// error message. How does it work? We use template magic and operator precedence. The assertion +// actually evaluates something like this: +// +// if (auto _kjCondition = kj::_::MAGIC_ASSERT << foo == bar) +// +// `<<` has operator precedence slightly above `==`, so `kj::_::MAGIC_ASSERT << foo` gets evaluated +// first. This wraps `foo` in a little wrapper that captures the comparison operators and keeps +// enough information around to be able to stringify the left and right sides of the comparison +// independently. As always, the stringification only actually occurs if the assert fails. +// +// You might ask why we use operator `<<` and not e.g. operator `<=`, since operators of the same +// precedence are evaluated left-to-right. The answer is that some compilers trigger all sorts of +// warnings when you seem to be using a comparison as the input to another comparison. The +// particular warning GCC produces is its general "-Wparentheses" warning which is broadly useful, +// so we don't want to disable it. `<<` also produces some warnings, but only on Clang and the +// specific warning is one we're comfortable disabling (see below). This does mean that we have to +// explicitly overload `operator<<` ourselves to make sure using it in an assert still works. +// +// You might also ask, if we're using operator `<<` anyway, why not start it from the right, in +// which case it would bind after computing any `<<` operators that were actually in the user's +// code? I tried this, but it resulted in a somewhat broader warning from clang that I felt worse +// about disabling (a warning about `<<` precedence not applying specifically to overloads) and +// also created ambiguous overload errors in the KJ units code. + +#if __clang__ +// We intentionally overload operator << for the specific purpose of evaluating it before +// evaluating comparison expressions, so stop Clang from warning about it. Unfortunately this means +// eliminating a warning that would otherwise be useful for people using iostreams... sorry. +#pragma GCC diagnostic ignored "-Woverloaded-shift-op-parentheses" +#endif + +template +struct DebugExpression; + +template ()))> +inline auto tryToCharSequence(T* value) { return kj::toCharSequence(*value); } +inline StringPtr tryToCharSequence(...) { return "(can't stringify)"_kj; } +// SFINAE to stringify a value if and only if it can be stringified. + +template +struct DebugComparison { + Left left; + Right right; + StringPtr op; + bool result; + + inline operator bool() const { return KJ_LIKELY(result); } + + template inline void operator&(T&& other) = delete; + template inline void operator^(T&& other) = delete; + template inline void operator|(T&& other) = delete; +}; + +template +String KJ_STRINGIFY(DebugComparison& cmp) { + return _::concat(tryToCharSequence(&cmp.left), cmp.op, tryToCharSequence(&cmp.right)); +} + +template +struct DebugExpression { + DebugExpression(T&& value): value(kj::fwd(value)) {} + T value; + + // Handle comparison operations by constructing a DebugComparison value. +#define DEFINE_OPERATOR(OP) \ + template \ + DebugComparison operator OP(U&& other) { \ + bool result = value OP other; \ + return { kj::fwd(value), kj::fwd(other), " " #OP " "_kj, result }; \ + } + DEFINE_OPERATOR(==); + DEFINE_OPERATOR(!=); + DEFINE_OPERATOR(<=); + DEFINE_OPERATOR(>=); + DEFINE_OPERATOR(< ); + DEFINE_OPERATOR(> ); +#undef DEFINE_OPERATOR + + // Handle binary operators that have equal or lower precedence than comparisons by performing + // the operation and wrapping the result. +#define DEFINE_OPERATOR(OP) \ + template inline auto operator OP(U&& other) { \ + return DebugExpression(value) OP kj::fwd(other))>(\ + kj::fwd(value) OP kj::fwd(other)); \ + } + DEFINE_OPERATOR(<<); + DEFINE_OPERATOR(>>); + DEFINE_OPERATOR(&); + DEFINE_OPERATOR(^); + DEFINE_OPERATOR(|); +#undef DEFINE_OPERATOR + + inline operator bool() { + // No comparison performed, we're just asserting the expression is truthy. This also covers + // the case of the logic operators && and || -- we cannot overload those because doing so would + // break short-circuiting behavior. + return value; + } +}; + +template +StringPtr KJ_STRINGIFY(const DebugExpression& exp) { + // Hack: This will only ever be called in cases where the expression's truthiness was asserted + // directly, and was determined to be falsy. + return "false"_kj; +} + +struct DebugExpressionStart { + template + DebugExpression operator<<(T&& value) const { + return DebugExpression(kj::fwd(value)); + } +}; +static constexpr DebugExpressionStart MAGIC_ASSERT; + +} // namespace _ (private) +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/encoding.c++ b/vendor/capnproto/src/kj/encoding.c++ new file mode 100644 index 0000000..11ca3d7 --- /dev/null +++ b/vendor/capnproto/src/kj/encoding.c++ @@ -0,0 +1,72 @@ +// Copyright (c) 2017 Cloudflare, Inc.; 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 "encoding.h" +#include "vector.h" + +namespace kj { + +namespace { + +const char HEX_DIGITS[] = "0123456789abcdef"; +// Maps integer in the range [0,16) to a hex digit. + +} // namespace + +namespace _ { // private + +String encodeCEscapeImpl(ArrayPtr bytes, bool isBinary) { + Vector escaped(bytes.size()); + + for (byte b: bytes) { + switch (b) { + case '\a': escaped.addAll(StringPtr("\\a")); break; + case '\b': escaped.addAll(StringPtr("\\b")); break; + case '\f': escaped.addAll(StringPtr("\\f")); break; + case '\n': escaped.addAll(StringPtr("\\n")); break; + case '\r': escaped.addAll(StringPtr("\\r")); break; + case '\t': escaped.addAll(StringPtr("\\t")); break; + case '\v': escaped.addAll(StringPtr("\\v")); break; + case '\'': escaped.addAll(StringPtr("\\\'")); break; + case '\"': escaped.addAll(StringPtr("\\\"")); break; + case '\\': escaped.addAll(StringPtr("\\\\")); break; + default: + if (b < 0x20 || b == 0x7f || (isBinary && b > 0x7f)) { + // Use octal escape, not hex, because hex escapes technically have no length limit and + // so can create ambiguity with subsequent characters. + escaped.add('\\'); + escaped.add(HEX_DIGITS[b / 64]); + escaped.add(HEX_DIGITS[(b / 8) % 8]); + escaped.add(HEX_DIGITS[b % 8]); + } else { + escaped.add(b); + } + break; + } + } + + escaped.add(0); + return String(escaped.releaseAsArray()); +} + +} // namespace + +} // namespace kj diff --git a/vendor/capnproto/src/kj/encoding.h b/vendor/capnproto/src/kj/encoding.h new file mode 100644 index 0000000..37a1659 --- /dev/null +++ b/vendor/capnproto/src/kj/encoding.h @@ -0,0 +1,69 @@ +// Copyright (c) 2017 Cloudflare, 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. + +#pragma once +// C-style string escaping. + +#include "string.h" + +KJ_BEGIN_HEADER + +namespace kj { + +String encodeCEscape(ArrayPtr bytes); +String encodeCEscape(ArrayPtr bytes); + +// ======================================================================================= +// inline implementation details + +namespace _ { // private + +String encodeCEscapeImpl(ArrayPtr bytes, bool isBinary); + +} // namespace _ (private) + +inline String encodeCEscape(ArrayPtr text) { + return _::encodeCEscapeImpl(text.asBytes(), false); +} + +inline String encodeCEscape(ArrayPtr bytes) { + return _::encodeCEscapeImpl(bytes, true); +} + + +// If you pass a string literal to a function taking ArrayPtr, it'll include the NUL +// terminator. These overloads avoid including it. + +template +inline String encodeCEscape(const char (&text)[s]) { + return encodeCEscape(arrayPtr(text, s - 1)); +} + +#if __cpp_char8_t +template +inline String encodeCEscape(const char8_t (&text)[s]) { + return encodeCEscape(arrayPtr(reinterpret_cast(text), s - 1)); +} +#endif + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/exception.c++ b/vendor/capnproto/src/kj/exception.c++ new file mode 100644 index 0000000..0fdd3af --- /dev/null +++ b/vendor/capnproto/src/kj/exception.c++ @@ -0,0 +1,822 @@ +// 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 _GNU_SOURCE +#define _GNU_SOURCE +#endif + + + +#include "exception.h" +#include "string.h" +#include "debug.h" +#include "threadlocal.h" +#include "miniposix.h" +#include +#include +#include +#include + +#if !KJ_NO_RTTI +#include +#endif +#if __GNUC__ +#include +#endif + +#ifndef KJ_USE_BACKTRACE +#if (__linux__ && __GLIBC__ && !__UCLIBC__) || __APPLE__ +#define KJ_USE_BACKTRACE 1 +#endif +#endif + +#if KJ_USE_BACKTRACE +#include +#endif + + +#if (__linux__ || __APPLE__) +#include +#include +#endif + + +#if KJ_HAS_LIBDL +#include "dlfcn.h" +#endif + + +#if KJ_HAS_COMPILER_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) +#include +#else +static void __lsan_ignore_object(const void* p) {} +#endif +// TODO(cleanup): Remove the LSAN stuff per https://github.com/capnproto/capnproto/pull/1255 +// feedback. + +namespace { +template +inline T* lsanIgnoreObjectAndReturn(T* ptr) { + // Defensively lsan_ignore_object since the documentation doesn't explicitly specify what happens + // if you call this multiple times on the same object. + // TODO(cleanup): Remove this per https://github.com/capnproto/capnproto/pull/1255. + __lsan_ignore_object(ptr); + return ptr; +} +} + +namespace kj { + +StringPtr KJ_STRINGIFY(LogSeverity severity) { + static const char* SEVERITY_STRINGS[] = { + "info", + "warning", + "error", + "fatal", + "debug" + }; + + return SEVERITY_STRINGS[static_cast(severity)]; +} + + +ArrayPtr getStackTrace(ArrayPtr space, uint ignoreCount) { + if (getExceptionCallback().stackTraceMode() == ExceptionCallback::StackTraceMode::NONE) { + return nullptr; + } + +#if KJ_USE_BACKTRACE + size_t size = backtrace(space.begin(), space.size()); + for (auto& addr: space.slice(0, size)) { + // The addresses produced by backtrace() are return addresses, which means they point to the + // instruction immediately after the call. Invoking addr2line on these can be confusing because + // it often points to the next line. If the next instruction is inlined from another function, + // the trace can be extra-confusing, since now it claims to be in a function that was not + // actually on the call stack. If we subtract 1 from each address, though, we get a much more + // reasonable trace. This may cause the addresses to be invalid instruction pointers if the + // instructions were multi-byte, but it appears addr2line is able to cope with this. + addr = reinterpret_cast(reinterpret_cast(addr) - 1); + } + return space.slice(kj::min(ignoreCount + 1, size), size); +#else + return nullptr; +#endif +} + +#if __GNUC__ || __clang__ +// Allow dependents to override the implementation of stack symbolication by making it a weak +// symbol. We prefer weak symbols over some sort of callback registration mechanism becasue this +// allows an alternate symbolication library to be easily linked into tests without changing the +// code of the test. +__attribute__((weak)) +#endif +String stringifyStackTrace(ArrayPtr trace) { + if (trace.size() == 0) return nullptr; + if (getExceptionCallback().stackTraceMode() != ExceptionCallback::StackTraceMode::FULL) { + return nullptr; + } + +#if (__linux__ || __APPLE__) && !__ANDROID__ + // We want to generate a human-readable stack trace. + + // TODO(someday): It would be really great if we could avoid farming out to another process + // and do this all in-process, but that may involve onerous requirements like large library + // dependencies or using -rdynamic. + + // The environment manipulation is not thread-safe, so lock a mutex. This could still be + // problematic if another thread is manipulating the environment in unrelated code, but there's + // not much we can do about that. This is debug-only anyway and only an issue when LD_PRELOAD + // is in use. + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&mutex); + KJ_DEFER(pthread_mutex_unlock(&mutex)); + + // Don't heapcheck / intercept syscalls. + const char* preload = getenv("LD_PRELOAD"); + String oldPreload; + if (preload != nullptr) { + oldPreload = heapString(preload); + unsetenv("LD_PRELOAD"); + } + KJ_DEFER(if (oldPreload != nullptr) { setenv("LD_PRELOAD", oldPreload.cStr(), true); }); + + String lines[32]; + FILE* p = nullptr; + auto strTrace = strArray(trace, " "); + +#if __linux__ + if (access("/proc/self/exe", R_OK) < 0) { + // Apparently /proc is not available? + return nullptr; + } + + // Obtain symbolic stack trace using addr2line. + // TODO(cleanup): Use fork() and exec() or maybe our own Subprocess API (once it exists), to + // avoid depending on a shell. + p = popen(str("addr2line -e /proc/", getpid(), "/exe ", strTrace).cStr(), "r"); +#elif __APPLE__ + // The Mac OS X equivalent of addr2line is atos. + // (Internally, it uses the private CoreSymbolication.framework library.) + p = popen(str("xcrun atos -p ", getpid(), ' ', strTrace).cStr(), "r"); +#endif + + if (p == nullptr) { + return nullptr; + } + + char line[512]; + size_t i = 0; + while (i < kj::size(lines) && fgets(line, sizeof(line), p) != nullptr) { + // Don't include exception-handling infrastructure or promise infrastructure in stack trace. + // addr2line output matches file names; atos output matches symbol names. + if (strstr(line, "kj/common.c++") != nullptr || + strstr(line, "kj/exception.") != nullptr || + strstr(line, "kj/debug.") != nullptr || + strstr(line, "kj/async.") != nullptr || + strstr(line, "kj/async-prelude.h") != nullptr || + strstr(line, "kj/async-inl.h") != nullptr || + strstr(line, "kj::Exception") != nullptr || + strstr(line, "kj::_::Debug") != nullptr) { + continue; + } + + size_t len = strlen(line); + if (len > 0 && line[len-1] == '\n') line[len-1] = '\0'; + lines[i++] = str("\n ", trimSourceFilename(line), ": returning here"); + } + + // Skip remaining input. + while (fgets(line, sizeof(line), p) != nullptr) {} + + pclose(p); + + return strArray(arrayPtr(lines, i), ""); + +#else + return nullptr; +#endif +} + +String stringifyStackTraceAddresses(ArrayPtr trace) { +#if KJ_HAS_LIBDL + return strArray(KJ_MAP(addr, trace) { + Dl_info info; + // Shared libraries are mapped near the end of the address space while the executable is mapped + // near the beginning. We want to print addresses in the executable as raw addresses, not + // offsets, since that's what addr2line expects for executables. For shared libraries it + // expects offsets. In any case, most frames are likely to be in the main executable so it + // makes the output cleaner if we don't repeatedly write its name. + if (reinterpret_cast(addr) >= 0x400000000000ull && dladdr(addr, &info)) { + uintptr_t offset = reinterpret_cast(addr) - + reinterpret_cast(info.dli_fbase); + return kj::str(info.dli_fname, '@', reinterpret_cast(offset)); + } else { + return kj::str(addr); + } + }, " "); +#else + // TODO(someday): Support other platforms. + return kj::strArray(trace, " "); +#endif +} + +StringPtr stringifyStackTraceAddresses(ArrayPtr trace, ArrayPtr scratch) { + // Version which writes into a pre-allocated buffer. This is safe for signal handlers to the + // extent that dladdr() is safe. + // + // TODO(cleanup): We should improve the KJ stringification framework so that there's a way to + // write this string directly into a larger message buffer with strPreallocated(). + +#if KJ_HAS_LIBDL + char* ptr = scratch.begin(); + char* limit = scratch.end() - 1; + + for (auto addr: trace) { + Dl_info info; + // Shared libraries are mapped near the end of the address space while the executable is mapped + // near the beginning. We want to print addresses in the executable as raw addresses, not + // offsets, since that's what addr2line expects for executables. For shared libraries it + // expects offsets. In any case, most frames are likely to be in the main executable so it + // makes the output cleaner if we don't repeatedly write its name. + if (reinterpret_cast(addr) >= 0x400000000000ull && dladdr(addr, &info)) { + uintptr_t offset = reinterpret_cast(addr) - + reinterpret_cast(info.dli_fbase); + ptr = _::fillLimited(ptr, limit, kj::StringPtr(info.dli_fname), "@0x"_kj, hex(offset)); + } else { + ptr = _::fillLimited(ptr, limit, toCharSequence(addr)); + } + + ptr = _::fillLimited(ptr, limit, " "_kj); + } + *ptr = '\0'; + return StringPtr(scratch.begin(), ptr); +#else + // TODO(someday): Support other platforms. + return kj::strPreallocated(scratch, kj::delimited(trace, " ")); +#endif +} + +String getStackTrace() { + void* space[32]; + auto trace = getStackTrace(space, 2); + return kj::str(stringifyStackTraceAddresses(trace), stringifyStackTrace(trace)); +} + +kj::StringPtr trimSourceFilename(kj::StringPtr filename) { + // Removes noisy prefixes from source code file name. + // + // The goal here is to produce the "canonical" filename given the filename returned by e.g. + // addr2line. addr2line gives us the full path of the file as passed on the compiler + // command-line, which in turn is affected by build system and by whether and where we're + // performing an out-of-tree build. + // + // To deal with all this, we look for directory names in the path which we recognize to be + // locations that represent roots of the source tree. We strip said root and everything before + // it. + // + // On Windows, we often get filenames containing backslashes. Since we aren't allowed to allocate + // a new string here, we can't do much about this, so our returned "canonical" name will + // unfortunately end up with backslashes. + + static constexpr const char* ROOTS[] = { + "ekam-provider/canonical/", // Ekam source file. + "ekam-provider/c++header/", // Ekam include file. + "src/", // Non-Ekam source root. + "tmp/", // Non-Ekam generated code. + }; + +retry: + for (size_t i: kj::indices(filename)) { + if (i == 0 || filename[i-1] == '/' + ) { + // We're at the start of a directory name. Check for valid prefixes. + for (kj::StringPtr root: ROOTS) { + if (filename.slice(i).startsWith(root)) { + filename = filename.slice(i + root.size()); + + // We should keep searching to find the last instance of a root name. `i` is no longer + // a valid index for `filename` so start the loop over. + goto retry; + } + } + } + } + + return filename; +} + +StringPtr KJ_STRINGIFY(Exception::Type type) { + static const char* TYPE_STRINGS[] = { + "failed", + "overloaded", + "disconnected", + "unimplemented" + }; + + return TYPE_STRINGS[static_cast(type)]; +} + +String KJ_STRINGIFY(const Exception& e) { + uint contextDepth = 0; + + Maybe contextPtr = e.getContext(); + for (;;) { + KJ_IF_MAYBE(c, contextPtr) { + ++contextDepth; + contextPtr = c->next; + } else { + break; + } + } + + Array contextText = heapArray(contextDepth); + + contextDepth = 0; + contextPtr = e.getContext(); + for (;;) { + KJ_IF_MAYBE(c, contextPtr) { + contextText[contextDepth++] = + str(trimSourceFilename(c->file), ":", c->line, ": context: ", c->description, "\n"); + contextPtr = c->next; + } else { + break; + } + } + + return str(strArray(contextText, ""), + e.getFile(), ":", e.getLine(), ": ", e.getType(), + e.getDescription() == nullptr ? "" : ": ", e.getDescription(), + e.getStackTrace().size() > 0 ? "\nstack: " : "", + stringifyStackTraceAddresses(e.getStackTrace()), + stringifyStackTrace(e.getStackTrace())); +} + +Exception::Exception(Type type, const char* file, int line, String description) noexcept + : file(trimSourceFilename(file).cStr()), line(line), type(type), description(mv(description)), + traceCount(0) {} + +Exception::Exception(Type type, String file, int line, String description) noexcept + : ownFile(kj::mv(file)), file(trimSourceFilename(ownFile).cStr()), line(line), type(type), + description(mv(description)), traceCount(0) {} + +Exception::Exception(const Exception& other) noexcept + : file(other.file), line(other.line), type(other.type), + description(heapString(other.description)), traceCount(other.traceCount) { + if (file == other.ownFile.cStr()) { + ownFile = heapString(other.ownFile); + file = ownFile.cStr(); + } + + + memcpy(trace, other.trace, sizeof(trace[0]) * traceCount); + + KJ_IF_MAYBE(c, other.context) { + context = heap(**c); + } +} + +Exception::~Exception() noexcept {} + +Exception::Context::Context(const Context& other) noexcept + : file(other.file), line(other.line), description(str(other.description)) { + KJ_IF_MAYBE(n, other.next) { + next = heap(**n); + } +} + +void Exception::wrapContext(const char* file, int line, String&& description) { + context = heap(file, line, mv(description), mv(context)); +} + +void Exception::extendTrace(uint ignoreCount, uint limit) { + if (isFullTrace) { + // Awkward: extendTrace() was called twice without truncating in between. This should probably + // be an error, but historically we didn't check for this so I'm hesitant to make it an error + // now. We shouldn't actually extend the trace, though, as our current trace is presumably + // rooted in main() and it'd be weird to append frames "above" that. + // TODO(cleanup): Abort here and see what breaks? + return; + } + + KJ_STACK_ARRAY(void*, newTraceSpace, kj::min(kj::size(trace), limit) + ignoreCount + 1, + sizeof(trace)/sizeof(trace[0]) + 8, 128); + + auto newTrace = kj::getStackTrace(newTraceSpace, ignoreCount + 1); + if (newTrace.size() > ignoreCount + 2) { + // Remove suffix that won't fit into our static-sized trace. + newTrace = newTrace.slice(0, kj::min(kj::size(trace) - traceCount, newTrace.size())); + + // Copy the rest into our trace. + memcpy(trace + traceCount, newTrace.begin(), newTrace.asBytes().size()); + traceCount += newTrace.size(); + isFullTrace = true; + } +} + +void Exception::truncateCommonTrace() { + if (isFullTrace) { + // We're truncating the common portion of the full trace, turning it back into a limited + // trace. + isFullTrace = false; + } else { + // If the trace was never extended in the first place, trying to truncate it is at best a waste + // of time and at worst might remove information for no reason. So, don't. + // + // This comes up in particular in coroutines, when the exception originated from a co_awaited + // promise. In that case we manually add the one relevant frame to the trace, rather than + // call extendTrace() just to have to truncate most of it again a moment later in the + // unhandled_exception() callback. + return; + } + + if (traceCount > 0) { + // Create a "reference" stack trace that is a little bit deeper than the one in the exception. + void* refTraceSpace[sizeof(this->trace) / sizeof(this->trace[0]) + 4]; + auto refTrace = kj::getStackTrace(refTraceSpace, 0); + + // We expect that the deepest frame in the exception's stack trace should be somewhere in our + // own trace, since our own trace has a deeper limit. Search for it. + for (uint i = refTrace.size(); i > 0; i--) { + if (refTrace[i-1] == trace[traceCount-1]) { + // See how many frames match. + for (uint j = 0; j < i; j++) { + if (j >= traceCount) { + // We matched the whole trace, apparently? + traceCount = 0; + return; + } else if (refTrace[i-j-1] != trace[traceCount-j-1]) { + // Found mismatching entry. + + // If we matched more than half of the reference trace, guess that this is in fact + // the prefix we're looking for. + if (j > refTrace.size() / 2) { + // Delete the matching suffix. Also delete one non-matched entry on the assumption + // that both traces contain that stack frame but are simply at different points in + // the function. + traceCount -= j + 1; + return; + } + } + } + } + } + + // No match. Ignore. + } +} + +#if !KJ_NO_EXCEPTIONS + +class ExceptionImpl: public Exception, public std::exception { +public: + inline ExceptionImpl(Exception&& other): Exception(mv(other)) {} + ExceptionImpl(const ExceptionImpl& other): Exception(other) {} + + const char* what() const noexcept override; + +private: + mutable String whatBuffer; + +}; + +const char* ExceptionImpl::what() const noexcept { + whatBuffer = str(*this); + return whatBuffer.begin(); +} + +#endif // !KJ_NO_EXCEPTIONS + +// ======================================================================================= + +namespace { + +KJ_THREADLOCAL_PTR(ExceptionCallback) threadLocalCallback = nullptr; + +} // namespace + +void requireOnStack(void* ptr, kj::StringPtr description) { +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || \ + KJ_HAS_COMPILER_FEATURE(address_sanitizer) || \ + KJ_HAS_COMPILER_FEATURE(hwaddress_sanitizer) || \ + defined(__SANITIZE_ADDRESS__) + // When using libfuzzer or ASAN, this sanity check may spurriously fail, so skip it. +#else + char stackVar; + ptrdiff_t offset = reinterpret_cast(ptr) - &stackVar; + KJ_REQUIRE(offset < 65536 && offset > -65536, + kj::str(description)); +#endif +} + +ExceptionCallback::ExceptionCallback(): next(getExceptionCallback()) { + requireOnStack(this, "ExceptionCallback must be allocated on the stack."); + threadLocalCallback = this; +} + +ExceptionCallback::ExceptionCallback(ExceptionCallback& next): next(next) {} + +ExceptionCallback::~ExceptionCallback() noexcept(false) { + if (&next != this) { + threadLocalCallback = &next; + } +} + +void ExceptionCallback::onRecoverableException(Exception&& exception) { + next.onRecoverableException(mv(exception)); +} + +void ExceptionCallback::onFatalException(Exception&& exception) { + next.onFatalException(mv(exception)); +} + +void ExceptionCallback::logMessage( + LogSeverity severity, const char* file, int line, int contextDepth, String&& text) { + next.logMessage(severity, file, line, contextDepth, mv(text)); +} + +ExceptionCallback::StackTraceMode ExceptionCallback::stackTraceMode() { + return next.stackTraceMode(); +} + +namespace _ { // private + uint uncaughtExceptionCount(); // defined later in this file +} + +class ExceptionCallback::RootExceptionCallback: public ExceptionCallback { +public: + RootExceptionCallback(): ExceptionCallback(*this) {} + + void onRecoverableException(Exception&& exception) override { +#if KJ_NO_EXCEPTIONS + logException(LogSeverity::ERROR, mv(exception)); +#else + if (_::uncaughtExceptionCount() > 0) { + // Bad time to throw an exception. Just log instead. + // + // TODO(someday): We should really compare uncaughtExceptionCount() against the count at + // the innermost runCatchingExceptions() frame in this thread to tell if exceptions are + // being caught correctly. + logException(LogSeverity::ERROR, mv(exception)); + } else { + throw ExceptionImpl(mv(exception)); + } +#endif + } + + void onFatalException(Exception&& exception) override { +#if KJ_NO_EXCEPTIONS + logException(LogSeverity::FATAL, mv(exception)); +#else + throw ExceptionImpl(mv(exception)); +#endif + } + + void logMessage(LogSeverity severity, const char* file, int line, int contextDepth, + String&& text) override { + text = str(kj::repeat('_', contextDepth), file, ":", line, ": ", severity, ": ", + mv(text), '\n'); + + StringPtr textPtr = text; + + while (textPtr != nullptr) { + miniposix::ssize_t n = miniposix::write(STDERR_FILENO, textPtr.begin(), textPtr.size()); + if (n <= 0) { + // stderr is broken. Give up. + return; + } + textPtr = textPtr.slice(n); + } + } + + StackTraceMode stackTraceMode() override { +#ifdef KJ_DEBUG + return StackTraceMode::FULL; +#else + return StackTraceMode::ADDRESS_ONLY; +#endif + } + + +private: + void logException(LogSeverity severity, Exception&& e) { + // We intentionally go back to the top exception callback on the stack because we don't want to + // bypass whatever log processing is in effect. + // + // We intentionally don't log the context since it should get re-added by the exception callback + // anyway. + getExceptionCallback().logMessage(severity, e.getFile(), e.getLine(), 0, str( + e.getType(), e.getDescription() == nullptr ? "" : ": ", e.getDescription(), + e.getStackTrace().size() > 0 ? "\nstack: " : "", + stringifyStackTraceAddresses(e.getStackTrace()), + stringifyStackTrace(e.getStackTrace()), "\n")); + } +}; + +ExceptionCallback& getExceptionCallback() { + static auto defaultCallback = lsanIgnoreObjectAndReturn( + new ExceptionCallback::RootExceptionCallback()); + // We allocate on the heap because some objects may throw in their destructors. If those objects + // had static storage, they might get fully constructed before the root callback. If they however + // then throw an exception during destruction, there would be a lifetime issue because their + // destructor would end up getting registered after the root callback's destructor. One solution + // is to just leak this pointer & allocate on first-use. The cost is that the initialization is + // mildly more expensive (+ we need to annotate sanitizers to ignore the problem). A great + // compiler annotation that would simply things would be one that allowed static variables to have + // their destruction omitted wholesale. That would allow us to avoid the heap but still have the + // same robust safety semantics leaking would give us. A practical alternative that could be + // implemented without new compilers would be to define another static root callback in + // RootExceptionCallback's destructor (+ a separate pointer to share its value with this + // function). Since this would end up getting constructed during exit unwind, it would have the + // nice property of effectively being guaranteed to be evicted last. + // + // All this being said, I came back to leaking the object is the easiest tweak here: + // * Can't go wrong + // * Easy to maintain + // * Throwing exceptions is bound to do be expensive and malloc-happy anyway, so the incremental + // cost of 1 heap allocation is minimal. + // + // TODO(cleanup): Harris has an excellent suggestion in + // https://github.com/capnproto/capnproto/pull/1255 that should ensure we initialize the root + // callback once on first use as a global & never destroy it. + + ExceptionCallback* scoped = threadLocalCallback; + return scoped != nullptr ? *scoped : *defaultCallback; +} + +void throwFatalException(kj::Exception&& exception, uint ignoreCount) { + if (ignoreCount != (uint)kj::maxValue) exception.extendTrace(ignoreCount + 1); + getExceptionCallback().onFatalException(kj::mv(exception)); + abort(); +} + +void throwRecoverableException(kj::Exception&& exception, uint ignoreCount) { + if (ignoreCount != (uint)kj::maxValue) exception.extendTrace(ignoreCount + 1); + getExceptionCallback().onRecoverableException(kj::mv(exception)); +} + +// ======================================================================================= + +namespace _ { // private + +#if KJ_CPP_STD >= 201703L + +uint uncaughtExceptionCount() { + return std::uncaught_exceptions(); +} + +#elif __GNUC__ + +// Horrible -- but working -- hack: We can dig into __cxa_get_globals() in order to extract the +// count of uncaught exceptions. This function is part of the C++ ABI implementation used on Linux, +// OSX, and probably other platforms that use GCC. Unfortunately, __cxa_get_globals() is only +// actually defined in cxxabi.h on some platforms (e.g. Linux, but not OSX), and even where it is +// defined, it returns an incomplete type. Here we use the same hack used by Evgeny Panasyuk: +// https://github.com/panaseleus/stack_unwinding/blob/master/boost/exception/uncaught_exception_count.hpp +// +// Notice that a similar hack is possible on MSVC -- if its C++11 support ever gets to the point of +// supporting KJ in the first place. +// +// It appears likely that a future version of the C++ standard may include an +// uncaught_exception_count() function in the standard library, or an equivalent language feature. +// Some discussion: +// https://groups.google.com/a/isocpp.org/d/msg/std-proposals/HglEslyZFYs/kKdu5jJw5AgJ + +struct FakeEhGlobals { + // Fake + + void* caughtExceptions; + uint uncaughtExceptions; +}; + +// LLVM's libstdc++ doesn't declare __cxa_get_globals in its cxxabi.h. GNU does. Because it is +// extern "C", the compiler wills get upset if we re-declare it even in a different namespace. +#if _LIBCPPABI_VERSION +extern "C" void* __cxa_get_globals(); +#else +using abi::__cxa_get_globals; +#endif + +uint uncaughtExceptionCount() { + return reinterpret_cast(__cxa_get_globals())->uncaughtExceptions; +} + +#else +#error "This needs to be ported to your compiler / C++ ABI." +#endif + +} // namespace _ (private) + +UnwindDetector::UnwindDetector(): uncaughtCount(_::uncaughtExceptionCount()) {} + +bool UnwindDetector::isUnwinding() const { + return _::uncaughtExceptionCount() > uncaughtCount; +} + +#if !KJ_NO_EXCEPTIONS +void UnwindDetector::catchThrownExceptionAsSecondaryFault() const { + // TODO(someday): Attach the secondary exception to whatever primary exception is causing + // the unwind. For now we just drop it on the floor as this is probably fine most of the + // time. + getCaughtExceptionAsKj(); +} +#endif + +#if __GNUC__ && !KJ_NO_RTTI +static kj::String demangleTypeName(const char* name) { + if (name == nullptr) return kj::heapString("(nil)"); + + int status; + char* buf = abi::__cxa_demangle(name, nullptr, nullptr, &status); + kj::String result = kj::heapString(buf == nullptr ? name : buf); + free(buf); + return kj::mv(result); +} + +kj::String getCaughtExceptionType() { + return demangleTypeName(abi::__cxa_current_exception_type()->name()); +} +#else +kj::String getCaughtExceptionType() { + return kj::heapString("(unknown)"); +} +#endif + +#if KJ_NO_EXCEPTIONS + +namespace _ { // private + +class RecoverableExceptionCatcher: public ExceptionCallback { + // Catches a recoverable exception without using try/catch. Used when compiled with + // -fno-exceptions. + +public: + virtual ~RecoverableExceptionCatcher() noexcept(false) {} + + void onRecoverableException(Exception&& exception) override { + if (caught == nullptr) { + caught = mv(exception); + } else { + // TODO(someday): Consider it a secondary fault? + } + } + + Maybe caught; +}; + +Maybe runCatchingExceptions(Runnable& runnable) { + RecoverableExceptionCatcher catcher; + runnable.run(); + KJ_IF_MAYBE(e, catcher.caught) { + e->truncateCommonTrace(); + } + return mv(catcher.caught); +} + +} // namespace _ (private) + +#else // KJ_NO_EXCEPTIONS + +kj::Exception getCaughtExceptionAsKj() { + try { + throw; + } catch (Exception& e) { + e.truncateCommonTrace(); + return kj::mv(e); + } catch (CanceledException) { + throw; + } catch (std::bad_alloc& e) { + return Exception(Exception::Type::OVERLOADED, + "(unknown)", -1, str("std::bad_alloc: ", e.what())); + } catch (std::exception& e) { + return Exception(Exception::Type::FAILED, + "(unknown)", -1, str("std::exception: ", e.what())); + } catch (...) { +#if __GNUC__ && !KJ_NO_RTTI + return Exception(Exception::Type::FAILED, "(unknown)", -1, str( + "unknown non-KJ exception of type: ", getCaughtExceptionType())); +#else + return Exception(Exception::Type::FAILED, "(unknown)", -1, str("unknown non-KJ exception")); +#endif + } +} +#endif // !KJ_NO_EXCEPTIONS + +} // namespace kj diff --git a/vendor/capnproto/src/kj/exception.h b/vendor/capnproto/src/kj/exception.h new file mode 100644 index 0000000..d37f78c --- /dev/null +++ b/vendor/capnproto/src/kj/exception.h @@ -0,0 +1,429 @@ +// 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. + +#pragma once + +#include "memory.h" +#include "array.h" +#include "string.h" + +KJ_BEGIN_HEADER + +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 . + +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 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> next; + + Context(const char* file, int line, String&& description, Maybe>&& next) + : file(file), line(line), description(mv(description)), next(mv(next)) {} + Context(const Context& other) noexcept; + }; + + inline Maybe 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, uint limit = kj::maxValue); + // Append the current stack trace to the exception's trace, ignoring the first `ignoreCount` + // frames (see `getStackTrace()` for discussion of `ignoreCount`). + // + // If `limit` is set, limit the number of frames added to the given number. + + 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. + +private: + String ownFile; + const char* file; + int line; + Type type; + String description; + Maybe> context; + void* trace[32]; + uint traceCount; + + bool isFullTrace = false; + // Is `trace` a full trace to the top of the stack (or as close as we could get before we ran + // out of space)? If this is false, then `trace` is instead a partial trace covering just the + // frames between where the exception was thrown and where it was caught. + // + // extendTrace() transitions this to true, and truncateCommonTrace() changes it back to false. + // + // In theory, an exception should only hold a full trace when it is in the process of being + // thrown via the C++ exception handling mechanism -- extendTrace() is called before the throw + // and truncateCommonTrace() after it is caught. Note that when exceptions propagate through + // async promises, the trace is extended one frame at a time instead, so isFullTrace should + // remain false. + + friend class ExceptionImpl; +}; + +struct CanceledException { }; +// This exception is thrown to force-unwind a stack in order to immediately cancel whatever that +// stack was doing. It is used in the implementation of fibers in particular. Application code +// should almost never catch this exception, unless you need to modify stack unwinding for some +// reason. kj::runCatchingExceptions() does not catch it. + +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_AND_MOVE(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 +Maybe runCatchingExceptions(Func&& func); +// 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. + +#if !KJ_NO_EXCEPTIONS + +kj::Exception getCaughtExceptionAsKj(); +// Call from the catch block of a try/catch to get a `kj::Exception` representing the exception +// that was caught, the same way that `kj::runCatchingExceptions` would when catching an exception. +// This is sometimes useful if `runCatchingExceptions()` doesn't quite fit your use case. You can +// call this from any catch block, including `catch (...)`. +// +// Some exception types will actually be rethrown by this function, rather than returned. The most +// common example is `CanceledException`, whose purpose is to unwind the stack and is not meant to +// be caught. + +#endif // !KJ_NO_EXCEPTIONS + +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 + 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; + +#if !KJ_NO_EXCEPTIONS + void catchThrownExceptionAsSecondaryFault() const; +#endif +}; + +#if KJ_NO_EXCEPTIONS + +namespace _ { // private + +class Runnable { +public: + virtual void run() = 0; +}; + +template +class RunnableImpl: public Runnable { +public: + RunnableImpl(Func&& func): func(kj::fwd(func)) {} + void run() override { + func(); + } +private: + Func func; +}; + +Maybe runCatchingExceptions(Runnable& runnable); + +} // namespace _ (private) + +#endif // KJ_NO_EXCEPTIONS + +template +Maybe runCatchingExceptions(Func&& func) { +#if KJ_NO_EXCEPTIONS + _::RunnableImpl runnable(kj::fwd(func)); + return _::runCatchingExceptions(runnable); +#else + try { + func(); + return nullptr; + } catch (...) { + return getCaughtExceptionAsKj(); + } +#endif +} + +template +void UnwindDetector::catchExceptionsIfUnwinding(Func&& func) const { +#if KJ_NO_EXCEPTIONS + // Can't possibly be unwinding... + func(); +#else + if (isUnwinding()) { + try { + func(); + } catch (...) { + catchThrownExceptionAsSecondaryFault(); + } + } else { + func(); + } +#endif +} + +#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 getStackTrace(ArrayPtr 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); +// Convert the stack trace to a string with file names and line numbers. This may involve executing +// suprocesses. + +String stringifyStackTraceAddresses(ArrayPtr trace); +StringPtr stringifyStackTraceAddresses(ArrayPtr trace, ArrayPtr scratch); +// Construct a string containing just enough information about a stack trace to be able to convert +// it to file and line numbers later using offline tools. This produces a sequence of +// space-separated code location identifiers. Each identifier may be an absolute address +// (hex number starting with 0x) or may be a module-relative address "@0x". The +// latter case is preferred when ASLR is in effect and has loaded different modules at different +// addresses. + +String getStackTrace(); +// Get a stack trace right now and stringify it. Useful for debugging. + +kj::StringPtr trimSourceFilename(kj::StringPtr filename); +// Given a source code file name, trim off noisy prefixes like "src/" or +// "/ekam-provider/canonical/". + +kj::String getCaughtExceptionType(); +// Utility function which attempts to return the human-readable type name of the exception +// currently being thrown. This can be called inside a catch block, including a catch (...) block, +// for the purpose of error logging. This function is best-effort; on some platforms it may simply +// return "(unknown)". + +void requireOnStack(void* ptr, kj::StringPtr description); +// Throw an exception if `ptr` does not appear to point to something near the top of the stack. +// Used as a safety check for types that must be stack-allocated, like ExceptionCallback. + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/filesystem-disk-unix.c++ b/vendor/capnproto/src/kj/filesystem-disk-unix.c++ new file mode 100644 index 0000000..3183c84 --- /dev/null +++ b/vendor/capnproto/src/kj/filesystem-disk-unix.c++ @@ -0,0 +1,1801 @@ +// 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 _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +// Request 64-bit off_t. (The code will still work if we get 32-bit off_t as long as actual files +// are under 4GB.) +#endif + +#include "filesystem.h" +#include "debug.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vector.h" +#include "miniposix.h" +#include + +#if __linux__ +#include +#include +#include +#endif + +namespace kj { +namespace { + +#define HIDDEN_PREFIX ".kj-tmp." +// Prefix for temp files which should be hidden when listing a directory. +// +// If you change this, make sure to update the unit test. + +#ifdef O_CLOEXEC +#define MAYBE_O_CLOEXEC O_CLOEXEC +#else +#define MAYBE_O_CLOEXEC 0 +#endif + +#ifdef O_DIRECTORY +#define MAYBE_O_DIRECTORY O_DIRECTORY +#else +#define MAYBE_O_DIRECTORY 0 +#endif + +#if __APPLE__ +// Mac OSX defines SEEK_HOLE, but it doesn't work. ("Inappropriate ioctl for device", it says.) +#undef SEEK_HOLE +#endif + +#if __BIONIC__ +// No no DTTOIF function +#undef DT_UNKNOWN +#endif + +static void setCloexec(int fd) KJ_UNUSED; +static void setCloexec(int fd) { + // Set the O_CLOEXEC flag on the given fd. + // + // We try to avoid the need to call this by taking advantage of syscall flags that set it + // atomically on new file descriptors. Unfortunately some platforms do not support such syscalls. + +#ifdef FIOCLEX + // Yay, we can set the flag in one call. + KJ_SYSCALL_HANDLE_ERRORS(ioctl(fd, FIOCLEX)) { + case EINVAL: + case EOPNOTSUPP: + break; + default: + KJ_FAIL_SYSCALL("ioctl(fd, FIOCLEX)", error) { break; } + break; + } else { + // success + return; + } +#endif + + // Sadness, we must resort to read/modify/write. + // + // (On many platforms, FD_CLOEXEC is the only flag modifiable via F_SETFD and therefore we could + // skip the read... but it seems dangerous to assume that's true of all platforms, and anyway + // most platforms support FIOCLEX.) + int flags; + KJ_SYSCALL(flags = fcntl(fd, F_GETFD)); + if (!(flags & FD_CLOEXEC)) { + KJ_SYSCALL(fcntl(fd, F_SETFD, flags | FD_CLOEXEC)); + } +} + +static Date toKjDate(struct timespec tv) { + return tv.tv_sec * SECONDS + tv.tv_nsec * NANOSECONDS + UNIX_EPOCH; +} + +static FsNode::Type modeToType(mode_t mode) { + switch (mode & S_IFMT) { + case S_IFREG : return FsNode::Type::FILE; + case S_IFDIR : return FsNode::Type::DIRECTORY; + case S_IFLNK : return FsNode::Type::SYMLINK; + case S_IFBLK : return FsNode::Type::BLOCK_DEVICE; + case S_IFCHR : return FsNode::Type::CHARACTER_DEVICE; + case S_IFIFO : return FsNode::Type::NAMED_PIPE; + case S_IFSOCK: return FsNode::Type::SOCKET; + default: return FsNode::Type::OTHER; + } +} + +static FsNode::Metadata statToMetadata(struct stat& stats) { + // Probably st_ino and st_dev are usually under 32 bits, so mix by rotating st_dev left 32 bits + // and XOR. + uint64_t d = stats.st_dev; + uint64_t hash = ((d << 32) | (d >> 32)) ^ stats.st_ino; + + return FsNode::Metadata { + modeToType(stats.st_mode), + implicitCast(stats.st_size), + implicitCast(stats.st_blocks * 512u), +#if __APPLE__ + toKjDate(stats.st_mtimespec), +#else + toKjDate(stats.st_mtim), +#endif + implicitCast(stats.st_nlink), + hash + }; +} + +static bool rmrf(int fd, StringPtr path); + +static void rmrfChildrenAndClose(int fd) { + // Assumes fd is seeked to beginning. + + DIR* dir = fdopendir(fd); + if (dir == nullptr) { + close(fd); + KJ_FAIL_SYSCALL("fdopendir", errno); + }; + KJ_DEFER(closedir(dir)); + + for (;;) { + errno = 0; + struct dirent* entry = readdir(dir); + if (entry == nullptr) { + int error = errno; + if (error == 0) { + break; + } else { + KJ_FAIL_SYSCALL("readdir", error); + } + } + + if (entry->d_name[0] == '.' && + (entry->d_name[1] == '\0' || + (entry->d_name[1] == '.' && + entry->d_name[2] == '\0'))) { + // ignore . and .. + } else { +#ifdef DT_UNKNOWN // d_type is not available on all platforms. + if (entry->d_type == DT_DIR) { + int subdirFd; + KJ_SYSCALL(subdirFd = openat( + fd, entry->d_name, O_RDONLY | MAYBE_O_DIRECTORY | MAYBE_O_CLOEXEC | O_NOFOLLOW)); + rmrfChildrenAndClose(subdirFd); + KJ_SYSCALL(unlinkat(fd, entry->d_name, AT_REMOVEDIR)); + } else if (entry->d_type != DT_UNKNOWN) { + KJ_SYSCALL(unlinkat(fd, entry->d_name, 0)); + } else { +#endif + KJ_ASSERT(rmrf(fd, entry->d_name)); +#ifdef DT_UNKNOWN + } +#endif + } + } +} + +static bool rmrf(int fd, StringPtr path) { + struct stat stats; + KJ_SYSCALL_HANDLE_ERRORS(fstatat(fd, path.cStr(), &stats, AT_SYMLINK_NOFOLLOW)) { + case ENOENT: + case ENOTDIR: + // Doesn't exist. + return false; + default: + KJ_FAIL_SYSCALL("lstat(path)", error, path) { return false; } + } + + if (S_ISDIR(stats.st_mode)) { + int subdirFd; + KJ_SYSCALL(subdirFd = openat( + fd, path.cStr(), O_RDONLY | MAYBE_O_DIRECTORY | MAYBE_O_CLOEXEC | O_NOFOLLOW)) { + return false; + } + rmrfChildrenAndClose(subdirFd); + KJ_SYSCALL(unlinkat(fd, path.cStr(), AT_REMOVEDIR)) { return false; } + } else { + KJ_SYSCALL(unlinkat(fd, path.cStr(), 0)) { return false; } + } + + return true; +} + +struct MmapRange { + uint64_t offset; + uint64_t size; +}; + +static MmapRange getMmapRange(uint64_t offset, uint64_t size) { + // Comes up with an offset and size to pass to mmap(), given an offset and size requested by + // the caller, and considering the fact that mappings must start at a page boundary. + // + // The offset is rounded down to the nearest page boundary, and the size is increased to + // compensate. Note that the endpoint of the mapping is *not* rounded up to a page boundary, as + // mmap() does not actually require this, and it causes trouble on some systems (notably Cygwin). + +#ifndef _SC_PAGESIZE +#define _SC_PAGESIZE _SC_PAGE_SIZE +#endif + static const uint64_t pageSize = sysconf(_SC_PAGESIZE); + uint64_t pageMask = pageSize - 1; + + uint64_t realOffset = offset & ~pageMask; + + return { realOffset, offset + size - realOffset }; +} + +class MmapDisposer: public ArrayDisposer { +protected: + void disposeImpl(void* firstElement, size_t elementSize, size_t elementCount, + size_t capacity, void (*destroyElement)(void*)) const { + auto range = getMmapRange(reinterpret_cast(firstElement), + elementSize * elementCount); + KJ_SYSCALL(munmap(reinterpret_cast(range.offset), range.size)) { break; } + } +}; + +constexpr MmapDisposer mmapDisposer = MmapDisposer(); + +class DiskHandle { + // We need to implement each of ReadableFile, AppendableFile, File, ReadableDirectory, and + // Directory for disk handles. There is a lot of implementation overlap between these, especially + // stat(), sync(), etc. We can't have everything inherit from a common DiskFsNode that implements + // these because then we get diamond inheritance which means we need to make all our inheritance + // virtual which means downcasting requires RTTI which violates our goal of supporting compiling + // with no RTTI. So instead we have the DiskHandle class which implements all the methods without + // inheriting anything, and then we have DiskFile, DiskDirectory, etc. hold this and delegate to + // it. Ugly, but works. + +public: + DiskHandle(AutoCloseFd&& fd): fd(kj::mv(fd)) {} + + // OsHandle ------------------------------------------------------------------ + + AutoCloseFd clone() const { + int fd2; +#ifdef F_DUPFD_CLOEXEC + KJ_SYSCALL_HANDLE_ERRORS(fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 3)) { + case EINVAL: + case EOPNOTSUPP: + // fall back + break; + default: + KJ_FAIL_SYSCALL("fnctl(fd, F_DUPFD_CLOEXEC, 3)", error) { break; } + break; + } else { + return AutoCloseFd(fd2); + } +#endif + + KJ_SYSCALL(fd2 = ::dup(fd)); + AutoCloseFd result(fd2); + setCloexec(result); + return result; + } + + int getFd() const { + return fd.get(); + } + + void setFd(AutoCloseFd newFd) { + // Used for one hack in DiskFilesystem's constructor... + fd = kj::mv(newFd); + } + + // FsNode -------------------------------------------------------------------- + + FsNode::Metadata stat() const { + struct stat stats; + KJ_SYSCALL(::fstat(fd, &stats)); + return statToMetadata(stats); + } + + void sync() const { +#if __APPLE__ + // For whatever reason, fsync() on OSX only flushes kernel buffers. It does not flush hardware + // disk buffers. This makes it not very useful. But OSX documents fcntl F_FULLFSYNC which does + // the right thing. Why they don't just make fsync() do the right thing, I do not know. + KJ_SYSCALL(fcntl(fd, F_FULLFSYNC)); +#else + KJ_SYSCALL(fsync(fd)); +#endif + } + + void datasync() const { + // The presence of the _POSIX_SYNCHRONIZED_IO define is supposed to tell us that fdatasync() + // exists. But Apple defines this yet doesn't offer fdatasync(). Thanks, Apple. +#if _POSIX_SYNCHRONIZED_IO && !__APPLE__ + KJ_SYSCALL(fdatasync(fd)); +#else + this->sync(); +#endif + } + + // ReadableFile -------------------------------------------------------------- + + size_t read(uint64_t offset, ArrayPtr buffer) const { + // pread() probably never returns short reads unless it hits EOF. Unfortunately, though, per + // spec we are not allowed to assume this. + + size_t total = 0; + while (buffer.size() > 0) { + ssize_t n; + KJ_SYSCALL(n = pread(fd, buffer.begin(), buffer.size(), offset)); + if (n == 0) break; + total += n; + offset += n; + buffer = buffer.slice(n, buffer.size()); + } + return total; + } + + Array mmap(uint64_t offset, uint64_t size) const { + if (size == 0) return nullptr; // zero-length mmap() returns EINVAL, so avoid it + auto range = getMmapRange(offset, size); + const void* mapping = ::mmap(NULL, range.size, PROT_READ, MAP_SHARED, fd, range.offset); + if (mapping == MAP_FAILED) { + KJ_FAIL_SYSCALL("mmap", errno); + } + return Array(reinterpret_cast(mapping) + (offset - range.offset), + size, mmapDisposer); + } + + Array mmapPrivate(uint64_t offset, uint64_t size) const { + if (size == 0) return nullptr; // zero-length mmap() returns EINVAL, so avoid it + auto range = getMmapRange(offset, size); + void* mapping = ::mmap(NULL, range.size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, range.offset); + if (mapping == MAP_FAILED) { + KJ_FAIL_SYSCALL("mmap", errno); + } + return Array(reinterpret_cast(mapping) + (offset - range.offset), + size, mmapDisposer); + } + + // File ---------------------------------------------------------------------- + + void write(uint64_t offset, ArrayPtr data) const { + // pwrite() probably never returns short writes unless there's no space left on disk. + // Unfortunately, though, per spec we are not allowed to assume this. + + while (data.size() > 0) { + ssize_t n; + KJ_SYSCALL(n = pwrite(fd, data.begin(), data.size(), offset)); + KJ_ASSERT(n > 0, "pwrite() returned zero?"); + offset += n; + data = data.slice(n, data.size()); + } + } + + void zero(uint64_t offset, uint64_t size) const { + // If FALLOC_FL_PUNCH_HOLE is defined, use it to efficiently zero the area. + // + // A fallocate() wrapper was only added to Android's Bionic C library as of API level 21, + // but FALLOC_FL_PUNCH_HOLE is apparently defined in the headers before that, so we'll + // have to explicitly test for that case. +#if defined(FALLOC_FL_PUNCH_HOLE) && !(__ANDROID__ && __BIONIC__ && __ANDROID_API__ < 21) + KJ_SYSCALL_HANDLE_ERRORS( + fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, offset, size)) { + case EOPNOTSUPP: + // fall back to below + break; + default: + KJ_FAIL_SYSCALL("fallocate(FALLOC_FL_PUNCH_HOLE)", error) { return; } + } else { + return; + } +#endif + + static const byte ZEROS[4096] = { 0 }; + +#if __APPLE__ || (defined(__ANDROID__) && __ANDROID_API__ < 24) + // Mac & Cygwin & Android API levels 23 and lower doesn't have pwritev(). + while (size > sizeof(ZEROS)) { + write(offset, ZEROS); + size -= sizeof(ZEROS); + offset += sizeof(ZEROS); + } + write(offset, kj::arrayPtr(ZEROS, size)); +#else + // Use a 4k buffer of zeros amplified by iov to write zeros with as few syscalls as possible. + size_t count = (size + sizeof(ZEROS) - 1) / sizeof(ZEROS); + const size_t iovmax = miniposix::iovMax(); + KJ_STACK_ARRAY(struct iovec, iov, kj::min(iovmax, count), 16, 256); + + for (auto& item: iov) { + item.iov_base = const_cast(ZEROS); + item.iov_len = sizeof(ZEROS); + } + + while (size > 0) { + size_t iovCount; + if (size >= iov.size() * sizeof(ZEROS)) { + iovCount = iov.size(); + } else { + iovCount = size / sizeof(ZEROS); + size_t rem = size % sizeof(ZEROS); + if (rem > 0) { + iov[iovCount++].iov_len = rem; + } + } + + ssize_t n; + KJ_SYSCALL(n = pwritev(fd, iov.begin(), count, offset)); + KJ_ASSERT(n > 0, "pwrite() returned zero?"); + + offset += n; + size -= n; + } +#endif + } + + void truncate(uint64_t size) const { + KJ_SYSCALL(ftruncate(fd, size)); + } + + class WritableFileMappingImpl final: public WritableFileMapping { + public: + WritableFileMappingImpl(Array bytes): bytes(kj::mv(bytes)) {} + + ArrayPtr get() const override { + // const_cast OK because WritableFileMapping does indeed provide a writable view despite + // being const itself. + return arrayPtr(const_cast(bytes.begin()), bytes.size()); + } + + void changed(ArrayPtr slice) const override { + KJ_REQUIRE(slice.begin() >= bytes.begin() && slice.end() <= bytes.end(), + "byte range is not part of this mapping"); + if (slice.size() == 0) return; + + // msync() requires page-alignment, apparently, so use getMmapRange() to accomplish that. + auto range = getMmapRange(reinterpret_cast(slice.begin()), slice.size()); + KJ_SYSCALL(msync(reinterpret_cast(range.offset), range.size, MS_ASYNC)); + } + + void sync(ArrayPtr slice) const override { + KJ_REQUIRE(slice.begin() >= bytes.begin() && slice.end() <= bytes.end(), + "byte range is not part of this mapping"); + if (slice.size() == 0) return; + + // msync() requires page-alignment, apparently, so use getMmapRange() to accomplish that. + auto range = getMmapRange(reinterpret_cast(slice.begin()), slice.size()); + KJ_SYSCALL(msync(reinterpret_cast(range.offset), range.size, MS_SYNC)); + } + + private: + Array bytes; + }; + + Own mmapWritable(uint64_t offset, uint64_t size) const { + if (size == 0) { + // zero-length mmap() returns EINVAL, so avoid it + return heap(nullptr); + } + auto range = getMmapRange(offset, size); + void* mapping = ::mmap(NULL, range.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, range.offset); + if (mapping == MAP_FAILED) { + KJ_FAIL_SYSCALL("mmap", errno); + } + auto array = Array(reinterpret_cast(mapping) + (offset - range.offset), + size, mmapDisposer); + return heap(kj::mv(array)); + } + + size_t copyChunk(uint64_t offset, int fromFd, uint64_t fromOffset, uint64_t size) const { + // Copies a range of bytes from `fromFd` to this file in the most efficient way possible for + // the OS. Only returns less than `size` if EOF. Does not account for holes. + +#if __linux__ + { + KJ_SYSCALL(lseek(fd, offset, SEEK_SET)); + off_t fromPos = fromOffset; + off_t end = fromOffset + size; + while (fromPos < end) { + ssize_t n; + KJ_SYSCALL_HANDLE_ERRORS(n = sendfile(fd, fromFd, &fromPos, end - fromPos)) { + case EINVAL: + case ENOSYS: + goto sendfileNotAvailable; + default: + KJ_FAIL_SYSCALL("sendfile", error) { return fromPos - fromOffset; } + } + if (n == 0) break; + } + return fromPos - fromOffset; + } + + sendfileNotAvailable: +#endif + uint64_t total = 0; + while (size > 0) { + byte buffer[4096]; + ssize_t n; + KJ_SYSCALL(n = pread(fromFd, buffer, kj::min(sizeof(buffer), size), fromOffset)); + if (n == 0) break; + write(offset, arrayPtr(buffer, n)); + fromOffset += n; + offset += n; + total += n; + size -= n; + } + return total; + } + + kj::Maybe copy(uint64_t offset, const ReadableFile& from, + uint64_t fromOffset, uint64_t size) const { + KJ_IF_MAYBE(otherFd, from.getFd()) { +#ifdef FICLONE + if (offset == 0 && fromOffset == 0 && size == kj::maxValue && stat().size == 0) { + if (ioctl(fd, FICLONE, *otherFd) >= 0) { + return stat().size; + } + } else if (size > 0) { // src_length = 0 has special meaning for the syscall, so avoid. + struct file_clone_range range; + memset(&range, 0, sizeof(range)); + range.src_fd = *otherFd; + range.dest_offset = offset; + range.src_offset = fromOffset; + range.src_length = size == kj::maxValue ? 0 : size; + if (ioctl(fd, FICLONERANGE, &range) >= 0) { + // TODO(someday): What does FICLONERANGE actually do if the range goes past EOF? The docs + // don't say. Maybe it only copies the parts that exist. Maybe it punches holes for the + // rest. Where does the destination file's EOF marker end up? Who knows? + return kj::min(from.stat().size - fromOffset, size); + } + } else { + // size == 0 + return size_t(0); + } + + // ioctl failed. Almost all failures documented for these are of the form "the operation is + // not supported for the filesystem(s) specified", so fall back to other approaches. +#endif + + off_t toPos = offset; + off_t fromPos = fromOffset; + off_t end = size == kj::maxValue ? off_t(kj::maxValue) : off_t(fromOffset + size); + + for (;;) { + // Handle data. + { + // Find out how much data there is before the next hole. + off_t nextHole; +#ifdef SEEK_HOLE + KJ_SYSCALL_HANDLE_ERRORS(nextHole = lseek(*otherFd, fromPos, SEEK_HOLE)) { + case EINVAL: + // SEEK_HOLE probably not supported. Assume no holes. + nextHole = end; + break; + case ENXIO: + // Past EOF. Stop here. + return fromPos - fromOffset; + default: + KJ_FAIL_SYSCALL("lseek(fd, pos, SEEK_HOLE)", error) { return fromPos - fromOffset; } + } +#else + // SEEK_HOLE not supported. Assume no holes. + nextHole = end; +#endif + + // Copy the next chunk of data. + off_t copyTo = kj::min(end, nextHole); + size_t amount = copyTo - fromPos; + if (amount > 0) { + size_t n = copyChunk(toPos, *otherFd, fromPos, amount); + fromPos += n; + toPos += n; + + if (n < amount) { + return fromPos - fromOffset; + } + } + + if (fromPos == end) { + return fromPos - fromOffset; + } + } + +#ifdef SEEK_HOLE + // Handle hole. + { + // Find out how much hole there is before the next data. + off_t nextData; + KJ_SYSCALL_HANDLE_ERRORS(nextData = lseek(*otherFd, fromPos, SEEK_DATA)) { + case EINVAL: + // SEEK_DATA probably not supported. But we should only have gotten here if we + // were expecting a hole. + KJ_FAIL_ASSERT("can't determine hole size; SEEK_DATA not supported"); + break; + case ENXIO: + // No more data. Set to EOF. + KJ_SYSCALL(nextData = lseek(*otherFd, 0, SEEK_END)); + if (nextData > end) { + end = nextData; + } + break; + default: + KJ_FAIL_SYSCALL("lseek(fd, pos, SEEK_HOLE)", error) { return fromPos - fromOffset; } + } + + // Write zeros. + off_t zeroTo = kj::min(end, nextData); + off_t amount = zeroTo - fromPos; + if (amount > 0) { + zero(toPos, amount); + toPos += amount; + fromPos = zeroTo; + } + + if (fromPos == end) { + return fromPos - fromOffset; + } + } +#endif + } + } + + // Indicates caller should call File::copy() default implementation. + return nullptr; + } + + // ReadableDirectory --------------------------------------------------------- + + template + auto list(bool needTypes, Func&& func) const + -> Array(), instance()))>> { + // Seek to start of directory. + KJ_SYSCALL(lseek(fd, 0, SEEK_SET)); + + // Unfortunately, fdopendir() takes ownership of the file descriptor. Therefore we need to + // make a duplicate. + int duped; + KJ_SYSCALL(duped = dup(fd)); + DIR* dir = fdopendir(duped); + if (dir == nullptr) { + close(duped); + KJ_FAIL_SYSCALL("fdopendir", errno); + } + + KJ_DEFER(closedir(dir)); + typedef Decay(), instance()))> Entry; + kj::Vector entries; + + for (;;) { + errno = 0; + struct dirent* entry = readdir(dir); + if (entry == nullptr) { + int error = errno; + if (error == 0) { + break; + } else { + KJ_FAIL_SYSCALL("readdir", error); + } + } + + kj::StringPtr name = entry->d_name; + if (name != "." && name != ".." && !name.startsWith(HIDDEN_PREFIX)) { +#ifdef DT_UNKNOWN // d_type is not available on all platforms. + if (entry->d_type != DT_UNKNOWN) { + entries.add(func(name, modeToType(DTTOIF(entry->d_type)))); + } else { +#endif + if (needTypes) { + // Unknown type. Fall back to stat. + struct stat stats; + KJ_SYSCALL(fstatat(fd, name.cStr(), &stats, AT_SYMLINK_NOFOLLOW)); + entries.add(func(name, modeToType(stats.st_mode))); + } else { + entries.add(func(name, FsNode::Type::OTHER)); + } +#ifdef DT_UNKNOWN + } +#endif + } + } + + auto result = entries.releaseAsArray(); + std::sort(result.begin(), result.end()); + return result; + } + + Array listNames() const { + return list(false, [](StringPtr name, FsNode::Type type) { return heapString(name); }); + } + + Array listEntries() const { + return list(true, [](StringPtr name, FsNode::Type type) { + return ReadableDirectory::Entry { type, heapString(name), }; + }); + } + + bool exists(PathPtr path) const { + KJ_SYSCALL_HANDLE_ERRORS(faccessat(fd, path.toString().cStr(), F_OK, 0)) { + case ENOENT: + case ENOTDIR: + return false; + default: + KJ_FAIL_SYSCALL("faccessat(fd, path)", error, path) { return false; } + } + return true; + } + + Maybe tryLstat(PathPtr path) const { + struct stat stats; + KJ_SYSCALL_HANDLE_ERRORS(fstatat(fd, path.toString().cStr(), &stats, AT_SYMLINK_NOFOLLOW)) { + case ENOENT: + case ENOTDIR: + return nullptr; + default: + KJ_FAIL_SYSCALL("faccessat(fd, path)", error, path) { return nullptr; } + } + return statToMetadata(stats); + } + + Maybe> tryOpenFile(PathPtr path) const { + int newFd; + KJ_SYSCALL_HANDLE_ERRORS(newFd = openat( + fd, path.toString().cStr(), O_RDONLY | MAYBE_O_CLOEXEC)) { + case ENOENT: + case ENOTDIR: + return nullptr; + default: + KJ_FAIL_SYSCALL("openat(fd, path, O_RDONLY)", error, path) { return nullptr; } + } + + kj::AutoCloseFd result(newFd); +#ifndef O_CLOEXEC + setCloexec(result); +#endif + + return newDiskReadableFile(kj::mv(result)); + } + + Maybe tryOpenSubdirInternal(PathPtr path) const { + int newFd; + KJ_SYSCALL_HANDLE_ERRORS(newFd = openat( + fd, path.toString().cStr(), O_RDONLY | MAYBE_O_CLOEXEC | MAYBE_O_DIRECTORY)) { + case ENOENT: + return nullptr; + case ENOTDIR: + // Could mean that a parent is not a directory, which we treat as "doesn't exist". + // Could also mean that the specified file is not a directory, which should throw. + // Check using exists(). + if (!exists(path)) { + return nullptr; + } + KJ_FALLTHROUGH; + default: + KJ_FAIL_SYSCALL("openat(fd, path, O_DIRECTORY)", error, path) { return nullptr; } + } + + kj::AutoCloseFd result(newFd); +#ifndef O_CLOEXEC + setCloexec(result); +#endif + + return kj::mv(result); + } + + Maybe> tryOpenSubdir(PathPtr path) const { + return tryOpenSubdirInternal(path).map(newDiskReadableDirectory); + } + + Maybe tryReadlink(PathPtr path) const { + size_t trySize = 256; + for (;;) { + KJ_STACK_ARRAY(char, buf, trySize, 256, 4096); + ssize_t n = readlinkat(fd, path.toString().cStr(), buf.begin(), buf.size()); + if (n < 0) { + int error = errno; + switch (error) { + case EINTR: + continue; + case ENOENT: + case ENOTDIR: + case EINVAL: // not a link + return nullptr; + default: + KJ_FAIL_SYSCALL("readlinkat(fd, path)", error, path) { return nullptr; } + } + } + + if (n >= buf.size()) { + // Didn't give it enough space. Better retry with a bigger buffer. + trySize *= 2; + continue; + } + + return heapString(buf.begin(), n); + } + } + + // Directory ----------------------------------------------------------------- + + bool tryMkdir(PathPtr path, WriteMode mode, bool noThrow) const { + // Internal function to make a directory. + + auto filename = path.toString(); + mode_t acl = has(mode, WriteMode::PRIVATE) ? 0700 : 0777; + + KJ_SYSCALL_HANDLE_ERRORS(mkdirat(fd, filename.cStr(), acl)) { + case EEXIST: { + // Apparently this path exists. + if (!has(mode, WriteMode::MODIFY)) { + // Require exclusive create. + return false; + } + + // MODIFY is allowed, so we just need to check whether the existing entry is a directory. + struct stat stats; + KJ_SYSCALL_HANDLE_ERRORS(fstatat(fd, filename.cStr(), &stats, 0)) { + default: + // mkdir() says EEXIST but we can't stat it. Maybe it's a dangling link, or maybe + // we can't access it for some reason. Assume failure. + // + // TODO(someday): Maybe we should be creating the directory at the target of the + // link? + goto failed; + } + return (stats.st_mode & S_IFMT) == S_IFDIR; + } + case ENOENT: + if (has(mode, WriteMode::CREATE_PARENT) && path.size() > 0 && + tryMkdir(path.parent(), WriteMode::CREATE | WriteMode::MODIFY | + WriteMode::CREATE_PARENT, true)) { + // Retry, but make sure we don't try to create the parent again. + return tryMkdir(path, mode - WriteMode::CREATE_PARENT, noThrow); + } else { + goto failed; + } + default: + failed: + if (noThrow) { + // Caller requested no throwing. + return false; + } else { + KJ_FAIL_SYSCALL("mkdirat(fd, path)", error, path); + } + } + + return true; + } + + kj::Maybe createNamedTemporary( + PathPtr finalName, WriteMode mode, Function tryCreate) const { + // Create a temporary file which will eventually replace `finalName`. + // + // Calls `tryCreate` to actually create the temporary, passing in the desired path. tryCreate() + // is expected to behave like a syscall, returning a negative value and setting `errno` on + // error. tryCreate() MUST fail with EEXIST if the path exists -- this is not checked in + // advance, since it needs to be checked atomically. In the case of EEXIST, tryCreate() will + // be called again with a new path. + // + // Returns the temporary path that succeeded. Only returns nullptr if there was an exception + // but we're compiled with -fno-exceptions. + + if (finalName.size() == 0) { + KJ_FAIL_REQUIRE("can't replace self") { break; } + return nullptr; + } + + static uint counter = 0; + static const pid_t pid = getpid(); + String pathPrefix; + if (finalName.size() > 1) { + pathPrefix = kj::str(finalName.parent(), '/'); + } + auto path = kj::str(pathPrefix, HIDDEN_PREFIX, pid, '.', counter++, '.', + finalName.basename()[0], ".partial"); + + KJ_SYSCALL_HANDLE_ERRORS(tryCreate(path)) { + case EEXIST: + return createNamedTemporary(finalName, mode, kj::mv(tryCreate)); + case ENOENT: + if (has(mode, WriteMode::CREATE_PARENT) && finalName.size() > 1 && + tryMkdir(finalName.parent(), WriteMode::CREATE | WriteMode::MODIFY | + WriteMode::CREATE_PARENT, true)) { + // Retry, but make sure we don't try to create the parent again. + mode = mode - WriteMode::CREATE_PARENT; + return createNamedTemporary(finalName, mode, kj::mv(tryCreate)); + } + KJ_FALLTHROUGH; + default: + KJ_FAIL_SYSCALL("create(path)", error, path) { break; } + return nullptr; + } + + return kj::mv(path); + } + + bool tryReplaceNode(PathPtr path, WriteMode mode, Function tryCreate) const { + // Replaces the given path with an object created by calling tryCreate(). + // + // tryCreate() must behave like a syscall which creates the node at the path passed to it, + // returning a negative value on error. If the path passed to tryCreate already exists, it + // MUST fail with EEXIST. + // + // When `mode` includes MODIFY, replaceNode() reacts to EEXIST by creating the node in a + // temporary location and then rename()ing it into place. + + if (path.size() == 0) { + KJ_FAIL_REQUIRE("can't replace self") { return false; } + } + + auto filename = path.toString(); + + if (has(mode, WriteMode::CREATE)) { + // First try just cerating the node in-place. + KJ_SYSCALL_HANDLE_ERRORS(tryCreate(filename)) { + case EEXIST: + // Target exists. + if (has(mode, WriteMode::MODIFY)) { + // Fall back to MODIFY path, below. + break; + } else { + return false; + } + case ENOENT: + if (has(mode, WriteMode::CREATE_PARENT) && path.size() > 0 && + tryMkdir(path.parent(), WriteMode::CREATE | WriteMode::MODIFY | + WriteMode::CREATE_PARENT, true)) { + // Retry, but make sure we don't try to create the parent again. + return tryReplaceNode(path, mode - WriteMode::CREATE_PARENT, kj::mv(tryCreate)); + } + KJ_FALLTHROUGH; + default: + KJ_FAIL_SYSCALL("create(path)", error, path) { return false; } + } else { + // Success. + return true; + } + } + + // Either we don't have CREATE mode or the target already exists. We need to perform a + // replacement instead. + + KJ_IF_MAYBE(tempPath, createNamedTemporary(path, mode, kj::mv(tryCreate))) { + if (tryCommitReplacement(filename, fd, *tempPath, mode)) { + return true; + } else { + KJ_SYSCALL_HANDLE_ERRORS(unlinkat(fd, tempPath->cStr(), 0)) { + case ENOENT: + // meh + break; + default: + KJ_FAIL_SYSCALL("unlinkat(fd, tempPath, 0)", error, *tempPath); + } + return false; + } + } else { + // threw, but exceptions are disabled + return false; + } + } + + Maybe tryOpenFileInternal(PathPtr path, WriteMode mode, bool append) const { + uint flags = O_RDWR | MAYBE_O_CLOEXEC; + mode_t acl = 0666; + if (has(mode, WriteMode::CREATE)) { + flags |= O_CREAT; + } + if (!has(mode, WriteMode::MODIFY)) { + if (!has(mode, WriteMode::CREATE)) { + // Neither CREATE nor MODIFY -- impossible to satisfy preconditions. + return nullptr; + } + flags |= O_EXCL; + } + if (append) { + flags |= O_APPEND; + } + if (has(mode, WriteMode::EXECUTABLE)) { + acl = 0777; + } + if (has(mode, WriteMode::PRIVATE)) { + acl &= 0700; + } + + auto filename = path.toString(); + + int newFd; + KJ_SYSCALL_HANDLE_ERRORS(newFd = openat(fd, filename.cStr(), flags, acl)) { + case ENOENT: + if (has(mode, WriteMode::CREATE)) { + // Either: + // - The file is a broken symlink. + // - A parent directory didn't exist. + if (has(mode, WriteMode::CREATE_PARENT) && path.size() > 0 && + tryMkdir(path.parent(), WriteMode::CREATE | WriteMode::MODIFY | + WriteMode::CREATE_PARENT, true)) { + // Retry, but make sure we don't try to create the parent again. + return tryOpenFileInternal(path, mode - WriteMode::CREATE_PARENT, append); + } + + // Check for broken link. + if (!has(mode, WriteMode::MODIFY) && + faccessat(fd, filename.cStr(), F_OK, AT_SYMLINK_NOFOLLOW) >= 0) { + // Yep. We treat this as already-exists, which means in CREATE-only mode this is a + // simple failure. + return nullptr; + } + + KJ_FAIL_REQUIRE("parent is not a directory", path) { return nullptr; } + } else { + // MODIFY-only mode. ENOENT = doesn't exist = return null. + return nullptr; + } + case ENOTDIR: + if (!has(mode, WriteMode::CREATE)) { + // MODIFY-only mode. ENOTDIR = parent not a directory = doesn't exist = return null. + return nullptr; + } + goto failed; + case EEXIST: + if (!has(mode, WriteMode::MODIFY)) { + // CREATE-only mode. EEXIST = already exists = return null. + return nullptr; + } + goto failed; + default: + failed: + KJ_FAIL_SYSCALL("openat(fd, path, O_RDWR | ...)", error, path) { return nullptr; } + } + + kj::AutoCloseFd result(newFd); +#ifndef O_CLOEXEC + setCloexec(result); +#endif + + return kj::mv(result); + } + + bool tryCommitReplacement(StringPtr toPath, int fromDirFd, StringPtr fromPath, WriteMode mode, + int* errorReason = nullptr) const { + if (has(mode, WriteMode::CREATE) && has(mode, WriteMode::MODIFY)) { + // Always clobber. Try it. + KJ_SYSCALL_HANDLE_ERRORS(renameat(fromDirFd, fromPath.cStr(), fd.get(), toPath.cStr())) { + case EISDIR: + case ENOTDIR: + case ENOTEMPTY: + case EEXIST: + // Failed because target exists and due to the various weird quirks of rename(), it + // can't remove it for us. On Linux we can try an exchange instead. On others we have + // to move the target out of the way. + break; + default: + if (errorReason == nullptr) { + KJ_FAIL_SYSCALL("rename(fromPath, toPath)", error, fromPath, toPath) { return false; } + } else { + *errorReason = error; + return false; + } + } else { + return true; + } + } + +#if __linux__ && defined(RENAME_EXCHANGE) && defined(SYS_renameat2) + // Try to use Linux's renameat2() to atomically check preconditions and apply. + + if (has(mode, WriteMode::MODIFY)) { + // Use an exchange to implement modification. + // + // We reach this branch when performing a MODIFY-only, or when performing a CREATE | MODIFY + // in which we determined above that there's a node of a different type blocking the + // exchange. + + KJ_SYSCALL_HANDLE_ERRORS(syscall(SYS_renameat2, + fromDirFd, fromPath.cStr(), fd.get(), toPath.cStr(), RENAME_EXCHANGE)) { + case ENOSYS: // Syscall not supported by kernel. + case EINVAL: // Maybe we screwed up, or maybe the syscall is not supported by the + // filesystem. Unfortunately, there's no way to tell, so assume the latter. + // ZFS in particular apparently produces EINVAL. + break; // fall back to traditional means + case ENOENT: + // Presumably because the target path doesn't exist. + if (has(mode, WriteMode::CREATE)) { + KJ_FAIL_ASSERT("rename(tmp, path) claimed path exists but " + "renameat2(fromPath, toPath, EXCHANGE) said it doesn't; concurrent modification?", + fromPath, toPath) { return false; } + } else { + // Assume target doesn't exist. + return false; + } + default: + if (errorReason == nullptr) { + KJ_FAIL_SYSCALL("renameat2(fromPath, toPath, EXCHANGE)", error, fromPath, toPath) { + return false; + } + } else { + *errorReason = error; + return false; + } + } else { + // Successful swap! Delete swapped-out content. + rmrf(fromDirFd, fromPath); + return true; + } + } else if (has(mode, WriteMode::CREATE)) { + KJ_SYSCALL_HANDLE_ERRORS(syscall(SYS_renameat2, + fromDirFd, fromPath.cStr(), fd.get(), toPath.cStr(), RENAME_NOREPLACE)) { + case ENOSYS: // Syscall not supported by kernel. + case EINVAL: // Maybe we screwed up, or maybe the syscall is not supported by the + // filesystem. Unfortunately, there's no way to tell, so assume the latter. + // ZFS in particular apparently produces EINVAL. + break; // fall back to traditional means + case EEXIST: + return false; + default: + if (errorReason == nullptr) { + KJ_FAIL_SYSCALL("renameat2(fromPath, toPath, NOREPLACE)", error, fromPath, toPath) { + return false; + } + } else { + *errorReason = error; + return false; + } + } else { + return true; + } + } +#endif + + // We're unable to do what we wanted atomically. :( + + if (has(mode, WriteMode::CREATE) && has(mode, WriteMode::MODIFY)) { + // We failed to atomically delete the target previously. So now we need to do two calls in + // rapid succession to move the old file away then move the new one into place. + + // Find out what kind of file exists at the target path. + struct stat stats; + KJ_SYSCALL(fstatat(fd, toPath.cStr(), &stats, AT_SYMLINK_NOFOLLOW)) { return false; } + + // Create a temporary location to move the existing object to. Note that rename() allows a + // non-directory to replace a non-directory, and allows a directory to replace an empty + // directory. So we have to create the right type. + Path toPathParsed = Path::parse(toPath); + String away; + KJ_IF_MAYBE(awayPath, createNamedTemporary(toPathParsed, WriteMode::CREATE, + [&](StringPtr candidatePath) { + if (S_ISDIR(stats.st_mode)) { + return mkdirat(fd, candidatePath.cStr(), 0700); + } else { +#if __APPLE__ || __FreeBSD__ + // - No mknodat() on OSX, gotta open() a file, ugh. + // - On a modern FreeBSD, mknodat() is reserved strictly for device nodes, + // you cannot create a regular file using it (EINVAL). + int newFd = openat(fd, candidatePath.cStr(), + O_RDWR | O_CREAT | O_EXCL | MAYBE_O_CLOEXEC, 0700); + if (newFd >= 0) close(newFd); + return newFd; +#else + return mknodat(fd, candidatePath.cStr(), S_IFREG | 0600, dev_t()); +#endif + } + })) { + away = kj::mv(*awayPath); + } else { + // Already threw. + return false; + } + + // OK, now move the target object to replace the thing we just created. + KJ_SYSCALL(renameat(fd, toPath.cStr(), fd, away.cStr())) { + // Something went wrong. Remove the thing we just created. + unlinkat(fd, away.cStr(), S_ISDIR(stats.st_mode) ? AT_REMOVEDIR : 0); + return false; + } + + // Now move the source object to the target location. + KJ_SYSCALL_HANDLE_ERRORS(renameat(fromDirFd, fromPath.cStr(), fd, toPath.cStr())) { + default: + // Try to put things back where they were. If this fails, though, then we have little + // choice but to leave things broken. + KJ_SYSCALL_HANDLE_ERRORS(renameat(fd, away.cStr(), fd, toPath.cStr())) { + default: break; + } + + if (errorReason == nullptr) { + KJ_FAIL_SYSCALL("rename(fromPath, toPath)", error, fromPath, toPath) { + return false; + } + } else { + *errorReason = error; + return false; + } + } + + // OK, success. Delete the old content. + rmrf(fd, away); + return true; + } else { + // Only one of CREATE or MODIFY is specified, so we need to verify non-atomically that the + // corresponding precondition (must-not-exist or must-exist, respectively) is held. + if (has(mode, WriteMode::CREATE)) { + struct stat stats; + KJ_SYSCALL_HANDLE_ERRORS(fstatat(fd.get(), toPath.cStr(), &stats, AT_SYMLINK_NOFOLLOW)) { + case ENOENT: + case ENOTDIR: + break; // doesn't exist; continue + default: + KJ_FAIL_SYSCALL("fstatat(fd, toPath)", error, toPath) { return false; } + } else { + return false; // already exists; fail + } + } else if (has(mode, WriteMode::MODIFY)) { + struct stat stats; + KJ_SYSCALL_HANDLE_ERRORS(fstatat(fd.get(), toPath.cStr(), &stats, AT_SYMLINK_NOFOLLOW)) { + case ENOENT: + case ENOTDIR: + return false; // doesn't exist; fail + default: + KJ_FAIL_SYSCALL("fstatat(fd, toPath)", error, toPath) { return false; } + } else { + // already exists; continue + } + } else { + // Neither CREATE nor MODIFY. + return false; + } + + // Start over in create-and-modify mode. + return tryCommitReplacement(toPath, fromDirFd, fromPath, + WriteMode::CREATE | WriteMode::MODIFY, + errorReason); + } + } + + template + class ReplacerImpl final: public Directory::Replacer { + public: + ReplacerImpl(Own&& object, const DiskHandle& handle, + String&& tempPath, String&& path, WriteMode mode) + : Directory::Replacer(mode), + object(kj::mv(object)), handle(handle), + tempPath(kj::mv(tempPath)), path(kj::mv(path)) {} + + ~ReplacerImpl() noexcept(false) { + if (!committed) { + rmrf(handle.fd, tempPath); + } + } + + const T& get() override { + return *object; + } + + bool tryCommit() override { + KJ_ASSERT(!committed, "already committed") { return false; } + return committed = handle.tryCommitReplacement(path, handle.fd, tempPath, + Directory::Replacer::mode); + } + + private: + Own object; + const DiskHandle& handle; + String tempPath; + String path; + bool committed = false; // true if *successfully* committed (in which case tempPath is gone) + }; + + template + class BrokenReplacer final: public Directory::Replacer { + // For recovery path when exceptions are disabled. + + public: + BrokenReplacer(Own inner) + : Directory::Replacer(WriteMode::CREATE | WriteMode::MODIFY), + inner(kj::mv(inner)) {} + + const T& get() override { return *inner; } + bool tryCommit() override { return false; } + + private: + Own inner; + }; + + Maybe> tryOpenFile(PathPtr path, WriteMode mode) const { + return tryOpenFileInternal(path, mode, false).map(newDiskFile); + } + + Own> replaceFile(PathPtr path, WriteMode mode) const { + mode_t acl = 0666; + if (has(mode, WriteMode::EXECUTABLE)) { + acl = 0777; + } + if (has(mode, WriteMode::PRIVATE)) { + acl &= 0700; + } + + int newFd_; + KJ_IF_MAYBE(temp, createNamedTemporary(path, mode, + [&](StringPtr candidatePath) { + return newFd_ = openat(fd, candidatePath.cStr(), + O_RDWR | O_CREAT | O_EXCL | MAYBE_O_CLOEXEC, acl); + })) { + AutoCloseFd newFd(newFd_); +#ifndef O_CLOEXEC + setCloexec(newFd); +#endif + return heap>(newDiskFile(kj::mv(newFd)), *this, kj::mv(*temp), + path.toString(), mode); + } else { + // threw, but exceptions are disabled + return heap>(newInMemoryFile(nullClock())); + } + } + + Own createTemporary() const { + int newFd_; + +#if __linux__ && defined(O_TMPFILE) + // Use syscall() to work around glibc bug with O_TMPFILE: + // https://sourceware.org/bugzilla/show_bug.cgi?id=17523 + KJ_SYSCALL_HANDLE_ERRORS(newFd_ = syscall( + SYS_openat, fd.get(), ".", O_RDWR | O_TMPFILE, 0700)) { + case EOPNOTSUPP: + case EINVAL: + case EISDIR: + // Maybe not supported by this kernel / filesystem. Fall back to below. + break; + default: + KJ_FAIL_SYSCALL("open(O_TMPFILE)", error) { break; } + break; + } else { + AutoCloseFd newFd(newFd_); +#ifndef O_CLOEXEC + setCloexec(newFd); +#endif + return newDiskFile(kj::mv(newFd)); + } +#endif + + KJ_IF_MAYBE(temp, createNamedTemporary(Path("unnamed"), WriteMode::CREATE, + [&](StringPtr path) { + return newFd_ = openat(fd, path.cStr(), O_RDWR | O_CREAT | O_EXCL | MAYBE_O_CLOEXEC, 0600); + })) { + AutoCloseFd newFd(newFd_); +#ifndef O_CLOEXEC + setCloexec(newFd); +#endif + auto result = newDiskFile(kj::mv(newFd)); + KJ_SYSCALL(unlinkat(fd, temp->cStr(), 0)) { break; } + return kj::mv(result); + } else { + // threw, but exceptions are disabled + return newInMemoryFile(nullClock()); + } + } + + Maybe> tryAppendFile(PathPtr path, WriteMode mode) const { + return tryOpenFileInternal(path, mode, true).map(newDiskAppendableFile); + } + + Maybe> tryOpenSubdir(PathPtr path, WriteMode mode) const { + // Must create before open. + if (has(mode, WriteMode::CREATE)) { + if (!tryMkdir(path, mode, false)) return nullptr; + } + + return tryOpenSubdirInternal(path).map(newDiskDirectory); + } + + Own> replaceSubdir(PathPtr path, WriteMode mode) const { + mode_t acl = has(mode, WriteMode::PRIVATE) ? 0700 : 0777; + + KJ_IF_MAYBE(temp, createNamedTemporary(path, mode, + [&](StringPtr candidatePath) { + return mkdirat(fd, candidatePath.cStr(), acl); + })) { + int subdirFd_; + KJ_SYSCALL_HANDLE_ERRORS(subdirFd_ = openat( + fd, temp->cStr(), O_RDONLY | MAYBE_O_CLOEXEC | MAYBE_O_DIRECTORY)) { + default: + KJ_FAIL_SYSCALL("open(just-created-temporary)", error); + return heap>(newInMemoryDirectory(nullClock())); + } + + AutoCloseFd subdirFd(subdirFd_); +#ifndef O_CLOEXEC + setCloexec(subdirFd); +#endif + return heap>( + newDiskDirectory(kj::mv(subdirFd)), *this, kj::mv(*temp), path.toString(), mode); + } else { + // threw, but exceptions are disabled + return heap>(newInMemoryDirectory(nullClock())); + } + } + + bool trySymlink(PathPtr linkpath, StringPtr content, WriteMode mode) const { + return tryReplaceNode(linkpath, mode, [&](StringPtr candidatePath) { + return symlinkat(content.cStr(), fd, candidatePath.cStr()); + }); + } + + bool tryTransfer(PathPtr toPath, WriteMode toMode, + const Directory& fromDirectory, PathPtr fromPath, + TransferMode mode, const Directory& self) const { + KJ_REQUIRE(toPath.size() > 0, "can't replace self") { return false; } + + if (mode == TransferMode::LINK) { + KJ_IF_MAYBE(fromFd, fromDirectory.getFd()) { + // Other is a disk directory, so we can hopefully do an efficient move/link. + return tryReplaceNode(toPath, toMode, [&](StringPtr candidatePath) { + return linkat(*fromFd, fromPath.toString().cStr(), fd, candidatePath.cStr(), 0); + }); + }; + } else if (mode == TransferMode::MOVE) { + KJ_IF_MAYBE(fromFd, fromDirectory.getFd()) { + KJ_ASSERT(mode == TransferMode::MOVE); + + int error = 0; + if (tryCommitReplacement(toPath.toString(), *fromFd, fromPath.toString(), toMode, + &error)) { + return true; + } else switch (error) { + case 0: + // Plain old WriteMode precondition failure. + return false; + case EXDEV: + // Can't move between devices. Fall back to default implementation, which does + // copy/delete. + break; + case ENOENT: + // Either the destination directory doesn't exist or the source path doesn't exist. + // Unfortunately we don't really know. If CREATE_PARENT was provided, try creating + // the parent directory. Otherwise, we don't actually need to distinguish between + // these two errors; just return false. + if (has(toMode, WriteMode::CREATE) && has(toMode, WriteMode::CREATE_PARENT) && + toPath.size() > 0 && tryMkdir(toPath.parent(), + WriteMode::CREATE | WriteMode::MODIFY | WriteMode::CREATE_PARENT, true)) { + // Retry, but make sure we don't try to create the parent again. + return tryTransfer(toPath, toMode - WriteMode::CREATE_PARENT, + fromDirectory, fromPath, mode, self); + } + return false; + default: + KJ_FAIL_SYSCALL("rename(fromPath, toPath)", error, fromPath, toPath) { + return false; + } + } + } + } + + // OK, we can't do anything efficient using the OS. Fall back to default implementation. + return self.Directory::tryTransfer(toPath, toMode, fromDirectory, fromPath, mode); + } + + bool tryRemove(PathPtr path) const { + return rmrf(fd, path.toString()); + } + +protected: + AutoCloseFd fd; +}; + +#define FSNODE_METHODS(classname) \ + Maybe getFd() const override { return DiskHandle::getFd(); } \ + \ + Own cloneFsNode() const override { \ + return heap(DiskHandle::clone()); \ + } \ + \ + Metadata stat() const override { return DiskHandle::stat(); } \ + void sync() const override { DiskHandle::sync(); } \ + void datasync() const override { DiskHandle::datasync(); } + +class DiskReadableFile final: public ReadableFile, public DiskHandle { +public: + DiskReadableFile(AutoCloseFd&& fd): DiskHandle(kj::mv(fd)) {} + + FSNODE_METHODS(DiskReadableFile); + + size_t read(uint64_t offset, ArrayPtr buffer) const override { + return DiskHandle::read(offset, buffer); + } + Array mmap(uint64_t offset, uint64_t size) const override { + return DiskHandle::mmap(offset, size); + } + Array mmapPrivate(uint64_t offset, uint64_t size) const override { + return DiskHandle::mmapPrivate(offset, size); + } +}; + +class DiskAppendableFile final: public AppendableFile, public DiskHandle, public FdOutputStream { +public: + DiskAppendableFile(AutoCloseFd&& fd) + : DiskHandle(kj::mv(fd)), + FdOutputStream(DiskHandle::fd.get()) {} + + FSNODE_METHODS(DiskAppendableFile); + + void write(const void* buffer, size_t size) override { + FdOutputStream::write(buffer, size); + } + void write(ArrayPtr> pieces) override { + FdOutputStream::write(pieces); + } +}; + +class DiskFile final: public File, public DiskHandle { +public: + DiskFile(AutoCloseFd&& fd): DiskHandle(kj::mv(fd)) {} + + FSNODE_METHODS(DiskFile); + + size_t read(uint64_t offset, ArrayPtr buffer) const override { + return DiskHandle::read(offset, buffer); + } + Array mmap(uint64_t offset, uint64_t size) const override { + return DiskHandle::mmap(offset, size); + } + Array mmapPrivate(uint64_t offset, uint64_t size) const override { + return DiskHandle::mmapPrivate(offset, size); + } + + void write(uint64_t offset, ArrayPtr data) const override { + DiskHandle::write(offset, data); + } + void zero(uint64_t offset, uint64_t size) const override { + DiskHandle::zero(offset, size); + } + void truncate(uint64_t size) const override { + DiskHandle::truncate(size); + } + Own mmapWritable(uint64_t offset, uint64_t size) const override { + return DiskHandle::mmapWritable(offset, size); + } + size_t copy(uint64_t offset, const ReadableFile& from, + uint64_t fromOffset, uint64_t size) const override { + KJ_IF_MAYBE(result, DiskHandle::copy(offset, from, fromOffset, size)) { + return *result; + } else { + return File::copy(offset, from, fromOffset, size); + } + } +}; + +class DiskReadableDirectory final: public ReadableDirectory, public DiskHandle { +public: + DiskReadableDirectory(AutoCloseFd&& fd): DiskHandle(kj::mv(fd)) {} + + FSNODE_METHODS(DiskReadableDirectory); + + Array listNames() const override { return DiskHandle::listNames(); } + Array listEntries() const override { return DiskHandle::listEntries(); } + bool exists(PathPtr path) const override { return DiskHandle::exists(path); } + Maybe tryLstat(PathPtr path) const override { + return DiskHandle::tryLstat(path); + } + Maybe> tryOpenFile(PathPtr path) const override { + return DiskHandle::tryOpenFile(path); + } + Maybe> tryOpenSubdir(PathPtr path) const override { + return DiskHandle::tryOpenSubdir(path); + } + Maybe tryReadlink(PathPtr path) const override { return DiskHandle::tryReadlink(path); } +}; + +class DiskDirectory final: public Directory, public DiskHandle { +public: + DiskDirectory(AutoCloseFd&& fd): DiskHandle(kj::mv(fd)) {} + + FSNODE_METHODS(DiskDirectory); + + Array listNames() const override { return DiskHandle::listNames(); } + Array listEntries() const override { return DiskHandle::listEntries(); } + bool exists(PathPtr path) const override { return DiskHandle::exists(path); } + Maybe tryLstat(PathPtr path) const override { + return DiskHandle::tryLstat(path); + } + Maybe> tryOpenFile(PathPtr path) const override { + return DiskHandle::tryOpenFile(path); + } + Maybe> tryOpenSubdir(PathPtr path) const override { + return DiskHandle::tryOpenSubdir(path); + } + Maybe tryReadlink(PathPtr path) const override { return DiskHandle::tryReadlink(path); } + + Maybe> tryOpenFile(PathPtr path, WriteMode mode) const override { + return DiskHandle::tryOpenFile(path, mode); + } + Own> replaceFile(PathPtr path, WriteMode mode) const override { + return DiskHandle::replaceFile(path, mode); + } + Own createTemporary() const override { + return DiskHandle::createTemporary(); + } + Maybe> tryAppendFile(PathPtr path, WriteMode mode) const override { + return DiskHandle::tryAppendFile(path, mode); + } + Maybe> tryOpenSubdir(PathPtr path, WriteMode mode) const override { + return DiskHandle::tryOpenSubdir(path, mode); + } + Own> replaceSubdir(PathPtr path, WriteMode mode) const override { + return DiskHandle::replaceSubdir(path, mode); + } + bool trySymlink(PathPtr linkpath, StringPtr content, WriteMode mode) const override { + return DiskHandle::trySymlink(linkpath, content, mode); + } + bool tryTransfer(PathPtr toPath, WriteMode toMode, + const Directory& fromDirectory, PathPtr fromPath, + TransferMode mode) const override { + return DiskHandle::tryTransfer(toPath, toMode, fromDirectory, fromPath, mode, *this); + } + // tryTransferTo() not implemented because we have nothing special we can do. + bool tryRemove(PathPtr path) const override { + return DiskHandle::tryRemove(path); + } +}; + +class DiskFilesystem final: public Filesystem { +public: + DiskFilesystem() + : root(openDir("/")), + current(openDir(".")), + currentPath(computeCurrentPath()) { + // We sometimes like to use qemu-user to test arm64 binaries cross-compiled from an x64 host + // machine. But, because it intercepts and rewrites system calls from userspace rather than + // emulating a whole kernel, it has a lot of quirks. One quirk that hits kj::Filesystem pretty + // badly is that open("/") actually returns a file descriptor for "/usr/aarch64-linux-gnu". + // Attempts to openat() any files within there then don't work. We can detect this problem and + // correct for it here. + struct stat realRoot, fsRoot; + KJ_SYSCALL_HANDLE_ERRORS(stat("/dev/..", &realRoot)) { + default: + // stat("/dev/..") failed? Give up. + return; + } + KJ_SYSCALL(fstat(root.DiskHandle::getFd(), &fsRoot)); + if (realRoot.st_ino != fsRoot.st_ino) { + KJ_LOG(WARNING, "root dir file descriptor is broken, probably because of qemu; compensating"); + root.setFd(openDir("/dev/..")); + } + } + + const Directory& getRoot() const override { + return root; + } + + const Directory& getCurrent() const override { + return current; + } + + PathPtr getCurrentPath() const override { + return currentPath; + } + +private: + DiskDirectory root; + DiskDirectory current; + Path currentPath; + + static AutoCloseFd openDir(const char* dir) { + int newFd; + KJ_SYSCALL_HANDLE_ERRORS(newFd = open(dir, O_RDONLY | MAYBE_O_CLOEXEC | MAYBE_O_DIRECTORY)) { +#ifdef O_PATH + case EACCES: + // If we don't have read permission, fall back to O_PATH if available + KJ_SYSCALL(newFd = open(dir, O_PATH | MAYBE_O_CLOEXEC | MAYBE_O_DIRECTORY)); + break; +#endif + default: + KJ_FAIL_SYSCALL("open(dir, O_RDONLY)", error, dir); + } + AutoCloseFd result(newFd); +#ifndef O_CLOEXEC + setCloexec(result); +#endif + return result; + } + + static Path computeCurrentPath() { + // If env var PWD is set and points to the current directory, use it. This captures the current + // path according to the user's shell, which may differ from the kernel's idea in the presence + // of symlinks. + const char* pwd = getenv("PWD"); + if (pwd != nullptr) { + Path result = nullptr; + struct stat pwdStat, dotStat; + KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() { + KJ_ASSERT(pwd[0] == '/') { return; } + result = Path::parse(pwd + 1); + KJ_SYSCALL(lstat(result.toString(true).cStr(), &pwdStat), result) { return; } + KJ_SYSCALL(lstat(".", &dotStat)) { return; } + })) { + // failed, give up on PWD + KJ_LOG(WARNING, "PWD environment variable seems invalid", pwd, *e); + } else { + if (pwdStat.st_ino == dotStat.st_ino && + pwdStat.st_dev == dotStat.st_dev) { + return kj::mv(result); + } else { + // It appears PWD doesn't actually point at the current directory. In practice, only + // shells tend to update PWD. Other programs, like build tools, may do `chdir()` without + // actually updating PWD to match. Arguably they are buggy, but realistically we have to + // live with them. So, we will treat an incorrect PWD the same as an absent PWD, and fall + // back to using the current directory's canonical path. + // + // We used to log a WARNING here but it was deemed too noisy, so we changed it to INFO. + KJ_LOG(INFO, "PWD environment variable doesn't match current directory", pwd); + } + } + } + + size_t size = 256; + retry: + KJ_STACK_ARRAY(char, buf, size, 256, 4096); + if (getcwd(buf.begin(), size) == nullptr) { + int error = errno; + if (error == ERANGE) { + size *= 2; + goto retry; + } else { + KJ_FAIL_SYSCALL("getcwd()", error); + } + } + + StringPtr path = buf.begin(); + + // On Linux, the path will start with "(unreachable)" if the working directory is not a subdir + // of the root directory, which is possible via chroot() or mount namespaces. + KJ_ASSERT(!path.startsWith("(unreachable)"), + "working directory is not reachable from root", path); + KJ_ASSERT(path.startsWith("/"), "current directory is not absolute", path); + + return Path::parse(path.slice(1)); + } +}; + +} // namespace + +Own newDiskReadableFile(kj::AutoCloseFd fd) { + return heap(kj::mv(fd)); +} +Own newDiskAppendableFile(kj::AutoCloseFd fd) { + return heap(kj::mv(fd)); +} +Own newDiskFile(kj::AutoCloseFd fd) { + return heap(kj::mv(fd)); +} +Own newDiskReadableDirectory(kj::AutoCloseFd fd) { + return heap(kj::mv(fd)); +} +Own newDiskDirectory(kj::AutoCloseFd fd) { + return heap(kj::mv(fd)); +} + +Own newDiskFilesystem() { + return heap(); +} + +} // namespace kj diff --git a/vendor/capnproto/src/kj/filesystem.c++ b/vendor/capnproto/src/kj/filesystem.c++ new file mode 100644 index 0000000..077e70e --- /dev/null +++ b/vendor/capnproto/src/kj/filesystem.c++ @@ -0,0 +1,1496 @@ +// 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. + +#include "filesystem.h" +#include "vector.h" +#include "debug.h" +#include "one-of.h" +#include "refcount.h" +#include "mutex.h" +#include + +namespace kj { + +Path::Path(StringPtr name): Path(heapString(name)) {} +Path::Path(String&& name): parts(heapArray(1)) { + parts[0] = kj::mv(name); + validatePart(parts[0]); +} + +Path::Path(ArrayPtr parts) + : Path(KJ_MAP(p, parts) { return heapString(p); }) {} +Path::Path(Array partsParam) + : Path(kj::mv(partsParam), ALREADY_CHECKED) { + for (auto& p: parts) { + validatePart(p); + } +} + +Path PathPtr::clone() { + return Path(KJ_MAP(p, parts) { return heapString(p); }, Path::ALREADY_CHECKED); +} + +Path Path::parse(StringPtr path) { + KJ_REQUIRE(!path.startsWith("/"), "expected a relative path, got absolute", path) { + // When exceptions are disabled, go on -- the leading '/' will end up ignored. + break; + } + return evalImpl(Vector(countParts(path)), path); +} + +Path PathPtr::append(Path&& suffix) const { + auto newParts = kj::heapArrayBuilder(parts.size() + suffix.parts.size()); + for (auto& p: parts) newParts.add(heapString(p)); + for (auto& p: suffix.parts) newParts.add(kj::mv(p)); + return Path(newParts.finish(), Path::ALREADY_CHECKED); +} +Path Path::append(Path&& suffix) && { + auto newParts = kj::heapArrayBuilder(parts.size() + suffix.parts.size()); + for (auto& p: parts) newParts.add(kj::mv(p)); + for (auto& p: suffix.parts) newParts.add(kj::mv(p)); + return Path(newParts.finish(), ALREADY_CHECKED); +} +Path PathPtr::append(PathPtr suffix) const { + auto newParts = kj::heapArrayBuilder(parts.size() + suffix.parts.size()); + for (auto& p: parts) newParts.add(heapString(p)); + for (auto& p: suffix.parts) newParts.add(heapString(p)); + return Path(newParts.finish(), Path::ALREADY_CHECKED); +} +Path Path::append(PathPtr suffix) && { + auto newParts = kj::heapArrayBuilder(parts.size() + suffix.parts.size()); + for (auto& p: parts) newParts.add(kj::mv(p)); + for (auto& p: suffix.parts) newParts.add(heapString(p)); + return Path(newParts.finish(), ALREADY_CHECKED); +} + +Path PathPtr::eval(StringPtr pathText) const { + if (pathText.startsWith("/")) { + // Optimization: avoid copying parts that will just be dropped. + return Path::evalImpl(Vector(Path::countParts(pathText)), pathText); + } else { + Vector newParts(parts.size() + Path::countParts(pathText)); + for (auto& p: parts) newParts.add(heapString(p)); + return Path::evalImpl(kj::mv(newParts), pathText); + } +} +Path Path::eval(StringPtr pathText) && { + if (pathText.startsWith("/")) { + // Optimization: avoid copying parts that will just be dropped. + return evalImpl(Vector(countParts(pathText)), pathText); + } else { + Vector newParts(parts.size() + countParts(pathText)); + for (auto& p: parts) newParts.add(kj::mv(p)); + return evalImpl(kj::mv(newParts), pathText); + } +} + +PathPtr PathPtr::basename() const { + KJ_REQUIRE(parts.size() > 0, "root path has no basename"); + return PathPtr(parts.slice(parts.size() - 1, parts.size())); +} +Path Path::basename() && { + KJ_REQUIRE(parts.size() > 0, "root path has no basename"); + auto newParts = kj::heapArrayBuilder(1); + newParts.add(kj::mv(parts[parts.size() - 1])); + return Path(newParts.finish(), ALREADY_CHECKED); +} + +PathPtr PathPtr::parent() const { + KJ_REQUIRE(parts.size() > 0, "root path has no parent"); + return PathPtr(parts.slice(0, parts.size() - 1)); +} +Path Path::parent() && { + KJ_REQUIRE(parts.size() > 0, "root path has no parent"); + return Path(KJ_MAP(p, parts.slice(0, parts.size() - 1)) { return kj::mv(p); }, ALREADY_CHECKED); +} + +String PathPtr::toString(bool absolute) const { + if (parts.size() == 0) { + // Special-case empty path. + return absolute ? kj::str("/") : kj::str("."); + } + + size_t size = absolute + (parts.size() - 1); + for (auto& p: parts) size += p.size(); + + String result = kj::heapString(size); + + char* ptr = result.begin(); + bool leadingSlash = absolute; + for (auto& p: parts) { + if (leadingSlash) *ptr++ = '/'; + leadingSlash = true; + memcpy(ptr, p.begin(), p.size()); + ptr += p.size(); + } + KJ_ASSERT(ptr == result.end()); + + return result; +} + +Path Path::slice(size_t start, size_t end) && { + return Path(KJ_MAP(p, parts.slice(start, end)) { return kj::mv(p); }); +} + +bool PathPtr::operator==(PathPtr other) const { + return parts == other.parts; +} +bool PathPtr::operator< (PathPtr other) const { + for (size_t i = 0; i < kj::min(parts.size(), other.parts.size()); i++) { + int comp = strcmp(parts[i].cStr(), other.parts[i].cStr()); + if (comp < 0) return true; + if (comp > 0) return false; + } + + return parts.size() < other.parts.size(); +} + +bool PathPtr::startsWith(PathPtr prefix) const { + return parts.size() >= prefix.parts.size() && + parts.slice(0, prefix.parts.size()) == prefix.parts; +} + +bool PathPtr::endsWith(PathPtr suffix) const { + return parts.size() >= suffix.parts.size() && + parts.slice(parts.size() - suffix.parts.size(), parts.size()) == suffix.parts; +} + +String Path::stripNul(String input) { + kj::Vector output(input.size()); + for (char c: input) { + if (c != '\0') output.add(c); + } + output.add('\0'); + return String(output.releaseAsArray()); +} + +void Path::validatePart(StringPtr part) { + KJ_REQUIRE(part != "" && part != "." && part != "..", "invalid path component", part); + KJ_REQUIRE(strlen(part.begin()) == part.size(), "NUL character in path component", part); + KJ_REQUIRE(part.findFirst('/') == nullptr, + "'/' character in path component; did you mean to use Path::parse()?", part); +} + +void Path::evalPart(Vector& parts, ArrayPtr part) { + if (part.size() == 0) { + // Ignore consecutive or trailing '/'s. + } else if (part.size() == 1 && part[0] == '.') { + // Refers to current directory; ignore. + } else if (part.size() == 2 && part[0] == '.' && part [1] == '.') { + KJ_REQUIRE(parts.size() > 0, "can't use \"..\" to break out of starting directory") { + // When exceptions are disabled, ignore. + return; + } + parts.removeLast(); + } else { + auto str = heapString(part); + KJ_REQUIRE(strlen(str.begin()) == str.size(), "NUL character in path component", str) { + // When exceptions are disabled, strip out '\0' chars. + str = stripNul(kj::mv(str)); + break; + } + parts.add(kj::mv(str)); + } +} + +Path Path::evalImpl(Vector&& parts, StringPtr path) { + if (path.startsWith("/")) { + parts.clear(); + } + + size_t partStart = 0; + for (auto i: kj::indices(path)) { + if (path[i] == '/') { + evalPart(parts, path.slice(partStart, i)); + partStart = i + 1; + } + } + evalPart(parts, path.slice(partStart)); + + return Path(parts.releaseAsArray(), Path::ALREADY_CHECKED); +} + +size_t Path::countParts(StringPtr path) { + size_t result = 1; + for (char c: path) { + result += (c == '/'); + } + return result; +} + +// ======================================================================================= + +String ReadableFile::readAllText() const { + String result = heapString(stat().size); + size_t n = read(0, result.asBytes()); + if (n < result.size()) { + // Apparently file was truncated concurrently. Reduce to new size to match. + result = heapString(result.slice(0, n)); + } + return result; +} + +Array ReadableFile::readAllBytes() const { + Array result = heapArray(stat().size); + size_t n = read(0, result.asBytes()); + if (n < result.size()) { + // Apparently file was truncated concurrently. Reduce to new size to match. + result = heapArray(result.slice(0, n)); + } + return result; +} + +void File::writeAll(ArrayPtr bytes) const { + truncate(0); + write(0, bytes); +} + +void File::writeAll(StringPtr text) const { + writeAll(text.asBytes()); +} + +size_t File::copy(uint64_t offset, const ReadableFile& from, + uint64_t fromOffset, uint64_t size) const { + byte buffer[8192]; + + size_t result = 0; + while (size > 0) { + size_t n = from.read(fromOffset, kj::arrayPtr(buffer, kj::min(sizeof(buffer), size))); + write(offset, arrayPtr(buffer, n)); + result += n; + if (n < sizeof(buffer)) { + // Either we copied the amount requested or we hit EOF. + break; + } + fromOffset += n; + offset += n; + size -= n; + } + + return result; +} + +FsNode::Metadata ReadableDirectory::lstat(PathPtr path) const { + KJ_IF_MAYBE(meta, tryLstat(path)) { + return *meta; + } else { + KJ_FAIL_REQUIRE("no such file or directory", path) { break; } + return FsNode::Metadata(); + } +} + +Own ReadableDirectory::openFile(PathPtr path) const { + KJ_IF_MAYBE(file, tryOpenFile(path)) { + return kj::mv(*file); + } else { + KJ_FAIL_REQUIRE("no such file", path) { break; } + return newInMemoryFile(nullClock()); + } +} + +Own ReadableDirectory::openSubdir(PathPtr path) const { + KJ_IF_MAYBE(dir, tryOpenSubdir(path)) { + return kj::mv(*dir); + } else { + KJ_FAIL_REQUIRE("no such directory", path) { break; } + return newInMemoryDirectory(nullClock()); + } +} + +String ReadableDirectory::readlink(PathPtr path) const { + KJ_IF_MAYBE(p, tryReadlink(path)) { + return kj::mv(*p); + } else { + KJ_FAIL_REQUIRE("not a symlink", path) { break; } + return kj::str("."); + } +} + +Own Directory::openFile(PathPtr path, WriteMode mode) const { + KJ_IF_MAYBE(f, tryOpenFile(path, mode)) { + return kj::mv(*f); + } else if (has(mode, WriteMode::CREATE) && !has(mode, WriteMode::MODIFY)) { + KJ_FAIL_REQUIRE("file already exists", path) { break; } + } else if (has(mode, WriteMode::MODIFY) && !has(mode, WriteMode::CREATE)) { + KJ_FAIL_REQUIRE("file does not exist", path) { break; } + } else if (!has(mode, WriteMode::MODIFY) && !has(mode, WriteMode::CREATE)) { + KJ_FAIL_ASSERT("neither WriteMode::CREATE nor WriteMode::MODIFY was given", path) { break; } + } else { + // Shouldn't happen. + KJ_FAIL_ASSERT("tryOpenFile() returned null despite no preconditions", path) { break; } + } + return newInMemoryFile(nullClock()); +} + +Own Directory::appendFile(PathPtr path, WriteMode mode) const { + KJ_IF_MAYBE(f, tryAppendFile(path, mode)) { + return kj::mv(*f); + } else if (has(mode, WriteMode::CREATE) && !has(mode, WriteMode::MODIFY)) { + KJ_FAIL_REQUIRE("file already exists", path) { break; } + } else if (has(mode, WriteMode::MODIFY) && !has(mode, WriteMode::CREATE)) { + KJ_FAIL_REQUIRE("file does not exist", path) { break; } + } else if (!has(mode, WriteMode::MODIFY) && !has(mode, WriteMode::CREATE)) { + KJ_FAIL_ASSERT("neither WriteMode::CREATE nor WriteMode::MODIFY was given", path) { break; } + } else { + // Shouldn't happen. + KJ_FAIL_ASSERT("tryAppendFile() returned null despite no preconditions", path) { break; } + } + return newFileAppender(newInMemoryFile(nullClock())); +} + +Own Directory::openSubdir(PathPtr path, WriteMode mode) const { + KJ_IF_MAYBE(f, tryOpenSubdir(path, mode)) { + return kj::mv(*f); + } else if (has(mode, WriteMode::CREATE) && !has(mode, WriteMode::MODIFY)) { + KJ_FAIL_REQUIRE("directory already exists", path) { break; } + } else if (has(mode, WriteMode::MODIFY) && !has(mode, WriteMode::CREATE)) { + KJ_FAIL_REQUIRE("directory does not exist", path) { break; } + } else if (!has(mode, WriteMode::MODIFY) && !has(mode, WriteMode::CREATE)) { + KJ_FAIL_ASSERT("neither WriteMode::CREATE nor WriteMode::MODIFY was given", path) { break; } + } else { + // Shouldn't happen. + KJ_FAIL_ASSERT("tryOpenSubdir() returned null despite no preconditions", path) { break; } + } + return newInMemoryDirectory(nullClock()); +} + +void Directory::symlink(PathPtr linkpath, StringPtr content, WriteMode mode) const { + if (!trySymlink(linkpath, content, mode)) { + if (has(mode, WriteMode::CREATE)) { + KJ_FAIL_REQUIRE("path already exists", linkpath) { break; } + } else { + // Shouldn't happen. + KJ_FAIL_ASSERT("symlink() returned null despite no preconditions", linkpath) { break; } + } + } +} + +void Directory::transfer(PathPtr toPath, WriteMode toMode, + const Directory& fromDirectory, PathPtr fromPath, + TransferMode mode) const { + if (!tryTransfer(toPath, toMode, fromDirectory, fromPath, mode)) { + if (has(toMode, WriteMode::CREATE)) { + KJ_FAIL_REQUIRE("toPath already exists or fromPath doesn't exist", toPath, fromPath) { + break; + } + } else { + KJ_FAIL_ASSERT("fromPath doesn't exist", fromPath) { break; } + } + } +} + +static void copyContents(const Directory& to, const ReadableDirectory& from); + +static bool tryCopyDirectoryEntry(const Directory& to, PathPtr toPath, WriteMode toMode, + const ReadableDirectory& from, PathPtr fromPath, + FsNode::Type type, bool atomic) { + // TODO(cleanup): Make this reusable? + + switch (type) { + case FsNode::Type::FILE: { + KJ_IF_MAYBE(fromFile, from.tryOpenFile(fromPath)) { + if (atomic) { + auto replacer = to.replaceFile(toPath, toMode); + replacer->get().copy(0, **fromFile, 0, kj::maxValue); + return replacer->tryCommit(); + } else KJ_IF_MAYBE(toFile, to.tryOpenFile(toPath, toMode)) { + toFile->get()->copy(0, **fromFile, 0, kj::maxValue); + return true; + } else { + return false; + } + } else { + // Apparently disappeared. Treat as source-doesn't-exist. + return false; + } + } + case FsNode::Type::DIRECTORY: + KJ_IF_MAYBE(fromSubdir, from.tryOpenSubdir(fromPath)) { + if (atomic) { + auto replacer = to.replaceSubdir(toPath, toMode); + copyContents(replacer->get(), **fromSubdir); + return replacer->tryCommit(); + } else KJ_IF_MAYBE(toSubdir, to.tryOpenSubdir(toPath, toMode)) { + copyContents(**toSubdir, **fromSubdir); + return true; + } else { + return false; + } + } else { + // Apparently disappeared. Treat as source-doesn't-exist. + return false; + } + case FsNode::Type::SYMLINK: + KJ_IF_MAYBE(content, from.tryReadlink(fromPath)) { + return to.trySymlink(toPath, *content, toMode); + } else { + // Apparently disappeared. Treat as source-doesn't-exist. + return false; + } + break; + + default: + // Note: Unclear whether it's better to throw an error here or just ignore it / log a + // warning. Can reconsider when we see an actual use case. + KJ_FAIL_REQUIRE("can only copy files, directories, and symlinks", fromPath) { + return false; + } + } +} + +static void copyContents(const Directory& to, const ReadableDirectory& from) { + for (auto& entry: from.listEntries()) { + Path subPath(kj::mv(entry.name)); + tryCopyDirectoryEntry(to, subPath, WriteMode::CREATE, from, subPath, entry.type, false); + } +} + +bool Directory::tryTransfer(PathPtr toPath, WriteMode toMode, + const Directory& fromDirectory, PathPtr fromPath, + TransferMode mode) const { + KJ_REQUIRE(toPath.size() > 0, "can't replace self") { return false; } + + // First try reversing. + KJ_IF_MAYBE(result, fromDirectory.tryTransferTo(*this, toPath, toMode, fromPath, mode)) { + return *result; + } + + switch (mode) { + case TransferMode::COPY: + KJ_IF_MAYBE(meta, fromDirectory.tryLstat(fromPath)) { + return tryCopyDirectoryEntry(*this, toPath, toMode, fromDirectory, + fromPath, meta->type, true); + } else { + // Source doesn't exist. + return false; + } + case TransferMode::MOVE: + // Implement move as copy-then-delete. + if (!tryTransfer(toPath, toMode, fromDirectory, fromPath, TransferMode::COPY)) { + return false; + } + fromDirectory.remove(fromPath); + return true; + case TransferMode::LINK: + KJ_FAIL_REQUIRE("can't link across different Directory implementations") { return false; } + } + + KJ_UNREACHABLE; +} + +Maybe Directory::tryTransferTo(const Directory& toDirectory, PathPtr toPath, WriteMode toMode, + PathPtr fromPath, TransferMode mode) const { + return nullptr; +} + +void Directory::remove(PathPtr path) const { + if (!tryRemove(path)) { + KJ_FAIL_REQUIRE("path to remove doesn't exist", path) { break; } + } +} + +void Directory::commitFailed(WriteMode mode) { + if (has(mode, WriteMode::CREATE) && !has(mode, WriteMode::MODIFY)) { + KJ_FAIL_REQUIRE("replace target already exists") { break; } + } else if (has(mode, WriteMode::MODIFY) && !has(mode, WriteMode::CREATE)) { + KJ_FAIL_REQUIRE("replace target does not exist") { break; } + } else if (!has(mode, WriteMode::MODIFY) && !has(mode, WriteMode::CREATE)) { + KJ_FAIL_ASSERT("neither WriteMode::CREATE nor WriteMode::MODIFY was given") { break; } + } else { + KJ_FAIL_ASSERT("tryCommit() returned null despite no preconditions") { break; } + } +} + +// ======================================================================================= + +namespace { + +class InMemoryFile final: public File, public AtomicRefcounted { +public: + InMemoryFile(const Clock& clock): impl(clock) {} + + Own cloneFsNode() const override { + return atomicAddRef(*this); + } + + Maybe getFd() const override { + return nullptr; + } + + Metadata stat() const override { + auto lock = impl.lockShared(); + uint64_t hash = reinterpret_cast(this); + return Metadata { Type::FILE, lock->size, lock->size, lock->lastModified, 1, hash }; + } + + void sync() const override {} + void datasync() const override {} + // no-ops + + size_t read(uint64_t offset, ArrayPtr buffer) const override { + auto lock = impl.lockShared(); + if (offset >= lock->size) { + // Entirely out-of-range. + return 0; + } + + size_t readSize = kj::min(buffer.size(), lock->size - offset); + memcpy(buffer.begin(), lock->bytes.begin() + offset, readSize); + return readSize; + } + + Array mmap(uint64_t offset, uint64_t size) const override { + KJ_REQUIRE(offset + size >= offset, "mmap() request overflows uint64"); + auto lock = impl.lockExclusive(); + lock->ensureCapacity(offset + size); + + ArrayDisposer* disposer = new MmapDisposer(atomicAddRef(*this)); + return Array(lock->bytes.begin() + offset, size, *disposer); + } + + Array mmapPrivate(uint64_t offset, uint64_t size) const override { + // Return a copy. + + // Allocate exactly the size requested. + auto result = heapArray(size); + + // Use read() to fill it. + size_t actual = read(offset, result); + + // Ignore the rest. + if (actual < size) { + memset(result.begin() + actual, 0, size - actual); + } + + return result; + } + + void write(uint64_t offset, ArrayPtr data) const override { + if (data.size() == 0) return; + auto lock = impl.lockExclusive(); + lock->modified(); + uint64_t end = offset + data.size(); + KJ_REQUIRE(end >= offset, "write() request overflows uint64"); + lock->ensureCapacity(end); + lock->size = kj::max(lock->size, end); + memcpy(lock->bytes.begin() + offset, data.begin(), data.size()); + } + + void zero(uint64_t offset, uint64_t zeroSize) const override { + if (zeroSize == 0) return; + auto lock = impl.lockExclusive(); + lock->modified(); + uint64_t end = offset + zeroSize; + KJ_REQUIRE(end >= offset, "zero() request overflows uint64"); + lock->ensureCapacity(end); + lock->size = kj::max(lock->size, end); + memset(lock->bytes.begin() + offset, 0, zeroSize); + } + + void truncate(uint64_t newSize) const override { + auto lock = impl.lockExclusive(); + if (newSize < lock->size) { + lock->modified(); + memset(lock->bytes.begin() + newSize, 0, lock->size - newSize); + lock->size = newSize; + } else if (newSize > lock->size) { + lock->modified(); + lock->ensureCapacity(newSize); + lock->size = newSize; + } + } + + Own mmapWritable(uint64_t offset, uint64_t size) const override { + uint64_t end = offset + size; + KJ_REQUIRE(end >= offset, "mmapWritable() request overflows uint64"); + auto lock = impl.lockExclusive(); + lock->ensureCapacity(end); + return heap(atomicAddRef(*this), lock->bytes.slice(offset, end)); + } + + size_t copy(uint64_t offset, const ReadableFile& from, + uint64_t fromOffset, uint64_t copySize) const override { + size_t fromFileSize = from.stat().size; + if (fromFileSize <= fromOffset) return 0; + + // Clamp size to EOF. + copySize = kj::min(copySize, fromFileSize - fromOffset); + if (copySize == 0) return 0; + + auto lock = impl.lockExclusive(); + + // Allocate space for the copy. + uint64_t end = offset + copySize; + lock->ensureCapacity(end); + + // Read directly into our backing store. + size_t n = from.read(fromOffset, lock->bytes.slice(offset, end)); + lock->size = kj::max(lock->size, offset + n); + + lock->modified(); + return n; + } + +private: + struct Impl { + const Clock& clock; + Array bytes; + size_t size = 0; // bytes may be larger than this to accommodate mmaps + Date lastModified; + uint mmapCount = 0; // number of mappings outstanding + + Impl(const Clock& clock): clock(clock), lastModified(clock.now()) {} + + void ensureCapacity(size_t capacity) { + if (bytes.size() < capacity) { + KJ_ASSERT(mmapCount == 0, + "InMemoryFile cannot resize the file backing store while memory mappings exist."); + + auto newBytes = heapArray(kj::max(capacity, bytes.size() * 2)); + if (size > 0) { // placate ubsan; bytes.begin() might be null + memcpy(newBytes.begin(), bytes.begin(), size); + } + memset(newBytes.begin() + size, 0, newBytes.size() - size); + bytes = kj::mv(newBytes); + } + } + + void modified() { + lastModified = clock.now(); + } + }; + kj::MutexGuarded impl; + + class MmapDisposer final: public ArrayDisposer { + public: + MmapDisposer(Own&& refParam): ref(kj::mv(refParam)) { + ++ref->impl.getAlreadyLockedExclusive().mmapCount; + } + ~MmapDisposer() noexcept(false) { + --ref->impl.lockExclusive()->mmapCount; + } + + void disposeImpl(void* firstElement, size_t elementSize, size_t elementCount, + size_t capacity, void (*destroyElement)(void*)) const override { + delete this; + } + + private: + Own ref; + }; + + class WritableFileMappingImpl final: public WritableFileMapping { + public: + WritableFileMappingImpl(Own&& refParam, ArrayPtr range) + : ref(kj::mv(refParam)), range(range) { + ++ref->impl.getAlreadyLockedExclusive().mmapCount; + } + ~WritableFileMappingImpl() noexcept(false) { + --ref->impl.lockExclusive()->mmapCount; + } + + ArrayPtr get() const override { + // const_cast OK because WritableFileMapping does indeed provide a writable view despite + // being const itself. + return arrayPtr(const_cast(range.begin()), range.size()); + } + + void changed(ArrayPtr slice) const override { + ref->impl.lockExclusive()->modified(); + } + + void sync(ArrayPtr slice) const override { + ref->impl.lockExclusive()->modified(); + } + + private: + Own ref; + ArrayPtr range; + }; +}; + +// ----------------------------------------------------------------------------- + +class InMemoryDirectory final: public Directory, public AtomicRefcounted { +public: + InMemoryDirectory(const Clock& clock): impl(clock) {} + + Own cloneFsNode() const override { + return atomicAddRef(*this); + } + + Maybe getFd() const override { + return nullptr; + } + + Metadata stat() const override { + auto lock = impl.lockShared(); + uint64_t hash = reinterpret_cast(this); + return Metadata { Type::DIRECTORY, 0, 0, lock->lastModified, 1, hash }; + } + + void sync() const override {} + void datasync() const override {} + // no-ops + + Array listNames() const override { + auto lock = impl.lockShared(); + return KJ_MAP(e, lock->entries) { return heapString(e.first); }; + } + + Array listEntries() const override { + auto lock = impl.lockShared(); + return KJ_MAP(e, lock->entries) { + FsNode::Type type; + if (e.second.node.is()) { + type = FsNode::Type::SYMLINK; + } else if (e.second.node.is()) { + type = FsNode::Type::FILE; + } else { + KJ_ASSERT(e.second.node.is()); + type = FsNode::Type::DIRECTORY; + } + + return Entry { type, heapString(e.first) }; + }; + } + + bool exists(PathPtr path) const override { + if (path.size() == 0) { + return true; + } else if (path.size() == 1) { + auto lock = impl.lockShared(); + KJ_IF_MAYBE(entry, lock->tryGetEntry(path[0])) { + return exists(lock, *entry); + } else { + return false; + } + } else { + KJ_IF_MAYBE(subdir, tryGetParent(path[0])) { + return subdir->get()->exists(path.slice(1, path.size())); + } else { + return false; + } + } + } + + Maybe tryLstat(PathPtr path) const override { + if (path.size() == 0) { + return stat(); + } else if (path.size() == 1) { + auto lock = impl.lockShared(); + KJ_IF_MAYBE(entry, lock->tryGetEntry(path[0])) { + if (entry->node.is()) { + return entry->node.get().file->stat(); + } else if (entry->node.is()) { + return entry->node.get().directory->stat(); + } else if (entry->node.is()) { + auto& link = entry->node.get(); + uint64_t hash = reinterpret_cast(link.content.begin()); + return FsNode::Metadata { FsNode::Type::SYMLINK, 0, 0, link.lastModified, 1, hash }; + } else { + KJ_FAIL_ASSERT("unknown node type") { return nullptr; } + } + } else { + return nullptr; + } + } else { + KJ_IF_MAYBE(subdir, tryGetParent(path[0])) { + return subdir->get()->tryLstat(path.slice(1, path.size())); + } else { + return nullptr; + } + } + } + + Maybe> tryOpenFile(PathPtr path) const override { + if (path.size() == 0) { + KJ_FAIL_REQUIRE("not a file") { return nullptr; } + } else if (path.size() == 1) { + auto lock = impl.lockShared(); + KJ_IF_MAYBE(entry, lock->tryGetEntry(path[0])) { + return asFile(lock, *entry); + } else { + return nullptr; + } + } else { + KJ_IF_MAYBE(subdir, tryGetParent(path[0])) { + return subdir->get()->tryOpenFile(path.slice(1, path.size())); + } else { + return nullptr; + } + } + } + + Maybe> tryOpenSubdir(PathPtr path) const override { + if (path.size() == 0) { + return clone(); + } else if (path.size() == 1) { + auto lock = impl.lockShared(); + KJ_IF_MAYBE(entry, lock->tryGetEntry(path[0])) { + return asDirectory(lock, *entry); + } else { + return nullptr; + } + } else { + KJ_IF_MAYBE(subdir, tryGetParent(path[0])) { + return subdir->get()->tryOpenSubdir(path.slice(1, path.size())); + } else { + return nullptr; + } + } + } + + Maybe tryReadlink(PathPtr path) const override { + if (path.size() == 0) { + KJ_FAIL_REQUIRE("not a symlink") { return nullptr; } + } else if (path.size() == 1) { + auto lock = impl.lockShared(); + KJ_IF_MAYBE(entry, lock->tryGetEntry(path[0])) { + return asSymlink(lock, *entry); + } else { + return nullptr; + } + } else { + KJ_IF_MAYBE(subdir, tryGetParent(path[0])) { + return subdir->get()->tryReadlink(path.slice(1, path.size())); + } else { + return nullptr; + } + } + } + + Maybe> tryOpenFile(PathPtr path, WriteMode mode) const override { + if (path.size() == 0) { + if (has(mode, WriteMode::MODIFY)) { + KJ_FAIL_REQUIRE("not a file") { return nullptr; } + } else if (has(mode, WriteMode::CREATE)) { + return nullptr; // already exists (as a directory) + } else { + KJ_FAIL_REQUIRE("can't replace self") { return nullptr; } + } + } else if (path.size() == 1) { + auto lock = impl.lockExclusive(); + KJ_IF_MAYBE(entry, lock->openEntry(path[0], mode)) { + return asFile(lock, *entry, mode); + } else { + return nullptr; + } + } else { + KJ_IF_MAYBE(child, tryGetParent(path[0], mode)) { + return child->get()->tryOpenFile(path.slice(1, path.size()), mode); + } else { + return nullptr; + } + } + } + + Own> replaceFile(PathPtr path, WriteMode mode) const override { + if (path.size() == 0) { + KJ_FAIL_REQUIRE("can't replace self") { break; } + } else if (path.size() == 1) { + // don't need lock just to read the clock ref + return heap>(*this, path[0], + newInMemoryFile(impl.getWithoutLock().clock), mode); + } else { + KJ_IF_MAYBE(child, tryGetParent(path[0], mode)) { + return child->get()->replaceFile(path.slice(1, path.size()), mode); + } + } + return heap>(newInMemoryFile(impl.getWithoutLock().clock)); + } + + Maybe> tryOpenSubdir(PathPtr path, WriteMode mode) const override { + if (path.size() == 0) { + if (has(mode, WriteMode::MODIFY)) { + return atomicAddRef(*this); + } else if (has(mode, WriteMode::CREATE)) { + return nullptr; // already exists + } else { + KJ_FAIL_REQUIRE("can't replace self") { return nullptr; } + } + } else if (path.size() == 1) { + auto lock = impl.lockExclusive(); + KJ_IF_MAYBE(entry, lock->openEntry(path[0], mode)) { + return asDirectory(lock, *entry, mode); + } else { + return nullptr; + } + } else { + KJ_IF_MAYBE(child, tryGetParent(path[0], mode)) { + return child->get()->tryOpenSubdir(path.slice(1, path.size()), mode); + } else { + return nullptr; + } + } + } + + Own> replaceSubdir(PathPtr path, WriteMode mode) const override { + if (path.size() == 0) { + KJ_FAIL_REQUIRE("can't replace self") { break; } + } else if (path.size() == 1) { + // don't need lock just to read the clock ref + return heap>(*this, path[0], + newInMemoryDirectory(impl.getWithoutLock().clock), mode); + } else { + KJ_IF_MAYBE(child, tryGetParent(path[0], mode)) { + return child->get()->replaceSubdir(path.slice(1, path.size()), mode); + } + } + return heap>(newInMemoryDirectory(impl.getWithoutLock().clock)); + } + + Maybe> tryAppendFile(PathPtr path, WriteMode mode) const override { + if (path.size() == 0) { + if (has(mode, WriteMode::MODIFY)) { + KJ_FAIL_REQUIRE("not a file") { return nullptr; } + } else if (has(mode, WriteMode::CREATE)) { + return nullptr; // already exists (as a directory) + } else { + KJ_FAIL_REQUIRE("can't replace self") { return nullptr; } + } + } else if (path.size() == 1) { + auto lock = impl.lockExclusive(); + KJ_IF_MAYBE(entry, lock->openEntry(path[0], mode)) { + return asFile(lock, *entry, mode).map(newFileAppender); + } else { + return nullptr; + } + } else { + KJ_IF_MAYBE(child, tryGetParent(path[0], mode)) { + return child->get()->tryAppendFile(path.slice(1, path.size()), mode); + } else { + return nullptr; + } + } + } + + bool trySymlink(PathPtr path, StringPtr content, WriteMode mode) const override { + if (path.size() == 0) { + if (has(mode, WriteMode::CREATE)) { + return false; + } else { + KJ_FAIL_REQUIRE("can't replace self") { return false; } + } + } else if (path.size() == 1) { + auto lock = impl.lockExclusive(); + KJ_IF_MAYBE(entry, lock->openEntry(path[0], mode)) { + entry->init(SymlinkNode { lock->clock.now(), heapString(content) }); + lock->modified(); + return true; + } else { + return false; + } + } else { + KJ_IF_MAYBE(child, tryGetParent(path[0], mode)) { + return child->get()->trySymlink(path.slice(1, path.size()), content, mode); + } else { + KJ_FAIL_REQUIRE("couldn't create parent directory") { return false; } + } + } + } + + Own createTemporary() const override { + // Don't need lock just to read the clock ref. + return newInMemoryFile(impl.getWithoutLock().clock); + } + + bool tryTransfer(PathPtr toPath, WriteMode toMode, + const Directory& fromDirectory, PathPtr fromPath, + TransferMode mode) const override { + if (toPath.size() == 0) { + if (has(toMode, WriteMode::CREATE)) { + return false; + } else { + KJ_FAIL_REQUIRE("can't replace self") { return false; } + } + } else if (toPath.size() == 1) { + // tryTransferChild() needs to at least know the node type, so do an lstat. + KJ_IF_MAYBE(meta, fromDirectory.tryLstat(fromPath)) { + auto lock = impl.lockExclusive(); + KJ_IF_MAYBE(entry, lock->openEntry(toPath[0], toMode)) { + // Make sure if we just cerated a new entry, and we don't successfully transfer to it, we + // remove the entry before returning. + bool needRollback = entry->node == nullptr; + KJ_DEFER(if (needRollback) { lock->entries.erase(toPath[0]); }); + + if (lock->tryTransferChild(*entry, meta->type, meta->lastModified, meta->size, + fromDirectory, fromPath, mode)) { + lock->modified(); + needRollback = false; + return true; + } else { + KJ_FAIL_REQUIRE("InMemoryDirectory can't link an inode of this type", fromPath) { + return false; + } + } + } else { + return false; + } + } else { + return false; + } + } else { + // TODO(someday): Ideally we wouldn't create parent directories if fromPath doesn't exist. + // This requires a different approach to the code here, though. + KJ_IF_MAYBE(child, tryGetParent(toPath[0], toMode)) { + return child->get()->tryTransfer( + toPath.slice(1, toPath.size()), toMode, fromDirectory, fromPath, mode); + } else { + return false; + } + } + } + + Maybe tryTransferTo(const Directory& toDirectory, PathPtr toPath, WriteMode toMode, + PathPtr fromPath, TransferMode mode) const override { + if (fromPath.size() <= 1) { + // If `fromPath` is in this directory (or *is* this directory) then we don't have any + // optimizations. + return nullptr; + } + + // `fromPath` is in a subdirectory. It could turn out that that subdirectory is not an + // InMemoryDirectory and is instead something `toDirectory` is friendly with. So let's follow + // the path. + + KJ_IF_MAYBE(child, tryGetParent(fromPath[0], WriteMode::MODIFY)) { + // OK, switch back to tryTransfer() but use the subdirectory. + return toDirectory.tryTransfer(toPath, toMode, + **child, fromPath.slice(1, fromPath.size()), mode); + } else { + // Hmm, doesn't exist. Fall back to standard path. + return nullptr; + } + } + + bool tryRemove(PathPtr path) const override { + if (path.size() == 0) { + KJ_FAIL_REQUIRE("can't remove self from self") { return false; } + } else if (path.size() == 1) { + auto lock = impl.lockExclusive(); + auto iter = lock->entries.find(path[0]); + if (iter == lock->entries.end()) { + return false; + } else { + lock->entries.erase(iter); + lock->modified(); + return true; + } + } else { + KJ_IF_MAYBE(child, tryGetParent(path[0], WriteMode::MODIFY)) { + return child->get()->tryRemove(path.slice(1, path.size())); + } else { + return false; + } + } + } + +private: + struct FileNode { + Own file; + }; + struct DirectoryNode { + Own directory; + }; + struct SymlinkNode { + Date lastModified; + String content; + + Path parse() const { + KJ_CONTEXT("parsing symlink", content); + return Path::parse(content); + } + }; + + struct EntryImpl { + String name; + OneOf node; + + EntryImpl(String&& name): name(kj::mv(name)) {} + + Own init(FileNode&& value) { + return node.init(kj::mv(value)).file->clone(); + } + Own init(DirectoryNode&& value) { + return node.init(kj::mv(value)).directory->clone(); + } + void init(SymlinkNode&& value) { + node.init(kj::mv(value)); + } + bool init(OneOf&& value) { + node = kj::mv(value); + return node != nullptr; + } + + void set(Own&& value) { + node.init(FileNode { kj::mv(value) }); + } + void set(Own&& value) { + node.init(DirectoryNode { kj::mv(value) }); + } + }; + + template + class ReplacerImpl final: public Replacer { + public: + ReplacerImpl(const InMemoryDirectory& directory, kj::StringPtr name, + Own inner, WriteMode mode) + : Replacer(mode), directory(atomicAddRef(directory)), name(heapString(name)), + inner(kj::mv(inner)) {} + + const T& get() override { return *inner; } + + bool tryCommit() override { + KJ_REQUIRE(!committed, "commit() already called") { return true; } + + auto lock = directory->impl.lockExclusive(); + KJ_IF_MAYBE(entry, lock->openEntry(name, Replacer::mode)) { + entry->set(inner->clone()); + lock->modified(); + return true; + } else { + return false; + } + } + + private: + bool committed = false; + Own directory; + kj::String name; + Own inner; + }; + + template + class BrokenReplacer final: public Replacer { + // For recovery path when exceptions are disabled. + + public: + BrokenReplacer(Own inner) + : Replacer(WriteMode::CREATE | WriteMode::MODIFY), + inner(kj::mv(inner)) {} + + const T& get() override { return *inner; } + bool tryCommit() override { return false; } + + private: + Own inner; + }; + + struct Impl { + const Clock& clock; + + std::map entries; + // Note: If this changes to a non-sorted map, listNames() and listEntries() must be updated to + // sort their results. + + Date lastModified; + + Impl(const Clock& clock): clock(clock), lastModified(clock.now()) {} + + Maybe openEntry(kj::StringPtr name, WriteMode mode) { + // TODO(perf): We could avoid a copy if the entry exists, at the expense of a double-lookup + // if it doesn't. Maybe a better map implementation will solve everything? + return openEntry(heapString(name), mode); + } + + Maybe openEntry(String&& name, WriteMode mode) { + if (has(mode, WriteMode::CREATE)) { + EntryImpl entry(kj::mv(name)); + StringPtr nameRef = entry.name; + auto insertResult = entries.insert(std::make_pair(nameRef, kj::mv(entry))); + + if (!insertResult.second && !has(mode, WriteMode::MODIFY)) { + // Entry already existed and MODIFY not specified. + return nullptr; + } + + return insertResult.first->second; + } else if (has(mode, WriteMode::MODIFY)) { + return tryGetEntry(name); + } else { + // Neither CREATE nor MODIFY specified: precondition always fails. + return nullptr; + } + } + + kj::Maybe tryGetEntry(kj::StringPtr name) const { + auto iter = entries.find(name); + if (iter == entries.end()) { + return nullptr; + } else { + return iter->second; + } + } + + kj::Maybe tryGetEntry(kj::StringPtr name) { + auto iter = entries.find(name); + if (iter == entries.end()) { + return nullptr; + } else { + return iter->second; + } + } + + void modified() { + lastModified = clock.now(); + } + + bool tryTransferChild(EntryImpl& entry, const FsNode::Type type, kj::Maybe lastModified, + kj::Maybe size, const Directory& fromDirectory, + PathPtr fromPath, TransferMode mode) { + switch (type) { + case FsNode::Type::FILE: + KJ_IF_MAYBE(file, fromDirectory.tryOpenFile(fromPath, WriteMode::MODIFY)) { + if (mode == TransferMode::COPY) { + auto copy = newInMemoryFile(clock); + copy->copy(0, **file, 0, size.orDefault(kj::maxValue)); + entry.set(kj::mv(copy)); + } else { + if (mode == TransferMode::MOVE) { + KJ_ASSERT(fromDirectory.tryRemove(fromPath), "couldn't move node", fromPath) { + return false; + } + } + entry.set(kj::mv(*file)); + } + return true; + } else { + KJ_FAIL_ASSERT("source node deleted concurrently during transfer", fromPath) { + return false; + } + } + case FsNode::Type::DIRECTORY: + KJ_IF_MAYBE(subdir, fromDirectory.tryOpenSubdir(fromPath, WriteMode::MODIFY)) { + if (mode == TransferMode::COPY) { + auto copy = atomicRefcounted(clock); + auto& cpim = copy->impl.getWithoutLock(); // safe because just-created + for (auto& subEntry: subdir->get()->listEntries()) { + EntryImpl newEntry(kj::mv(subEntry.name)); + Path filename(newEntry.name); + if (!cpim.tryTransferChild(newEntry, subEntry.type, nullptr, nullptr, **subdir, + filename, TransferMode::COPY)) { + KJ_LOG(ERROR, "couldn't copy node of type not supported by InMemoryDirectory", + filename); + } else { + StringPtr nameRef = newEntry.name; + cpim.entries.insert(std::make_pair(nameRef, kj::mv(newEntry))); + } + } + entry.set(kj::mv(copy)); + } else { + if (mode == TransferMode::MOVE) { + KJ_ASSERT(fromDirectory.tryRemove(fromPath), "couldn't move node", fromPath) { + return false; + } + } + entry.set(kj::mv(*subdir)); + } + return true; + } else { + KJ_FAIL_ASSERT("source node deleted concurrently during transfer", fromPath) { + return false; + } + } + case FsNode::Type::SYMLINK: + KJ_IF_MAYBE(content, fromDirectory.tryReadlink(fromPath)) { + // Since symlinks are immutable, we can implement LINK the same as COPY. + entry.init(SymlinkNode { lastModified.orDefault(clock.now()), kj::mv(*content) }); + if (mode == TransferMode::MOVE) { + KJ_ASSERT(fromDirectory.tryRemove(fromPath), "couldn't move node", fromPath) { + return false; + } + } + return true; + } else { + KJ_FAIL_ASSERT("source node deleted concurrently during transfer", fromPath) { + return false; + } + } + default: + return false; + } + } + }; + + kj::MutexGuarded impl; + + bool exists(kj::Locked& lock, const EntryImpl& entry) const { + if (entry.node.is()) { + auto newPath = entry.node.get().parse(); + lock.release(); + return exists(newPath); + } else { + return true; + } + } + Maybe> asFile( + kj::Locked& lock, const EntryImpl& entry) const { + if (entry.node.is()) { + return entry.node.get().file->clone(); + } else if (entry.node.is()) { + auto newPath = entry.node.get().parse(); + lock.release(); + return tryOpenFile(newPath); + } else { + KJ_FAIL_REQUIRE("not a file") { return nullptr; } + } + } + Maybe> asDirectory( + kj::Locked& lock, const EntryImpl& entry) const { + if (entry.node.is()) { + return entry.node.get().directory->clone(); + } else if (entry.node.is()) { + auto newPath = entry.node.get().parse(); + lock.release(); + return tryOpenSubdir(newPath); + } else { + KJ_FAIL_REQUIRE("not a directory") { return nullptr; } + } + } + Maybe asSymlink(kj::Locked& lock, const EntryImpl& entry) const { + if (entry.node.is()) { + return heapString(entry.node.get().content); + } else { + KJ_FAIL_REQUIRE("not a symlink") { return nullptr; } + } + } + + Maybe> asFile(kj::Locked& lock, EntryImpl& entry, WriteMode mode) const { + if (entry.node.is()) { + return entry.node.get().file->clone(); + } else if (entry.node.is()) { + // CREATE_PARENT doesn't apply to creating the parents of a symlink target. However, the + // target itself can still be created. + auto newPath = entry.node.get().parse(); + lock.release(); + return tryOpenFile(newPath, mode - WriteMode::CREATE_PARENT); + } else if (entry.node == nullptr) { + KJ_ASSERT(has(mode, WriteMode::CREATE)); + lock->modified(); + return entry.init(FileNode { newInMemoryFile(lock->clock) }); + } else { + KJ_FAIL_REQUIRE("not a file") { return nullptr; } + } + } + Maybe> asDirectory( + kj::Locked& lock, EntryImpl& entry, WriteMode mode) const { + if (entry.node.is()) { + return entry.node.get().directory->clone(); + } else if (entry.node.is()) { + // CREATE_PARENT doesn't apply to creating the parents of a symlink target. However, the + // target itself can still be created. + auto newPath = entry.node.get().parse(); + lock.release(); + return tryOpenSubdir(newPath, mode - WriteMode::CREATE_PARENT); + } else if (entry.node == nullptr) { + KJ_ASSERT(has(mode, WriteMode::CREATE)); + lock->modified(); + return entry.init(DirectoryNode { newInMemoryDirectory(lock->clock) }); + } else { + KJ_FAIL_REQUIRE("not a directory") { return nullptr; } + } + } + + kj::Maybe> tryGetParent(kj::StringPtr name) const { + auto lock = impl.lockShared(); + KJ_IF_MAYBE(entry, impl.lockShared()->tryGetEntry(name)) { + return asDirectory(lock, *entry); + } else { + return nullptr; + } + } + + kj::Maybe> tryGetParent(kj::StringPtr name, WriteMode mode) const { + // Get a directory which is a parent of the eventual target. If `mode` includes + // WriteMode::CREATE_PARENTS, possibly create the parent directory. + + auto lock = impl.lockExclusive(); + + WriteMode parentMode = has(mode, WriteMode::CREATE) && has(mode, WriteMode::CREATE_PARENT) + ? WriteMode::CREATE | WriteMode::MODIFY // create parent + : WriteMode::MODIFY; // don't create parent + + // Possibly create parent. + KJ_IF_MAYBE(entry, lock->openEntry(name, parentMode)) { + if (entry->node.is()) { + return entry->node.get().directory->clone(); + } else if (entry->node == nullptr) { + lock->modified(); + return entry->init(DirectoryNode { newInMemoryDirectory(lock->clock) }); + } + // Continue on. + } + + if (has(mode, WriteMode::CREATE)) { + // CREATE is documented as returning null when the file already exists. In this case, the + // file does NOT exist because the parent directory does not exist or is not a directory. + KJ_FAIL_REQUIRE("parent is not a directory") { return nullptr; } + } else { + return nullptr; + } + } +}; + +// ----------------------------------------------------------------------------- + +class AppendableFileImpl final: public AppendableFile { +public: + AppendableFileImpl(Own&& fileParam): file(kj::mv(fileParam)) {} + + Own cloneFsNode() const override { + return heap(file->clone()); + } + + Maybe getFd() const override { + return nullptr; + } + + Metadata stat() const override { + return file->stat(); + } + + void sync() const override { file->sync(); } + void datasync() const override { file->datasync(); } + + void write(const void* buffer, size_t size) override { + file->write(file->stat().size, arrayPtr(reinterpret_cast(buffer), size)); + } + +private: + Own file; +}; + +} // namespace + +// ----------------------------------------------------------------------------- + +Own newInMemoryFile(const Clock& clock) { + return atomicRefcounted(clock); +} +Own newInMemoryDirectory(const Clock& clock) { + return atomicRefcounted(clock); +} +Own newFileAppender(Own inner) { + return heap(kj::mv(inner)); +} + +} // namespace kj diff --git a/vendor/capnproto/src/kj/filesystem.h b/vendor/capnproto/src/kj/filesystem.h new file mode 100644 index 0000000..f38d739 --- /dev/null +++ b/vendor/capnproto/src/kj/filesystem.h @@ -0,0 +1,1028 @@ +// 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. + +#pragma once + +#include "memory.h" +#include "io.h" +#include +#include "time.h" +#include "function.h" +#include "hash.h" + +KJ_BEGIN_HEADER + +namespace kj { + +template +class Vector; + +class PathPtr; + +class Path { + // A Path identifies a file in a directory tree. + // + // In KJ, we avoid representing paths as plain strings because this can lead to path injection + // bugs as well as numerous kinds of bugs relating to path parsing edge cases. The Path class's + // interface is designed to "make it hard to screw up". + // + // A "Path" is in fact a list of strings, each string being one component of the path (as would + // normally be separated by '/'s). Path components are not allowed to contain '/' nor '\0', nor + // are they allowed to be the special names "", ".", nor "..". + // + // If you explicitly want to parse a path that contains '/'s, ".", and "..", you must use + // parse() and/or eval(). However, users of this interface are encouraged to avoid parsing + // paths at all, and instead express paths as string arrays. + // + // Note that when using the Path class, ".." is always canonicalized in path space without + // consulting the actual filesystem. This means that "foo/some-symlink/../bar" is exactly + // equivalent to "foo/bar". This differs from the kernel's behavior when resolving paths passed + // to system calls: the kernel would have resolved "some-symlink" to its target physical path, + // and then would have interpreted ".." relative to that. In practice, the kernel's behavior is + // rarely what the user or programmer intended, hence canonicalizing in path space produces a + // better result. + // + // Path objects are "immutable": functions that "modify" the path return a new path. However, + // if the path being operated on is an rvalue, copying can be avoided. Hence it makes sense to + // write code like: + // + // Path p = ...; + // p = kj::mv(p).append("bar"); // in-place update, avoids string copying + +public: + Path(decltype(nullptr)); // empty path + + explicit Path(StringPtr name); + explicit Path(String&& name); + // Create a Path containing only one component. `name` is a single filename; it cannot contain + // '/' nor '\0' nor can it be exactly "" nor "." nor "..". + // + // If you want to allow '/'s and such, you must call Path::parse(). We force you to do this to + // prevent path injection bugs where you didn't consider what would happen if the path contained + // a '/'. + + explicit Path(std::initializer_list parts); + explicit Path(ArrayPtr parts); + explicit Path(Array parts); + // Construct a path from an array. Note that this means you can do: + // + // Path{"foo", "bar", "baz"} // equivalent to Path::parse("foo/bar/baz") + + KJ_DISALLOW_COPY(Path); + Path(Path&&) = default; + Path& operator=(Path&&) = default; + + Path clone() const; + + static Path parse(StringPtr path); + // Parses a path in traditional format. Components are separated by '/'. Any use of "." or + // ".." will be canonicalized (if they can't be canonicalized, e.g. because the path starts with + // "..", an exception is thrown). Multiple consecutive '/'s will be collapsed. A leading '/' + // is NOT accepted -- if that is a problem, you probably want `eval()`. Trailing '/'s are + // ignored. + + Path append(Path&& suffix) const&; + Path append(Path&& suffix) &&; + Path append(PathPtr suffix) const&; + Path append(PathPtr suffix) &&; + Path append(StringPtr suffix) const&; + Path append(StringPtr suffix) &&; + Path append(String&& suffix) const&; + Path append(String&& suffix) &&; + // Create a new path by appending the given path to this path. + // + // `suffix` cannot contain '/' characters. Instead, you can append an array: + // + // path.append({"foo", "bar"}) + // + // Or, use Path::parse(): + // + // path.append(Path::parse("foo//baz/../bar")) + + Path eval(StringPtr pathText) const&; + Path eval(StringPtr pathText) &&; + // Evaluates a traditional path relative to this one. `pathText` is parsed like `parse()` would, + // except that: + // - It can contain leading ".." components that traverse up the tree. + // - It can have a leading '/' which completely replaces the current path. + // + // THE NAME OF THIS METHOD WAS CHOSEN TO INSPIRE FEAR. + // + // Instead of using `path.eval(str)`, always consider whether you really want + // `path.append(Path::parse(str))`. The former is much riskier than the latter in terms of path + // injection vulnerabilities. + + PathPtr basename() const&; + Path basename() &&; + // Get the last component of the path. (Use `basename()[0]` to get just the string.) + + PathPtr parent() const&; + Path parent() &&; + // Get the parent path. + + String toString(bool absolute = false) const; + // Converts the path to a traditional path string, appropriate to pass to a unix system call. + // Never throws. + + const String& operator[](size_t i) const&; + String operator[](size_t i) &&; + size_t size() const; + const String* begin() const; + const String* end() const; + PathPtr slice(size_t start, size_t end) const&; + Path slice(size_t start, size_t end) &&; + // A Path can be accessed as an array of strings. + + bool operator==(PathPtr other) const; + bool operator!=(PathPtr other) const; + bool operator< (PathPtr other) const; + bool operator> (PathPtr other) const; + bool operator<=(PathPtr other) const; + bool operator>=(PathPtr other) const; + // Compare path components lexically. + + bool operator==(const Path& other) const; + bool operator!=(const Path& other) const; + bool operator< (const Path& other) const; + bool operator> (const Path& other) const; + bool operator<=(const Path& other) const; + bool operator>=(const Path& other) const; + + uint hashCode() const; + // Can use in HashMap. + + bool startsWith(PathPtr prefix) const; + bool endsWith(PathPtr suffix) const; + // Compare prefix / suffix. + + Path evalNative(StringPtr pathText) const&; + Path evalNative(StringPtr pathText) &&; + // Alias for eval(). Use this when you are + // parsing a path provided by a user and you want the user to be able to use the "natural" format + // for their platform. + + String toNativeString(bool absolute = false) const; + // Alias for toString(). Use this when + // you are formatting a path to display to a user and you want to present it in the "natural" + // format for the user's platform. + +private: + Array parts; + + // TODO(perf): Consider unrolling one element from `parts`, so that a one-element path doesn't + // require allocation of an array. + + enum { ALREADY_CHECKED }; + Path(Array parts, decltype(ALREADY_CHECKED)); + + friend class PathPtr; + + static String stripNul(String input); + static void validatePart(StringPtr part); + static void evalPart(Vector& parts, ArrayPtr part); + static Path evalImpl(Vector&& parts, StringPtr path); + static size_t countParts(StringPtr path); +}; + +class PathPtr { + // Points to a Path or a slice of a Path, but doesn't own it. + // + // PathPtr is to Path as ArrayPtr is to Array and StringPtr is to String. + +public: + PathPtr(decltype(nullptr)); + PathPtr(const Path& path); + + Path clone(); + Path append(Path&& suffix) const; + Path append(PathPtr suffix) const; + Path append(StringPtr suffix) const; + Path append(String&& suffix) const; + Path eval(StringPtr pathText) const; + PathPtr basename() const; + PathPtr parent() const; + String toString(bool absolute = false) const; + const String& operator[](size_t i) const; + size_t size() const; + const String* begin() const; + const String* end() const; + PathPtr slice(size_t start, size_t end) const; + bool operator==(PathPtr other) const; + bool operator!=(PathPtr other) const; + bool operator< (PathPtr other) const; + bool operator> (PathPtr other) const; + bool operator<=(PathPtr other) const; + bool operator>=(PathPtr other) const; + uint hashCode() const; + bool startsWith(PathPtr prefix) const; + bool endsWith(PathPtr suffix) const; + Path evalNative(StringPtr pathText) const; + String toNativeString(bool absolute = false) const; + // Equivalent to the corresponding methods of `Path`. + +private: + ArrayPtr parts; + + explicit PathPtr(ArrayPtr parts); + + + friend class Path; +}; + +// ======================================================================================= +// The filesystem API +// +// This API is strictly synchronous because, unfortunately, there's no such thing as asynchronous +// filesystem access in practice. The filesystem drivers on Linux are written to assume they can +// block. The AIO API is only actually asynchronous for reading/writing the raw file blocks, but if +// the filesystem needs to be involved (to allocate blocks, update metadata, etc.) that will block. +// It's best to imagine that the filesystem is just another tier of memory that happens to be +// slower than RAM (which is slower than L3 cache, which is slower than L2, which is slower than +// L1). You can't do asynchronous RAM access so why asynchronous filesystem? The only way to +// parallelize these is using threads. +// +// All KJ filesystem objects are thread-safe, and so all methods are marked "const" (even write +// methods). Of course, if you concurrently write the same bytes of a file from multiple threads, +// it's unspecified which write will "win". + +class FsNode { + // Base class for filesystem node types. + +public: + Own clone() const; + // Creates a new object of exactly the same type as this one, pointing at exactly the same + // external object. + // + // Under the hood, this will call dup(), so the FD number will not be the same. + + virtual Maybe getFd() const { return nullptr; } + // Get the underlying Unix file descriptor, if any. Returns nullptr if this object actually isn't + // wrapping a file descriptor. + + enum class Type { + FILE, + DIRECTORY, + SYMLINK, + BLOCK_DEVICE, + CHARACTER_DEVICE, + NAMED_PIPE, + SOCKET, + OTHER, + }; + + struct Metadata { + Type type = Type::FILE; + + uint64_t size = 0; + // Logical size of the file. + + uint64_t spaceUsed = 0; + // Physical size of the file on disk. May be smaller for sparse files, or larger for + // pre-allocated files. + + Date lastModified = UNIX_EPOCH; + // Last modification time of the file. + + uint linkCount = 1; + // Number of hard links pointing to this node. + + uint64_t hashCode = 0; + // Hint which can be used to determine if two FsNode instances point to the same underlying + // file object. If two FsNodes report different hashCodes, then they are not the same object. + // If they report the same hashCode, then they may or may not be the same object. + // + // The Unix filesystem implementation builds the hashCode based on st_dev and st_ino of + // `struct stat`. However, note that some filesystems -- especially FUSE-based -- may not fill + // in st_ino. + // + // The Windows filesystem implementation builds the hashCode based on dwVolumeSerialNumber and + // dwFileIndex{Low,High} of the BY_HANDLE_FILE_INFORMATION structure. However, these are again + // not guaranteed to be unique on all filesystems. In particular the documentation says that + // ReFS uses 128-bit identifiers which can't be represented here, and again virtual filesystems + // may often not report real identifiers. + // + // Of course, the process of hashing values into a single hash code can also cause collisions + // even if the filesystem reports reliable information. + // + // Additionally note that this value is not reliable when returned by `lstat()`. You should + // actually open the object, then call `stat()` on the opened object. + + // Not currently included: + // - Access control info: Differs wildly across platforms, and KJ prefers capabilities anyway. + // - Other timestamps: Differs across platforms. + // - Device number: If you care, you're probably doing platform-specific stuff anyway. + + Metadata() = default; + Metadata(Type type, uint64_t size, uint64_t spaceUsed, Date lastModified, uint linkCount, + uint64_t hashCode) + : type(type), size(size), spaceUsed(spaceUsed), lastModified(lastModified), + linkCount(linkCount), hashCode(hashCode) {} + // TODO(cleanup): This constructor is redundant in C++14, but needed in C++11. + }; + + virtual Metadata stat() const = 0; + + virtual void sync() const = 0; + virtual void datasync() const = 0; + // Maps to fsync() and fdatasync() system calls. + // + // Also, when creating or overwriting a file, the first call to sync() atomically links the file + // into the filesystem (*after* syncing the data), so than incomplete data is never visible to + // other processes. (In practice this works by writing into a temporary file and then rename()ing + // it.) + +protected: + virtual Own cloneFsNode() const = 0; + // Implements clone(). Required to return an object with exactly the same type as this one. + // Hence, every subclass must implement this. +}; + +class ReadableFile: public FsNode { +public: + Own clone() const; + + String readAllText() const; + // Read all text in the file and return as a big string. + + Array readAllBytes() const; + // Read all bytes in the file and return as a big byte array. + // + // This differs from mmap() in that the read is performed all at once. Future changes to the file + // do not affect the returned copy. Consider using mmap() instead, particularly for large files. + + virtual size_t read(uint64_t offset, ArrayPtr buffer) const = 0; + // Fills `buffer` with data starting at `offset`. Returns the number of bytes actually read -- + // the only time this is less than `buffer.size()` is when EOF occurs mid-buffer. + + virtual Array mmap(uint64_t offset, uint64_t size) const = 0; + // Maps the file to memory read-only. The returned array always has exactly the requested size. + // Depending on the capabilities of the OS and filesystem, the mapping may or may not reflect + // changes that happen to the file after mmap() returns. + // + // Multiple calls to mmap() on the same file may or may not return the same mapping (it is + // immutable, so there's no possibility of interference). + // + // If the file cannot be mmap()ed, an implementation may choose to allocate a buffer on the heap, + // read into it, and return that. This should only happen if a real mmap() is impossible. + // + // The returned array is always exactly the size requested. However, accessing bytes beyond the + // current end of the file may raise SIGBUS, or may simply return zero. + + virtual Array mmapPrivate(uint64_t offset, uint64_t size) const = 0; + // Like mmap() but returns a view that the caller can modify. Modifications will not be written + // to the underlying file. Every call to this method returns a unique mapping. Changes made to + // the underlying file by other clients may or may not be reflected in the mapping -- in fact, + // some changes may be reflected while others aren't, even within the same mapping. + // + // In practice this is often implemented using copy-on-write pages. When you first write to a + // page, a copy is made. Hence, changes to the underlying file within that page stop being + // reflected in the mapping. +}; + +class AppendableFile: public FsNode, public OutputStream { +public: + Own clone() const; + + // All methods are inherited. +}; + +class WritableFileMapping { +public: + virtual ArrayPtr get() const = 0; + // Gets the mapped bytes. The returned array can be modified, and those changes may be written to + // the underlying file, but there is no guarantee that they are written unless you subsequently + // call changed(). + + virtual void changed(ArrayPtr slice) const = 0; + // Notifies the implementation that the given bytes have changed. For some implementations this + // may be a no-op while for others it may be necessary in order for the changes to be written + // back at all. + // + // `slice` must be a slice of `bytes()`. + + virtual void sync(ArrayPtr slice) const = 0; + // Implies `changed()`, and then waits until the range has actually been written to disk before + // returning. + // + // `slice` must be a slice of `bytes()`. + // + // On Windows, this calls FlushViewOfFile(). The documentation for this function implies that in + // some circumstances, to fully sync to physical disk, you may need to call FlushFileBuffers() on + // the file HANDLE as well. The documentation is not very clear on when and why this is needed. + // If you believe your program needs this, you can accomplish it by calling `.sync()` on the File + // object after calling `.sync()` on the WritableFileMapping. +}; + +class File: public ReadableFile { +public: + Own clone() const; + + void writeAll(ArrayPtr bytes) const; + void writeAll(StringPtr text) const; + // Completely replace the file with the given bytes or text. + + virtual void write(uint64_t offset, ArrayPtr data) const = 0; + // Write the given data starting at the given offset in the file. + + virtual void zero(uint64_t offset, uint64_t size) const = 0; + // Write zeros to the file, starting at `offset` and continuing for `size` bytes. If the platform + // supports it, this will "punch a hole" in the file, such that blocks that are entirely zeros + // do not take space on disk. + + virtual void truncate(uint64_t size) const = 0; + // Set the file end pointer to `size`. If `size` is less than the current size, data past the end + // is truncated. If `size` is larger than the current size, zeros are added to the end of the + // file. If the platform supports it, blocks containing all-zeros will not be stored to disk. + + virtual Own mmapWritable(uint64_t offset, uint64_t size) const = 0; + // Like ReadableFile::mmap() but returns a mapping for which any changes will be immediately + // visible in other mappings of the file on the same system and will eventually be written back + // to the file. + + virtual size_t copy(uint64_t offset, const ReadableFile& from, uint64_t fromOffset, + uint64_t size) const; + // Copies bytes from one file to another. + // + // Copies `size` bytes or to EOF, whichever comes first. Returns the number of bytes actually + // copied. Hint: Pass kj::maxValue for `size` to always copy to EOF. + // + // The copy is not atomic. Concurrent writes may lead to garbage results. + // + // The default implementation performs a series of reads and writes. Subclasses can often provide + // superior implementations that offload the work to the OS or even implement copy-on-write. +}; + +class ReadableDirectory: public FsNode { + // Read-only subset of `Directory`. + +public: + Own clone() const; + + virtual Array listNames() const = 0; + // List the contents of this directory. Does NOT include "." nor "..". + + struct Entry { + FsNode::Type type; + String name; + + inline bool operator< (const Entry& other) const { return name < other.name; } + inline bool operator> (const Entry& other) const { return name > other.name; } + inline bool operator<=(const Entry& other) const { return name <= other.name; } + inline bool operator>=(const Entry& other) const { return name >= other.name; } + // Convenience comparison operators to sort entries by name. + }; + + virtual Array listEntries() const = 0; + // List the contents of the directory including the type of each file. On some platforms and + // filesystems, this is just as fast as listNames(), but on others it may require stat()ing each + // file. + + virtual bool exists(PathPtr path) const = 0; + // Does the specified path exist? + // + // If the path is a symlink, the symlink is followed and the return value indicates if the target + // exists. If you want to know if the symlink exists, use lstat(). (This implies that listNames() + // may return names for which exists() reports false.) + + FsNode::Metadata lstat(PathPtr path) const; + virtual Maybe tryLstat(PathPtr path) const = 0; + // Gets metadata about the path. If the path is a symlink, it is not followed -- the metadata + // describes the symlink itself. `tryLstat()` returns null if the path doesn't exist. + + Own openFile(PathPtr path) const; + virtual Maybe> tryOpenFile(PathPtr path) const = 0; + // Open a file for reading. + // + // `tryOpenFile()` returns null if the path doesn't exist. Other errors still throw exceptions. + + Own openSubdir(PathPtr path) const; + virtual Maybe> tryOpenSubdir(PathPtr path) const = 0; + // Opens a subdirectory. + // + // `tryOpenSubdir()` returns null if the path doesn't exist. Other errors still throw exceptions. + + String readlink(PathPtr path) const; + virtual Maybe tryReadlink(PathPtr path) const = 0; + // If `path` is a symlink, reads and returns the link contents. + // + // Note that tryReadlink() differs subtly from tryOpen*(). For example, tryOpenFile() throws if + // the path is not a file (e.g. if it's a directory); it only returns null if the path doesn't + // exist at all. tryReadlink() returns null if either the path doesn't exist, or if it does exist + // but isn't a symlink. This is because if it were to throw instead, then almost every real-world + // use case of tryReadlink() would be forced to perform an lstat() first for the sole purpose of + // checking if it is a link, wasting a syscall and a path traversal. + // + // See Directory::symlink() for warnings about symlinks. +}; + +enum class WriteMode { + // Mode for opening a file (or directory) for write. + // + // (To open a file or directory read-only, do not specify a mode.) + // + // WriteMode is a bitfield. Hence, it overloads the bitwise logic operators. To check if a + // particular bit is set in a bitfield, use kj::has(), like: + // + // if (kj::has(mode, WriteMode::MUST_EXIST)) { + // requireExists(path); + // } + // + // (`if (mode & WriteMode::MUST_EXIST)` doesn't work because WriteMode is an enum class, which + // cannot be converted to bool. Alas, C++ does not allow you to define a conversion operator + // on an enum type, so we can't define a conversion to bool.) + + // ----------------------------------------- + // Core flags + // + // At least one of CREATE or MODIFY must be specified. Optionally, the two flags can be combined + // with a bitwise-OR. + + CREATE = 1, + // Create a new empty file. + // + // When not combined with MODIFY, if the file already exists (including as a broken symlink), + // tryOpenFile() returns null (and openFile() throws). + // + // When combined with MODIFY, if the path already exists, it will be opened as if CREATE hadn't + // been specified at all. If the path refers to a broken symlink, the file at the target of the + // link will be created (if its parent directory exists). + + MODIFY = 2, + // Modify an existing file. + // + // When not combined with CREATE, if the file doesn't exist (including if it is a broken symlink), + // tryOpenFile() returns null (and openFile() throws). + // + // When combined with CREATE, if the path doesn't exist, it will be created as if MODIFY hadn't + // been specified at all. If the path refers to a broken symlink, the file at the target of the + // link will be created (if its parent directory exists). + + // ----------------------------------------- + // Additional flags + // + // Any number of these may be OR'd with the core flags. + + CREATE_PARENT = 4, + // Indicates that if the target node's parent directory doesn't exist, it should be created + // automatically, along with its parent, and so on. This creation is NOT atomic. + // + // This bit only makes sense with CREATE or REPLACE. + + EXECUTABLE = 8, + // Mark this file executable, if this is a meaningful designation on the host platform. + + PRIVATE = 16, + // Indicates that this file is sensitive and should have permissions masked so that it is only + // accessible by the current user. + // + // When this is not used, the platform's default access control settings are used. On Unix, + // that usually means the umask is applied. On Windows, it means permissions are inherited from + // the parent. +}; + +inline constexpr WriteMode operator|(WriteMode a, WriteMode b) { + return static_cast(static_cast(a) | static_cast(b)); +} +inline constexpr WriteMode operator&(WriteMode a, WriteMode b) { + return static_cast(static_cast(a) & static_cast(b)); +} +inline constexpr WriteMode operator+(WriteMode a, WriteMode b) { + return static_cast(static_cast(a) | static_cast(b)); +} +inline constexpr WriteMode operator-(WriteMode a, WriteMode b) { + return static_cast(static_cast(a) & ~static_cast(b)); +} +template > +bool has(T haystack, T needle) { + return (static_cast<__underlying_type(T)>(haystack) & + static_cast<__underlying_type(T)>(needle)) == + static_cast<__underlying_type(T)>(needle); +} + +enum class TransferMode { + // Specifies desired behavior for Directory::transfer(). + + MOVE, + // The node is moved to the new location, i.e. the old location is deleted. If possible, this + // move is performed without copying, otherwise it is performed as a copy followed by a delete. + + LINK, + // The new location becomes a synonym for the old location (a "hard link"). Filesystems have + // varying support for this -- typically, it is not supported on directories. + + COPY + // The new location becomes a copy of the old. + // + // Some filesystems may implement this in terms of copy-on-write. + // + // If the filesystem supports sparse files, COPY takes sparseness into account -- it will punch + // holes in the target file where holes exist in the source file. +}; + +class Directory: public ReadableDirectory { + // Refers to a specific directory on disk. + // + // A `Directory` object *only* provides access to children of the directory, not parents. That + // is, you cannot open the file "..", nor jump to the root directory with "/". + // + // On OSs that support it, a `Directory` is backed by an open handle to the directory node. This + // means: + // - If the directory is renamed on-disk, the `Directory` object still points at it. + // - Opening files in the directory only requires the OS to traverse the path from the directory + // to the file; it doesn't have to re-traverse all the way from the filesystem root. + // + // On Windows, a `Directory` object holds a lock on the underlying directory such that it cannot + // be renamed nor deleted while the object exists. This is necessary because Windows does not + // fully support traversing paths relative to file handles (it does for some operations but not + // all), so the KJ filesystem implementation is forced to remember the full path and needs to + // ensure that the path is not invalidated. If, in the future, Windows fully supports + // handle-relative paths, KJ may stop locking directories in this way, so do not rely on this + // behavior. + +public: + Own clone() const; + + template + class Replacer { + // Implements an atomic replacement of a file or directory, allowing changes to be made to + // storage in a way that avoids losing data in a power outage and prevents other processes + // from observing content in an inconsistent state. + // + // `T` may be `File` or `Directory`. For readability, the text below describes replacing a + // file, but the logic is the same for directories. + // + // When you call `Directory::replaceFile()`, a temporary file is created, but the specified + // path is not yet touched. You may call `get()` to obtain the temporary file object, through + // which you may initialize its content, knowing that no other process can see it yet. The file + // is atomically moved to its final path when you call `commit()`. If you destroy the Replacer + // without calling commit(), the temporary file is deleted. + // + // Note that most operating systems sadly do not support creating a truly unnamed temporary file + // and then linking it in later. Moreover, the file cannot necessarily be created in the system + // temporary directory because it might not be on the same filesystem as the target. Therefore, + // the replacement file may initially be created in the same directory as its eventual target. + // The implementation of Directory will choose a name that is unique and "hidden" according to + // the conventions of the filesystem. Additionally, the implementation of Directory will avoid + // returning these temporary files from its list*() methods, in order to avoid observable + // inconsistencies across platforms. + public: + explicit Replacer(WriteMode mode); + + virtual const T& get() = 0; + // Gets the File or Directory representing the replacement data. Fill in this object before + // calling commit(). + + void commit(); + virtual bool tryCommit() = 0; + // Commit the replacement. + // + // `tryCommit()` may return false based on the CREATE/MODIFY bits passed as the WriteMode when + // the replacement was initiated. (If CREATE but not MODIFY was used, tryCommit() returns + // false to indicate that the target file already existed. If MODIFY but not CREATE was used, + // tryCommit() returns false to indicate that the file didn't exist.) + // + // `commit()` is atomic, meaning that there is no point in time at which other processes + // observing the file will see it in an intermediate state -- they will either see the old + // content or the complete new content. This includes in the case of a power outage or machine + // failure: on recovery, the file will either be in the old state or the new state, but not in + // some intermediate state. + // + // It's important to note that a power failure *after commit() returns* can still revert the + // file to its previous state. That is, `commit()` does NOT guarantee that, upon return, the + // new content is durable. In order to guarantee this, you must call `sync()` on the immediate + // parent directory of the replaced file. + // + // Note that, sadly, not all filesystems / platforms are capable of supporting all of the + // guarantees documented above. In such cases, commit() will make a best-effort attempt to do + // what it claims. Some examples of possible problems include: + // - Any guarantees about durability through a power outage probably require a journaling + // filesystem. + // - Many platforms do not support atomically replacing a non-empty directory. Linux does as + // of kernel 3.15 (via the renameat2() syscall using RENAME_EXCHANGE). Where not supported, + // the old directory will be moved away just before the replacement is moved into place. + // - Many platforms do not support atomically requiring the existence or non-existence of a + // file before replacing it. In these cases, commit() may have to perform the check as a + // separate step, with a small window for a race condition. + // - Many platforms do not support "unlinking" a non-empty directory, meaning that a replaced + // directory will need to be deconstructed by deleting all contents. If another process has + // the directory open when it is replaced, that process will observe the contents + // disappearing after the replacement (actually, a swap) has taken place. This differs from + // files, where a process that has opened a file before it is replaced will continue see the + // file's old content unchanged after the replacement. + // - On Windows, there are multiple ways to replace one file with another in a single system + // call, but none are documented as being atomic. KJ always uses `MoveFileEx()` with + // MOVEFILE_REPLACE_EXISTING. While the alternative `ReplaceFile()` is attractive for many + // reasons, it has the critical problem that it cannot be used when the source file has open + // file handles, which is generally the case when using Replacer. + + protected: + const WriteMode mode; + }; + + using ReadableDirectory::openFile; + using ReadableDirectory::openSubdir; + using ReadableDirectory::tryOpenFile; + using ReadableDirectory::tryOpenSubdir; + + Own openFile(PathPtr path, WriteMode mode) const; + virtual Maybe> tryOpenFile(PathPtr path, WriteMode mode) const = 0; + // Open a file for writing. + // + // `tryOpenFile()` returns null if the path is required to exist but doesn't (MODIFY or REPLACE) + // or if the path is required not to exist but does (CREATE or RACE). These are the only cases + // where it returns null -- all other types of errors (like "access denied") throw exceptions. + + virtual Own> replaceFile(PathPtr path, WriteMode mode) const = 0; + // Construct a file which, when ready, will be atomically moved to `path`, replacing whatever + // is there already. See `Replacer` for detalis. + // + // The `CREATE` and `MODIFY` bits of `mode` are not enforced until commit time, hence + // `replaceFile()` has no "try" variant. + + virtual Own createTemporary() const = 0; + // Create a temporary file backed by this directory's filesystem, but which isn't linked into + // the directory tree. The file is deleted from disk when all references to it have been dropped. + + Own appendFile(PathPtr path, WriteMode mode) const; + virtual Maybe> tryAppendFile(PathPtr path, WriteMode mode) const = 0; + // Opens the file for appending only. Useful for log files. + // + // If the underlying filesystem supports it, writes to the file will always be appended even if + // other writers are writing to the same file at the same time -- however, some implementations + // may instead assume that no other process is changing the file size between writes. + + Own openSubdir(PathPtr path, WriteMode mode) const; + virtual Maybe> tryOpenSubdir(PathPtr path, WriteMode mode) const = 0; + // Opens a subdirectory for writing. + + virtual Own> replaceSubdir(PathPtr path, WriteMode mode) const = 0; + // Construct a directory which, when ready, will be atomically moved to `path`, replacing + // whatever is there already. See `Replacer` for detalis. + // + // The `CREATE` and `MODIFY` bits of `mode` are not enforced until commit time, hence + // `replaceSubdir()` has no "try" variant. + + void symlink(PathPtr linkpath, StringPtr content, WriteMode mode) const; + virtual bool trySymlink(PathPtr linkpath, StringPtr content, WriteMode mode) const = 0; + // Create a symlink. `content` is the raw text which will be written into the symlink node. + // How this text is interpreted is entirely dependent on the filesystem. Note in particular that: + // - Windows will require a path that uses backslashes as the separator. + // - InMemoryDirectory does not support symlinks containing "..". + // + // Unfortunately under many implementations symlink() can be used to break out of the directory + // by writing an absolute path or utilizing "..". Do not call this method with a value for + // `target` that you don't trust. + // + // `mode` must be CREATE or REPLACE, not MODIFY. CREATE_PARENT is honored but EXECUTABLE and + // PRIVATE have no effect. `trySymlink()` returns false in CREATE mode when the target already + // exists. + + void transfer(PathPtr toPath, WriteMode toMode, + PathPtr fromPath, TransferMode mode) const; + void transfer(PathPtr toPath, WriteMode toMode, + const Directory& fromDirectory, PathPtr fromPath, + TransferMode mode) const; + virtual bool tryTransfer(PathPtr toPath, WriteMode toMode, + const Directory& fromDirectory, PathPtr fromPath, + TransferMode mode) const; + virtual Maybe tryTransferTo(const Directory& toDirectory, PathPtr toPath, WriteMode toMode, + PathPtr fromPath, TransferMode mode) const; + // Move, link, or copy a file/directory tree from one location to another. + // + // Filesystems vary in what kinds of transfers are allowed, especially for TransferMode::LINK, + // and whether TransferMode::MOVE is implemented as an actual move vs. copy+delete. + // + // tryTransfer() returns false if the source location didn't exist, or when `toMode` is CREATE + // and the target already exists. The default implementation implements only TransferMode::COPY. + // + // tryTransferTo() exists to implement double-dispatch. It should be called as a fallback by + // implementations of tryTransfer() in cases where the target directory would otherwise fail or + // perform a pessimal transfer. The default implementation returns nullptr, which the caller + // should interpret as: "I don't have any special optimizations; do the obvious thing." + // + // `toMode` controls how the target path is created. CREATE_PARENT is honored but EXECUTABLE and + // PRIVATE have no effect. + + void remove(PathPtr path) const; + virtual bool tryRemove(PathPtr path) const = 0; + // Deletes/unlinks the given path. If the path names a directory, it is recursively deleted. + // + // tryRemove() returns false in the specific case that the path doesn't exist. remove() would + // throw in this case. In all other error cases (like "access denied"), tryRemove() still throws; + // it is only "does not exist" that produces a false return. + // + // TODO(someday): + // - Support sockets? There's no openat()-like interface for sockets, so it's hard to support + // them currently. Also you'd probably want to use them with the async library. + // - Support named pipes? Unclear if there's a use case that isn't better-served by sockets. + // Then again, they can be openat()ed. + // - Support watching for changes (inotify). Probably also requires the async library. Also + // lacks openat()-like semantics. + // - xattrs -- linux-specific + // - chown/chmod/etc. -- unix-specific, ACLs, eww + // - set timestamps -- only needed by archiving programs/ + // - advisory locks + // - sendfile? + // - fadvise and such + +private: + static void commitFailed(WriteMode mode); +}; + +class Filesystem { +public: + virtual const Directory& getRoot() const = 0; + // Get the filesystem's root directory, as of the time the Filesystem object was created. + + virtual const Directory& getCurrent() const = 0; + // Get the filesystem's current directory, as of the time the Filesystem object was created. + + virtual PathPtr getCurrentPath() const = 0; + // Get the path from the root to the current directory, as of the time the Filesystem object was + // created. Note that because a `Directory` does not provide access to its parent, if you want to + // follow `..` from the current directory, you must use `getCurrentPath().eval("..")` or + // `getCurrentPath().parent()`. + // + // This function attempts to determine the path as it appeared in the user's shell before this + // program was started. That means, if the user had `cd`ed into a symlink, the path through that + // symlink is returned, *not* the canonical path. + // + // Because of this, there is an important difference between how the operating system interprets + // "../foo" and what you get when you write `getCurrentPath().eval("../foo")`: The former + // will interpret ".." relative to the directory's canonical path, whereas the latter will + // interpret it relative to the path shown in the user's shell. In practice, the latter is + // almost always what the user wants! But the former behavior is what almost all commands do + // in practice, and it leads to confusion. KJ commands should implement the behavior the user + // expects. +}; + +// ======================================================================================= + +Own newInMemoryFile(const Clock& clock); +Own newInMemoryDirectory(const Clock& clock); +// Construct file and directory objects which reside in-memory. +// +// InMemoryFile has the following special properties: +// - The backing store is not sparse and never gets smaller even if you truncate the file. +// - While a non-private memory mapping exists, the backing store cannot get larger. Any operation +// which would expand it will throw. +// +// InMemoryDirectory has the following special properties: +// - Symlinks are processed using Path::parse(). This implies that a symlink cannot point to a +// parent directory -- InMemoryDirectory does not know its parent. +// - link() can link directory nodes in addition to files. +// - link() and rename() accept any kind of Directory as `fromDirectory` -- it doesn't need to be +// another InMemoryDirectory. However, for rename(), the from path must be a directory. + +Own newFileAppender(Own inner); +// Creates an AppendableFile by wrapping a File. Note that this implementation assumes it is the +// only writer. A correct implementation should always append to the file even if other writes +// are happening simultaneously, as is achieved with the O_APPEND flag to open(2), but that +// behavior is not possible to emulate on top of `File`. + +typedef AutoCloseFd OsFileHandle; + +Own newDiskReadableFile(OsFileHandle fd); +Own newDiskAppendableFile(OsFileHandle fd); +Own newDiskFile(OsFileHandle fd); +Own newDiskReadableDirectory(OsFileHandle fd); +Own newDiskDirectory(OsFileHandle fd); +// Wrap a file descriptor (or Windows HANDLE) as various filesystem types. + +Own newDiskFilesystem(); +// Get at implementation of `Filesystem` representing the real filesystem. +// +// DO NOT CALL THIS except at the top level of your program, e.g. in main(). Anywhere else, you +// should instead have your caller pass in a Filesystem object, or a specific Directory object, +// or whatever it is that your code needs. This ensures that your code supports dependency +// injection, which makes it more reusable and testable. +// +// newDiskFilesystem() reads the current working directory at the time it is called. The returned +// object is not affected by subsequent calls to chdir(). + +// ======================================================================================= +// inline implementation details + +inline Path::Path(decltype(nullptr)): parts(nullptr) {} +inline Path::Path(std::initializer_list parts) + : Path(arrayPtr(parts.begin(), parts.end())) {} +inline Path::Path(Array parts, decltype(ALREADY_CHECKED)) + : parts(kj::mv(parts)) {} +inline Path Path::clone() const { return PathPtr(*this).clone(); } +inline Path Path::append(Path&& suffix) const& { return PathPtr(*this).append(kj::mv(suffix)); } +inline Path Path::append(PathPtr suffix) const& { return PathPtr(*this).append(suffix); } +inline Path Path::append(StringPtr suffix) const& { return append(Path(suffix)); } +inline Path Path::append(StringPtr suffix) && { return kj::mv(*this).append(Path(suffix)); } +inline Path Path::append(String&& suffix) const& { return append(Path(kj::mv(suffix))); } +inline Path Path::append(String&& suffix) && { return kj::mv(*this).append(Path(kj::mv(suffix))); } +inline Path Path::eval(StringPtr pathText) const& { return PathPtr(*this).eval(pathText); } +inline PathPtr Path::basename() const& { return PathPtr(*this).basename(); } +inline PathPtr Path::parent() const& { return PathPtr(*this).parent(); } +inline const String& Path::operator[](size_t i) const& { return parts[i]; } +inline String Path::operator[](size_t i) && { return kj::mv(parts[i]); } +inline size_t Path::size() const { return parts.size(); } +inline const String* Path::begin() const { return parts.begin(); } +inline const String* Path::end() const { return parts.end(); } +inline PathPtr Path::slice(size_t start, size_t end) const& { + return PathPtr(*this).slice(start, end); +} +inline bool Path::operator==(PathPtr other) const { return PathPtr(*this) == other; } +inline bool Path::operator!=(PathPtr other) const { return PathPtr(*this) != other; } +inline bool Path::operator< (PathPtr other) const { return PathPtr(*this) < other; } +inline bool Path::operator> (PathPtr other) const { return PathPtr(*this) > other; } +inline bool Path::operator<=(PathPtr other) const { return PathPtr(*this) <= other; } +inline bool Path::operator>=(PathPtr other) const { return PathPtr(*this) >= other; } +inline bool Path::operator==(const Path& other) const { return PathPtr(*this) == PathPtr(other); } +inline bool Path::operator!=(const Path& other) const { return PathPtr(*this) != PathPtr(other); } +inline bool Path::operator< (const Path& other) const { return PathPtr(*this) < PathPtr(other); } +inline bool Path::operator> (const Path& other) const { return PathPtr(*this) > PathPtr(other); } +inline bool Path::operator<=(const Path& other) const { return PathPtr(*this) <= PathPtr(other); } +inline bool Path::operator>=(const Path& other) const { return PathPtr(*this) >= PathPtr(other); } +inline uint Path::hashCode() const { return kj::hashCode(parts); } +inline bool Path::startsWith(PathPtr prefix) const { return PathPtr(*this).startsWith(prefix); } +inline bool Path::endsWith (PathPtr suffix) const { return PathPtr(*this).endsWith (suffix); } +inline String Path::toString(bool absolute) const { return PathPtr(*this).toString(absolute); } + +inline PathPtr::PathPtr(decltype(nullptr)): parts(nullptr) {} +inline PathPtr::PathPtr(const Path& path): parts(path.parts) {} +inline PathPtr::PathPtr(ArrayPtr parts): parts(parts) {} +inline Path PathPtr::append(StringPtr suffix) const { return append(Path(suffix)); } +inline Path PathPtr::append(String&& suffix) const { return append(Path(kj::mv(suffix))); } +inline const String& PathPtr::operator[](size_t i) const { return parts[i]; } +inline size_t PathPtr::size() const { return parts.size(); } +inline const String* PathPtr::begin() const { return parts.begin(); } +inline const String* PathPtr::end() const { return parts.end(); } +inline PathPtr PathPtr::slice(size_t start, size_t end) const { + return PathPtr(parts.slice(start, end)); +} +inline bool PathPtr::operator!=(PathPtr other) const { return !(*this == other); } +inline bool PathPtr::operator> (PathPtr other) const { return other < *this; } +inline bool PathPtr::operator<=(PathPtr other) const { return !(other < *this); } +inline bool PathPtr::operator>=(PathPtr other) const { return !(*this < other); } +inline uint PathPtr::hashCode() const { return kj::hashCode(parts); } + +inline Path Path::evalNative(StringPtr pathText) const& { + return eval(pathText); +} +inline Path Path::evalNative(StringPtr pathText) && { + return kj::mv(*this).eval(pathText); +} +inline String Path::toNativeString(bool absolute) const { + return toString(absolute); +} +inline Path PathPtr::evalNative(StringPtr pathText) const { + return eval(pathText); +} +inline String PathPtr::toNativeString(bool absolute) const { + return toString(absolute); +} + +inline Own FsNode::clone() const { return cloneFsNode(); } +inline Own ReadableFile::clone() const { + return cloneFsNode().downcast(); +} +inline Own AppendableFile::clone() const { + return cloneFsNode().downcast(); +} +inline Own File::clone() const { return cloneFsNode().downcast(); } +inline Own ReadableDirectory::clone() const { + return cloneFsNode().downcast(); +} +inline Own Directory::clone() const { + return cloneFsNode().downcast(); +} + +inline void Directory::transfer( + PathPtr toPath, WriteMode toMode, PathPtr fromPath, TransferMode mode) const { + return transfer(toPath, toMode, *this, fromPath, mode); +} + +template +inline Directory::Replacer::Replacer(WriteMode mode): mode(mode) {} + +template +void Directory::Replacer::commit() { + if (!tryCommit()) commitFailed(mode); +} + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/function.h b/vendor/capnproto/src/kj/function.h new file mode 100644 index 0000000..59ba5f3 --- /dev/null +++ b/vendor/capnproto/src/kj/function.h @@ -0,0 +1,293 @@ +// 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. + +#pragma once + +#include "memory.h" + +KJ_BEGIN_HEADER + +namespace kj { + +template +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 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 f1 = AddN{2}; +// // f1 owns an instance of AddN. It may safely be moved out +// // of the local scope. +// +// AddN adder(2); +// Function f2 = adder; +// // f2 contains a reference to `adder`. Thus, it becomes invalid +// // when `adder` goes out-of-scope. +// +// AddN adder2(2); +// Function 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 intPrinter = KJ_BIND_METHOD(p, print); +// // Will call Printer::print(int). +// +// Function 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 +class ConstFunction; +// Like Function, but wraps a "const" (i.e. thread-safe) call. + +template +class FunctionParam; +// Like Function, but used specifically as a call parameter type. Does not do any heap allocation. +// +// This type MUST NOT be used for anything other than a parameter type to a function or method. +// This is because if FunctionParam binds to a temporary, it assumes that the temporary will +// outlive the FunctionParam instance. This is true when FunctionParam is used as a parameter type, +// but not if it is used as a local variable nor a class member variable. + +template +class Function { +public: + template + inline Function(F&& f): impl(heap>(kj::fwd(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 Function(const Function&) = delete; + template Function& operator=(const Function&) = delete; + template Function(const ConstFunction&) = delete; + template Function& operator=(const ConstFunction&) = delete; + Function(Function&&) = default; + Function& operator=(Function&&) = default; + + inline Return operator()(Params... params) { + return (*impl)(kj::fwd(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 + class Impl final: public Iface { + public: + explicit Impl(F&& f): f(kj::fwd(f)) {} + + Return operator()(Params... params) override { + return f(kj::fwd(params)...); + } + + private: + F f; + }; + + Own impl; +}; + +template +class ConstFunction { +public: + template + inline ConstFunction(F&& f): impl(heap>(kj::fwd(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 ConstFunction(const ConstFunction&) = delete; + template ConstFunction& operator=(const ConstFunction&) = delete; + template ConstFunction(const Function&) = delete; + template ConstFunction& operator=(const Function&) = delete; + ConstFunction(ConstFunction&&) = default; + ConstFunction& operator=(ConstFunction&&) = default; + + inline Return operator()(Params... params) const { + return (*impl)(kj::fwd(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 + class Impl final: public Iface { + public: + explicit Impl(F&& f): f(kj::fwd(f)) {} + + Return operator()(Params... params) const override { + return f(kj::fwd(params)...); + } + + private: + F f; + }; + + Own impl; +}; + +template +class FunctionParam { +public: + template + FunctionParam(Func&& func) { + typedef Wrapper> WrapperType; + + // All instances of Wrapper are two pointers in size: a vtable, and a Func&. So if we + // allocate space for two pointers, we can construct a Wrapper in it! + static_assert(sizeof(WrapperType) == sizeof(space), + "expected WrapperType to be two pointers"); + + // Even if `func` is an rvalue reference, it's OK to use it as an lvalue here, because + // FunctionParam is used strictly for parameters. If we captured a temporary, we know that + // temporary will not be destroyed until after the function call completes. + ctor(*reinterpret_cast(space), func); + } + + FunctionParam(const FunctionParam& other) = default; + FunctionParam(FunctionParam&& other) = default; + // Magically, a plain copy works. + + inline Return operator()(Params... params) { + return (*reinterpret_cast(space))(kj::fwd(params)...); + } + +private: + alignas(void*) char space[2 * sizeof(void*)]; + + class WrapperBase { + public: + virtual Return operator()(Params... params) = 0; + }; + + template + class Wrapper: public WrapperBase { + public: + Wrapper(Func& func): func(func) {} + + inline Return operator()(Params... params) override { + return func(kj::fwd(params)...); + } + + private: + Func& func; + }; +}; + +namespace _ { // private + +template +class BoundMethod { +public: + BoundMethod(T&& t, Func&& func, ConstFunc&& constFunc) + : t(kj::fwd(t)), func(kj::mv(func)), constFunc(kj::mv(constFunc)) {} + + template + auto operator()(Params&&... params) { + return func(t, kj::fwd(params)...); + } + template + auto operator()(Params&&... params) const { + return constFunc(t, kj::fwd(params)...); + } + +private: + T t; + Func func; + ConstFunc constFunc; +}; + +template +BoundMethod boundMethod(T&& t, Func&& func, ConstFunc&& constFunc) { + return { kj::fwd(t), kj::fwd(func), kj::fwd(constFunc) }; +} + +} // namespace _ (private) + +#define KJ_BIND_METHOD(obj, method) \ + ::kj::_::boundMethod(obj, \ + [](auto& s, auto&&... p) mutable { return s.method(kj::fwd(p)...); }, \ + [](auto& s, auto&&... p) { return s.method(kj::fwd(p)...); }) +// 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 method is allowed to be overloaded. + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/hash.c++ b/vendor/capnproto/src/kj/hash.c++ new file mode 100644 index 0000000..bf80a55 --- /dev/null +++ b/vendor/capnproto/src/kj/hash.c++ @@ -0,0 +1,65 @@ +// Copyright (c) 2018 Kenton Varda 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 "hash.h" + +namespace kj { +namespace _ { // private + +uint HashCoder::operator*(ArrayPtr s) const { + // murmur2 adapted from libc++ source code. + // + // TODO(perf): Use CityHash or FarmHash on 64-bit machines? They seem optimized for x86-64; what + // about ARM? Ask Vlad for advice. + + constexpr uint m = 0x5bd1e995; + constexpr uint r = 24; + uint h = s.size(); + const byte* data = s.begin(); + uint len = s.size(); + for (; len >= 4; data += 4, len -= 4) { + uint k; + memcpy(&k, data, sizeof(k)); + k *= m; + k ^= k >> r; + k *= m; + h *= m; + h ^= k; + } + switch (len) { + case 3: + h ^= data[2] << 16; + KJ_FALLTHROUGH; + case 2: + h ^= data[1] << 8; + KJ_FALLTHROUGH; + case 1: + h ^= data[0]; + h *= m; + } + h ^= h >> 13; + h *= m; + h ^= h >> 15; + return h; +} + +} // namespace _ (private) +} // namespace kj diff --git a/vendor/capnproto/src/kj/hash.h b/vendor/capnproto/src/kj/hash.h new file mode 100644 index 0000000..d6ff46f --- /dev/null +++ b/vendor/capnproto/src/kj/hash.h @@ -0,0 +1,196 @@ +// Copyright (c) 2018 Kenton Varda 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. + +#pragma once + +#include "string.h" + +KJ_BEGIN_HEADER + +namespace kj { +namespace _ { // private + +struct HashCoder { + // This is a dummy type with only one instance: HASHCODER (below). To make an arbitrary type + // hashable, define `operator*(HashCoder, T)` to return any other type that is already hashable. + // Be sure to declare the operator in the same namespace as `T` **or** in the global scope. + // You can use the KJ_HASHCODE() macro as syntax sugar for this. + // + // A more usual way to accomplish what we're doing here would be to require that you define + // a function like `hashCode(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 `hashCode` which do something + // different. Declaring `operator*` with `HashCoder` as the left operand cannot conflict with + // anything. + + uint operator*(ArrayPtr s) const; + inline uint operator*(ArrayPtr s) const { return operator*(s.asConst()); } + + inline uint operator*(ArrayPtr s) const { return operator*(s.asBytes()); } + inline uint operator*(ArrayPtr s) const { return operator*(s.asBytes()); } + inline uint operator*(const Array& s) const { return operator*(s.asBytes()); } + inline uint operator*(const Array& s) const { return operator*(s.asBytes()); } + inline uint operator*(const String& s) const { return operator*(s.asBytes()); } + inline uint operator*(const StringPtr& s) const { return operator*(s.asBytes()); } + inline uint operator*(const ConstString& s) const { return operator*(s.asBytes()); } + + inline uint operator*(decltype(nullptr)) const { return 0; } + inline uint operator*(bool b) const { return b; } + inline uint operator*(char i) const { return i; } + inline uint operator*(signed char i) const { return i; } + inline uint operator*(unsigned char i) const { return i; } + inline uint operator*(signed short i) const { return i; } + inline uint operator*(unsigned short i) const { return i; } + inline uint operator*(signed int i) const { return i; } + inline uint operator*(unsigned int i) const { return i; } + + inline uint operator*(signed long i) const { + if (sizeof(i) == sizeof(uint)) { + return operator*(static_cast(i)); + } else { + return operator*(static_cast(i)); + } + } + inline uint operator*(unsigned long i) const { + if (sizeof(i) == sizeof(uint)) { + return operator*(static_cast(i)); + } else { + return operator*(static_cast(i)); + } + } + inline uint operator*(signed long long i) const { + return operator*(static_cast(i)); + } + inline uint operator*(unsigned long long i) const { + // Mix 64 bits to 32 bits in such a way that if our input values differ primarily in the upper + // 32 bits, we still get good diffusion. (I.e. we cannot just truncate!) + // + // 49123 is an arbitrarily-chosen prime that is vaguely close to 2^16. + // + // TODO(perf): I just made this up. Is it OK? + return static_cast(i) + static_cast(i >> 32) * 49123; + } + + template + uint operator*(T* ptr) const { + static_assert(!isSameType, char>(), "Wrap in StringPtr if you want to hash string " + "contents. If you want to hash the pointer, cast to void*"); + if (sizeof(ptr) == sizeof(uint)) { + // TODO(cleanup): In C++17, make the if() above be `if constexpr ()`, then change this to + // reinterpret_cast(ptr). + return reinterpret_cast(ptr); + } else { + return operator*(reinterpret_cast(ptr)); + } + } + + template () * instance())> + uint operator*(ArrayPtr arr) const; + template () * instance())> + uint operator*(const Array& arr) const; + template > + inline uint operator*(T e) const; + + template ().hashCode())> + inline Result operator*(T&& value) const { return kj::fwd(value).hashCode(); } +}; +static KJ_CONSTEXPR(const) HashCoder HASHCODER = HashCoder(); + +} // namespace _ (private) + +#define KJ_HASHCODE(...) operator*(::kj::_::HashCoder, __VA_ARGS__) +// Defines a hash function for a custom type. Example: +// +// class Foo {...}; +// inline uint KJ_HASHCODE(const Foo& foo) { return kj::hashCode(foo.x, foo.y); } +// +// This allows Foo to be passed to hashCode(). +// +// 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 itself is hashable -- that value will be hashed in turn +// until a `uint` comes out. + +inline uint hashCode(uint value) { return value; } +template +inline uint hashCode(T&& value) { return hashCode(_::HASHCODER * kj::fwd(value)); } +template +inline uint hashCode(T (&arr)[N]) { + static_assert(!isSameType, char>(), "Wrap in StringPtr if you want to hash string " + "contents. If you want to hash the pointer, cast to void*"); + static_assert(isSameType, char>(), "Wrap in ArrayPtr if you want to hash a C array. " + "If you want to hash the pointer, cast to void*"); + return 0; +} +template +inline uint hashCode(T&&... values) { + uint hashes[] = { hashCode(kj::fwd(values))... }; + return hashCode(kj::ArrayPtr(hashes).asBytes()); +} +// kj::hashCode() is a universal hashing function, like kj::str() is a universal stringification +// function. Throw stuff in, get a hash code. +// +// Hash codes may differ between different processes, even running exactly the same code. +// +// NOT SUITABLE FOR CRYPTOGRAPHY. This is for hash tables, not crypto. + +// ======================================================================================= +// inline implementation details + +namespace _ { // private + +template +inline uint HashCoder::operator*(ArrayPtr arr) const { + // Hash each array element to create a string of hashes, then murmur2 over those. + // + // TODO(perf): Choose a more-modern hash. (See hash.c++.) + + constexpr uint m = 0x5bd1e995; + constexpr uint r = 24; + uint h = arr.size() * sizeof(uint); + + for (auto& e: arr) { + uint k = kj::hashCode(e); + k *= m; + k ^= k >> r; + k *= m; + h *= m; + h ^= k; + } + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + return h; +} +template +inline uint HashCoder::operator*(const Array& arr) const { + return operator*(arr.asPtr()); +} + +template +inline uint HashCoder::operator*(T e) const { + return operator*(static_cast<__underlying_type(T)>(e)); +} + +} // namespace _ (private) +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/io.c++ b/vendor/capnproto/src/kj/io.c++ new file mode 100644 index 0000000..885d68d --- /dev/null +++ b/vendor/capnproto/src/kj/io.c++ @@ -0,0 +1,171 @@ +// 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 _GNU_SOURCE +#define _GNU_SOURCE +#endif + + +#include "io.h" +#include "debug.h" +#include "miniposix.h" +#include +#include +#include "vector.h" +#include + +#include + +namespace kj { + +OutputStream::~OutputStream() noexcept(false) {} + +void OutputStream::write(ArrayPtr> pieces) { + for (auto piece: pieces) { + write(piece.begin(), piece.size()); + } +} + +AutoCloseFd::~AutoCloseFd() noexcept(false) { + if (fd >= 0) { + // Don't use SYSCALL() here because close() should not be repeated on EINTR. + if (miniposix::close(fd) < 0) { + KJ_FAIL_SYSCALL("close", errno, fd) { + // This ensures we don't throw an exception if unwinding. + break; + } + } + } +} + +FdOutputStream::~FdOutputStream() noexcept(false) {} + +#if __APPLE__ +// macOS cannot handle writes of more than INT_MAX, so we clamp +// writes to this size. We use 1GB rather than INT_MAX since INT_MAX is 2GB minus 1 byte. Being +// off by one from a big round number feels rude (alignment issues may harm performance), and 1GB +// should be plenty in any case. +static constexpr size_t WRITE_CLAMP_SIZE = 1u << 30; +#endif + +void FdOutputStream::write(const void* buffer, size_t size) { + const char* pos = reinterpret_cast(buffer); + + while (size > 0) { + miniposix::ssize_t n; +#if __APPLE__ + // macOS fails if given more than INT_MAX bytes + // in a single write operation. We can just clamp the size since the loop will then handle + // writing the rest. I don't know why these platforms don't just do this themselves. + KJ_SYSCALL(n = miniposix::write(fd, pos, kj::min(size, WRITE_CLAMP_SIZE)), fd); +#else + KJ_SYSCALL(n = miniposix::write(fd, pos, size), fd); +#endif + KJ_ASSERT(n > 0, "write() returned zero."); + pos += n; + size -= n; + } +} + +void FdOutputStream::write(ArrayPtr> pieces) { + const size_t iovmax = miniposix::iovMax(); + while (pieces.size() > iovmax) { + write(pieces.slice(0, iovmax)); + pieces = pieces.slice(iovmax, pieces.size()); + } + + KJ_STACK_ARRAY(struct iovec, iov, pieces.size(), 16, 128); + + for (uint i = 0; i < pieces.size(); i++) { + // writev() interface is not const-correct. :( + iov[i].iov_base = const_cast(pieces[i].begin()); + iov[i].iov_len = pieces[i].size(); + } + + struct iovec* current = iov.begin(); + + // Advance past any leading empty buffers so that a write full of only empty buffers does not + // cause a syscall at all. + while (current < iov.end() && current->iov_len == 0) { + ++current; + } + + while (current < iov.end()) { + size_t iovCount = iov.end() - current; + +#if __APPLE__ + // MacOS will fail if you give it more than INT_MAX bytes to write at once. We can solve this + // by carefully truncating the list to a lesser number. Why the OS doesn't just return a short + // write itself, I don't know. + size_t totalSize = 0; + struct iovec* editedPiece = nullptr; + size_t editedPieceOriginalLen = 0; + for (auto i: kj::zeroTo(iovCount)) { + auto& piece = *(current + i); + totalSize += piece.iov_len; + if (totalSize >= WRITE_CLAMP_SIZE) { + // Truncate the list after this piece. + iovCount = i + 1; + + if (totalSize > WRITE_CLAMP_SIZE) { + // We also have to truncate this piece. Patch it in-place and plan to fix it later. + editedPiece = &piece; + editedPieceOriginalLen = piece.iov_len; + size_t overage = totalSize - WRITE_CLAMP_SIZE; + piece.iov_len -= overage; + } + + break; + } + } +#endif + + // Issue the write. + ssize_t n = 0; + KJ_SYSCALL(n = ::writev(fd, current, iovCount), fd); + KJ_ASSERT(n > 0, "writev() returned zero."); + +#if __APPLE__ + // If we patched the list above, unpatch now. + if (editedPiece != nullptr) { + editedPiece->iov_len = editedPieceOriginalLen; + } +#endif + + // Advance past all buffers that were fully-written. + while (current < iov.end() && static_cast(n) >= current->iov_len) { + n -= current->iov_len; + ++current; + } + + // If we only partially-wrote one of the buffers, adjust the pointer and size to include only + // the unwritten part. + if (n > 0) { + current->iov_base = reinterpret_cast(current->iov_base) + n; + current->iov_len -= n; + } + } +} + +// ======================================================================================= + + +} // namespace kj diff --git a/vendor/capnproto/src/kj/io.h b/vendor/capnproto/src/kj/io.h new file mode 100644 index 0000000..2be7c74 --- /dev/null +++ b/vendor/capnproto/src/kj/io.h @@ -0,0 +1,129 @@ +// 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. + +#pragma once + +#include +#include "common.h" +#include "array.h" +#include "exception.h" +#include + +KJ_BEGIN_HEADER + +namespace kj { + +// ======================================================================================= +// Abstract interfaces + +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> 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. +}; + +// ======================================================================================= +// 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; } + + inline int release() { + // Release ownership of an FD. Not recommended. + int result = fd; + fd = -1; + return result; + } + +private: + int fd; +}; + +inline auto KJ_STRINGIFY(const AutoCloseFd& fd) + -> decltype(kj::toCharSequence(implicitCast(fd))) { + return kj::toCharSequence(implicitCast(fd)); +} + +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_AND_MOVE(FdOutputStream); + ~FdOutputStream() noexcept(false); + + void write(const void* buffer, size_t size) override; + void write(ArrayPtr> pieces) override; + + inline int getFd() const { return fd; } + +private: + int fd; + AutoCloseFd autoclose; +}; + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/map.h b/vendor/capnproto/src/kj/map.h new file mode 100644 index 0000000..4f92a20 --- /dev/null +++ b/vendor/capnproto/src/kj/map.h @@ -0,0 +1,578 @@ +// Copyright (c) 2018 Kenton Varda 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. + +#pragma once + +#include "table.h" +#include "hash.h" + +KJ_BEGIN_HEADER + +namespace kj { + +template +class HashMap { + // A key/value mapping backed by hashing. + // + // `Key` must be hashable (via a `.hashCode()` method or `KJ_HASHCODE()`; see `hash.h`) and must + // implement `operator==()`. Additionally, when performing lookups, you can use key types other + // than `Key` as long as the other type is also hashable (producing the same hash codes) and + // there is an `operator==` implementation with `Key` on the left and that other type on the + // right. For example, if the key type is `String`, you can pass `StringPtr` to `find()`. + +public: + void reserve(size_t size); + // Pre-allocates space for a map of the given size. + + size_t size() const; + size_t capacity() const; + void clear(); + + struct Entry { + Key key; + Value value; + }; + + Entry* begin(); + Entry* end(); + const Entry* begin() const; + const Entry* end() const; + // Deterministic iteration. If you only ever insert(), iteration order will be insertion order. + // If you erase(), the erased element is swapped with the last element in the ordering. + + Entry& insert(Key key, Value value); + // Inserts a new entry. Throws if the key already exists. + + template + void insertAll(Collection&& collection); + // Given an iterable collection of `Entry`s, inserts all of them into this map. If the + // input is an rvalue, the entries will be moved rather than copied. + + template + Entry& upsert(Key key, Value value, UpdateFunc&& update); + Entry& upsert(Key key, Value value); + // Tries to insert a new entry. However, if a duplicate already exists (according to some index), + // then update(Value& existingValue, Value&& newValue) is called to modify the existing value. + // If no function is provided, the default is to simply replace the value (but not the key). + + template + kj::Maybe find(KeyLike&& key); + template + kj::Maybe find(KeyLike&& key) const; + // Search for a matching key. The input does not have to be of type `Key`; it merely has to + // be something that the Hasher accepts. + // + // Note that the default hasher for String accepts StringPtr. + + template + Value& findOrCreate(KeyLike&& key, Func&& createEntry); + // Like find() but if the key isn't present then call createEntry() to create the corresponding + // entry and insert it. createEntry() must return type `Entry`. + + template + kj::Maybe findEntry(KeyLike&& key); + template + kj::Maybe findEntry(KeyLike&& key) const; + template + Entry& findOrCreateEntry(KeyLike&& key, Func&& createEntry); + // Sometimes you need to see the whole matching Entry, not just the Value. + + template + bool erase(KeyLike&& key); + // Erase the entry with the matching key. + // + // WARNING: This invalidates all pointers and iterators into the map. Use eraseAll() if you need + // to iterate and erase multiple entries. + + void erase(Entry& entry); + // Erase an entry by reference. + + Entry release(Entry& row); + // Erase an entry and return its content by move. + + template ()(instance(), instance()))> + size_t eraseAll(Predicate&& predicate); + // Erase all values for which predicate(key, value) returns true. This scans over the entire map. + +private: + class Callbacks { + public: + inline const Key& keyForRow(const Entry& entry) const { return entry.key; } + inline Key& keyForRow(Entry& entry) const { return entry.key; } + + template + inline bool matches(Entry& e, KeyLike&& key) const { + return e.key == key; + } + template + inline bool matches(const Entry& e, KeyLike&& key) const { + return e.key == key; + } + template + inline auto hashCode(KeyLike&& key) const { + return kj::hashCode(key); + } + }; + + kj::Table> table; +}; + +template +class TreeMap { + // A key/value mapping backed by a B-tree. + // + // `Key` must support `operator<` and `operator==` against other Keys, and against any type + // which you might want to pass to find() (with `Key` always on the left of the comparison). + +public: + void reserve(size_t size); + // Pre-allocates space for a map of the given size. + + size_t size() const; + size_t capacity() const; + void clear(); + + struct Entry { + Key key; + Value value; + }; + + auto begin(); + auto end(); + auto begin() const; + auto end() const; + // Iteration is in sorted order by key. + + Entry& insert(Key key, Value value); + // Inserts a new entry. Throws if the key already exists. + + template + void insertAll(Collection&& collection); + // Given an iterable collection of `Entry`s, inserts all of them into this map. If the + // input is an rvalue, the entries will be moved rather than copied. + + template + Entry& upsert(Key key, Value value, UpdateFunc&& update); + Entry& upsert(Key key, Value value); + // Tries to insert a new entry. However, if a duplicate already exists (according to some index), + // then update(Value& existingValue, Value&& newValue) is called to modify the existing value. + // If no function is provided, the default is to simply replace the value (but not the key). + + template + kj::Maybe find(KeyLike&& key); + template + kj::Maybe find(KeyLike&& key) const; + // Search for a matching key. The input does not have to be of type `Key`; it merely has to + // be something that can be compared against `Key`. + + template + Value& findOrCreate(KeyLike&& key, Func&& createEntry); + // Like find() but if the key isn't present then call createEntry() to create the corresponding + // entry and insert it. createEntry() must return type `Entry`. + + template + kj::Maybe findEntry(KeyLike&& key); + template + kj::Maybe findEntry(KeyLike&& key) const; + template + Entry& findOrCreateEntry(KeyLike&& key, Func&& createEntry); + // Sometimes you need to see the whole matching Entry, not just the Value. + + template + auto range(K1&& k1, K2&& k2); + template + auto range(K1&& k1, K2&& k2) const; + // Returns an iterable range of entries with keys between k1 (inclusive) and k2 (exclusive). + + template + bool erase(KeyLike&& key); + // Erase the entry with the matching key. + // + // WARNING: This invalidates all pointers and iterators into the map. Use eraseAll() if you need + // to iterate and erase multiple entries. + + void erase(Entry& entry); + // Erase an entry by reference. + + Entry release(Entry& row); + // Erase an entry and return its content by move. + + template ()(instance(), instance()))> + size_t eraseAll(Predicate&& predicate); + // Erase all values for which predicate(key, value) returns true. This scans over the entire map. + + template + size_t eraseRange(K1&& k1, K2&& k2); + // Erases all entries with keys between k1 (inclusive) and k2 (exclusive). + +private: + class Callbacks { + public: + inline const Key& keyForRow(const Entry& entry) const { return entry.key; } + inline Key& keyForRow(Entry& entry) const { return entry.key; } + + template + inline bool matches(Entry& e, KeyLike&& key) const { + return e.key == key; + } + template + inline bool matches(const Entry& e, KeyLike&& key) const { + return e.key == key; + } + template + inline bool isBefore(Entry& e, KeyLike&& key) const { + return e.key < key; + } + template + inline bool isBefore(const Entry& e, KeyLike&& key) const { + return e.key < key; + } + }; + + kj::Table> table; +}; + +namespace _ { // private + +class HashSetCallbacks { +public: + template + inline Row& keyForRow(Row& row) const { return row; } + + template + inline bool matches(T& a, U& b) const { return a == b; } + template + inline auto hashCode(KeyLike&& key) const { + return kj::hashCode(key); + } +}; + +class TreeSetCallbacks { +public: + template + inline Row& keyForRow(Row& row) const { return row; } + + template + inline bool matches(T& a, U& b) const { return a == b; } + template + inline bool isBefore(T& a, U& b) const { return a < b; } +}; + +} // namespace _ (private) + +template +class HashSet: public Table> { + // A simple hashtable-based set, using kj::hashCode() and operator==(). + +public: + // Everything is inherited. + + template + inline bool contains(Params&&... params) const { + return this->find(kj::fwd(params)...) != nullptr; + } +}; + +template +class TreeSet: public Table> { + // A simple b-tree-based set, using operator<() and operator==(). + +public: + // Everything is inherited. +}; + +// ======================================================================================= +// inline implementation details + +template +void HashMap::reserve(size_t size) { + table.reserve(size); +} + +template +size_t HashMap::size() const { + return table.size(); +} +template +size_t HashMap::capacity() const { + return table.capacity(); +} +template +void HashMap::clear() { + return table.clear(); +} + +template +typename HashMap::Entry* HashMap::begin() { + return table.begin(); +} +template +typename HashMap::Entry* HashMap::end() { + return table.end(); +} +template +const typename HashMap::Entry* HashMap::begin() const { + return table.begin(); +} +template +const typename HashMap::Entry* HashMap::end() const { + return table.end(); +} + +template +typename HashMap::Entry& HashMap::insert(Key key, Value value) { + return table.insert(Entry { kj::mv(key), kj::mv(value) }); +} + +template +template +void HashMap::insertAll(Collection&& collection) { + return table.insertAll(kj::fwd(collection)); +} + +template +template +typename HashMap::Entry& HashMap::upsert( + Key key, Value value, UpdateFunc&& update) { + return table.upsert(Entry { kj::mv(key), kj::mv(value) }, + [&](Entry& existingEntry, Entry&& newEntry) { + update(existingEntry.value, kj::mv(newEntry.value)); + }); +} + +template +typename HashMap::Entry& HashMap::upsert( + Key key, Value value) { + return table.upsert(Entry { kj::mv(key), kj::mv(value) }, + [&](Entry& existingEntry, Entry&& newEntry) { + existingEntry.value = kj::mv(newEntry.value); + }); +} + +template +template +kj::Maybe HashMap::find(KeyLike&& key) { + return table.find(key).map([](Entry& e) -> Value& { return e.value; }); +} +template +template +kj::Maybe HashMap::find(KeyLike&& key) const { + return table.find(key).map([](const Entry& e) -> const Value& { return e.value; }); +} + +template +template +Value& HashMap::findOrCreate(KeyLike&& key, Func&& createEntry) { + return table.findOrCreate(key, kj::fwd(createEntry)).value; +} + +template +template +kj::Maybe::Entry&> +HashMap::findEntry(KeyLike&& key) { + return table.find(kj::fwd(key)); +} +template +template +kj::Maybe::Entry&> +HashMap::findEntry(KeyLike&& key) const { + return table.find(kj::fwd(key)); +} +template +template +typename HashMap::Entry& +HashMap::findOrCreateEntry(KeyLike&& key, Func&& createEntry) { + return table.findOrCreate(kj::fwd(key), kj::fwd(createEntry)); +} + +template +template +bool HashMap::erase(KeyLike&& key) { + return table.eraseMatch(key); +} + +template +void HashMap::erase(Entry& entry) { + table.erase(entry); +} + +template +typename HashMap::Entry HashMap::release(Entry& entry) { + return table.release(entry); +} + +template +template +size_t HashMap::eraseAll(Predicate&& predicate) { + return table.eraseAll([&](Entry& entry) { + return predicate(entry.key, entry.value); + }); +} + +// ----------------------------------------------------------------------------- + +template +void TreeMap::reserve(size_t size) { + table.reserve(size); +} + +template +size_t TreeMap::size() const { + return table.size(); +} +template +size_t TreeMap::capacity() const { + return table.capacity(); +} +template +void TreeMap::clear() { + return table.clear(); +} + +template +auto TreeMap::begin() { + return table.ordered().begin(); +} +template +auto TreeMap::end() { + return table.ordered().end(); +} +template +auto TreeMap::begin() const { + return table.ordered().begin(); +} +template +auto TreeMap::end() const { + return table.ordered().end(); +} + +template +typename TreeMap::Entry& TreeMap::insert(Key key, Value value) { + return table.insert(Entry { kj::mv(key), kj::mv(value) }); +} + +template +template +void TreeMap::insertAll(Collection&& collection) { + return table.insertAll(kj::fwd(collection)); +} + +template +template +typename TreeMap::Entry& TreeMap::upsert( + Key key, Value value, UpdateFunc&& update) { + return table.upsert(Entry { kj::mv(key), kj::mv(value) }, + [&](Entry& existingEntry, Entry&& newEntry) { + update(existingEntry.value, kj::mv(newEntry.value)); + }); +} + +template +typename TreeMap::Entry& TreeMap::upsert( + Key key, Value value) { + return table.upsert(Entry { kj::mv(key), kj::mv(value) }, + [&](Entry& existingEntry, Entry&& newEntry) { + existingEntry.value = kj::mv(newEntry.value); + }); +} + +template +template +kj::Maybe TreeMap::find(KeyLike&& key) { + return table.find(key).map([](Entry& e) -> Value& { return e.value; }); +} +template +template +kj::Maybe TreeMap::find(KeyLike&& key) const { + return table.find(key).map([](const Entry& e) -> const Value& { return e.value; }); +} + +template +template +Value& TreeMap::findOrCreate(KeyLike&& key, Func&& createEntry) { + return table.findOrCreate(key, kj::fwd(createEntry)).value; +} + +template +template +kj::Maybe::Entry&> +TreeMap::findEntry(KeyLike&& key) { + return table.find(kj::fwd(key)); +} +template +template +kj::Maybe::Entry&> +TreeMap::findEntry(KeyLike&& key) const { + return table.find(kj::fwd(key)); +} +template +template +typename TreeMap::Entry& +TreeMap::findOrCreateEntry(KeyLike&& key, Func&& createEntry) { + return table.findOrCreate(kj::fwd(key), kj::fwd(createEntry)); +} + +template +template +auto TreeMap::range(K1&& k1, K2&& k2) { + return table.range(kj::fwd(k1), kj::fwd(k2)); +} +template +template +auto TreeMap::range(K1&& k1, K2&& k2) const { + return table.range(kj::fwd(k1), kj::fwd(k2)); +} + +template +template +bool TreeMap::erase(KeyLike&& key) { + return table.eraseMatch(key); +} + +template +void TreeMap::erase(Entry& entry) { + table.erase(entry); +} + +template +typename TreeMap::Entry TreeMap::release(Entry& entry) { + return table.release(entry); +} + +template +template +size_t TreeMap::eraseAll(Predicate&& predicate) { + return table.eraseAll([&](Entry& entry) { + return predicate(entry.key, entry.value); + }); +} + +template +template +size_t TreeMap::eraseRange(K1&& k1, K2&& k2) { + return table.eraseRange(kj::fwd(k1), kj::fwd(k2)); +} + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/memory.h b/vendor/capnproto/src/kj/memory.h new file mode 100644 index 0000000..5feb52a --- /dev/null +++ b/vendor/capnproto/src/kj/memory.h @@ -0,0 +1,776 @@ +// 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. + +#pragma once + +#include "common.h" + +KJ_BEGIN_HEADER + +namespace kj { + +template +inline constexpr bool _kj_internal_isPolymorphic(T*) { + // If you get a compiler error here complaining that T is incomplete, it's because you are trying + // to use kj::Own with a type that has only been forward-declared. Since KJ doesn't know if + // the type might be involved in inheritance (especially multiple inheritance), it doesn't know + // how to correctly call the disposer to destroy the type, since the object's true memory address + // may differ from the address used to point to a superclass. + // + // However, if you know for sure that T is NOT polymorphic (i.e. it doesn't have a vtable and + // isn't involved in inheritance), then you can use KJ_DECLARE_NON_POLYMORPHIC(T) to declare this + // to KJ without actually completing the type. Place this macro invocation either in the global + // scope, or in the same namespace as T is defined. + return __is_polymorphic(T); +} + +#define KJ_DECLARE_NON_POLYMORPHIC(...) \ + inline constexpr bool _kj_internal_isPolymorphic(__VA_ARGS__*) { \ + return false; \ + } +// If you want to use kj::Own for an incomplete type T that you know is not polymorphic, then +// write `KJ_DECLARE_NON_POLYMORPHIC(T)` either at the global scope or in the same namespace as +// T is declared. +// +// This also works for templates, e.g.: +// +// template +// struct MyType; +// template +// KJ_DECLARE_NON_POLYMORPHIC(MyType) + +namespace _ { // private + +template struct RefOrVoid_ { typedef T& Type; }; +template <> struct RefOrVoid_ { typedef void Type; }; +template <> struct RefOrVoid_ { typedef void Type; }; + +template +using RefOrVoid = typename RefOrVoid_::Type; +// Evaluates to T&, unless T is `void`, in which case evaluates to `void`. +// +// This is a hack needed to avoid defining Own as a totally separate class. + +template +struct CastToVoid_; + +template +struct CastToVoid_ { + static void* apply(T* ptr) { + return static_cast(ptr); + } + static const void* applyConst(T* ptr) { + const T* cptr = ptr; + return static_cast(cptr); + } +}; + +template +struct CastToVoid_ { + static void* apply(T* ptr) { + return dynamic_cast(ptr); + } + static const void* applyConst(T* ptr) { + const T* cptr = ptr; + return dynamic_cast(cptr); + } +}; + +template +void* castToVoid(T* ptr) { + return CastToVoid_::apply(ptr); +} + +template +const void* castToConstVoid(T* ptr) { + return CastToVoid_::applyConst(ptr); +} + +} // namespace _ (private) + +// ======================================================================================= +// 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` 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(). For non-polymorphic types, + // Own does not allow any casting, so the pointer exactly matches the original one given to + // Own. + +public: + + template + void dispose(T* object) const; + // Helper wrapper around disposeImpl(). + // + // If T is polymorphic, calls `disposeImpl(dynamic_cast(object))`, otherwise calls + // `disposeImpl(implicitCast(object))`. + // + // Callers must not call dispose() on the same pointer twice, even if the first call throws + // an exception. + +private: + template + struct Dispose_; +}; + +template +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(pointer)->~T(); + } +}; + +template +const DestructorOnlyDisposer DestructorOnlyDisposer::instance = DestructorOnlyDisposer(); + +// ======================================================================================= +// Own -- An owned pointer. + +template +class Own; + +template +class Own { + // A transferrable title to a T. When an Own goes out of scope, the object's Disposer is + // called to dispose of it. An Own 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, 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>&& other) noexcept + : disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; } + template ()>> + inline Own(Own&& other) noexcept + : disposer(other.disposer), ptr(cast(other.ptr)) { + other.ptr = nullptr; + } + template ()>> + inline Own(Own&& other) noexcept; + // Convert statically-disposed Own to dynamically-disposed Own. + inline Own(T* ptr, const Disposer& disposer) noexcept: disposer(&disposer), ptr(ptr) {} + + ~Own() noexcept(false) { dispose(); } + + inline Own& operator=(Own&& other) { + // Move-assignnment 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*>(ptrCopy)); + } + return *this; + } + + inline Own& operator=(decltype(nullptr)) { + dispose(); + return *this; + } + + template + Own attach(Attachments&&... attachments) KJ_WARN_UNUSED_RESULT; + // Returns an Own which points to the same object but which also ensures that all values + // passed to `attachments` remain alive until after this object is destroyed. Normally + // `attachments` are other Owns pointing to objects that this one depends on. + // + // Note that attachments will eventually be destroyed in the order they are listed. Hence, + // foo.attach(bar, baz) is equivalent to (but more efficient than) foo.attach(bar).attach(baz). + + template + Own downcast() { + // Downcast the pointer to Own, 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 result; + if (ptr != nullptr) { + result.ptr = &kj::downcast(*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 _::RefOrVoid operator*() { NULLCHECK; return *ptr; } + inline _::RefOrVoid 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>. + + 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*>(ptrCopy)); + } + } + + template + static inline T* cast(U* ptr) { + static_assert(_kj_internal_isPolymorphic((T*)nullptr), + "Casting owned pointers requires that the target type is polymorphic."); + return ptr; + } + + template + friend class Own; + friend class Maybe>; +}; + +template <> +template +inline void* Own::cast(U* ptr) { + return _::castToVoid(ptr); +} + +template <> +template +inline const void* Own::cast(U* ptr) { + return _::castToConstVoid(ptr); +} + +template +class Own { + // If a `StaticDisposer` is specified (which is not the norm), then the object will be deleted + // by calling StaticDisposer::dispose(pointer). The pointer passed to `dispose()` could be a + // superclass of `T`, if the pointer has been upcast. + // + // This type can be useful for micro-optimization, if you've found that you are doing excessive + // heap allocations to the point where the virtual call on destruction is costing non-negligible + // resources. You should avoid this unless you have a specific need, because it precludes a lot + // of power. + +public: + KJ_DISALLOW_COPY(Own); + inline Own(): ptr(nullptr) {} + inline Own(Own&& other) noexcept + : ptr(other.ptr) { other.ptr = nullptr; } + inline Own(Own, StaticDisposer>&& other) noexcept + : ptr(other.ptr) { other.ptr = nullptr; } + template ()>> + inline Own(Own&& other) noexcept + : ptr(cast(other.ptr)) { + other.ptr = nullptr; + } + inline explicit Own(T* ptr) noexcept: ptr(ptr) {} + + ~Own() noexcept(false) { dispose(); } + + inline Own& operator=(Own&& other) { + // Move-assignnment operator. + + // Careful, this might own `other`. Therefore we have to transfer the pointers first, then + // dispose. + T* ptrCopy = ptr; + ptr = other.ptr; + other.ptr = nullptr; + if (ptrCopy != nullptr) { + StaticDisposer::dispose(ptrCopy); + } + return *this; + } + + inline Own& operator=(decltype(nullptr)) { + dispose(); + return *this; + } + + template + Own downcast() { + // Downcast the pointer to Own, 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 result; + if (ptr != nullptr) { + result.ptr = &kj::downcast(*ptr); + 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 _::RefOrVoid operator*() { NULLCHECK; return *ptr; } + inline _::RefOrVoid 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: + T* ptr; + + inline explicit Own(decltype(nullptr)): ptr(nullptr) {} + + inline bool operator==(decltype(nullptr)) { return ptr == nullptr; } + inline bool operator!=(decltype(nullptr)) { return ptr != nullptr; } + // Only called by Maybe>. + + 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; + StaticDisposer::dispose(ptrCopy); + } + } + + template + static inline T* cast(U* ptr) { + return ptr; + } + + template + friend class Own; + friend class Maybe>; +}; + +namespace _ { // private + +template +class OwnOwn { +public: + inline OwnOwn(Own&& value) noexcept: value(kj::mv(value)) {} + + inline Own& operator*() & { return value; } + inline const Own& operator*() const & { return value; } + inline Own&& operator*() && { return kj::mv(value); } + inline const Own&& operator*() const && { return kj::mv(value); } + inline Own* operator->() { return &value; } + inline const Own* operator->() const { return &value; } + inline operator Own*() { return value ? &value : nullptr; } + inline operator const Own*() const { return value ? &value : nullptr; } + +private: + Own value; +}; + +template +OwnOwn readMaybe(Maybe>&& maybe) { return OwnOwn(kj::mv(maybe.ptr)); } +template +Own* readMaybe(Maybe>& maybe) { return maybe.ptr ? &maybe.ptr : nullptr; } +template +const Own* readMaybe(const Maybe>& maybe) { + return maybe.ptr ? &maybe.ptr : nullptr; +} + +} // namespace _ (private) + +template +class Maybe> { +public: + inline Maybe(): ptr(nullptr) {} + inline Maybe(Own&& t) noexcept: ptr(kj::mv(t)) {} + inline Maybe(Maybe&& other) noexcept: ptr(kj::mv(other.ptr)) {} + + template + inline Maybe(Maybe>&& other): ptr(mv(other.ptr)) {} + template + inline Maybe(Own&& other): ptr(mv(other)) {} + + inline Maybe(decltype(nullptr)) noexcept: ptr(nullptr) {} + + inline Own& emplace(Own value) { + // Assign the Maybe to the given value and return the content. This avoids the need to do a + // KJ_ASSERT_NONNULL() immediately after setting the Maybe just to read it back again. + ptr = kj::mv(value); + return ptr; + } + + template + inline operator NoInfer>() { return ptr.get(); } + template + inline operator NoInfer>() const { return ptr.get(); } + // Implicit conversion to `Maybe`. The weird templating is to make sure that + // `Maybe>` can be instantiated with the compiler complaining about forming references + // to void -- the use of templates here will cause SFINAE to kick in and hide these, whereas if + // they are not templates then SFINAE isn't applied and so they are considered errors. + + 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& orDefault(Own& defaultValue) { + if (ptr == nullptr) { + return defaultValue; + } else { + return ptr; + } + } + const Own& orDefault(const Own& defaultValue) const { + if (ptr == nullptr) { + return defaultValue; + } else { + return ptr; + } + } + + template () ? instance>() : instance()())> + Result orDefault(F&& lazyDefaultValue) && { + if (ptr == nullptr) { + return lazyDefaultValue(); + } else { + return kj::mv(ptr); + } + } + + template + auto map(Func&& f) & -> Maybe&>()))> { + if (ptr == nullptr) { + return nullptr; + } else { + return f(ptr); + } + } + + template + auto map(Func&& f) const & -> Maybe&>()))> { + if (ptr == nullptr) { + return nullptr; + } else { + return f(ptr); + } + } + + template + auto map(Func&& f) && -> Maybe&&>()))> { + if (ptr == nullptr) { + return nullptr; + } else { + return f(kj::mv(ptr)); + } + } + + template + auto map(Func&& f) const && -> Maybe&&>()))> { + if (ptr == nullptr) { + return nullptr; + } else { + return f(kj::mv(ptr)); + } + } + +private: + Own ptr; + + template + friend class Maybe; + template + friend _::OwnOwn _::readMaybe(Maybe>&& maybe); + template + friend Own* _::readMaybe(Maybe>& maybe); + template + friend const Own* _::readMaybe(const Maybe>& maybe); +}; + +namespace _ { // private + +template +class HeapDisposer final: public Disposer { +public: + virtual void disposeImpl(void* pointer) const override { delete reinterpret_cast(pointer); } + + static const HeapDisposer instance; +}; + +template +const HeapDisposer HeapDisposer::instance = HeapDisposer(); + +#if KJ_CPP_STD >= 202002L +template +class CustomDisposer: public Disposer { +public: + void disposeImpl(void* pointer) const override { + (*F)(reinterpret_cast(pointer)); + } +}; + +template +static constexpr CustomDisposer CUSTOM_DISPOSER_INSTANCE {}; +#else +template +class CustomDisposer: public Disposer { +public: + static const CustomDisposer instance; + + void disposeImpl(void* pointer) const override { + (*F)(reinterpret_cast(pointer)); + } +}; + +template +const CustomDisposer CustomDisposer::instance = CustomDisposer(); +#endif + +} // namespace _ (private) + +template +Own heap(Params&&... params) { + // heap(...) 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(new T(kj::fwd(params)...), _::HeapDisposer::instance); +} + +template +Own> 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 T2; + return Own(new T2(kj::fwd(orig)), _::HeapDisposer::instance); +} + +#if KJ_CPP_STD > 201402L +#if KJ_CPP_STD < 202002L +template +Own disposeWith(T* ptr) { + // Associate a pre-allocated raw pointer with a corresponding disposal function. + // The first template parameter should be a function pointer e.g. disposeWith(new int(0)). + + return Own(ptr, _::CustomDisposer::instance); +} +#else +template +Own disposeWith(T* ptr) { + // Associate a pre-allocated raw pointer with a corresponding disposal function. + // The first template parameter should be a function pointer e.g. disposeWith(new int(0)). + + return Own(ptr, _::CUSTOM_DISPOSER_INSTANCE); +} +#endif +#endif + +template +Own> attachVal(T&& value, Attachments&&... attachments); +// Returns an Own that takes ownership of `value` and `attachments`, and points to `value`. +// +// This is equivalent to heap(value).attach(attachments), but only does one allocation rather than +// two. + +template +Own attachRef(T& value, Attachments&&... attachments); +// Like attach() but `value` is not moved; the resulting Own points to its existing location. +// This is preferred if `value` is already owned by one of `attachments`. + +// ======================================================================================= +// SpaceFor -- assists in manual allocation + +template +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 which will take care of calling T's destructor later. + +public: + inline SpaceFor() {} + inline ~SpaceFor() {} + + template + Own construct(Params&&... params) { + ctor(value, kj::fwd(params)...); + return Own(&value, DestructorOnlyDisposer::instance); + } + +private: + union { + T value; + }; +}; + +// ======================================================================================= +// Inline implementation details + +template +struct Disposer::Dispose_ { + static void dispose(T* object, const Disposer& disposer) { + // Note that dynamic_cast 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(object)); + } +}; +template +struct Disposer::Dispose_ { + static void dispose(T* object, const Disposer& disposer) { + disposer.disposeImpl(static_cast(object)); + } +}; + +template +void Disposer::dispose(T* object) const { + Dispose_::dispose(object, *this); +} + +namespace _ { // private + +template +struct OwnedBundle; + +template <> +struct OwnedBundle<> {}; + +template +struct OwnedBundle: public OwnedBundle { + OwnedBundle(First&& first, Rest&&... rest) + : OwnedBundle(kj::fwd(rest)...), first(kj::fwd(first)) {} + + // Note that it's intentional that `first` is destroyed before `rest`. This way, doing + // ptr.attach(foo, bar, baz) is equivalent to ptr.attach(foo).attach(bar).attach(baz) in terms + // of destruction order (although the former does fewer allocations). + Decay first; +}; + +template +struct DisposableOwnedBundle final: public Disposer, public OwnedBundle { + DisposableOwnedBundle(T&&... values): OwnedBundle(kj::fwd(values)...) {} + void disposeImpl(void* pointer) const override { delete this; } +}; + +template +class StaticDisposerAdapter final: public Disposer { + // Adapts a static disposer to be called dynamically. +public: + virtual void disposeImpl(void* pointer) const override { + StaticDisposer::dispose(reinterpret_cast(pointer)); + } + + static const StaticDisposerAdapter instance; +}; + +template +const StaticDisposerAdapter StaticDisposerAdapter::instance = + StaticDisposerAdapter(); + +} // namespace _ (private) + +template +template +Own Own::attach(Attachments&&... attachments) { + T* ptrCopy = ptr; + + KJ_IREQUIRE(ptrCopy != nullptr, "cannot attach to null pointer"); + + // HACK: If someone accidentally calls .attach() on a null pointer in opt mode, try our best to + // accomplish reasonable behavior: We turn the pointer non-null but still invalid, so that the + // disposer will still be called when the pointer goes out of scope. + if (ptrCopy == nullptr) ptrCopy = reinterpret_cast(1); + + auto bundle = new _::DisposableOwnedBundle, Attachments...>( + kj::mv(*this), kj::fwd(attachments)...); + return Own(ptrCopy, *bundle); +} + +template +Own attachRef(T& value, Attachments&&... attachments) { + auto bundle = new _::DisposableOwnedBundle(kj::fwd(attachments)...); + return Own(&value, *bundle); +} + +template +Own> attachVal(T&& value, Attachments&&... attachments) { + auto bundle = new _::DisposableOwnedBundle( + kj::fwd(value), kj::fwd(attachments)...); + return Own>(&bundle->first, *bundle); +} + +template +template +inline Own::Own(Own&& other) noexcept + : ptr(cast(other.ptr)) { + if (_::castToVoid(other.ptr) != reinterpret_cast(other.ptr)) { + // Oh dangit, there's some sort of multiple inheritance going on and `StaticDisposerAdapter` + // won't actually work because it'll receive a pointer pointing to the top of the object, which + // isn't exactly the same as the `U*` pointer it wants. We have no choice but to allocate + // a dynamic disposer here. + disposer = new _::DisposableOwnedBundle>(kj::mv(other)); + } else { + disposer = &_::StaticDisposerAdapter::instance; + other.ptr = nullptr; + } +} + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/miniposix.h b/vendor/capnproto/src/kj/miniposix.h new file mode 100644 index 0000000..957e739 --- /dev/null +++ b/vendor/capnproto/src/kj/miniposix.h @@ -0,0 +1,79 @@ +// 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. + +#pragma once + +// This header provides a small subset of the POSIX API. + +#include +#include + +#include +#include +#include + +#include + +// To get KJ_BEGIN_HEADER/KJ_END_HEADER +#include "common.h" + +KJ_BEGIN_HEADER + +namespace kj { +namespace miniposix { + +using ::ssize_t; +using ::read; +using ::write; +using ::close; + + +using ::pipe; +using ::mkdir; + + +// Apparently, there is a maximum number of iovecs allowed per call. I don't understand why. +// Most platforms define IOV_MAX but Linux defines only UIO_MAXIOV and others, like Hurd, +// define neither. +// +// On platforms where both IOV_MAX and UIO_MAXIOV are undefined, we poke sysconf(_SC_IOV_MAX), +// then try to fall back to the POSIX-mandated minimum of _XOPEN_IOV_MAX if that fails. +// +// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html#tag_13_23_03_01 +#if defined(IOV_MAX) +// Solaris, MacOS (& all other BSD-variants?) (and others?) +static constexpr inline size_t iovMax() { + return IOV_MAX; +} +#elif defined(UIO_MAX_IOV) +// Linux +static constexpr inline size_t iovMax() { + return UIO_MAX_IOV; +} +#else +#error "Please determine the appropriate constant for IOV_MAX on your system." +#endif + + +} // namespace miniposix +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/mutex.c++ b/vendor/capnproto/src/kj/mutex.c++ new file mode 100644 index 0000000..fdbd632 --- /dev/null +++ b/vendor/capnproto/src/kj/mutex.c++ @@ -0,0 +1,854 @@ +// 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 "mutex.h" +#include "debug.h" + +#include +#include + +#if KJ_USE_FUTEX +#include +#include +#include +#include + +#ifndef SYS_futex +// Missing on Android/Bionic. +#ifdef __NR_futex +#define SYS_futex __NR_futex +#elif defined(SYS_futex_time64) +#define SYS_futex SYS_futex_time64 +#else +#error "Need working SYS_futex" +#endif +#endif + +#ifndef FUTEX_WAIT_PRIVATE +// Missing on Android/Bionic. +#define FUTEX_WAIT_PRIVATE FUTEX_WAIT +#define FUTEX_WAKE_PRIVATE FUTEX_WAKE +#endif + +#endif + +namespace kj { +#if KJ_TRACK_LOCK_BLOCKING +static thread_local const BlockedOnReason* tlsBlockReason __attribute((tls_model("initial-exec"))); +// The initial-exec model ensures that even if this code is part of a shared library built PIC, then +// we still place this variable in the appropriate ELF section so that __tls_get_addr is avoided. +// It's unclear if __tls_get_addr is still not async signal safe in glibc. The only negative +// downside of this approach is that a shared library built with kj & lock tracking will fail if +// dlopen'ed which isn't an intended use-case for the initial implementation. + +Maybe blockedReason() noexcept { + if (tlsBlockReason == nullptr) { + return nullptr; + } + return *tlsBlockReason; +} + +static void setCurrentThreadIsWaitingFor(const BlockedOnReason* meta) { + tlsBlockReason = meta; +} + +static void setCurrentThreadIsNoLongerWaiting() { + tlsBlockReason = nullptr; +} +#elif KJ_USE_FUTEX +struct BlockedOnMutexAcquisition { + constexpr BlockedOnMutexAcquisition(const _::Mutex& mutex, LockSourceLocationArg) {} +}; + +struct BlockedOnCondVarWait { + constexpr BlockedOnCondVarWait(const _::Mutex& mutex, const void *waiter, + LockSourceLocationArg) {} +}; + +struct BlockedOnOnceInit { + constexpr BlockedOnOnceInit(const _::Once& once, LockSourceLocationArg) {} +}; + +struct BlockedOnReason { + constexpr BlockedOnReason(const BlockedOnMutexAcquisition&) {} + constexpr BlockedOnReason(const BlockedOnCondVarWait&) {} + constexpr BlockedOnReason(const BlockedOnOnceInit&) {} +}; + +static void setCurrentThreadIsWaitingFor(const BlockedOnReason* meta) {} +static void setCurrentThreadIsNoLongerWaiting() {} +#endif + +namespace _ { // private + +#if KJ_USE_FUTEX +constexpr uint Mutex::EXCLUSIVE_HELD; +constexpr uint Mutex::EXCLUSIVE_REQUESTED; +constexpr uint Mutex::SHARED_COUNT_MASK; +#endif + +inline void Mutex::addWaiter(Waiter& waiter) { +#ifdef KJ_DEBUG + assertLockedByCaller(EXCLUSIVE); +#endif + *waitersTail = waiter; + waitersTail = &waiter.next; +} +inline void Mutex::removeWaiter(Waiter& waiter) { +#ifdef KJ_DEBUG + assertLockedByCaller(EXCLUSIVE); +#endif + *waiter.prev = waiter.next; + KJ_IF_MAYBE(next, waiter.next) { + next->prev = waiter.prev; + } else { + KJ_DASSERT(waitersTail == &waiter.next); + waitersTail = waiter.prev; + } +} + +bool Mutex::checkPredicate(Waiter& waiter) { + // Run the predicate from a thread other than the waiting thread, returning true if it's time to + // signal the waiting thread. This is not only when the predicate passes, but also when it + // throws, in which case we want to propagate the exception to the waiting thread. + + if (waiter.exception != nullptr) return true; // don't run again after an exception + + bool result = false; + KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() { + result = waiter.predicate.check(); + })) { + // Exception thrown. + result = true; + waiter.exception = kj::heap(kj::mv(*exception)); + }; + return result; +} + +namespace { + +TimePoint toTimePoint(struct timespec ts) { + return kj::origin() + ts.tv_sec * kj::SECONDS + ts.tv_nsec * kj::NANOSECONDS; +} +TimePoint now() { + struct timespec now; + KJ_SYSCALL(clock_gettime(CLOCK_MONOTONIC, &now)); + return toTimePoint(now); +} +struct timespec toRelativeTimespec(Duration timeout) { + struct timespec ts; + ts.tv_sec = timeout / kj::SECONDS; + ts.tv_nsec = timeout % kj::SECONDS / kj::NANOSECONDS; + return ts; +} +struct timespec toAbsoluteTimespec(TimePoint time) { + return toRelativeTimespec(time - kj::origin()); +} + +} // namespace + +#if KJ_USE_FUTEX +// ======================================================================================= +// Futex-based implementation (Linux-only) + +#if KJ_SAVE_ACQUIRED_LOCK_INFO +#if !__GLIBC_PREREQ(2, 30) +#ifndef SYS_gettid +#error SYS_gettid is unavailable on this system +#endif + +#define gettid() ((pid_t)syscall(SYS_gettid)) +#endif + +static thread_local pid_t tlsTid = gettid(); +#define TRACK_ACQUIRED_TID() tlsTid + +Mutex::AcquiredMetadata Mutex::lockedInfo() const { + auto state = __atomic_load_n(&futex, __ATOMIC_RELAXED); + auto tid = lockedExclusivelyByThread; + auto location = lockAcquiredLocation; + + if (state & EXCLUSIVE_HELD) { + return HoldingExclusively{tid, location}; + } else { + return HoldingShared{location}; + } +} + +#else +#define TRACK_ACQUIRED_TID() 0 +#endif + +Mutex::Mutex(): futex(0) {} +Mutex::~Mutex() { + // This will crash anyway, might as well crash with a nice error message. + KJ_ASSERT(futex == 0, "Mutex destroyed while locked.") { break; } +} + +bool Mutex::lock(Exclusivity exclusivity, Maybe timeout, LockSourceLocationArg location) { + BlockedOnReason blockReason = BlockedOnMutexAcquisition{*this, location}; + KJ_DEFER(setCurrentThreadIsNoLongerWaiting()); + + auto spec = timeout.map([](Duration d) { return toRelativeTimespec(d); }); + struct timespec* specp = nullptr; + KJ_IF_MAYBE(s, spec) { + specp = s; + } + + switch (exclusivity) { + case EXCLUSIVE: + for (;;) { + uint state = 0; + if (KJ_LIKELY(__atomic_compare_exchange_n(&futex, &state, EXCLUSIVE_HELD, false, + __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))) { + + // Acquired. + break; + } + + // The mutex is contended. Set the exclusive-requested bit and wait. + if ((state & EXCLUSIVE_REQUESTED) == 0) { + if (!__atomic_compare_exchange_n(&futex, &state, state | EXCLUSIVE_REQUESTED, false, + __ATOMIC_RELAXED, __ATOMIC_RELAXED)) { + // Oops, the state changed before we could set the request bit. Start over. + continue; + } + + state |= EXCLUSIVE_REQUESTED; + } + + setCurrentThreadIsWaitingFor(&blockReason); + + auto result = syscall(SYS_futex, &futex, FUTEX_WAIT_PRIVATE, state, specp, nullptr, 0); + if (result < 0) { + if (errno == ETIMEDOUT) { + setCurrentThreadIsNoLongerWaiting(); + // We timed out, we can't remove the exclusive request flag (since others might be waiting) + // so we just return false. + return false; + } + } + } + acquiredExclusive(TRACK_ACQUIRED_TID(), location); +#if KJ_CONTENTION_WARNING_THRESHOLD + printContendedReader = false; +#endif + break; + case SHARED: { +#if KJ_CONTENTION_WARNING_THRESHOLD + kj::Maybe contentionWaitStart; +#endif + + uint state = __atomic_add_fetch(&futex, 1, __ATOMIC_ACQUIRE); + + for (;;) { + if (KJ_LIKELY((state & EXCLUSIVE_HELD) == 0)) { + // Acquired. + break; + } + +#if KJ_CONTENTION_WARNING_THRESHOLD + if (contentionWaitStart == nullptr) { + // We could have the exclusive mutex tell us how long it was holding the lock. That would + // be the nicest. However, I'm hesitant to bloat the structure. I suspect having a reader + // tell us how long it was waiting for is probably a good proxy. + contentionWaitStart = kj::systemPreciseMonotonicClock().now(); + } +#endif + + setCurrentThreadIsWaitingFor(&blockReason); + + // The mutex is exclusively locked by another thread. Since we incremented the counter + // already, we just have to wait for it to be unlocked. + auto result = syscall(SYS_futex, &futex, FUTEX_WAIT_PRIVATE, state, specp, nullptr, 0); + if (result < 0) { + // If we timeout though, we need to signal that we're not waiting anymore. + if (errno == ETIMEDOUT) { + setCurrentThreadIsNoLongerWaiting(); + state = __atomic_sub_fetch(&futex, 1, __ATOMIC_RELAXED); + + // We may have unlocked since we timed out. So act like we just unlocked the mutex + // and maybe send a wait signal if needed. See Mutex::unlock SHARED case. + if (KJ_UNLIKELY(state == EXCLUSIVE_REQUESTED)) { + if (__atomic_compare_exchange_n( + &futex, &state, 0, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) { + // Wake all exclusive waiters. We have to wake all of them because one of them will + // grab the lock while the others will re-establish the exclusive-requested bit. + syscall(SYS_futex, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0); + } + } + return false; + } + } + state = __atomic_load_n(&futex, __ATOMIC_ACQUIRE); + } + +#ifdef KJ_CONTENTION_WARNING_THRESHOLD + KJ_IF_MAYBE(start, contentionWaitStart) { + if (__atomic_load_n(&printContendedReader, __ATOMIC_RELAXED)) { + // Double-checked lock avoids the CPU needing to acquire the lock in most cases. + if (__atomic_exchange_n(&printContendedReader, false, __ATOMIC_RELAXED)) { + auto contentionDuration = kj::systemPreciseMonotonicClock().now() - *start; + KJ_LOG(WARNING, "Acquired contended lock", location, contentionDuration, + kj::getStackTrace()); + } + } + } +#endif + + // We just want to record the lock being acquired somewhere but the specific location doesn't + // matter. This does mean that race conditions could occur where a thread might read this + // inconsistently (e.g. filename from 1 lock & function from another). This currently is just + // meant to be a debugging aid for manual analysis so it's OK for that purpose. If it's ever + // required for this to be used for anything else, then this should probably be changed to + // use an additional atomic variable that can ensure only one writer updates this. Or use the + // futex variable to ensure that this is only done for the first one to acquire the lock, + // although there may be thundering herd problems with that whereby there's a long wallclock + // time between when the lock is acquired and when the location is updated (since the first + // locker isn't really guaranteed to be the first one unlocked). + acquiredShared(location); + + break; + } + } + return true; +} + +void Mutex::unlock(Exclusivity exclusivity, Waiter* waiterToSkip) { + switch (exclusivity) { + case EXCLUSIVE: { + KJ_DASSERT(futex & EXCLUSIVE_HELD, "Unlocked a mutex that wasn't locked."); + +#ifdef KJ_CONTENTION_WARNING_THRESHOLD + auto acquiredLocation = releasingExclusive(); +#endif + + // First check if there are any conditional waiters. Note we only do this when unlocking an + // exclusive lock since under a shared lock the state couldn't have changed. + auto nextWaiter = waitersHead; + for (;;) { + KJ_IF_MAYBE(waiter, nextWaiter) { + nextWaiter = waiter->next; + + if (waiter != waiterToSkip && checkPredicate(*waiter)) { + // This waiter's predicate now evaluates true, so wake it up. + if (waiter->hasTimeout) { + // In this case we need to be careful to make sure the target thread isn't already + // processing a timeout, so we need to do an atomic CAS rather than just a store. + uint expected = 0; + if (__atomic_compare_exchange_n(&waiter->futex, &expected, 1, false, + __ATOMIC_RELEASE, __ATOMIC_RELAXED)) { + // Good, we set it to 1, transferring ownership of the mutex. Continue on below. + } else { + // Looks like the thread already timed out and set its own futex to 1. In that + // case it is going to try to lock the mutex itself, so we should NOT attempt an + // ownership transfer as this will deadlock. + // + // We have two options here: We can continue along the waiter list looking for + // another waiter that's ready to be signaled, or we could drop out of the list + // immediately since we know that another thread is already waiting for the lock + // and will re-evaluate the waiter queue itself when it is done. It feels cleaner + // to me to continue. + continue; + } + } else { + __atomic_store_n(&waiter->futex, 1, __ATOMIC_RELEASE); + } + syscall(SYS_futex, &waiter->futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0); + + // We transferred ownership of the lock to this waiter, so we're done now. + return; + } + } else { + // No more waiters. + break; + } + } + +#ifdef KJ_CONTENTION_WARNING_THRESHOLD + uint readerCount; + { + uint oldState = __atomic_load_n(&futex, __ATOMIC_RELAXED); + readerCount = oldState & SHARED_COUNT_MASK; + if (readerCount >= KJ_CONTENTION_WARNING_THRESHOLD) { + // Atomic not needed because we're still holding the exclusive lock. + printContendedReader = true; + } + } +#endif + + // Didn't wake any waiters, so wake normally. + uint oldState = __atomic_fetch_and( + &futex, ~(EXCLUSIVE_HELD | EXCLUSIVE_REQUESTED), __ATOMIC_RELEASE); + + if (KJ_UNLIKELY(oldState & ~EXCLUSIVE_HELD)) { + // Other threads are waiting. If there are any shared waiters, they now collectively hold + // the lock, and we must wake them up. If there are any exclusive waiters, we must wake + // them up even if readers are waiting so that at the very least they may re-establish the + // EXCLUSIVE_REQUESTED bit that we just removed. + syscall(SYS_futex, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0); + +#ifdef KJ_CONTENTION_WARNING_THRESHOLD + if (readerCount >= KJ_CONTENTION_WARNING_THRESHOLD) { + KJ_LOG(WARNING, "excessively many readers were waiting on this lock", readerCount, + acquiredLocation, kj::getStackTrace()); + } +#endif + } + break; + } + + case SHARED: { + KJ_DASSERT(futex & SHARED_COUNT_MASK, "Unshared a mutex that wasn't shared."); + uint state = __atomic_sub_fetch(&futex, 1, __ATOMIC_RELEASE); + + // The only case where anyone is waiting is if EXCLUSIVE_REQUESTED is set, and the only time + // it makes sense to wake up that waiter is if the shared count has reached zero. + if (KJ_UNLIKELY(state == EXCLUSIVE_REQUESTED)) { + if (__atomic_compare_exchange_n( + &futex, &state, 0, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) { + // Wake all exclusive waiters. We have to wake all of them because one of them will + // grab the lock while the others will re-establish the exclusive-requested bit. + syscall(SYS_futex, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0); + } + } + break; + } + } +} + +void Mutex::assertLockedByCaller(Exclusivity exclusivity) const { + switch (exclusivity) { + case EXCLUSIVE: + KJ_ASSERT(futex & EXCLUSIVE_HELD, + "Tried to call getAlreadyLocked*() but lock is not held."); + break; + case SHARED: + KJ_ASSERT(futex & SHARED_COUNT_MASK, + "Tried to call getAlreadyLocked*() but lock is not held."); + break; + } +} + +void Mutex::wait(Predicate& predicate, Maybe timeout, LockSourceLocationArg location) { + // Add waiter to list. + Waiter waiter { nullptr, waitersTail, predicate, nullptr, 0, timeout != nullptr }; + addWaiter(waiter); + + BlockedOnReason blockReason = BlockedOnCondVarWait{*this, &waiter, location}; + KJ_DEFER(setCurrentThreadIsNoLongerWaiting()); + + // To guarantee that we've re-locked the mutex before scope exit, keep track of whether it is + // currently. + bool currentlyLocked = true; + KJ_DEFER({ + // Infinite timeout for re-obtaining the lock is on purpose because the post-condition for this + // function has to be that the lock state hasn't changed (& we have to be locked when we enter + // since that's how condvars work). + if (!currentlyLocked) lock(EXCLUSIVE, nullptr, location); + removeWaiter(waiter); + }); + + if (!predicate.check()) { + unlock(EXCLUSIVE, &waiter); + currentlyLocked = false; + + struct timespec ts; + struct timespec* tsp = nullptr; + KJ_IF_MAYBE(t, timeout) { + ts = toAbsoluteTimespec(now() + *t); + tsp = &ts; + } + + setCurrentThreadIsWaitingFor(&blockReason); + + // Wait for someone to set our futex to 1. + for (;;) { + // Note we use FUTEX_WAIT_BITSET_PRIVATE + FUTEX_BITSET_MATCH_ANY to get the same effect as + // FUTEX_WAIT_PRIVATE except that the timeout is specified as an absolute time based on + // CLOCK_MONOTONIC. Otherwise, FUTEX_WAIT_PRIVATE interprets it as a relative time, forcing + // us to recompute the time after every iteration. + KJ_SYSCALL_HANDLE_ERRORS(syscall(SYS_futex, + &waiter.futex, FUTEX_WAIT_BITSET_PRIVATE, 0, tsp, nullptr, FUTEX_BITSET_MATCH_ANY)) { + case EAGAIN: + // Indicates that the futex was already non-zero by the time the kernel looked at it. + // Not an error. + break; + case ETIMEDOUT: { + // Wait timed out. This leaves us in a bit of a pickle: Ownership of the mutex was not + // transferred to us from another thread. So, we need to lock it ourselves. But, another + // thread might be in the process of signaling us and transferring ownership. So, we + // first must atomically take control of our destiny. + KJ_ASSERT(timeout != nullptr); + uint expected = 0; + if (__atomic_compare_exchange_n(&waiter.futex, &expected, 1, false, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) { + // OK, we set our own futex to 1. That means no other thread will, and so we won't be + // receiving a mutex ownership transfer. We have to lock the mutex ourselves. + setCurrentThreadIsNoLongerWaiting(); + lock(EXCLUSIVE, nullptr, location); + currentlyLocked = true; + return; + } else { + // Oh, someone else actually did signal us, apparently. Let's move on as if the futex + // call told us so. + break; + } + } + default: + KJ_FAIL_SYSCALL("futex(FUTEX_WAIT_PRIVATE)", error); + } + + setCurrentThreadIsNoLongerWaiting(); + + if (__atomic_load_n(&waiter.futex, __ATOMIC_ACQUIRE)) { + // We received a lock ownership transfer from another thread. + currentlyLocked = true; + + // The other thread checked the predicate before the transfer. +#ifdef KJ_DEBUG + assertLockedByCaller(EXCLUSIVE); +#endif + + KJ_IF_MAYBE(exception, waiter.exception) { + // The predicate threw an exception, apparently. Propagate it. + // TODO(someday): Could we somehow have this be a recoverable exception? Presumably we'd + // then want MutexGuarded::when() to skip calling the callback, but then what should it + // return, since it normally returns the callback's result? Or maybe people who disable + // exceptions just really should not write predicates that can throw. + kj::throwFatalException(kj::mv(**exception)); + } + + return; + } + } + } +} + +void Once::runOnce(Initializer& init, LockSourceLocationArg location) { +startOver: + uint state = UNINITIALIZED; + if (__atomic_compare_exchange_n(&futex, &state, INITIALIZING, false, + __ATOMIC_RELAXED, __ATOMIC_RELAXED)) { + // It's our job to initialize! + { + KJ_ON_SCOPE_FAILURE({ + // An exception was thrown by the initializer. We have to revert. + if (__atomic_exchange_n(&futex, UNINITIALIZED, __ATOMIC_RELEASE) == + INITIALIZING_WITH_WAITERS) { + // Someone was waiting for us to finish. + syscall(SYS_futex, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0); + } + }); + + init.run(); + } + if (__atomic_exchange_n(&futex, INITIALIZED, __ATOMIC_RELEASE) == + INITIALIZING_WITH_WAITERS) { + // Someone was waiting for us to finish. + syscall(SYS_futex, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0); + } + } else { + BlockedOnReason blockReason = BlockedOnOnceInit{*this, location}; + KJ_DEFER(setCurrentThreadIsNoLongerWaiting()); + + for (;;) { + if (state == INITIALIZED) { + break; + } else if (state == INITIALIZING) { + // Initialization is taking place in another thread. Indicate that we're waiting. + if (!__atomic_compare_exchange_n(&futex, &state, INITIALIZING_WITH_WAITERS, true, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) { + // State changed, retry. + continue; + } + } else { + KJ_DASSERT(state == INITIALIZING_WITH_WAITERS); + } + + // Wait for initialization. + setCurrentThreadIsWaitingFor(&blockReason); + syscall(SYS_futex, &futex, FUTEX_WAIT_PRIVATE, INITIALIZING_WITH_WAITERS, + nullptr, nullptr, 0); + state = __atomic_load_n(&futex, __ATOMIC_ACQUIRE); + + if (state == UNINITIALIZED) { + // Oh hey, apparently whoever was trying to initialize gave up. Let's take it from the + // top. + goto startOver; + } + } + } +} + +void Once::reset() { + uint state = INITIALIZED; + if (!__atomic_compare_exchange_n(&futex, &state, UNINITIALIZED, + false, __ATOMIC_RELEASE, __ATOMIC_RELAXED)) { + KJ_FAIL_REQUIRE("reset() called while not initialized."); + } +} + +#else +// ======================================================================================= +// Generic pthreads-based implementation + +#define KJ_PTHREAD_CALL(code) \ + { \ + int pthreadError = code; \ + if (pthreadError != 0) { \ + KJ_FAIL_SYSCALL(#code, pthreadError); \ + } \ + } + +#define KJ_PTHREAD_CLEANUP(code) \ + { \ + int pthreadError = code; \ + if (pthreadError != 0) { \ + KJ_LOG(ERROR, #code, strerror(pthreadError)); \ + } \ + } + +Mutex::Mutex(): mutex(PTHREAD_RWLOCK_INITIALIZER) { +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070 + // In older versions of MacOS, mutexes initialized statically cannot be destroyed, + // so we must call the init function. + KJ_PTHREAD_CALL(pthread_rwlock_init(&mutex, NULL)); +#endif +} +Mutex::~Mutex() { + KJ_PTHREAD_CLEANUP(pthread_rwlock_destroy(&mutex)); +} + +bool Mutex::lock(Exclusivity exclusivity, Maybe timeout, NoopSourceLocation) { + if (timeout != nullptr) { + KJ_UNIMPLEMENTED("Locking a mutex with a timeout is only supported on Linux."); + } + switch (exclusivity) { + case EXCLUSIVE: + KJ_PTHREAD_CALL(pthread_rwlock_wrlock(&mutex)); + break; + case SHARED: + KJ_PTHREAD_CALL(pthread_rwlock_rdlock(&mutex)); + break; + } + return true; +} + +void Mutex::unlock(Exclusivity exclusivity, Waiter* waiterToSkip) { + KJ_DEFER(KJ_PTHREAD_CALL(pthread_rwlock_unlock(&mutex))); + + if (exclusivity == EXCLUSIVE) { + // Check if there are any conditional waiters. Note we only do this when unlocking an + // exclusive lock since under a shared lock the state couldn't have changed. + auto nextWaiter = waitersHead; + for (;;) { + KJ_IF_MAYBE(waiter, nextWaiter) { + nextWaiter = waiter->next; + + if (waiter != waiterToSkip && checkPredicate(*waiter)) { + // This waiter's predicate now evaluates true, so wake it up. It doesn't matter if we + // use _signal() vs. _broadcast() here since there's always only one thread waiting. + KJ_PTHREAD_CALL(pthread_mutex_lock(&waiter->stupidMutex)); + KJ_PTHREAD_CALL(pthread_cond_signal(&waiter->condvar)); + KJ_PTHREAD_CALL(pthread_mutex_unlock(&waiter->stupidMutex)); + + // We only need to wake one waiter. Note that unlike the futex-based implementation, we + // cannot "transfer ownership" of the lock to the waiter, therefore we cannot guarantee + // that the condition is still true when that waiter finally awakes. However, if the + // condition is no longer true at that point, the waiter will re-check all other waiters' + // conditions and possibly wake up any other waiter who is now ready, hence we still only + // need to wake one waiter here. + break; + } + } else { + // No more waiters. + break; + } + } + } +} + +void Mutex::assertLockedByCaller(Exclusivity exclusivity) const { + switch (exclusivity) { + case EXCLUSIVE: + // A read lock should fail if the mutex is already held for writing. + if (pthread_rwlock_tryrdlock(&mutex) == 0) { + pthread_rwlock_unlock(&mutex); + KJ_FAIL_ASSERT("Tried to call getAlreadyLocked*() but lock is not held."); + } + break; + case SHARED: + // A write lock should fail if the mutex is already held for reading or writing. We don't + // have any way to prove that the lock is held only for reading. + if (pthread_rwlock_trywrlock(&mutex) == 0) { + pthread_rwlock_unlock(&mutex); + KJ_FAIL_ASSERT("Tried to call getAlreadyLocked*() but lock is not held."); + } + break; + } +} + +void Mutex::wait(Predicate& predicate, Maybe timeout, NoopSourceLocation) { + // Add waiter to list. + Waiter waiter { + nullptr, waitersTail, predicate, nullptr, + PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER + }; + +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070 + // In older versions of MacOS, mutexes initialized statically cannot be destroyed, + // so we must call the init function. + KJ_PTHREAD_CALL(pthread_cond_init(&waiter.condvar, NULL)); + KJ_PTHREAD_CALL(pthread_mutex_init(&waiter.stupidMutex, NULL)); +#endif + + addWaiter(waiter); + + // To guarantee that we've re-locked the mutex before scope exit, keep track of whether it is + // currently. + bool currentlyLocked = true; + KJ_DEFER({ + if (!currentlyLocked) lock(EXCLUSIVE, nullptr, NoopSourceLocation{}); + removeWaiter(waiter); + + // Destroy pthread objects. + KJ_PTHREAD_CLEANUP(pthread_mutex_destroy(&waiter.stupidMutex)); + KJ_PTHREAD_CLEANUP(pthread_cond_destroy(&waiter.condvar)); + }); + +#if !__APPLE__ + if (timeout != nullptr) { + // Oops, the default condvar uses the wall clock, which is dumb... fix it to use the monotonic + // clock. (Except not on macOS, where pthread_condattr_setclock() is unimplemented, but there's + // a bizarre pthread_cond_timedwait_relative_np() method we can use instead...) + pthread_condattr_t attr; + KJ_PTHREAD_CALL(pthread_condattr_init(&attr)); + KJ_PTHREAD_CALL(pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)); + pthread_cond_init(&waiter.condvar, &attr); + KJ_PTHREAD_CALL(pthread_condattr_destroy(&attr)); + } +#endif + + Maybe endTime = timeout.map([](Duration d) { + return toAbsoluteTimespec(now() + d); + }); + + while (!predicate.check()) { + // pthread condvars only work with basic mutexes, not rwlocks. So, we need to lock a basic + // mutex before we unlock the real mutex, and the signaling thread also needs to lock this + // mutex, in order to ensure that this thread is actually waiting on the condvar before it is + // signaled. + KJ_PTHREAD_CALL(pthread_mutex_lock(&waiter.stupidMutex)); + + // OK, now we can unlock the main mutex. + unlock(EXCLUSIVE, &waiter); + currentlyLocked = false; + + bool timedOut = false; + + // Wait for someone to signal the condvar. + KJ_IF_MAYBE(t, endTime) { +#if __APPLE__ + // On macOS, the absolute timeout can only be specified in wall time, not monotonic time, + // which means modifying the system clock will break the wait. However, macOS happens to + // provide an alternative relative-time wait function, so I guess we'll use that. It does + // require recomputing the time every iteration... + struct timespec ts = toRelativeTimespec(kj::max(toTimePoint(*t) - now(), 0 * kj::SECONDS)); + int error = pthread_cond_timedwait_relative_np(&waiter.condvar, &waiter.stupidMutex, &ts); +#else + int error = pthread_cond_timedwait(&waiter.condvar, &waiter.stupidMutex, t); +#endif + if (error != 0) { + if (error == ETIMEDOUT) { + timedOut = true; + } else { + KJ_FAIL_SYSCALL("pthread_cond_timedwait", error); + } + } + } else { + KJ_PTHREAD_CALL(pthread_cond_wait(&waiter.condvar, &waiter.stupidMutex)); + } + + // We have to be very careful about lock ordering here. We need to unlock stupidMutex before + // re-locking the main mutex, because another thread may have a lock on the main mutex already + // and be waiting for a lock on stupidMutex. Note that other thread may signal the condvar + // right after we unlock stupidMutex but before we re-lock the main mutex. That is fine, + // because we've already been signaled. + KJ_PTHREAD_CALL(pthread_mutex_unlock(&waiter.stupidMutex)); + + lock(EXCLUSIVE, nullptr, NoopSourceLocation{}); + currentlyLocked = true; + + KJ_IF_MAYBE(exception, waiter.exception) { + // The predicate threw an exception, apparently. Propagate it. + // TODO(someday): Could we somehow have this be a recoverable exception? Presumably we'd + // then want MutexGuarded::when() to skip calling the callback, but then what should it + // return, since it normally returns the callback's result? Or maybe people who disable + // exceptions just really should not write predicates that can throw. + kj::throwFatalException(kj::mv(**exception)); + } + + if (timedOut) { + return; + } + } +} + +Once::Once(bool startInitialized) + : state(startInitialized ? INITIALIZED : UNINITIALIZED), + mutex(PTHREAD_MUTEX_INITIALIZER) { +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070 + // In older versions of MacOS, mutexes initialized statically cannot be destroyed, + // so we must call the init function. + KJ_PTHREAD_CALL(pthread_mutex_init(&mutex, NULL)); +#endif +} +Once::~Once() { + KJ_PTHREAD_CLEANUP(pthread_mutex_destroy(&mutex)); +} + +void Once::runOnce(Initializer& init, NoopSourceLocation) { + KJ_PTHREAD_CALL(pthread_mutex_lock(&mutex)); + KJ_DEFER(KJ_PTHREAD_CALL(pthread_mutex_unlock(&mutex))); + + if (state != UNINITIALIZED) { + return; + } + + init.run(); + + __atomic_store_n(&state, INITIALIZED, __ATOMIC_RELEASE); +} + +void Once::reset() { + State oldState = INITIALIZED; + if (!__atomic_compare_exchange_n(&state, &oldState, UNINITIALIZED, + false, __ATOMIC_RELEASE, __ATOMIC_RELAXED)) { + KJ_FAIL_REQUIRE("reset() called while not initialized."); + } +} + +#endif + +} // namespace _ (private) +} // namespace kj diff --git a/vendor/capnproto/src/kj/mutex.h b/vendor/capnproto/src/kj/mutex.h new file mode 100644 index 0000000..6cec6db --- /dev/null +++ b/vendor/capnproto/src/kj/mutex.h @@ -0,0 +1,739 @@ +// 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. + +#pragma once + +#include "debug.h" +#include "memory.h" +#include +#include "time.h" +#include "source-location.h" +#include "one-of.h" + +KJ_BEGIN_HEADER + +#if __linux__ && !defined(KJ_USE_FUTEX) +#define KJ_USE_FUTEX 1 +#endif + +#if !KJ_USE_FUTEX +// We fall back to pthreads when we don't have a better platform-specific primitive. pthreads +// mutexes are bloated, though, so we use futex() on Linux. +// +// TODO(someday): Write efficient low-level locking primitives for other platforms. +#include +#endif + +// There are 3 macros controlling lock tracking: +// KJ_TRACK_LOCK_BLOCKING will set up async signal safe TLS variables that can be used to identify +// the KJ primitive blocking the current thread. +// KJ_SAVE_ACQUIRED_LOCK_INFO will allow introspection of a Mutex to get information about what is +// currently holding the lock. +// KJ_TRACK_LOCK_ACQUISITION is automatically enabled by either one of them. + +#if KJ_TRACK_LOCK_BLOCKING +// Lock tracking is required to keep track of what blocked. +#define KJ_TRACK_LOCK_ACQUISITION 1 +#endif + +#if KJ_SAVE_ACQUIRED_LOCK_INFO +#define KJ_TRACK_LOCK_ACQUISITION 1 +#include +#endif + +namespace kj { +#if KJ_TRACK_LOCK_ACQUISITION +#if !KJ_USE_FUTEX +#error Lock tracking is only currently supported for futex-based mutexes. +#endif + +#if !KJ_COMPILER_SUPPORTS_SOURCE_LOCATION +#error C++20 or newer is required (or the use of clang/gcc). +#endif + +using LockSourceLocation = SourceLocation; +using LockSourceLocationArg = const SourceLocation&; +// On x86-64 the codegen is optimal if the argument has type const& for the location. However, +// since this conflicts with the optimal call signature for NoopSourceLocation, +// LockSourceLocationArg is used to conditionally select the right type without polluting the usage +// themselves. Interestingly this makes no difference on ARM. +// https://godbolt.org/z/q6G8ee5a3 +#else +using LockSourceLocation = NoopSourceLocation; +using LockSourceLocationArg = NoopSourceLocation; +#endif + + +class Exception; + +// ======================================================================================= +// Private details -- public interfaces follow below. + +namespace _ { // private + +#if KJ_SAVE_ACQUIRED_LOCK_INFO +class HoldingExclusively { + // The lock is being held in exclusive mode. +public: + constexpr HoldingExclusively(pid_t tid, const SourceLocation& location) + : heldBy(tid), acquiredAt(location) {} + + pid_t threadHoldingLock() const { return heldBy; } + const SourceLocation& lockAcquiredAt() const { return acquiredAt; } + +private: + pid_t heldBy; + SourceLocation acquiredAt; +}; + +class HoldingShared { + // The lock is being held in shared mode currently. Which threads are holding this lock open + // is unknown. +public: + constexpr HoldingShared(const SourceLocation& location) : acquiredAt(location) {} + + const SourceLocation& lockAcquiredAt() const { return acquiredAt; } + +private: + SourceLocation acquiredAt; +}; +#endif + +class Mutex { + // Internal implementation details. See `MutexGuarded`. + + struct Waiter; + +public: + Mutex(); + ~Mutex(); + KJ_DISALLOW_COPY_AND_MOVE(Mutex); + + enum Exclusivity { + EXCLUSIVE, + SHARED + }; + + bool lock(Exclusivity exclusivity, Maybe timeout, LockSourceLocationArg location); + void unlock(Exclusivity exclusivity, Waiter* waiterToSkip = nullptr); + + void assertLockedByCaller(Exclusivity exclusivity) const; + // 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. + + class Predicate { + public: + virtual bool check() = 0; + }; + + void wait(Predicate& predicate, Maybe timeout, LockSourceLocationArg location); + // If predicate.check() returns false, unlock the mutex until predicate.check() returns true, or + // when the timeout (if any) expires. The mutex is always re-locked when this returns regardless + // of whether the timeout expired, and including if it throws. + // + // Requires that the mutex is already exclusively locked before calling. + +#if KJ_SAVE_ACQUIRED_LOCK_INFO + using AcquiredMetadata = kj::OneOf; + KJ_DISABLE_TSAN AcquiredMetadata lockedInfo() const; + // Returns metadata about this lock when its held. This method is async signal safe. It must also + // be called in a state where it's guaranteed that the lock state won't be released by another + // thread. In other words this has to be called from the signal handler within the thread that's + // holding the lock. +#endif + +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. + +#ifdef KJ_CONTENTION_WARNING_THRESHOLD + bool printContendedReader = false; +#endif + + static constexpr uint EXCLUSIVE_HELD = 1u << 31; + static constexpr uint EXCLUSIVE_REQUESTED = 1u << 30; + static constexpr uint SHARED_COUNT_MASK = EXCLUSIVE_REQUESTED - 1; + +#else + mutable pthread_rwlock_t mutex; +#endif + +#if KJ_SAVE_ACQUIRED_LOCK_INFO + pid_t lockedExclusivelyByThread = 0; + SourceLocation lockAcquiredLocation; + + KJ_DISABLE_TSAN void acquiredExclusive(pid_t tid, const SourceLocation& location) noexcept { + lockAcquiredLocation = location; + __atomic_store_n(&lockedExclusivelyByThread, tid, __ATOMIC_RELAXED); + } + + KJ_DISABLE_TSAN void acquiredShared(const SourceLocation& location) noexcept { + lockAcquiredLocation = location; + } + + KJ_DISABLE_TSAN SourceLocation releasingExclusive() noexcept { + auto tmp = lockAcquiredLocation; + lockAcquiredLocation = SourceLocation{}; + lockedExclusivelyByThread = 0; + return tmp; + } +#else + static constexpr void acquiredExclusive(uint, LockSourceLocationArg) {} + static constexpr void acquiredShared(LockSourceLocationArg) {} + static constexpr NoopSourceLocation releasingExclusive() { return NoopSourceLocation{}; } +#endif + struct Waiter { + kj::Maybe next; + kj::Maybe* prev; + Predicate& predicate; + Maybe> exception; +#if KJ_USE_FUTEX + uint futex; + bool hasTimeout; +#else + pthread_cond_t condvar; + + pthread_mutex_t stupidMutex; + // pthread condvars are only compatible with basic pthread mutexes, not rwlocks, for no + // particularly good reason. To work around this, we need an extra mutex per condvar. +#endif + }; + + kj::Maybe waitersHead = nullptr; + kj::Maybe* waitersTail = &waitersHead; + // linked list of waiters; can only modify under lock + + inline void addWaiter(Waiter& waiter); + inline void removeWaiter(Waiter& waiter); + bool checkPredicate(Waiter& waiter); +}; + +class Once { + // Internal implementation details. See `Lazy`. + +public: +#if KJ_USE_FUTEX + inline Once(bool startInitialized = false) + : futex(startInitialized ? INITIALIZED : UNINITIALIZED) {} +#else + Once(bool startInitialized = false); + ~Once(); +#endif + KJ_DISALLOW_COPY_AND_MOVE(Once); + + class Initializer { + public: + virtual void run() = 0; + }; + + void runOnce(Initializer& init, LockSourceLocationArg location); + + 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 + } + + 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 + }; + +#else + enum State { + UNINITIALIZED, + INITIALIZED + }; + State state; + pthread_mutex_t mutex; +#endif +}; + +} // namespace _ (private) + +// ======================================================================================= +// Public interface + +template +class Locked { + // Return type for `MutexGuarded::lock()`. `Locked` 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() ? _::Mutex::SHARED : _::Mutex::EXCLUSIVE); + } + + inline Locked& operator=(Locked&& other) { + if (mutex != nullptr) mutex->unlock(isConst() ? _::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() ? _::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; } + + template + void wait(Cond&& condition, Maybe timeout = nullptr, + LockSourceLocationArg location = {}) { + // Unlocks the lock until `condition(state)` evaluates true (where `state` is type `const T&` + // referencing the object protected by the lock). + + // We can't wait on a shared lock because the internal bookkeeping needed for a wait requires + // the protection of an exclusive lock. + static_assert(!isConst(), "cannot wait() on shared lock"); + + struct PredicateImpl final: public _::Mutex::Predicate { + bool check() override { + return condition(value); + } + + Cond&& condition; + const T& value; + + PredicateImpl(Cond&& condition, const T& value) + : condition(kj::fwd(condition)), value(value) {} + }; + + PredicateImpl impl(kj::fwd(condition), *ptr); + mutex->wait(impl, timeout, location); + } + +private: + _::Mutex* mutex; + T* ptr; + + inline Locked(_::Mutex& mutex, T& value): mutex(&mutex), ptr(&value) {} + + template + friend class MutexGuarded; + template + friend class ExternalMutexGuarded; + + +}; + +template +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 + explicit MutexGuarded(Params&&... params); + // Initialize the mutex-bounded object by passing the given parameters to its constructor. + + Locked lockExclusive(LockSourceLocationArg location = {}) const; + // Exclusively locks the object and returns it. The returned `Locked` can be passed by + // move, similar to `Own`. + // + // 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 lockShared(LockSourceLocationArg location = {}) 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. + + Maybe> lockExclusiveWithTimeout(Duration timeout, + LockSourceLocationArg location = {}) const; + // Attempts to exclusively lock the object. If the timeout elapses before the lock is acquired, + // this returns null. + + Maybe> lockSharedWithTimeout(Duration timeout, + LockSourceLocationArg location = {}) const; + // Attempts to lock the value for shared access. If the timeout elapses before the lock is acquired, + // this returns null. + + 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. + + template + auto when(Cond&& condition, Func&& callback, Maybe timeout = nullptr, + LockSourceLocationArg location = {}) const + -> decltype(callback(instance())) { + // Waits until condition(state) returns true, then calls callback(state) under lock. + // + // `condition`, when called, receives as its parameter a const reference to the state, which is + // locked (either shared or exclusive). `callback` receives a mutable reference, which is + // exclusively locked. + // + // `condition()` may be called multiple times, from multiple threads, while waiting for the + // condition to become true. It may even return true once, but then be called more times. + // It is guaranteed, though, that at the time `callback()` is finally called, `condition()` + // would currently return true (assuming it is a pure function of the guarded data). + // + // If `timeout` is specified, then after the given amount of time, the callback will be called + // regardless of whether the condition is true. In this case, when `callback()` is called, + // `condition()` may in fact evaluate false, but *only* if the timeout was reached. + // + // TODO(cleanup): lock->wait() is a better interface. Can we deprecate this one? + + auto lock = lockExclusive(); + lock.wait(kj::fwd(condition), timeout, location); + return callback(value); + } + +private: + mutable _::Mutex mutex; + mutable T value; +}; + +template +class MutexGuarded { + // MutexGuarded cannot guard a const type. This would be pointless anyway, and would complicate + // the implementation of Locked, which uses constness to decide what kind of lock it holds. + static_assert(sizeof(T) < 0, "MutexGuarded's type cannot be const."); +}; + +template +class ExternalMutexGuarded { + // Holds a value that can only be manipulated while some other mutex is locked. + // + // The ExternalMutexGuarded lives *outside* the scope of any lock on the mutex, but ensures + // that the value it holds can only be accessed under lock by forcing the caller to present a + // lock before accessing the value. + // + // Additionally, ExternalMutexGuarded's destructor will take an exclusive lock on the mutex + // while destroying the held value, unless the value has been release()ed before hand. + // + // The type T must have the following properties (which probably all movable types satisfy): + // - T is movable. + // - Immediately after any of the following has happened, T's destructor is effectively a no-op + // (hence certainly not requiring locks): + // - The value has been default-constructed. + // - The value has been initialized by-move from a default-constructed T. + // - The value has been moved away. + // - If ExternalMutexGuarded is ever moved, then T must have a move constructor and move + // assignment operator that do not follow any pointers, therefore do not need to take a lock. + // + // Inherits from LockSourceLocation to perform an empty base class optimization when lock tracking + // is compiled out. Once the minimum C++ standard for the KJ library is C++20, this optimization + // could be replaced by a member variable with a [[no_unique_address]] annotation. +public: + ExternalMutexGuarded(LockSourceLocationArg location = {}) + : location(location) {} + + template + ExternalMutexGuarded(Locked lock, Params&&... params, LockSourceLocationArg location = {}) + : mutex(lock.mutex), + value(kj::fwd(params)...), + location(location) {} + // Construct the value in-place. This constructor requires passing ownership of the lock into + // the constructor. Normally this should be a lock that you take on the line calling the + // constructor, like: + // + // ExternalMutexGuarded foo(someMutexGuarded.lockExclusive()); + // + // The reason this constructor does not accept an lvalue reference to an existing lock is because + // this would be deadlock-prone: If an exception were thrown immediately after the constructor + // completed, then the destructor would deadlock, because the lock would still be held. An + // ExternalMutexGuarded must live outside the scope of any locks to avoid such a deadlock. + + ~ExternalMutexGuarded() noexcept(false) { + if (mutex != nullptr) { + mutex->lock(_::Mutex::EXCLUSIVE, nullptr, location); + KJ_DEFER(mutex->unlock(_::Mutex::EXCLUSIVE)); + value = T(); + } + } + + ExternalMutexGuarded(ExternalMutexGuarded&& other) + : mutex(other.mutex), value(kj::mv(other.value)), location(other.location) { + other.mutex = nullptr; + } + ExternalMutexGuarded& operator=(ExternalMutexGuarded&& other) { + mutex = other.mutex; + value = kj::mv(other.value); + location = other.location; + other.mutex = nullptr; + return *this; + } + + template + void set(Locked& lock, T&& newValue) { + KJ_IREQUIRE(mutex == nullptr); + mutex = lock.mutex; + value = kj::mv(newValue); + } + + template + T& get(Locked& lock) { + KJ_IREQUIRE(lock.mutex == mutex); + return value; + } + + template + const T& get(Locked& lock) const { + KJ_IREQUIRE(lock.mutex == mutex); + return value; + } + + template + T release(Locked& lock) { + // Release (move away) the value. This allows the destructor to skip locking the mutex. + KJ_IREQUIRE(lock.mutex == mutex); + T result = kj::mv(value); + mutex = nullptr; + return result; + } + +private: + _::Mutex* mutex = nullptr; + T value; + KJ_NO_UNIQUE_ADDRESS LockSourceLocation location; + // When built against C++20 (or clang >= 9.0), the overhead of this is elided. Otherwise this + // struct will be 1 byte larger than it would otherwise be. +}; + +template +class Lazy { + // A lazily-initialized value. + +public: + template + T& get(Func&& init, LockSourceLocationArg location = {}); + template + const T& get(Func&& init, LockSourceLocationArg location = {}) 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&` as its parameter and returns + // `Own`. 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 space; + mutable Own value; + + template + class InitImpl; +}; + +// ======================================================================================= +// Inline implementation details + +template +template +inline MutexGuarded::MutexGuarded(Params&&... params) + : value(kj::fwd(params)...) {} + +template +inline Locked MutexGuarded::lockExclusive(LockSourceLocationArg location) + const { + mutex.lock(_::Mutex::EXCLUSIVE, nullptr, location); + return Locked(mutex, value); +} + +template +inline Locked MutexGuarded::lockShared(LockSourceLocationArg location) const { + mutex.lock(_::Mutex::SHARED, nullptr, location); + return Locked(mutex, value); +} + +template +inline Maybe> MutexGuarded::lockExclusiveWithTimeout(Duration timeout, + LockSourceLocationArg location) const { + if (mutex.lock(_::Mutex::EXCLUSIVE, timeout, location)) { + return Locked(mutex, value); + } else { + return nullptr; + } +} + +template +inline Maybe> MutexGuarded::lockSharedWithTimeout(Duration timeout, + LockSourceLocationArg location) const { + if (mutex.lock(_::Mutex::SHARED, timeout, location)) { + return Locked(mutex, value); + } else { + return nullptr; + } +} + +template +inline const T& MutexGuarded::getAlreadyLockedShared() const { +#ifdef KJ_DEBUG + mutex.assertLockedByCaller(_::Mutex::SHARED); +#endif + return value; +} +template +inline T& MutexGuarded::getAlreadyLockedShared() { +#ifdef KJ_DEBUG + mutex.assertLockedByCaller(_::Mutex::SHARED); +#endif + return value; +} +template +inline T& MutexGuarded::getAlreadyLockedExclusive() const { +#ifdef KJ_DEBUG + mutex.assertLockedByCaller(_::Mutex::EXCLUSIVE); +#endif + return const_cast(value); +} + +template +template +class Lazy::InitImpl: public _::Once::Initializer { +public: + inline InitImpl(const Lazy& lazy, Func&& func): lazy(lazy), func(kj::fwd(func)) {} + + void run() override { + lazy.value = func(lazy.space); + } + +private: + const Lazy& lazy; + Func func; +}; + +template +template +inline T& Lazy::get(Func&& init, LockSourceLocationArg location) { + if (!once.isInitialized()) { + InitImpl initImpl(*this, kj::fwd(init)); + once.runOnce(initImpl, location); + } + return *value; +} + +template +template +inline const T& Lazy::get(Func&& init, LockSourceLocationArg location) const { + if (!once.isInitialized()) { + InitImpl initImpl(*this, kj::fwd(init)); + once.runOnce(initImpl, location); + } + return *value; +} + +#if KJ_TRACK_LOCK_BLOCKING +struct BlockedOnMutexAcquisition { + const _::Mutex& mutex; + // The mutex we are blocked on. + + const SourceLocation& origin; + // Where did the blocking operation originate from. +}; + +struct BlockedOnCondVarWait { + const _::Mutex& mutex; + // The mutex the condition variable is using (may or may not be locked). + + const void* waiter; + // Pointer to the waiter that's being waited on. + + const SourceLocation& origin; + // Where did the blocking operation originate from. +}; + +struct BlockedOnOnceInit { + const _::Once& once; + + const SourceLocation& origin; + // Where did the blocking operation originate from. +}; + +using BlockedOnReason = OneOf; + +Maybe blockedReason() noexcept; +// Returns the information about the reason the current thread is blocked synchronously on KJ +// lock primitives. Returns nullptr if the current thread is not currently blocked on such +// primitives. This is intended to be called from a signal handler to check whether the current +// thread is blocked. Outside of a signal handler there is little value to this function. In those +// cases by definition the thread is not blocked. This includes the callable used as part of a +// condition variable since that happens after the lock is acquired & the current thread is no +// longer blocked). The utility could be made useful for non-signal handler use-cases by being able +// to fetch the pointer to the TLS variable directly (i.e. const BlockedOnReason&*). However, there +// would have to be additional changes/complexity to try make that work since you'd need +// synchronization to ensure that the memory you'd try to reference is still valid. The likely +// solution would be to make these mutually exclusive options where you can use either the fast +// async-safe option, or a mutex-guarded TLS variable you can get a reference to that isn't +// async-safe. That being said, maybe someone can come up with a way to make something that works +// in both use-cases which would of course be more preferable. +#endif + + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/one-of.h b/vendor/capnproto/src/kj/one-of.h new file mode 100644 index 0000000..334e779 --- /dev/null +++ b/vendor/capnproto/src/kj/one-of.h @@ -0,0 +1,656 @@ +// 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. + +#pragma once + +#include "common.h" + +KJ_BEGIN_HEADER + +namespace kj { + +namespace _ { // private + +template class Fail, typename Key, typename... Variants> +struct TypeIndex_; +template class Fail, typename Key, typename First, typename... Rest> +struct TypeIndex_ { + static constexpr uint value = TypeIndex_::value; +}; +template class Fail, typename Key, typename... Rest> +struct TypeIndex_ { static constexpr uint value = i; }; +template class Fail, typename Key> +struct TypeIndex_: public Fail {}; + +template +struct OneOfFailError_ { + static_assert(i == -1, "type does not match any in OneOf"); +}; +template +struct OneOfFailZero_ { + static constexpr int value = 0; +}; + +template +struct SuccessIfNotZero { + typedef int Success; +}; +template <> +struct SuccessIfNotZero<0> {}; + +enum class Variants0 {}; +enum class Variants1 { _variant0 }; +enum class Variants2 { _variant0, _variant1 }; +enum class Variants3 { _variant0, _variant1, _variant2 }; +enum class Variants4 { _variant0, _variant1, _variant2, _variant3 }; +enum class Variants5 { _variant0, _variant1, _variant2, _variant3, _variant4 }; +enum class Variants6 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5 }; +enum class Variants7 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6 }; +enum class Variants8 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7 }; +enum class Variants9 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8 }; +enum class Variants10 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9 }; +enum class Variants11 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10 }; +enum class Variants12 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11 }; +enum class Variants13 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12 }; +enum class Variants14 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13 }; +enum class Variants15 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14 }; +enum class Variants16 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15 }; +enum class Variants17 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16 }; +enum class Variants18 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17 }; +enum class Variants19 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18 }; +enum class Variants20 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19 }; +enum class Variants21 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20 }; +enum class Variants22 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21 }; +enum class Variants23 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22 }; +enum class Variants24 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23 }; +enum class Variants25 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24 }; +enum class Variants26 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25 }; +enum class Variants27 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26 }; +enum class Variants28 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27 }; +enum class Variants29 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28 }; +enum class Variants30 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29 }; +enum class Variants31 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30 }; +enum class Variants32 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31 }; +enum class Variants33 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32 }; +enum class Variants34 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33 }; +enum class Variants35 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34 }; +enum class Variants36 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35 }; +enum class Variants37 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36 }; +enum class Variants38 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36, + _variant37 }; +enum class Variants39 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36, + _variant37, _variant38 }; +enum class Variants40 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36, + _variant37, _variant38, _variant39 }; +enum class Variants41 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36, + _variant37, _variant38, _variant39, _variant40 }; +enum class Variants42 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36, + _variant37, _variant38, _variant39, _variant40, _variant41 }; +enum class Variants43 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36, + _variant37, _variant38, _variant39, _variant40, _variant41, _variant42 }; +enum class Variants44 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36, + _variant37, _variant38, _variant39, _variant40, _variant41, _variant42, + _variant43 }; +enum class Variants45 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36, + _variant37, _variant38, _variant39, _variant40, _variant41, _variant42, + _variant43, _variant44 }; +enum class Variants46 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36, + _variant37, _variant38, _variant39, _variant40, _variant41, _variant42, + _variant43, _variant44, _variant45 }; +enum class Variants47 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36, + _variant37, _variant38, _variant39, _variant40, _variant41, _variant42, + _variant43, _variant44, _variant45, _variant46 }; +enum class Variants48 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36, + _variant37, _variant38, _variant39, _variant40, _variant41, _variant42, + _variant43, _variant44, _variant45, _variant46, _variant47 }; +enum class Variants49 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36, + _variant37, _variant38, _variant39, _variant40, _variant41, _variant42, + _variant43, _variant44, _variant45, _variant46, _variant47, _variant48 }; +enum class Variants50 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6, + _variant7, _variant8, _variant9, _variant10, _variant11, _variant12, + _variant13, _variant14, _variant15, _variant16, _variant17, _variant18, + _variant19, _variant20, _variant21, _variant22, _variant23, _variant24, + _variant25, _variant26, _variant27, _variant28, _variant29, _variant30, + _variant31, _variant32, _variant33, _variant34, _variant35, _variant36, + _variant37, _variant38, _variant39, _variant40, _variant41, _variant42, + _variant43, _variant44, _variant45, _variant46, _variant47, _variant48, + _variant49 }; + +template struct Variants_; +template <> struct Variants_<0> { typedef Variants0 Type; }; +template <> struct Variants_<1> { typedef Variants1 Type; }; +template <> struct Variants_<2> { typedef Variants2 Type; }; +template <> struct Variants_<3> { typedef Variants3 Type; }; +template <> struct Variants_<4> { typedef Variants4 Type; }; +template <> struct Variants_<5> { typedef Variants5 Type; }; +template <> struct Variants_<6> { typedef Variants6 Type; }; +template <> struct Variants_<7> { typedef Variants7 Type; }; +template <> struct Variants_<8> { typedef Variants8 Type; }; +template <> struct Variants_<9> { typedef Variants9 Type; }; +template <> struct Variants_<10> { typedef Variants10 Type; }; +template <> struct Variants_<11> { typedef Variants11 Type; }; +template <> struct Variants_<12> { typedef Variants12 Type; }; +template <> struct Variants_<13> { typedef Variants13 Type; }; +template <> struct Variants_<14> { typedef Variants14 Type; }; +template <> struct Variants_<15> { typedef Variants15 Type; }; +template <> struct Variants_<16> { typedef Variants16 Type; }; +template <> struct Variants_<17> { typedef Variants17 Type; }; +template <> struct Variants_<18> { typedef Variants18 Type; }; +template <> struct Variants_<19> { typedef Variants19 Type; }; +template <> struct Variants_<20> { typedef Variants20 Type; }; +template <> struct Variants_<21> { typedef Variants21 Type; }; +template <> struct Variants_<22> { typedef Variants22 Type; }; +template <> struct Variants_<23> { typedef Variants23 Type; }; +template <> struct Variants_<24> { typedef Variants24 Type; }; +template <> struct Variants_<25> { typedef Variants25 Type; }; +template <> struct Variants_<26> { typedef Variants26 Type; }; +template <> struct Variants_<27> { typedef Variants27 Type; }; +template <> struct Variants_<28> { typedef Variants28 Type; }; +template <> struct Variants_<29> { typedef Variants29 Type; }; +template <> struct Variants_<30> { typedef Variants30 Type; }; +template <> struct Variants_<31> { typedef Variants31 Type; }; +template <> struct Variants_<32> { typedef Variants32 Type; }; +template <> struct Variants_<33> { typedef Variants33 Type; }; +template <> struct Variants_<34> { typedef Variants34 Type; }; +template <> struct Variants_<35> { typedef Variants35 Type; }; +template <> struct Variants_<36> { typedef Variants36 Type; }; +template <> struct Variants_<37> { typedef Variants37 Type; }; +template <> struct Variants_<38> { typedef Variants38 Type; }; +template <> struct Variants_<39> { typedef Variants39 Type; }; +template <> struct Variants_<40> { typedef Variants40 Type; }; +template <> struct Variants_<41> { typedef Variants41 Type; }; +template <> struct Variants_<42> { typedef Variants42 Type; }; +template <> struct Variants_<43> { typedef Variants43 Type; }; +template <> struct Variants_<44> { typedef Variants44 Type; }; +template <> struct Variants_<45> { typedef Variants45 Type; }; +template <> struct Variants_<46> { typedef Variants46 Type; }; +template <> struct Variants_<47> { typedef Variants47 Type; }; +template <> struct Variants_<48> { typedef Variants48 Type; }; +template <> struct Variants_<49> { typedef Variants49 Type; }; +template <> struct Variants_<50> { typedef Variants50 Type; }; + +template +using Variants = typename Variants_::Type; + +} // namespace _ (private) + +template +class OneOf { + template + static inline constexpr uint typeIndex() { + return _::TypeIndex_<1, _::OneOfFailError_, Key, Variants...>::value; + } + // Get the 1-based index of Key within the type list Types, or static_assert with a nice error. + + template + static inline constexpr uint typeIndexOrZero() { + return _::TypeIndex_<1, _::OneOfFailZero_, Key, Variants...>::value; + } + + template + struct HasAll; + // Has a member type called "Success" if and only if all of `OtherVariants` are types that + // appear in `Variants`. Used with SFINAE to enable subset constructors. + +public: + inline OneOf(): tag(0) {} + + OneOf(const OneOf& other) { copyFrom(other); } + OneOf(OneOf& other) { copyFrom(other); } + OneOf(OneOf&& other) { moveFrom(other); } + // Copy/move from same OneOf type. + + template ::Success> + OneOf(const OneOf& other) { copyFromSubset(other); } + template ::Success> + OneOf(OneOf& other) { copyFromSubset(other); } + template ::Success> + OneOf(OneOf&& other) { moveFromSubset(other); } + // Copy/move from OneOf that contains a subset of the types we do. + + template >::Success> + OneOf(T&& other): tag(typeIndex>()) { + ctor(*reinterpret_cast*>(space), kj::fwd(other)); + } + // Copy/move from a value that matches one of the individual types in the OneOf. + + ~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 + bool is() const { + return tag == typeIndex(); + } + + template + T& get() & { + KJ_IREQUIRE(is(), "Must check OneOf::is() before calling get()."); + return *reinterpret_cast(space); + } + template + T&& get() && { + KJ_IREQUIRE(is(), "Must check OneOf::is() before calling get()."); + return kj::mv(*reinterpret_cast(space)); + } + template + const T& get() const& { + KJ_IREQUIRE(is(), "Must check OneOf::is() before calling get()."); + return *reinterpret_cast(space); + } + template + const T&& get() const&& { + KJ_IREQUIRE(is(), "Must check OneOf::is() before calling get()."); + return kj::mv(*reinterpret_cast(space)); + } + + template + T& init(Params&&... params) { + if (tag != 0) destroy(); + ctor(*reinterpret_cast(space), kj::fwd(params)...); + tag = typeIndex(); + return *reinterpret_cast(space); + } + + template + Maybe tryGet() { + if (is()) { + return *reinterpret_cast(space); + } else { + return nullptr; + } + } + template + Maybe tryGet() const { + if (is()) { + return *reinterpret_cast(space); + } else { + return nullptr; + } + } + + template + KJ_NORETURN(void allHandled()); + // After a series of if/else blocks handling each variant of the OneOf, have the final else + // block call allHandled() where n is the number of variants. This will fail to compile + // if new variants are added in the future. + + typedef _::Variants Tag; + + Tag which() const { + KJ_IREQUIRE(tag != 0, "Can't KJ_SWITCH_ONEOF() on uninitialized value."); + return static_cast(tag - 1); + } + + template + static constexpr Tag tagFor() { + return static_cast(typeIndex() - 1); + } + + OneOf* _switchSubject() & { return this; } + const OneOf* _switchSubject() const& { return this; } + _::NullableValue _switchSubject() && { return kj::mv(*this); } + +private: + uint tag; + + static inline constexpr size_t maxSize(size_t a) { + return a; + } + template + 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 + inline void doAll(T... t) {} + + template + inline bool destroyVariant() { + if (tag == typeIndex()) { + tag = 0; + dtor(*reinterpret_cast(space)); + } + return false; + } + void destroy() { + doAll(destroyVariant()...); + } + + template + inline bool copyVariantFrom(const OneOf& other) { + if (other.is()) { + ctor(*reinterpret_cast(space), other.get()); + } + 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(other)...); + } + + template + inline bool copyVariantFrom(OneOf& other) { + if (other.is()) { + ctor(*reinterpret_cast(space), other.get()); + } + return false; + } + void copyFrom(OneOf& other) { + // Initialize as a copy of `other`. Expects that `this` starts out uninitialized, so the tag + // is invalid. + tag = other.tag; + doAll(copyVariantFrom(other)...); + } + + template + inline bool moveVariantFrom(OneOf& other) { + if (other.is()) { + ctor(*reinterpret_cast(space), kj::mv(other.get())); + } + 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(other)...); + } + + template + inline bool copySubsetVariantFrom(const OneOf& other) { + if (other.template is()) { + tag = typeIndex>(); + ctor(*reinterpret_cast(space), other.template get()); + } + return false; + } + template + void copyFromSubset(const OneOf& other) { + doAll(copySubsetVariantFrom(other)...); + } + + template + inline bool copySubsetVariantFrom(OneOf& other) { + if (other.template is()) { + tag = typeIndex>(); + ctor(*reinterpret_cast(space), other.template get()); + } + return false; + } + template + void copyFromSubset(OneOf& other) { + doAll(copySubsetVariantFrom(other)...); + } + + template + inline bool moveSubsetVariantFrom(OneOf& other) { + if (other.template is()) { + tag = typeIndex>(); + ctor(*reinterpret_cast(space), kj::mv(other.template get())); + } + return false; + } + template + void moveFromSubset(OneOf& other) { + doAll(moveSubsetVariantFrom(other)...); + } +}; + +template +template +struct OneOf::HasAll + : public HasAll(), Rest...> {}; +template +template +struct OneOf::HasAll: public _::SuccessIfNotZero {}; + +template +template +void OneOf::allHandled() { + // After a series of if/else blocks handling each variant of the OneOf, have the final else + // block call allHandled() where n is the number of variants. This will fail to compile + // if new variants are added in the future. + + static_assert(i == sizeof...(Variants), "new OneOf variants need to be handled here"); + KJ_UNREACHABLE; +} + +#if KJ_CPP_STD > 201402L +#define KJ_SWITCH_ONEOF(value) \ + switch (auto _kj_switch_subject = (value)._switchSubject(); _kj_switch_subject->which()) +#else +#define KJ_SWITCH_ONEOF(value) \ + /* Without C++17, we can only support one switch per containing block. Deal with it. */ \ + auto _kj_switch_subject = (value)._switchSubject(); \ + switch (_kj_switch_subject->which()) +#endif +#define KJ_CASE_ONEOF(name, ...) \ + break; \ + case ::kj::Decay::template tagFor<__VA_ARGS__>(): \ + for (auto& name = _kj_switch_subject->template get<__VA_ARGS__>(), *_kj_switch_done = &name; \ + _kj_switch_done; _kj_switch_done = nullptr) +#define KJ_CASE_ONEOF_DEFAULT break; default: +// Allows switching over a OneOf. +// +// Example: +// +// kj::OneOf variant; +// KJ_SWITCH_ONEOF(variant) { +// KJ_CASE_ONEOF(i, int) { +// doSomethingWithInt(i); +// } +// KJ_CASE_ONEOF(s, const char*) { +// doSomethingWithString(s); +// } +// KJ_CASE_ONEOF_DEFAULT { +// doSomethingElse(); +// } +// } +// +// Notes: +// - If you don't handle all possible types and don't include a default branch, you'll get a +// compiler warning, just like a regular switch() over an enum where one of the enum values is +// missing. +// - There's no need for a `break` statement in a KJ_CASE_ONEOF; it is implied. +// - Under C++11 and C++14, only one KJ_SWITCH_ONEOF() can appear in a block. Wrap the switch in +// a pair of braces if you need a second switch in the same block. If C++17 is enabled, this is +// not an issue. +// +// Implementation notes: +// - The use of __VA_ARGS__ is to account for template types that have commas separating type +// parameters, since macros don't recognize <> as grouping. +// - _kj_switch_done is really used as a boolean flag to prevent the for() loop from actually +// looping, but it's defined as a pointer since that's all we can define in this context. + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/parse/char.c++ b/vendor/capnproto/src/kj/parse/char.c++ new file mode 100644 index 0000000..4db9914 --- /dev/null +++ b/vendor/capnproto/src/kj/parse/char.c++ @@ -0,0 +1,71 @@ +// 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 "char.h" +#include "../debug.h" +#include + +namespace kj { +namespace parse { + +namespace _ { // private + +double ParseFloat::operator()(const Array& digits, + const Maybe>& fraction, + const Maybe, Array>>& exponent) const { + size_t bufSize = digits.size(); + KJ_IF_MAYBE(f, fraction) { + bufSize += 1 + f->size(); + } + KJ_IF_MAYBE(e, exponent) { + bufSize += 1 + (get<0>(*e) != nullptr) + get<1>(*e).size(); + } + + KJ_STACK_ARRAY(char, buf, bufSize + 1, 128, 128); + + char* pos = buf.begin(); + memcpy(pos, digits.begin(), digits.size()); + pos += digits.size(); + KJ_IF_MAYBE(f, fraction) { + *pos++ = '.'; + memcpy(pos, f->begin(), f->size()); + pos += f->size(); + } + KJ_IF_MAYBE(e, exponent) { + *pos++ = 'e'; + KJ_IF_MAYBE(sign, get<0>(*e)) { + *pos++ = *sign; + } + memcpy(pos, get<1>(*e).begin(), get<1>(*e).size()); + pos += get<1>(*e).size(); + } + + *pos++ = '\0'; + KJ_DASSERT(pos == buf.end()); + + // The above construction should always produce a valid double, so this should never throw... + return StringPtr(buf.begin(), bufSize).parseAs(); +} + +} // namespace _ (private) + +} // namespace parse +} // namespace kj diff --git a/vendor/capnproto/src/kj/parse/char.h b/vendor/capnproto/src/kj/parse/char.h new file mode 100644 index 0000000..dd53fa9 --- /dev/null +++ b/vendor/capnproto/src/kj/parse/char.h @@ -0,0 +1,358 @@ +// 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. + +#pragma once + +#include "common.h" +#include "../string.h" +#include + +KJ_BEGIN_HEADER + +namespace kj { +namespace parse { + +// ======================================================================================= +// Exact char/string. + +class ExactString_ { +public: + constexpr inline ExactString_(const char* str): str(str) {} + + template + Maybe> 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 +constexpr ExactlyConst_ exactChar() { + // Returns a parser that matches exactly the character given by the template argument (returning + // no result). + return ExactlyConst_(); +} + +// ======================================================================================= +// 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; + } + + inline bool containsAll(ArrayPtr text) const { + for (char c: text) { + if (!contains(c)) return false; + } + return true; + } + + template + Maybe 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); +} + +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); +} + +// ======================================================================================= + +namespace _ { // private + +struct ArrayToString { + inline String operator()(const Array& arr) const { + return heapString(arr); + } +}; + +} // namespace _ (private) + +template +constexpr inline auto charsToString(SubParser&& subParser) + -> decltype(transform(kj::fwd(subParser), _::ArrayToString())) { + // Wraps a parser that returns Array such that it returns String instead. + return parse::transform(kj::fwd(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& rest) const { + if (rest.size() == 0) return heapString(&first, 1); + 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 +struct ParseInteger { + inline uint64_t operator()(const Array& digits) const { + return operator()('0', digits); + } + uint64_t operator()(char first, const Array& 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& digits, + const Maybe>& fraction, + const Maybe, Array>>& 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 second, Maybe 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. + +} // namespace parse +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/parse/common.h b/vendor/capnproto/src/kj/parse/common.h new file mode 100644 index 0000000..dde0784 --- /dev/null +++ b/vendor/capnproto/src/kj/parse/common.h @@ -0,0 +1,799 @@ +// 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. + +#pragma once + +#include "../common.h" +#include "../memory.h" +#include "../array.h" +#include "../tuple.h" +#include "../vector.h" + + + +KJ_BEGIN_HEADER + +namespace kj { +namespace parse { + +template +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_AND_MOVE(IteratorInput); + + void advanceParent() { + parent->pos = pos; + } + void forgetParent() { + parent = nullptr; + } + + bool atEnd() { return pos == end; } + auto current() -> decltype(*instance()) { + KJ_IREQUIRE(!atEnd()); + return *pos; + } + auto consume() -> decltype(*instance()) { + 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 struct OutputType_; +template struct OutputType_> { typedef T Type; }; +template +using OutputType = typename OutputType_< + decltype(instance()(instance())) + >::Type; +// Synonym for the output type of a parser, given the parser type and the input type. + +// ======================================================================================= + +template +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 + constexpr ParserRef(Other&& other) + : parser(&other), wrapper(&WrapperImplInstance>::instance) { + static_assert(kj::isReference(), "ParserRef should not be assigned to a temporary."); + } + + template + inline ParserRef& operator=(Other&& other) { + static_assert(kj::isReference(), "ParserRef should not be assigned to a temporary."); + parser = &other; + wrapper = &WrapperImplInstance>::instance; + return *this; + } + + KJ_ALWAYS_INLINE(Maybe 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 parse(const void* parser, Input& input) const = 0; + }; + template + struct WrapperImpl: public Wrapper { + Maybe parse(const void* parser, Input& input) const override { + return (*reinterpret_cast(parser))(input); + } + }; + template + struct WrapperImplInstance { + static constexpr WrapperImpl instance = WrapperImpl(); + }; + + const void* parser; + const Wrapper* wrapper; +}; + +template +template +constexpr typename ParserRef::template WrapperImpl +ParserRef::WrapperImplInstance::instance; + +template +constexpr ParserRef> ref(ParserImpl& impl) { + // Constructs a ParserRef. You must specify the input type explicitly, e.g. + // `ref(myParser)`. + + return ParserRef>(impl); +} + +// ------------------------------------------------------------------- +// any +// Output = one token + +class Any_ { +public: + template + Maybe().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 +class Exactly_ { +public: + explicit constexpr Exactly_(T&& expected): expected(expected) {} + + template + Maybe> operator()(Input& input) const { + if (input.atEnd() || input.current() != expected) { + return nullptr; + } else { + input.next(); + return Tuple<>(); + } + } + +private: + T expected; +}; + +template +constexpr Exactly_ 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_(kj::fwd(expected)); +} + +// ------------------------------------------------------------------- +// exactlyConst() +// Output = Tuple<> + +template +class ExactlyConst_ { +public: + explicit constexpr ExactlyConst_() {} + + template + Maybe> operator()(Input& input) const { + if (input.atEnd() || input.current() != expected) { + return nullptr; + } else { + input.next(); + return Tuple<>(); + } + } +}; + +template +constexpr ExactlyConst_ 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_(); +} + +// ------------------------------------------------------------------- +// constResult() + +template +class ConstResult_ { +public: + explicit constexpr ConstResult_(SubParser&& subParser, Result&& result) + : subParser(kj::fwd(subParser)), result(kj::fwd(result)) {} + + template + Maybe operator()(Input& input) const { + if (subParser(input) == nullptr) { + return nullptr; + } else { + return result; + } + } + +private: + SubParser subParser; + Result result; +}; + +template +constexpr ConstResult_ constResult(SubParser&& subParser, Result&& result) { + // Constructs a parser which returns exactly `result` if `subParser` is successful. + return ConstResult_(kj::fwd(subParser), kj::fwd(result)); +} + +template +constexpr ConstResult_> discard(SubParser&& subParser) { + // Constructs a parser which wraps `subParser` but discards the result. + return constResult(kj::fwd(subParser), Tuple<>()); +} + +// ------------------------------------------------------------------- +// sequence() +// Output = Flattened Tuple of outputs of sub-parsers. + +template class Sequence_; + +template +class Sequence_ { +public: + template + explicit constexpr Sequence_(T&& firstSubParser, U&&... rest) + : first(kj::fwd(firstSubParser)), rest(kj::fwd(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 + auto operator()(Input& input) const + -> Maybe>(), + instance>()...))> + { + return parseNext(input); + } + + template + auto parseNext(Input& input, InitialParams&&... initialParams) const + -> Maybe(initialParams)..., + instance>(), + instance>()...))> + { + KJ_IF_MAYBE(firstResult, first(input)) { + return rest.parseNext(input, kj::fwd(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(initialParams)..., + instance>(), + instance>()...))>{nullptr}; + } + } + +private: + FirstSubParser first; + Sequence_ rest; +}; + +template <> +class Sequence_<> { +public: + template + Maybe> operator()(Input& input) const { + return parseNext(input); + } + + template + auto parseNext(Input& input, Params&&... params) const -> + Maybe(params)...))> { + return tuple(kj::fwd(params)...); + } +}; + +template +constexpr Sequence_ sequence(SubParsers&&... subParsers) { + // Constructs a parser that executes each of the parameter parsers in sequence and returns a + // tuple of their results. + + return Sequence_(kj::fwd(subParsers)...); +} + +// ------------------------------------------------------------------- +// many() +// Output = Array of output of sub-parser, or just a uint count if the sub-parser returns Tuple<>. + +template +class Many_ { + template > + struct Impl; +public: + explicit constexpr Many_(SubParser&& subParser) + : subParser(kj::fwd(subParser)) {} + + template + auto operator()(Input& input) const + -> decltype(Impl::apply(instance(), input)); + +private: + SubParser subParser; +}; + +template +template +struct Many_::Impl { + static Maybe> apply(const SubParser& subParser, Input& input) { + typedef Vector> 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 +template +struct Many_::Impl> { + // If the sub-parser output is Tuple<>, just return a count. + + static Maybe 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 +template +auto Many_::operator()(Input& input) const + -> decltype(Impl::apply(instance(), input)) { + return Impl>::apply(subParser, input); +} + +template +constexpr Many_ 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_(kj::fwd(subParser)); +} + +template +constexpr Many_ oneOrMore(SubParser&& subParser) { + // Like `many()` but the parser must parse at least one item to be successful. + return Many_(kj::fwd(subParser)); +} + +// ------------------------------------------------------------------- +// times() +// Output = Array of output of sub-parser, or Tuple<> if sub-parser returns Tuple<>. + +template +class Times_ { + template > + struct Impl; +public: + explicit constexpr Times_(SubParser&& subParser, uint count) + : subParser(kj::fwd(subParser)), count(count) {} + + template + auto operator()(Input& input) const + -> decltype(Impl::apply(instance(), instance(), input)); + +private: + SubParser subParser; + uint count; +}; + +template +template +struct Times_::Impl { + static Maybe> apply(const SubParser& subParser, uint count, Input& input) { + auto results = heapArrayBuilder>(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 +template +struct Times_::Impl> { + // If the sub-parser output is Tuple<>, just return a count. + + static Maybe> 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 +template +auto Times_::operator()(Input& input) const + -> decltype(Impl::apply(instance(), instance(), input)) { + return Impl>::apply(subParser, count, input); +} + +template +constexpr Times_ times(SubParser&& subParser, uint count) { + // Constructs a parser that repeats the subParser exactly `count` times. + return Times_(kj::fwd(subParser), count); +} + +// ------------------------------------------------------------------- +// optional() +// Output = Maybe + +template +class Optional_ { +public: + explicit constexpr Optional_(SubParser&& subParser) + : subParser(kj::fwd(subParser)) {} + + template + Maybe>> operator()(Input& input) const { + typedef Maybe> 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 +constexpr Optional_ 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_(kj::fwd(subParser)); +} + +// ------------------------------------------------------------------- +// oneOf() +// All SubParsers must have same output type, which becomes the output type of the +// OneOfParser. + +template +class OneOf_; + +template +class OneOf_ { +public: + explicit constexpr OneOf_(FirstSubParser&& firstSubParser, SubParsers&&... rest) + : first(kj::fwd(firstSubParser)), rest(kj::fwd(rest)...) {} + + template + Maybe> operator()(Input& input) const { + { + Input subInput(input); + Maybe> 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_ rest; +}; + +template <> +class OneOf_<> { +public: + template + decltype(nullptr) operator()(Input& input) const { + return nullptr; + } +}; + +template +constexpr OneOf_ 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_(kj::fwd(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 +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 +constexpr Span> span(Position&& start, Position&& end) { + return Span>(kj::fwd(start), kj::fwd(end)); +} + +template +class Transform_ { +public: + explicit constexpr Transform_(SubParser&& subParser, TransformFunc&& transform) + : subParser(kj::fwd(subParser)), transform(kj::fwd(transform)) {} + + template + Maybe(), + instance&&>()))> + 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 +class TransformOrReject_ { +public: + explicit constexpr TransformOrReject_(SubParser&& subParser, TransformFunc&& transform) + : subParser(kj::fwd(subParser)), transform(kj::fwd(transform)) {} + + template + decltype(kj::apply(instance(), instance&&>())) + 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 +class TransformWithLocation_ { +public: + explicit constexpr TransformWithLocation_(SubParser&& subParser, TransformFunc&& transform) + : subParser(kj::fwd(subParser)), transform(kj::fwd(transform)) {} + + template + Maybe(), + instance().getPosition())>>>(), + instance&&>()))> + operator()(Input& input) const { + auto start = input.getPosition(); + KJ_IF_MAYBE(subResult, subParser(input)) { + return kj::apply(transform, Span(kj::mv(start), input.getPosition()), + kj::mv(*subResult)); + } else { + return nullptr; + } + } + +private: + SubParser subParser; + TransformFunc transform; +}; + +template +constexpr Transform_ 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_( + kj::fwd(subParser), kj::fwd(functor)); +} + +template +constexpr TransformOrReject_ 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_( + kj::fwd(subParser), kj::fwd(functor)); +} + +template +constexpr TransformWithLocation_ 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_( + kj::fwd(subParser), kj::fwd(functor)); +} + +// ------------------------------------------------------------------- +// notLookingAt() +// Fails if the given parser succeeds at the current location. + +template +class NotLookingAt_ { +public: + explicit constexpr NotLookingAt_(SubParser&& subParser) + : subParser(kj::fwd(subParser)) {} + + template + Maybe> operator()(Input& input) const { + Input subInput(input); + subInput.forgetParent(); + if (subParser(subInput) == nullptr) { + return Tuple<>(); + } else { + return nullptr; + } + } + +private: + SubParser subParser; +}; + +template +constexpr NotLookingAt_ 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_(kj::fwd(subParser)); +} + +// ------------------------------------------------------------------- +// endOfInput() +// Output = Tuple<>, only succeeds if at end-of-input + +class EndOfInput_ { +public: + template + Maybe> 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 + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/refcount.c++ b/vendor/capnproto/src/kj/refcount.c++ new file mode 100644 index 0000000..03abf76 --- /dev/null +++ b/vendor/capnproto/src/kj/refcount.c++ @@ -0,0 +1,72 @@ +// 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 "refcount.h" +#include "debug.h" + + +namespace kj { + +// ======================================================================================= +// Non-atomic (thread-unsafe) refcounting + +Refcounted::~Refcounted() noexcept(false) { + KJ_ASSERT(refcount == 0, "Refcounted object deleted with non-zero refcount."); +} + +void Refcounted::disposeImpl(void* pointer) const { + if (--refcount == 0) { + delete this; + } +} + +// ======================================================================================= +// Atomic (thread-safe) refcounting + +AtomicRefcounted::~AtomicRefcounted() noexcept(false) { + KJ_ASSERT(refcount == 0, "Refcounted object deleted with non-zero refcount."); +} + +void AtomicRefcounted::disposeImpl(void* pointer) const { + if (__atomic_sub_fetch(&refcount, 1, __ATOMIC_RELEASE) == 0) { + __atomic_thread_fence(__ATOMIC_ACQUIRE); + delete this; + } +} + +bool AtomicRefcounted::addRefWeakInternal() const { + uint orig = __atomic_load_n(&refcount, __ATOMIC_RELAXED); + + for (;;) { + if (orig == 0) { + // Refcount already hit zero. Destructor is already running so we can't revive the object. + return false; + } + + if (__atomic_compare_exchange_n(&refcount, &orig, orig + 1, true, + __ATOMIC_RELAXED, __ATOMIC_RELAXED)) { + // Successfully incremented refcount without letting it hit zero. + return true; + } + } +} + +} // namespace kj diff --git a/vendor/capnproto/src/kj/refcount.h b/vendor/capnproto/src/kj/refcount.h new file mode 100644 index 0000000..d2aca23 --- /dev/null +++ b/vendor/capnproto/src/kj/refcount.h @@ -0,0 +1,253 @@ +// 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. + +#pragma once + +#include "memory.h" + + +KJ_BEGIN_HEADER + +namespace kj { + +// ======================================================================================= +// Non-atomic (thread-unsafe) refcounting + +class Refcounted: private Disposer { + // Subclass this to create a class that contains a reference count. Then, use + // `kj::refcounted()` 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`. 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 type to replace + // Own could also be nice. + +public: + Refcounted() = default; + virtual ~Refcounted() noexcept(false); + KJ_DISALLOW_COPY_AND_MOVE(Refcounted); + + 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 + static Own addRefInternal(T* object); + + template + friend Own addRef(T& object); + template + friend Own refcounted(Params&&... params); + + template + friend class RefcountedWrapper; +}; + +template +inline Own 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)...)); +} + +template +Own 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 +Own Refcounted::addRefInternal(T* object) { + Refcounted* refcounted = object; + ++refcounted->refcount; + return Own(object, *refcounted); +} + +template +class RefcountedWrapper: public Refcounted { + // Adds refcounting as a wrapper around an existing type, allowing you to construct references + // with type Own that appears to point directly to the underlying object. + +public: + template + RefcountedWrapper(Params&&... params): wrapped(kj::fwd(params)...) {} + + T& getWrapped() { return wrapped; } + const T& getWrapped() const { return wrapped; } + + Own addWrappedRef() { + // Return an owned reference to the wrapped object that is backed by a refcount. + ++refcount; + return Own(&wrapped, *this); + } + +private: + T wrapped; +}; + +template +class RefcountedWrapper>: public Refcounted { + // Specialization for when the wrapped type is itself Own. We don't want this to result in + // Own>. + +public: + RefcountedWrapper(Own wrapped): wrapped(kj::mv(wrapped)) {} + + T& getWrapped() { return *wrapped; } + const T& getWrapped() const { return *wrapped; } + + Own addWrappedRef() { + // Return an owned reference to the wrapped object that is backed by a refcount. + ++refcount; + return Own(wrapped.get(), *this); + } + +private: + Own wrapped; +}; + +template +Own> refcountedWrapper(Params&&... params) { + return refcounted>(kj::fwd(params)...); +} + +template +Own>> refcountedWrapper(Own&& wrapped) { + return refcounted>>(kj::mv(wrapped)); +} + +// ======================================================================================= +// Atomic (thread-safe) refcounting +// +// Warning: Atomic ops are SLOW. + + +class AtomicRefcounted: private kj::Disposer { +public: + AtomicRefcounted() = default; + virtual ~AtomicRefcounted() noexcept(false); + KJ_DISALLOW_COPY_AND_MOVE(AtomicRefcounted); + + inline bool isShared() const { + return __atomic_load_n(&refcount, __ATOMIC_ACQUIRE) > 1; + } + +private: + mutable volatile uint refcount = 0; + + bool addRefWeakInternal() const; + + void disposeImpl(void* pointer) const override; + template + static kj::Own addRefInternal(T* object); + template + static kj::Own addRefInternal(const T* object); + + template + friend kj::Own atomicAddRef(T& object); + template + friend kj::Own atomicAddRef(const T& object); + template + friend kj::Maybe> atomicAddRefWeak(const T& object); + template + friend kj::Own atomicRefcounted(Params&&... params); +}; + +template +inline kj::Own atomicRefcounted(Params&&... params) { + return AtomicRefcounted::addRefInternal(new T(kj::fwd(params)...)); +} + +template +kj::Own atomicAddRef(T& object) { + KJ_IREQUIRE(object.AtomicRefcounted::refcount > 0, + "Object not allocated with kj::atomicRefcounted()."); + return AtomicRefcounted::addRefInternal(&object); +} + +template +kj::Own atomicAddRef(const T& object) { + KJ_IREQUIRE(object.AtomicRefcounted::refcount > 0, + "Object not allocated with kj::atomicRefcounted()."); + return AtomicRefcounted::addRefInternal(&object); +} + +template +kj::Maybe> atomicAddRefWeak(const T& object) { + // Try to addref an object whose refcount could have already reached zero in another thread, and + // whose destructor could therefore already have started executing. The destructor must contain + // some synchronization that guarantees that said destructor has not yet completed when + // attomicAddRefWeak() is called (so that the object is still valid). Since the destructor cannot + // be canceled once it has started, in the case that it has already started, this function + // returns nullptr. + + const AtomicRefcounted* refcounted = &object; + if (refcounted->addRefWeakInternal()) { + return kj::Own(&object, *refcounted); + } else { + return nullptr; + } +} + +template +kj::Own AtomicRefcounted::addRefInternal(T* object) { + AtomicRefcounted* refcounted = object; + __atomic_add_fetch(&refcounted->refcount, 1, __ATOMIC_RELAXED); + return kj::Own(object, *refcounted); +} + +template +kj::Own AtomicRefcounted::addRefInternal(const T* object) { + const AtomicRefcounted* refcounted = object; + __atomic_add_fetch(&refcounted->refcount, 1, __ATOMIC_RELAXED); + return kj::Own(object, *refcounted); +} + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/source-location.c++ b/vendor/capnproto/src/kj/source-location.c++ new file mode 100644 index 0000000..fda1932 --- /dev/null +++ b/vendor/capnproto/src/kj/source-location.c++ @@ -0,0 +1,28 @@ +// Copyright (c) 2021 Cloudflare, 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 "source-location.h" + +namespace kj { +kj::String KJ_STRINGIFY(const SourceLocation& l) { + return kj::str(l.fileName, ":", l.lineNumber, ":", l.columnNumber, " in ", l.function); +} +} // namespace kj diff --git a/vendor/capnproto/src/kj/source-location.h b/vendor/capnproto/src/kj/source-location.h new file mode 100644 index 0000000..40c53e8 --- /dev/null +++ b/vendor/capnproto/src/kj/source-location.h @@ -0,0 +1,111 @@ +// Copyright (c) 2021 Cloudflare, 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. + +#pragma once + +#include "string.h" + +KJ_BEGIN_HEADER + +// GCC does not implement __builtin_COLUMN() as that's non-standard but MSVC & clang do. +// MSVC does as of version https://github.com/microsoft/STL/issues/54) but there's currently not any +// pressing need for this for MSVC & writing the write compiler version check is annoying. +// Checking for clang version is problematic due to the way that XCode lies about __clang_major__. +// Instead we use __has_builtin as the feature check to check clang. +// Context: https://github.com/capnproto/capnproto/issues/1305 +#ifdef __has_builtin +#if __has_builtin(__builtin_COLUMN) +#define KJ_CALLER_COLUMN() __builtin_COLUMN() +#else +#define KJ_CALLER_COLUMN() 0 +#endif +#else +#define KJ_CALLER_COLUMN() 0 +#endif + +#if KJ_CPP_STD > 201703L +#define KJ_COMPILER_SUPPORTS_SOURCE_LOCATION 1 +#elif defined(__has_builtin) +// Clang 9 added these builtins: https://releases.llvm.org/9.0.0/tools/clang/docs/LanguageExtensions.html +// Use __has_builtin as the way to detect this because __clang_major__ is unreliable (see above +// about issue with Xcode-provided clang). +#define KJ_COMPILER_SUPPORTS_SOURCE_LOCATION ( \ + __has_builtin(__builtin_FILE) && \ + __has_builtin(__builtin_LINE) && \ + __has_builtin(__builtin_FUNCTION) \ + ) +#elif __GNUC__ >= 5 +// GCC 5 supports the required builtins: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Other-Builtins.html +#define KJ_COMPILER_SUPPORTS_SOURCE_LOCATION 1 +#endif + +namespace kj { +class SourceLocation { + // libc++ doesn't seem to implement (or even ), so + // this is a non-STL wrapper over the compiler primitives (these are the same across MSVC/clang/ + // gcc). Additionally this uses kj::StringPtr for holding the strings instead of const char* which + // makes it integrate a little more nicely into KJ. + + struct Badge { explicit constexpr Badge() = default; }; + // Neat little trick to make sure we can never call SourceLocation with explicit arguments. +public: +#if !KJ_COMPILER_SUPPORTS_SOURCE_LOCATION + constexpr SourceLocation() : fileName("??"), function("??"), lineNumber(0), columnNumber(0) {} + // Constructs a dummy source location that's not pointing at anything. +#else + constexpr SourceLocation(Badge = Badge{}, const char* file = __builtin_FILE(), + const char* func = __builtin_FUNCTION(), uint line = __builtin_LINE(), + uint column = KJ_CALLER_COLUMN()) + : fileName(file), function(func), lineNumber(line), columnNumber(column) + {} +#endif + +#if KJ_COMPILER_SUPPORTS_SOURCE_LOCATION + // This can only be exposed if we actually generate valid SourceLocation objects as otherwise all + // SourceLocation objects would confusingly (and likely problematically) be equated equal. + constexpr bool operator==(const SourceLocation& o) const { + // Pointer equality is fine here based on how SourceLocation operates & how compilers will + // intern all duplicate string constants. + return fileName == o.fileName && function == o.function && lineNumber == o.lineNumber && + columnNumber == o.columnNumber; + } +#endif + + const char* fileName; + const char* function; + uint lineNumber; + uint columnNumber; +}; + +kj::String KJ_STRINGIFY(const SourceLocation& l); + +class NoopSourceLocation { + // This is used in places where we want to conditionally compile out tracking the source location. + // As such it intentionally lacks all the features but the default constructor so that the API + // isn't accidentally used in the wrong compilation context. +}; + +KJ_UNUSED static kj::String KJ_STRINGIFY(const NoopSourceLocation& l) { + return kj::String(); +} +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/string-tree.c++ b/vendor/capnproto/src/kj/string-tree.c++ new file mode 100644 index 0000000..94d2055 --- /dev/null +++ b/vendor/capnproto/src/kj/string-tree.c++ @@ -0,0 +1,73 @@ +// 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 "string-tree.h" + +namespace kj { + +StringTree::StringTree(Array&& pieces, StringPtr delim) + : size_(0), + branches(heapArray(pieces.size())) { + if (pieces.size() > 0) { + if (pieces.size() > 1 && delim.size() > 0) { + text = heapString((pieces.size() - 1) * delim.size()); + size_ = text.size(); + } + + branches[0].index = 0; + branches[0].content = kj::mv(pieces[0]); + size_ += pieces[0].size(); + + for (uint i = 1; i < pieces.size(); i++) { + if (delim.size() > 0) { + memcpy(text.begin() + (i - 1) * delim.size(), delim.begin(), delim.size()); + } + branches[i].index = i * delim.size(); + branches[i].content = kj::mv(pieces[i]); + size_ += pieces[i].size(); + } + } +} + +String StringTree::flatten() const { + String result = heapString(size()); + flattenTo(result.begin()); + return result; +} + +char* StringTree::flattenTo(char* __restrict__ target) const { + visit([&target](ArrayPtr text) { + memcpy(target, text.begin(), text.size()); + target += text.size(); + }); + return target; +} + +char* StringTree::flattenTo(char* __restrict__ target, char* limit) const { + visit([&target,limit](ArrayPtr text) { + size_t size = kj::min(text.size(), limit - target); + memcpy(target, text.begin(), size); + target += size; + }); + return target; +} + +} // namespace kj diff --git a/vendor/capnproto/src/kj/string-tree.h b/vendor/capnproto/src/kj/string-tree.h new file mode 100644 index 0000000..19281bd --- /dev/null +++ b/vendor/capnproto/src/kj/string-tree.h @@ -0,0 +1,219 @@ +// 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. + +#pragma once + +#include "string.h" + +KJ_BEGIN_HEADER + +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&& 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 + 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). + + char* flattenTo(char* __restrict__ target) const; + char* flattenTo(char* __restrict__ target, char* limit) const; + // Copy the contents to the given character array. Does not add a NUL terminator. Returns a + // pointer just past the end of what was filled. + +private: + size_t size_; + String text; + + struct Branch; + Array branches; // In order. + + inline void fill(char* pos, size_t branchIndex); + template + void fill(char* pos, size_t branchIndex, First&& first, Rest&&... rest); + template + void fill(char* pos, size_t branchIndex, StringTree&& first, Rest&&... rest); + template + void fill(char* pos, size_t branchIndex, Array&& first, Rest&&... rest); + template + void fill(char* pos, size_t branchIndex, String&& first, Rest&&... rest); + + template + static StringTree concat(Params&&... params); + static StringTree&& concat(StringTree&& param) { return kj::mv(param); } + + template + 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 + 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 + 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&& trees) { return StringTree(kj::mv(trees), ""); } + +template +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 +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)...); +} + +template +char* fillLimited(char* __restrict__ target, char* limit, const StringTree& first, Rest&&... rest) { + // Make str() work with stringifiers that return StringTree by patching fill(). + + target = first.flattenTo(target, limit); + return fillLimited(target + first.size(), limit, kj::fwd(rest)...); +} + +template constexpr bool isStringTree() { return false; } +template <> constexpr bool isStringTree() { return true; } + +inline StringTree&& toStringTreeOrCharSequence(StringTree&& tree) { return kj::mv(tree); } +inline StringTree toStringTreeOrCharSequence(String&& str) { return StringTree(kj::mv(str)); } + +template +inline auto toStringTreeOrCharSequence(T&& value) + -> decltype(toCharSequence(kj::fwd(value))) { + static_assert(!isStringTree>(), + "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(value)); +} + +} // namespace _ (private) + +struct StringTree::Branch { + size_t index; + // Index in `text` where this branch should be inserted. + + StringTree content; +}; + +template +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 +void StringTree::fill(char* pos, size_t branchIndex, First&& first, Rest&&... rest) { + pos = _::fill(pos, kj::fwd(first)); + fill(pos, branchIndex, kj::fwd(rest)...); +} + +template +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)...); +} + +template +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)...); +} + +template +StringTree StringTree::concat(Params&&... params) { + StringTree result; + result.size_ = _::sum({params.size()...}); + result.text = heapString( + _::sum({StringTree::flatSize(kj::fwd(params))...})); + result.branches = heapArray( + _::sum({StringTree::branchCount(kj::fwd(params))...})); + result.fill(result.text.begin(), 0, kj::fwd(params)...); + return result; +} + +template +StringTree strTree(Params&&... params) { + return StringTree::concat(_::toStringTreeOrCharSequence(kj::fwd(params))...); +} + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/string.c++ b/vendor/capnproto/src/kj/string.c++ new file mode 100644 index 0000000..f298599 --- /dev/null +++ b/vendor/capnproto/src/kj/string.c++ @@ -0,0 +1,593 @@ +// 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 "string.h" +#include "debug.h" +#include +#include +#include +#include +#include + +namespace kj { + +namespace { +bool isHex(const char *s) { + if (*s == '-') s++; + return s[0] == '0' && (s[1] == 'x' || s[1] == 'X'); +} + +long long parseSigned(const StringPtr& s, long long min, long long max) { + KJ_REQUIRE(s != nullptr, "String does not contain valid number", s) { return 0; } + char *endPtr; + errno = 0; + auto value = strtoll(s.begin(), &endPtr, isHex(s.cStr()) ? 16 : 10); + KJ_REQUIRE(endPtr == s.end(), "String does not contain valid number", s) { return 0; } + KJ_REQUIRE(errno != ERANGE, "Value out-of-range", s) { return 0; } + KJ_REQUIRE(value >= min && value <= max, "Value out-of-range", value, min, max) { return 0; } + return value; +} + +Maybe tryParseSigned(const StringPtr& s, long long min, long long max) { + if (s == nullptr) { return nullptr; } // String does not contain valid number. + char *endPtr; + errno = 0; + auto value = strtoll(s.begin(), &endPtr, isHex(s.cStr()) ? 16 : 10); + if (endPtr != s.end() || errno == ERANGE || value < min || max < value) { + return nullptr; + } + return value; +} + +unsigned long long parseUnsigned(const StringPtr& s, unsigned long long max) { + KJ_REQUIRE(s != nullptr, "String does not contain valid number", s) { return 0; } + char *endPtr; + errno = 0; + auto value = strtoull(s.begin(), &endPtr, isHex(s.cStr()) ? 16 : 10); + KJ_REQUIRE(endPtr == s.end(), "String does not contain valid number", s) { return 0; } + KJ_REQUIRE(errno != ERANGE, "Value out-of-range", s) { return 0; } + KJ_REQUIRE(value <= max, "Value out-of-range", value, max) { return 0; } + //strtoull("-1") does not fail with ERANGE + KJ_REQUIRE(s[0] != '-', "Value out-of-range", s) { return 0; } + return value; +} + +Maybe tryParseUnsigned(const StringPtr& s, unsigned long long max) { + if (s == nullptr) { return nullptr; } // String does not contain valid number. + char *endPtr; + errno = 0; + auto value = strtoull(s.begin(), &endPtr, isHex(s.cStr()) ? 16 : 10); + if (endPtr != s.end() || errno == ERANGE || max < value || s[0] == '-') { return nullptr; } + return value; +} + +template +T parseInteger(const StringPtr& s) { + if (static_cast(minValue) < 0) { + long long min = static_cast(minValue); + long long max = static_cast(maxValue); + return static_cast(parseSigned(s, min, max)); + } else { + unsigned long long max = static_cast(maxValue); + return static_cast(parseUnsigned(s, max)); + } +} + +template +Maybe tryParseInteger(const StringPtr& s) { + if (static_cast(minValue) < 0) { + long long min = static_cast(minValue); + long long max = static_cast(maxValue); + return static_cast>(tryParseSigned(s, min, max)); + } else { + unsigned long long max = static_cast(maxValue); + return static_cast>(tryParseUnsigned(s, max)); + } +} + +} // namespace + +#define PARSE_AS_INTEGER(T) \ + template <> T StringPtr::parseAs() const { return parseInteger(*this); } +PARSE_AS_INTEGER(char); +PARSE_AS_INTEGER(signed char); +PARSE_AS_INTEGER(unsigned char); +PARSE_AS_INTEGER(short); +PARSE_AS_INTEGER(unsigned short); +PARSE_AS_INTEGER(int); +PARSE_AS_INTEGER(unsigned int); +PARSE_AS_INTEGER(long); +PARSE_AS_INTEGER(unsigned long); +PARSE_AS_INTEGER(long long); +PARSE_AS_INTEGER(unsigned long long); +#undef PARSE_AS_INTEGER + +#define TRY_PARSE_AS_INTEGER(T) \ + template <> Maybe StringPtr::tryParseAs() const { return tryParseInteger(*this); } +TRY_PARSE_AS_INTEGER(char); +TRY_PARSE_AS_INTEGER(signed char); +TRY_PARSE_AS_INTEGER(unsigned char); +TRY_PARSE_AS_INTEGER(short); +TRY_PARSE_AS_INTEGER(unsigned short); +TRY_PARSE_AS_INTEGER(int); +TRY_PARSE_AS_INTEGER(unsigned int); +TRY_PARSE_AS_INTEGER(long); +TRY_PARSE_AS_INTEGER(unsigned long); +TRY_PARSE_AS_INTEGER(long long); +TRY_PARSE_AS_INTEGER(unsigned long long); +#undef TRY_PARSE_AS_INTEGER + +String heapString(size_t size) { + char* buffer = _::HeapArrayDisposer::allocate(size + 1); + buffer[size] = '\0'; + return String(buffer, size, _::HeapArrayDisposer::instance); +} + +String heapString(const char* value, size_t size) { + char* buffer = _::HeapArrayDisposer::allocate(size + 1); + if (size != 0u) { + memcpy(buffer, value, size); + } + buffer[size] = '\0'; + return String(buffer, size, _::HeapArrayDisposer::instance); +} + +template +static CappedArray hexImpl(T i) { + // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()). + CappedArray result; + uint8_t reverse[sizeof(T) * 2]; + uint8_t* p = reverse; + if (i == 0) { + *p++ = 0; + } else { + while (i > 0) { + *p++ = i % 16; + i /= 16; + } + } + + char* p2 = result.begin(); + while (p > reverse) { + *p2++ = "0123456789abcdef"[*--p]; + } + result.setSize(p2 - result.begin()); + return result; +} + +#define HEXIFY_INT(type) \ +CappedArray hex(type i) { \ + return hexImpl(i); \ +} + +HEXIFY_INT(unsigned char); +HEXIFY_INT(unsigned short); +HEXIFY_INT(unsigned int); +HEXIFY_INT(unsigned long); +HEXIFY_INT(unsigned long long); + +#undef HEXIFY_INT + +namespace _ { // private + +StringPtr Stringifier::operator*(decltype(nullptr)) const { + return "nullptr"; +} + +StringPtr Stringifier::operator*(bool b) const { + return b ? StringPtr("true") : StringPtr("false"); +} + +template +static CappedArray stringifyImpl(T i) { + // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()). + CappedArray result; + bool negative = i < 0; + // Note that if `i` is the most-negative value, negating it produces the same bit value. But + // since it's a signed integer, this is considered an overflow. We therefore must make it + // unsigned first, then negate it, to avoid ubsan complaining. + Unsigned u = i; + if (negative) u = -u; + uint8_t reverse[sizeof(T) * 3 + 1]; + uint8_t* p = reverse; + if (u == 0) { + *p++ = 0; + } else { + while (u > 0) { + *p++ = u % 10; + u /= 10; + } + } + + char* p2 = result.begin(); + if (negative) *p2++ = '-'; + while (p > reverse) { + *p2++ = '0' + *--p; + } + result.setSize(p2 - result.begin()); + return result; +} + +#define STRINGIFY_INT(type, unsigned) \ +CappedArray Stringifier::operator*(type i) const { \ + return stringifyImpl(i); \ +} + +STRINGIFY_INT(signed char, uint); +STRINGIFY_INT(unsigned char, uint); +STRINGIFY_INT(short, uint); +STRINGIFY_INT(unsigned short, uint); +STRINGIFY_INT(int, uint); +STRINGIFY_INT(unsigned int, uint); +STRINGIFY_INT(long, unsigned long); +STRINGIFY_INT(unsigned long, unsigned long); +STRINGIFY_INT(long long, unsigned long long); +STRINGIFY_INT(unsigned long long, unsigned long long); + +#undef STRINGIFY_INT + +CappedArray Stringifier::operator*(const void* i) const { \ + return hexImpl(reinterpret_cast(i)); +} + +namespace { + +// ---------------------------------------------------------------------- +// DoubleToBuffer() +// FloatToBuffer() +// Copied from Protocol Buffers, (C) Google, BSD license. +// Kenton wrote this code originally. The following commentary is +// from the original. +// +// Description: converts a double or float to a string which, if +// passed to NoLocaleStrtod(), will produce the exact same original double +// (except in case of NaN; all NaNs are considered the same value). +// We try to keep the string short but it's not guaranteed to be as +// short as possible. +// +// DoubleToBuffer() and FloatToBuffer() write the text to the given +// buffer and return it. The buffer must be at least +// kDoubleToBufferSize bytes for doubles and kFloatToBufferSize +// bytes for floats. kFastToBufferSize is also guaranteed to be large +// enough to hold either. +// +// We want to print the value without losing precision, but we also do +// not want to print more digits than necessary. This turns out to be +// trickier than it sounds. Numbers like 0.2 cannot be represented +// exactly in binary. If we print 0.2 with a very large precision, +// e.g. "%.50g", we get "0.2000000000000000111022302462515654042363167". +// On the other hand, if we set the precision too low, we lose +// significant digits when printing numbers that actually need them. +// It turns out there is no precision value that does the right thing +// for all numbers. +// +// Our strategy is to first try printing with a precision that is never +// over-precise, then parse the result with strtod() to see if it +// matches. If not, we print again with a precision that will always +// give a precise result, but may use more digits than necessary. +// +// An arguably better strategy would be to use the algorithm described +// in "How to Print Floating-Point Numbers Accurately" by Steele & +// White, e.g. as implemented by David M. Gay's dtoa(). It turns out, +// however, that the following implementation is about as fast as +// DMG's code. Furthermore, DMG's code locks mutexes, which means it +// will not scale well on multi-core machines. DMG's code is slightly +// more accurate (in that it will never use more digits than +// necessary), but this is probably irrelevant for most users. +// +// Rob Pike and Ken Thompson also have an implementation of dtoa() in +// third_party/fmt/fltfmt.cc. Their implementation is similar to this +// one in that it makes guesses and then uses strtod() to check them. +// Their implementation is faster because they use their own code to +// generate the digits in the first place rather than use snprintf(), +// thus avoiding format string parsing overhead. However, this makes +// it considerably more complicated than the following implementation, +// and it is embedded in a larger library. If speed turns out to be +// an issue, we could re-implement this in terms of their +// implementation. +// ---------------------------------------------------------------------- + + +inline bool IsNaN(double value) { + // NaN is never equal to anything, even itself. + return value != value; +} + +// In practice, doubles should never need more than 24 bytes and floats +// should never need more than 14 (including null terminators), but we +// overestimate to be safe. +static const int kDoubleToBufferSize = 32; +static const int kFloatToBufferSize = 24; + +static inline bool IsValidFloatChar(char c) { + return ('0' <= c && c <= '9') || + c == 'e' || c == 'E' || + c == '+' || c == '-'; +} + +void DelocalizeRadix(char* buffer) { + // Fast check: if the buffer has a normal decimal point, assume no + // translation is needed. + if (strchr(buffer, '.') != NULL) return; + + // Find the first unknown character. + while (IsValidFloatChar(*buffer)) ++buffer; + + if (*buffer == '\0') { + // No radix character found. + return; + } + + // We are now pointing at the locale-specific radix character. Replace it + // with '.'. + *buffer = '.'; + ++buffer; + + if (!IsValidFloatChar(*buffer) && *buffer != '\0') { + // It appears the radix was a multi-byte character. We need to remove the + // extra bytes. + char* target = buffer; + do { ++buffer; } while (!IsValidFloatChar(*buffer) && *buffer != '\0'); + memmove(target, buffer, strlen(buffer) + 1); + } +} + +void RemovePlus(char* buffer) { + // Remove any + characters because they are redundant and ugly. + + for (;;) { + buffer = strchr(buffer, '+'); + if (buffer == NULL) { + return; + } + memmove(buffer, buffer + 1, strlen(buffer + 1) + 1); + } +} + + +char* DoubleToBuffer(double value, char* buffer) { + // DBL_DIG is 15 for IEEE-754 doubles, which are used on almost all + // platforms these days. Just in case some system exists where DBL_DIG + // is significantly larger -- and risks overflowing our buffer -- we have + // this assert. + static_assert(DBL_DIG < 20, "DBL_DIG is too big."); + + if (value == inf()) { + strcpy(buffer, "inf"); + return buffer; + } else if (value == -inf()) { + strcpy(buffer, "-inf"); + return buffer; + } else if (IsNaN(value)) { + strcpy(buffer, "nan"); + return buffer; + } + + int snprintf_result KJ_UNUSED = + snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG, value); + + // The snprintf should never overflow because the buffer is significantly + // larger than the precision we asked for. + KJ_DASSERT(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize); + + // We need to make parsed_value volatile in order to force the compiler to + // write it out to the stack. Otherwise, it may keep the value in a + // register, and if it does that, it may keep it as a long double instead + // of a double. This long double may have extra bits that make it compare + // unequal to "value" even though it would be exactly equal if it were + // truncated to a double. + volatile double parsed_value = strtod(buffer, NULL); + if (parsed_value != value) { + int snprintf_result2 KJ_UNUSED = + snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG+2, value); + + // Should never overflow; see above. + KJ_DASSERT(snprintf_result2 > 0 && snprintf_result2 < kDoubleToBufferSize); + } + + DelocalizeRadix(buffer); + RemovePlus(buffer); + return buffer; +} + +bool safe_strtof(const char* str, float* value) { + char* endptr; + errno = 0; // errno only gets set on errors +#if defined (__hpux) // has no strtof() + *value = static_cast(strtod(str, &endptr)); +#else + *value = strtof(str, &endptr); +#endif + return *str != 0 && *endptr == 0 && errno == 0; +} + +char* FloatToBuffer(float value, char* buffer) { + // FLT_DIG is 6 for IEEE-754 floats, which are used on almost all + // platforms these days. Just in case some system exists where FLT_DIG + // is significantly larger -- and risks overflowing our buffer -- we have + // this assert. + static_assert(FLT_DIG < 10, "FLT_DIG is too big"); + + if (value == inf()) { + strcpy(buffer, "inf"); + return buffer; + } else if (value == -inf()) { + strcpy(buffer, "-inf"); + return buffer; + } else if (IsNaN(value)) { + strcpy(buffer, "nan"); + return buffer; + } + + int snprintf_result KJ_UNUSED = + snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG, value); + + // The snprintf should never overflow because the buffer is significantly + // larger than the precision we asked for. + KJ_DASSERT(snprintf_result > 0 && snprintf_result < kFloatToBufferSize); + + float parsed_value; + if (!safe_strtof(buffer, &parsed_value) || parsed_value != value) { + int snprintf_result2 KJ_UNUSED = + snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG+2, value); + + // Should never overflow; see above. + KJ_DASSERT(snprintf_result2 > 0 && snprintf_result2 < kFloatToBufferSize); + } + + DelocalizeRadix(buffer); + RemovePlus(buffer); + return buffer; +} + +// ---------------------------------------------------------------------- +// NoLocaleStrtod() +// This code will make you cry. +// ---------------------------------------------------------------------- + +namespace { + +// Returns a string identical to *input except that the character pointed to +// by radix_pos (which should be '.') is replaced with the locale-specific +// radix character. +kj::String LocalizeRadix(const char* input, const char* radix_pos) { + // Determine the locale-specific radix character by calling sprintf() to + // print the number 1.5, then stripping off the digits. As far as I can + // tell, this is the only portable, thread-safe way to get the C library + // to divuldge the locale's radix character. No, localeconv() is NOT + // thread-safe. + char temp[16]; + int size = snprintf(temp, sizeof(temp), "%.1f", 1.5); + KJ_ASSERT(temp[0] == '1'); + KJ_ASSERT(temp[size-1] == '5'); + KJ_ASSERT(size <= 6); + + // Now replace the '.' in the input with it. + return kj::str( + kj::arrayPtr(input, radix_pos), + kj::arrayPtr(temp + 1, size - 2), + kj::StringPtr(radix_pos + 1)); +} + +} // namespace + +double NoLocaleStrtod(const char* text, char** original_endptr) { + // We cannot simply set the locale to "C" temporarily with setlocale() + // as this is not thread-safe. Instead, we try to parse in the current + // locale first. If parsing stops at a '.' character, then this is a + // pretty good hint that we're actually in some other locale in which + // '.' is not the radix character. + + char* temp_endptr; + double result = strtod(text, &temp_endptr); + if (original_endptr != NULL) *original_endptr = temp_endptr; + if (*temp_endptr != '.') return result; + + // Parsing halted on a '.'. Perhaps we're in a different locale? Let's + // try to replace the '.' with a locale-specific radix character and + // try again. + kj::String localized = LocalizeRadix(text, temp_endptr); + const char* localized_cstr = localized.cStr(); + char* localized_endptr; + result = strtod(localized_cstr, &localized_endptr); + if ((localized_endptr - localized_cstr) > + (temp_endptr - text)) { + // This attempt got further, so replacing the decimal must have helped. + // Update original_endptr to point at the right location. + if (original_endptr != NULL) { + // size_diff is non-zero if the localized radix has multiple bytes. + int size_diff = localized.size() - strlen(text); + // const_cast is necessary to match the strtod() interface. + *original_endptr = const_cast( + text + (localized_endptr - localized_cstr - size_diff)); + } + } + + return result; +} + +// ---------------------------------------------------------------------- +// End of code copied from Protobuf +// ---------------------------------------------------------------------- + +} // namespace + +CappedArray Stringifier::operator*(float f) const { + CappedArray result; + result.setSize(strlen(FloatToBuffer(f, result.begin()))); + return result; +} + +CappedArray Stringifier::operator*(double f) const { + CappedArray result; + result.setSize(strlen(DoubleToBuffer(f, result.begin()))); + return result; +} + +double parseDouble(const StringPtr& s) { + KJ_REQUIRE(s != nullptr, "String does not contain valid number", s) { return 0; } + char *endPtr; + errno = 0; + auto value = _::NoLocaleStrtod(s.begin(), &endPtr); + KJ_REQUIRE(endPtr == s.end(), "String does not contain valid floating number", s) { return 0; } +#if __BIONIC__ + // When Windows' strtod() parses "nan", it returns a value with the sign bit set. But, our + // preferred canonical value for NaN does not have the sign bit set, and all other platforms + // return one without the sign bit set. So, on Windows, detect NaN and return our preferred + // version. + // + // Cygwin seemingly does not try to emulate Linux behavior here, but rather allows Windows' + // behavior to leak through. (Conversely, WINE actually produces the Linux behavior despite + // trying to behave like Win32...) + // + // Bionic (Android) failed the unit test and so I added it to the list without investigating + // further. + if (isNaN(value)) { + // NaN + return kj::nan(); + } +#endif + return value; +} + +Maybe tryParseDouble(const StringPtr& s) { + if(s == nullptr) { return nullptr; } + char *endPtr; + errno = 0; + auto value = _::NoLocaleStrtod(s.begin(), &endPtr); + if (endPtr != s.end()) { return nullptr; } +#if __BIONIC__ + if (isNaN(value)) { + return kj::nan(); + } +#endif + return value; +} + +} // namespace _ (private) + +template <> double StringPtr::parseAs() const { return _::parseDouble(*this); } +template <> float StringPtr::parseAs() const { return _::parseDouble(*this); } + +template <> Maybe StringPtr::tryParseAs() const { return _::tryParseDouble(*this); } +template <> Maybe StringPtr::tryParseAs() const { return _::tryParseDouble(*this); } + +} // namespace kj diff --git a/vendor/capnproto/src/kj/string.h b/vendor/capnproto/src/kj/string.h new file mode 100644 index 0000000..e4b428e --- /dev/null +++ b/vendor/capnproto/src/kj/string.h @@ -0,0 +1,935 @@ +// 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. + +#pragma once + +#include +#include "array.h" +#include "kj/common.h" +#include + +KJ_BEGIN_HEADER + +namespace kj { + class StringPtr; + class LiteralStringConst; + class String; + class ConstString; + + class StringTree; // string-tree.h +} + +constexpr kj::StringPtr operator "" _kj(const char* str, size_t n); +// You can append _kj to a string literal to make its type be StringPtr. There are a few cases +// where you must do this for correctness: +// - When you want to declare a constexpr StringPtr. Without _kj, this is a compile error. +// - When you want to initialize a static/global StringPtr from a string literal without forcing +// global constructor code to run at dynamic initialization time. +// - When you have a string literal that contains NUL characters. Without _kj, the string will +// be considered to end at the first NUL. +// - When you want to initialize an ArrayPtr from a string literal, without including +// the NUL terminator in the data. (Initializing an ArrayPtr from a regular string literal is +// a compile error specifically due to this ambiguity.) +// +// In other cases, there should be no difference between initializing a StringPtr from a regular +// string literal vs. one with _kj (assuming the compiler is able to optimize away strlen() on a +// string literal). + +constexpr kj::LiteralStringConst operator "" _kjc(const char* str, size_t n); + +namespace kj { + +// 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) +#define KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP 1 +#endif + +// ======================================================================================= +// StringPtr -- A NUL-terminated ArrayPtr 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 KJ_LIFETIMEBOUND): content(value, strlen(value) + 1) {} + inline StringPtr(const char* value KJ_LIFETIMEBOUND, size_t size): content(value, size + 1) { + KJ_IREQUIRE(value[size] == '\0', "StringPtr must be NUL-terminated."); + } + inline StringPtr(const char* begin KJ_LIFETIMEBOUND, const char* end KJ_LIFETIMEBOUND): StringPtr(begin, end - begin) {} + inline StringPtr(String&& value KJ_LIFETIMEBOUND) : StringPtr(value) {} + inline StringPtr(const String& value KJ_LIFETIMEBOUND); + inline StringPtr(const ConstString& value KJ_LIFETIMEBOUND); + StringPtr& operator=(String&& value) = delete; + inline StringPtr& operator=(decltype(nullptr)) { + content = ArrayPtr("", 1); + return *this; + } + +#if __cpp_char8_t + inline StringPtr(const char8_t* value KJ_LIFETIMEBOUND): StringPtr(reinterpret_cast(value)) {} + inline StringPtr(const char8_t* value KJ_LIFETIMEBOUND, size_t size) + : StringPtr(reinterpret_cast(value), size) {} + inline StringPtr(const char8_t* begin KJ_LIFETIMEBOUND, const char8_t* end KJ_LIFETIMEBOUND) + : StringPtr(reinterpret_cast(begin), reinterpret_cast(end)) {} + // KJ strings are and always have been UTF-8, so screw this C++20 char8_t stuff. +#endif + +#if KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP + template < + typename T, + typename = EnableIf().c_str()), const char*>()>, + typename = decltype(instance().size())> + inline StringPtr(const T& t KJ_LIFETIMEBOUND): StringPtr(t.c_str(), t.size()) {} + // Allow implicit conversion from any class that has a c_str() and a size() 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 = EnableIf().c_str()), const char*>()>, + typename = decltype(instance().size())> + inline operator T() const { return {cStr(), size()}; } + // Allow implicit conversion to any class that has a c_str() method and a size() 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 constexpr operator ArrayPtr() const; + inline constexpr ArrayPtr asArray() const; + inline ArrayPtr 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 constexpr const char* begin() const { return content.begin(); } + inline constexpr const char* end() const { return content.end() - 1; } + + inline constexpr bool operator==(decltype(nullptr)) const { return content.size() <= 1; } +#if !__cpp_impl_three_way_comparison + inline constexpr bool operator!=(decltype(nullptr)) const { return content.size() > 1; } +#endif + + inline bool operator==(const StringPtr& other) const; +#if !__cpp_impl_three_way_comparison + inline bool operator!=(const StringPtr& other) const { return !(*this == other); } +#endif + 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 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 { return asArray().startsWith(other);} + inline bool endsWith(const StringPtr& other) const { return asArray().endsWith(other); } + + inline Maybe findFirst(char c) const { return asArray().findFirst(c); } + inline Maybe findLast(char c) const { return asArray().findLast(c); } + + template + 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. + template + Maybe tryParseAs() const; + // Same as parseAs, but rather than throwing an exception we return NULL. + + template + ConstString attach(Attachments&&... attachments) const KJ_WARN_UNUSED_RESULT; + ConstString attach() const KJ_WARN_UNUSED_RESULT; + // Like ArrayPtr::attach(), but instead promotes a StringPtr into a ConstString. Generally the + // attachment should be an object that somehow owns the String that the StringPtr is pointing at. + +private: + inline explicit constexpr StringPtr(ArrayPtr content): content(content) {} + friend constexpr StringPtr (::operator "" _kj)(const char* str, size_t n); + friend class LiteralStringConst; + + ArrayPtr content; + friend class SourceLocation; +}; + +#if !__cpp_impl_three_way_comparison +inline bool operator==(const char* a, const StringPtr& b) { return b == a; } +inline bool operator!=(const char* a, const StringPtr& b) { return b != a; } +#endif + +template <> char StringPtr::parseAs() const; +template <> signed char StringPtr::parseAs() const; +template <> unsigned char StringPtr::parseAs() const; +template <> short StringPtr::parseAs() const; +template <> unsigned short StringPtr::parseAs() const; +template <> int StringPtr::parseAs() const; +template <> unsigned StringPtr::parseAs() const; +template <> long StringPtr::parseAs() const; +template <> unsigned long StringPtr::parseAs() const; +template <> long long StringPtr::parseAs() const; +template <> unsigned long long StringPtr::parseAs() const; +template <> float StringPtr::parseAs() const; +template <> double StringPtr::parseAs() const; + +template <> Maybe StringPtr::tryParseAs() const; +template <> Maybe StringPtr::tryParseAs() const; +template <> Maybe StringPtr::tryParseAs() const; +template <> Maybe StringPtr::tryParseAs() const; +template <> Maybe StringPtr::tryParseAs() const; +template <> Maybe StringPtr::tryParseAs() const; +template <> Maybe StringPtr::tryParseAs() const; +template <> Maybe StringPtr::tryParseAs() const; +template <> Maybe StringPtr::tryParseAs() const; +template <> Maybe StringPtr::tryParseAs() const; +template <> Maybe StringPtr::tryParseAs() const; +template <> Maybe StringPtr::tryParseAs() const; +template <> Maybe StringPtr::tryParseAs() const; + +class LiteralStringConst: public StringPtr { +public: + inline operator ConstString() const; + +private: + inline explicit constexpr LiteralStringConst(ArrayPtr content): StringPtr(content) {} + friend constexpr LiteralStringConst (::operator "" _kjc)(const char* str, size_t n); +}; + +// ======================================================================================= +// String -- A NUL-terminated Array 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 buffer); + // Does not copy. Requires `buffer` ends with `\0`. + + inline operator ArrayPtr() KJ_LIFETIMEBOUND; + inline operator ArrayPtr() const KJ_LIFETIMEBOUND; + inline ArrayPtr asArray() KJ_LIFETIMEBOUND; + inline ArrayPtr asArray() const KJ_LIFETIMEBOUND; + inline ArrayPtr asBytes() KJ_LIFETIMEBOUND { return asArray().asBytes(); } + inline ArrayPtr asBytes() const KJ_LIFETIMEBOUND { return asArray().asBytes(); } + // Result does not include NUL terminator. + + inline StringPtr asPtr() const KJ_LIFETIMEBOUND { + // Convenience operator to return a StringPtr. + return StringPtr{*this}; + } + + inline Array 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 KJ_LIFETIMEBOUND; + + inline size_t size() const; + // Result does not include NUL terminator. + + inline char operator[](size_t index) const; + inline char& operator[](size_t index) KJ_LIFETIMEBOUND; + + inline char* begin() KJ_LIFETIMEBOUND; + inline char* end() KJ_LIFETIMEBOUND; + inline const char* begin() const KJ_LIFETIMEBOUND; + inline const char* end() const KJ_LIFETIMEBOUND; + + 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; } +#if !__cpp_impl_three_way_comparison + inline bool operator!=(const StringPtr& other) const { return StringPtr(*this) != other; } +#endif + 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 String& other) const { return StringPtr(*this) == StringPtr(other); } +#if !__cpp_impl_three_way_comparison + inline bool operator!=(const String& other) const { return StringPtr(*this) != StringPtr(other); } +#endif + inline bool operator< (const String& other) const { return StringPtr(*this) < StringPtr(other); } + inline bool operator> (const String& other) const { return StringPtr(*this) > StringPtr(other); } + inline bool operator<=(const String& other) const { return StringPtr(*this) <= StringPtr(other); } + inline bool operator>=(const String& other) const { return StringPtr(*this) >= StringPtr(other); } + // Note that if we don't overload for `const String&` specifically, then C++20 will decide that + // comparisons between two strings are ambiguous. (Clang turns this into a warning, + // -Wambiguous-reversed-operator, due to the stupidity...) + + inline bool operator==(const ConstString& other) const { return StringPtr(*this) == StringPtr(other); } +#if !__cpp_impl_three_way_comparison + inline bool operator!=(const ConstString& other) const { return StringPtr(*this) != StringPtr(other); } +#endif + inline bool operator< (const ConstString& other) const { return StringPtr(*this) < StringPtr(other); } + inline bool operator> (const ConstString& other) const { return StringPtr(*this) > StringPtr(other); } + inline bool operator<=(const ConstString& other) const { return StringPtr(*this) <= StringPtr(other); } + inline bool operator>=(const ConstString& other) const { return StringPtr(*this) >= StringPtr(other); } + + inline bool startsWith(const StringPtr& other) const { return asArray().startsWith(other);} + inline bool endsWith(const StringPtr& other) const { return asArray().endsWith(other); } + + inline StringPtr slice(size_t start) const KJ_LIFETIMEBOUND { + return StringPtr(*this).slice(start); + } + inline ArrayPtr slice(size_t start, size_t end) const KJ_LIFETIMEBOUND { + return StringPtr(*this).slice(start, end); + } + + inline Maybe findFirst(char c) const { return asArray().findFirst(c); } + inline Maybe findLast(char c) const { return asArray().findLast(c); } + + template + T parseAs() const { return StringPtr(*this).parseAs(); } + // Parse as number + + template + Maybe tryParseAs() const { return StringPtr(*this).tryParseAs(); } + +private: + Array content; +}; + +// ======================================================================================= +// ConstString -- Same as String, but the backing buffer is const. +// +// This has the useful property that it can reference a string literal without allocating +// a copy. Any String can also convert (by move) to ConstString, transferring ownership of +// the buffer. + +class ConstString { +public: + ConstString() = default; + inline ConstString(decltype(nullptr)): content(nullptr) {} + inline ConstString(const 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 ConstString(Array buffer); + // Does not copy. Requires `buffer` ends with `\0`. + inline explicit ConstString(String&& string): content(string.releaseArray()) {} + // Does not copy. Ownership is transfered. + + inline operator ArrayPtr() const KJ_LIFETIMEBOUND; + inline ArrayPtr asArray() const KJ_LIFETIMEBOUND; + inline ArrayPtr asBytes() const KJ_LIFETIMEBOUND { return asArray().asBytes(); } + // Result does not include NUL terminator. + + inline StringPtr asPtr() const KJ_LIFETIMEBOUND { + // Convenience operator to return a StringPtr. + return StringPtr{*this}; + } + + inline Array releaseArray() { return kj::mv(content); } + // Disowns the backing array (which includes the NUL terminator) and returns it. The ConstString value + // is clobbered (as if moved away). + + inline const char* cStr() const KJ_LIFETIMEBOUND; + + inline size_t size() const; + // Result does not include NUL terminator. + + inline char operator[](size_t index) const; + inline char& operator[](size_t index) KJ_LIFETIMEBOUND; + + inline const char* begin() const KJ_LIFETIMEBOUND; + inline const char* end() const KJ_LIFETIMEBOUND; + + 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; } +#if !__cpp_impl_three_way_comparison + inline bool operator!=(const StringPtr& other) const { return StringPtr(*this) != other; } +#endif + 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 String& other) const { return StringPtr(*this) == StringPtr(other); } +#if !__cpp_impl_three_way_comparison + inline bool operator!=(const String& other) const { return StringPtr(*this) != StringPtr(other); } +#endif + inline bool operator< (const String& other) const { return StringPtr(*this) < StringPtr(other); } + inline bool operator> (const String& other) const { return StringPtr(*this) > StringPtr(other); } + inline bool operator<=(const String& other) const { return StringPtr(*this) <= StringPtr(other); } + inline bool operator>=(const String& other) const { return StringPtr(*this) >= StringPtr(other); } + + inline bool operator==(const ConstString& other) const { return StringPtr(*this) == StringPtr(other); } +#if !__cpp_impl_three_way_comparison + inline bool operator!=(const ConstString& other) const { return StringPtr(*this) != StringPtr(other); } +#endif + inline bool operator< (const ConstString& other) const { return StringPtr(*this) < StringPtr(other); } + inline bool operator> (const ConstString& other) const { return StringPtr(*this) > StringPtr(other); } + inline bool operator<=(const ConstString& other) const { return StringPtr(*this) <= StringPtr(other); } + inline bool operator>=(const ConstString& other) const { return StringPtr(*this) >= StringPtr(other); } + // Note that if we don't overload for `const ConstString&` specifically, then C++20 will decide that + // comparisons between two strings are ambiguous. (Clang turns this into a warning, + // -Wambiguous-reversed-operator, due to the stupidity...) + + inline bool startsWith(const StringPtr& other) const { return asArray().startsWith(other);} + inline bool endsWith(const StringPtr& other) const { return asArray().endsWith(other); } + + inline StringPtr slice(size_t start) const KJ_LIFETIMEBOUND { + return StringPtr(*this).slice(start); + } + inline ArrayPtr slice(size_t start, size_t end) const KJ_LIFETIMEBOUND { + return StringPtr(*this).slice(start, end); + } + + inline Maybe findFirst(char c) const { return asArray().findFirst(c); } + inline Maybe findLast(char c) const { return asArray().findLast(c); } + + template + T parseAs() const { return StringPtr(*this).parseAs(); } + // Parse as number + + template + Maybe tryParseAs() const { return StringPtr(*this).tryParseAs(); } + +private: + Array content; +}; + +#if !__cpp_impl_three_way_comparison +inline bool operator==(const char* a, const String& b) { return b == a; } +inline bool operator!=(const char* a, const String& b) { return b != a; } +#endif + +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 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 nums) { + size_t result = 0; + for (auto num: nums) { + result += num; + } + return result; +} + +inline char* fill(char* ptr) { return ptr; } +inline char* fillLimited(char* ptr, char* limit) { return ptr; } + +template +char* fill(char* __restrict__ target, const StringTree& first, Rest&&... rest); +template +char* fillLimited(char* __restrict__ target, char* limit, const StringTree& first, Rest&&... rest); +// Make str() work with stringifiers that return StringTree by patching fill(). +// +// Defined in string-tree.h. + +template +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)...); +} + +template +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)...); + return result; +} + +inline String concat(String&& arr) { + return kj::mv(arr); +} + +template +char* fillLimited(char* __restrict__ target, char* limit, const First& first, Rest&&... rest) { + auto i = first.begin(); + auto end = first.end(); + while (i != end) { + if (target == limit) return target; + *target++ = *i++; + } + return fillLimited(target, limit, kj::fwd(rest)...); +} + +template +class Delimited; +// Delimits a sequence of type T with a string delimiter. Implements kj::delimited(). + +template +char* fill(char* __restrict__ target, Delimited&& first, Rest&&... rest); +template +char* fillLimited(char* __restrict__ target, char* limit, Delimited&& first,Rest&&... rest); +template +char* fill(char* __restrict__ target, Delimited& first, Rest&&... rest); +template +char* fillLimited(char* __restrict__ target, char* limit, Delimited& first,Rest&&... rest); +// As with StringTree, we special-case Delimited. + +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 operator*(ArrayPtr s) const { return s; } + inline ArrayPtr operator*(ArrayPtr s) const { return s; } + inline ArrayPtr operator*(const Array& s) const KJ_LIFETIMEBOUND { + return s; + } + inline ArrayPtr operator*(const Array& s) const KJ_LIFETIMEBOUND { return s; } + template + inline ArrayPtr operator*(const CappedArray& s) const KJ_LIFETIMEBOUND { + return s; + } + template + inline ArrayPtr operator*(const FixedArray& s) const KJ_LIFETIMEBOUND { + return s; + } + inline ArrayPtr operator*(const char* s) const KJ_LIFETIMEBOUND { + return arrayPtr(s, strlen(s)); + } +#if __cpp_char8_t + inline ArrayPtr operator*(const char8_t* s) const KJ_LIFETIMEBOUND { + return operator*(reinterpret_cast(s)); + } +#endif + inline ArrayPtr operator*(const String& s) const KJ_LIFETIMEBOUND { + return s.asArray(); + } + inline ArrayPtr operator*(const StringPtr& s) const { return s.asArray(); } + inline ArrayPtr operator*(const ConstString& s) const { return s.asArray(); } + + inline Range operator*(const Range& r) const { return r; } + inline Repeat operator*(const Repeat& r) const { return r; } + + inline FixedArray operator*(char c) const { + FixedArray result; + result[0] = c; + return result; + } + + StringPtr operator*(decltype(nullptr)) const; + StringPtr operator*(bool b) const; + + CappedArray operator*(signed char i) const; + CappedArray operator*(unsigned char i) const; + CappedArray operator*(short i) const; + CappedArray operator*(unsigned short i) const; + CappedArray operator*(int i) const; + CappedArray operator*(unsigned int i) const; + CappedArray operator*(long i) const; + CappedArray operator*(unsigned long i) const; + CappedArray operator*(long long i) const; + CappedArray operator*(unsigned long long i) const; + CappedArray operator*(float f) const; + CappedArray operator*(double f) const; + CappedArray operator*(const void* s) const; + +#if KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP // supports expression SFINAE? + template ().toString())> + inline Result operator*(T&& value) const { return kj::fwd(value).toString(); } +#endif +}; +static KJ_CONSTEXPR(const) Stringifier STR = Stringifier(); + +} // namespace _ (private) + +template +auto toCharSequence(T&& value) -> decltype(_::STR * kj::fwd(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(value); +} + +CappedArray hex(unsigned char i); +CappedArray hex(unsigned short i); +CappedArray hex(unsigned int i); +CappedArray hex(unsigned long i); +CappedArray hex(unsigned long long i); + +template +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))...); +} + +inline String str(String&& s) { return mv(s); } +// Overload to prevent redundant allocation. + +template +_::Delimited delimited(T&& arr, kj::StringPtr delim); +// Use to stringify an array. + +template +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; +} + +template +StringPtr strPreallocated(ArrayPtr buffer, Params&&... params) { + // Like str() but writes into a preallocated buffer. If the buffer is not long enough, the result + // is truncated (but still NUL-terminated). + // + // This can be used like: + // + // char buffer[256]; + // StringPtr text = strPreallocated(buffer, params...); + // + // This is useful for optimization. It can also potentially be used safely in async signal + // handlers. HOWEVER, to use in an async signal handler, all of the stringifiers for the inputs + // must also be signal-safe. KJ guarantees signal safety when stringifying any built-in integer + // type (but NOT floating-points), basic char/byte sequences (ArrayPtr, String, etc.), as + // well as Array as long as T can also be stringified safely. To safely stringify a delimited + // array, you must use kj::delimited(arr, delim) rather than the deprecated + // kj::strArray(arr, delim). + + char* end = _::fillLimited(buffer.begin(), buffer.end() - 1, + toCharSequence(kj::fwd(params))...); + *end = '\0'; + return StringPtr(buffer.begin(), end); +} + +template ()))> +inline _::Delimited> operator*(const _::Stringifier&, ArrayPtr arr) { + return _::Delimited>(arr, ", "); +} + +template ()))> +inline _::Delimited> operator*(const _::Stringifier&, const Array& arr) { + return _::Delimited>(arr, ", "); +} + +#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(); } +// // or perhaps +// inline String KJ_STRINGIFY(const Foo& foo) { return kj::str(foo.fld1(), ",", foo.fld2()); } +// +// 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.cStr(), value.size() + 1) {} +inline StringPtr::StringPtr(const ConstString& value): content(value.cStr(), value.size() + 1) {} + +inline constexpr StringPtr::operator ArrayPtr() const { + return ArrayPtr(content.begin(), content.size() - 1); +} + +inline constexpr ArrayPtr StringPtr::asArray() const { + return ArrayPtr(content.begin(), 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 StringPtr::slice(size_t start, size_t end) const { + return content.slice(start, end); +} + +inline LiteralStringConst::operator ConstString() const { + return ConstString(begin(), size(), NullArrayDisposer::instance); +} + +inline ConstString StringPtr::attach() const { + // This is meant as a roundabout way to make a ConstString from a StringPtr + return ConstString(begin(), size(), NullArrayDisposer::instance); +} + +template +inline ConstString StringPtr::attach(Attachments&&... attachments) const { + return ConstString { content.attach(kj::fwd(attachments)...) }; +} + +inline String::operator ArrayPtr() { + return content == nullptr ? ArrayPtr(nullptr) : content.slice(0, content.size() - 1); +} +inline String::operator ArrayPtr() const { + return content == nullptr ? ArrayPtr(nullptr) : content.slice(0, content.size() - 1); +} +inline ConstString::operator ArrayPtr() const { + return content == nullptr ? ArrayPtr(nullptr) : content.slice(0, content.size() - 1); +} + +inline ArrayPtr String::asArray() { + return content == nullptr ? ArrayPtr(nullptr) : content.slice(0, content.size() - 1); +} +inline ArrayPtr String::asArray() const { + return content == nullptr ? ArrayPtr(nullptr) : content.slice(0, content.size() - 1); +} +inline ArrayPtr ConstString::asArray() const { + return content == nullptr ? ArrayPtr(nullptr) : content.slice(0, content.size() - 1); +} + +inline const char* String::cStr() const { return content == nullptr ? "" : content.begin(); } +inline const char* ConstString::cStr() const { return content == nullptr ? "" : content.begin(); } + +inline size_t String::size() const { return content == nullptr ? 0 : content.size() - 1; } +inline size_t ConstString::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 ConstString::operator[](size_t index) const { 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 const char* ConstString::begin() const { return content == nullptr ? nullptr : content.begin(); } +inline const char* ConstString::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 ConstString::ConstString(const 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 buffer): content(kj::mv(buffer)) { + KJ_IREQUIRE(content.size() > 0 && content.back() == '\0', "String must be NUL-terminated."); +} +inline ConstString::ConstString(Array 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 value) { + return heapString(value.begin(), value.size()); +} + +namespace _ { // private + +template +class Delimited { +public: + Delimited(T array, kj::StringPtr delimiter) + : array(kj::fwd(array)), delimiter(delimiter) {} + + // TODO(someday): In theory we should support iteration as a character sequence, but the iterator + // will be pretty complicated. + + size_t size() { + ensureStringifiedInitialized(); + + size_t result = 0; + bool first = true; + for (auto& e: stringified) { + if (first) { + first = false; + } else { + result += delimiter.size(); + } + result += e.size(); + } + return result; + } + + char* flattenTo(char* __restrict__ target) { + ensureStringifiedInitialized(); + + bool first = true; + for (auto& elem: stringified) { + if (first) { + first = false; + } else { + target = fill(target, delimiter); + } + target = fill(target, elem); + } + return target; + } + + char* flattenTo(char* __restrict__ target, char* limit) { + // This is called in the strPreallocated(). We want to avoid allocation. size() will not have + // been called in this case, so hopefully `stringified` is still uninitialized. We will + // stringify each item and immediately use it. + bool first = true; + for (auto&& elem: array) { + if (target == limit) return target; + if (first) { + first = false; + } else { + target = fillLimited(target, limit, delimiter); + } + target = fillLimited(target, limit, kj::toCharSequence(elem)); + } + return target; + } + +private: + typedef decltype(toCharSequence(*instance().begin())) StringifiedItem; + T array; + kj::StringPtr delimiter; + Array stringified; + + void ensureStringifiedInitialized() { + if (array.size() > 0 && stringified.size() == 0) { + stringified = KJ_MAP(e, array) { return toCharSequence(e); }; + } + } +}; + +template +char* fill(char* __restrict__ target, Delimited&& first, Rest&&... rest) { + target = first.flattenTo(target); + return fill(target, kj::fwd(rest)...); +} +template +char* fillLimited(char* __restrict__ target, char* limit, Delimited&& first, Rest&&... rest) { + target = first.flattenTo(target, limit); + return fillLimited(target, limit, kj::fwd(rest)...); +} +template +char* fill(char* __restrict__ target, Delimited& first, Rest&&... rest) { + target = first.flattenTo(target); + return fill(target, kj::fwd(rest)...); +} +template +char* fillLimited(char* __restrict__ target, char* limit, Delimited& first, Rest&&... rest) { + target = first.flattenTo(target, limit); + return fillLimited(target, limit, kj::fwd(rest)...); +} + +template +inline Delimited&& KJ_STRINGIFY(Delimited&& delimited) { return kj::mv(delimited); } +template +inline const Delimited& KJ_STRINGIFY(const Delimited& delimited) { return delimited; } + +} // namespace _ (private) + +template +_::Delimited delimited(T&& arr, kj::StringPtr delim) { + return _::Delimited(kj::fwd(arr), delim); +} + +} // namespace kj + +constexpr kj::StringPtr operator "" _kj(const char* str, size_t n) { + return kj::StringPtr(kj::ArrayPtr(str, n + 1)); +}; + +constexpr kj::LiteralStringConst operator "" _kjc(const char* str, size_t n) { + return kj::LiteralStringConst(kj::ArrayPtr(str, n + 1)); +}; + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/table.c++ b/vendor/capnproto/src/kj/table.c++ new file mode 100644 index 0000000..360d41e --- /dev/null +++ b/vendor/capnproto/src/kj/table.c++ @@ -0,0 +1,945 @@ +// Copyright (c) 2018 Kenton Varda 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 "table.h" +#include "debug.h" +#include + +#if KJ_DEBUG_TABLE_IMPL +#undef KJ_DASSERT +#define KJ_DASSERT KJ_ASSERT +#endif + +namespace kj { +namespace _ { + +static inline uint lg(uint value) { + // Compute floor(log2(value)). + // + // Undefined for value = 0. + return sizeof(uint) * 8 - 1 - __builtin_clz(value); +} + +void throwDuplicateTableRow() { + KJ_FAIL_REQUIRE("inserted row already exists in table"); +} + +void logHashTableInconsistency() { + KJ_LOG(ERROR, + "HashIndex detected hash table inconsistency. This can happen if you create a kj::Table " + "with a hash index and you modify the rows in the table post-indexing in a way that would " + "change their hash. This is a serious bug which will lead to undefined behavior." + "\nstack: ", kj::getStackTrace()); +} + +// List of primes where each element is roughly double the previous. Obtained +// from: +// http://planetmath.org/goodhashtableprimes +// Primes < 53 were added to ensure that small tables don't allocate excessive memory. +static const size_t PRIMES[] = { + 1, // 2^ 0 = 1 + 3, // 2^ 1 = 2 + 5, // 2^ 2 = 4 + 11, // 2^ 3 = 8 + 23, // 2^ 4 = 16 + 53, // 2^ 5 = 32 + 97, // 2^ 6 = 64 + 193, // 2^ 7 = 128 + 389, // 2^ 8 = 256 + 769, // 2^ 9 = 512 + 1543, // 2^10 = 1024 + 3079, // 2^11 = 2048 + 6151, // 2^12 = 4096 + 12289, // 2^13 = 8192 + 24593, // 2^14 = 16384 + 49157, // 2^15 = 32768 + 98317, // 2^16 = 65536 + 196613, // 2^17 = 131072 + 393241, // 2^18 = 262144 + 786433, // 2^19 = 524288 + 1572869, // 2^20 = 1048576 + 3145739, // 2^21 = 2097152 + 6291469, // 2^22 = 4194304 + 12582917, // 2^23 = 8388608 + 25165843, // 2^24 = 16777216 + 50331653, // 2^25 = 33554432 + 100663319, // 2^26 = 67108864 + 201326611, // 2^27 = 134217728 + 402653189, // 2^28 = 268435456 + 805306457, // 2^29 = 536870912 + 1610612741, // 2^30 = 1073741824 +}; + +uint chooseBucket(uint hash, uint count) { + // Integer modulus is really, really slow. It turns out that the compiler can generate much + // faster code if the denominator is a constant. Since we have a fixed set of possible + // denominators, a big old switch() statement is a win. + + // TODO(perf): Consider using power-of-two bucket sizes. We can safely do so as long as we demand + // high-quality hash functions -- kj::hashCode() needs good diffusion even for integers, can't + // just be a cast. Also be sure to implement Robin Hood hashing to avoid extremely bad negative + // lookup time when elements have sequential hashes (otherwise, it could be necessary to scan + // the entire list to determine that an element isn't present). + + switch (count) { +#define HANDLE(i) case i##u: return hash % i##u + HANDLE( 1); + HANDLE( 3); + HANDLE( 5); + HANDLE( 11); + HANDLE( 23); + HANDLE( 53); + HANDLE( 97); + HANDLE( 193); + HANDLE( 389); + HANDLE( 769); + HANDLE( 1543); + HANDLE( 3079); + HANDLE( 6151); + HANDLE( 12289); + HANDLE( 24593); + HANDLE( 49157); + HANDLE( 98317); + HANDLE( 196613); + HANDLE( 393241); + HANDLE( 786433); + HANDLE( 1572869); + HANDLE( 3145739); + HANDLE( 6291469); + HANDLE( 12582917); + HANDLE( 25165843); + HANDLE( 50331653); + HANDLE( 100663319); + HANDLE( 201326611); + HANDLE( 402653189); + HANDLE( 805306457); + HANDLE(1610612741); +#undef HANDLE + default: return hash % count; + } +} + +size_t chooseHashTableSize(uint size) { + if (size == 0) return 0; + + // Add 1 to compensate for the floor() above, then look up the best prime bucket size for that + // target size. + return PRIMES[lg(size) + 1]; +} + +kj::Array rehash(kj::ArrayPtr oldBuckets, size_t targetSize) { + // Rehash the whole table. + + KJ_REQUIRE(targetSize < (1 << 30), "hash table has reached maximum size"); + + size_t size = chooseHashTableSize(targetSize); + + if (size < oldBuckets.size()) { + size = oldBuckets.size(); + } + + auto newBuckets = kj::heapArray(size); + memset(newBuckets.begin(), 0, sizeof(HashBucket) * size); + + uint entryCount = 0; + uint collisionCount = 0; + + for (auto& oldBucket: oldBuckets) { + if (oldBucket.isOccupied()) { + ++entryCount; + for (uint i = oldBucket.hash % newBuckets.size();; i = probeHash(newBuckets, i)) { + auto& newBucket = newBuckets[i]; + if (newBucket.isEmpty()) { + newBucket = oldBucket; + break; + } + ++collisionCount; + } + } + } + + if (collisionCount > 16 + entryCount * 4) { + static bool warned = false; + if (!warned) { + KJ_LOG(WARNING, "detected excessive collisions in hash table; is your hash function OK?", + entryCount, collisionCount, kj::getStackTrace()); + warned = true; + } + } + + return newBuckets; +} + +// ======================================================================================= +// BTree + +#define aligned_free ::free + +BTreeImpl::BTreeImpl() + : tree(const_cast(&EMPTY_NODE)), + treeCapacity(1), + height(0), + freelistHead(1), + freelistSize(0), + beginLeaf(0), + endLeaf(0) {} + +BTreeImpl::~BTreeImpl() noexcept(false) { + if (tree != &EMPTY_NODE) { + aligned_free(tree); + } +} + +BTreeImpl::BTreeImpl(BTreeImpl&& other) + : BTreeImpl() { + *this = kj::mv(other); +} + +BTreeImpl& BTreeImpl::operator=(BTreeImpl&& other) { + KJ_DASSERT(&other != this); + + if (tree != &EMPTY_NODE) { + aligned_free(tree); + } + tree = other.tree; + treeCapacity = other.treeCapacity; + height = other.height; + freelistHead = other.freelistHead; + freelistSize = other.freelistSize; + beginLeaf = other.beginLeaf; + endLeaf = other.endLeaf; + + other.tree = const_cast(&EMPTY_NODE); + other.treeCapacity = 1; + other.height = 0; + other.freelistHead = 1; + other.freelistSize = 0; + other.beginLeaf = 0; + other.endLeaf = 0; + + return *this; +} + +const BTreeImpl::NodeUnion BTreeImpl::EMPTY_NODE = {{{0, {0}}}}; + +void BTreeImpl::verify(size_t size, FunctionParam f) { + KJ_ASSERT(verifyNode(size, f, 0, height, nullptr) == size); +} +size_t BTreeImpl::verifyNode(size_t size, FunctionParam& f, + uint pos, uint height, MaybeUint maxRow) { + if (height > 0) { + auto& parent = tree[pos].parent; + + auto n = parent.keyCount(); + size_t total = 0; + for (auto i: kj::zeroTo(n)) { + KJ_ASSERT(*parent.keys[i] < size, n, i); + total += verifyNode(size, f, parent.children[i], height - 1, parent.keys[i]); + if (i > 0) { + KJ_ASSERT(f(*parent.keys[i - 1], *parent.keys[i]), + n, i, parent.keys[i - 1], parent.keys[i]); + } + } + total += verifyNode(size, f, parent.children[n], height - 1, maxRow); + if (maxRow != nullptr) { + KJ_ASSERT(f(*parent.keys[n-1], *maxRow), n, parent.keys[n-1], maxRow); + } + return total; + } else { + auto& leaf = tree[pos].leaf; + auto n = leaf.size(); + for (auto i: kj::zeroTo(n)) { + KJ_ASSERT(*leaf.rows[i] < size, n, i); + if (i > 0) { + KJ_ASSERT(f(*leaf.rows[i - 1], *leaf.rows[i]), + n, i, leaf.rows[i - 1], leaf.rows[i]); + } + } + if (maxRow != nullptr) { + KJ_ASSERT(leaf.rows[n-1] == maxRow, n); + } + return n; + } +} + +kj::String BTreeImpl::MaybeUint::toString() const { + return i == 0 ? kj::str("(null)") : kj::str(i - 1); +} + +void BTreeImpl::logInconsistency() const { + KJ_LOG(ERROR, + "BTreeIndex detected tree state inconsistency. This can happen if you create a kj::Table " + "with a b-tree index and you modify the rows in the table post-indexing in a way that would " + "change their ordering. This is a serious bug which will lead to undefined behavior." + "\nstack: ", kj::getStackTrace()); +} + +void BTreeImpl::reserve(size_t size) { + KJ_REQUIRE(size < (1u << 31), "b-tree has reached maximum size"); + + // Calculate the worst-case number of leaves to cover the size, given that a leaf is always at + // least half-full. (Note that it's correct for this calculation to round down, not up: The + // remainder will necessarily be distributed among the non-full leaves, rather than creating a + // new leaf, because if it went into a new leaf, that leaf would be less than half-full.) + uint leaves = size / (Leaf::NROWS / 2); + + // Calculate the worst-case number of parents to cover the leaves, given that a parent is always + // at least half-full. Since the parents form a tree with branching factor B, the size of the + // tree is N/B + N/B^2 + N/B^3 + N/B^4 + ... = N / (B - 1). Math. + constexpr uint branchingFactor = Parent::NCHILDREN / 2; + uint parents = leaves / (branchingFactor - 1); + + // Height is log-base-branching-factor of leaves, plus 1 for the root node. + uint height = lg(leaves | 1) / lg(branchingFactor) + 1; + + size_t newSize = leaves + + parents + 1 + // + 1 for the root + height + 2; // minimum freelist size needed by insert() + + if (treeCapacity < newSize) { + growTree(newSize); + } +} + +void BTreeImpl::clear() { + if (tree != &EMPTY_NODE) { + azero(tree, treeCapacity); + height = 0; + freelistHead = 1; + freelistSize = treeCapacity - 1; // subtract one to account for the root node + beginLeaf = 0; + endLeaf = 0; + } +} + +void BTreeImpl::growTree(uint minCapacity) { + uint newCapacity = kj::max(kj::max(minCapacity, treeCapacity * 2), 4); + freelistSize += newCapacity - treeCapacity; + + // Allocate some aligned memory! In theory this should be as simple as calling the C11 standard + // aligned_alloc() function. Unfortunately, many platforms don't implement it. Luckily, there + // are usually alternatives. + + // macOS, OpenBSD, and Android lack aligned_alloc(), but have posix_memalign(). Fine. + void* allocPtr; + int error = posix_memalign(&allocPtr, + sizeof(BTreeImpl::NodeUnion), newCapacity * sizeof(BTreeImpl::NodeUnion)); + if (error != 0) { + KJ_FAIL_SYSCALL("posix_memalign", error); + } + NodeUnion* newTree = reinterpret_cast(allocPtr); + + // Note: C11 introduces aligned_alloc() as a standard, but it's still missing on many platforms, + // so we don't use it. But if you wanted to use it, you'd do this: +// NodeUnion* newTree = reinterpret_cast( +// aligned_alloc(sizeof(BTreeImpl::NodeUnion), newCapacity * sizeof(BTreeImpl::NodeUnion))); +// KJ_ASSERT(newTree != nullptr, "memory allocation failed", newCapacity); + + acopy(newTree, tree, treeCapacity); + azero(newTree + treeCapacity, newCapacity - treeCapacity); + if (tree != &EMPTY_NODE) aligned_free(tree); + tree = newTree; + treeCapacity = newCapacity; +} + +BTreeImpl::Iterator BTreeImpl::search(const SearchKey& searchKey) const { + // Find the "first" row number (in sorted order) for which searchKey.isAfter(rowNumber) returns + // false. + + uint pos = 0; + + for (auto i KJ_UNUSED: zeroTo(height)) { + auto& parent = tree[pos].parent; + pos = parent.children[searchKey.search(parent)]; + } + + auto& leaf = tree[pos].leaf; + return { tree, &leaf, searchKey.search(leaf) }; +} + +template +struct BTreeImpl::AllocResult { + uint index; + T& node; +}; + +template +inline BTreeImpl::AllocResult BTreeImpl::alloc() { + // Allocate a new item from the freelist. Guaranteed to be zero'd except for the first member. + uint i = freelistHead; + NodeUnion* ptr = &tree[i]; + freelistHead = i + 1 + ptr->freelist.nextOffset; + --freelistSize; + return { i, *ptr }; +} + +inline void BTreeImpl::free(uint pos) { + // Add the given node to the freelist. + + // HACK: This is typically called on a node immediately after copying its contents away, but the + // pointer used to copy it away may be a different pointer pointing to a different union member + // which the compiler may not recgonize as aliasing with this object. Just to be extra-safe, + // insert a compiler barrier. + compilerBarrier(); + + auto& node = tree[pos]; + node.freelist.nextOffset = freelistHead - pos - 1; + azero(node.freelist.zero, kj::size(node.freelist.zero)); + freelistHead = pos; + ++freelistSize; +} + +BTreeImpl::Iterator BTreeImpl::insert(const SearchKey& searchKey) { + // Like search() but ensures that there is room in the leaf node to insert a new row. + + // If we split the root node it will generate two new nodes. If we split any other node in the + // path it will generate one new node. `height` doesn't count leaf nodes, but we can equivalently + // think of it as not counting the root node, so in the worst case we may allocate height + 2 + // new nodes. + // + // (Also note that if the tree is currently empty, then `tree` points to a dummy root node in + // read-only memory. We definitely need to allocate a real tree node array in this case, and + // we'll start out allocating space for four nodes, which will be all we need up to 28 rows.) + if (freelistSize < height + 2) { + if (height > 0 && !tree[0].parent.isFull() && freelistSize >= height) { + // Slight optimization: The root node is not full, so we're definitely not going to split it. + // That means that the maximum allocations we might do is equal to `height`, not + // `height + 2`, and we have that much space, so no need to grow yet. + // + // This optimization is particularly important for small trees, e.g. when treeCapacity is 4 + // and the tree so far consists of a root and two children, we definitely don't need to grow + // the tree yet. + } else { + growTree(); + + if (freelistHead == 0) { + // We have no root yet. Allocate one. + KJ_ASSERT(alloc().index == 0); + } + } + } + + uint pos = 0; + + // Track grandparent node and child index within grandparent. + Parent* parent = nullptr; + uint indexInParent = 0; + + for (auto i KJ_UNUSED: zeroTo(height)) { + Parent& node = insertHelper(searchKey, tree[pos].parent, parent, indexInParent, pos); + + parent = &node; + indexInParent = searchKey.search(node); + pos = node.children[indexInParent]; + } + + Leaf& leaf = insertHelper(searchKey, tree[pos].leaf, parent, indexInParent, pos); + + // Fun fact: Unlike erase(), there's no need to climb back up the tree modifying keys, because + // either the newly-inserted node will not be the last in the leaf (and thus parent keys aren't + // modified), or the leaf is the last leaf in the tree (and thus there's no parent key to + // modify). + + return { tree, &leaf, searchKey.search(leaf) }; +} + +template +Node& BTreeImpl::insertHelper(const SearchKey& searchKey, + Node& node, Parent* parent, uint indexInParent, uint pos) { + if (node.isFull()) { + // This node is full. Need to split. + if (parent == nullptr) { + // This is the root node. We need to split into two nodes and create a new root. + auto n1 = alloc(); + auto n2 = alloc(); + + uint pivot = split(n2.node, n2.index, node, pos); + move(n1.node, n1.index, node); + + // Rewrite root to have the two children. + tree[0].parent.initRoot(pivot, n1.index, n2.index); + + // Increased height. + ++height; + + // Decide which new branch has our search key. + if (searchKey.isAfter(pivot)) { + // the right one + return n2.node; + } else { + // the left one + return n1.node; + } + } else { + // This is a non-root parent node. We need to split it into two and insert the new node + // into the grandparent. + auto n = alloc(); + uint pivot = split(n.node, n.index, node, pos); + + // Insert new child into grandparent. + parent->insertAfter(indexInParent, pivot, n.index); + + // Decide which new branch has our search key. + if (searchKey.isAfter(pivot)) { + // the new one, which is right of the original + return n.node; + } else { + // the original one, which is left of the new one + return node; + } + } + } else { + // No split needed. + return node; + } +} + +void BTreeImpl::erase(uint row, const SearchKey& searchKey) { + // Erase the given row number from the tree. predicate() returns true for the given row and all + // rows after it. + + uint pos = 0; + + // Track grandparent node and child index within grandparent. + Parent* parent = nullptr; + uint indexInParent = 0; + + MaybeUint* fixup = nullptr; + + for (auto i KJ_UNUSED: zeroTo(height)) { + Parent& node = eraseHelper(tree[pos].parent, parent, indexInParent, pos, fixup); + + parent = &node; + indexInParent = searchKey.search(node); + pos = node.children[indexInParent]; + + if (indexInParent < kj::size(node.keys) && node.keys[indexInParent] == row) { + // Oh look, the row is a key in this node! We'll need to come back and fix this up later. + // Note that any particular row can only appear as *one* key value anywhere in the tree, so + // we only need one fixup pointer, which is nice. + MaybeUint* newFixup = &node.keys[indexInParent]; + if (fixup == newFixup) { + // The fixup pointer was already set while processing a parent node, and then a merge or + // rotate caused it to be moved, but the fixup pointer was updated... so it's already set + // to point at the slot we wanted it to point to, so nothing to see here. + } else { + KJ_DASSERT(fixup == nullptr); + fixup = newFixup; + } + } + } + + Leaf& leaf = eraseHelper(tree[pos].leaf, parent, indexInParent, pos, fixup); + + uint r = searchKey.search(leaf); + if (leaf.rows[r] == row) { + leaf.erase(r); + + if (fixup != nullptr) { + // There's a key in a parent node that needs fixup. This is only possible if the removed + // node is the last in its leaf. + KJ_DASSERT(leaf.rows[r] == nullptr); + KJ_DASSERT(r > 0); // non-root nodes must be at least half full so this can't be item 0 + KJ_DASSERT(*fixup == row); + *fixup = leaf.rows[r - 1]; + } + } else { + logInconsistency(); + } +} + +template +Node& BTreeImpl::eraseHelper( + Node& node, Parent* parent, uint indexInParent, uint pos, MaybeUint*& fixup) { + if (parent != nullptr && !node.isMostlyFull()) { + // This is not the root, but it's only half-full. Rebalance. + KJ_DASSERT(node.isHalfFull()); + + if (indexInParent > 0) { + // There's a sibling to the left. + uint sibPos = parent->children[indexInParent - 1]; + Node& sib = tree[sibPos]; + if (sib.isMostlyFull()) { + // Left sibling is more than half full. Steal one member. + rotateRight(sib, node, *parent, indexInParent - 1); + return node; + } else { + // Left sibling is half full, too. Merge. + KJ_ASSERT(sib.isHalfFull()); + merge(sib, sibPos, *parent->keys[indexInParent - 1], node); + parent->eraseAfter(indexInParent - 1); + free(pos); + if (fixup == &parent->keys[indexInParent]) --fixup; + + if (parent->keys[0] == nullptr) { + // Oh hah, the parent has no keys left. It must be the root. We can eliminate it. + KJ_DASSERT(parent == &tree->parent); + compilerBarrier(); // don't reorder any writes to parent below here + move(tree[0], 0, sib); + free(sibPos); + --height; + return tree[0]; + } else { + return sib; + } + } + } else if (indexInParent < Parent::NKEYS && parent->keys[indexInParent] != nullptr) { + // There's a sibling to the right. + uint sibPos = parent->children[indexInParent + 1]; + Node& sib = tree[sibPos]; + if (sib.isMostlyFull()) { + // Right sibling is more than half full. Steal one member. + rotateLeft(node, sib, *parent, indexInParent, fixup); + return node; + } else { + // Right sibling is half full, too. Merge. + KJ_ASSERT(sib.isHalfFull()); + merge(node, pos, *parent->keys[indexInParent], sib); + parent->eraseAfter(indexInParent); + free(sibPos); + if (fixup == &parent->keys[indexInParent]) fixup = nullptr; + + if (parent->keys[0] == nullptr) { + // Oh hah, the parent has no keys left. It must be the root. We can eliminate it. + KJ_DASSERT(parent == &tree->parent); + compilerBarrier(); // don't reorder any writes to parent below here + move(tree[0], 0, node); + free(pos); + --height; + return tree[0]; + } else { + return node; + } + } + } else { + KJ_FAIL_ASSERT("inconsistent b-tree"); + } + } + + return node; +} + +void BTreeImpl::renumber(uint oldRow, uint newRow, const SearchKey& searchKey) { + // Renumber the given row from oldRow to newRow. predicate() returns true for oldRow and all + // rows after it. (It will not be called on newRow.) + + uint pos = 0; + + for (auto i KJ_UNUSED: zeroTo(height)) { + auto& node = tree[pos].parent; + uint indexInParent = searchKey.search(node); + pos = node.children[indexInParent]; + if (indexInParent < kj::size(node.keys) && node.keys[indexInParent] == oldRow) { + node.keys[indexInParent] = newRow; + } + KJ_DASSERT(pos != 0); + } + + auto& leaf = tree[pos].leaf; + uint r = searchKey.search(leaf); + if (leaf.rows[r] == oldRow) { + leaf.rows[r] = newRow; + } else { + logInconsistency(); + } +} + +uint BTreeImpl::split(Parent& dst, uint dstPos, Parent& src, uint srcPos) { + constexpr size_t mid = Parent::NKEYS / 2; + uint pivot = *src.keys[mid]; + acopy(dst.keys, src.keys + mid + 1, Parent::NKEYS - mid - 1); + azero(src.keys + mid, Parent::NKEYS - mid); + acopy(dst.children, src.children + mid + 1, Parent::NCHILDREN - mid - 1); + azero(src.children + mid + 1, Parent::NCHILDREN - mid - 1); + return pivot; +} + +uint BTreeImpl::split(Leaf& dst, uint dstPos, Leaf& src, uint srcPos) { + constexpr size_t mid = Leaf::NROWS / 2; + uint pivot = *src.rows[mid - 1]; + acopy(dst.rows, src.rows + mid, Leaf::NROWS - mid); + azero(src.rows + mid, Leaf::NROWS - mid); + + if (src.next == 0) { + endLeaf = dstPos; + } else { + tree[src.next].leaf.prev = dstPos; + } + dst.next = src.next; + dst.prev = srcPos; + src.next = dstPos; + + return pivot; +} + +void BTreeImpl::merge(Parent& dst, uint dstPos, uint pivot, Parent& src) { + // merge() is only legal if both nodes are half-empty. Meanwhile, B-tree invariants + // guarantee that the node can't be more than half-empty, or we would have merged it sooner. + // (The root can be more than half-empty, but it is never merged with anything.) + KJ_DASSERT(src.isHalfFull()); + KJ_DASSERT(dst.isHalfFull()); + + constexpr size_t mid = Parent::NKEYS/2; + dst.keys[mid] = pivot; + acopy(dst.keys + mid + 1, src.keys, mid); + acopy(dst.children + mid + 1, src.children, mid + 1); +} + +void BTreeImpl::merge(Leaf& dst, uint dstPos, uint pivot, Leaf& src) { + // merge() is only legal if both nodes are half-empty. Meanwhile, B-tree invariants + // guarantee that the node can't be more than half-empty, or we would have merged it sooner. + // (The root can be more than half-empty, but it is never merged with anything.) + KJ_DASSERT(src.isHalfFull()); + KJ_DASSERT(dst.isHalfFull()); + + constexpr size_t mid = Leaf::NROWS/2; + KJ_DASSERT(dst.rows[mid-1] == pivot); + acopy(dst.rows + mid, src.rows, mid); + + dst.next = src.next; + if (dst.next == 0) { + endLeaf = dstPos; + } else { + tree[dst.next].leaf.prev = dstPos; + } +} + +void BTreeImpl::move(Parent& dst, uint dstPos, Parent& src) { + dst = src; +} + +void BTreeImpl::move(Leaf& dst, uint dstPos, Leaf& src) { + dst = src; + if (src.next == 0) { + endLeaf = dstPos; + } else { + tree[src.next].leaf.prev = dstPos; + } + if (src.prev == 0) { + beginLeaf = dstPos; + } else { + tree[src.prev].leaf.next = dstPos; + } +} + +void BTreeImpl::rotateLeft( + Parent& left, Parent& right, Parent& parent, uint indexInParent, MaybeUint*& fixup) { + // Steal one item from the right node and move it to the left node. + + // Like merge(), this is only called on an exactly-half-empty node. + KJ_DASSERT(left.isHalfFull()); + KJ_DASSERT(right.isMostlyFull()); + + constexpr size_t mid = Parent::NKEYS/2; + left.keys[mid] = parent.keys[indexInParent]; + if (fixup == &parent.keys[indexInParent]) fixup = &left.keys[mid]; + parent.keys[indexInParent] = right.keys[0]; + left.children[mid + 1] = right.children[0]; + amove(right.keys, right.keys + 1, Parent::NKEYS - 1); + right.keys[Parent::NKEYS - 1] = nullptr; + amove(right.children, right.children + 1, Parent::NCHILDREN - 1); + right.children[Parent::NCHILDREN - 1] = 0; +} + +void BTreeImpl::rotateLeft( + Leaf& left, Leaf& right, Parent& parent, uint indexInParent, MaybeUint*& fixup) { + // Steal one item from the right node and move it to the left node. + + // Like merge(), this is only called on an exactly-half-empty node. + KJ_DASSERT(left.isHalfFull()); + KJ_DASSERT(right.isMostlyFull()); + + constexpr size_t mid = Leaf::NROWS/2; + parent.keys[indexInParent] = left.rows[mid] = right.rows[0]; + if (fixup == &parent.keys[indexInParent]) fixup = nullptr; + amove(right.rows, right.rows + 1, Leaf::NROWS - 1); + right.rows[Leaf::NROWS - 1] = nullptr; +} + +void BTreeImpl::rotateRight(Parent& left, Parent& right, Parent& parent, uint indexInParent) { + // Steal one item from the left node and move it to the right node. + + // Like merge(), this is only called on an exactly-half-empty node. + KJ_DASSERT(right.isHalfFull()); + KJ_DASSERT(left.isMostlyFull()); + + constexpr size_t mid = Parent::NKEYS/2; + amove(right.keys + 1, right.keys, mid); + amove(right.children + 1, right.children, mid + 1); + + uint back = left.keyCount() - 1; + + right.keys[0] = parent.keys[indexInParent]; + parent.keys[indexInParent] = left.keys[back]; + right.children[0] = left.children[back + 1]; + left.keys[back] = nullptr; + left.children[back + 1] = 0; +} + +void BTreeImpl::rotateRight(Leaf& left, Leaf& right, Parent& parent, uint indexInParent) { + // Steal one item from the left node and move it to the right node. + + // Like mergeFrom(), this is only called on an exactly-half-empty node. + KJ_DASSERT(right.isHalfFull()); + KJ_DASSERT(left.isMostlyFull()); + + constexpr size_t mid = Leaf::NROWS/2; + amove(right.rows + 1, right.rows, mid); + + uint back = left.size() - 1; + + right.rows[0] = left.rows[back]; + parent.keys[indexInParent] = left.rows[back - 1]; + left.rows[back] = nullptr; +} + +void BTreeImpl::Parent::initRoot(uint key, uint leftChild, uint rightChild) { + // HACK: This is typically called on the root node immediately after copying its contents away, + // but the pointer used to copy it away may be a different pointer pointing to a different + // union member which the compiler may not recgonize as aliasing with this object. Just to + // be extra-safe, insert a compiler barrier. + compilerBarrier(); + + keys[0] = key; + children[0] = leftChild; + children[1] = rightChild; + azero(keys + 1, Parent::NKEYS - 1); + azero(children + 2, Parent::NCHILDREN - 2); +} + +void BTreeImpl::Parent::insertAfter(uint i, uint splitKey, uint child) { + KJ_IREQUIRE(children[Parent::NCHILDREN - 1] == 0); // check not full + + amove(keys + i + 1, keys + i, Parent::NKEYS - (i + 1)); + keys[i] = splitKey; + + amove(children + i + 2, children + i + 1, Parent::NCHILDREN - (i + 2)); + children[i + 1] = child; +} + +void BTreeImpl::Parent::eraseAfter(uint i) { + amove(keys + i, keys + i + 1, Parent::NKEYS - (i + 1)); + keys[Parent::NKEYS - 1] = nullptr; + amove(children + i + 1, children + i + 2, Parent::NCHILDREN - (i + 2)); + children[Parent::NCHILDREN - 1] = 0; +} + +} // namespace _ + +// ======================================================================================= +// Insertion order + +const InsertionOrderIndex::Link InsertionOrderIndex::EMPTY_LINK = { 0, 0 }; + +InsertionOrderIndex::InsertionOrderIndex(): capacity(0), links(const_cast(&EMPTY_LINK)) {} +InsertionOrderIndex::InsertionOrderIndex(InsertionOrderIndex&& other) + : capacity(other.capacity), links(other.links) { + other.capacity = 0; + other.links = const_cast(&EMPTY_LINK); +} +InsertionOrderIndex& InsertionOrderIndex::operator=(InsertionOrderIndex&& other) { + KJ_DASSERT(&other != this); + capacity = other.capacity; + links = other.links; + other.capacity = 0; + other.links = const_cast(&EMPTY_LINK); + return *this; +} +InsertionOrderIndex::~InsertionOrderIndex() noexcept(false) { + if (links != &EMPTY_LINK) delete[] links; +} + +void InsertionOrderIndex::reserve(size_t size) { + KJ_ASSERT(size < (1u << 31), "Table too big for InsertionOrderIndex"); + + if (size > capacity) { + // Need to grow. + // Note that `size` and `capacity` do not include the special link[0]. + + // Round up to the next power of 2. + size_t allocation = 1u << (_::lg(size) + 1); + KJ_DASSERT(allocation > size); + KJ_DASSERT(allocation <= size * 2); + + // Round first allocation up to 8. + allocation = kj::max(allocation, 8); + + Link* newLinks = new Link[allocation]; +#ifdef KJ_DEBUG + // To catch bugs, fill unused links with 0xff. + memset(newLinks, 0xff, allocation * sizeof(Link)); +#endif + _::acopy(newLinks, links, capacity + 1); + if (links != &EMPTY_LINK) delete[] links; + links = newLinks; + capacity = allocation - 1; + } +} + +void InsertionOrderIndex::clear() { + links[0] = Link { 0, 0 }; + +#ifdef KJ_DEBUG + // To catch bugs, fill unused links with 0xff. + memset(links + 1, 0xff, capacity * sizeof(Link)); +#endif +} + +kj::Maybe InsertionOrderIndex::insertImpl(size_t pos) { + if (pos >= capacity) { + reserve(pos + 1); + } + + links[pos + 1].prev = links[0].prev; + links[pos + 1].next = 0; + links[links[0].prev].next = pos + 1; + links[0].prev = pos + 1; + + return nullptr; +} + +void InsertionOrderIndex::eraseImpl(size_t pos) { + Link& link = links[pos + 1]; + links[link.next].prev = link.prev; + links[link.prev].next = link.next; + +#ifdef KJ_DEBUG + memset(&link, 0xff, sizeof(Link)); +#endif +} + +void InsertionOrderIndex::moveImpl(size_t oldPos, size_t newPos) { + Link& link = links[oldPos + 1]; + Link& newLink = links[newPos + 1]; + + newLink = link; + + KJ_DASSERT(links[link.next].prev == oldPos + 1); + KJ_DASSERT(links[link.prev].next == oldPos + 1); + links[link.next].prev = newPos + 1; + links[link.prev].next = newPos + 1; + +#ifdef KJ_DEBUG + memset(&link, 0xff, sizeof(Link)); +#endif +} + +} // namespace kj diff --git a/vendor/capnproto/src/kj/table.h b/vendor/capnproto/src/kj/table.h new file mode 100644 index 0000000..90f8982 --- /dev/null +++ b/vendor/capnproto/src/kj/table.h @@ -0,0 +1,1640 @@ +// Copyright (c) 2018 Kenton Varda 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. + +#pragma once + +#include "common.h" +#include "tuple.h" +#include "vector.h" +#include "function.h" + + +#if KJ_DEBUG_TABLE_IMPL +#include "debug.h" +#define KJ_TABLE_IREQUIRE KJ_REQUIRE +#define KJ_TABLE_IASSERT KJ_ASSERT +#else +#define KJ_TABLE_IREQUIRE KJ_IREQUIRE +#define KJ_TABLE_IASSERT KJ_IASSERT +#endif + +KJ_BEGIN_HEADER + +namespace kj { + +class String; + +namespace _ { // private + +template +class TableMapping; +template +using TableIterable = MappedIterable>; +template +using TableIterator = MappedIterator>; + +} // namespace _ (private) + +template +class Table { + // A table with one or more indexes. This is the KJ alternative to map, set, unordered_map, and + // unordered_set. + // + // Unlike a traditional map, which explicitly stores key/value pairs, a Table simply stores + // "rows" of arbitrary type, and then lets the application specify how these should be indexed. + // Rows could be indexed on a specific struct field, or they could be indexed based on a computed + // property. An index could be hash-based or tree-based. Multiple indexes are supported, making + // it easy to construct a "bimap". + // + // The table has deterministic iteration order based on the sequence of insertions and deletions. + // In the case of only insertions, the iteration order is the order of insertion. If deletions + // occur, then the current last row is moved to occupy the deleted slot. This determinism is + // intended to be reliable for the purpose of testing, etc. + // + // Each index is a class that looks like: + // + // class Index { + // public: + // void reserve(size_t size); + // // Called when Table::reserve() is called. + // + // SearchParam& keyForRow(const Row& row) const; + // // Given a row, return a value appropriate to pass as SearchParams to the other functions. + // + // // In all function calls below, `SearchPrams` refers to whatever parameters the index + // // supports for looking up a row in the table. + // + // template + // kj::Maybe insert(kj::ArrayPtr table, size_t pos, SearchParams&&...); + // // Called to indicate that we're about to insert a new row which will match the given + // // search parameters, and will be located at the given position. If this index disallows + // // duplicates and some other matching row already exists, then insert() returns the index + // // of that row without modifying the index. If the row does not exist, then insert() + // // updates the index to note that the new row is located at `pos`. Note that `table[pos]` + // // may not be valid yet at the time of this call; the index must go on the search params + // // alone. + // // + // // Insert may throw an exception, in which case the table will roll back insertion. + // + // template + // void erase(kj::ArrayPtr table, size_t pos, SearchParams&&...); + // // Called to indicate that the index must remove references to row number `pos`. The + // // index must not attempt to access table[pos] directly -- in fact, `pos` may be equal to + // // `table.size()`, i.e., may be out-of-bounds (this happens when rolling back a failed + // // insertion). Instead, the index can use the search params to search for the row -- they + // // will either be the same as the params passed to insert(), or will be a single value of + // // type `Row&`. + // // + // // erase() called immediately after a successful insert() must not throw an exception, as + // // it may be called during unwind. + // + // template + // void move(kj::ArrayPtr table, size_t oldPos, size_t newPos, SearchParams&&...); + // // Called when a row is about to be moved from `oldPos` to `newPos` in the table. The + // // index should update it to the new location. Neither `table[oldPos]` nor `table[newPos]` + // // is valid during the call -- use the search params to find the row. Before this call + // // `oldPos` is indexed and `newPos` is not -- after the call, the opposite is true. + // // + // // This should never throw; if it does the table may be corrupted. + // + // class Iterator; // Behaves like a C++ iterator over size_t values. + // class Iterable; // Has begin() and end() methods returning iterators. + // + // template + // Maybe find(kj::ArrayPtr table, SearchParams&&...) const; + // // Optional. Implements Table::find(...). + // + // template + // Iterator seek(kj::ArrayPtr table, SearchParams&&...) const; + // // Optional. Implements Table::seek() and Table::range(...). + // + // Iterator begin() const; + // Iterator end() const; + // // Optional. Implements Table::ordered(). + // }; + +public: + Table(); + Table(Indexes&&... indexes); + + void reserve(size_t size); + // Pre-allocates space for a table of the given size. Normally a Table grows by re-allocating + // its backing array whenever more space is needed. Reserving in advance avoids redundantly + // re-allocating as the table grows. + + size_t size() const; + size_t capacity() const; + + void clear(); + + Row* begin(); + Row* end(); + const Row* begin() const; + const Row* end() const; + + Row& insert(Row&& row); + Row& insert(const Row& row); + // Inserts a new row. Throws an exception if this would violate the uniqueness constraints of any + // of the indexes. + + template + void insertAll(Collection&& collection); + template + void insertAll(Collection& collection); + // Given an iterable collection of Rows, inserts all of them into this table. If the input is + // an rvalue, the rows will be moved rather than copied. + // + // If an insertion throws (e.g. because it violates a uniqueness constraint of some index), + // subsequent insertions do not occur, but previous insertions remain inserted. + + template + Row& upsert(Row&& row, UpdateFunc&& update); + template + Row& upsert(const Row& row, UpdateFunc&& update); + // Tries to insert a new row. However, if a duplicate already exists (according to some index), + // then update(Row& existingRow, Row&& newRow) is called to modify the existing row. + + template + kj::Maybe find(Params&&... params); + template + kj::Maybe find(Params&&... params) const; + // Using the given index, search for a matching row. What parameters are accepted depends on the + // index. Not all indexes support this method -- "multimap" indexes may support only range(). + + template + Row& findOrCreate(Params&&... params, Func&& createFunc); + // Like find(), but if the row doesn't exist, call a function to create it. createFunc() must + // return `Row` or something that implicitly converts to `Row`. + // + // NOTE: C++ doesn't actually properly support inferring types of a parameter pack at the + // beginning of an argument list, but we define a hack to support it below. Don't worry about + // it. + + template + auto range(BeginKey&& begin, EndKey&& end); + template + auto range(BeginKey&& begin, EndKey&& end) const; + // Using the given index, look up a range of values, returning an iterable. What parameters are + // accepted depends on the index. Not all indexes support this method (in particular, unordered + // indexes normally don't). + + template + _::TableIterable ordered(); + template + _::TableIterable ordered() const; + // Returns an iterable over the whole table ordered using the given index. Not all indexes + // support this method. + + template + auto seek(Params&&... params); + template + auto seek(Params&&... params) const; + // Takes same parameters as find(), but returns an iterator at the position where the search + // key should go. That is, this returns an iterator that points to the matching entry or, if + // there is no matching entry, points at the next entry after the key, in order. Or, if there + // is no such entry, the returned iterator is the same as ordered().end(). + // + // seek() is only supported by indexes that support ordered(). It returns the same kind of + // iterator that ordered() uses. + + template + bool eraseMatch(Params&&... params); + // Erase the row that would be matched by `find(params)`. Returns true if there was a + // match. + + template + size_t eraseRange(BeginKey&& begin, EndKey&& end); + // Erase the row that would be matched by `range(params)`. Returns the number of + // elements erased. + + void erase(Row& row); + // Erase the given row. + // + // WARNING: This invalidates all iterators, so you can't iterate over rows and erase them this + // way. Use `eraseAll()` for that. + + Row release(Row& row); + // Remove the given row from the table and return it in one operation. + // + // WARNING: This invalidates all iterators, so you can't iterate over rows and release them this + // way. + + template ()(instance()))> + size_t eraseAll(Predicate&& predicate); + // Erase all rows for which predicate(row) returns true. This scans over the entire table. + + template ().begin()), bool = true> + size_t eraseAll(Collection&& collection); + // Erase all rows in the given iterable collection of rows. This carefully marks rows for + // deletion in a first pass then deletes them in a second. + + template + kj::Maybe find(Params&&... params); + template + kj::Maybe find(Params&&... params) const; + template + Row& findOrCreate(Params&&... params, Func&& createFunc); + template + auto range(BeginKey&& begin, EndKey&& end); + template + auto range(BeginKey&& begin, EndKey&& end) const; + template + _::TableIterable>&> ordered(); + template + _::TableIterable>&> ordered() const; + template + auto seek(Params&&... params); + template + auto seek(Params&&... params) const; + template + bool eraseMatch(Params&&... params); + template + size_t eraseRange(BeginKey&& begin, EndKey&& end); + // Methods which take an index type as a template parameter can also take an index number. This + // is useful particularly when you have multiple indexes of the same type but different runtime + // properties. Additionally, you can omit the template parameter altogether to use the first + // index. + + template + void verify(); + // Checks the integrity of indexes, throwing an exception if there are any problems. This is + // intended to be called within the unit test for an index. + + template + Row& findOrCreate(First&& first, Rest&&... rest); + template + Row& findOrCreate(First&& first, Rest&&... rest); + // HACK: A parameter pack can only be inferred if it lives at the end of the argument list, so + // the findOrCreate() definitions from earlier won't actually work. These ones will, but we + // have to do some annoying things inside to regroup the arguments. + +private: + Vector rows; + Tuple indexes; + + template = sizeof...(Indexes))> + class Impl; + template + class FindOrCreateImpl; + + template + struct FindOrCreateHack; + + void eraseImpl(size_t pos); + template + size_t eraseAllImpl(Collection&& collection); +}; + +template +class HashIndex; +// A Table index based on a hash table. +// +// This implementation: +// * Is based on linear probing, not chaining. It is important to use a high-quality hash function. +// Use the KJ hashing library if possible. +// * Is limited to tables of 2^30 rows or less, mainly to allow for tighter packing with 32-bit +// integers instead of 64-bit. +// * Caches hash codes so that each table row need only be hashed once, and never checks equality +// unless hash codes have already been determined to be equal. +// +// The `Callbacks` type defines how to compute hash codes and equality. It should be defined like: +// +// class Callbacks { +// public: +// // In this interface, `SearchParams...` means whatever parameters you want to support in +// // a call to table.find(...). By overloading the calls to support various inputs, you can +// // affect what table.find(...) accepts. +// +// SearchParam& keyForRow(const Row& row); +// // Given a row of the table, return the SearchParams that might be passed to the other +// // methods to match this row. +// +// bool matches(const Row&, SearchParams&&...) const; +// // Returns true if the row on the left matches the search params on the right. +// +// uint hashCode(SearchParams&&...) const; +// // Computes the hash code of the given search params. Matching rows (as determined by +// // matches()) must have the same hash code. Non-matching rows should have different hash +// // codes, to the maximum extent possible. Non-matching rows with the same hash code hurt +// // performance. +// }; +// +// If your `Callbacks` type has dynamic state, you may pass its constructor parameters as the +// constructor parameters to `HashIndex`. + +template +class TreeIndex; +// A Table index based on a B-tree. +// +// This allows sorted iteration over rows. +// +// The `Callbacks` type defines how to compare rows. It should be defined like: +// +// class Callbacks { +// public: +// // In this interface, `SearchParams...` means whatever parameters you want to support in +// // a call to table.find(...). By overloading the calls to support various inputs, you can +// // affect what table.find(...) accepts. +// +// SearchParam& keyForRow(const Row& row); +// // Given a row of the table, return the SearchParams that might be passed to the other +// // methods to match this row. +// +// bool isBefore(const Row&, SearchParams&&...) const; +// // Returns true if the row on the left comes before the search params on the right. +// +// bool matches(const Row&, SearchParams&&...) const; +// // Returns true if the row "matches" the search params. +// }; + +// ======================================================================================= +// inline implementation details + +namespace _ { // private + +KJ_NORETURN(void throwDuplicateTableRow()); + +template ().size())> +inline void tryReserveSize(Dst& dst, Src&& src) { dst.reserve(dst.size() + src.size()); } +template +inline void tryReserveSize(Params&&...) {} +// If `src` has a `.size()` method, call dst.reserve(dst.size() + src.size()). +// Otherwise, do nothing. + +template +class TableMapping { +public: + TableMapping(Row* table): table(table) {} + Row& map(size_t i) const { return table[i]; } + +private: + Row* table; +}; + +template +class TableUnmapping { +public: + TableUnmapping(Row* table): table(table) {} + size_t map(Row& row) const { return &row - table; } + size_t map(Row* row) const { return row - table; } + +private: + Row* table; +}; + +template +class IterRange { +public: + inline IterRange(Iterator b, Iterator e): b(b), e(e) {} + + inline Iterator begin() const { return b; } + inline Iterator end() const { return e; } +private: + Iterator b; + Iterator e; +}; + +template +inline IterRange> iterRange(Iterator b, Iterator e) { + return { b, e }; +} + +} // namespace _ (private) + +template +template +class Table::Impl { +public: + static void reserve(Table& table, size_t size) { + get(table.indexes).reserve(size); + Impl::reserve(table, size); + } + + static void clear(Table& table) { + get(table.indexes).clear(); + Impl::clear(table); + } + + static kj::Maybe insert(Table& table, size_t pos, Row& row, uint skip) { + if (skip == index) { + return Impl::insert(table, pos, row, skip); + } + auto& indexObj = get(table.indexes); + KJ_IF_MAYBE(existing, indexObj.insert(table.rows.asPtr(), pos, indexObj.keyForRow(row))) { + return *existing; + } + + bool success = false; + KJ_DEFER(if (!success) { + indexObj.erase(table.rows.asPtr(), pos, indexObj.keyForRow(row)); + }); + auto result = Impl::insert(table, pos, row, skip); + success = result == nullptr; + return result; + } + + static void erase(Table& table, size_t pos, Row& row) { + auto& indexObj = get(table.indexes); + indexObj.erase(table.rows.asPtr(), pos, indexObj.keyForRow(row)); + Impl::erase(table, pos, row); + } + + static void move(Table& table, size_t oldPos, size_t newPos, Row& row) { + auto& indexObj = get(table.indexes); + indexObj.move(table.rows.asPtr(), oldPos, newPos, indexObj.keyForRow(row)); + Impl::move(table, oldPos, newPos, row); + } +}; + +template +template +class Table::Impl { +public: + static void reserve(Table& table, size_t size) {} + static void clear(Table& table) {} + static kj::Maybe insert(Table& table, size_t pos, Row& row, uint skip) { + return nullptr; + } + static void erase(Table& table, size_t pos, Row& row) {} + static void move(Table& table, size_t oldPos, size_t newPos, Row& row) {} +}; + +template +Table::Table() {} + +template +Table::Table(Indexes&&... indexes) + : indexes(tuple(kj::fwd(indexes)...)) {} + +template +void Table::reserve(size_t size) { + rows.reserve(size); + Impl<>::reserve(*this, size); +} + +template +size_t Table::size() const { + return rows.size(); +} +template +void Table::clear() { + Impl<>::clear(*this); + rows.clear(); +} +template +size_t Table::capacity() const { + return rows.capacity(); +} + +template +Row* Table::begin() { + return rows.begin(); +} +template +Row* Table::end() { + return rows.end(); +} +template +const Row* Table::begin() const { + return rows.begin(); +} +template +const Row* Table::end() const { + return rows.end(); +} + +template +Row& Table::insert(Row&& row) { + KJ_IF_MAYBE(existing, Impl<>::insert(*this, rows.size(), row, kj::maxValue)) { + _::throwDuplicateTableRow(); + } else { + return rows.add(kj::mv(row)); + } +} +template +Row& Table::insert(const Row& row) { + return insert(kj::cp(row)); +} + +template +template +void Table::insertAll(Collection&& collection) { + _::tryReserveSize(*this, collection); + for (auto& row: collection) { + insert(kj::mv(row)); + } +} + +template +template +void Table::insertAll(Collection& collection) { + _::tryReserveSize(*this, collection); + for (auto& row: collection) { + insert(row); + } +} + +template +template +Row& Table::upsert(Row&& row, UpdateFunc&& update) { + KJ_IF_MAYBE(existing, Impl<>::insert(*this, rows.size(), row, kj::maxValue)) { + update(rows[*existing], kj::mv(row)); + return rows[*existing]; + } else { + return rows.add(kj::mv(row)); + } +} +template +template +Row& Table::upsert(const Row& row, UpdateFunc&& update) { + return upsert(kj::cp(row), kj::fwd(update)); +} + +template +template +kj::Maybe Table::find(Params&&... params) { + return find>()>(kj::fwd(params)...); +} +template +template +kj::Maybe Table::find(Params&&... params) { + KJ_IF_MAYBE(pos, get(indexes).find(rows.asPtr(), kj::fwd(params)...)) { + return rows[*pos]; + } else { + return nullptr; + } +} +template +template +kj::Maybe Table::find(Params&&... params) const { + return find>()>(kj::fwd(params)...); +} +template +template +kj::Maybe Table::find(Params&&... params) const { + KJ_IF_MAYBE(pos, get(indexes).find(rows.asPtr(), kj::fwd(params)...)) { + return rows[*pos]; + } else { + return nullptr; + } +} + +template +template +class Table::FindOrCreateImpl { +public: + template + static Row& apply(Table& table, Params&&... params, Func&& createFunc) { + auto pos = table.rows.size(); + KJ_IF_MAYBE(existing, get(table.indexes).insert(table.rows.asPtr(), pos, params...)) { + return table.rows[*existing]; + } else { + bool success = false; + KJ_DEFER({ + if (!success) { + get(table.indexes).erase(table.rows.asPtr(), pos, params...); + } + }); + auto& newRow = table.rows.add(createFunc()); + KJ_DEFER({ + if (!success) { + table.rows.removeLast(); + } + }); + if (Table::template Impl<>::insert(table, pos, newRow, index) == nullptr) { + success = true; + } else { + _::throwDuplicateTableRow(); + } + return newRow; + } + } +}; + +template +template +struct Table::FindOrCreateHack<_::Tuple, U, V, W...> + : public FindOrCreateHack<_::Tuple, V, W...> {}; +template +template +struct Table::FindOrCreateHack<_::Tuple, U> + : public FindOrCreateImpl {}; +// This awful hack works around C++'s lack of support for parameter packs anywhere other than at +// the end of an argument list. We accumulate all of the types except for the last one into a +// Tuple, then forward to FindOrCreateImpl with the last parameter as the Func. + +template +template +Row& Table::findOrCreate(First&& first, Rest&&... rest) { + return findOrCreate>()>( + kj::fwd(first), kj::fwd(rest)...); +} +template +template +Row& Table::findOrCreate(First&& first, Rest&&... rest) { + return FindOrCreateHack<_::Tuple<>, First, Rest...>::template apply( + *this, kj::fwd(first), kj::fwd(rest)...); +} + +template +template +auto Table::range(BeginKey&& begin, EndKey&& end) { + return range>()>( + kj::fwd(begin), kj::fwd(end)); +} +template +template +auto Table::range(BeginKey&& begin, EndKey&& end) { + auto inner = _::iterRange(get(indexes).seek(rows.asPtr(), kj::fwd(begin)), + get(indexes).seek(rows.asPtr(), kj::fwd(end))); + return _::TableIterable(kj::mv(inner), rows.begin()); +} +template +template +auto Table::range(BeginKey&& begin, EndKey&& end) const { + return range>()>( + kj::fwd(begin), kj::fwd(end)); +} +template +template +auto Table::range(BeginKey&& begin, EndKey&& end) const { + auto inner = _::iterRange(get(indexes).seek(rows.asPtr(), kj::fwd(begin)), + get(indexes).seek(rows.asPtr(), kj::fwd(end))); + return _::TableIterable(kj::mv(inner), rows.begin()); +} + +template +template +_::TableIterable Table::ordered() { + return ordered>()>(); +} +template +template +_::TableIterable>&> Table::ordered() { + return { get(indexes), rows.begin() }; +} +template +template +_::TableIterable Table::ordered() const { + return ordered>()>(); +} +template +template +_::TableIterable>&> +Table::ordered() const { + return { get(indexes), rows.begin() }; +} + +template +template +auto Table::seek(Params&&... params) { + return seek>()>(kj::fwd(params)...); +} +template +template +auto Table::seek(Params&&... params) { + auto inner = get(indexes).seek(rows.asPtr(), kj::fwd(params)...); + return _::TableIterator(kj::mv(inner), rows.begin()); +} +template +template +auto Table::seek(Params&&... params) const { + return seek>()>(kj::fwd(params)...); +} +template +template +auto Table::seek(Params&&... params) const { + auto inner = get(indexes).seek(rows.asPtr(), kj::fwd(params)...); + return _::TableIterator(kj::mv(inner), rows.begin()); +} + +template +template +bool Table::eraseMatch(Params&&... params) { + return eraseMatch>()>(kj::fwd(params)...); +} +template +template +bool Table::eraseMatch(Params&&... params) { + KJ_IF_MAYBE(pos, get(indexes).find(rows.asPtr(), kj::fwd(params)...)) { + eraseImpl(*pos); + return true; + } else { + return false; + } +} + +template +template +size_t Table::eraseRange(BeginKey&& begin, EndKey&& end) { + return eraseRange>()>( + kj::fwd(begin), kj::fwd(end)); +} +template +template +size_t Table::eraseRange(BeginKey&& begin, EndKey&& end) { + auto inner = _::iterRange(get(indexes).seek(rows.asPtr(), kj::fwd(begin)), + get(indexes).seek(rows.asPtr(), kj::fwd(end))); + return eraseAllImpl(inner); +} + +template +template +void Table::verify() { + get(indexes).verify(rows.asPtr()); +} + +template +void Table::erase(Row& row) { + KJ_TABLE_IREQUIRE(&row >= rows.begin() && &row < rows.end(), "row is not a member of this table"); + eraseImpl(&row - rows.begin()); +} +template +void Table::eraseImpl(size_t pos) { + Impl<>::erase(*this, pos, rows[pos]); + size_t back = rows.size() - 1; + if (pos != back) { + Impl<>::move(*this, back, pos, rows[back]); + rows[pos] = kj::mv(rows[back]); + } + rows.removeLast(); +} + +template +Row Table::release(Row& row) { + KJ_TABLE_IREQUIRE(&row >= rows.begin() && &row < rows.end(), "row is not a member of this table"); + size_t pos = &row - rows.begin(); + Impl<>::erase(*this, pos, row); + Row result = kj::mv(row); + size_t back = rows.size() - 1; + if (pos != back) { + Impl<>::move(*this, back, pos, rows[back]); + row = kj::mv(rows[back]); + } + rows.removeLast(); + return result; +} + +template +template +size_t Table::eraseAll(Predicate&& predicate) { + size_t count = 0; + for (size_t i = 0; i < rows.size();) { + if (predicate(rows[i])) { + eraseImpl(i); + ++count; + // eraseImpl() replaces the erased row with the last row, so don't increment i here; repeat + // with the same i. + } else { + ++i; + } + } + return count; +} + +template +template +size_t Table::eraseAll(Collection&& collection) { + return eraseAllImpl(MappedIterable>( + collection, rows.begin())); +} + +template +template +size_t Table::eraseAllImpl(Collection&& collection) { + // We need to transform the collection of row numbers into a sequence of erasures, accounting + // for the fact that each erasure re-positions the last row into its slot. + Vector erased; + _::tryReserveSize(erased, collection); + for (size_t pos: collection) { + while (pos >= rows.size() - erased.size()) { + // Oops, the next item to be erased is already scheduled to be moved to a different location + // due to a previous erasure. Figure out where it will be at this point. + size_t erasureNumber = rows.size() - pos - 1; + pos = erased[erasureNumber]; + } + erased.add(pos); + } + + // Now we can execute the sequence of erasures. + for (size_t pos: erased) { + eraseImpl(pos); + } + + return erased.size(); +} + +// ----------------------------------------------------------------------------- +// Hash table index + +namespace _ { // private + +void logHashTableInconsistency(); + +struct HashBucket { + uint hash; + uint value; + + HashBucket() = default; + HashBucket(uint hash, uint pos) + : hash(hash), value(pos + 2) {} + + inline bool isEmpty() const { return value == 0; } + inline bool isErased() const { return value == 1; } + inline bool isOccupied() const { return value >= 2; } + template + inline Row& getRow(ArrayPtr table) const { return table[getPos()]; } + template + inline const Row& getRow(ArrayPtr table) const { return table[getPos()]; } + inline bool isPos(uint pos) const { return pos + 2 == value; } + inline uint getPos() const { + KJ_TABLE_IASSERT(value >= 2); + return value - 2; + } + inline void setEmpty() { value = 0; } + inline void setErased() { value = 1; } + inline void setPos(uint pos) { value = pos + 2; } +}; + +inline size_t probeHash(const kj::Array& buckets, size_t i) { + // TODO(perf): Is linear probing OK or should we do something fancier? + if (++i == buckets.size()) { + return 0; + } else { + return i; + } +} + +kj::Array rehash(kj::ArrayPtr oldBuckets, size_t targetSize); + +uint chooseBucket(uint hash, uint count); + +} // namespace _ (private) + +template +class HashIndex { +public: + HashIndex() = default; + template + HashIndex(Params&&... params): cb(kj::fwd(params)...) {} + + size_t capacity() { + // This method is for testing. + return buckets.size(); + } + + void reserve(size_t size) { + if (buckets.size() < size * 2) { + rehash(size); + } + } + + void clear() { + erasedCount = 0; + if (buckets.size() > 0) memset(buckets.begin(), 0, buckets.asBytes().size()); + } + + template + decltype(auto) keyForRow(Row&& row) const { + return cb.keyForRow(kj::fwd(row)); + } + + template + kj::Maybe insert(kj::ArrayPtr table, size_t pos, Params&&... params) { + if (buckets.size() * 2 < (table.size() + 1 + erasedCount) * 3) { + // Load factor is more than 2/3, let's rehash so that it's 1/3, i.e. double the buckets. + // Note that rehashing also cleans up erased entries, so we may not actually be doubling if + // there are a lot of erasures. Nevertheless, this gives us amortized constant time -- it + // would take at least O(table.size()) more insertions (whether or not erasures occur) + // before another rehash is needed. + rehash((table.size() + 1) * 3); + } + + uint hashCode = cb.hashCode(params...); + Maybe<_::HashBucket&> erasedSlot; + for (uint i = _::chooseBucket(hashCode, buckets.size());; i = _::probeHash(buckets, i)) { + auto& bucket = buckets[i]; + if (bucket.isEmpty()) { + // no duplicates found + KJ_IF_MAYBE(s, erasedSlot) { + --erasedCount; + *s = { hashCode, uint(pos) }; + } else { + bucket = { hashCode, uint(pos) }; + } + return nullptr; + } else if (bucket.isErased()) { + // We can fill in the erased slot. However, we have to keep searching to make sure there + // are no duplicates before we do that. + if (erasedSlot == nullptr) { + erasedSlot = bucket; + } + } else if (bucket.hash == hashCode && + cb.matches(bucket.getRow(table), params...)) { + // duplicate row + return size_t(bucket.getPos()); + } + } + } + + template + void erase(kj::ArrayPtr table, size_t pos, Params&&... params) { + uint hashCode = cb.hashCode(params...); + for (uint i = _::chooseBucket(hashCode, buckets.size());; i = _::probeHash(buckets, i)) { + auto& bucket = buckets[i]; + if (bucket.isPos(pos)) { + // found it + ++erasedCount; + bucket.setErased(); + return; + } else if (bucket.isEmpty()) { + // can't find the bucket, something is very wrong + _::logHashTableInconsistency(); + return; + } + } + } + + template + void move(kj::ArrayPtr table, size_t oldPos, size_t newPos, Params&&... params) { + uint hashCode = cb.hashCode(params...); + for (uint i = _::chooseBucket(hashCode, buckets.size());; i = _::probeHash(buckets, i)) { + auto& bucket = buckets[i]; + if (bucket.isPos(oldPos)) { + // found it + bucket.setPos(newPos); + return; + } else if (bucket.isEmpty()) { + // can't find the bucket, something is very wrong + _::logHashTableInconsistency(); + return; + } + } + } + + template + Maybe find(kj::ArrayPtr table, Params&&... params) const { + if (buckets.size() == 0) return nullptr; + + uint hashCode = cb.hashCode(params...); + for (uint i = _::chooseBucket(hashCode, buckets.size());; i = _::probeHash(buckets, i)) { + auto& bucket = buckets[i]; + if (bucket.isEmpty()) { + // not found. + return nullptr; + } else if (bucket.isErased()) { + // skip, keep searching + } else if (bucket.hash == hashCode && + cb.matches(bucket.getRow(table), params...)) { + // found + return size_t(bucket.getPos()); + } + } + } + + // No begin() nor end() because hash tables are not usefully ordered. + +private: + Callbacks cb; + size_t erasedCount = 0; + Array<_::HashBucket> buckets; + + void rehash(size_t targetSize) { + buckets = _::rehash(buckets, targetSize); + erasedCount = 0; + } +}; + +// ----------------------------------------------------------------------------- +// BTree index + +namespace _ { // private + +KJ_ALWAYS_INLINE(void compilerBarrier()); +void compilerBarrier() { + // Make sure that reads occurring before this call cannot be re-ordered to happen after + // writes that occur after this call. We need this in a couple places below to prevent C++ + // strict aliasing rules from breaking things. + __asm__ __volatile__("": : :"memory"); +} + +template +inline void acopy(T* to, T* from, size_t size) { memcpy(to, from, size * sizeof(T)); } +template +inline void amove(T* to, T* from, size_t size) { memmove(to, from, size * sizeof(T)); } +template +inline void azero(T* ptr, size_t size) { memset(ptr, 0, size * sizeof(T)); } +// memcpy/memmove/memset variants that count size in elements, not bytes. +// +// TODO(cleanup): These are generally useful, put them somewhere. + +class BTreeImpl { +public: + class Iterator; + class MaybeUint; + struct NodeUnion; + struct Leaf; + struct Parent; + struct Freelisted; + + class SearchKey { + // Passed to methods that need to search the tree. This class allows most of the B-tree + // implementation to be kept out of templates, avoiding code bloat, at the cost of some + // performance trade-off. In order to lessen the performance cost of virtual calls, we design + // this interface so that it only needs to be called once per tree node, rather than once per + // comparison. + + public: + virtual uint search(const Parent& parent) const = 0; + virtual uint search(const Leaf& leaf) const = 0; + // Binary search for the first key/row in the parent/leaf that is equal to or comes after the + // search key. + + virtual bool isAfter(uint rowIndex) const = 0; + // Returns true if the key comes after the value in the given row. + }; + + BTreeImpl(); + ~BTreeImpl() noexcept(false); + + KJ_DISALLOW_COPY(BTreeImpl); + BTreeImpl(BTreeImpl&& other); + BTreeImpl& operator=(BTreeImpl&& other); + + void logInconsistency() const; + + void reserve(size_t size); + + void clear(); + + Iterator begin() const; + Iterator end() const; + + Iterator search(const SearchKey& searchKey) const; + // Find the "first" row (in sorted order) for which searchKey.isAfter(rowNumber) returns true. + + Iterator insert(const SearchKey& searchKey); + // Like search() but ensures that there is room in the leaf node to insert a new row. + + void erase(uint row, const SearchKey& searchKey); + // Erase the given row number from the tree. searchKey.isAfter() returns true for the given row + // and all rows after it. + + void renumber(uint oldRow, uint newRow, const SearchKey& searchKey); + // Renumber the given row from oldRow to newRow. searchKey.isAfter() returns true for oldRow and + // all rows after it. (It will not be called on newRow.) + + void verify(size_t size, FunctionParam); + +private: + NodeUnion* tree; // allocated with aligned_alloc aligned to cache lines + uint treeCapacity; + uint height; // height of *parent* tree -- does not include the leaf level + uint freelistHead; + uint freelistSize; + uint beginLeaf; + uint endLeaf; + void growTree(uint minCapacity = 0); + + template + struct AllocResult; + + template + inline AllocResult alloc(); + inline void free(uint pos); + + inline uint split(Parent& src, uint srcPos, Parent& dst, uint dstPos); + inline uint split(Leaf& dst, uint dstPos, Leaf& src, uint srcPos); + inline void merge(Parent& dst, uint dstPos, uint pivot, Parent& src); + inline void merge(Leaf& dst, uint dstPos, uint pivot, Leaf& src); + inline void move(Parent& dst, uint dstPos, Parent& src); + inline void move(Leaf& dst, uint dstPos, Leaf& src); + inline void rotateLeft( + Parent& left, Parent& right, Parent& parent, uint indexInParent, MaybeUint*& fixup); + inline void rotateLeft( + Leaf& left, Leaf& right, Parent& parent, uint indexInParent, MaybeUint*& fixup); + inline void rotateRight(Parent& left, Parent& right, Parent& parent, uint indexInParent); + inline void rotateRight(Leaf& left, Leaf& right, Parent& parent, uint indexInParent); + + template + inline Node& insertHelper(const SearchKey& searchKey, + Node& node, Parent* parent, uint indexInParent, uint pos); + + template + inline Node& eraseHelper( + Node& node, Parent* parent, uint indexInParent, uint pos, MaybeUint*& fixup); + + size_t verifyNode(size_t size, FunctionParam&, + uint pos, uint height, MaybeUint maxRow); + + static const NodeUnion EMPTY_NODE; +}; + +class BTreeImpl::MaybeUint { + // A nullable uint, using the value zero to mean null and shifting all other values up by 1. +public: + MaybeUint() = default; + inline MaybeUint(uint i): i(i - 1) {} + inline MaybeUint(decltype(nullptr)): i(0) {} + + inline bool operator==(decltype(nullptr)) const { return i == 0; } + inline bool operator==(uint j) const { return i == j + 1; } + inline bool operator==(const MaybeUint& other) const { return i == other.i; } + inline bool operator!=(decltype(nullptr)) const { return i != 0; } + inline bool operator!=(uint j) const { return i != j + 1; } + inline bool operator!=(const MaybeUint& other) const { return i != other.i; } + + inline MaybeUint& operator=(decltype(nullptr)) { i = 0; return *this; } + inline MaybeUint& operator=(uint j) { i = j + 1; return *this; } + + inline uint operator*() const { KJ_TABLE_IREQUIRE(i != 0); return i - 1; } + + template + inline bool check(Func& func) const { return i != 0 && func(i - 1); } + // Equivalent to *this != nullptr && func(**this) + + kj::String toString() const; + +private: + uint i; +}; + +struct BTreeImpl::Leaf { + uint next; + uint prev; + // Pointers to next and previous nodes at the same level, used for fast iteration. + + static constexpr size_t NROWS = 14; + MaybeUint rows[NROWS]; + // Pointers to table rows, offset by 1 so that 0 is an empty value. + + inline bool isFull() const; + inline bool isMostlyFull() const; + inline bool isHalfFull() const; + + inline void insert(uint i, uint newRow) { + KJ_TABLE_IREQUIRE(rows[Leaf::NROWS - 1] == nullptr); // check not full + + amove(rows + i + 1, rows + i, Leaf::NROWS - (i + 1)); + rows[i] = newRow; + } + + inline void erase(uint i) { + KJ_TABLE_IREQUIRE(rows[0] != nullptr); // check not empty + + amove(rows + i, rows + i + 1, Leaf::NROWS - (i + 1)); + rows[Leaf::NROWS - 1] = nullptr; + } + + inline uint size() const { + static_assert(Leaf::NROWS == 14, "logic here needs updating"); + + // Binary search for first empty element in `rows`, or return 14 if no empty elements. We do + // this in a branch-free manner. Since there are 15 possible results (0 through 14, inclusive), + // this isn't a perfectly balanced binary search. We carefully choose the split points so that + // there's no way we'll try to dereference row[14] or later (which would be a buffer overflow). + uint i = (rows[6] != nullptr) * 7; + i += (rows[i + 3] != nullptr) * 4; + i += (rows[i + 1] != nullptr) * 2; + i += (rows[i ] != nullptr); + return i; + } + + template + inline uint binarySearch(Func& predicate) const { + // Binary search to find first row for which predicate(row) is false. + + static_assert(Leaf::NROWS == 14, "logic here needs updating"); + + // See comments in size(). + uint i = (rows[6].check(predicate)) * 7; + i += (rows[i + 3].check(predicate)) * 4; + i += (rows[i + 1].check(predicate)) * 2; + if (i != 6) { // don't redundantly check row 6 + i += (rows[i ].check(predicate)); + } + return i; + } +}; + +struct BTreeImpl::Parent { + uint unused; + // Not used. May be arbitrarily non-zero due to overlap with Freelisted::nextOffset. + + static constexpr size_t NKEYS = 7; + MaybeUint keys[NKEYS]; + // Pointers to table rows, offset by 1 so that 0 is an empty value. + // + // Each keys[i] specifies the table row which is the "last" row found under children[i]. + // + // Note that `keys` has size 7 but `children` has size 8. `children[8]`'s "last row" is not + // recorded here, because the Parent's Parent records it instead. (Or maybe the Parent's Parent's + // Parent, if this Parent is `children[8]` of its own Parent. And so on.) + + static constexpr size_t NCHILDREN = NKEYS + 1; + uint children[NCHILDREN]; + // Pointers to children. Not offset because the root is always at position 0, and a pointer + // to the root would be nonsensical. + + inline bool isFull() const; + inline bool isMostlyFull() const; + inline bool isHalfFull() const; + inline void initRoot(uint key, uint leftChild, uint rightChild); + inline void insertAfter(uint i, uint splitKey, uint child); + inline void eraseAfter(uint i); + + inline uint keyCount() const { + static_assert(Parent::NKEYS == 7, "logic here needs updating"); + + // Binary search for first empty element in `keys`, or return 7 if no empty elements. We do + // this in a branch-free manner. Since there are 8 possible results (0 through 7, inclusive), + // this is a perfectly balanced binary search. + uint i = (keys[3] != nullptr) * 4; + i += (keys[i + 1] != nullptr) * 2; + i += (keys[i ] != nullptr); + return i; + } + + template + inline uint binarySearch(Func& predicate) const { + // Binary search to find first key for which predicate(key) is false. + + static_assert(Parent::NKEYS == 7, "logic here needs updating"); + + // See comments in size(). + uint i = (keys[3].check(predicate)) * 4; + i += (keys[i + 1].check(predicate)) * 2; + i += (keys[i ].check(predicate)); + return i; + } +}; + +struct BTreeImpl::Freelisted { + int nextOffset; + // The next node in the freelist is at: this + 1 + nextOffset + // + // Hence, newly-allocated space can initialize this to zero. + + uint zero[15]; + // Freelisted entries are always zero'd. +}; + +struct BTreeImpl::NodeUnion { + union { + Freelisted freelist; + // If this node is in the freelist. + + Leaf leaf; + // If this node is a leaf. + + Parent parent; + // If this node is not a leaf. + }; + + inline operator Leaf&() { return leaf; } + inline operator Parent&() { return parent; } + inline operator const Leaf&() const { return leaf; } + inline operator const Parent&() const { return parent; } +}; + +static_assert(sizeof(BTreeImpl::Parent) == 64, + "BTreeImpl::Parent should be optimized to fit a cache line"); +static_assert(sizeof(BTreeImpl::Leaf) == 64, + "BTreeImpl::Leaf should be optimized to fit a cache line"); +static_assert(sizeof(BTreeImpl::Freelisted) == 64, + "BTreeImpl::Freelisted should be optimized to fit a cache line"); +static_assert(sizeof(BTreeImpl::NodeUnion) == 64, + "BTreeImpl::NodeUnion should be optimized to fit a cache line"); + +bool BTreeImpl::Leaf::isFull() const { + return rows[Leaf::NROWS - 1] != nullptr; +} +bool BTreeImpl::Leaf::isMostlyFull() const { + return rows[Leaf::NROWS / 2] != nullptr; +} +bool BTreeImpl::Leaf::isHalfFull() const { + KJ_TABLE_IASSERT(rows[Leaf::NROWS / 2 - 1] != nullptr); + return rows[Leaf::NROWS / 2] == nullptr; +} + +bool BTreeImpl::Parent::isFull() const { + return keys[Parent::NKEYS - 1] != nullptr; +} +bool BTreeImpl::Parent::isMostlyFull() const { + return keys[Parent::NKEYS / 2] != nullptr; +} +bool BTreeImpl::Parent::isHalfFull() const { + KJ_TABLE_IASSERT(keys[Parent::NKEYS / 2 - 1] != nullptr); + return keys[Parent::NKEYS / 2] == nullptr; +} + +class BTreeImpl::Iterator { +public: + Iterator(const NodeUnion* tree, const Leaf* leaf, uint row) + : tree(tree), leaf(leaf), row(row) {} + + size_t operator*() const { + KJ_TABLE_IREQUIRE(row < Leaf::NROWS && leaf->rows[row] != nullptr, + "tried to dereference end() iterator"); + return *leaf->rows[row]; + } + + inline Iterator& operator++() { + KJ_TABLE_IREQUIRE(leaf->rows[row] != nullptr, "B-tree iterator overflow"); + ++row; + if (row >= Leaf::NROWS || leaf->rows[row] == nullptr) { + if (leaf->next == 0) { + // at end; stay on current leaf + } else { + leaf = &tree[leaf->next].leaf; + row = 0; + } + } + return *this; + } + inline Iterator operator++(int) { + Iterator other = *this; + ++*this; + return other; + } + + inline Iterator& operator--() { + if (row == 0) { + KJ_TABLE_IREQUIRE(leaf->prev != 0, "B-tree iterator underflow"); + leaf = &tree[leaf->prev].leaf; + row = leaf->size() - 1; + } else { + --row; + } + return *this; + } + inline Iterator operator--(int) { + Iterator other = *this; + --*this; + return other; + } + + inline bool operator==(const Iterator& other) const { + return leaf == other.leaf && row == other.row; + } + inline bool operator!=(const Iterator& other) const { + return leaf != other.leaf || row != other.row; + } + + bool isEnd() { + return row == Leaf::NROWS || leaf->rows[row] == nullptr; + } + + void insert(BTreeImpl& impl, uint newRow) { + KJ_TABLE_IASSERT(impl.tree == tree); + const_cast(leaf)->insert(row, newRow); + } + + void erase(BTreeImpl& impl) { + KJ_TABLE_IASSERT(impl.tree == tree); + const_cast(leaf)->erase(row); + } + + void replace(BTreeImpl& impl, uint newRow) { + KJ_TABLE_IASSERT(impl.tree == tree); + const_cast(leaf)->rows[row] = newRow; + } + +private: + const NodeUnion* tree; + const Leaf* leaf; + uint row; +}; + +inline BTreeImpl::Iterator BTreeImpl::begin() const { + return { tree, &tree[beginLeaf].leaf, 0 }; +} +inline BTreeImpl::Iterator BTreeImpl::end() const { + auto& leaf = tree[endLeaf].leaf; + return { tree, &leaf, leaf.size() }; +} + +} // namespace _ (private) + +template +class TreeIndex { +public: + TreeIndex() = default; + template + TreeIndex(Params&&... params): cb(kj::fwd(params)...) {} + + template + void verify(kj::ArrayPtr table) { + impl.verify(table.size(), [&](uint i, uint j) { + return cb.isBefore(table[i], table[j]); + }); + } + + inline void reserve(size_t size) { impl.reserve(size); } + inline void clear() { impl.clear(); } + inline auto begin() const { return impl.begin(); } + inline auto end() const { return impl.end(); } + + template + decltype(auto) keyForRow(Row&& row) const { + return cb.keyForRow(kj::fwd(row)); + } + + template + kj::Maybe insert(kj::ArrayPtr table, size_t pos, Params&&... params) { + auto iter = impl.insert(searchKey(table, params...)); + + if (!iter.isEnd() && cb.matches(table[*iter], params...)) { + return *iter; + } else { + iter.insert(impl, pos); + return nullptr; + } + } + + template + void erase(kj::ArrayPtr table, size_t pos, Params&&... params) { + impl.erase(pos, searchKeyForErase(table, pos, params...)); + } + + template + void move(kj::ArrayPtr table, size_t oldPos, size_t newPos, Params&&... params) { + impl.renumber(oldPos, newPos, searchKey(table, params...)); + } + + template + Maybe find(kj::ArrayPtr table, Params&&... params) const { + auto iter = impl.search(searchKey(table, params...)); + + if (!iter.isEnd() && cb.matches(table[*iter], params...)) { + return size_t(*iter); + } else { + return nullptr; + } + } + + template + _::BTreeImpl::Iterator seek(kj::ArrayPtr table, Params&&... params) const { + return impl.search(searchKey(table, params...)); + } + +private: + Callbacks cb; + _::BTreeImpl impl; + + template + class SearchKeyImpl: public _::BTreeImpl::SearchKey { + public: + SearchKeyImpl(Predicate&& predicate) + : predicate(kj::mv(predicate)) {} + + uint search(const _::BTreeImpl::Parent& parent) const override { + return parent.binarySearch(predicate); + } + uint search(const _::BTreeImpl::Leaf& leaf) const override { + return leaf.binarySearch(predicate); + } + bool isAfter(uint rowIndex) const override { + return predicate(rowIndex); + } + + private: + Predicate predicate; + }; + + template + inline auto searchKey(kj::ArrayPtr& table, Params&... params) const { + auto predicate = [&](uint i) { return cb.isBefore(table[i], params...); }; + return SearchKeyImpl(kj::mv(predicate)); + } + + template + inline auto searchKeyForErase(kj::ArrayPtr& table, uint pos, Params&... params) const { + // When erasing, the table entry for the erased row may already be invalid, so we must avoid + // accessing it. + auto predicate = [&,pos](uint i) { + return i != pos && cb.isBefore(table[i], params...); + }; + return SearchKeyImpl(kj::mv(predicate)); + } +}; + +// ----------------------------------------------------------------------------- +// Insertion order index + +class InsertionOrderIndex { + // Table index which allows iterating over elements in order of insertion. This index cannot + // be used for Table::find(), but can be used for Table::ordered(). + + struct Link; +public: + InsertionOrderIndex(); + InsertionOrderIndex(const InsertionOrderIndex&) = delete; + InsertionOrderIndex& operator=(const InsertionOrderIndex&) = delete; + InsertionOrderIndex(InsertionOrderIndex&& other); + InsertionOrderIndex& operator=(InsertionOrderIndex&& other); + ~InsertionOrderIndex() noexcept(false); + + class Iterator { + public: + Iterator(const Link* links, uint pos) + : links(links), pos(pos) {} + + inline size_t operator*() const { + KJ_TABLE_IREQUIRE(pos != 0, "can't dereference end() iterator"); + return pos - 1; + }; + + inline Iterator& operator++() { + pos = links[pos].next; + return *this; + } + inline Iterator operator++(int) { + Iterator result = *this; + ++*this; + return result; + } + inline Iterator& operator--() { + pos = links[pos].prev; + return *this; + } + inline Iterator operator--(int) { + Iterator result = *this; + --*this; + return result; + } + + inline bool operator==(const Iterator& other) const { + return pos == other.pos; + } + inline bool operator!=(const Iterator& other) const { + return pos != other.pos; + } + + private: + const Link* links; + uint pos; + }; + + template + Row& keyForRow(Row& row) const { return row; } + + void reserve(size_t size); + void clear(); + inline Iterator begin() const { return Iterator(links, links[0].next); } + inline Iterator end() const { return Iterator(links, 0); } + + template + kj::Maybe insert(kj::ArrayPtr table, size_t pos, const Row& row) { + return insertImpl(pos); + } + + template + void erase(kj::ArrayPtr table, size_t pos, const Row& row) { + eraseImpl(pos); + } + + template + void move(kj::ArrayPtr table, size_t oldPos, size_t newPos, const Row& row) { + return moveImpl(oldPos, newPos); + } + +private: + struct Link { + uint next; + uint prev; + }; + + uint capacity; + Link* links; + // links[0] is special: links[0].next points to the first link, links[0].prev points to the last. + // links[n+1] corresponds to row n. + + kj::Maybe insertImpl(size_t pos); + void eraseImpl(size_t pos); + void moveImpl(size_t oldPos, size_t newPos); + + static const Link EMPTY_LINK; +}; + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/threadlocal.h b/vendor/capnproto/src/kj/threadlocal.h new file mode 100644 index 0000000..613b96e --- /dev/null +++ b/vendor/capnproto/src/kj/threadlocal.h @@ -0,0 +1,66 @@ +// Copyright (c) 2014, Jason Choy +// 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. + +#pragma once + +// 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" + +KJ_BEGIN_HEADER + +namespace kj { + +#if __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. +// +// TODO(cleanup): The above comment was written many years ago. Is it still true? Shouldn't the +// compiler be smart enough to optimize a thread_local of POD type? + +#else + +#define KJ_THREADLOCAL_PTR(type) static thread_local type* + +#endif // KJ_USE_PTHREAD_TLS + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/time.c++ b/vendor/capnproto/src/kj/time.c++ new file mode 100644 index 0000000..5e5b615 --- /dev/null +++ b/vendor/capnproto/src/kj/time.c++ @@ -0,0 +1,127 @@ +// Copyright (c) 2014 Google Inc. (contributed by Remy Blank ) +// 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 "time.h" +#include "debug.h" + +#include + +namespace kj { + +const Clock& nullClock() { + class NullClock final: public Clock { + public: + Date now() const override { return UNIX_EPOCH; } + }; + static KJ_CONSTEXPR(const) NullClock NULL_CLOCK = NullClock(); + return NULL_CLOCK; +} + + +namespace { + +class PosixMonotonicClock: public MonotonicClock { +public: + constexpr PosixMonotonicClock(clockid_t clockId): clockId(clockId) {} + + TimePoint now() const override { + struct timespec ts; + KJ_SYSCALL(clock_gettime(clockId, &ts)); + return kj::origin() + ts.tv_sec * kj::SECONDS + ts.tv_nsec * kj::NANOSECONDS; + } + +private: + clockid_t clockId; +}; + +} // namespace + +// FreeBSD has "_PRECISE", but Linux just defaults to precise. +#ifndef CLOCK_MONOTONIC_PRECISE +#define CLOCK_MONOTONIC_PRECISE CLOCK_MONOTONIC +#endif + +const MonotonicClock& systemPreciseMonotonicClock() { + static constexpr PosixMonotonicClock clock(CLOCK_MONOTONIC_PRECISE); + return clock; +} + + +CappedArray KJ_STRINGIFY(TimePoint t) { + return kj::toCharSequence(t - kj::origin()); +} +CappedArray KJ_STRINGIFY(Date d) { + return kj::toCharSequence(d - UNIX_EPOCH); +} +CappedArray KJ_STRINGIFY(Duration d) { + bool negative = d < 0 * kj::SECONDS; + uint64_t ns = d / kj::NANOSECONDS; + if (negative) { + ns = -ns; + } + + auto digits = kj::toCharSequence(ns); + ArrayPtr arr = digits; + + size_t point; + kj::StringPtr suffix; + kj::Duration unit; + if (digits.size() > 9) { + point = arr.size() - 9; + suffix = "s"; + unit = kj::SECONDS; + } else if (digits.size() > 6) { + point = arr.size() - 6; + suffix = "ms"; + unit = kj::MILLISECONDS; + } else if (digits.size() > 3) { + point = arr.size() - 3; + suffix = "μs"; + unit = kj::MICROSECONDS; + } else { + point = arr.size(); + suffix = "ns"; + unit = kj::NANOSECONDS; + } + + CappedArray result; + char* begin = result.begin(); + char* end; + if (negative) { + *begin++ = '-'; + } + if (d % unit == 0 * kj::NANOSECONDS) { + end = _::fillLimited(begin, result.end(), arr.slice(0, point), suffix); + } else { + while (arr.back() == '0') { + arr = arr.slice(0, arr.size() - 1); + } + KJ_DASSERT(arr.size() > point); + end = _::fillLimited(begin, result.end(), arr.slice(0, point), "."_kj, + arr.slice(point, arr.size()), suffix); + } + result.setSize(end - result.begin()); + return result; +} + +} // namespace kj diff --git a/vendor/capnproto/src/kj/time.h b/vendor/capnproto/src/kj/time.h new file mode 100644 index 0000000..e9d0b24 --- /dev/null +++ b/vendor/capnproto/src/kj/time.h @@ -0,0 +1,100 @@ +// Copyright (c) 2014 Google Inc. (contributed by Remy Blank ) +// 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. + +#pragma once + +#include "units.h" +#include +#include "string.h" + +KJ_BEGIN_HEADER + +namespace kj { +namespace _ { // private + +class NanosecondLabel; +class TimeLabel; +class DateLabel; + +static constexpr size_t TIME_STR_LEN = sizeof(int64_t) * 3 + 8; +// Maximum length of a stringified time. 3 digits per byte of integer, plus 8 digits to cover +// negative sign, decimal point, unit, NUL terminator, and anything else that might sneak in. + +} // namespace _ (private) + +using Duration = Quantity; +// A time value, in nanoseconds. + +constexpr Duration NANOSECONDS = unit(); +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; +// An absolute time measured by some particular instance of `Timer` or `MonotonicClock`. `Time`s +// from two different `Timer`s or `MonotonicClock`s may be measured from different origins and so +// are not necessarily compatible. + +using Date = Absolute; +// A point in real-world time, measured relative to the Unix epoch (Jan 1, 1970 00:00:00 UTC). + +CappedArray KJ_STRINGIFY(TimePoint); +CappedArray KJ_STRINGIFY(Date); +CappedArray KJ_STRINGIFY(Duration); + +constexpr Date UNIX_EPOCH = origin(); +// The `Date` representing Jan 1, 1970 00:00:00 UTC. + +class Clock { + // Interface to read the current date and time. +public: + virtual Date now() const = 0; +}; + +class MonotonicClock { + // Interface to read time in a way that increases as real-world time increases, independent of + // any manual changes to the calendar date/time. Such a clock never "goes backwards" even if the + // system administrator changes the calendar time or suspends the system. However, this clock's + // time points are only meaningful in comparison to other time points from the same clock, and + // cannot be used to determine the current calendar date. + +public: + virtual TimePoint now() const = 0; +}; + +const Clock& nullClock(); +// A clock which always returns UNIX_EPOCH as the current time. Useful when you don't care about +// time. + +const MonotonicClock& systemPreciseMonotonicClock(); +// A MonotonicClock that reads the real system time. +// +// In well-designed code, this should only be called by the top-level dependency injector. All +// other modules should request that the caller provide a Clock so that alternate clock +// implementations can be injected for testing, simulation, reproducibility, and other purposes. +// +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/tuple.h b/vendor/capnproto/src/kj/tuple.h new file mode 100644 index 0000000..1351912 --- /dev/null +++ b/vendor/capnproto/src/kj/tuple.h @@ -0,0 +1,443 @@ +// 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 than `std::tuple`. It works as follows: +// - `kj::Tuple 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(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` 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()`. + +#pragma once + +#include "common.h" + +KJ_BEGIN_HEADER + +namespace kj { +namespace _ { // private + +template +struct TypeByIndex_; +template +struct TypeByIndex_<0, First, Rest...> { + typedef First Type; +}; +template +struct TypeByIndex_ + : public TypeByIndex_ {}; +template +struct TypeByIndex_ { + static_assert(index != index, "Index out-of-range."); +}; +template +using TypeByIndex = typename TypeByIndex_::Type; +// Chose a particular type out of a list of types, by index. + +template +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 +struct MakeIndexes_: public MakeIndexes_ {}; +template +struct MakeIndexes_<0, prefix...> { + typedef Indexes Type; +}; +template +using MakeIndexes = typename MakeIndexes_::Type; +// Equivalent to Indexes<0, 1, 2, ..., end>. + +template +class Tuple; +template +inline TypeByIndex& getImpl(Tuple& tuple); +template +inline TypeByIndex&& getImpl(Tuple&& tuple); +template +inline const TypeByIndex& getImpl(const Tuple& tuple); + +template +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 +struct TupleElement { + // A tuple containing references can be constructed using refTuple(). + + T& value; + constexpr inline TupleElement(T& value): value(value) {} +}; + +template +struct TupleElement> { + static_assert(sizeof(Tuple*) == 0, + "Tuples cannot contain other tuples -- they should be flattened."); +}; + +template +struct TupleImpl; + +template +struct TupleImpl, Types...> + : public TupleElement... { + // 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."); + + TupleImpl() = default; + + template + inline TupleImpl(Params&&... params) + : TupleElement(kj::fwd(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 + constexpr inline TupleImpl(Tuple&& other) + : TupleElement(kj::fwd(getImpl(other)))... {} + template + constexpr inline TupleImpl(Tuple& other) + : TupleElement(getImpl(other))... {} + template + constexpr inline TupleImpl(const Tuple& other) + : TupleElement(getImpl(other))... {} +}; + +struct MakeTupleFunc; +struct MakeRefTupleFunc; + +template +class Tuple { + // The actual Tuple class (used for tuples of size other than 1). + +public: + Tuple() = default; + + template + constexpr inline Tuple(Tuple&& other): impl(kj::mv(other)) {} + template + constexpr inline Tuple(Tuple& other): impl(other) {} + template + constexpr inline Tuple(const Tuple& other): impl(other) {} + +private: + template + constexpr Tuple(Params&&... params): impl(kj::fwd(params)...) {} + + TupleImpl, T...> impl; + + template + friend inline TypeByIndex& getImpl(Tuple& tuple); + template + friend inline TypeByIndex&& getImpl(Tuple&& tuple); + template + friend inline const TypeByIndex& getImpl(const Tuple& tuple); + friend struct MakeTupleFunc; + friend struct MakeRefTupleFunc; +}; + +template <> +class Tuple<> { + // Simplified zero-member version of Tuple. In particular this is important to make sure that + // Tuple<>() is constexpr. +}; + +template +class Tuple; +// Single-element tuple should never be used. The public API should ensure this. + +template +inline TypeByIndex& getImpl(Tuple& 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>&>(tuple.impl).value; +} +template +inline TypeByIndex&& getImpl(Tuple&& 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>&>(tuple.impl).value); +} +template +inline const TypeByIndex& getImpl(const Tuple& 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>&>(tuple.impl).value; +} +template +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(value); +} + + +template +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 +struct ExpandAndApplyResult_, First, Rest...> + : public ExpandAndApplyResult_, Rest...> {}; +template +struct ExpandAndApplyResult_, Tuple, Rest...> + : public ExpandAndApplyResult_, FirstTypes&&..., Rest...> {}; +template +struct ExpandAndApplyResult_, Tuple&, Rest...> + : public ExpandAndApplyResult_, FirstTypes&..., Rest...> {}; +template +struct ExpandAndApplyResult_, const Tuple&, Rest...> + : public ExpandAndApplyResult_, const FirstTypes&..., Rest...> {}; +template +struct ExpandAndApplyResult_> { + typedef decltype(instance()(instance()...)) Type; +}; +template +using ExpandAndApplyResult = typename ExpandAndApplyResult_, T...>::Type; +// Computes the expected return type of `expandAndApply()`. + +template +inline auto expandAndApply(Func&& func) -> ExpandAndApplyResult { + return func(); +} + +template +struct ExpandAndApplyFunc { + Func&& func; + First&& first; + ExpandAndApplyFunc(Func&& func, First&& first) + : func(kj::fwd(func)), first(kj::fwd(first)) {} + template + auto operator()(T&&... params) + -> decltype(this->func(kj::fwd(first), kj::fwd(params)...)) { + return this->func(kj::fwd(first), kj::fwd(params)...); + } +}; + +template +inline auto expandAndApply(Func&& func, First&& first, Rest&&... rest) + -> ExpandAndApplyResult { + + return expandAndApply( + ExpandAndApplyFunc(kj::fwd(func), kj::fwd(first)), + kj::fwd(rest)...); +} + +template +inline auto expandAndApply(Func&& func, Tuple&& first, Rest&&... rest) + -> ExpandAndApplyResult { + return expandAndApplyWithIndexes(MakeIndexes(), + kj::fwd(func), kj::mv(first), kj::fwd(rest)...); +} + +template +inline auto expandAndApply(Func&& func, Tuple& first, Rest&&... rest) + -> ExpandAndApplyResult { + return expandAndApplyWithIndexes(MakeIndexes(), + kj::fwd(func), first, kj::fwd(rest)...); +} + +template +inline auto expandAndApply(Func&& func, const Tuple& first, Rest&&... rest) + -> ExpandAndApplyResult { + return expandAndApplyWithIndexes(MakeIndexes(), + kj::fwd(func), first, kj::fwd(rest)...); +} + +template +inline auto expandAndApplyWithIndexes( + Indexes, Func&& func, Tuple&& first, Rest&&... rest) + -> ExpandAndApplyResult { + return expandAndApply(kj::fwd(func), kj::mv(getImpl(first))..., + kj::fwd(rest)...); +} + +template +inline auto expandAndApplyWithIndexes( + Indexes, Func&& func, const Tuple& first, Rest&&... rest) + -> ExpandAndApplyResult { + return expandAndApply(kj::fwd(func), getImpl(first)..., + kj::fwd(rest)...); +} + +struct MakeTupleFunc { + template + Tuple...> operator()(Params&&... params) { + return Tuple...>(kj::fwd(params)...); + } + template + Decay operator()(Param&& param) { + return kj::fwd(param); + } +}; + +struct MakeRefTupleFunc { + template + Tuple operator()(Params&&... params) { + return Tuple(kj::fwd(params)...); + } + template + Param operator()(Param&& param) { + return kj::fwd(param); + } +}; + +} // namespace _ (private) + +template struct Tuple_ { typedef _::Tuple Type; }; +template struct Tuple_ { typedef T Type; }; + +template using Tuple = typename Tuple_::Type; +// Tuple type. `Tuple` (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(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 +inline auto tuple(Params&&... params) + -> decltype(_::expandAndApply(_::MakeTupleFunc(), kj::fwd(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)...); +} + +template +inline auto refTuple(Params&&... params) + -> decltype(_::expandAndApply(_::MakeRefTupleFunc(), kj::fwd(params)...)) { + // Like tuple(), but if the params include lvalue references, they will be captured as + // references. rvalue references will still be captured as whole values (moved). + return _::expandAndApply(_::MakeRefTupleFunc(), kj::fwd(params)...); +} + +template +inline auto get(Tuple&& tuple) -> decltype(_::getImpl(kj::fwd(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(kj::fwd(tuple)); +} + +template +inline auto apply(Func&& func, Params&&... params) + -> decltype(_::expandAndApply(kj::fwd(func), kj::fwd(params)...)) { + // Apply a function to some arguments, expanding tuples into separate arguments. + return _::expandAndApply(kj::fwd(func), kj::fwd(params)...); +} + +template struct TupleSize_ { static constexpr size_t size = 1; }; +template struct TupleSize_<_::Tuple> { + static constexpr size_t size = sizeof...(T); +}; + +template +constexpr size_t tupleSize() { return TupleSize_::size; } +// Returns size of the tuple T. + +template +struct IndexOfType_; +template +struct HasType_ { + static constexpr bool value = false; +}; + +template +struct IndexOfType_ { + static constexpr size_t value = 0; +}; +template +struct HasType_ { + static constexpr bool value = true; +}; + +template +struct IndexOfType_> { + static constexpr size_t value = 0; + static_assert(!HasType_>::value, + "requested type appears multiple times in tuple"); +}; +template +struct HasType_> { + static constexpr bool value = true; +}; + +template +struct IndexOfType_> { + static constexpr size_t value = IndexOfType_>::value + 1; +}; +template +struct HasType_> { + static constexpr bool value = HasType_>::value; +}; + +template +inline constexpr size_t indexOfType() { + static_assert(HasType_::value, "type not present"); + return IndexOfType_::value; +} + +template +struct TypeOfIndex_; +template +struct TypeOfIndex_<0, T> { + typedef T Type; +}; +template +struct TypeOfIndex_> + : public TypeOfIndex_> {}; +template +struct TypeOfIndex_<0, _::Tuple> { + typedef T Type; +}; + +template +using TypeOfIndex = typename TypeOfIndex_::Type; + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/units.c++ b/vendor/capnproto/src/kj/units.c++ new file mode 100644 index 0000000..6947c12 --- /dev/null +++ b/vendor/capnproto/src/kj/units.c++ @@ -0,0 +1,31 @@ +// 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 "units.h" +#include "debug.h" + +namespace kj { + +void ThrowOverflow::operator()() const { + KJ_FAIL_REQUIRE("integer overflow"); +} + +} // namespace kj diff --git a/vendor/capnproto/src/kj/units.h b/vendor/capnproto/src/kj/units.h new file mode 100644 index 0000000..530abaf --- /dev/null +++ b/vendor/capnproto/src/kj/units.h @@ -0,0 +1,1170 @@ +// 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. + +#pragma once + +#include "common.h" +#include + +KJ_BEGIN_HEADER + +namespace kj { + +// ======================================================================================= +// IDs + +template +struct Id { + // A type-safe numeric ID. `UnderlyingType` is the underlying integer representation. `Label` + // distinguishes this Id from other Id types. Sample usage: + // + // class Foo; + // typedef Id FooId; + // + // class Bar; + // typedef Id BarId; + // + // You can now use the FooId and BarId types without any possibility of accidentally using a + // FooId when you really wanted a BarId or vice-versa. + + UnderlyingType value; + + inline constexpr Id(): value(0) {} + inline constexpr explicit Id(int value): value(value) {} + + inline constexpr bool operator==(const Id& other) const { return value == other.value; } + inline constexpr bool operator!=(const Id& other) const { return value != other.value; } + inline constexpr bool operator<=(const Id& other) const { return value <= other.value; } + inline constexpr bool operator>=(const Id& other) const { return value >= other.value; } + inline constexpr bool operator< (const Id& other) const { return value < other.value; } + inline constexpr bool operator> (const Id& other) const { return value > other.value; } +}; + +// ======================================================================================= +// Quantity and UnitRatio -- implement unit analysis via the type system + +struct Unsafe_ {}; +constexpr Unsafe_ unsafe = Unsafe_(); +// Use as a parameter to constructors that are unsafe to indicate that you really do mean it. + +template +class Bounded; +template +class BoundedConst; + +template +struct IsIntegralOrBounded_ { static constexpr bool value = isIntegral(); }; +template +struct IsIntegralOrBounded_> { static constexpr bool value = true; }; +template +struct IsIntegralOrBounded_> { static constexpr bool value = true; }; + +template +inline constexpr bool isIntegralOrBounded() { return IsIntegralOrBounded_::value; } + +template +class UnitRatio { + // A multiplier used to convert Quantities of one unit to Quantities of another unit. See + // Quantity, below. + // + // Construct this type by dividing one Quantity by another of a different unit. Use this type + // by multiplying it by a Quantity, or dividing a Quantity by it. + + static_assert(isIntegralOrBounded(), + "Underlying type for UnitRatio must be integer."); + +public: + inline UnitRatio() {} + + constexpr UnitRatio(Number unit1PerUnit2, decltype(unsafe)): unit1PerUnit2(unit1PerUnit2) {} + // This constructor was intended to be private, but GCC complains about it being private in a + // bunch of places that don't appear to even call it, so I made it public. Oh well. + + template + inline constexpr UnitRatio(const UnitRatio& other) + : unit1PerUnit2(other.unit1PerUnit2) {} + + template + inline constexpr UnitRatio + operator+(UnitRatio other) const { + return UnitRatio( + unit1PerUnit2 + other.unit1PerUnit2, unsafe); + } + template + inline constexpr UnitRatio + operator-(UnitRatio other) const { + return UnitRatio( + unit1PerUnit2 - other.unit1PerUnit2, unsafe); + } + + template + inline constexpr UnitRatio + operator*(UnitRatio other) const { + // U1 / U2 * U3 / U1 = U3 / U2 + return UnitRatio( + unit1PerUnit2 * other.unit1PerUnit2, unsafe); + } + template + inline constexpr UnitRatio + operator*(UnitRatio other) const { + // U1 / U2 * U2 / U3 = U1 / U3 + return UnitRatio( + unit1PerUnit2 * other.unit1PerUnit2, unsafe); + } + + template + inline constexpr UnitRatio + operator/(UnitRatio other) const { + // (U1 / U2) / (U1 / U3) = U3 / U2 + return UnitRatio( + unit1PerUnit2 / other.unit1PerUnit2, unsafe); + } + template + inline constexpr UnitRatio + operator/(UnitRatio other) const { + // (U1 / U2) / (U3 / U2) = U1 / U3 + return UnitRatio( + unit1PerUnit2 / other.unit1PerUnit2, unsafe); + } + + template + inline decltype(Number() / OtherNumber()) + operator/(UnitRatio other) const { + return unit1PerUnit2 / other.unit1PerUnit2; + } + + template + inline constexpr bool operator==(const UnitRatio& other) const { + return unit1PerUnit2 == other.unit1PerUnit2; + } + template + inline constexpr bool operator!=(const UnitRatio& other) const { + return unit1PerUnit2 != other.unit1PerUnit2; + } + +private: + Number unit1PerUnit2; + + template + friend class Quantity; + template + friend class UnitRatio; + + template + friend inline constexpr UnitRatio + operator*(N1, UnitRatio); +}; + +template () && isIntegralOrBounded()>> +inline constexpr UnitRatio + operator*(N1 n, UnitRatio r) { + return UnitRatio(n * r.unit1PerUnit2, unsafe); +} + +template +class Quantity { + // A type-safe numeric quantity, specified in terms of some unit. Two Quantities cannot be used + // in arithmetic unless they use the same unit. The `Unit` type parameter is only used to prevent + // accidental mixing of units; this type is never instantiated and can very well be incomplete. + // `Number` is the underlying primitive numeric type. + // + // Quantities support most basic arithmetic operators, intelligently handling units, and + // automatically casting the underlying type in the same way that the compiler would. + // + // To convert a primitive number to a Quantity, multiply it by unit>(). + // To convert a Quantity to a primitive number, divide it by unit>(). + // To convert a Quantity of one unit to another unit, multiply or divide by a UnitRatio. + // + // The Quantity class is not well-suited to hardcore physics as it does not allow multiplying + // one quantity by another. For example, multiplying meters by meters won't get you square + // meters; it will get you a compiler error. It would be interesting to see if template + // metaprogramming could properly deal with such things but this isn't needed for the present + // use case. + // + // Sample usage: + // + // class SecondsLabel; + // typedef Quantity Seconds; + // constexpr Seconds SECONDS = unit(); + // + // class MinutesLabel; + // typedef Quantity Minutes; + // constexpr Minutes MINUTES = unit(); + // + // constexpr UnitRatio SECONDS_PER_MINUTE = + // 60 * SECONDS / MINUTES; + // + // void waitFor(Seconds seconds) { + // sleep(seconds / SECONDS); + // } + // void waitFor(Minutes minutes) { + // waitFor(minutes * SECONDS_PER_MINUTE); + // } + // + // void waitThreeMinutes() { + // waitFor(3 * MINUTES); + // } + + static_assert(isIntegralOrBounded(), + "Underlying type for Quantity must be integer."); + +public: + inline constexpr Quantity() = default; + + inline constexpr Quantity(MaxValue_): value(maxValue) {} + inline constexpr Quantity(MinValue_): value(minValue) {} + // Allow initialization from maxValue and minValue. + // TODO(msvc): decltype(maxValue) and decltype(minValue) deduce unknown-type for these function + // parameters, causing the compiler to complain of a duplicate constructor definition, so we + // specify MaxValue_ and MinValue_ types explicitly. + + inline constexpr Quantity(Number value, decltype(unsafe)): value(value) {} + // This constructor was intended to be private, but GCC complains about it being private in a + // bunch of places that don't appear to even call it, so I made it public. Oh well. + + template + inline constexpr Quantity(const Quantity& other) + : value(other.value) {} + + template + inline Quantity& operator=(const Quantity& other) { + value = other.value; + return *this; + } + + template + inline constexpr Quantity + operator+(const Quantity& other) const { + return Quantity(value + other.value, unsafe); + } + template + inline constexpr Quantity + operator-(const Quantity& other) const { + return Quantity(value - other.value, unsafe); + } + template ()>> + inline constexpr Quantity + operator*(OtherNumber other) const { + return Quantity(value * other, unsafe); + } + template ()>> + inline constexpr Quantity + operator/(OtherNumber other) const { + return Quantity(value / other, unsafe); + } + template + inline constexpr decltype(Number() / OtherNumber()) + operator/(const Quantity& other) const { + return value / other.value; + } + template + inline constexpr Quantity + operator%(const Quantity& other) const { + return Quantity(value % other.value, unsafe); + } + + template + inline constexpr Quantity + operator*(UnitRatio ratio) const { + return Quantity( + value * ratio.unit1PerUnit2, unsafe); + } + template + inline constexpr Quantity + operator/(UnitRatio ratio) const { + return Quantity( + value / ratio.unit1PerUnit2, unsafe); + } + template + inline constexpr Quantity + operator%(UnitRatio ratio) const { + return Quantity( + value % ratio.unit1PerUnit2, unsafe); + } + template + inline constexpr UnitRatio + operator/(Quantity other) const { + return UnitRatio( + value / other.value, unsafe); + } + + template + inline constexpr bool operator==(const Quantity& other) const { + return value == other.value; + } + template + inline constexpr bool operator!=(const Quantity& other) const { + return value != other.value; + } + template + inline constexpr bool operator<=(const Quantity& other) const { + return value <= other.value; + } + template + inline constexpr bool operator>=(const Quantity& other) const { + return value >= other.value; + } + template + inline constexpr bool operator<(const Quantity& other) const { + return value < other.value; + } + template + inline constexpr bool operator>(const Quantity& other) const { + return value > other.value; + } + + template + inline Quantity& operator+=(const Quantity& other) { + value += other.value; + return *this; + } + template + inline Quantity& operator-=(const Quantity& other) { + value -= other.value; + return *this; + } + template + inline Quantity& operator*=(OtherNumber other) { + value *= other; + return *this; + } + template + inline Quantity& operator/=(OtherNumber other) { + value /= other.value; + return *this; + } + +private: + Number value; + + template + friend class Quantity; + + template + friend inline constexpr auto operator*(Number1 a, Quantity b) + -> Quantity; +}; + +template struct Unit_ { + static inline constexpr T get() { return T(1); } +}; +template +struct Unit_> { + static inline constexpr Quantity::get()), U> get() { + return Quantity::get()), U>(Unit_::get(), unsafe); + } +}; + +template +inline constexpr auto unit() -> decltype(Unit_::get()) { return Unit_::get(); } +// unit>() returns a Quantity of value 1. It also, intentionally, works on basic +// numeric types. + +template ()>> +inline constexpr auto operator*(Number1 a, Quantity b) + -> Quantity { + return Quantity(a * b.value, unsafe); +} + +template +inline constexpr auto operator*(UnitRatio ratio, + Quantity measure) + -> decltype(measure * ratio) { + return measure * ratio; +} + +// ======================================================================================= +// Absolute measures + +template +class Absolute { + // Wraps some other value -- typically a Quantity -- but represents a value measured based on + // some absolute origin. For example, if `Duration` is a type representing a time duration, + // Absolute might be a calendar date. + // + // Since Absolute represents measurements relative to some arbitrary origin, the only sensible + // arithmetic to perform on them is addition and subtraction. + + // TODO(someday): Do the same automatic expansion of integer width that Quantity does? Doesn't + // matter for our time use case, where we always use 64-bit anyway. Note that fixing this + // would implicitly allow things like multiplying an Absolute by a UnitRatio to change its + // units, which is actually totally logical and kind of neat. + +public: + inline constexpr Absolute(MaxValue_): value(maxValue) {} + inline constexpr Absolute(MinValue_): value(minValue) {} + // Allow initialization from maxValue and minValue. + // TODO(msvc): decltype(maxValue) and decltype(minValue) deduce unknown-type for these function + // parameters, causing the compiler to complain of a duplicate constructor definition, so we + // specify MaxValue_ and MinValue_ types explicitly. + + inline constexpr Absolute operator+(const T& other) const { return Absolute(value + other); } + inline constexpr Absolute operator-(const T& other) const { return Absolute(value - other); } + inline constexpr T operator-(const Absolute& other) const { return value - other.value; } + + inline Absolute& operator+=(const T& other) { value += other; return *this; } + inline Absolute& operator-=(const T& other) { value -= other; return *this; } + + inline constexpr bool operator==(const Absolute& other) const { return value == other.value; } + inline constexpr bool operator!=(const Absolute& other) const { return value != other.value; } + inline constexpr bool operator<=(const Absolute& other) const { return value <= other.value; } + inline constexpr bool operator>=(const Absolute& other) const { return value >= other.value; } + inline constexpr bool operator< (const Absolute& other) const { return value < other.value; } + inline constexpr bool operator> (const Absolute& other) const { return value > other.value; } + +private: + T value; + + explicit constexpr Absolute(T value): value(value) {} + + template + friend inline constexpr U origin(); +}; + +template +inline constexpr Absolute operator+(const T& a, const Absolute& b) { + return b + a; +} + +template struct UnitOf_ { typedef T Type; }; +template struct UnitOf_> { typedef T Type; }; +template +using UnitOf = typename UnitOf_::Type; +// UnitOf> is T. UnitOf is AnythingElse. + +template +inline constexpr T origin() { return T(0 * unit>()); } +// origin>() returns an Absolute of value 0. It also, intentionally, works on basic +// numeric types. + +// ======================================================================================= +// Overflow avoidance + +template +struct BitCount_ { + static constexpr uint value = BitCount_<(n >> 1), accum + 1>::value; +}; +template +struct BitCount_<0, accum> { + static constexpr uint value = accum; +}; + +template +inline constexpr uint bitCount() { return BitCount_::value; } +// Number of bits required to represent the number `n`. + +template struct AtLeastUInt_ { + static_assert(bitCountBitCount < 7, "don't know how to represent integers over 64 bits"); +}; +template <> struct AtLeastUInt_<0> { typedef uint8_t Type; }; +template <> struct AtLeastUInt_<1> { typedef uint8_t Type; }; +template <> struct AtLeastUInt_<2> { typedef uint8_t Type; }; +template <> struct AtLeastUInt_<3> { typedef uint8_t Type; }; +template <> struct AtLeastUInt_<4> { typedef uint16_t Type; }; +template <> struct AtLeastUInt_<5> { typedef uint32_t Type; }; +template <> struct AtLeastUInt_<6> { typedef uint64_t Type; }; + +template +using AtLeastUInt = typename AtLeastUInt_()>::Type; +// AtLeastUInt is an unsigned integer of at least n bits. E.g. AtLeastUInt<12> is uint16_t. + +// ------------------------------------------------------------------- + +template +class BoundedConst { + // A constant integer value on which we can do bit size analysis. + +public: + BoundedConst() = default; + + inline constexpr uint unwrap() const { return value; } + +#define OP(op, check) \ + template \ + inline constexpr BoundedConst<(value op other)> \ + operator op(BoundedConst) const { \ + static_assert(check, "overflow in BoundedConst arithmetic"); \ + return BoundedConst<(value op other)>(); \ + } +#define COMPARE_OP(op) \ + template \ + inline constexpr bool operator op(BoundedConst) const { \ + return value op other; \ + } + + OP(+, value + other >= value) + OP(-, value - other <= value) + OP(*, value * other / other == value) + OP(/, true) // div by zero already errors out; no other division ever overflows + OP(%, true) // mod by zero already errors out; no other modulus ever overflows + OP(<<, value << other >= value) + OP(>>, true) // right shift can't overflow + OP(&, true) // bitwise ops can't overflow + OP(|, true) // bitwise ops can't overflow + + COMPARE_OP(==) + COMPARE_OP(!=) + COMPARE_OP(< ) + COMPARE_OP(> ) + COMPARE_OP(<=) + COMPARE_OP(>=) +#undef OP +#undef COMPARE_OP +}; + +template +struct Unit_> { + static inline constexpr BoundedConst<1> get() { return BoundedConst<1>(); } +}; + +template +struct Unit_> { + static inline constexpr BoundedConst<1> get() { return BoundedConst<1>(); } +}; + +template +inline constexpr BoundedConst bounded() { + return BoundedConst(); +} + +template +static constexpr uint64_t boundedAdd() { + static_assert(a + b >= a, "possible overflow detected"); + return a + b; +} +template +static constexpr uint64_t boundedSub() { + static_assert(a - b <= a, "possible underflow detected"); + return a - b; +} +template +static constexpr uint64_t boundedMul() { + static_assert(a * b / b == a, "possible overflow detected"); + return a * b; +} +template +static constexpr uint64_t boundedLShift() { + static_assert(a << b >= a, "possible overflow detected"); + return a << b; +} + +template +inline constexpr BoundedConst min(BoundedConst, BoundedConst) { + return bounded(); +} +template +inline constexpr BoundedConst max(BoundedConst, BoundedConst) { + return bounded(); +} +// We need to override min() and max() between constants because the ternary operator in the +// default implementation would complain. + +// ------------------------------------------------------------------- + +template +class Bounded { +public: + static_assert(maxN <= T(kj::maxValue), "possible overflow detected"); + + Bounded() = default; + + Bounded(const Bounded& other) = default; + template ()>> + inline constexpr Bounded(OtherInt value): value(value) { + static_assert(OtherInt(maxValue) <= maxN, "possible overflow detected"); + } + template + inline constexpr Bounded(const Bounded& other) + : value(other.value) { + static_assert(otherMax <= maxN, "possible overflow detected"); + } + template + inline constexpr Bounded(BoundedConst) + : value(otherValue) { + static_assert(otherValue <= maxN, "overflow detected"); + } + + Bounded& operator=(const Bounded& other) = default; + template ()>> + Bounded& operator=(OtherInt other) { + static_assert(OtherInt(maxValue) <= maxN, "possible overflow detected"); + value = other; + return *this; + } + template + inline Bounded& operator=(const Bounded& other) { + static_assert(otherMax <= maxN, "possible overflow detected"); + value = other.value; + return *this; + } + template + inline Bounded& operator=(BoundedConst) { + static_assert(otherValue <= maxN, "overflow detected"); + value = otherValue; + return *this; + } + + inline constexpr T unwrap() const { return value; } + +#define OP(op, newMax) \ + template \ + inline constexpr Bounded \ + operator op(const Bounded& other) const { \ + return Bounded(value op other.value, unsafe); \ + } +#define COMPARE_OP(op) \ + template \ + inline constexpr bool operator op(const Bounded& other) const { \ + return value op other.value; \ + } + + OP(+, (boundedAdd())) + OP(*, (boundedMul())) + OP(/, maxN) + OP(%, otherMax - 1) + + // operator- is intentionally omitted because we mostly use this with unsigned types, and + // subtraction requires proof that subtrahend is not greater than the minuend. + + COMPARE_OP(==) + COMPARE_OP(!=) + COMPARE_OP(< ) + COMPARE_OP(> ) + COMPARE_OP(<=) + COMPARE_OP(>=) + +#undef OP +#undef COMPARE_OP + + template + inline Bounded assertMax(ErrorFunc&& func) const { + // Assert that the number is no more than `newMax`. Otherwise, call `func`. + static_assert(newMax < maxN, "this bounded size assertion is redundant"); + if (KJ_UNLIKELY(value > newMax)) func(); + return Bounded(value, unsafe); + } + + template + inline Bounded subtractChecked( + const Bounded& other, ErrorFunc&& func) const { + // Subtract a number, calling func() if the result would underflow. + if (KJ_UNLIKELY(value < other.value)) func(); + return Bounded(value - other.value, unsafe); + } + + template + inline Bounded subtractChecked( + BoundedConst, ErrorFunc&& func) const { + // Subtract a number, calling func() if the result would underflow. + static_assert(otherValue <= maxN, "underflow detected"); + if (KJ_UNLIKELY(value < otherValue)) func(); + return Bounded(value - otherValue, unsafe); + } + + template + inline Maybe> trySubtract( + const Bounded& other) const { + // Subtract a number, calling func() if the result would underflow. + if (value < other.value) { + return nullptr; + } else { + return Bounded(value - other.value, unsafe); + } + } + + template + inline Maybe> trySubtract(BoundedConst) const { + // Subtract a number, calling func() if the result would underflow. + if (value < otherValue) { + return nullptr; + } else { + return Bounded(value - otherValue, unsafe); + } + } + + inline constexpr Bounded(T value, decltype(unsafe)): value(value) {} + template + inline constexpr Bounded(Bounded value, decltype(unsafe)) + : value(value.value) {} + // Mainly for internal use. + // + // Only use these as a last resort, with ample commentary on why you think it's safe. + +private: + T value; + + template + friend class Bounded; +}; + +template +inline constexpr Bounded bounded(Number value) { + return Bounded(value, unsafe); +} + +inline constexpr Bounded<1, uint8_t> bounded(bool value) { + return Bounded<1, uint8_t>(value, unsafe); +} + +template +inline constexpr Bounded(), Number> assumeBits(Number value) { + return Bounded(), Number>(value, unsafe); +} + +template +inline constexpr Bounded(), T> assumeBits(Bounded value) { + return Bounded(), T>(value, unsafe); +} + +template +inline constexpr auto assumeBits(Quantity value) + -> Quantity(value / unit>())), Unit> { + return Quantity(value / unit>())), Unit>( + assumeBits(value / unit>()), unsafe); +} + +template +inline constexpr Bounded assumeMax(Number value) { + return Bounded(value, unsafe); +} + +template +inline constexpr Bounded assumeMax(Bounded value) { + return Bounded(value, unsafe); +} + +template +inline constexpr auto assumeMax(Quantity value) + -> Quantity(value / unit>())), Unit> { + return Quantity(value / unit>())), Unit>( + assumeMax(value / unit>()), unsafe); +} + +template +inline constexpr Bounded assumeMax(BoundedConst, Number value) { + return assumeMax(value); +} + +template +inline constexpr Bounded assumeMax(BoundedConst, Bounded value) { + return assumeMax(value); +} + +template +inline constexpr auto assumeMax(Quantity, Unit>, Quantity value) + -> decltype(assumeMax(value)) { + return assumeMax(value); +} + +template +inline Bounded assertMax(Bounded value, ErrorFunc&& errorFunc) { + // Assert that the bounded value is less than or equal to the given maximum, calling errorFunc() + // if not. + static_assert(newMax < maxN, "this bounded size assertion is redundant"); + return value.template assertMax(kj::fwd(errorFunc)); +} + +template +inline Quantity, Unit> assertMax( + Quantity, Unit> value, ErrorFunc&& errorFunc) { + // Assert that the bounded value is less than or equal to the given maximum, calling errorFunc() + // if not. + static_assert(newMax < maxN, "this bounded size assertion is redundant"); + return (value / unit()).template assertMax( + kj::fwd(errorFunc)) * unit(); +} + +template +inline Bounded assertMax( + BoundedConst, Bounded value, ErrorFunc&& errorFunc) { + return assertMax(value, kj::mv(errorFunc)); +} + +template +inline Quantity, Unit> assertMax( + Quantity, Unit>, + Quantity, Unit> value, ErrorFunc&& errorFunc) { + return assertMax(value, kj::mv(errorFunc)); +} + +template +inline Bounded(), T> assertMaxBits( + Bounded value, ErrorFunc&& errorFunc = ErrorFunc()) { + // Assert that the bounded value requires no more than the given number of bits, calling + // errorFunc() if not. + return assertMax()>(value, kj::fwd(errorFunc)); +} + +template +inline Quantity(), T>, Unit> assertMaxBits( + Quantity, Unit> value, ErrorFunc&& errorFunc = ErrorFunc()) { + // Assert that the bounded value requires no more than the given number of bits, calling + // errorFunc() if not. + return assertMax()>(value, kj::fwd(errorFunc)); +} + +template +inline constexpr Bounded upgradeBound(Bounded value) { + return value; +} + +template +inline constexpr Quantity, Unit> upgradeBound( + Quantity, Unit> value) { + return value; +} + +template +inline auto subtractChecked(Bounded value, Other other, ErrorFunc&& errorFunc) + -> decltype(value.subtractChecked(other, kj::fwd(errorFunc))) { + return value.subtractChecked(other, kj::fwd(errorFunc)); +} + +template +inline auto subtractChecked(Quantity value, Quantity other, ErrorFunc&& errorFunc) + -> Quantity(errorFunc))), Unit> { + return subtractChecked(value / unit>(), + other / unit>(), + kj::fwd(errorFunc)) + * unit>(); +} + +template +inline auto trySubtract(Bounded value, Other other) + -> decltype(value.trySubtract(other)) { + return value.trySubtract(other); +} + +template +inline auto trySubtract(Quantity value, Quantity other) + -> Maybe> { + return trySubtract(value / unit>(), + other / unit>()) + .map([](decltype(subtractChecked(T(), U(), int())) x) { + return x * unit>(); + }); +} + +template +inline constexpr Bounded> +min(Bounded a, Bounded b) { + return Bounded>(kj::min(a.unwrap(), b.unwrap()), unsafe); +} +template +inline constexpr Bounded> +max(Bounded a, Bounded b) { + return Bounded>(kj::max(a.unwrap(), b.unwrap()), unsafe); +} +// We need to override min() and max() because: +// 1) WiderType<> might not choose the correct bounds. +// 2) One of the two sides of the ternary operator in the default implementation would fail to +// typecheck even though it is OK in practice. + +// ------------------------------------------------------------------- +// Operators between Bounded and BoundedConst + +#define OP(op, newMax) \ +template \ +inline constexpr Bounded<(newMax), decltype(T() op uint())> operator op( \ + Bounded value, BoundedConst) { \ + return Bounded<(newMax), decltype(T() op uint())>(value.unwrap() op cvalue, unsafe); \ +} + +#define REVERSE_OP(op, newMax) \ +template \ +inline constexpr Bounded<(newMax), decltype(uint() op T())> operator op( \ + BoundedConst, Bounded value) { \ + return Bounded<(newMax), decltype(uint() op T())>(cvalue op value.unwrap(), unsafe); \ +} + +#define COMPARE_OP(op) \ +template \ +inline constexpr bool operator op(Bounded value, BoundedConst) { \ + return value.unwrap() op cvalue; \ +} \ +template \ +inline constexpr bool operator op(BoundedConst, Bounded value) { \ + return cvalue op value.unwrap(); \ +} + +OP(+, (boundedAdd())) +REVERSE_OP(+, (boundedAdd())) + +OP(*, (boundedMul())) +REVERSE_OP(*, (boundedAdd())) + +OP(/, maxN / cvalue) +REVERSE_OP(/, cvalue) // denominator could be 1 + +OP(%, cvalue - 1) +REVERSE_OP(%, maxN - 1) + +OP(<<, (boundedLShift())) +REVERSE_OP(<<, (boundedLShift())) + +OP(>>, maxN >> cvalue) +REVERSE_OP(>>, cvalue >> maxN) + +OP(&, maxValueForBits()>() & cvalue) +REVERSE_OP(&, maxValueForBits()>() & cvalue) + +OP(|, maxN | cvalue) +REVERSE_OP(|, maxN | cvalue) + +COMPARE_OP(==) +COMPARE_OP(!=) +COMPARE_OP(< ) +COMPARE_OP(> ) +COMPARE_OP(<=) +COMPARE_OP(>=) + +#undef OP +#undef REVERSE_OP +#undef COMPARE_OP + +template +inline constexpr Bounded + operator-(BoundedConst, Bounded value) { + // We allow subtraction of a variable from a constant only if the constant is greater than or + // equal to the maximum possible value of the variable. Since the variable could be zero, the + // result can be as large as the constant. + // + // We do not allow subtraction of a constant from a variable because there's never a guarantee it + // won't underflow (unless the constant is zero, which is silly). + static_assert(cvalue >= maxN, "possible underflow detected"); + return Bounded(cvalue - value.unwrap(), unsafe); +} + +template +inline constexpr Bounded min(Bounded a, BoundedConst) { + return Bounded(kj::min(b, a.unwrap()), unsafe); +} +template +inline constexpr Bounded min(BoundedConst, Bounded a) { + return Bounded(kj::min(a.unwrap(), b), unsafe); +} +template +inline constexpr Bounded max(Bounded a, BoundedConst) { + return Bounded(kj::max(b, a.unwrap()), unsafe); +} +template +inline constexpr Bounded max(BoundedConst, Bounded a) { + return Bounded(kj::max(a.unwrap(), b), unsafe); +} +// We need to override min() between a Bounded and a constant since: +// 1) WiderType<> might choose BoundedConst over a 1-byte Bounded, which is wrong. +// 2) To clamp the bounds of the output type. +// 3) Same ternary operator typechecking issues. + +// ------------------------------------------------------------------- + +template +class SafeUnwrapper { +public: + inline explicit constexpr SafeUnwrapper(Bounded value): value(value.unwrap()) {} + + template ()>> + inline constexpr operator U() const { + static_assert(maxN <= U(maxValue), "possible truncation detected"); + return value; + } + + inline constexpr operator bool() const { + static_assert(maxN <= 1, "possible truncation detected"); + return value; + } + +private: + T value; +}; + +template +inline constexpr SafeUnwrapper unbound(Bounded bounded) { + // Unwraps the bounded value, returning a value that can be implicitly cast to any integer type. + // If this implicit cast could truncate, a compile-time error will be raised. + return SafeUnwrapper(bounded); +} + +template +class SafeConstUnwrapper { +public: + template ()>> + inline constexpr operator T() const { + static_assert(value <= T(maxValue), "this operation will truncate"); + return value; + } + + inline constexpr operator bool() const { + static_assert(value <= 1, "this operation will truncate"); + return value; + } +}; + +template +inline constexpr SafeConstUnwrapper unbound(BoundedConst) { + return SafeConstUnwrapper(); +} + +template +inline constexpr T unboundAs(U value) { + return unbound(value); +} + +template +inline constexpr T unboundMax(Bounded value) { + // Explicitly unguard expecting a value that is at most `maxN`. + static_assert(maxN <= requestedMax, "possible overflow detected"); + return value.unwrap(); +} + +template +inline constexpr uint unboundMax(BoundedConst) { + // Explicitly unguard expecting a value that is at most `maxN`. + static_assert(value <= requestedMax, "overflow detected"); + return value; +} + +template +inline constexpr auto unboundMaxBits(T value) -> + decltype(unboundMax()>(value)) { + // Explicitly unguard expecting a value that fits into `bits` bits. + return unboundMax()>(value); +} + +#define OP(op) \ +template \ +inline constexpr auto operator op(T a, SafeUnwrapper b) -> decltype(a op (T)b) { \ + return a op (AtLeastUInt)b; \ +} \ +template \ +inline constexpr auto operator op(SafeUnwrapper b, T a) -> decltype((T)b op a) { \ + return (AtLeastUInt)b op a; \ +} \ +template \ +inline constexpr auto operator op(T a, SafeConstUnwrapper b) -> decltype(a op (T)b) { \ + return a op (AtLeastUInt)b; \ +} \ +template \ +inline constexpr auto operator op(SafeConstUnwrapper b, T a) -> decltype((T)b op a) { \ + return (AtLeastUInt)b op a; \ +} + +OP(+) +OP(-) +OP(*) +OP(/) +OP(%) +OP(<<) +OP(>>) +OP(&) +OP(|) +OP(==) +OP(!=) +OP(<=) +OP(>=) +OP(<) +OP(>) + +#undef OP + +// ------------------------------------------------------------------- + +template +class Range> { +public: + inline constexpr Range(Bounded begin, Bounded end) + : inner(unbound(begin), unbound(end)) {} + inline explicit constexpr Range(Bounded end) + : inner(unbound(end)) {} + + class Iterator { + public: + Iterator() = default; + inline explicit Iterator(typename Range::Iterator inner): inner(inner) {} + + inline Bounded operator* () const { return Bounded(*inner, unsafe); } + inline Iterator& operator++() { ++inner; return *this; } + + inline bool operator==(const Iterator& other) const { return inner == other.inner; } + inline bool operator!=(const Iterator& other) const { return inner != other.inner; } + + private: + typename Range::Iterator inner; + }; + + inline Iterator begin() const { return Iterator(inner.begin()); } + inline Iterator end() const { return Iterator(inner.end()); } + +private: + Range inner; +}; + +template +class Range> { +public: + inline constexpr Range(Quantity begin, Quantity end) + : inner(begin / unit>(), end / unit>()) {} + inline explicit constexpr Range(Quantity end) + : inner(end / unit>()) {} + + class Iterator { + public: + Iterator() = default; + inline explicit Iterator(typename Range::Iterator inner): inner(inner) {} + + inline Quantity operator* () const { return *inner * unit>(); } + inline Iterator& operator++() { ++inner; return *this; } + + inline bool operator==(const Iterator& other) const { return inner == other.inner; } + inline bool operator!=(const Iterator& other) const { return inner != other.inner; } + + private: + typename Range::Iterator inner; + }; + + inline Iterator begin() const { return Iterator(inner.begin()); } + inline Iterator end() const { return Iterator(inner.end()); } + +private: + Range inner; +}; + +template +inline constexpr Range> zeroTo(BoundedConst end) { + return Range>(end); +} + +template +inline constexpr Range, Unit>> + zeroTo(Quantity, Unit> end) { + return Range, Unit>>(end); +} + +} // namespace kj + +KJ_END_HEADER diff --git a/vendor/capnproto/src/kj/vector.h b/vendor/capnproto/src/kj/vector.h new file mode 100644 index 0000000..d072448 --- /dev/null +++ b/vendor/capnproto/src/kj/vector.h @@ -0,0 +1,153 @@ +// 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. + +#pragma once + +#include "array.h" + +KJ_BEGIN_HEADER + +namespace kj { + +template +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(capacity)) {} + inline Vector(Array&& array): builder(kj::mv(array)) {} + + inline operator ArrayPtr() KJ_LIFETIMEBOUND { return builder; } + inline operator ArrayPtr() const KJ_LIFETIMEBOUND { return builder; } + inline ArrayPtr asPtr() KJ_LIFETIMEBOUND { return builder.asPtr(); } + inline ArrayPtr asPtr() const KJ_LIFETIMEBOUND { 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) KJ_LIFETIMEBOUND { return builder[index]; } + inline const T& operator[](size_t index) const KJ_LIFETIMEBOUND { return builder[index]; } + + inline const T* begin() const KJ_LIFETIMEBOUND { return builder.begin(); } + inline const T* end() const KJ_LIFETIMEBOUND { return builder.end(); } + inline const T& front() const KJ_LIFETIMEBOUND { return builder.front(); } + inline const T& back() const KJ_LIFETIMEBOUND { return builder.back(); } + inline T* begin() KJ_LIFETIMEBOUND { return builder.begin(); } + inline T* end() KJ_LIFETIMEBOUND { return builder.end(); } + inline T& front() KJ_LIFETIMEBOUND { return builder.front(); } + inline T& back() KJ_LIFETIMEBOUND { return builder.back(); } + + inline Array releaseAsArray() { + // TODO(perf): Avoid a copy/move by allowing Array to point to incomplete space? + if (!builder.isFull()) { + setCapacity(size()); + } + return builder.finish(); + } + + template + inline bool operator==(const U& other) const { return asPtr() == other; } + template + inline bool operator!=(const U& other) const { return asPtr() != other; } + + inline ArrayPtr slice(size_t start, size_t end) KJ_LIFETIMEBOUND { + return asPtr().slice(start, end); + } + inline ArrayPtr slice(size_t start, size_t end) const KJ_LIFETIMEBOUND { + return asPtr().slice(start, end); + } + + template + inline T& add(Params&&... params) KJ_LIFETIMEBOUND { + if (builder.isFull()) grow(); + return builder.add(kj::fwd(params)...); + } + + template + 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 + 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() { + builder.clear(); + } + + inline void truncate(size_t size) { + builder.truncate(size); + } + + inline void reserve(size_t size) { + if (size > builder.capacity()) { + grow(size); + } + } + +private: + ArrayBuilder 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 newBuilder = heapArrayBuilder(newSize); + newBuilder.addAll(kj::mv(builder)); + builder = kj::mv(newBuilder); + } +}; + +template +inline auto KJ_STRINGIFY(const Vector& v) -> decltype(toCharSequence(v.asPtr())) { + return toCharSequence(v.asPtr()); +} + +} // namespace kj + +KJ_END_HEADER