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
18module Arrow
19  class Datum
20    class << self
21      # @api private
22      def try_convert(value)
23        case value
24        when Table
25          TableDatum.new(value)
26        when Array
27          ArrayDatum.new(value)
28        when ChunkedArray
29          ChunkedArrayDatum.new(value)
30        when Scalar
31          ScalarDatum.new(value)
32        when ::Array
33          ArrayDatum.new(ArrayBuilder.build(value))
34        when Integer
35          case value
36          when (0..((2 ** 8) - 1))
37            try_convert(UInt8Scalar.new(value))
38          when ((-(2 ** 7))..((2 ** 7) - 1))
39            try_convert(Int8Scalar.new(value))
40          when (0..((2 ** 16) - 1))
41            try_convert(UInt16Scalar.new(value))
42          when ((-(2 ** 15))..((2 ** 15) - 1))
43            try_convert(Int16Scalar.new(value))
44          when (0..((2 ** 32) - 1))
45            try_convert(UInt32Scalar.new(value))
46          when ((-(2 ** 31))..((2 ** 31) - 1))
47            try_convert(Int32Scalar.new(value))
48          when (0..((2 ** 64) - 1))
49            try_convert(UInt64Scalar.new(value))
50          when ((-(2 ** 63))..((2 ** 63) - 1))
51            try_convert(Int64Scalar.new(value))
52          else
53            nil
54          end
55        when Float
56          try_convert(DoubleScalar.new(value))
57        when true, false
58          try_convert(BooleanScalar.new(value))
59        when String
60          if value.ascii_only? or value.encoding == Encoding::UTF_8
61            if value.bytesize <= ((2 ** 31) - 1)
62              try_convert(StringScalar.new(value))
63            else
64              try_convert(LargeStringScalar.new(value))
65            end
66          else
67            if value.bytesize <= ((2 ** 31) - 1)
68              try_convert(BinaryScalar.new(value))
69            else
70              try_convert(LargeBinaryScalar.new(value))
71            end
72          end
73        when Date
74          date32_value = (value - Date32ArrayBuilder::UNIX_EPOCH).to_i
75          try_convert(Date32Scalar.new(date32_value))
76        when Time
77          case value.unit
78          when TimeUnit::SECOND, TimeUnit::MILLI
79            data_type = Time32DataType.new(value.unit)
80            scalar_class = Time32Scalar
81          else
82            data_type = Time64DataType.new(value.unit)
83            scalar_class = Time64Scalar
84          end
85          try_convert(scalar_class.new(data_type, value.value))
86        when ::Time
87          data_type = TimestampDataType.new(:nano)
88          timestamp_value = value.to_i * 1_000_000_000 + value.nsec
89          try_convert(TimestampScalar.new(data_type, timestamp_value))
90        when Decimal128
91          data_type = TimestampDataType.new(:nano)
92          timestamp_value = value.to_i * 1_000_000_000 + value.nsec
93          try_convert(Decimal128Scalar.new(data_type, timestamp_value))
94        else
95          nil
96        end
97      end
98    end
99  end
100end
101