// Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef dap_typeof_h #define dap_typeof_h #include "typeinfo.h" #include "types.h" #include "serialization.h" namespace dap { // BasicTypeInfo is an implementation of the TypeInfo interface for the simple // template type T. template struct BasicTypeInfo : public TypeInfo { constexpr BasicTypeInfo(std::string&& name) : name_(std::move(name)) {} // TypeInfo compliance inline std::string name() const override { return name_; } inline size_t size() const override { return sizeof(T); } inline size_t alignment() const override { return alignof(T); } inline void construct(void* ptr) const override { new (ptr) T(); } inline void copyConstruct(void* dst, const void* src) const override { new (dst) T(*reinterpret_cast(src)); } inline void destruct(void* ptr) const override { reinterpret_cast(ptr)->~T(); } inline bool deserialize(const Deserializer* d, void* ptr) const override { return d->deserialize(reinterpret_cast(ptr)); } inline bool serialize(Serializer* s, const void* ptr) const override { return s->serialize(*reinterpret_cast(ptr)); } private: std::string name_; }; // TypeOf has a template specialization for each DAP type, each declaring a // const TypeInfo* type() static member function that describes type T. template struct TypeOf {}; template <> struct TypeOf { static const TypeInfo* type(); }; template <> struct TypeOf { static const TypeInfo* type(); }; template <> struct TypeOf { static const TypeInfo* type(); }; template <> struct TypeOf { static const TypeInfo* type(); }; template <> struct TypeOf { static const TypeInfo* type(); }; template <> struct TypeOf { static const TypeInfo* type(); }; template <> struct TypeOf { static const TypeInfo* type(); }; template struct TypeOf> { static inline const TypeInfo* type() { static auto typeinfo = TypeInfo::create>>( "array<" + TypeOf::type()->name() + ">"); return typeinfo; } }; template struct TypeOf> { static inline const TypeInfo* type() { static auto typeinfo = TypeInfo::create>>("variant"); return typeinfo; } }; template struct TypeOf> { static inline const TypeInfo* type() { static auto typeinfo = TypeInfo::create>>( "optional<" + TypeOf::type()->name() + ">"); return typeinfo; } }; // DAP_OFFSETOF() macro is a generalization of the offsetof() macro defined in // . It evaluates to the offset of the given field, with fewer // restrictions than offsetof(). We cast the address '32' and subtract it again, // because null-dereference is undefined behavior. #define DAP_OFFSETOF(s, m) \ ((int)(size_t) & reinterpret_cast((((s*)32)->m)) - 32) // internal functionality namespace detail { template M member_type(M T::*); } // namespace detail // DAP_TYPEOF() returns the type of the struct (s) member (m). #define DAP_TYPEOF(s, m) decltype(detail::member_type(&s::m)) // DAP_FIELD() declares a structure field for the DAP_IMPLEMENT_STRUCT_TYPEINFO // macro. // FIELD is the name of the struct field. // NAME is the serialized name of the field, as described by the DAP // specification. #define DAP_FIELD(FIELD, NAME) \ ::dap::Field { \ NAME, DAP_OFFSETOF(StructTy, FIELD), \ TypeOf::type(), \ } // DAP_DECLARE_STRUCT_TYPEINFO() declares a TypeOf<> specialization for STRUCT. // Must be used within the 'dap' namespace. #define DAP_DECLARE_STRUCT_TYPEINFO(STRUCT) \ template <> \ struct TypeOf { \ static constexpr bool has_custom_serialization = true; \ static const TypeInfo* type(); \ static bool deserializeFields(const Deserializer*, void* obj); \ static bool serializeFields(FieldSerializer*, const void* obj); \ } // DAP_IMPLEMENT_STRUCT_FIELD_SERIALIZATION() implements the deserializeFields() // and serializeFields() static methods of a TypeOf<> specialization. Used // internally by DAP_IMPLEMENT_STRUCT_TYPEINFO() and // DAP_IMPLEMENT_STRUCT_TYPEINFO_EXT(). // You probably do not want to use this directly. #define DAP_IMPLEMENT_STRUCT_FIELD_SERIALIZATION(STRUCT, NAME, ...) \ bool TypeOf::deserializeFields(const Deserializer* fd, void* obj) { \ using StructTy = STRUCT; \ (void)sizeof(StructTy); /* avoid unused 'using' warning */ \ for (auto field : std::initializer_list{__VA_ARGS__}) { \ if (!fd->field(field.name, [&](Deserializer* d) { \ auto ptr = reinterpret_cast(obj) + field.offset; \ return field.type->deserialize(d, ptr); \ })) { \ return false; \ } \ } \ return true; \ } \ bool TypeOf::serializeFields(FieldSerializer* fs, const void* obj) {\ using StructTy = STRUCT; \ (void)sizeof(StructTy); /* avoid unused 'using' warning */ \ for (auto field : std::initializer_list{__VA_ARGS__}) { \ if (!fs->field(field.name, [&](Serializer* s) { \ auto ptr = reinterpret_cast(obj) + field.offset; \ return field.type->serialize(s, ptr); \ })) { \ return false; \ } \ } \ return true; \ } // DAP_IMPLEMENT_STRUCT_TYPEINFO() implements the type() member function for the // TypeOf<> specialization for STRUCT. // STRUCT is the structure typename. // NAME is the serialized name of the structure, as described by the DAP // specification. The variadic (...) parameters should be a repeated list of // DAP_FIELD()s, one for each field of the struct. // Must be used within the 'dap' namespace. #define DAP_IMPLEMENT_STRUCT_TYPEINFO(STRUCT, NAME, ...) \ DAP_IMPLEMENT_STRUCT_FIELD_SERIALIZATION(STRUCT, NAME, __VA_ARGS__) \ const ::dap::TypeInfo* TypeOf::type() { \ struct TI : BasicTypeInfo { \ TI() : BasicTypeInfo(NAME) {} \ bool deserialize(const Deserializer* d, void* obj) const override { \ return deserializeFields(d, obj); \ } \ bool serialize(Serializer* s, const void* obj) const override { \ return s->object( \ [&](FieldSerializer* fs) { return serializeFields(fs, obj); }); \ } \ }; \ static TI typeinfo; \ return &typeinfo; \ } // DAP_STRUCT_TYPEINFO() is a helper for declaring and implementing a TypeOf<> // specialization for STRUCT in a single statement. // Must be used within the 'dap' namespace. #define DAP_STRUCT_TYPEINFO(STRUCT, NAME, ...) \ DAP_DECLARE_STRUCT_TYPEINFO(STRUCT); \ DAP_IMPLEMENT_STRUCT_TYPEINFO(STRUCT, NAME, __VA_ARGS__) // DAP_IMPLEMENT_STRUCT_TYPEINFO_EXT() implements the type() member function for // the TypeOf<> specialization for STRUCT that derives from BASE. // STRUCT is the structure typename. // BASE is the base structure typename. // NAME is the serialized name of the structure, as described by the DAP // specification. The variadic (...) parameters should be a repeated list of // DAP_FIELD()s, one for each field of the struct. // Must be used within the 'dap' namespace. #define DAP_IMPLEMENT_STRUCT_TYPEINFO_EXT(STRUCT, BASE, NAME, ...) \ static_assert(std::is_base_of::value, \ #STRUCT " does not derive from " #BASE); \ DAP_IMPLEMENT_STRUCT_FIELD_SERIALIZATION(STRUCT, NAME, __VA_ARGS__) \ const ::dap::TypeInfo* TypeOf::type() { \ struct TI : BasicTypeInfo { \ TI() : BasicTypeInfo(NAME) {} \ bool deserialize(const Deserializer* d, void* obj) const override { \ auto derived = static_cast(obj); \ auto base = static_cast(obj); \ return TypeOf::deserializeFields(d, base) && \ deserializeFields(d, derived); \ } \ bool serialize(Serializer* s, const void* obj) const override { \ return s->object([&](FieldSerializer* fs) { \ auto derived = static_cast(obj); \ auto base = static_cast(obj); \ return TypeOf::serializeFields(fs, base) && \ serializeFields(fs, derived); \ }); \ } \ }; \ static TI typeinfo; \ return &typeinfo; \ } // DAP_STRUCT_TYPEINFO_EXT() is a helper for declaring and implementing a // TypeOf<> specialization for STRUCT that derives from BASE in a single // statement. // Must be used within the 'dap' namespace. #define DAP_STRUCT_TYPEINFO_EXT(STRUCT, BASE, NAME, ...) \ DAP_DECLARE_STRUCT_TYPEINFO(STRUCT); \ DAP_IMPLEMENT_STRUCT_TYPEINFO_EXT(STRUCT, BASE, NAME, __VA_ARGS__) } // namespace dap #endif // dap_typeof_h