1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements.  See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership.  The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License.  You may obtain a copy of the License at
8 //
9 //   http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied.  See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17 
18 #pragma once
19 
20 #include <memory>
21 #include <string>
22 #include <type_traits>
23 #include <vector>
24 
25 #include "arrow/type_fwd.h"
26 #include "arrow/util/bit_util.h"
27 
28 namespace arrow {
29 
30 //
31 // Per-type type traits
32 //
33 
34 template <typename T>
35 struct TypeTraits {};
36 
37 template <typename T>
38 struct CTypeTraits {};
39 
40 template <>
41 struct TypeTraits<NullType> {
42   using ArrayType = NullArray;
43   using BuilderType = NullBuilder;
44   using ScalarType = NullScalar;
45 
46   static constexpr int64_t bytes_required(int64_t) { return 0; }
47   constexpr static bool is_parameter_free = true;
48   static inline std::shared_ptr<DataType> type_singleton() { return null(); }
49 };
50 
51 template <>
52 struct TypeTraits<BooleanType> {
53   using ArrayType = BooleanArray;
54   using BuilderType = BooleanBuilder;
55   using ScalarType = BooleanScalar;
56   using CType = bool;
57 
58   static constexpr int64_t bytes_required(int64_t elements) {
59     return BitUtil::BytesForBits(elements);
60   }
61   constexpr static bool is_parameter_free = true;
62   static inline std::shared_ptr<DataType> type_singleton() { return boolean(); }
63 };
64 
65 template <>
66 struct CTypeTraits<bool> : public TypeTraits<BooleanType> {
67   using ArrowType = BooleanType;
68 };
69 
70 #define PRIMITIVE_TYPE_TRAITS_DEF_(CType_, ArrowType_, ArrowArrayType, ArrowBuilderType, \
71                                    ArrowScalarType, ArrowTensorType, SingletonFn)        \
72   template <>                                                                            \
73   struct TypeTraits<ArrowType_> {                                                        \
74     using ArrayType = ArrowArrayType;                                                    \
75     using BuilderType = ArrowBuilderType;                                                \
76     using ScalarType = ArrowScalarType;                                                  \
77     using TensorType = ArrowTensorType;                                                  \
78     using CType = ArrowType_::c_type;                                                    \
79     static constexpr int64_t bytes_required(int64_t elements) {                          \
80       return elements * static_cast<int64_t>(sizeof(CType));                             \
81     }                                                                                    \
82     constexpr static bool is_parameter_free = true;                                      \
83     static inline std::shared_ptr<DataType> type_singleton() { return SingletonFn(); }   \
84   };                                                                                     \
85                                                                                          \
86   template <>                                                                            \
87   struct CTypeTraits<CType_> : public TypeTraits<ArrowType_> {                           \
88     using ArrowType = ArrowType_;                                                        \
89   };
90 
91 #define PRIMITIVE_TYPE_TRAITS_DEF(CType, ArrowShort, SingletonFn)             \
92   PRIMITIVE_TYPE_TRAITS_DEF_(                                                 \
93       CType, ARROW_CONCAT(ArrowShort, Type), ARROW_CONCAT(ArrowShort, Array), \
94       ARROW_CONCAT(ArrowShort, Builder), ARROW_CONCAT(ArrowShort, Scalar),    \
95       ARROW_CONCAT(ArrowShort, Tensor), SingletonFn)
96 
97 PRIMITIVE_TYPE_TRAITS_DEF(uint8_t, UInt8, uint8)
98 PRIMITIVE_TYPE_TRAITS_DEF(int8_t, Int8, int8)
99 PRIMITIVE_TYPE_TRAITS_DEF(uint16_t, UInt16, uint16)
100 PRIMITIVE_TYPE_TRAITS_DEF(int16_t, Int16, int16)
101 PRIMITIVE_TYPE_TRAITS_DEF(uint32_t, UInt32, uint32)
102 PRIMITIVE_TYPE_TRAITS_DEF(int32_t, Int32, int32)
103 PRIMITIVE_TYPE_TRAITS_DEF(uint64_t, UInt64, uint64)
104 PRIMITIVE_TYPE_TRAITS_DEF(int64_t, Int64, int64)
105 PRIMITIVE_TYPE_TRAITS_DEF(float, Float, float32)
106 PRIMITIVE_TYPE_TRAITS_DEF(double, Double, float64)
107 
108 #undef PRIMITIVE_TYPE_TRAITS_DEF
109 #undef PRIMITIVE_TYPE_TRAITS_DEF_
110 
111 template <>
112 struct TypeTraits<Date64Type> {
113   using ArrayType = Date64Array;
114   using BuilderType = Date64Builder;
115   using ScalarType = Date64Scalar;
116   using CType = Date64Type::c_type;
117 
118   static constexpr int64_t bytes_required(int64_t elements) {
119     return elements * static_cast<int64_t>(sizeof(int64_t));
120   }
121   constexpr static bool is_parameter_free = true;
122   static inline std::shared_ptr<DataType> type_singleton() { return date64(); }
123 };
124 
125 template <>
126 struct TypeTraits<Date32Type> {
127   using ArrayType = Date32Array;
128   using BuilderType = Date32Builder;
129   using ScalarType = Date32Scalar;
130   using CType = Date32Type::c_type;
131 
132   static constexpr int64_t bytes_required(int64_t elements) {
133     return elements * static_cast<int64_t>(sizeof(int32_t));
134   }
135   constexpr static bool is_parameter_free = true;
136   static inline std::shared_ptr<DataType> type_singleton() { return date32(); }
137 };
138 
139 template <>
140 struct TypeTraits<TimestampType> {
141   using ArrayType = TimestampArray;
142   using BuilderType = TimestampBuilder;
143   using ScalarType = TimestampScalar;
144   using CType = TimestampType::c_type;
145 
146   static constexpr int64_t bytes_required(int64_t elements) {
147     return elements * static_cast<int64_t>(sizeof(int64_t));
148   }
149   constexpr static bool is_parameter_free = false;
150 };
151 
152 template <>
153 struct TypeTraits<DurationType> {
154   using ArrayType = DurationArray;
155   using BuilderType = DurationBuilder;
156   using ScalarType = DurationScalar;
157   using CType = DurationType::c_type;
158 
159   static constexpr int64_t bytes_required(int64_t elements) {
160     return elements * static_cast<int64_t>(sizeof(int64_t));
161   }
162   constexpr static bool is_parameter_free = false;
163 };
164 
165 template <>
166 struct TypeTraits<DayTimeIntervalType> {
167   using ArrayType = DayTimeIntervalArray;
168   using BuilderType = DayTimeIntervalBuilder;
169   using ScalarType = DayTimeIntervalScalar;
170 
171   static constexpr int64_t bytes_required(int64_t elements) {
172     return elements * static_cast<int64_t>(sizeof(DayTimeIntervalType::DayMilliseconds));
173   }
174   constexpr static bool is_parameter_free = true;
175   static std::shared_ptr<DataType> type_singleton() { return day_time_interval(); }
176 };
177 
178 template <>
179 struct TypeTraits<MonthIntervalType> {
180   using ArrayType = MonthIntervalArray;
181   using BuilderType = MonthIntervalBuilder;
182   using ScalarType = MonthIntervalScalar;
183 
184   static constexpr int64_t bytes_required(int64_t elements) {
185     return elements * static_cast<int64_t>(sizeof(int32_t));
186   }
187   constexpr static bool is_parameter_free = true;
188   static std::shared_ptr<DataType> type_singleton() { return month_interval(); }
189 };
190 
191 template <>
192 struct TypeTraits<Time32Type> {
193   using ArrayType = Time32Array;
194   using BuilderType = Time32Builder;
195   using ScalarType = Time32Scalar;
196   using CType = Time32Type::c_type;
197 
198   static constexpr int64_t bytes_required(int64_t elements) {
199     return elements * static_cast<int64_t>(sizeof(int32_t));
200   }
201   constexpr static bool is_parameter_free = false;
202 };
203 
204 template <>
205 struct TypeTraits<Time64Type> {
206   using ArrayType = Time64Array;
207   using BuilderType = Time64Builder;
208   using ScalarType = Time64Scalar;
209   using CType = Time64Type::c_type;
210 
211   static constexpr int64_t bytes_required(int64_t elements) {
212     return elements * static_cast<int64_t>(sizeof(int64_t));
213   }
214   constexpr static bool is_parameter_free = false;
215 };
216 
217 template <>
218 struct TypeTraits<HalfFloatType> {
219   using ArrayType = HalfFloatArray;
220   using BuilderType = HalfFloatBuilder;
221   using ScalarType = HalfFloatScalar;
222   using TensorType = HalfFloatTensor;
223 
224   static constexpr int64_t bytes_required(int64_t elements) {
225     return elements * static_cast<int64_t>(sizeof(uint16_t));
226   }
227   constexpr static bool is_parameter_free = true;
228   static inline std::shared_ptr<DataType> type_singleton() { return float16(); }
229 };
230 
231 template <>
232 struct TypeTraits<Decimal128Type> {
233   using ArrayType = Decimal128Array;
234   using BuilderType = Decimal128Builder;
235   using ScalarType = Decimal128Scalar;
236   constexpr static bool is_parameter_free = false;
237 };
238 
239 template <>
240 struct TypeTraits<BinaryType> {
241   using ArrayType = BinaryArray;
242   using BuilderType = BinaryBuilder;
243   using ScalarType = BinaryScalar;
244   constexpr static bool is_parameter_free = true;
245   static inline std::shared_ptr<DataType> type_singleton() { return binary(); }
246 };
247 
248 template <>
249 struct TypeTraits<LargeBinaryType> {
250   using ArrayType = LargeBinaryArray;
251   using BuilderType = LargeBinaryBuilder;
252   using ScalarType = LargeBinaryScalar;
253   constexpr static bool is_parameter_free = true;
254   static inline std::shared_ptr<DataType> type_singleton() { return large_binary(); }
255 };
256 
257 template <>
258 struct TypeTraits<FixedSizeBinaryType> {
259   using ArrayType = FixedSizeBinaryArray;
260   using BuilderType = FixedSizeBinaryBuilder;
261   using ScalarType = FixedSizeBinaryScalar;
262   constexpr static bool is_parameter_free = false;
263 };
264 
265 template <>
266 struct TypeTraits<StringType> {
267   using ArrayType = StringArray;
268   using BuilderType = StringBuilder;
269   using ScalarType = StringScalar;
270   using OffsetType = Int32Type;
271   constexpr static bool is_parameter_free = true;
272   static inline std::shared_ptr<DataType> type_singleton() { return utf8(); }
273 };
274 
275 template <>
276 struct TypeTraits<LargeStringType> {
277   using ArrayType = LargeStringArray;
278   using BuilderType = LargeStringBuilder;
279   using ScalarType = LargeStringScalar;
280   using OffsetType = Int64Type;
281   constexpr static bool is_parameter_free = true;
282   static inline std::shared_ptr<DataType> type_singleton() { return large_utf8(); }
283 };
284 
285 template <>
286 struct CTypeTraits<std::string> : public TypeTraits<StringType> {
287   using ArrowType = StringType;
288 };
289 
290 template <>
291 struct CTypeTraits<const char*> : public CTypeTraits<std::string> {};
292 
293 template <size_t N>
294 struct CTypeTraits<const char (&)[N]> : public CTypeTraits<std::string> {};
295 
296 template <>
297 struct CTypeTraits<DayTimeIntervalType::DayMilliseconds>
298     : public TypeTraits<DayTimeIntervalType> {
299   using ArrowType = DayTimeIntervalType;
300 };
301 
302 template <>
303 struct TypeTraits<ListType> {
304   using ArrayType = ListArray;
305   using BuilderType = ListBuilder;
306   using ScalarType = ListScalar;
307   using OffsetType = Int32Type;
308   using OffsetArrayType = Int32Array;
309   using OffsetBuilderType = Int32Builder;
310   constexpr static bool is_parameter_free = false;
311 };
312 
313 template <>
314 struct TypeTraits<LargeListType> {
315   using ArrayType = LargeListArray;
316   using BuilderType = LargeListBuilder;
317   using ScalarType = LargeListScalar;
318   using OffsetType = Int64Type;
319   using OffsetArrayType = Int64Array;
320   using OffsetBuilderType = Int64Builder;
321   constexpr static bool is_parameter_free = false;
322 };
323 
324 template <>
325 struct TypeTraits<MapType> {
326   using ArrayType = MapArray;
327   using BuilderType = MapBuilder;
328   using ScalarType = MapScalar;
329   using OffsetType = Int32Type;
330   using OffsetArrayType = Int32Array;
331   using OffsetBuilderType = Int32Builder;
332   constexpr static bool is_parameter_free = false;
333 };
334 
335 template <>
336 struct TypeTraits<FixedSizeListType> {
337   using ArrayType = FixedSizeListArray;
338   using BuilderType = FixedSizeListBuilder;
339   using ScalarType = FixedSizeListScalar;
340   constexpr static bool is_parameter_free = false;
341 };
342 
343 template <typename CType>
344 struct CTypeTraits<std::vector<CType>> : public TypeTraits<ListType> {
345   using ArrowType = ListType;
346 
347   static inline std::shared_ptr<DataType> type_singleton() {
348     return list(CTypeTraits<CType>::type_singleton());
349   }
350 };
351 
352 template <>
353 struct TypeTraits<StructType> {
354   using ArrayType = StructArray;
355   using BuilderType = StructBuilder;
356   using ScalarType = StructScalar;
357   constexpr static bool is_parameter_free = false;
358 };
359 
360 template <>
361 struct TypeTraits<UnionType> {
362   using ArrayType = UnionArray;
363   using ScalarType = UnionScalar;
364   constexpr static bool is_parameter_free = false;
365 };
366 
367 template <>
368 struct TypeTraits<DictionaryType> {
369   using ArrayType = DictionaryArray;
370   using ScalarType = DictionaryScalar;
371   constexpr static bool is_parameter_free = false;
372 };
373 
374 template <>
375 struct TypeTraits<ExtensionType> {
376   using ArrayType = ExtensionArray;
377   using ScalarType = ExtensionScalar;
378   constexpr static bool is_parameter_free = false;
379 };
380 
381 namespace internal {
382 
383 template <typename... Ts>
384 struct make_void {
385   using type = void;
386 };
387 
388 template <typename... Ts>
389 using void_t = typename make_void<Ts...>::type;
390 
391 }  // namespace internal
392 
393 //
394 // Useful type predicates
395 //
396 
397 // only in C++14
398 template <bool B, typename T = void>
399 using enable_if_t = typename std::enable_if<B, T>::type;
400 
401 template <typename T>
402 using is_null_type = std::is_same<NullType, T>;
403 
404 template <typename T, typename R = void>
405 using enable_if_null = enable_if_t<is_null_type<T>::value, R>;
406 
407 template <typename T>
408 using is_boolean_type = std::is_same<BooleanType, T>;
409 
410 template <typename T, typename R = void>
411 using enable_if_boolean = enable_if_t<is_boolean_type<T>::value, R>;
412 
413 template <typename T>
414 using is_number_type = std::is_base_of<NumberType, T>;
415 
416 template <typename T, typename R = void>
417 using enable_if_number = enable_if_t<is_number_type<T>::value, R>;
418 
419 template <typename T>
420 using is_integer_type = std::is_base_of<IntegerType, T>;
421 
422 template <typename T, typename R = void>
423 using enable_if_integer = enable_if_t<is_integer_type<T>::value, R>;
424 
425 template <typename T>
426 using is_signed_integer_type =
427     std::integral_constant<bool, is_integer_type<T>::value &&
428                                      std::is_signed<typename T::c_type>::value>;
429 
430 template <typename T, typename R = void>
431 using enable_if_signed_integer = enable_if_t<is_signed_integer_type<T>::value, R>;
432 
433 template <typename T>
434 using is_unsigned_integer_type =
435     std::integral_constant<bool, is_integer_type<T>::value &&
436                                      std::is_unsigned<typename T::c_type>::value>;
437 
438 template <typename T, typename R = void>
439 using enable_if_unsigned_integer = enable_if_t<is_unsigned_integer_type<T>::value, R>;
440 
441 // Note this will also include HalfFloatType which is represented by a
442 // non-floating point primitive (uint16_t).
443 template <typename T>
444 using is_floating_type = std::is_base_of<FloatingPointType, T>;
445 
446 template <typename T, typename R = void>
447 using enable_if_floating_point = enable_if_t<is_floating_type<T>::value, R>;
448 
449 // Half floats are special in that they behave physically like an unsigned
450 // integer.
451 template <typename T>
452 using is_half_float_type = std::is_same<HalfFloatType, T>;
453 
454 template <typename T, typename R = void>
455 using enable_if_half_float = enable_if_t<is_half_float_type<T>::value, R>;
456 
457 // Binary Types
458 
459 // Base binary refers to Binary/LargeBinary/String/LargeString
460 template <typename T>
461 using is_base_binary_type = std::is_base_of<BaseBinaryType, T>;
462 
463 template <typename T, typename R = void>
464 using enable_if_base_binary = enable_if_t<is_base_binary_type<T>::value, R>;
465 
466 // Any binary excludes string from Base binary
467 template <typename T>
468 using is_any_binary_type =
469     std::integral_constant<bool, std::is_same<BinaryType, T>::value ||
470                                      std::is_same<LargeBinaryType, T>::value>;
471 
472 template <typename T, typename R = void>
473 using enable_if_any_binary = enable_if_t<is_any_binary_type<T>::value, R>;
474 
475 template <typename T>
476 using is_string_like_type =
477     std::integral_constant<bool, is_base_binary_type<T>::value && T::is_utf8>;
478 
479 template <typename T, typename R = void>
480 using enable_if_string_like = enable_if_t<is_string_like_type<T>::value, R>;
481 
482 // Note that this also includes DecimalType
483 template <typename T>
484 using is_fixed_size_binary_type = std::is_base_of<FixedSizeBinaryType, T>;
485 
486 template <typename T, typename R = void>
487 using enable_if_fixed_size_binary = enable_if_t<is_fixed_size_binary_type<T>::value, R>;
488 
489 template <typename T>
490 using is_binary_like_type =
491     std::integral_constant<bool, (is_base_binary_type<T>::value &&
492                                   !is_string_like_type<T>::value) ||
493                                      is_fixed_size_binary_type<T>::value>;
494 
495 template <typename T, typename R = void>
496 using enable_if_binary_like = enable_if_t<is_binary_like_type<T>::value, R>;
497 
498 template <typename T>
499 using is_decimal_type = std::is_base_of<DecimalType, T>;
500 
501 template <typename T, typename R = void>
502 using enable_if_decimal = enable_if_t<is_decimal_type<T>::value, R>;
503 
504 // Nested Types
505 
506 template <typename T>
507 using is_nested_type = std::is_base_of<NestedType, T>;
508 
509 template <typename T, typename R = void>
510 using enable_if_nested = enable_if_t<is_nested_type<T>::value, R>;
511 
512 template <typename T>
513 using is_var_length_list_type =
514     std::integral_constant<bool, std::is_base_of<LargeListType, T>::value ||
515                                      std::is_base_of<ListType, T>::value>;
516 
517 template <typename T, typename R = void>
518 using enable_if_var_size_list = enable_if_t<is_var_length_list_type<T>::value, R>;
519 
520 // DEPRECATED use is_var_length_list_type.
521 template <typename T>
522 using is_base_list_type = is_var_length_list_type<T>;
523 
524 // DEPRECATED use enable_if_var_size_list
525 template <typename T, typename R = void>
526 using enable_if_base_list = enable_if_var_size_list<T, R>;
527 
528 template <typename T>
529 using is_fixed_size_list_type = std::is_same<FixedSizeListType, T>;
530 
531 template <typename T, typename R = void>
532 using enable_if_fixed_size_list = enable_if_t<is_fixed_size_list_type<T>::value, R>;
533 
534 template <typename T>
535 using is_list_like_type =
536     std::integral_constant<bool, is_base_list_type<T>::value ||
537                                      is_fixed_size_list_type<T>::value>;
538 
539 template <typename T, typename R = void>
540 using enable_if_list_like = enable_if_t<is_list_like_type<T>::value, R>;
541 
542 template <typename T>
543 using is_struct_type = std::is_base_of<StructType, T>;
544 
545 template <typename T, typename R = void>
546 using enable_if_struct = enable_if_t<is_struct_type<T>::value, R>;
547 
548 template <typename T>
549 using is_union_type = std::is_base_of<UnionType, T>;
550 
551 template <typename T, typename R = void>
552 using enable_if_union = enable_if_t<is_union_type<T>::value, R>;
553 
554 // TemporalTypes
555 
556 template <typename T>
557 using is_temporal_type = std::is_base_of<TemporalType, T>;
558 
559 template <typename T, typename R = void>
560 using enable_if_temporal = enable_if_t<is_temporal_type<T>::value, R>;
561 
562 template <typename T>
563 using is_date_type = std::is_base_of<DateType, T>;
564 
565 template <typename T, typename R = void>
566 using enable_if_date = enable_if_t<is_date_type<T>::value, R>;
567 
568 template <typename T>
569 using is_time_type = std::is_base_of<TimeType, T>;
570 
571 template <typename T, typename R = void>
572 using enable_if_time = enable_if_t<is_time_type<T>::value, R>;
573 
574 template <typename T>
575 using is_timestamp_type = std::is_base_of<TimestampType, T>;
576 
577 template <typename T, typename R = void>
578 using enable_if_timestamp = enable_if_t<is_timestamp_type<T>::value, R>;
579 
580 template <typename T>
581 using is_duration_type = std::is_base_of<DurationType, T>;
582 
583 template <typename T, typename R = void>
584 using enable_if_duration = enable_if_t<is_duration_type<T>::value, R>;
585 
586 template <typename T>
587 using is_interval_type = std::is_base_of<IntervalType, T>;
588 
589 template <typename T, typename R = void>
590 using enable_if_interval = enable_if_t<is_interval_type<T>::value, R>;
591 
592 // Attribute differentiation
593 
594 template <typename T>
595 using is_primitive_ctype = std::is_base_of<PrimitiveCType, T>;
596 
597 template <typename T, typename R = void>
598 using enable_if_primitive_ctype = enable_if_t<is_primitive_ctype<T>::value, R>;
599 
600 template <typename T>
601 using has_c_type = std::integral_constant<bool, is_primitive_ctype<T>::value ||
602                                                     is_temporal_type<T>::value>;
603 
604 template <typename T, typename R = void>
605 using enable_if_has_c_type = enable_if_t<has_c_type<T>::value, R>;
606 
607 template <typename T>
608 using has_string_view = std::integral_constant<bool, is_binary_like_type<T>::value ||
609                                                          is_string_like_type<T>::value>;
610 
611 template <typename T, typename R = void>
612 using enable_if_has_string_view = enable_if_t<has_string_view<T>::value, R>;
613 
614 template <typename T>
615 using is_8bit_int = std::integral_constant<bool, std::is_same<UInt8Type, T>::value ||
616                                                      std::is_same<Int8Type, T>::value>;
617 
618 template <typename T, typename R = void>
619 using enable_if_8bit_int = enable_if_t<is_8bit_int<T>::value, R>;
620 
621 template <typename T>
622 using is_parameter_free_type =
623     std::integral_constant<bool, TypeTraits<T>::is_parameter_free>;
624 
625 template <typename T, typename R = void>
626 using enable_if_parameter_free = enable_if_t<is_parameter_free_type<T>::value, R>;
627 
628 // Physical representation quirks
629 
630 template <typename T>
631 using is_physical_signed_integer_type =
632     std::integral_constant<bool,
633                            is_signed_integer_type<T>::value ||
634                                (is_temporal_type<T>::value && has_c_type<T>::value)>;
635 
636 template <typename T, typename R = void>
637 using enable_if_physical_signed_integer =
638     enable_if_t<is_physical_signed_integer_type<T>::value, R>;
639 
640 template <typename T>
641 using is_physical_unsigned_integer_type =
642     std::integral_constant<bool, is_unsigned_integer_type<T>::value ||
643                                      is_half_float_type<T>::value>;
644 
645 template <typename T, typename R = void>
646 using enable_if_physical_unsigned_integer =
647     enable_if_t<is_physical_unsigned_integer_type<T>::value, R>;
648 
649 // Like is_floating_type but excluding half-floats which don't have a
650 // float-like c type.
651 template <typename T>
652 using is_physical_floating_type =
653     std::integral_constant<bool,
654                            is_floating_type<T>::value && !is_half_float_type<T>::value>;
655 
656 template <typename T, typename R = void>
657 using enable_if_physical_floating_point =
658     enable_if_t<is_physical_floating_type<T>::value, R>;
659 
660 static inline bool is_integer(Type::type type_id) {
661   switch (type_id) {
662     case Type::UINT8:
663     case Type::INT8:
664     case Type::UINT16:
665     case Type::INT16:
666     case Type::UINT32:
667     case Type::INT32:
668     case Type::UINT64:
669     case Type::INT64:
670       return true;
671     default:
672       break;
673   }
674   return false;
675 }
676 
677 static inline bool is_floating(Type::type type_id) {
678   switch (type_id) {
679     case Type::HALF_FLOAT:
680     case Type::FLOAT:
681     case Type::DOUBLE:
682       return true;
683     default:
684       break;
685   }
686   return false;
687 }
688 
689 static inline bool is_primitive(Type::type type_id) {
690   switch (type_id) {
691     case Type::NA:
692     case Type::BOOL:
693     case Type::UINT8:
694     case Type::INT8:
695     case Type::UINT16:
696     case Type::INT16:
697     case Type::UINT32:
698     case Type::INT32:
699     case Type::UINT64:
700     case Type::INT64:
701     case Type::HALF_FLOAT:
702     case Type::FLOAT:
703     case Type::DOUBLE:
704     case Type::DATE32:
705     case Type::DATE64:
706     case Type::TIME32:
707     case Type::TIME64:
708     case Type::TIMESTAMP:
709     case Type::DURATION:
710     case Type::INTERVAL_MONTHS:
711     case Type::INTERVAL_DAY_TIME:
712       return true;
713     default:
714       break;
715   }
716   return false;
717 }
718 
719 static inline bool is_base_binary_like(Type::type type_id) {
720   switch (type_id) {
721     case Type::BINARY:
722     case Type::LARGE_BINARY:
723     case Type::STRING:
724     case Type::LARGE_STRING:
725       return true;
726     default:
727       break;
728   }
729   return false;
730 }
731 
732 static inline bool is_binary_like(Type::type type_id) {
733   switch (type_id) {
734     case Type::BINARY:
735     case Type::STRING:
736       return true;
737     default:
738       break;
739   }
740   return false;
741 }
742 
743 static inline bool is_large_binary_like(Type::type type_id) {
744   switch (type_id) {
745     case Type::LARGE_BINARY:
746     case Type::LARGE_STRING:
747       return true;
748     default:
749       break;
750   }
751   return false;
752 }
753 
754 static inline bool is_dictionary(Type::type type_id) {
755   return type_id == Type::DICTIONARY;
756 }
757 
758 static inline bool is_fixed_size_binary(Type::type type_id) {
759   switch (type_id) {
760     case Type::DECIMAL:
761     case Type::FIXED_SIZE_BINARY:
762       return true;
763     default:
764       break;
765   }
766   return false;
767 }
768 
769 static inline bool is_fixed_width(Type::type type_id) {
770   return is_primitive(type_id) || is_dictionary(type_id) || is_fixed_size_binary(type_id);
771 }
772 
773 static inline bool is_nested(Type::type type_id) {
774   switch (type_id) {
775     case Type::LIST:
776     case Type::LARGE_LIST:
777     case Type::FIXED_SIZE_LIST:
778     case Type::MAP:
779     case Type::STRUCT:
780     case Type::UNION:
781       return true;
782     default:
783       break;
784   }
785   return false;
786 }
787 
788 }  // namespace arrow
789