Status ConcreteTypeFromFlatbuffer()

in cpp/src/arrow/ipc/metadata_internal.cc [241:426]


Status ConcreteTypeFromFlatbuffer(flatbuf::Type type, const void* type_data,
                                  FieldVector children, std::shared_ptr<DataType>* out) {
  switch (type) {
    case flatbuf::Type::Type_NONE:
      return Status::Invalid("Type metadata cannot be none");
    case flatbuf::Type::Type_Null:
      *out = null();
      return Status::OK();
    case flatbuf::Type::Type_Int:
      return IntFromFlatbuffer(static_cast<const flatbuf::Int*>(type_data), out);
    case flatbuf::Type::Type_FloatingPoint:
      return FloatFromFlatbuffer(static_cast<const flatbuf::FloatingPoint*>(type_data),
                                 out);
    case flatbuf::Type::Type_Binary:
      *out = binary();
      return Status::OK();
    case flatbuf::Type::Type_LargeBinary:
      *out = large_binary();
      return Status::OK();
    case flatbuf::Type::Type_BinaryView:
      *out = binary_view();
      return Status::OK();
    case flatbuf::Type::Type_FixedSizeBinary: {
      auto fw_binary = static_cast<const flatbuf::FixedSizeBinary*>(type_data);
      return FixedSizeBinaryType::Make(fw_binary->byteWidth()).Value(out);
    }
    case flatbuf::Type::Type_Utf8:
      *out = utf8();
      return Status::OK();
    case flatbuf::Type::Type_LargeUtf8:
      *out = large_utf8();
      return Status::OK();
    case flatbuf::Type::Type_Utf8View:
      *out = utf8_view();
      return Status::OK();
    case flatbuf::Type::Type_Bool:
      *out = boolean();
      return Status::OK();
    case flatbuf::Type::Type_Decimal: {
      auto dec_type = static_cast<const flatbuf::Decimal*>(type_data);
      switch (dec_type->bitWidth()) {
        case 32:
          return Decimal32Type::Make(dec_type->precision(), dec_type->scale()).Value(out);
        case 64:
          return Decimal64Type::Make(dec_type->precision(), dec_type->scale()).Value(out);
        case 128:
          return Decimal128Type::Make(dec_type->precision(), dec_type->scale())
              .Value(out);
        case 256:
          return Decimal256Type::Make(dec_type->precision(), dec_type->scale())
              .Value(out);
      }
      return Status::Invalid("Library only supports 32/64/128/256-bit decimal values");
    }
    case flatbuf::Type::Type_Date: {
      auto date_type = static_cast<const flatbuf::Date*>(type_data);
      if (date_type->unit() == flatbuf::DateUnit::DateUnit_DAY) {
        *out = date32();
      } else {
        *out = date64();
      }
      return Status::OK();
    }
    case flatbuf::Type::Type_Time: {
      auto time_type = static_cast<const flatbuf::Time*>(type_data);
      TimeUnit::type unit = FromFlatbufferUnit(time_type->unit());
      int32_t bit_width = time_type->bitWidth();
      switch (unit) {
        case TimeUnit::SECOND:
        case TimeUnit::MILLI:
          if (bit_width != 32) {
            return Status::Invalid("Time is 32 bits for second/milli unit");
          }
          *out = time32(unit);
          break;
        default:
          if (bit_width != 64) {
            return Status::Invalid("Time is 64 bits for micro/nano unit");
          }
          *out = time64(unit);
          break;
      }
      return Status::OK();
    }
    case flatbuf::Type::Type_Timestamp: {
      auto ts_type = static_cast<const flatbuf::Timestamp*>(type_data);
      TimeUnit::type unit = FromFlatbufferUnit(ts_type->unit());
      *out = timestamp(unit, StringFromFlatbuffers(ts_type->timezone()));
      return Status::OK();
    }
    case flatbuf::Type::Type_Duration: {
      auto duration = static_cast<const flatbuf::Duration*>(type_data);
      TimeUnit::type unit = FromFlatbufferUnit(duration->unit());
      *out = arrow::duration(unit);
      return Status::OK();
    }

    case flatbuf::Type::Type_Interval: {
      auto i_type = static_cast<const flatbuf::Interval*>(type_data);
      switch (i_type->unit()) {
        case flatbuf::IntervalUnit::IntervalUnit_YEAR_MONTH: {
          *out = month_interval();
          return Status::OK();
        }
        case flatbuf::IntervalUnit::IntervalUnit_DAY_TIME: {
          *out = day_time_interval();
          return Status::OK();
        }
        case flatbuf::IntervalUnit::IntervalUnit_MONTH_DAY_NANO: {
          *out = month_day_nano_interval();
          return Status::OK();
        }
      }
      return Status::NotImplemented("Unrecognized interval type.");
    }

    case flatbuf::Type::Type_List:
      if (children.size() != 1) {
        return Status::Invalid("List must have exactly 1 child field");
      }
      *out = std::make_shared<ListType>(children[0]);
      return Status::OK();
    case flatbuf::Type::Type_LargeList:
      if (children.size() != 1) {
        return Status::Invalid("LargeList must have exactly 1 child field");
      }
      *out = std::make_shared<LargeListType>(children[0]);
      return Status::OK();
    case flatbuf::Type::Type_ListView:
      if (children.size() != 1) {
        return Status::Invalid("ListView must have exactly 1 child field");
      }
      *out = std::make_shared<ListViewType>(children[0]);
      return Status::OK();
    case flatbuf::Type::Type_LargeListView:
      if (children.size() != 1) {
        return Status::Invalid("LargeListView must have exactly 1 child field");
      }
      *out = std::make_shared<LargeListViewType>(children[0]);
      return Status::OK();
    case flatbuf::Type::Type_Map:
      if (children.size() != 1) {
        return Status::Invalid("Map must have exactly 1 child field");
      }
      if (children[0]->nullable() || children[0]->type()->id() != Type::STRUCT ||
          children[0]->type()->num_fields() != 2) {
        return Status::Invalid("Map's key-item pairs must be non-nullable structs");
      }
      if (children[0]->type()->field(0)->nullable()) {
        return Status::Invalid("Map's keys must be non-nullable");
      } else {
        auto map = static_cast<const flatbuf::Map*>(type_data);
        *out = std::make_shared<MapType>(children[0]->type()->field(0)->WithName("key"),
                                         children[0]->type()->field(1)->WithName("value"),
                                         map->keysSorted());
      }
      return Status::OK();
    case flatbuf::Type::Type_FixedSizeList:
      if (children.size() != 1) {
        return Status::Invalid("FixedSizeList must have exactly 1 child field");
      } else {
        auto fs_list = static_cast<const flatbuf::FixedSizeList*>(type_data);
        *out = std::make_shared<FixedSizeListType>(children[0], fs_list->listSize());
      }
      return Status::OK();
    case flatbuf::Type::Type_Struct_:
      *out = std::make_shared<StructType>(children);
      return Status::OK();
    case flatbuf::Type::Type_Union:
      return UnionFromFlatbuffer(static_cast<const flatbuf::Union*>(type_data), children,
                                 out);
    case flatbuf::Type::Type_RunEndEncoded:
      if (children.size() != 2) {
        return Status::Invalid("RunEndEncoded must have exactly 2 child fields");
      }
      if (!is_run_end_type(children[0]->type()->id())) {
        return Status::Invalid(
            "RunEndEncoded run_ends field must be typed as: int16, int32, or int64");
      }
      *out =
          std::make_shared<RunEndEncodedType>(children[0]->type(), children[1]->type());
      return Status::OK();
    default:
      return Status::Invalid("Unrecognized type: " + ToChars(static_cast<int>(type)));
  }
}