| 171 | } // namespace |
| 172 | |
| 173 | TypePtr Type::create(const folly::dynamic& obj) { |
| 174 | std::vector<TypePtr> childTypes; |
| 175 | if (obj.find("cTypes") != obj.items().end()) { |
| 176 | childTypes = deserializeChildTypes(obj); |
| 177 | } |
| 178 | |
| 179 | auto typeName = obj["type"].asString(); |
| 180 | if (isDecimalName(typeName)) { |
| 181 | return DECIMAL(obj["precision"].asInt(), obj["scale"].asInt()); |
| 182 | } |
| 183 | // Checks if 'typeName' specifies a custom type. |
| 184 | if (customTypeExists(typeName)) { |
| 185 | return getCustomType(typeName); |
| 186 | } |
| 187 | |
| 188 | // 'typeName' must be a built-in type. |
| 189 | TypeKind typeKind = mapNameToTypeKind(typeName); |
| 190 | switch (typeKind) { |
| 191 | case TypeKind::ROW: { |
| 192 | BOLT_USER_CHECK(obj["names"].isArray()); |
| 193 | std::vector<std::string> names; |
| 194 | for (const auto& name : obj["names"]) { |
| 195 | names.push_back(name.asString()); |
| 196 | } |
| 197 | |
| 198 | return std::make_shared<const RowType>( |
| 199 | std::move(names), std::move(childTypes)); |
| 200 | } |
| 201 | |
| 202 | case TypeKind::OPAQUE: { |
| 203 | const auto& persistentName = obj["opaque"].asString(); |
| 204 | const auto& registry = OpaqueSerdeRegistry::get(); |
| 205 | auto it = registry.reverse.find(persistentName); |
| 206 | BOLT_USER_CHECK( |
| 207 | it != registry.reverse.end(), |
| 208 | "Opaque type with persistent name '{}' is not registered", |
| 209 | persistentName); |
| 210 | if (auto withExtra = it->second->deserializeExtra(obj)) { |
| 211 | return withExtra; |
| 212 | } |
| 213 | return it->second; |
| 214 | } |
| 215 | case TypeKind::VARIANT: { |
| 216 | return VARIANT(); |
| 217 | } |
| 218 | default: { |
| 219 | return createType(typeKind, std::move(childTypes)); |
| 220 | } |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | // static |
| 225 | void Type::registerSerDe() { |
nothing calls this directly
no test coverage detected