diff win32-mingw/include/capnp/schema.h @ 149:279b18cc7785

Update Win32 capnp builds to v0.6
author Chris Cannam <cannam@all-day-breakfast.com>
date Tue, 23 May 2017 09:16:54 +0100
parents 38d1c0e7850b
children
line wrap: on
line diff
--- a/win32-mingw/include/capnp/schema.h	Mon May 22 18:56:49 2017 +0100
+++ b/win32-mingw/include/capnp/schema.h	Tue May 23 09:16:54 2017 +0100
@@ -1,934 +1,934 @@
-// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
-// Licensed under the MIT License:
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#ifndef CAPNP_SCHEMA_H_
-#define CAPNP_SCHEMA_H_
-
-#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
-#pragma GCC system_header
-#endif
-
-#if CAPNP_LITE
-#error "Reflection APIs, including this header, are not available in lite mode."
-#endif
-
-#include <capnp/schema.capnp.h>
-
-namespace capnp {
-
-class Schema;
-class StructSchema;
-class EnumSchema;
-class InterfaceSchema;
-class ConstSchema;
-class ListSchema;
-class Type;
-
-template <typename T, Kind k = kind<T>()> struct SchemaType_ { typedef Schema Type; };
-template <typename T> struct SchemaType_<T, Kind::PRIMITIVE> { typedef schema::Type::Which Type; };
-template <typename T> struct SchemaType_<T, Kind::BLOB> { typedef schema::Type::Which Type; };
-template <typename T> struct SchemaType_<T, Kind::ENUM> { typedef EnumSchema Type; };
-template <typename T> struct SchemaType_<T, Kind::STRUCT> { typedef StructSchema Type; };
-template <typename T> struct SchemaType_<T, Kind::INTERFACE> { typedef InterfaceSchema Type; };
-template <typename T> struct SchemaType_<T, Kind::LIST> { typedef ListSchema Type; };
-
-template <typename T>
-using SchemaType = typename SchemaType_<T>::Type;
-// SchemaType<T> is the type of T's schema, e.g. StructSchema if T is a struct.
-
-namespace _ {  // private
-extern const RawSchema NULL_SCHEMA;
-extern const RawSchema NULL_STRUCT_SCHEMA;
-extern const RawSchema NULL_ENUM_SCHEMA;
-extern const RawSchema NULL_INTERFACE_SCHEMA;
-extern const RawSchema NULL_CONST_SCHEMA;
-// The schema types default to these null (empty) schemas in case of error, especially when
-// exceptions are disabled.
-}  // namespace _ (private)
-
-class Schema {
-  // Convenience wrapper around capnp::schema::Node.
-
-public:
-  inline Schema(): raw(&_::NULL_SCHEMA.defaultBrand) {}
-
-  template <typename T>
-  static inline SchemaType<T> from() { return SchemaType<T>::template fromImpl<T>(); }
-  // Get the Schema for a particular compiled-in type.
-
-  schema::Node::Reader getProto() const;
-  // Get the underlying Cap'n Proto representation of the schema node.  (Note that this accessor
-  // has performance comparable to accessors of struct-typed fields on Reader classes.)
-
-  kj::ArrayPtr<const word> asUncheckedMessage() const;
-  // Get the encoded schema node content as a single message segment.  It is safe to read as an
-  // unchecked message.
-
-  Schema getDependency(uint64_t id) const KJ_DEPRECATED("Does not handle generics correctly.");
-  // DEPRECATED: This method cannot correctly account for generic type parameter bindings that
-  //   may apply to the dependency. Instead of using this method, use a method of the Schema API
-  //   that corresponds to the exact kind of dependency. For example, to get a field type, use
-  //   StructSchema::Field::getType().
-  //
-  // Gets the Schema for one of this Schema's dependencies.  For example, if this Schema is for a
-  // struct, you could look up the schema for one of its fields' types.  Throws an exception if this
-  // schema doesn't actually depend on the given id.
-  //
-  // Note that not all type IDs found in the schema node are considered "dependencies" -- only the
-  // ones that are needed to implement the dynamic API are.  That includes:
-  // - Field types.
-  // - Group types.
-  // - scopeId for group nodes, but NOT otherwise.
-  // - Method parameter and return types.
-  //
-  // The following are NOT considered dependencies:
-  // - Nested nodes.
-  // - scopeId for a non-group node.
-  // - Annotations.
-  //
-  // To obtain schemas for those, you would need a SchemaLoader.
-
-  bool isBranded() const;
-  // Returns true if this schema represents a non-default parameterization of this type.
-
-  Schema getGeneric() const;
-  // Get the version of this schema with any brands removed.
-
-  class BrandArgumentList;
-  BrandArgumentList getBrandArgumentsAtScope(uint64_t scopeId) const;
-  // Gets the values bound to the brand parameters at the given scope.
-
-  StructSchema asStruct() const;
-  EnumSchema asEnum() const;
-  InterfaceSchema asInterface() const;
-  ConstSchema asConst() const;
-  // Cast the Schema to a specific type.  Throws an exception if the type doesn't match.  Use
-  // getProto() to determine type, e.g. getProto().isStruct().
-
-  inline bool operator==(const Schema& other) const { return raw == other.raw; }
-  inline bool operator!=(const Schema& other) const { return raw != other.raw; }
-  // Determine whether two Schemas are wrapping the exact same underlying data, by identity.  If
-  // you want to check if two Schemas represent the same type (but possibly different versions of
-  // it), compare their IDs instead.
-
-  template <typename T>
-  void requireUsableAs() const;
-  // Throws an exception if a value with this Schema cannot safely be cast to a native value of
-  // the given type.  This passes if either:
-  // - *this == from<T>()
-  // - This schema was loaded with SchemaLoader, the type ID matches typeId<T>(), and
-  //   loadCompiledTypeAndDependencies<T>() was called on the SchemaLoader.
-
-  kj::StringPtr getShortDisplayName() const;
-  // Get the short version of the node's display name.
-
-private:
-  const _::RawBrandedSchema* raw;
-
-  inline explicit Schema(const _::RawBrandedSchema* raw): raw(raw) {
-    KJ_IREQUIRE(raw->lazyInitializer == nullptr,
-        "Must call ensureInitialized() on RawSchema before constructing Schema.");
-  }
-
-  template <typename T> static inline Schema fromImpl() {
-    return Schema(&_::rawSchema<T>());
-  }
-
-  void requireUsableAs(const _::RawSchema* expected) const;
-
-  uint32_t getSchemaOffset(const schema::Value::Reader& value) const;
-
-  Type getBrandBinding(uint64_t scopeId, uint index) const;
-  // Look up the binding for a brand parameter used by this Schema. Returns `AnyPointer` if the
-  // parameter is not bound.
-  //
-  // TODO(someday): Public interface for iterating over all bindings?
-
-  Schema getDependency(uint64_t id, uint location) const;
-  // Look up schema for a particular dependency of this schema. `location` is the dependency
-  // location number as defined in _::RawBrandedSchema.
-
-  Type interpretType(schema::Type::Reader proto, uint location) const;
-  // Interpret a schema::Type in the given location within the schema, compiling it into a
-  // Type object.
-
-  friend class StructSchema;
-  friend class EnumSchema;
-  friend class InterfaceSchema;
-  friend class ConstSchema;
-  friend class ListSchema;
-  friend class SchemaLoader;
-  friend class Type;
-  friend kj::StringTree _::structString(
-      _::StructReader reader, const _::RawBrandedSchema& schema);
-  friend kj::String _::enumString(uint16_t value, const _::RawBrandedSchema& schema);
-};
-
-kj::StringPtr KJ_STRINGIFY(const Schema& schema);
-
-class Schema::BrandArgumentList {
-  // A list of generic parameter bindings for parameters of some particular type. Note that since
-  // parameters on an outer type apply to all inner types as well, a deeply-nested type can have
-  // multiple BrandArgumentLists that apply to it.
-  //
-  // A BrandArgumentList only represents the arguments that the client of the type specified. Since
-  // new parameters can be added over time, this list may not cover all defined parameters for the
-  // type. Missing parameters should be treated as AnyPointer. This class's implementation of
-  // operator[] already does this for you; out-of-bounds access will safely return AnyPointer.
-
-public:
-  inline BrandArgumentList(): scopeId(0), size_(0), bindings(nullptr) {}
-
-  inline uint size() const { return size_; }
-  Type operator[](uint index) const;
-
-  typedef _::IndexingIterator<const BrandArgumentList, Type> Iterator;
-  inline Iterator begin() const { return Iterator(this, 0); }
-  inline Iterator end() const { return Iterator(this, size()); }
-
-private:
-  uint64_t scopeId;
-  uint size_;
-  bool isUnbound;
-  const _::RawBrandedSchema::Binding* bindings;
-
-  inline BrandArgumentList(uint64_t scopeId, bool isUnbound)
-      : scopeId(scopeId), size_(0), isUnbound(isUnbound), bindings(nullptr) {}
-  inline BrandArgumentList(uint64_t scopeId, uint size,
-                           const _::RawBrandedSchema::Binding* bindings)
-      : scopeId(scopeId), size_(size), isUnbound(false), bindings(bindings) {}
-
-  friend class Schema;
-};
-
-// -------------------------------------------------------------------
-
-class StructSchema: public Schema {
-public:
-  inline StructSchema(): Schema(&_::NULL_STRUCT_SCHEMA.defaultBrand) {}
-
-  class Field;
-  class FieldList;
-  class FieldSubset;
-
-  FieldList getFields() const;
-  // List top-level fields of this struct.  This list will contain top-level groups (including
-  // named unions) but not the members of those groups.  The list does, however, contain the
-  // members of the unnamed union, if there is one.
-
-  FieldSubset getUnionFields() const;
-  // If the field contains an unnamed union, get a list of fields in the union, ordered by
-  // ordinal.  Since discriminant values are assigned sequentially by ordinal, you may index this
-  // list by discriminant value.
-
-  FieldSubset getNonUnionFields() const;
-  // Get the fields of this struct which are not in an unnamed union, ordered by ordinal.
-
-  kj::Maybe<Field> findFieldByName(kj::StringPtr name) const;
-  // Find the field with the given name, or return null if there is no such field.  If the struct
-  // contains an unnamed union, then this will find fields of that union in addition to fields
-  // of the outer struct, since they exist in the same namespace.  It will not, however, find
-  // members of groups (including named unions) -- you must first look up the group itself,
-  // then dig into its type.
-
-  Field getFieldByName(kj::StringPtr name) const;
-  // Like findFieldByName() but throws an exception on failure.
-
-  kj::Maybe<Field> getFieldByDiscriminant(uint16_t discriminant) const;
-  // Finds the field whose `discriminantValue` is equal to the given value, or returns null if
-  // there is no such field.  (If the schema does not represent a union or a struct containing
-  // an unnamed union, then this always returns null.)
-
-private:
-  StructSchema(Schema base): Schema(base) {}
-  template <typename T> static inline StructSchema fromImpl() {
-    return StructSchema(Schema(&_::rawBrandedSchema<T>()));
-  }
-  friend class Schema;
-  friend class Type;
-};
-
-class StructSchema::Field {
-public:
-  Field() = default;
-
-  inline schema::Field::Reader getProto() const { return proto; }
-  inline StructSchema getContainingStruct() const { return parent; }
-
-  inline uint getIndex() const { return index; }
-  // Get the index of this field within the containing struct or union.
-
-  Type getType() const;
-  // Get the type of this field. Note that this is preferred over getProto().getType() as this
-  // method will apply generics.
-
-  uint32_t getDefaultValueSchemaOffset() const;
-  // For struct, list, and object fields, returns the offset, in words, within the first segment of
-  // the struct's schema, where this field's default value pointer is located.  The schema is
-  // always stored as a single-segment unchecked message, which in turn means that the default
-  // value pointer itself can be treated as the root of an unchecked message -- if you know where
-  // to find it, which is what this method helps you with.
-  //
-  // For blobs, returns the offset of the beginning of the blob's content within the first segment
-  // of the struct's schema.
-  //
-  // This is primarily useful for code generators.  The C++ code generator, for example, embeds
-  // the entire schema as a raw word array within the generated code.  Of course, to implement
-  // field accessors, it needs access to those fields' default values.  Embedding separate copies
-  // of those default values would be redundant since they are already included in the schema, but
-  // seeking through the schema at runtime to find the default values would be ugly.  Instead,
-  // the code generator can use getDefaultValueSchemaOffset() to find the offset of the default
-  // value within the schema, and can simply apply that offset at runtime.
-  //
-  // If the above does not make sense, you probably don't need this method.
-
-  inline bool operator==(const Field& other) const;
-  inline bool operator!=(const Field& other) const { return !(*this == other); }
-
-private:
-  StructSchema parent;
-  uint index;
-  schema::Field::Reader proto;
-
-  inline Field(StructSchema parent, uint index, schema::Field::Reader proto)
-      : parent(parent), index(index), proto(proto) {}
-
-  friend class StructSchema;
-};
-
-kj::StringPtr KJ_STRINGIFY(const StructSchema::Field& field);
-
-class StructSchema::FieldList {
-public:
-  FieldList() = default;  // empty list
-
-  inline uint size() const { return list.size(); }
-  inline Field operator[](uint index) const { return Field(parent, index, list[index]); }
-
-  typedef _::IndexingIterator<const FieldList, Field> Iterator;
-  inline Iterator begin() const { return Iterator(this, 0); }
-  inline Iterator end() const { return Iterator(this, size()); }
-
-private:
-  StructSchema parent;
-  List<schema::Field>::Reader list;
-
-  inline FieldList(StructSchema parent, List<schema::Field>::Reader list)
-      : parent(parent), list(list) {}
-
-  friend class StructSchema;
-};
-
-class StructSchema::FieldSubset {
-public:
-  FieldSubset() = default;  // empty list
-
-  inline uint size() const { return size_; }
-  inline Field operator[](uint index) const {
-    return Field(parent, indices[index], list[indices[index]]);
-  }
-
-  typedef _::IndexingIterator<const FieldSubset, Field> Iterator;
-  inline Iterator begin() const { return Iterator(this, 0); }
-  inline Iterator end() const { return Iterator(this, size()); }
-
-private:
-  StructSchema parent;
-  List<schema::Field>::Reader list;
-  const uint16_t* indices;
-  uint size_;
-
-  inline FieldSubset(StructSchema parent, List<schema::Field>::Reader list,
-                     const uint16_t* indices, uint size)
-      : parent(parent), list(list), indices(indices), size_(size) {}
-
-  friend class StructSchema;
-};
-
-// -------------------------------------------------------------------
-
-class EnumSchema: public Schema {
-public:
-  inline EnumSchema(): Schema(&_::NULL_ENUM_SCHEMA.defaultBrand) {}
-
-  class Enumerant;
-  class EnumerantList;
-
-  EnumerantList getEnumerants() const;
-
-  kj::Maybe<Enumerant> findEnumerantByName(kj::StringPtr name) const;
-
-  Enumerant getEnumerantByName(kj::StringPtr name) const;
-  // Like findEnumerantByName() but throws an exception on failure.
-
-private:
-  EnumSchema(Schema base): Schema(base) {}
-  template <typename T> static inline EnumSchema fromImpl() {
-    return EnumSchema(Schema(&_::rawBrandedSchema<T>()));
-  }
-  friend class Schema;
-  friend class Type;
-};
-
-class EnumSchema::Enumerant {
-public:
-  Enumerant() = default;
-
-  inline schema::Enumerant::Reader getProto() const { return proto; }
-  inline EnumSchema getContainingEnum() const { return parent; }
-
-  inline uint16_t getOrdinal() const { return ordinal; }
-  inline uint getIndex() const { return ordinal; }
-
-  inline bool operator==(const Enumerant& other) const;
-  inline bool operator!=(const Enumerant& other) const { return !(*this == other); }
-
-private:
-  EnumSchema parent;
-  uint16_t ordinal;
-  schema::Enumerant::Reader proto;
-
-  inline Enumerant(EnumSchema parent, uint16_t ordinal, schema::Enumerant::Reader proto)
-      : parent(parent), ordinal(ordinal), proto(proto) {}
-
-  friend class EnumSchema;
-};
-
-class EnumSchema::EnumerantList {
-public:
-  EnumerantList() = default;  // empty list
-
-  inline uint size() const { return list.size(); }
-  inline Enumerant operator[](uint index) const { return Enumerant(parent, index, list[index]); }
-
-  typedef _::IndexingIterator<const EnumerantList, Enumerant> Iterator;
-  inline Iterator begin() const { return Iterator(this, 0); }
-  inline Iterator end() const { return Iterator(this, size()); }
-
-private:
-  EnumSchema parent;
-  List<schema::Enumerant>::Reader list;
-
-  inline EnumerantList(EnumSchema parent, List<schema::Enumerant>::Reader list)
-      : parent(parent), list(list) {}
-
-  friend class EnumSchema;
-};
-
-// -------------------------------------------------------------------
-
-class InterfaceSchema: public Schema {
-public:
-  inline InterfaceSchema(): Schema(&_::NULL_INTERFACE_SCHEMA.defaultBrand) {}
-
-  class Method;
-  class MethodList;
-
-  MethodList getMethods() const;
-
-  kj::Maybe<Method> findMethodByName(kj::StringPtr name) const;
-
-  Method getMethodByName(kj::StringPtr name) const;
-  // Like findMethodByName() but throws an exception on failure.
-
-  class SuperclassList;
-
-  SuperclassList getSuperclasses() const;
-  // Get the immediate superclasses of this type, after applying generics.
-
-  bool extends(InterfaceSchema other) const;
-  // Returns true if `other` is a superclass of this interface (including if `other == *this`).
-
-  kj::Maybe<InterfaceSchema> findSuperclass(uint64_t typeId) const;
-  // Find the superclass of this interface with the given type ID.  Returns null if the interface
-  // extends no such type.
-
-private:
-  InterfaceSchema(Schema base): Schema(base) {}
-  template <typename T> static inline InterfaceSchema fromImpl() {
-    return InterfaceSchema(Schema(&_::rawBrandedSchema<T>()));
-  }
-  friend class Schema;
-  friend class Type;
-
-  kj::Maybe<Method> findMethodByName(kj::StringPtr name, uint& counter) const;
-  bool extends(InterfaceSchema other, uint& counter) const;
-  kj::Maybe<InterfaceSchema> findSuperclass(uint64_t typeId, uint& counter) const;
-  // We protect against malicious schemas with large or cyclic hierarchies by cutting off the
-  // search when the counter reaches a threshold.
-};
-
-class InterfaceSchema::Method {
-public:
-  Method() = default;
-
-  inline schema::Method::Reader getProto() const { return proto; }
-  inline InterfaceSchema getContainingInterface() const { return parent; }
-
-  inline uint16_t getOrdinal() const { return ordinal; }
-  inline uint getIndex() const { return ordinal; }
-
-  StructSchema getParamType() const;
-  StructSchema getResultType() const;
-  // Get the parameter and result types, including substituting generic parameters.
-
-  inline bool operator==(const Method& other) const;
-  inline bool operator!=(const Method& other) const { return !(*this == other); }
-
-private:
-  InterfaceSchema parent;
-  uint16_t ordinal;
-  schema::Method::Reader proto;
-
-  inline Method(InterfaceSchema parent, uint16_t ordinal,
-                schema::Method::Reader proto)
-      : parent(parent), ordinal(ordinal), proto(proto) {}
-
-  friend class InterfaceSchema;
-};
-
-class InterfaceSchema::MethodList {
-public:
-  MethodList() = default;  // empty list
-
-  inline uint size() const { return list.size(); }
-  inline Method operator[](uint index) const { return Method(parent, index, list[index]); }
-
-  typedef _::IndexingIterator<const MethodList, Method> Iterator;
-  inline Iterator begin() const { return Iterator(this, 0); }
-  inline Iterator end() const { return Iterator(this, size()); }
-
-private:
-  InterfaceSchema parent;
-  List<schema::Method>::Reader list;
-
-  inline MethodList(InterfaceSchema parent, List<schema::Method>::Reader list)
-      : parent(parent), list(list) {}
-
-  friend class InterfaceSchema;
-};
-
-class InterfaceSchema::SuperclassList {
-public:
-  SuperclassList() = default;  // empty list
-
-  inline uint size() const { return list.size(); }
-  InterfaceSchema operator[](uint index) const;
-
-  typedef _::IndexingIterator<const SuperclassList, InterfaceSchema> Iterator;
-  inline Iterator begin() const { return Iterator(this, 0); }
-  inline Iterator end() const { return Iterator(this, size()); }
-
-private:
-  InterfaceSchema parent;
-  List<schema::Superclass>::Reader list;
-
-  inline SuperclassList(InterfaceSchema parent, List<schema::Superclass>::Reader list)
-      : parent(parent), list(list) {}
-
-  friend class InterfaceSchema;
-};
-
-// -------------------------------------------------------------------
-
-class ConstSchema: public Schema {
-  // Represents a constant declaration.
-  //
-  // `ConstSchema` can be implicitly cast to DynamicValue to read its value.
-
-public:
-  inline ConstSchema(): Schema(&_::NULL_CONST_SCHEMA.defaultBrand) {}
-
-  template <typename T>
-  ReaderFor<T> as() const;
-  // Read the constant's value.  This is a convenience method equivalent to casting the ConstSchema
-  // to a DynamicValue and then calling its `as<T>()` method.  For dependency reasons, this method
-  // is defined in <capnp/dynamic.h>, which you must #include explicitly.
-
-  uint32_t getValueSchemaOffset() const;
-  // Much like StructSchema::Field::getDefaultValueSchemaOffset(), if the constant has pointer
-  // type, this gets the offset from the beginning of the constant's schema node to a pointer
-  // representing the constant value.
-
-  Type getType() const;
-
-private:
-  ConstSchema(Schema base): Schema(base) {}
-  friend class Schema;
-};
-
-// -------------------------------------------------------------------
-
-class Type {
-public:
-  struct BrandParameter {
-    uint64_t scopeId;
-    uint index;
-  };
-  struct ImplicitParameter {
-    uint index;
-  };
-
-  inline Type();
-  inline Type(schema::Type::Which primitive);
-  inline Type(StructSchema schema);
-  inline Type(EnumSchema schema);
-  inline Type(InterfaceSchema schema);
-  inline Type(ListSchema schema);
-  inline Type(schema::Type::AnyPointer::Unconstrained::Which anyPointerKind);
-  inline Type(BrandParameter param);
-  inline Type(ImplicitParameter param);
-
-  template <typename T>
-  inline static Type from();
-
-  inline schema::Type::Which which() const;
-
-  StructSchema asStruct() const;
-  EnumSchema asEnum() const;
-  InterfaceSchema asInterface() const;
-  ListSchema asList() const;
-  // Each of these methods may only be called if which() returns the corresponding type.
-
-  kj::Maybe<BrandParameter> getBrandParameter() const;
-  // Only callable if which() returns ANY_POINTER. Returns null if the type is just a regular
-  // AnyPointer and not a parameter.
-
-  kj::Maybe<ImplicitParameter> getImplicitParameter() const;
-  // Only callable if which() returns ANY_POINTER. Returns null if the type is just a regular
-  // AnyPointer and not a parameter. "Implicit parameters" refer to type parameters on methods.
-
-  inline schema::Type::AnyPointer::Unconstrained::Which whichAnyPointerKind() const;
-  // Only callable if which() returns ANY_POINTER.
-
-  inline bool isVoid() const;
-  inline bool isBool() const;
-  inline bool isInt8() const;
-  inline bool isInt16() const;
-  inline bool isInt32() const;
-  inline bool isInt64() const;
-  inline bool isUInt8() const;
-  inline bool isUInt16() const;
-  inline bool isUInt32() const;
-  inline bool isUInt64() const;
-  inline bool isFloat32() const;
-  inline bool isFloat64() const;
-  inline bool isText() const;
-  inline bool isData() const;
-  inline bool isList() const;
-  inline bool isEnum() const;
-  inline bool isStruct() const;
-  inline bool isInterface() const;
-  inline bool isAnyPointer() const;
-
-  bool operator==(const Type& other) const;
-  inline bool operator!=(const Type& other) const { return !(*this == other); }
-
-  size_t hashCode() const;
-
-  inline Type wrapInList(uint depth = 1) const;
-  // Return the Type formed by wrapping this type in List() `depth` times.
-
-  inline Type(schema::Type::Which derived, const _::RawBrandedSchema* schema);
-  // For internal use.
-
-private:
-  schema::Type::Which baseType;  // type not including applications of List()
-  uint8_t listDepth;             // 0 for T, 1 for List(T), 2 for List(List(T)), ...
-
-  bool isImplicitParam;
-  // If true, this refers to an implicit method parameter. baseType must be ANY_POINTER, scopeId
-  // must be zero, and paramIndex indicates the parameter index.
-
-  union {
-    uint16_t paramIndex;
-    // If baseType is ANY_POINTER but this Type actually refers to a type parameter, this is the
-    // index of the parameter among the parameters at its scope, and `scopeId` below is the type ID
-    // of the scope where the parameter was defined.
-
-    schema::Type::AnyPointer::Unconstrained::Which anyPointerKind;
-    // If scopeId is zero and isImplicitParam is false.
-  };
-
-  union {
-    const _::RawBrandedSchema* schema;  // if type is struct, enum, interface...
-    uint64_t scopeId;  // if type is AnyPointer but it's actually a type parameter...
-  };
-
-  Type(schema::Type::Which baseType, uint8_t listDepth, const _::RawBrandedSchema* schema)
-      : baseType(baseType), listDepth(listDepth), schema(schema) {
-    KJ_IREQUIRE(baseType != schema::Type::ANY_POINTER);
-  }
-
-  void requireUsableAs(Type expected) const;
-
-  friend class ListSchema;  // only for requireUsableAs()
-};
-
-// -------------------------------------------------------------------
-
-class ListSchema {
-  // ListSchema is a little different because list types are not described by schema nodes.  So,
-  // ListSchema doesn't subclass Schema.
-
-public:
-  ListSchema() = default;
-
-  static ListSchema of(schema::Type::Which primitiveType);
-  static ListSchema of(StructSchema elementType);
-  static ListSchema of(EnumSchema elementType);
-  static ListSchema of(InterfaceSchema elementType);
-  static ListSchema of(ListSchema elementType);
-  static ListSchema of(Type elementType);
-  // Construct the schema for a list of the given type.
-
-  static ListSchema of(schema::Type::Reader elementType, Schema context)
-      KJ_DEPRECATED("Does not handle generics correctly.");
-  // DEPRECATED: This method cannot correctly account for generic type parameter bindings that
-  //   may apply to the input type. Instead of using this method, use a method of the Schema API
-  //   that corresponds to the exact kind of dependency. For example, to get a field type, use
-  //   StructSchema::Field::getType().
-  //
-  // Construct from an element type schema.  Requires a context which can handle getDependency()
-  // requests for any type ID found in the schema.
-
-  Type getElementType() const;
-
-  inline schema::Type::Which whichElementType() const;
-  // Get the element type's "which()".  ListSchema does not actually store a schema::Type::Reader
-  // describing the element type, but if it did, this would be equivalent to calling
-  // .getBody().which() on that type.
-
-  StructSchema getStructElementType() const;
-  EnumSchema getEnumElementType() const;
-  InterfaceSchema getInterfaceElementType() const;
-  ListSchema getListElementType() const;
-  // Get the schema for complex element types.  Each of these throws an exception if the element
-  // type is not of the requested kind.
-
-  inline bool operator==(const ListSchema& other) const { return elementType == other.elementType; }
-  inline bool operator!=(const ListSchema& other) const { return elementType != other.elementType; }
-
-  template <typename T>
-  void requireUsableAs() const;
-
-private:
-  Type elementType;
-
-  inline explicit ListSchema(Type elementType): elementType(elementType) {}
-
-  template <typename T>
-  struct FromImpl;
-  template <typename T> static inline ListSchema fromImpl() {
-    return FromImpl<T>::get();
-  }
-
-  void requireUsableAs(ListSchema expected) const;
-
-  friend class Schema;
-};
-
-// =======================================================================================
-// inline implementation
-
-template <> inline schema::Type::Which Schema::from<Void>() { return schema::Type::VOID; }
-template <> inline schema::Type::Which Schema::from<bool>() { return schema::Type::BOOL; }
-template <> inline schema::Type::Which Schema::from<int8_t>() { return schema::Type::INT8; }
-template <> inline schema::Type::Which Schema::from<int16_t>() { return schema::Type::INT16; }
-template <> inline schema::Type::Which Schema::from<int32_t>() { return schema::Type::INT32; }
-template <> inline schema::Type::Which Schema::from<int64_t>() { return schema::Type::INT64; }
-template <> inline schema::Type::Which Schema::from<uint8_t>() { return schema::Type::UINT8; }
-template <> inline schema::Type::Which Schema::from<uint16_t>() { return schema::Type::UINT16; }
-template <> inline schema::Type::Which Schema::from<uint32_t>() { return schema::Type::UINT32; }
-template <> inline schema::Type::Which Schema::from<uint64_t>() { return schema::Type::UINT64; }
-template <> inline schema::Type::Which Schema::from<float>() { return schema::Type::FLOAT32; }
-template <> inline schema::Type::Which Schema::from<double>() { return schema::Type::FLOAT64; }
-template <> inline schema::Type::Which Schema::from<Text>() { return schema::Type::TEXT; }
-template <> inline schema::Type::Which Schema::from<Data>() { return schema::Type::DATA; }
-
-inline Schema Schema::getDependency(uint64_t id) const {
-  return getDependency(id, 0);
-}
-
-inline bool Schema::isBranded() const {
-  return raw != &raw->generic->defaultBrand;
-}
-
-inline Schema Schema::getGeneric() const {
-  return Schema(&raw->generic->defaultBrand);
-}
-
-template <typename T>
-inline void Schema::requireUsableAs() const {
-  requireUsableAs(&_::rawSchema<T>());
-}
-
-inline bool StructSchema::Field::operator==(const Field& other) const {
-  return parent == other.parent && index == other.index;
-}
-inline bool EnumSchema::Enumerant::operator==(const Enumerant& other) const {
-  return parent == other.parent && ordinal == other.ordinal;
-}
-inline bool InterfaceSchema::Method::operator==(const Method& other) const {
-  return parent == other.parent && ordinal == other.ordinal;
-}
-
-inline ListSchema ListSchema::of(StructSchema elementType) {
-  return ListSchema(Type(elementType));
-}
-inline ListSchema ListSchema::of(EnumSchema elementType) {
-  return ListSchema(Type(elementType));
-}
-inline ListSchema ListSchema::of(InterfaceSchema elementType) {
-  return ListSchema(Type(elementType));
-}
-inline ListSchema ListSchema::of(ListSchema elementType) {
-  return ListSchema(Type(elementType));
-}
-inline ListSchema ListSchema::of(Type elementType) {
-  return ListSchema(elementType);
-}
-
-inline Type ListSchema::getElementType() const {
-  return elementType;
-}
-
-inline schema::Type::Which ListSchema::whichElementType() const {
-  return elementType.which();
-}
-
-inline StructSchema ListSchema::getStructElementType() const {
-  return elementType.asStruct();
-}
-
-inline EnumSchema ListSchema::getEnumElementType() const {
-  return elementType.asEnum();
-}
-
-inline InterfaceSchema ListSchema::getInterfaceElementType() const {
-  return elementType.asInterface();
-}
-
-inline ListSchema ListSchema::getListElementType() const {
-  return elementType.asList();
-}
-
-template <typename T>
-inline void ListSchema::requireUsableAs() const {
-  static_assert(kind<T>() == Kind::LIST,
-                "ListSchema::requireUsableAs<T>() requires T is a list type.");
-  requireUsableAs(Schema::from<T>());
-}
-
-inline void ListSchema::requireUsableAs(ListSchema expected) const {
-  elementType.requireUsableAs(expected.elementType);
-}
-
-template <typename T>
-struct ListSchema::FromImpl<List<T>> {
-  static inline ListSchema get() { return of(Schema::from<T>()); }
-};
-
-inline Type::Type(): baseType(schema::Type::VOID), listDepth(0), schema(nullptr) {}
-inline Type::Type(schema::Type::Which primitive)
-    : baseType(primitive), listDepth(0), isImplicitParam(false) {
-  KJ_IREQUIRE(primitive != schema::Type::STRUCT &&
-              primitive != schema::Type::ENUM &&
-              primitive != schema::Type::INTERFACE &&
-              primitive != schema::Type::LIST);
-  if (primitive == schema::Type::ANY_POINTER) {
-    scopeId = 0;
-    anyPointerKind = schema::Type::AnyPointer::Unconstrained::ANY_KIND;
-  } else {
-    schema = nullptr;
-  }
-}
-inline Type::Type(schema::Type::Which derived, const _::RawBrandedSchema* schema)
-    : baseType(derived), listDepth(0), isImplicitParam(false), schema(schema) {
-  KJ_IREQUIRE(derived == schema::Type::STRUCT ||
-              derived == schema::Type::ENUM ||
-              derived == schema::Type::INTERFACE);
-}
-
-inline Type::Type(StructSchema schema)
-    : baseType(schema::Type::STRUCT), listDepth(0), schema(schema.raw) {}
-inline Type::Type(EnumSchema schema)
-    : baseType(schema::Type::ENUM), listDepth(0), schema(schema.raw) {}
-inline Type::Type(InterfaceSchema schema)
-    : baseType(schema::Type::INTERFACE), listDepth(0), schema(schema.raw) {}
-inline Type::Type(ListSchema schema)
-    : Type(schema.getElementType()) { ++listDepth; }
-inline Type::Type(schema::Type::AnyPointer::Unconstrained::Which anyPointerKind)
-    : baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(false),
-      anyPointerKind(anyPointerKind), scopeId(0) {}
-inline Type::Type(BrandParameter param)
-    : baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(false),
-      paramIndex(param.index), scopeId(param.scopeId) {}
-inline Type::Type(ImplicitParameter param)
-    : baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(true),
-      paramIndex(param.index), scopeId(0) {}
-
-inline schema::Type::Which Type::which() const {
-  return listDepth > 0 ? schema::Type::LIST : baseType;
-}
-
-inline schema::Type::AnyPointer::Unconstrained::Which Type::whichAnyPointerKind() const {
-  KJ_IREQUIRE(baseType == schema::Type::ANY_POINTER);
-  return !isImplicitParam && scopeId == 0 ? anyPointerKind
-      : schema::Type::AnyPointer::Unconstrained::ANY_KIND;
-}
-
-template <typename T>
-inline Type Type::from() { return Type(Schema::from<T>()); }
-
-inline bool Type::isVoid   () const { return baseType == schema::Type::VOID     && listDepth == 0; }
-inline bool Type::isBool   () const { return baseType == schema::Type::BOOL     && listDepth == 0; }
-inline bool Type::isInt8   () const { return baseType == schema::Type::INT8     && listDepth == 0; }
-inline bool Type::isInt16  () const { return baseType == schema::Type::INT16    && listDepth == 0; }
-inline bool Type::isInt32  () const { return baseType == schema::Type::INT32    && listDepth == 0; }
-inline bool Type::isInt64  () const { return baseType == schema::Type::INT64    && listDepth == 0; }
-inline bool Type::isUInt8  () const { return baseType == schema::Type::UINT8    && listDepth == 0; }
-inline bool Type::isUInt16 () const { return baseType == schema::Type::UINT16   && listDepth == 0; }
-inline bool Type::isUInt32 () const { return baseType == schema::Type::UINT32   && listDepth == 0; }
-inline bool Type::isUInt64 () const { return baseType == schema::Type::UINT64   && listDepth == 0; }
-inline bool Type::isFloat32() const { return baseType == schema::Type::FLOAT32  && listDepth == 0; }
-inline bool Type::isFloat64() const { return baseType == schema::Type::FLOAT64  && listDepth == 0; }
-inline bool Type::isText   () const { return baseType == schema::Type::TEXT     && listDepth == 0; }
-inline bool Type::isData   () const { return baseType == schema::Type::DATA     && listDepth == 0; }
-inline bool Type::isList   () const { return listDepth > 0; }
-inline bool Type::isEnum   () const { return baseType == schema::Type::ENUM     && listDepth == 0; }
-inline bool Type::isStruct () const { return baseType == schema::Type::STRUCT   && listDepth == 0; }
-inline bool Type::isInterface() const {
-  return baseType == schema::Type::INTERFACE && listDepth == 0;
-}
-inline bool Type::isAnyPointer() const {
-  return baseType == schema::Type::ANY_POINTER && listDepth == 0;
-}
-
-inline Type Type::wrapInList(uint depth) const {
-  Type result = *this;
-  result.listDepth += depth;
-  return result;
-}
-
-}  // namespace capnp
-
-#endif  // CAPNP_SCHEMA_H_
+// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
+// Licensed under the MIT License:
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CAPNP_SCHEMA_H_
+#define CAPNP_SCHEMA_H_
+
+#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
+#pragma GCC system_header
+#endif
+
+#if CAPNP_LITE
+#error "Reflection APIs, including this header, are not available in lite mode."
+#endif
+
+#include <capnp/schema.capnp.h>
+
+namespace capnp {
+
+class Schema;
+class StructSchema;
+class EnumSchema;
+class InterfaceSchema;
+class ConstSchema;
+class ListSchema;
+class Type;
+
+template <typename T, Kind k = kind<T>()> struct SchemaType_ { typedef Schema Type; };
+template <typename T> struct SchemaType_<T, Kind::PRIMITIVE> { typedef schema::Type::Which Type; };
+template <typename T> struct SchemaType_<T, Kind::BLOB> { typedef schema::Type::Which Type; };
+template <typename T> struct SchemaType_<T, Kind::ENUM> { typedef EnumSchema Type; };
+template <typename T> struct SchemaType_<T, Kind::STRUCT> { typedef StructSchema Type; };
+template <typename T> struct SchemaType_<T, Kind::INTERFACE> { typedef InterfaceSchema Type; };
+template <typename T> struct SchemaType_<T, Kind::LIST> { typedef ListSchema Type; };
+
+template <typename T>
+using SchemaType = typename SchemaType_<T>::Type;
+// SchemaType<T> is the type of T's schema, e.g. StructSchema if T is a struct.
+
+namespace _ {  // private
+extern const RawSchema NULL_SCHEMA;
+extern const RawSchema NULL_STRUCT_SCHEMA;
+extern const RawSchema NULL_ENUM_SCHEMA;
+extern const RawSchema NULL_INTERFACE_SCHEMA;
+extern const RawSchema NULL_CONST_SCHEMA;
+// The schema types default to these null (empty) schemas in case of error, especially when
+// exceptions are disabled.
+}  // namespace _ (private)
+
+class Schema {
+  // Convenience wrapper around capnp::schema::Node.
+
+public:
+  inline Schema(): raw(&_::NULL_SCHEMA.defaultBrand) {}
+
+  template <typename T>
+  static inline SchemaType<T> from() { return SchemaType<T>::template fromImpl<T>(); }
+  // Get the Schema for a particular compiled-in type.
+
+  schema::Node::Reader getProto() const;
+  // Get the underlying Cap'n Proto representation of the schema node.  (Note that this accessor
+  // has performance comparable to accessors of struct-typed fields on Reader classes.)
+
+  kj::ArrayPtr<const word> asUncheckedMessage() const;
+  // Get the encoded schema node content as a single message segment.  It is safe to read as an
+  // unchecked message.
+
+  Schema getDependency(uint64_t id) const KJ_DEPRECATED("Does not handle generics correctly.");
+  // DEPRECATED: This method cannot correctly account for generic type parameter bindings that
+  //   may apply to the dependency. Instead of using this method, use a method of the Schema API
+  //   that corresponds to the exact kind of dependency. For example, to get a field type, use
+  //   StructSchema::Field::getType().
+  //
+  // Gets the Schema for one of this Schema's dependencies.  For example, if this Schema is for a
+  // struct, you could look up the schema for one of its fields' types.  Throws an exception if this
+  // schema doesn't actually depend on the given id.
+  //
+  // Note that not all type IDs found in the schema node are considered "dependencies" -- only the
+  // ones that are needed to implement the dynamic API are.  That includes:
+  // - Field types.
+  // - Group types.
+  // - scopeId for group nodes, but NOT otherwise.
+  // - Method parameter and return types.
+  //
+  // The following are NOT considered dependencies:
+  // - Nested nodes.
+  // - scopeId for a non-group node.
+  // - Annotations.
+  //
+  // To obtain schemas for those, you would need a SchemaLoader.
+
+  bool isBranded() const;
+  // Returns true if this schema represents a non-default parameterization of this type.
+
+  Schema getGeneric() const;
+  // Get the version of this schema with any brands removed.
+
+  class BrandArgumentList;
+  BrandArgumentList getBrandArgumentsAtScope(uint64_t scopeId) const;
+  // Gets the values bound to the brand parameters at the given scope.
+
+  StructSchema asStruct() const;
+  EnumSchema asEnum() const;
+  InterfaceSchema asInterface() const;
+  ConstSchema asConst() const;
+  // Cast the Schema to a specific type.  Throws an exception if the type doesn't match.  Use
+  // getProto() to determine type, e.g. getProto().isStruct().
+
+  inline bool operator==(const Schema& other) const { return raw == other.raw; }
+  inline bool operator!=(const Schema& other) const { return raw != other.raw; }
+  // Determine whether two Schemas are wrapping the exact same underlying data, by identity.  If
+  // you want to check if two Schemas represent the same type (but possibly different versions of
+  // it), compare their IDs instead.
+
+  template <typename T>
+  void requireUsableAs() const;
+  // Throws an exception if a value with this Schema cannot safely be cast to a native value of
+  // the given type.  This passes if either:
+  // - *this == from<T>()
+  // - This schema was loaded with SchemaLoader, the type ID matches typeId<T>(), and
+  //   loadCompiledTypeAndDependencies<T>() was called on the SchemaLoader.
+
+  kj::StringPtr getShortDisplayName() const;
+  // Get the short version of the node's display name.
+
+private:
+  const _::RawBrandedSchema* raw;
+
+  inline explicit Schema(const _::RawBrandedSchema* raw): raw(raw) {
+    KJ_IREQUIRE(raw->lazyInitializer == nullptr,
+        "Must call ensureInitialized() on RawSchema before constructing Schema.");
+  }
+
+  template <typename T> static inline Schema fromImpl() {
+    return Schema(&_::rawSchema<T>());
+  }
+
+  void requireUsableAs(const _::RawSchema* expected) const;
+
+  uint32_t getSchemaOffset(const schema::Value::Reader& value) const;
+
+  Type getBrandBinding(uint64_t scopeId, uint index) const;
+  // Look up the binding for a brand parameter used by this Schema. Returns `AnyPointer` if the
+  // parameter is not bound.
+  //
+  // TODO(someday): Public interface for iterating over all bindings?
+
+  Schema getDependency(uint64_t id, uint location) const;
+  // Look up schema for a particular dependency of this schema. `location` is the dependency
+  // location number as defined in _::RawBrandedSchema.
+
+  Type interpretType(schema::Type::Reader proto, uint location) const;
+  // Interpret a schema::Type in the given location within the schema, compiling it into a
+  // Type object.
+
+  friend class StructSchema;
+  friend class EnumSchema;
+  friend class InterfaceSchema;
+  friend class ConstSchema;
+  friend class ListSchema;
+  friend class SchemaLoader;
+  friend class Type;
+  friend kj::StringTree _::structString(
+      _::StructReader reader, const _::RawBrandedSchema& schema);
+  friend kj::String _::enumString(uint16_t value, const _::RawBrandedSchema& schema);
+};
+
+kj::StringPtr KJ_STRINGIFY(const Schema& schema);
+
+class Schema::BrandArgumentList {
+  // A list of generic parameter bindings for parameters of some particular type. Note that since
+  // parameters on an outer type apply to all inner types as well, a deeply-nested type can have
+  // multiple BrandArgumentLists that apply to it.
+  //
+  // A BrandArgumentList only represents the arguments that the client of the type specified. Since
+  // new parameters can be added over time, this list may not cover all defined parameters for the
+  // type. Missing parameters should be treated as AnyPointer. This class's implementation of
+  // operator[] already does this for you; out-of-bounds access will safely return AnyPointer.
+
+public:
+  inline BrandArgumentList(): scopeId(0), size_(0), bindings(nullptr) {}
+
+  inline uint size() const { return size_; }
+  Type operator[](uint index) const;
+
+  typedef _::IndexingIterator<const BrandArgumentList, Type> Iterator;
+  inline Iterator begin() const { return Iterator(this, 0); }
+  inline Iterator end() const { return Iterator(this, size()); }
+
+private:
+  uint64_t scopeId;
+  uint size_;
+  bool isUnbound;
+  const _::RawBrandedSchema::Binding* bindings;
+
+  inline BrandArgumentList(uint64_t scopeId, bool isUnbound)
+      : scopeId(scopeId), size_(0), isUnbound(isUnbound), bindings(nullptr) {}
+  inline BrandArgumentList(uint64_t scopeId, uint size,
+                           const _::RawBrandedSchema::Binding* bindings)
+      : scopeId(scopeId), size_(size), isUnbound(false), bindings(bindings) {}
+
+  friend class Schema;
+};
+
+// -------------------------------------------------------------------
+
+class StructSchema: public Schema {
+public:
+  inline StructSchema(): Schema(&_::NULL_STRUCT_SCHEMA.defaultBrand) {}
+
+  class Field;
+  class FieldList;
+  class FieldSubset;
+
+  FieldList getFields() const;
+  // List top-level fields of this struct.  This list will contain top-level groups (including
+  // named unions) but not the members of those groups.  The list does, however, contain the
+  // members of the unnamed union, if there is one.
+
+  FieldSubset getUnionFields() const;
+  // If the field contains an unnamed union, get a list of fields in the union, ordered by
+  // ordinal.  Since discriminant values are assigned sequentially by ordinal, you may index this
+  // list by discriminant value.
+
+  FieldSubset getNonUnionFields() const;
+  // Get the fields of this struct which are not in an unnamed union, ordered by ordinal.
+
+  kj::Maybe<Field> findFieldByName(kj::StringPtr name) const;
+  // Find the field with the given name, or return null if there is no such field.  If the struct
+  // contains an unnamed union, then this will find fields of that union in addition to fields
+  // of the outer struct, since they exist in the same namespace.  It will not, however, find
+  // members of groups (including named unions) -- you must first look up the group itself,
+  // then dig into its type.
+
+  Field getFieldByName(kj::StringPtr name) const;
+  // Like findFieldByName() but throws an exception on failure.
+
+  kj::Maybe<Field> getFieldByDiscriminant(uint16_t discriminant) const;
+  // Finds the field whose `discriminantValue` is equal to the given value, or returns null if
+  // there is no such field.  (If the schema does not represent a union or a struct containing
+  // an unnamed union, then this always returns null.)
+
+private:
+  StructSchema(Schema base): Schema(base) {}
+  template <typename T> static inline StructSchema fromImpl() {
+    return StructSchema(Schema(&_::rawBrandedSchema<T>()));
+  }
+  friend class Schema;
+  friend class Type;
+};
+
+class StructSchema::Field {
+public:
+  Field() = default;
+
+  inline schema::Field::Reader getProto() const { return proto; }
+  inline StructSchema getContainingStruct() const { return parent; }
+
+  inline uint getIndex() const { return index; }
+  // Get the index of this field within the containing struct or union.
+
+  Type getType() const;
+  // Get the type of this field. Note that this is preferred over getProto().getType() as this
+  // method will apply generics.
+
+  uint32_t getDefaultValueSchemaOffset() const;
+  // For struct, list, and object fields, returns the offset, in words, within the first segment of
+  // the struct's schema, where this field's default value pointer is located.  The schema is
+  // always stored as a single-segment unchecked message, which in turn means that the default
+  // value pointer itself can be treated as the root of an unchecked message -- if you know where
+  // to find it, which is what this method helps you with.
+  //
+  // For blobs, returns the offset of the beginning of the blob's content within the first segment
+  // of the struct's schema.
+  //
+  // This is primarily useful for code generators.  The C++ code generator, for example, embeds
+  // the entire schema as a raw word array within the generated code.  Of course, to implement
+  // field accessors, it needs access to those fields' default values.  Embedding separate copies
+  // of those default values would be redundant since they are already included in the schema, but
+  // seeking through the schema at runtime to find the default values would be ugly.  Instead,
+  // the code generator can use getDefaultValueSchemaOffset() to find the offset of the default
+  // value within the schema, and can simply apply that offset at runtime.
+  //
+  // If the above does not make sense, you probably don't need this method.
+
+  inline bool operator==(const Field& other) const;
+  inline bool operator!=(const Field& other) const { return !(*this == other); }
+
+private:
+  StructSchema parent;
+  uint index;
+  schema::Field::Reader proto;
+
+  inline Field(StructSchema parent, uint index, schema::Field::Reader proto)
+      : parent(parent), index(index), proto(proto) {}
+
+  friend class StructSchema;
+};
+
+kj::StringPtr KJ_STRINGIFY(const StructSchema::Field& field);
+
+class StructSchema::FieldList {
+public:
+  FieldList() = default;  // empty list
+
+  inline uint size() const { return list.size(); }
+  inline Field operator[](uint index) const { return Field(parent, index, list[index]); }
+
+  typedef _::IndexingIterator<const FieldList, Field> Iterator;
+  inline Iterator begin() const { return Iterator(this, 0); }
+  inline Iterator end() const { return Iterator(this, size()); }
+
+private:
+  StructSchema parent;
+  List<schema::Field>::Reader list;
+
+  inline FieldList(StructSchema parent, List<schema::Field>::Reader list)
+      : parent(parent), list(list) {}
+
+  friend class StructSchema;
+};
+
+class StructSchema::FieldSubset {
+public:
+  FieldSubset() = default;  // empty list
+
+  inline uint size() const { return size_; }
+  inline Field operator[](uint index) const {
+    return Field(parent, indices[index], list[indices[index]]);
+  }
+
+  typedef _::IndexingIterator<const FieldSubset, Field> Iterator;
+  inline Iterator begin() const { return Iterator(this, 0); }
+  inline Iterator end() const { return Iterator(this, size()); }
+
+private:
+  StructSchema parent;
+  List<schema::Field>::Reader list;
+  const uint16_t* indices;
+  uint size_;
+
+  inline FieldSubset(StructSchema parent, List<schema::Field>::Reader list,
+                     const uint16_t* indices, uint size)
+      : parent(parent), list(list), indices(indices), size_(size) {}
+
+  friend class StructSchema;
+};
+
+// -------------------------------------------------------------------
+
+class EnumSchema: public Schema {
+public:
+  inline EnumSchema(): Schema(&_::NULL_ENUM_SCHEMA.defaultBrand) {}
+
+  class Enumerant;
+  class EnumerantList;
+
+  EnumerantList getEnumerants() const;
+
+  kj::Maybe<Enumerant> findEnumerantByName(kj::StringPtr name) const;
+
+  Enumerant getEnumerantByName(kj::StringPtr name) const;
+  // Like findEnumerantByName() but throws an exception on failure.
+
+private:
+  EnumSchema(Schema base): Schema(base) {}
+  template <typename T> static inline EnumSchema fromImpl() {
+    return EnumSchema(Schema(&_::rawBrandedSchema<T>()));
+  }
+  friend class Schema;
+  friend class Type;
+};
+
+class EnumSchema::Enumerant {
+public:
+  Enumerant() = default;
+
+  inline schema::Enumerant::Reader getProto() const { return proto; }
+  inline EnumSchema getContainingEnum() const { return parent; }
+
+  inline uint16_t getOrdinal() const { return ordinal; }
+  inline uint getIndex() const { return ordinal; }
+
+  inline bool operator==(const Enumerant& other) const;
+  inline bool operator!=(const Enumerant& other) const { return !(*this == other); }
+
+private:
+  EnumSchema parent;
+  uint16_t ordinal;
+  schema::Enumerant::Reader proto;
+
+  inline Enumerant(EnumSchema parent, uint16_t ordinal, schema::Enumerant::Reader proto)
+      : parent(parent), ordinal(ordinal), proto(proto) {}
+
+  friend class EnumSchema;
+};
+
+class EnumSchema::EnumerantList {
+public:
+  EnumerantList() = default;  // empty list
+
+  inline uint size() const { return list.size(); }
+  inline Enumerant operator[](uint index) const { return Enumerant(parent, index, list[index]); }
+
+  typedef _::IndexingIterator<const EnumerantList, Enumerant> Iterator;
+  inline Iterator begin() const { return Iterator(this, 0); }
+  inline Iterator end() const { return Iterator(this, size()); }
+
+private:
+  EnumSchema parent;
+  List<schema::Enumerant>::Reader list;
+
+  inline EnumerantList(EnumSchema parent, List<schema::Enumerant>::Reader list)
+      : parent(parent), list(list) {}
+
+  friend class EnumSchema;
+};
+
+// -------------------------------------------------------------------
+
+class InterfaceSchema: public Schema {
+public:
+  inline InterfaceSchema(): Schema(&_::NULL_INTERFACE_SCHEMA.defaultBrand) {}
+
+  class Method;
+  class MethodList;
+
+  MethodList getMethods() const;
+
+  kj::Maybe<Method> findMethodByName(kj::StringPtr name) const;
+
+  Method getMethodByName(kj::StringPtr name) const;
+  // Like findMethodByName() but throws an exception on failure.
+
+  class SuperclassList;
+
+  SuperclassList getSuperclasses() const;
+  // Get the immediate superclasses of this type, after applying generics.
+
+  bool extends(InterfaceSchema other) const;
+  // Returns true if `other` is a superclass of this interface (including if `other == *this`).
+
+  kj::Maybe<InterfaceSchema> findSuperclass(uint64_t typeId) const;
+  // Find the superclass of this interface with the given type ID.  Returns null if the interface
+  // extends no such type.
+
+private:
+  InterfaceSchema(Schema base): Schema(base) {}
+  template <typename T> static inline InterfaceSchema fromImpl() {
+    return InterfaceSchema(Schema(&_::rawBrandedSchema<T>()));
+  }
+  friend class Schema;
+  friend class Type;
+
+  kj::Maybe<Method> findMethodByName(kj::StringPtr name, uint& counter) const;
+  bool extends(InterfaceSchema other, uint& counter) const;
+  kj::Maybe<InterfaceSchema> findSuperclass(uint64_t typeId, uint& counter) const;
+  // We protect against malicious schemas with large or cyclic hierarchies by cutting off the
+  // search when the counter reaches a threshold.
+};
+
+class InterfaceSchema::Method {
+public:
+  Method() = default;
+
+  inline schema::Method::Reader getProto() const { return proto; }
+  inline InterfaceSchema getContainingInterface() const { return parent; }
+
+  inline uint16_t getOrdinal() const { return ordinal; }
+  inline uint getIndex() const { return ordinal; }
+
+  StructSchema getParamType() const;
+  StructSchema getResultType() const;
+  // Get the parameter and result types, including substituting generic parameters.
+
+  inline bool operator==(const Method& other) const;
+  inline bool operator!=(const Method& other) const { return !(*this == other); }
+
+private:
+  InterfaceSchema parent;
+  uint16_t ordinal;
+  schema::Method::Reader proto;
+
+  inline Method(InterfaceSchema parent, uint16_t ordinal,
+                schema::Method::Reader proto)
+      : parent(parent), ordinal(ordinal), proto(proto) {}
+
+  friend class InterfaceSchema;
+};
+
+class InterfaceSchema::MethodList {
+public:
+  MethodList() = default;  // empty list
+
+  inline uint size() const { return list.size(); }
+  inline Method operator[](uint index) const { return Method(parent, index, list[index]); }
+
+  typedef _::IndexingIterator<const MethodList, Method> Iterator;
+  inline Iterator begin() const { return Iterator(this, 0); }
+  inline Iterator end() const { return Iterator(this, size()); }
+
+private:
+  InterfaceSchema parent;
+  List<schema::Method>::Reader list;
+
+  inline MethodList(InterfaceSchema parent, List<schema::Method>::Reader list)
+      : parent(parent), list(list) {}
+
+  friend class InterfaceSchema;
+};
+
+class InterfaceSchema::SuperclassList {
+public:
+  SuperclassList() = default;  // empty list
+
+  inline uint size() const { return list.size(); }
+  InterfaceSchema operator[](uint index) const;
+
+  typedef _::IndexingIterator<const SuperclassList, InterfaceSchema> Iterator;
+  inline Iterator begin() const { return Iterator(this, 0); }
+  inline Iterator end() const { return Iterator(this, size()); }
+
+private:
+  InterfaceSchema parent;
+  List<schema::Superclass>::Reader list;
+
+  inline SuperclassList(InterfaceSchema parent, List<schema::Superclass>::Reader list)
+      : parent(parent), list(list) {}
+
+  friend class InterfaceSchema;
+};
+
+// -------------------------------------------------------------------
+
+class ConstSchema: public Schema {
+  // Represents a constant declaration.
+  //
+  // `ConstSchema` can be implicitly cast to DynamicValue to read its value.
+
+public:
+  inline ConstSchema(): Schema(&_::NULL_CONST_SCHEMA.defaultBrand) {}
+
+  template <typename T>
+  ReaderFor<T> as() const;
+  // Read the constant's value.  This is a convenience method equivalent to casting the ConstSchema
+  // to a DynamicValue and then calling its `as<T>()` method.  For dependency reasons, this method
+  // is defined in <capnp/dynamic.h>, which you must #include explicitly.
+
+  uint32_t getValueSchemaOffset() const;
+  // Much like StructSchema::Field::getDefaultValueSchemaOffset(), if the constant has pointer
+  // type, this gets the offset from the beginning of the constant's schema node to a pointer
+  // representing the constant value.
+
+  Type getType() const;
+
+private:
+  ConstSchema(Schema base): Schema(base) {}
+  friend class Schema;
+};
+
+// -------------------------------------------------------------------
+
+class Type {
+public:
+  struct BrandParameter {
+    uint64_t scopeId;
+    uint index;
+  };
+  struct ImplicitParameter {
+    uint index;
+  };
+
+  inline Type();
+  inline Type(schema::Type::Which primitive);
+  inline Type(StructSchema schema);
+  inline Type(EnumSchema schema);
+  inline Type(InterfaceSchema schema);
+  inline Type(ListSchema schema);
+  inline Type(schema::Type::AnyPointer::Unconstrained::Which anyPointerKind);
+  inline Type(BrandParameter param);
+  inline Type(ImplicitParameter param);
+
+  template <typename T>
+  inline static Type from();
+
+  inline schema::Type::Which which() const;
+
+  StructSchema asStruct() const;
+  EnumSchema asEnum() const;
+  InterfaceSchema asInterface() const;
+  ListSchema asList() const;
+  // Each of these methods may only be called if which() returns the corresponding type.
+
+  kj::Maybe<BrandParameter> getBrandParameter() const;
+  // Only callable if which() returns ANY_POINTER. Returns null if the type is just a regular
+  // AnyPointer and not a parameter.
+
+  kj::Maybe<ImplicitParameter> getImplicitParameter() const;
+  // Only callable if which() returns ANY_POINTER. Returns null if the type is just a regular
+  // AnyPointer and not a parameter. "Implicit parameters" refer to type parameters on methods.
+
+  inline schema::Type::AnyPointer::Unconstrained::Which whichAnyPointerKind() const;
+  // Only callable if which() returns ANY_POINTER.
+
+  inline bool isVoid() const;
+  inline bool isBool() const;
+  inline bool isInt8() const;
+  inline bool isInt16() const;
+  inline bool isInt32() const;
+  inline bool isInt64() const;
+  inline bool isUInt8() const;
+  inline bool isUInt16() const;
+  inline bool isUInt32() const;
+  inline bool isUInt64() const;
+  inline bool isFloat32() const;
+  inline bool isFloat64() const;
+  inline bool isText() const;
+  inline bool isData() const;
+  inline bool isList() const;
+  inline bool isEnum() const;
+  inline bool isStruct() const;
+  inline bool isInterface() const;
+  inline bool isAnyPointer() const;
+
+  bool operator==(const Type& other) const;
+  inline bool operator!=(const Type& other) const { return !(*this == other); }
+
+  size_t hashCode() const;
+
+  inline Type wrapInList(uint depth = 1) const;
+  // Return the Type formed by wrapping this type in List() `depth` times.
+
+  inline Type(schema::Type::Which derived, const _::RawBrandedSchema* schema);
+  // For internal use.
+
+private:
+  schema::Type::Which baseType;  // type not including applications of List()
+  uint8_t listDepth;             // 0 for T, 1 for List(T), 2 for List(List(T)), ...
+
+  bool isImplicitParam;
+  // If true, this refers to an implicit method parameter. baseType must be ANY_POINTER, scopeId
+  // must be zero, and paramIndex indicates the parameter index.
+
+  union {
+    uint16_t paramIndex;
+    // If baseType is ANY_POINTER but this Type actually refers to a type parameter, this is the
+    // index of the parameter among the parameters at its scope, and `scopeId` below is the type ID
+    // of the scope where the parameter was defined.
+
+    schema::Type::AnyPointer::Unconstrained::Which anyPointerKind;
+    // If scopeId is zero and isImplicitParam is false.
+  };
+
+  union {
+    const _::RawBrandedSchema* schema;  // if type is struct, enum, interface...
+    uint64_t scopeId;  // if type is AnyPointer but it's actually a type parameter...
+  };
+
+  Type(schema::Type::Which baseType, uint8_t listDepth, const _::RawBrandedSchema* schema)
+      : baseType(baseType), listDepth(listDepth), schema(schema) {
+    KJ_IREQUIRE(baseType != schema::Type::ANY_POINTER);
+  }
+
+  void requireUsableAs(Type expected) const;
+
+  friend class ListSchema;  // only for requireUsableAs()
+};
+
+// -------------------------------------------------------------------
+
+class ListSchema {
+  // ListSchema is a little different because list types are not described by schema nodes.  So,
+  // ListSchema doesn't subclass Schema.
+
+public:
+  ListSchema() = default;
+
+  static ListSchema of(schema::Type::Which primitiveType);
+  static ListSchema of(StructSchema elementType);
+  static ListSchema of(EnumSchema elementType);
+  static ListSchema of(InterfaceSchema elementType);
+  static ListSchema of(ListSchema elementType);
+  static ListSchema of(Type elementType);
+  // Construct the schema for a list of the given type.
+
+  static ListSchema of(schema::Type::Reader elementType, Schema context)
+      KJ_DEPRECATED("Does not handle generics correctly.");
+  // DEPRECATED: This method cannot correctly account for generic type parameter bindings that
+  //   may apply to the input type. Instead of using this method, use a method of the Schema API
+  //   that corresponds to the exact kind of dependency. For example, to get a field type, use
+  //   StructSchema::Field::getType().
+  //
+  // Construct from an element type schema.  Requires a context which can handle getDependency()
+  // requests for any type ID found in the schema.
+
+  Type getElementType() const;
+
+  inline schema::Type::Which whichElementType() const;
+  // Get the element type's "which()".  ListSchema does not actually store a schema::Type::Reader
+  // describing the element type, but if it did, this would be equivalent to calling
+  // .getBody().which() on that type.
+
+  StructSchema getStructElementType() const;
+  EnumSchema getEnumElementType() const;
+  InterfaceSchema getInterfaceElementType() const;
+  ListSchema getListElementType() const;
+  // Get the schema for complex element types.  Each of these throws an exception if the element
+  // type is not of the requested kind.
+
+  inline bool operator==(const ListSchema& other) const { return elementType == other.elementType; }
+  inline bool operator!=(const ListSchema& other) const { return elementType != other.elementType; }
+
+  template <typename T>
+  void requireUsableAs() const;
+
+private:
+  Type elementType;
+
+  inline explicit ListSchema(Type elementType): elementType(elementType) {}
+
+  template <typename T>
+  struct FromImpl;
+  template <typename T> static inline ListSchema fromImpl() {
+    return FromImpl<T>::get();
+  }
+
+  void requireUsableAs(ListSchema expected) const;
+
+  friend class Schema;
+};
+
+// =======================================================================================
+// inline implementation
+
+template <> inline schema::Type::Which Schema::from<Void>() { return schema::Type::VOID; }
+template <> inline schema::Type::Which Schema::from<bool>() { return schema::Type::BOOL; }
+template <> inline schema::Type::Which Schema::from<int8_t>() { return schema::Type::INT8; }
+template <> inline schema::Type::Which Schema::from<int16_t>() { return schema::Type::INT16; }
+template <> inline schema::Type::Which Schema::from<int32_t>() { return schema::Type::INT32; }
+template <> inline schema::Type::Which Schema::from<int64_t>() { return schema::Type::INT64; }
+template <> inline schema::Type::Which Schema::from<uint8_t>() { return schema::Type::UINT8; }
+template <> inline schema::Type::Which Schema::from<uint16_t>() { return schema::Type::UINT16; }
+template <> inline schema::Type::Which Schema::from<uint32_t>() { return schema::Type::UINT32; }
+template <> inline schema::Type::Which Schema::from<uint64_t>() { return schema::Type::UINT64; }
+template <> inline schema::Type::Which Schema::from<float>() { return schema::Type::FLOAT32; }
+template <> inline schema::Type::Which Schema::from<double>() { return schema::Type::FLOAT64; }
+template <> inline schema::Type::Which Schema::from<Text>() { return schema::Type::TEXT; }
+template <> inline schema::Type::Which Schema::from<Data>() { return schema::Type::DATA; }
+
+inline Schema Schema::getDependency(uint64_t id) const {
+  return getDependency(id, 0);
+}
+
+inline bool Schema::isBranded() const {
+  return raw != &raw->generic->defaultBrand;
+}
+
+inline Schema Schema::getGeneric() const {
+  return Schema(&raw->generic->defaultBrand);
+}
+
+template <typename T>
+inline void Schema::requireUsableAs() const {
+  requireUsableAs(&_::rawSchema<T>());
+}
+
+inline bool StructSchema::Field::operator==(const Field& other) const {
+  return parent == other.parent && index == other.index;
+}
+inline bool EnumSchema::Enumerant::operator==(const Enumerant& other) const {
+  return parent == other.parent && ordinal == other.ordinal;
+}
+inline bool InterfaceSchema::Method::operator==(const Method& other) const {
+  return parent == other.parent && ordinal == other.ordinal;
+}
+
+inline ListSchema ListSchema::of(StructSchema elementType) {
+  return ListSchema(Type(elementType));
+}
+inline ListSchema ListSchema::of(EnumSchema elementType) {
+  return ListSchema(Type(elementType));
+}
+inline ListSchema ListSchema::of(InterfaceSchema elementType) {
+  return ListSchema(Type(elementType));
+}
+inline ListSchema ListSchema::of(ListSchema elementType) {
+  return ListSchema(Type(elementType));
+}
+inline ListSchema ListSchema::of(Type elementType) {
+  return ListSchema(elementType);
+}
+
+inline Type ListSchema::getElementType() const {
+  return elementType;
+}
+
+inline schema::Type::Which ListSchema::whichElementType() const {
+  return elementType.which();
+}
+
+inline StructSchema ListSchema::getStructElementType() const {
+  return elementType.asStruct();
+}
+
+inline EnumSchema ListSchema::getEnumElementType() const {
+  return elementType.asEnum();
+}
+
+inline InterfaceSchema ListSchema::getInterfaceElementType() const {
+  return elementType.asInterface();
+}
+
+inline ListSchema ListSchema::getListElementType() const {
+  return elementType.asList();
+}
+
+template <typename T>
+inline void ListSchema::requireUsableAs() const {
+  static_assert(kind<T>() == Kind::LIST,
+                "ListSchema::requireUsableAs<T>() requires T is a list type.");
+  requireUsableAs(Schema::from<T>());
+}
+
+inline void ListSchema::requireUsableAs(ListSchema expected) const {
+  elementType.requireUsableAs(expected.elementType);
+}
+
+template <typename T>
+struct ListSchema::FromImpl<List<T>> {
+  static inline ListSchema get() { return of(Schema::from<T>()); }
+};
+
+inline Type::Type(): baseType(schema::Type::VOID), listDepth(0), schema(nullptr) {}
+inline Type::Type(schema::Type::Which primitive)
+    : baseType(primitive), listDepth(0), isImplicitParam(false) {
+  KJ_IREQUIRE(primitive != schema::Type::STRUCT &&
+              primitive != schema::Type::ENUM &&
+              primitive != schema::Type::INTERFACE &&
+              primitive != schema::Type::LIST);
+  if (primitive == schema::Type::ANY_POINTER) {
+    scopeId = 0;
+    anyPointerKind = schema::Type::AnyPointer::Unconstrained::ANY_KIND;
+  } else {
+    schema = nullptr;
+  }
+}
+inline Type::Type(schema::Type::Which derived, const _::RawBrandedSchema* schema)
+    : baseType(derived), listDepth(0), isImplicitParam(false), schema(schema) {
+  KJ_IREQUIRE(derived == schema::Type::STRUCT ||
+              derived == schema::Type::ENUM ||
+              derived == schema::Type::INTERFACE);
+}
+
+inline Type::Type(StructSchema schema)
+    : baseType(schema::Type::STRUCT), listDepth(0), schema(schema.raw) {}
+inline Type::Type(EnumSchema schema)
+    : baseType(schema::Type::ENUM), listDepth(0), schema(schema.raw) {}
+inline Type::Type(InterfaceSchema schema)
+    : baseType(schema::Type::INTERFACE), listDepth(0), schema(schema.raw) {}
+inline Type::Type(ListSchema schema)
+    : Type(schema.getElementType()) { ++listDepth; }
+inline Type::Type(schema::Type::AnyPointer::Unconstrained::Which anyPointerKind)
+    : baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(false),
+      anyPointerKind(anyPointerKind), scopeId(0) {}
+inline Type::Type(BrandParameter param)
+    : baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(false),
+      paramIndex(param.index), scopeId(param.scopeId) {}
+inline Type::Type(ImplicitParameter param)
+    : baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(true),
+      paramIndex(param.index), scopeId(0) {}
+
+inline schema::Type::Which Type::which() const {
+  return listDepth > 0 ? schema::Type::LIST : baseType;
+}
+
+inline schema::Type::AnyPointer::Unconstrained::Which Type::whichAnyPointerKind() const {
+  KJ_IREQUIRE(baseType == schema::Type::ANY_POINTER);
+  return !isImplicitParam && scopeId == 0 ? anyPointerKind
+      : schema::Type::AnyPointer::Unconstrained::ANY_KIND;
+}
+
+template <typename T>
+inline Type Type::from() { return Type(Schema::from<T>()); }
+
+inline bool Type::isVoid   () const { return baseType == schema::Type::VOID     && listDepth == 0; }
+inline bool Type::isBool   () const { return baseType == schema::Type::BOOL     && listDepth == 0; }
+inline bool Type::isInt8   () const { return baseType == schema::Type::INT8     && listDepth == 0; }
+inline bool Type::isInt16  () const { return baseType == schema::Type::INT16    && listDepth == 0; }
+inline bool Type::isInt32  () const { return baseType == schema::Type::INT32    && listDepth == 0; }
+inline bool Type::isInt64  () const { return baseType == schema::Type::INT64    && listDepth == 0; }
+inline bool Type::isUInt8  () const { return baseType == schema::Type::UINT8    && listDepth == 0; }
+inline bool Type::isUInt16 () const { return baseType == schema::Type::UINT16   && listDepth == 0; }
+inline bool Type::isUInt32 () const { return baseType == schema::Type::UINT32   && listDepth == 0; }
+inline bool Type::isUInt64 () const { return baseType == schema::Type::UINT64   && listDepth == 0; }
+inline bool Type::isFloat32() const { return baseType == schema::Type::FLOAT32  && listDepth == 0; }
+inline bool Type::isFloat64() const { return baseType == schema::Type::FLOAT64  && listDepth == 0; }
+inline bool Type::isText   () const { return baseType == schema::Type::TEXT     && listDepth == 0; }
+inline bool Type::isData   () const { return baseType == schema::Type::DATA     && listDepth == 0; }
+inline bool Type::isList   () const { return listDepth > 0; }
+inline bool Type::isEnum   () const { return baseType == schema::Type::ENUM     && listDepth == 0; }
+inline bool Type::isStruct () const { return baseType == schema::Type::STRUCT   && listDepth == 0; }
+inline bool Type::isInterface() const {
+  return baseType == schema::Type::INTERFACE && listDepth == 0;
+}
+inline bool Type::isAnyPointer() const {
+  return baseType == schema::Type::ANY_POINTER && listDepth == 0;
+}
+
+inline Type Type::wrapInList(uint depth) const {
+  Type result = *this;
+  result.listDepth += depth;
+  return result;
+}
+
+}  // namespace capnp
+
+#endif  // CAPNP_SCHEMA_H_