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#ifndef ARROW_STL_H
19#define ARROW_STL_H
20
21#include <memory>
22#include <string>
23#include <tuple>
24#include <vector>
25
26#include "arrow/type.h"
27
28namespace arrow {
29
30class Schema;
31
32namespace stl {
33
34/// Traits meta class to map standard C/C++ types to equivalent Arrow types.
35template <typename T>
36struct ConversionTraits {};
37
38#define ARROW_STL_CONVERSION(c_type, ArrowType_) \
39 template <> \
40 struct ConversionTraits<c_type> { \
41 static std::shared_ptr<DataType> arrow_type() { \
42 return std::make_shared<ArrowType_>(); \
43 } \
44 constexpr static bool nullable = false; \
45 };
46
47ARROW_STL_CONVERSION(bool, BooleanType)
48ARROW_STL_CONVERSION(int8_t, Int8Type)
49ARROW_STL_CONVERSION(int16_t, Int16Type)
50ARROW_STL_CONVERSION(int32_t, Int32Type)
51ARROW_STL_CONVERSION(int64_t, Int64Type)
52ARROW_STL_CONVERSION(uint8_t, UInt8Type)
53ARROW_STL_CONVERSION(uint16_t, UInt16Type)
54ARROW_STL_CONVERSION(uint32_t, UInt32Type)
55ARROW_STL_CONVERSION(uint64_t, UInt64Type)
56ARROW_STL_CONVERSION(float, FloatType)
57ARROW_STL_CONVERSION(double, DoubleType)
58ARROW_STL_CONVERSION(std::string, StringType)
59
60template <typename value_c_type>
61struct ConversionTraits<std::vector<value_c_type>> {
62 static std::shared_ptr<DataType> arrow_type() {
63 return list(ConversionTraits<value_c_type>::arrow_type());
64 }
65 constexpr static bool nullable = false;
66};
67
68/// Build an arrow::Schema based upon the types defined in a std::tuple-like structure.
69///
70/// While the type information is available at compile-time, we still need to add the
71/// column names at runtime, thus these methods are not constexpr.
72template <typename Tuple, std::size_t N = std::tuple_size<Tuple>::value>
73struct SchemaFromTuple {
74 using Element = typename std::tuple_element<N - 1, Tuple>::type;
75
76 // Implementations that take a vector-like object for the column names.
77
78 /// Recursively build a vector of arrow::Field from the defined types.
79 ///
80 /// In most cases MakeSchema is the better entrypoint for the Schema creation.
81 static std::vector<std::shared_ptr<Field>> MakeSchemaRecursion(
82 const std::vector<std::string>& names) {
83 std::vector<std::shared_ptr<Field>> ret =
84 SchemaFromTuple<Tuple, N - 1>::MakeSchemaRecursion(names);
85 std::shared_ptr<DataType> type = ConversionTraits<Element>::arrow_type();
86 ret.push_back(field(names[N - 1], type, ConversionTraits<Element>::nullable));
87 return ret;
88 }
89
90 /// Build a Schema from the types of the tuple-like structure passed in as template
91 /// parameter assign the column names at runtime.
92 ///
93 /// An example usage of this API can look like the following:
94 ///
95 /// \code{.cpp}
96 /// using TupleType = std::tuple<int, std::vector<std::string>>;
97 /// std::shared_ptr<Schema> schema =
98 /// SchemaFromTuple<TupleType>::MakeSchema({"int_column", "list_of_strings_column"});
99 /// \endcode
100 static std::shared_ptr<Schema> MakeSchema(const std::vector<std::string>& names) {
101 return std::make_shared<Schema>(MakeSchemaRecursion(names));
102 }
103
104 // Implementations that take a tuple-like object for the column names.
105
106 /// Recursively build a vector of arrow::Field from the defined types.
107 ///
108 /// In most cases MakeSchema is the better entrypoint for the Schema creation.
109 template <typename NamesTuple>
110 static std::vector<std::shared_ptr<Field>> MakeSchemaRecursionT(
111 const NamesTuple& names) {
112 std::vector<std::shared_ptr<Field>> ret =
113 SchemaFromTuple<Tuple, N - 1>::MakeSchemaRecursionT(names);
114 std::shared_ptr<DataType> type = ConversionTraits<Element>::arrow_type();
115 ret.push_back(
116 field(std::get<N - 1>(names), type, ConversionTraits<Element>::nullable));
117 return ret;
118 }
119
120 /// Build a Schema from the types of the tuple-like structure passed in as template
121 /// parameter assign the column names at runtime.
122 ///
123 /// An example usage of this API can look like the following:
124 ///
125 /// \code{.cpp}
126 /// using TupleType = std::tuple<int, std::vector<std::string>>;
127 /// std::shared_ptr<Schema> schema =
128 /// SchemaFromTuple<TupleType>::MakeSchema({"int_column", "list_of_strings_column"});
129 /// \endcode
130 template <typename NamesTuple>
131 static std::shared_ptr<Schema> MakeSchema(const NamesTuple& names) {
132 return std::make_shared<Schema>(MakeSchemaRecursionT<NamesTuple>(names));
133 }
134};
135
136template <typename Tuple>
137struct SchemaFromTuple<Tuple, 0> {
138 static std::vector<std::shared_ptr<Field>> MakeSchemaRecursion(
139 const std::vector<std::string>& names) {
140 std::vector<std::shared_ptr<Field>> ret;
141 ret.reserve(names.size());
142 return ret;
143 }
144
145 template <typename NamesTuple>
146 static std::vector<std::shared_ptr<Field>> MakeSchemaRecursionT(
147 const NamesTuple& names) {
148 std::vector<std::shared_ptr<Field>> ret;
149 ret.reserve(std::tuple_size<NamesTuple>::value);
150 return ret;
151 }
152};
153/// @endcond
154
155} // namespace stl
156} // namespace arrow
157
158#endif // ARROW_STL_H
159