/** * Copyright (c) 2019 by Contributors * @file packed_func_ext.h * @brief Extension package to PackedFunc * This enables pass ObjectRef types into/from PackedFunc. */ #ifndef DGL_PACKED_FUNC_EXT_H_ #define DGL_PACKED_FUNC_EXT_H_ #include #include #include #include #include "./runtime/container.h" #include "./runtime/object.h" #include "./runtime/packed_func.h" namespace dgl { namespace runtime { /** * @brief Runtime type checker for node type. * @tparam T the type to be checked. */ template struct ObjectTypeChecker { static inline bool Check(Object* sptr) { // This is the only place in the project where RTTI is used // It can be turned off, but will make non strict checking. // TODO(tqchen) possibly find alternative to turn of RTTI using ContainerType = typename T::ContainerType; return sptr->derived_from(); } static inline void PrintName(std::ostringstream& os) { // NOLINT(*) using ContainerType = typename T::ContainerType; os << ContainerType::_type_key; } }; template struct ObjectTypeChecker > { static inline bool Check(Object* sptr) { if (sptr == nullptr) return false; if (!sptr->is_type()) return false; ListObject* n = static_cast(sptr); for (const auto& p : n->data) { if (!ObjectTypeChecker::Check(p.get())) return false; } return true; } static inline void PrintName(std::ostringstream& os) { // NOLINT(*) os << "list<"; ObjectTypeChecker::PrintName(os); os << ">"; } }; template struct ObjectTypeChecker > { static inline bool Check(Object* sptr) { if (sptr == nullptr) return false; if (!sptr->is_type()) return false; StrMapObject* n = static_cast(sptr); for (const auto& kv : n->data) { if (!ObjectTypeChecker::Check(kv.second.get())) return false; } return true; } static inline void PrintName(std::ostringstream& os) { // NOLINT(*) os << "map::PrintName(os); os << '>'; } }; template struct ObjectTypeChecker > { static inline bool Check(Object* sptr) { if (sptr == nullptr) return false; if (!sptr->is_type()) return false; MapObject* n = static_cast(sptr); for (const auto& kv : n->data) { if (!ObjectTypeChecker::Check(kv.first.get())) return false; if (!ObjectTypeChecker::Check(kv.second.get())) return false; } return true; } static inline void PrintName(std::ostringstream& os) { // NOLINT(*) os << "map<"; ObjectTypeChecker::PrintName(os); os << ','; ObjectTypeChecker::PrintName(os); os << '>'; } }; template inline std::string NodeTypeName() { std::ostringstream os; ObjectTypeChecker::PrintName(os); return os.str(); } // extensions for DGLArgValue template inline TObjectRef DGLArgValue::AsObjectRef() const { static_assert( std::is_base_of::value, "Conversion only works for ObjectRef derived class"); if (type_code_ == kNull) return TObjectRef(); DGL_CHECK_TYPE_CODE(type_code_, kObjectHandle); std::shared_ptr& sptr = *ptr >(); CHECK(ObjectTypeChecker::Check(sptr.get())) << "Expected type " << NodeTypeName() << " but get " << sptr->type_key(); return TObjectRef(sptr); } inline std::shared_ptr& DGLArgValue::obj_sptr() { DGL_CHECK_TYPE_CODE(type_code_, kObjectHandle); return *ptr >(); } template inline bool DGLArgValue::IsObjectType() const { DGL_CHECK_TYPE_CODE(type_code_, kObjectHandle); std::shared_ptr& sptr = *ptr >(); return ObjectTypeChecker::Check(sptr.get()); } // extensions for DGLRetValue inline DGLRetValue& DGLRetValue::operator=( const std::shared_ptr& other) { if (other.get() == nullptr) { SwitchToPOD(kNull); } else { SwitchToClass >(kObjectHandle, other); } return *this; } inline DGLRetValue& DGLRetValue::operator=(const ObjectRef& other) { if (!other.defined()) { SwitchToPOD(kNull); } else { SwitchToClass >(kObjectHandle, other.obj_); } return *this; } template inline TObjectRef DGLRetValue::AsObjectRef() const { static_assert( std::is_base_of::value, "Conversion only works for ObjectRef"); if (type_code_ == kNull) return TObjectRef(); DGL_CHECK_TYPE_CODE(type_code_, kObjectHandle); return TObjectRef(*ptr >()); } inline void DGLArgsSetter::operator()( size_t i, const ObjectRef& other) const { // NOLINT(*) if (other.defined()) { values_[i].v_handle = const_cast*>(&(other.obj_)); type_codes_[i] = kObjectHandle; } else { type_codes_[i] = kNull; } } } // namespace runtime } // namespace dgl #endif // DGL_PACKED_FUNC_EXT_H_