variant variant::create()

in velox/type/Variant.cpp [394:471]


variant variant::create(const folly::dynamic& variantobj) {
  TypeKind kind = mapNameToTypeKind(variantobj["type"].asString());
  const folly::dynamic& obj = variantobj["value"];

  if (obj.isNull()) {
    return variant::null(kind);
  }
  switch (kind) {
    case TypeKind::MAP: {
      std::map<variant, variant> map;
      const folly::dynamic& keys = obj["keys"];
      const folly::dynamic& values = obj["values"];
      VELOX_USER_CHECK(keys.isArray() && values.isArray());
      VELOX_USER_CHECK_EQ(keys.size(), values.size());
      for (size_t idx = 0; idx < keys.size(); ++idx) {
        auto first = variant::create(keys[idx]);
        auto second = variant::create(values[idx]);
        map.insert(std::pair<variant, variant>(first, second));
      }
      return variant::map(map);
    }
    case TypeKind::ROW:
      FOLLY_FALLTHROUGH;
    case TypeKind::ARRAY: {
      VELOX_USER_CHECK(kind == TypeKind::ARRAY || kind == TypeKind::ROW);
      std::vector<variant> values;
      for (auto& val : obj) {
        values.push_back(variant::create(val));
      }
      return kind == TypeKind::ARRAY ? variant::array(values)
                                     : variant::row(values);
    }

    case TypeKind::VARBINARY: {
      auto str = obj.asString();
      auto result = encoding::Base64::decode(str);
      return variant::binary(std::move(result));
    }
    case TypeKind::VARCHAR:
      return variant::create<TypeKind::VARCHAR>(obj.asString());
    case TypeKind::TINYINT:
      return variant::create<TypeKind::TINYINT>(obj.asInt());
    case TypeKind::SMALLINT:
      return variant::create<TypeKind::SMALLINT>(obj.asInt());
    case TypeKind::INTEGER:
      return variant::create<TypeKind::INTEGER>(obj.asInt());
    case TypeKind::BIGINT:
      return variant::create<TypeKind::BIGINT>(obj.asInt());
    case TypeKind::BOOLEAN: {
      return variant(obj.asBool());
    }
    case TypeKind::REAL:
      if (obj.isInt()) {
        // folly::parseJson() parses eg: "2293699590479675400"
        // to int64 instead of double, and asDouble() will throw
        // "folly::ConversionError: Loss of precision", so we do
        // the check here to make it more robust.
        return variant::create<TypeKind::REAL>(obj.asInt());
      }
      return variant::create<TypeKind::REAL>(obj.asDouble());
    case TypeKind::DOUBLE: {
      if (obj.isInt()) {
        return variant::create<TypeKind::DOUBLE>(obj.asInt());
      }
      return variant::create<TypeKind::DOUBLE>(obj.asDouble());
    }
    case TypeKind::DATE:
    case TypeKind::TIMESTAMP:
      FOLLY_FALLTHROUGH;
    case TypeKind::INVALID:
      VELOX_NYI();

    default:
      VELOX_UNSUPPORTED(
          "specified object can not be converted to variant ",
          variantobj["type"].asString());
  }
}