generated-header-support.h (13682B)
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors 2 // Licensed under the MIT License: 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 22 // This file is included from all generated headers. 23 24 #pragma once 25 26 #include "raw-schema.h" 27 #include "layout.h" 28 #include "list.h" 29 #include "orphan.h" 30 #include "pointer-helpers.h" 31 #include "any.h" 32 #include <kj/string.h> 33 #include <kj/string-tree.h> 34 #include <kj/hash.h> 35 36 CAPNP_BEGIN_HEADER 37 38 namespace capnp { 39 40 class MessageBuilder; // So that it can be declared a friend. 41 42 template <typename T, Kind k = CAPNP_KIND(T)> 43 struct ToDynamic_; // Defined in dynamic.h, needs to be declared as everyone's friend. 44 45 struct DynamicStruct; // So that it can be declared a friend. 46 47 struct Capability; // To declare brandBindingFor<Capability>() 48 49 namespace _ { // private 50 51 #if !CAPNP_LITE 52 53 template <typename T, typename CapnpPrivate = typename T::_capnpPrivate, bool = false> 54 inline const RawSchema& rawSchema() { 55 return *CapnpPrivate::schema; 56 } 57 template <typename T, uint64_t id = schemas::EnumInfo<T>::typeId> 58 inline const RawSchema& rawSchema() { 59 return *schemas::EnumInfo<T>::schema; 60 } 61 62 template <typename T, typename CapnpPrivate = typename T::_capnpPrivate> 63 inline const RawBrandedSchema& rawBrandedSchema() { 64 return *CapnpPrivate::brand(); 65 } 66 template <typename T, uint64_t id = schemas::EnumInfo<T>::typeId> 67 inline const RawBrandedSchema& rawBrandedSchema() { 68 return schemas::EnumInfo<T>::schema->defaultBrand; 69 } 70 71 template <typename TypeTag, typename... Params> 72 struct ChooseBrand; 73 // If all of `Params` are `AnyPointer`, return the type's default brand. Otherwise, return a 74 // specific brand instance. TypeTag is the _capnpPrivate struct for the type in question. 75 76 template <typename TypeTag> 77 struct ChooseBrand<TypeTag> { 78 // All params were AnyPointer. No specific brand needed. 79 static constexpr _::RawBrandedSchema const* brand() { return &TypeTag::schema->defaultBrand; } 80 }; 81 82 template <typename TypeTag, typename... Rest> 83 struct ChooseBrand<TypeTag, AnyPointer, Rest...>: public ChooseBrand<TypeTag, Rest...> {}; 84 // The first parameter is AnyPointer, so recurse to check the rest. 85 86 template <typename TypeTag, typename First, typename... Rest> 87 struct ChooseBrand<TypeTag, First, Rest...> { 88 // At least one parameter is not AnyPointer, so use the specificBrand constant. 89 static constexpr _::RawBrandedSchema const* brand() { return &TypeTag::specificBrand; } 90 }; 91 92 template <typename T, Kind k = kind<T>()> 93 struct BrandBindingFor_; 94 95 #define HANDLE_TYPE(Type, which) \ 96 template <> \ 97 struct BrandBindingFor_<Type, Kind::PRIMITIVE> { \ 98 static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { \ 99 return { which, listDepth, nullptr }; \ 100 } \ 101 } 102 HANDLE_TYPE(Void, 0); 103 HANDLE_TYPE(bool, 1); 104 HANDLE_TYPE(int8_t, 2); 105 HANDLE_TYPE(int16_t, 3); 106 HANDLE_TYPE(int32_t, 4); 107 HANDLE_TYPE(int64_t, 5); 108 HANDLE_TYPE(uint8_t, 6); 109 HANDLE_TYPE(uint16_t, 7); 110 HANDLE_TYPE(uint32_t, 8); 111 HANDLE_TYPE(uint64_t, 9); 112 HANDLE_TYPE(float, 10); 113 HANDLE_TYPE(double, 11); 114 #undef HANDLE_TYPE 115 116 template <> 117 struct BrandBindingFor_<Text, Kind::BLOB> { 118 static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { 119 return { 12, listDepth, nullptr }; 120 } 121 }; 122 123 template <> 124 struct BrandBindingFor_<Data, Kind::BLOB> { 125 static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { 126 return { 13, listDepth, nullptr }; 127 } 128 }; 129 130 template <typename T> 131 struct BrandBindingFor_<List<T>, Kind::LIST> { 132 static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { 133 return BrandBindingFor_<T>::get(listDepth + 1); 134 } 135 }; 136 137 template <typename T> 138 struct BrandBindingFor_<T, Kind::ENUM> { 139 static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { 140 return { 15, listDepth, nullptr }; 141 } 142 }; 143 144 template <typename T> 145 struct BrandBindingFor_<T, Kind::STRUCT> { 146 static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { 147 return { 16, listDepth, T::_capnpPrivate::brand() }; 148 } 149 }; 150 151 template <typename T> 152 struct BrandBindingFor_<T, Kind::INTERFACE> { 153 static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { 154 return { 17, listDepth, T::_capnpPrivate::brand() }; 155 } 156 }; 157 158 template <> 159 struct BrandBindingFor_<AnyPointer, Kind::OTHER> { 160 static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { 161 return { 18, listDepth, 0, 0 }; 162 } 163 }; 164 165 template <> 166 struct BrandBindingFor_<AnyStruct, Kind::OTHER> { 167 static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { 168 return { 18, listDepth, 0, 1 }; 169 } 170 }; 171 172 template <> 173 struct BrandBindingFor_<AnyList, Kind::OTHER> { 174 static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { 175 return { 18, listDepth, 0, 2 }; 176 } 177 }; 178 179 template <> 180 struct BrandBindingFor_<Capability, Kind::OTHER> { 181 static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { 182 return { 18, listDepth, 0, 3 }; 183 } 184 }; 185 186 template <typename T> 187 constexpr RawBrandedSchema::Binding brandBindingFor() { 188 return BrandBindingFor_<T>::get(0); 189 } 190 191 kj::StringTree structString(StructReader reader, const RawBrandedSchema& schema); 192 kj::String enumString(uint16_t value, const RawBrandedSchema& schema); 193 // Declared here so that we can declare inline stringify methods on generated types. 194 // Defined in stringify.c++, which depends on dynamic.c++, which is allowed not to be linked in. 195 196 template <typename T> 197 inline kj::StringTree structString(StructReader reader) { 198 return structString(reader, rawBrandedSchema<T>()); 199 } 200 template <typename T> 201 inline kj::String enumString(T value) { 202 return enumString(static_cast<uint16_t>(value), rawBrandedSchema<T>()); 203 } 204 205 #endif // !CAPNP_LITE 206 207 // TODO(cleanup): Unify ConstStruct and ConstList. 208 template <typename T> 209 class ConstStruct { 210 public: 211 ConstStruct() = delete; 212 KJ_DISALLOW_COPY(ConstStruct); 213 inline explicit constexpr ConstStruct(const word* ptr): ptr(ptr) {} 214 215 inline typename T::Reader get() const { 216 return AnyPointer::Reader(PointerReader::getRootUnchecked(ptr)).getAs<T>(); 217 } 218 219 inline operator typename T::Reader() const { return get(); } 220 inline typename T::Reader operator*() const { return get(); } 221 inline TemporaryPointer<typename T::Reader> operator->() const { return get(); } 222 223 private: 224 const word* ptr; 225 }; 226 227 template <typename T> 228 class ConstList { 229 public: 230 ConstList() = delete; 231 KJ_DISALLOW_COPY(ConstList); 232 inline explicit constexpr ConstList(const word* ptr): ptr(ptr) {} 233 234 inline typename List<T>::Reader get() const { 235 return AnyPointer::Reader(PointerReader::getRootUnchecked(ptr)).getAs<List<T>>(); 236 } 237 238 inline operator typename List<T>::Reader() const { return get(); } 239 inline typename List<T>::Reader operator*() const { return get(); } 240 inline TemporaryPointer<typename List<T>::Reader> operator->() const { return get(); } 241 242 private: 243 const word* ptr; 244 }; 245 246 template <size_t size> 247 class ConstText { 248 public: 249 ConstText() = delete; 250 KJ_DISALLOW_COPY(ConstText); 251 inline explicit constexpr ConstText(const word* ptr): ptr(ptr) {} 252 253 inline Text::Reader get() const { 254 return Text::Reader(reinterpret_cast<const char*>(ptr), size); 255 } 256 257 inline operator Text::Reader() const { return get(); } 258 inline Text::Reader operator*() const { return get(); } 259 inline TemporaryPointer<Text::Reader> operator->() const { return get(); } 260 261 inline kj::StringPtr toString() const { 262 return get(); 263 } 264 265 private: 266 const word* ptr; 267 }; 268 269 template <size_t size> 270 inline kj::StringPtr KJ_STRINGIFY(const ConstText<size>& s) { 271 return s.get(); 272 } 273 274 template <size_t size> 275 class ConstData { 276 public: 277 ConstData() = delete; 278 KJ_DISALLOW_COPY(ConstData); 279 inline explicit constexpr ConstData(const word* ptr): ptr(ptr) {} 280 281 inline Data::Reader get() const { 282 return Data::Reader(reinterpret_cast<const byte*>(ptr), size); 283 } 284 285 inline operator Data::Reader() const { return get(); } 286 inline Data::Reader operator*() const { return get(); } 287 inline TemporaryPointer<Data::Reader> operator->() const { return get(); } 288 289 private: 290 const word* ptr; 291 }; 292 293 template <size_t size> 294 inline auto KJ_STRINGIFY(const ConstData<size>& s) -> decltype(kj::toCharSequence(s.get())) { 295 return kj::toCharSequence(s.get()); 296 } 297 298 } // namespace _ (private) 299 300 template <typename T, typename CapnpPrivate = typename T::_capnpPrivate> 301 inline constexpr uint64_t typeId() { return CapnpPrivate::typeId; } 302 template <typename T, uint64_t id = schemas::EnumInfo<T>::typeId> 303 inline constexpr uint64_t typeId() { return id; } 304 // typeId<MyType>() returns the type ID as defined in the schema. Works with structs, enums, and 305 // interfaces. 306 307 template <typename T> 308 inline constexpr uint sizeInWords() { 309 // Return the size, in words, of a Struct type, if allocated free-standing (not in a list). 310 // May be useful for pre-computing space needed in order to precisely allocate messages. 311 312 return unbound((upgradeBound<uint>(_::structSize<T>().data) + 313 _::structSize<T>().pointers * WORDS_PER_POINTER) / WORDS); 314 } 315 316 } // namespace capnp 317 318 #if _MSC_VER && !defined(__clang__) 319 // MSVC doesn't understand floating-point constexpr yet. 320 // 321 // TODO(msvc): Remove this hack when MSVC is fixed. 322 #define CAPNP_NON_INT_CONSTEXPR_DECL_INIT(value) 323 #define CAPNP_NON_INT_CONSTEXPR_DEF_INIT(value) = value 324 #else 325 #define CAPNP_NON_INT_CONSTEXPR_DECL_INIT(value) = value 326 #define CAPNP_NON_INT_CONSTEXPR_DEF_INIT(value) 327 #endif 328 329 #if _MSC_VER && !defined(__clang__) 330 // TODO(msvc): A little hack to allow MSVC to use C++14 return type deduction in cases where the 331 // explicit type exposes bugs in the compiler. 332 #define CAPNP_AUTO_IF_MSVC(...) auto 333 #else 334 #define CAPNP_AUTO_IF_MSVC(...) __VA_ARGS__ 335 #endif 336 337 #if CAPNP_LITE 338 339 #define CAPNP_DECLARE_SCHEMA(id) \ 340 extern ::capnp::word const* const bp_##id 341 342 #define CAPNP_DECLARE_ENUM(type, id) \ 343 inline ::kj::String KJ_STRINGIFY(type##_##id value) { \ 344 return ::kj::str(static_cast<uint16_t>(value)); \ 345 } \ 346 template <> struct EnumInfo<type##_##id> { \ 347 struct IsEnum; \ 348 static constexpr uint64_t typeId = 0x##id; \ 349 static inline ::capnp::word const* encodedSchema() { return bp_##id; } \ 350 } 351 352 #if _MSC_VER && !defined(__clang__) 353 // TODO(msvc): MSVC doesn't expect constexprs to have definitions. 354 #define CAPNP_DEFINE_ENUM(type, id) 355 #else 356 #define CAPNP_DEFINE_ENUM(type, id) \ 357 constexpr uint64_t EnumInfo<type>::typeId 358 #endif 359 360 #define CAPNP_DECLARE_STRUCT_HEADER(id, dataWordSize_, pointerCount_) \ 361 struct IsStruct; \ 362 static constexpr uint64_t typeId = 0x##id; \ 363 static constexpr uint16_t dataWordSize = dataWordSize_; \ 364 static constexpr uint16_t pointerCount = pointerCount_; \ 365 static inline ::capnp::word const* encodedSchema() { return ::capnp::schemas::bp_##id; } 366 367 #else // CAPNP_LITE 368 369 #define CAPNP_DECLARE_SCHEMA(id) \ 370 extern ::capnp::word const* const bp_##id; \ 371 extern const ::capnp::_::RawSchema s_##id 372 373 #define CAPNP_DECLARE_ENUM(type, id) \ 374 inline ::kj::String KJ_STRINGIFY(type##_##id value) { \ 375 return ::capnp::_::enumString(value); \ 376 } \ 377 template <> struct EnumInfo<type##_##id> { \ 378 struct IsEnum; \ 379 static constexpr uint64_t typeId = 0x##id; \ 380 static inline ::capnp::word const* encodedSchema() { return bp_##id; } \ 381 static constexpr ::capnp::_::RawSchema const* schema = &s_##id; \ 382 } 383 #define CAPNP_DEFINE_ENUM(type, id) \ 384 constexpr uint64_t EnumInfo<type>::typeId; \ 385 constexpr ::capnp::_::RawSchema const* EnumInfo<type>::schema 386 387 #define CAPNP_DECLARE_STRUCT_HEADER(id, dataWordSize_, pointerCount_) \ 388 struct IsStruct; \ 389 static constexpr uint64_t typeId = 0x##id; \ 390 static constexpr ::capnp::Kind kind = ::capnp::Kind::STRUCT; \ 391 static constexpr uint16_t dataWordSize = dataWordSize_; \ 392 static constexpr uint16_t pointerCount = pointerCount_; \ 393 static inline ::capnp::word const* encodedSchema() { return ::capnp::schemas::bp_##id; } \ 394 static constexpr ::capnp::_::RawSchema const* schema = &::capnp::schemas::s_##id; 395 396 #define CAPNP_DECLARE_INTERFACE_HEADER(id) \ 397 struct IsInterface; \ 398 static constexpr uint64_t typeId = 0x##id; \ 399 static constexpr ::capnp::Kind kind = ::capnp::Kind::INTERFACE; \ 400 static inline ::capnp::word const* encodedSchema() { return ::capnp::schemas::bp_##id; } \ 401 static constexpr ::capnp::_::RawSchema const* schema = &::capnp::schemas::s_##id; 402 403 #endif // CAPNP_LITE, else 404 405 namespace capnp { 406 namespace schemas { 407 CAPNP_DECLARE_SCHEMA(995f9a3377c0b16e); 408 // HACK: Forward-declare the RawSchema for StreamResult, from stream.capnp. This allows capnp 409 // files which declare streaming methods to avoid including stream.capnp.h. 410 } 411 } 412 413 CAPNP_END_HEADER