create the data for the object, if the type has a custom data to json function, use it. otherwise, we go over the fields and create the data.
| 195 | // create the data for the object, if the type has a custom data to json function, |
| 196 | // use it. otherwise, we go over the fields and create the data. |
| 197 | json::Value CreateObjectData(const Any& value) { |
| 198 | static reflection::TypeAttrColumn data_to_json = |
| 199 | reflection::TypeAttrColumn(reflection::type_attr::kDataToJson); |
| 200 | if (data_to_json[value.type_index()] != nullptr) { |
| 201 | return data_to_json[value.type_index()].cast<Function>()(value); |
| 202 | } |
| 203 | // NOTE: invariant: lhs and rhs are already the same type |
| 204 | const TVMFFITypeInfo* type_info = TVMFFIGetTypeInfo(value.type_index()); |
| 205 | if (!HasCreator(type_info)) { |
| 206 | TVM_FFI_THROW(TypeError) << "Type `" << String(type_info->type_key) |
| 207 | << "` does not support ToJSONGraph " |
| 208 | << "(no native creator or __ffi_new__ type attr)"; |
| 209 | } |
| 210 | const Object* obj = value.cast<const Object*>(); |
| 211 | json::Object data; |
| 212 | // go over the content and hash the fields |
| 213 | reflection::ForEachFieldInfo(type_info, [&](const TVMFFIFieldInfo* field_info) { |
| 214 | // get the field value from both side |
| 215 | reflection::FieldGetter getter(field_info); |
| 216 | Any field_value = getter(obj); |
| 217 | int field_static_type_index = field_info->field_static_type_index; |
| 218 | String field_name(field_info->name); |
| 219 | // for static field index that are known, we can directly set the field value. |
| 220 | switch (field_static_type_index) { |
| 221 | case TypeIndex::kTVMFFINone: { |
| 222 | data.Set(field_name, nullptr); |
| 223 | break; |
| 224 | } |
| 225 | case TypeIndex::kTVMFFIBool: { |
| 226 | data.Set(field_name, details::AnyUnsafe::CopyFromAnyViewAfterCheck<bool>(field_value)); |
| 227 | break; |
| 228 | } |
| 229 | case TypeIndex::kTVMFFIInt: { |
| 230 | data.Set(field_name, details::AnyUnsafe::CopyFromAnyViewAfterCheck<int64_t>(field_value)); |
| 231 | break; |
| 232 | } |
| 233 | case TypeIndex::kTVMFFIFloat: { |
| 234 | data.Set(field_name, details::AnyUnsafe::CopyFromAnyViewAfterCheck<double>(field_value)); |
| 235 | break; |
| 236 | } |
| 237 | case TypeIndex::kTVMFFIDataType: { |
| 238 | DLDataType dtype = details::AnyUnsafe::CopyFromAnyViewAfterCheck<DLDataType>(field_value); |
| 239 | data.Set(field_name, DLDataTypeToString(dtype)); |
| 240 | break; |
| 241 | } |
| 242 | default: { |
| 243 | // for dynamic field index, we need need to put them onto nodes |
| 244 | int64_t node_index = GetOrCreateNodeIndex(field_value); |
| 245 | data.Set(field_name, node_index); |
| 246 | break; |
| 247 | } |
| 248 | } |
| 249 | }); |
| 250 | return data; |
| 251 | } |
| 252 | |
| 253 | // maps the original value to the index of the node in the nodes_ array |
| 254 | std::unordered_map<Any, int64_t, AnyHash, AnyEqual> node_index_map_; |
nothing calls this directly
no test coverage detected