This is an automated email from the ASF dual-hosted git repository.

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git


The following commit(s) were added to refs/heads/main by this push:
     new f918093  refactor(arrow/array): replace some codegen with generics 
(#315)
f918093 is described below

commit f91809315974aefd45bc117eb4723910034a668f
Author: Matt Topol <[email protected]>
AuthorDate: Mon Mar 17 10:24:33 2025 -0400

    refactor(arrow/array): replace some codegen with generics (#315)
    
    ### Rationale for this change
    Simplifying code and removing old code-gen
    
    ### What changes are included in this PR?
    Replacing the old `numeric.gen.go` and `numeric.gen.go.tmpl` with a new
    version built using go generics.
    
    ### Are these changes tested?
    All the same unit tests will test the new versions of the objects
    
    ### Are there any user-facing changes?
    There shouldn't be any user-facing changes. Everything was designed to
    avoid any public breaking changes.
---
 arrow/array.go                  |   12 +
 arrow/array/binary.go           |    4 +
 arrow/array/boolean.go          |    3 +-
 arrow/array/compare.go          |   58 +-
 arrow/array/decimal.go          |    5 +
 arrow/array/float16.go          |    3 +-
 arrow/array/interval.go         |    4 +
 arrow/array/numeric.gen.go      | 1469 ---------------------------------------
 arrow/array/numeric.gen.go.tmpl |  192 -----
 arrow/array/numeric_generic.go  |  418 +++++++++++
 arrow/array/string.go           |    4 +
 arrow/array/timestamp.go        |    5 +-
 12 files changed, 483 insertions(+), 1694 deletions(-)

diff --git a/arrow/array.go b/arrow/array.go
index df186f2..d42ca6d 100644
--- a/arrow/array.go
+++ b/arrow/array.go
@@ -127,3 +127,15 @@ type Array interface {
        // When the reference count goes to zero, the memory is freed.
        Release()
 }
+
+// ValueType is a generic constraint for valid Arrow primitive types
+type ValueType interface {
+       bool | FixedWidthType | string | []byte
+}
+
+// TypedArray is an interface representing an Array of a particular type
+// allowing for easy propagation of generics
+type TypedArray[T ValueType] interface {
+       Array
+       Value(int) T
+}
diff --git a/arrow/array/binary.go b/arrow/array/binary.go
index 1af7631..ab53c8a 100644
--- a/arrow/array/binary.go
+++ b/arrow/array/binary.go
@@ -450,4 +450,8 @@ var (
 
        _ BinaryLike = (*Binary)(nil)
        _ BinaryLike = (*LargeBinary)(nil)
+
+       _ arrow.TypedArray[[]byte] = (*Binary)(nil)
+       _ arrow.TypedArray[[]byte] = (*LargeBinary)(nil)
+       _ arrow.TypedArray[[]byte] = (*BinaryView)(nil)
 )
diff --git a/arrow/array/boolean.go b/arrow/array/boolean.go
index fb2dba7..e610996 100644
--- a/arrow/array/boolean.go
+++ b/arrow/array/boolean.go
@@ -122,5 +122,6 @@ func arrayEqualBoolean(left, right *Boolean) bool {
 }
 
 var (
-       _ arrow.Array = (*Boolean)(nil)
+       _ arrow.Array            = (*Boolean)(nil)
+       _ arrow.TypedArray[bool] = (*Boolean)(nil)
 )
diff --git a/arrow/array/compare.go b/arrow/array/compare.go
index e412feb..fda15f5 100644
--- a/arrow/array/compare.go
+++ b/arrow/array/compare.go
@@ -240,37 +240,37 @@ func Equal(left, right arrow.Array) bool {
                return arrayEqualStringView(l, r)
        case *Int8:
                r := right.(*Int8)
-               return arrayEqualInt8(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Int16:
                r := right.(*Int16)
-               return arrayEqualInt16(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Int32:
                r := right.(*Int32)
-               return arrayEqualInt32(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Int64:
                r := right.(*Int64)
-               return arrayEqualInt64(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Uint8:
                r := right.(*Uint8)
-               return arrayEqualUint8(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Uint16:
                r := right.(*Uint16)
-               return arrayEqualUint16(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Uint32:
                r := right.(*Uint32)
-               return arrayEqualUint32(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Uint64:
                r := right.(*Uint64)
-               return arrayEqualUint64(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Float16:
                r := right.(*Float16)
-               return arrayEqualFloat16(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Float32:
                r := right.(*Float32)
-               return arrayEqualFloat32(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Float64:
                r := right.(*Float64)
-               return arrayEqualFloat64(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Decimal32:
                r := right.(*Decimal32)
                return arrayEqualDecimal(l, r)
@@ -285,16 +285,16 @@ func Equal(left, right arrow.Array) bool {
                return arrayEqualDecimal(l, r)
        case *Date32:
                r := right.(*Date32)
-               return arrayEqualDate32(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Date64:
                r := right.(*Date64)
-               return arrayEqualDate64(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Time32:
                r := right.(*Time32)
-               return arrayEqualTime32(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Time64:
                r := right.(*Time64)
-               return arrayEqualTime64(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Timestamp:
                r := right.(*Timestamp)
                return arrayEqualTimestamp(l, r)
@@ -327,7 +327,7 @@ func Equal(left, right arrow.Array) bool {
                return arrayEqualMonthDayNanoInterval(l, r)
        case *Duration:
                r := right.(*Duration)
-               return arrayEqualDuration(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Map:
                r := right.(*Map)
                return arrayEqualMap(l, r)
@@ -502,28 +502,28 @@ func arrayApproxEqual(left, right arrow.Array, opt 
equalOption) bool {
                return arrayApproxEqualStringView(l, r)
        case *Int8:
                r := right.(*Int8)
-               return arrayEqualInt8(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Int16:
                r := right.(*Int16)
-               return arrayEqualInt16(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Int32:
                r := right.(*Int32)
-               return arrayEqualInt32(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Int64:
                r := right.(*Int64)
-               return arrayEqualInt64(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Uint8:
                r := right.(*Uint8)
-               return arrayEqualUint8(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Uint16:
                r := right.(*Uint16)
-               return arrayEqualUint16(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Uint32:
                r := right.(*Uint32)
-               return arrayEqualUint32(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Uint64:
                r := right.(*Uint64)
-               return arrayEqualUint64(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Float16:
                r := right.(*Float16)
                return arrayApproxEqualFloat16(l, r, opt)
@@ -547,16 +547,16 @@ func arrayApproxEqual(left, right arrow.Array, opt 
equalOption) bool {
                return arrayEqualDecimal(l, r)
        case *Date32:
                r := right.(*Date32)
-               return arrayEqualDate32(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Date64:
                r := right.(*Date64)
-               return arrayEqualDate64(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Time32:
                r := right.(*Time32)
-               return arrayEqualTime32(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Time64:
                r := right.(*Time64)
-               return arrayEqualTime64(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Timestamp:
                r := right.(*Timestamp)
                return arrayEqualTimestamp(l, r)
@@ -589,7 +589,7 @@ func arrayApproxEqual(left, right arrow.Array, opt 
equalOption) bool {
                return arrayEqualMonthDayNanoInterval(l, r)
        case *Duration:
                r := right.(*Duration)
-               return arrayEqualDuration(l, r)
+               return arrayEqualFixedWidth(l, r)
        case *Map:
                r := right.(*Map)
                if opt.unorderedMapKeys {
diff --git a/arrow/array/decimal.go b/arrow/array/decimal.go
index 1a9d61c..8bbbc1a 100644
--- a/arrow/array/decimal.go
+++ b/arrow/array/decimal.go
@@ -429,4 +429,9 @@ var (
        _ Builder     = (*Decimal64Builder)(nil)
        _ Builder     = (*Decimal128Builder)(nil)
        _ Builder     = (*Decimal256Builder)(nil)
+
+       _ arrow.TypedArray[decimal.Decimal32]  = (*Decimal32)(nil)
+       _ arrow.TypedArray[decimal.Decimal64]  = (*Decimal64)(nil)
+       _ arrow.TypedArray[decimal.Decimal128] = (*Decimal128)(nil)
+       _ arrow.TypedArray[decimal.Decimal256] = (*Decimal256)(nil)
 )
diff --git a/arrow/array/float16.go b/arrow/array/float16.go
index 6b0e820..c98362d 100644
--- a/arrow/array/float16.go
+++ b/arrow/array/float16.go
@@ -119,5 +119,6 @@ func arrayEqualFloat16(left, right *Float16) bool {
 }
 
 var (
-       _ arrow.Array = (*Float16)(nil)
+       _ arrow.Array                   = (*Float16)(nil)
+       _ arrow.TypedArray[float16.Num] = (*Float16)(nil)
 )
diff --git a/arrow/array/interval.go b/arrow/array/interval.go
index 324647e..a9c52d3 100644
--- a/arrow/array/interval.go
+++ b/arrow/array/interval.go
@@ -950,4 +950,8 @@ var (
        _ Builder = (*MonthIntervalBuilder)(nil)
        _ Builder = (*DayTimeIntervalBuilder)(nil)
        _ Builder = (*MonthDayNanoIntervalBuilder)(nil)
+
+       _ arrow.TypedArray[arrow.MonthInterval]        = (*MonthInterval)(nil)
+       _ arrow.TypedArray[arrow.DayTimeInterval]      = (*DayTimeInterval)(nil)
+       _ arrow.TypedArray[arrow.MonthDayNanoInterval] = 
(*MonthDayNanoInterval)(nil)
 )
diff --git a/arrow/array/numeric.gen.go b/arrow/array/numeric.gen.go
deleted file mode 100644
index 7e94fe5..0000000
--- a/arrow/array/numeric.gen.go
+++ /dev/null
@@ -1,1469 +0,0 @@
-// Code generated by array/numeric.gen.go.tmpl. DO NOT EDIT.
-
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package array
-
-import (
-       "fmt"
-       "math"
-       "strconv"
-       "strings"
-
-       "github.com/apache/arrow-go/v18/arrow"
-       "github.com/apache/arrow-go/v18/internal/json"
-)
-
-// A type which represents an immutable sequence of int64 values.
-type Int64 struct {
-       array
-       values []int64
-}
-
-// NewInt64Data creates a new Int64.
-func NewInt64Data(data arrow.ArrayData) *Int64 {
-       a := &Int64{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Int64) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Int64) Value(i int) int64 { return a.values[i] }
-
-// Values returns the values.
-func (a *Int64) Int64Values() []int64 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Int64) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Int64) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Int64Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Int64) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return strconv.FormatInt(int64(a.Value(i)), 10)
-}
-
-func (a *Int64) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-
-       return a.values[i]
-}
-
-func (a *Int64) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := 0; i < a.Len(); i++ {
-
-               if a.IsValid(i) {
-                       vals[i] = a.values[i]
-               } else {
-                       vals[i] = nil
-               }
-
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualInt64(left, right *Int64) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of uint64 values.
-type Uint64 struct {
-       array
-       values []uint64
-}
-
-// NewUint64Data creates a new Uint64.
-func NewUint64Data(data arrow.ArrayData) *Uint64 {
-       a := &Uint64{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Uint64) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Uint64) Value(i int) uint64 { return a.values[i] }
-
-// Values returns the values.
-func (a *Uint64) Uint64Values() []uint64 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Uint64) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Uint64) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Uint64Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Uint64) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return strconv.FormatUint(uint64(a.Value(i)), 10)
-}
-
-func (a *Uint64) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-
-       return a.values[i]
-}
-
-func (a *Uint64) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := 0; i < a.Len(); i++ {
-
-               if a.IsValid(i) {
-                       vals[i] = a.values[i]
-               } else {
-                       vals[i] = nil
-               }
-
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualUint64(left, right *Uint64) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of float64 values.
-type Float64 struct {
-       array
-       values []float64
-}
-
-// NewFloat64Data creates a new Float64.
-func NewFloat64Data(data arrow.ArrayData) *Float64 {
-       a := &Float64{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Float64) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Float64) Value(i int) float64 { return a.values[i] }
-
-// Values returns the values.
-func (a *Float64) Float64Values() []float64 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Float64) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Float64) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Float64Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Float64) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return strconv.FormatFloat(float64(a.Value(i)), 'g', -1, 64)
-}
-
-func (a *Float64) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-
-       return a.values[i]
-}
-
-func (a *Float64) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := 0; i < a.Len(); i++ {
-               if !a.IsValid(i) {
-                       vals[i] = nil
-                       continue
-               }
-
-               f := a.Value(i)
-               switch {
-               case math.IsNaN(f):
-                       vals[i] = "NaN"
-               case math.IsInf(f, 1):
-                       vals[i] = "+Inf"
-               case math.IsInf(f, -1):
-                       vals[i] = "-Inf"
-               default:
-                       vals[i] = f
-               }
-
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualFloat64(left, right *Float64) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of int32 values.
-type Int32 struct {
-       array
-       values []int32
-}
-
-// NewInt32Data creates a new Int32.
-func NewInt32Data(data arrow.ArrayData) *Int32 {
-       a := &Int32{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Int32) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Int32) Value(i int) int32 { return a.values[i] }
-
-// Values returns the values.
-func (a *Int32) Int32Values() []int32 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Int32) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Int32) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Int32Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Int32) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return strconv.FormatInt(int64(a.Value(i)), 10)
-}
-
-func (a *Int32) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-
-       return a.values[i]
-}
-
-func (a *Int32) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := 0; i < a.Len(); i++ {
-
-               if a.IsValid(i) {
-                       vals[i] = a.values[i]
-               } else {
-                       vals[i] = nil
-               }
-
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualInt32(left, right *Int32) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of uint32 values.
-type Uint32 struct {
-       array
-       values []uint32
-}
-
-// NewUint32Data creates a new Uint32.
-func NewUint32Data(data arrow.ArrayData) *Uint32 {
-       a := &Uint32{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Uint32) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Uint32) Value(i int) uint32 { return a.values[i] }
-
-// Values returns the values.
-func (a *Uint32) Uint32Values() []uint32 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Uint32) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Uint32) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Uint32Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Uint32) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return strconv.FormatUint(uint64(a.Value(i)), 10)
-}
-
-func (a *Uint32) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-
-       return a.values[i]
-}
-
-func (a *Uint32) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := 0; i < a.Len(); i++ {
-
-               if a.IsValid(i) {
-                       vals[i] = a.values[i]
-               } else {
-                       vals[i] = nil
-               }
-
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualUint32(left, right *Uint32) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of float32 values.
-type Float32 struct {
-       array
-       values []float32
-}
-
-// NewFloat32Data creates a new Float32.
-func NewFloat32Data(data arrow.ArrayData) *Float32 {
-       a := &Float32{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Float32) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Float32) Value(i int) float32 { return a.values[i] }
-
-// Values returns the values.
-func (a *Float32) Float32Values() []float32 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Float32) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Float32) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Float32Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Float32) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return strconv.FormatFloat(float64(a.Value(i)), 'g', -1, 32)
-}
-
-func (a *Float32) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-
-       return a.values[i]
-}
-
-func (a *Float32) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := 0; i < a.Len(); i++ {
-               if !a.IsValid(i) {
-                       vals[i] = nil
-                       continue
-               }
-
-               f := a.Value(i)
-               v := strconv.FormatFloat(float64(f), 'g', -1, 32)
-
-               switch v {
-               case "NaN", "+Inf", "-Inf":
-                       vals[i] = v
-               default:
-                       vals[i] = f
-               }
-
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualFloat32(left, right *Float32) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of int16 values.
-type Int16 struct {
-       array
-       values []int16
-}
-
-// NewInt16Data creates a new Int16.
-func NewInt16Data(data arrow.ArrayData) *Int16 {
-       a := &Int16{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Int16) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Int16) Value(i int) int16 { return a.values[i] }
-
-// Values returns the values.
-func (a *Int16) Int16Values() []int16 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Int16) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Int16) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Int16Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Int16) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return strconv.FormatInt(int64(a.Value(i)), 10)
-}
-
-func (a *Int16) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-
-       return a.values[i]
-}
-
-func (a *Int16) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := 0; i < a.Len(); i++ {
-
-               if a.IsValid(i) {
-                       vals[i] = a.values[i]
-               } else {
-                       vals[i] = nil
-               }
-
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualInt16(left, right *Int16) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of uint16 values.
-type Uint16 struct {
-       array
-       values []uint16
-}
-
-// NewUint16Data creates a new Uint16.
-func NewUint16Data(data arrow.ArrayData) *Uint16 {
-       a := &Uint16{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Uint16) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Uint16) Value(i int) uint16 { return a.values[i] }
-
-// Values returns the values.
-func (a *Uint16) Uint16Values() []uint16 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Uint16) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Uint16) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Uint16Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Uint16) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return strconv.FormatUint(uint64(a.Value(i)), 10)
-}
-
-func (a *Uint16) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-
-       return a.values[i]
-}
-
-func (a *Uint16) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := 0; i < a.Len(); i++ {
-
-               if a.IsValid(i) {
-                       vals[i] = a.values[i]
-               } else {
-                       vals[i] = nil
-               }
-
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualUint16(left, right *Uint16) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of int8 values.
-type Int8 struct {
-       array
-       values []int8
-}
-
-// NewInt8Data creates a new Int8.
-func NewInt8Data(data arrow.ArrayData) *Int8 {
-       a := &Int8{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Int8) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Int8) Value(i int) int8 { return a.values[i] }
-
-// Values returns the values.
-func (a *Int8) Int8Values() []int8 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Int8) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Int8) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Int8Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Int8) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return strconv.FormatInt(int64(a.Value(i)), 10)
-}
-
-func (a *Int8) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-
-       return float64(a.values[i]) // prevent uint8 from being seen as binary 
data
-}
-
-func (a *Int8) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := 0; i < a.Len(); i++ {
-
-               if a.IsValid(i) {
-                       vals[i] = float64(a.values[i]) // prevent uint8 from 
being seen as binary data
-               } else {
-                       vals[i] = nil
-               }
-
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualInt8(left, right *Int8) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of uint8 values.
-type Uint8 struct {
-       array
-       values []uint8
-}
-
-// NewUint8Data creates a new Uint8.
-func NewUint8Data(data arrow.ArrayData) *Uint8 {
-       a := &Uint8{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Uint8) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Uint8) Value(i int) uint8 { return a.values[i] }
-
-// Values returns the values.
-func (a *Uint8) Uint8Values() []uint8 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Uint8) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Uint8) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Uint8Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Uint8) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return strconv.FormatUint(uint64(a.Value(i)), 10)
-}
-
-func (a *Uint8) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-
-       return float64(a.values[i]) // prevent uint8 from being seen as binary 
data
-}
-
-func (a *Uint8) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := 0; i < a.Len(); i++ {
-
-               if a.IsValid(i) {
-                       vals[i] = float64(a.values[i]) // prevent uint8 from 
being seen as binary data
-               } else {
-                       vals[i] = nil
-               }
-
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualUint8(left, right *Uint8) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of arrow.Time32 values.
-type Time32 struct {
-       array
-       values []arrow.Time32
-}
-
-// NewTime32Data creates a new Time32.
-func NewTime32Data(data arrow.ArrayData) *Time32 {
-       a := &Time32{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Time32) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Time32) Value(i int) arrow.Time32 { return a.values[i] }
-
-// Values returns the values.
-func (a *Time32) Time32Values() []arrow.Time32 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Time32) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Time32) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Time32Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Time32) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return 
a.values[i].FormattedString(a.DataType().(*arrow.Time32Type).Unit)
-}
-
-func (a *Time32) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-       return 
a.values[i].ToTime(a.DataType().(*arrow.Time32Type).Unit).Format("15:04:05.999999999")
-}
-
-func (a *Time32) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := range a.values {
-               vals[i] = a.GetOneForMarshal(i)
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualTime32(left, right *Time32) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of arrow.Time64 values.
-type Time64 struct {
-       array
-       values []arrow.Time64
-}
-
-// NewTime64Data creates a new Time64.
-func NewTime64Data(data arrow.ArrayData) *Time64 {
-       a := &Time64{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Time64) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Time64) Value(i int) arrow.Time64 { return a.values[i] }
-
-// Values returns the values.
-func (a *Time64) Time64Values() []arrow.Time64 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Time64) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Time64) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Time64Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Time64) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return 
a.values[i].FormattedString(a.DataType().(*arrow.Time64Type).Unit)
-}
-
-func (a *Time64) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-       return 
a.values[i].ToTime(a.DataType().(*arrow.Time64Type).Unit).Format("15:04:05.999999999")
-}
-
-func (a *Time64) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := range a.values {
-               vals[i] = a.GetOneForMarshal(i)
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualTime64(left, right *Time64) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of arrow.Date32 values.
-type Date32 struct {
-       array
-       values []arrow.Date32
-}
-
-// NewDate32Data creates a new Date32.
-func NewDate32Data(data arrow.ArrayData) *Date32 {
-       a := &Date32{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Date32) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Date32) Value(i int) arrow.Date32 { return a.values[i] }
-
-// Values returns the values.
-func (a *Date32) Date32Values() []arrow.Date32 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Date32) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Date32) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Date32Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Date32) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return a.values[i].FormattedString()
-}
-
-func (a *Date32) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-       return a.values[i].ToTime().Format("2006-01-02")
-}
-
-func (a *Date32) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := range a.values {
-               vals[i] = a.GetOneForMarshal(i)
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualDate32(left, right *Date32) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of arrow.Date64 values.
-type Date64 struct {
-       array
-       values []arrow.Date64
-}
-
-// NewDate64Data creates a new Date64.
-func NewDate64Data(data arrow.ArrayData) *Date64 {
-       a := &Date64{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Date64) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Date64) Value(i int) arrow.Date64 { return a.values[i] }
-
-// Values returns the values.
-func (a *Date64) Date64Values() []arrow.Date64 { return a.values }
-
-// String returns a string representation of the array.
-func (a *Date64) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Date64) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.Date64Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Date64) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       return a.values[i].FormattedString()
-}
-
-func (a *Date64) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-       return a.values[i].ToTime().Format("2006-01-02")
-}
-
-func (a *Date64) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := range a.values {
-               vals[i] = a.GetOneForMarshal(i)
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualDate64(left, right *Date64) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-// A type which represents an immutable sequence of arrow.Duration values.
-type Duration struct {
-       array
-       values []arrow.Duration
-}
-
-// NewDurationData creates a new Duration.
-func NewDurationData(data arrow.ArrayData) *Duration {
-       a := &Duration{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *Duration) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *Duration) Value(i int) arrow.Duration { return a.values[i] }
-
-// Values returns the values.
-func (a *Duration) DurationValues() []arrow.Duration { return a.values }
-
-// String returns a string representation of the array.
-func (a *Duration) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *Duration) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.DurationTraits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *Duration) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-       // return value and suffix as a string such as "12345ms"
-       return fmt.Sprintf("%d%s", a.values[i], 
a.DataType().(*arrow.DurationType).Unit)
-}
-
-func (a *Duration) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-       // return value and suffix as a string such as "12345ms"
-       return fmt.Sprintf("%d%s", a.values[i], 
a.DataType().(*arrow.DurationType).Unit.String())
-}
-
-func (a *Duration) MarshalJSON() ([]byte, error) {
-       vals := make([]interface{}, a.Len())
-       for i := range a.values {
-               vals[i] = a.GetOneForMarshal(i)
-       }
-
-       return json.Marshal(vals)
-}
-
-func arrayEqualDuration(left, right *Duration) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
diff --git a/arrow/array/numeric.gen.go.tmpl b/arrow/array/numeric.gen.go.tmpl
deleted file mode 100644
index df07f20..0000000
--- a/arrow/array/numeric.gen.go.tmpl
+++ /dev/null
@@ -1,192 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package array
-
-import (
-       "fmt"
-       "strings"
-       "time"
-
-       "github.com/apache/arrow-go/v18/arrow"
-       "github.com/apache/arrow-go/v18/internal/json"
-)
-
-{{range .In}}
-
-// A type which represents an immutable sequence of {{or .QualifiedType 
.Type}} values.
-type {{.Name}} struct {
-       array
-       values []{{or .QualifiedType .Type}}
-}
-
-// New{{.Name}}Data creates a new {{.Name}}.
-func New{{.Name}}Data(data arrow.ArrayData) *{{.Name}} {
-       a := &{{.Name}}{}
-       a.refCount = 1
-       a.setData(data.(*Data))
-       return a
-}
-
-// Reset resets the array for re-use.
-func (a *{{.Name}}) Reset(data *Data) {
-       a.setData(data)
-}
-
-// Value returns the value at the specified index.
-func (a *{{.Name}}) Value(i int)      {{or .QualifiedType .Type}} { return 
a.values[i] }
-
-// Values returns the values.
-func (a *{{.Name}}) {{.Name}}Values() []{{or .QualifiedType .Type}} { return 
a.values }
-
-// String returns a string representation of the array.
-func (a *{{.Name}}) String() string {
-       o := new(strings.Builder)
-       o.WriteString("[")
-       for i, v := range a.values {
-               if i > 0 {
-                       fmt.Fprintf(o, " ")
-               }
-               switch {
-               case a.IsNull(i):
-                       o.WriteString(NullValueStr)
-               default:
-                       fmt.Fprintf(o, "%v", v)
-               }
-       }
-       o.WriteString("]")
-       return o.String()
-}
-
-func (a *{{.Name}}) setData(data *Data) {
-       a.array.setData(data)
-       vals := data.buffers[1]
-       if vals != nil {
-               a.values = arrow.{{.Name}}Traits.CastFromBytes(vals.Bytes())
-               beg := a.array.data.offset
-               end := beg + a.array.data.length
-               a.values = a.values[beg:end]
-       }
-}
-
-func (a *{{.Name}}) ValueStr(i int) string {
-       if a.IsNull(i) {
-               return NullValueStr
-       }
-{{if or (eq .Name "Date32") (eq .Name "Date64") -}}
-  return a.values[i].FormattedString()
-{{else if or (eq .Name "Time32") (eq .Name "Time64") -}}
-  return 
a.values[i].FormattedString(a.DataType().(*{{.QualifiedType}}Type).Unit)
-{{else if (eq .Name "Duration") -}}
-       // return value and suffix as a string such as "12345ms"
-       return fmt.Sprintf("%d%s", a.values[i], 
a.DataType().(*{{.QualifiedType}}Type).Unit)
-{{else if or (eq .Name "Int8") (eq .Name "Int16") (eq .Name "Int32") (eq .Name 
"Int64") -}}
-  return strconv.FormatInt(int64(a.Value(i)), 10)
-{{else if or (eq .Name "Uint8") (eq .Name "Uint16") (eq .Name "Uint32") (eq 
.Name "Uint64") -}}
-  return strconv.FormatUint(uint64(a.Value(i)), 10)
-{{else if or (eq .Name "Float32") -}}
-  return strconv.FormatFloat(float64(a.Value(i)), 'g', -1, 32)
-{{else if or (eq .Name "Float64") -}}
-  return strconv.FormatFloat(float64(a.Value(i)), 'g', -1, 64)
-{{else}}
-       return fmt.Sprintf("%v", a.values[i])
-{{end -}}
-}
-
-func (a *{{.Name}}) GetOneForMarshal(i int) interface{} {
-       if a.IsNull(i) {
-               return nil
-       }
-{{if or (eq .Name "Date32") (eq .Name "Date64") -}}
-       return a.values[i].ToTime().Format("2006-01-02")
-{{else if or (eq .Name "Time32") (eq .Name "Time64") -}}
-       return 
a.values[i].ToTime(a.DataType().(*{{.QualifiedType}}Type).Unit).Format("15:04:05.999999999")
-{{else if (eq .Name "Duration") -}}
-       // return value and suffix as a string such as "12345ms"
-       return fmt.Sprintf("%d%s", a.values[i], 
a.DataType().(*{{.QualifiedType}}Type).Unit.String())
-{{else if (eq .Size "1")}}
-       return float64(a.values[i]) // prevent uint8 from being seen as binary 
data
-{{else}}
-       return a.values[i]
-{{end -}}
-}
-
-func (a *{{.Name}}) MarshalJSON() ([]byte, error) {
-{{if .QualifiedType -}}
-       vals := make([]interface{}, a.Len())
-       for i := range a.values {
-               vals[i] = a.GetOneForMarshal(i)
-       }
-{{else -}}
-       vals := make([]interface{}, a.Len())
-       for i := 0; i < a.Len(); i++ {
-       {{if (eq .Name "Float32") -}}
-               if !a.IsValid(i) {
-                       vals[i] = nil
-                       continue
-               }
-
-               f := a.Value(i)
-               v := strconv.FormatFloat(float64(f), 'g', -1, 32)
-
-               switch v {
-               case "NaN", "+Inf", "-Inf":
-                       vals[i] = v
-               default:
-                       vals[i] = f
-               }
-       {{else if (eq .Name "Float64") -}}
-               if !a.IsValid(i) {
-                       vals[i] = nil
-                       continue
-               }
-
-               f := a.Value(i)
-               switch {
-               case math.IsNaN(f):
-                       vals[i] = "NaN"
-               case math.IsInf(f, 1):
-                       vals[i] = "+Inf"
-               case math.IsInf(f, -1):
-                       vals[i] = "-Inf"
-               default:
-                       vals[i] = f
-               }
-       {{else}}
-               if a.IsValid(i) {
-                       {{ if (eq .Size "1") }}vals[i] = float64(a.values[i]) 
// prevent uint8 from being seen as binary data{{ else }}vals[i] = 
a.values[i]{{ end }}
-               } else {
-                       vals[i] = nil
-               }
-       {{end}}
-       }
-{{end}}
-       return json.Marshal(vals)
-}
-
-func arrayEqual{{.Name}}(left, right *{{.Name}}) bool {
-       for i := 0; i < left.Len(); i++ {
-               if left.IsNull(i) {
-                       continue
-               }
-               if left.Value(i) != right.Value(i) {
-                       return false
-               }
-       }
-       return true
-}
-
-{{end}}
diff --git a/arrow/array/numeric_generic.go b/arrow/array/numeric_generic.go
new file mode 100644
index 0000000..8c18edd
--- /dev/null
+++ b/arrow/array/numeric_generic.go
@@ -0,0 +1,418 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package array
+
+import (
+       "fmt"
+       "strconv"
+       "strings"
+       "time"
+       "unsafe"
+
+       "github.com/apache/arrow-go/v18/arrow"
+       "github.com/apache/arrow-go/v18/internal/json"
+)
+
+type numericArray[T arrow.IntType | arrow.UintType | arrow.FloatType] struct {
+       array
+       values []T
+}
+
+func newNumericData[T arrow.IntType | arrow.UintType | arrow.FloatType](data 
arrow.ArrayData) numericArray[T] {
+       a := numericArray[T]{}
+       a.refCount = 1
+       a.setData(data.(*Data))
+       return a
+}
+
+func (a *numericArray[T]) Reset(data *Data) {
+       a.setData(data)
+}
+
+func (a *numericArray[T]) Value(i int) T { return a.values[i] }
+func (a *numericArray[T]) Values() []T   { return a.values }
+func (a *numericArray[T]) String() string {
+       o := new(strings.Builder)
+       o.WriteString("[")
+       for i, v := range a.values {
+               if i > 0 {
+                       fmt.Fprintf(o, " ")
+               }
+               switch {
+               case a.IsNull(i):
+                       o.WriteString(NullValueStr)
+               default:
+                       fmt.Fprintf(o, "%v", v)
+               }
+       }
+       o.WriteString("]")
+       return o.String()
+}
+
+func (a *numericArray[T]) setData(data *Data) {
+       a.array.setData(data)
+       vals := data.buffers[1]
+       if vals != nil {
+               a.values = arrow.GetData[T](vals.Bytes())
+               beg := a.array.data.offset
+               end := beg + a.array.data.length
+               a.values = a.values[beg:end]
+       }
+}
+
+func (a *numericArray[T]) ValueStr(i int) string {
+       if a.IsNull(i) {
+               return NullValueStr
+       }
+
+       return fmt.Sprintf("%v", a.values[i])
+}
+
+func (a *numericArray[T]) GetOneForMarshal(i int) any {
+       if a.IsNull(i) {
+               return nil
+       }
+
+       return a.values[i]
+}
+
+func (a *numericArray[T]) MarshalJSON() ([]byte, error) {
+       vals := make([]any, a.Len())
+       for i := range a.Len() {
+               if a.IsValid(i) {
+                       vals[i] = a.values[i]
+               } else {
+                       vals[i] = nil
+               }
+       }
+       return json.Marshal(vals)
+}
+
+type oneByteArrs[T int8 | uint8] struct {
+       numericArray[T]
+}
+
+func (a *oneByteArrs[T]) GetOneForMarshal(i int) any {
+       if a.IsNull(i) {
+               return nil
+       }
+
+       return float64(a.values[i]) // prevent uint8/int8 from being seen as 
binary data
+}
+
+func (a *oneByteArrs[T]) MarshalJSON() ([]byte, error) {
+       vals := make([]any, a.Len())
+       for i := range a.Len() {
+               if a.IsValid(i) {
+                       vals[i] = float64(a.values[i]) // prevent uint8/int8 
from being seen as binary data
+               } else {
+                       vals[i] = nil
+               }
+       }
+       return json.Marshal(vals)
+}
+
+type floatArray[T float32 | float64] struct {
+       numericArray[T]
+}
+
+func (a *floatArray[T]) ValueStr(i int) string {
+       if a.IsNull(i) {
+               return NullValueStr
+       }
+
+       f := a.Value(i)
+       bitWidth := int(unsafe.Sizeof(f) * 8)
+       return strconv.FormatFloat(float64(a.Value(i)), 'g', -1, bitWidth)
+}
+
+func (a *floatArray[T]) GetOneForMarshal(i int) any {
+       if a.IsNull(i) {
+               return nil
+       }
+
+       f := a.Value(i)
+       bitWidth := int(unsafe.Sizeof(f) * 8)
+       v := strconv.FormatFloat(float64(a.Value(i)), 'g', -1, bitWidth)
+       switch v {
+       case "NaN", "+Inf", "-Inf":
+               return v
+       default:
+               return f
+       }
+}
+
+func (a *floatArray[T]) MarshalJSON() ([]byte, error) {
+       vals := make([]any, a.Len())
+       for i := range a.values {
+               vals[i] = a.GetOneForMarshal(i)
+       }
+       return json.Marshal(vals)
+}
+
+type dateArray[T interface {
+       arrow.Date32 | arrow.Date64
+       FormattedString() string
+       ToTime() time.Time
+}] struct {
+       numericArray[T]
+}
+
+func (d *dateArray[T]) MarshalJSON() ([]byte, error) {
+       vals := make([]any, d.Len())
+       for i := range d.values {
+               vals[i] = d.GetOneForMarshal(i)
+       }
+       return json.Marshal(vals)
+}
+
+func (d *dateArray[T]) ValueStr(i int) string {
+       if d.IsNull(i) {
+               return NullValueStr
+       }
+
+       return d.values[i].FormattedString()
+}
+
+func (d *dateArray[T]) GetOneForMarshal(i int) interface{} {
+       if d.IsNull(i) {
+               return nil
+       }
+
+       return d.values[i].FormattedString()
+}
+
+type timeType interface {
+       TimeUnit() arrow.TimeUnit
+}
+
+type timeArray[T interface {
+       arrow.Time32 | arrow.Time64
+       FormattedString(arrow.TimeUnit) string
+       ToTime(arrow.TimeUnit) time.Time
+}] struct {
+       numericArray[T]
+}
+
+func (a *timeArray[T]) MarshalJSON() ([]byte, error) {
+       vals := make([]any, a.Len())
+       for i := range a.values {
+               vals[i] = a.GetOneForMarshal(i)
+       }
+       return json.Marshal(vals)
+}
+
+func (a *timeArray[T]) ValueStr(i int) string {
+       if a.IsNull(i) {
+               return NullValueStr
+       }
+
+       return a.values[i].FormattedString(a.DataType().(timeType).TimeUnit())
+}
+
+func (a *timeArray[T]) GetOneForMarshal(i int) interface{} {
+       if a.IsNull(i) {
+               return nil
+       }
+
+       return 
a.values[i].ToTime(a.DataType().(timeType).TimeUnit()).Format("15:04:05.999999999")
+}
+
+type Duration struct {
+       numericArray[arrow.Duration]
+}
+
+func NewDurationData(data arrow.ArrayData) *Duration {
+       return &Duration{numericArray: newNumericData[arrow.Duration](data)}
+}
+
+func (a *Duration) DurationValues() []arrow.Duration { return a.Values() }
+
+func (a *Duration) MarshalJSON() ([]byte, error) {
+       vals := make([]any, a.Len())
+       for i := range a.values {
+               vals[i] = a.GetOneForMarshal(i)
+       }
+       return json.Marshal(vals)
+}
+
+func (a *Duration) ValueStr(i int) string {
+       if a.IsNull(i) {
+               return NullValueStr
+       }
+
+       return fmt.Sprintf("%d%s", a.values[i], 
a.DataType().(timeType).TimeUnit())
+}
+
+func (a *Duration) GetOneForMarshal(i int) any {
+       if a.IsNull(i) {
+               return nil
+       }
+       return fmt.Sprintf("%d%s", a.values[i], 
a.DataType().(timeType).TimeUnit())
+}
+
+type Int64 struct {
+       numericArray[int64]
+}
+
+func NewInt64Data(data arrow.ArrayData) *Int64 {
+       return &Int64{numericArray: newNumericData[int64](data)}
+}
+
+func (a *Int64) Int64Values() []int64 { return a.Values() }
+
+type Uint64 struct {
+       numericArray[uint64]
+}
+
+func NewUint64Data(data arrow.ArrayData) *Uint64 {
+       return &Uint64{numericArray: newNumericData[uint64](data)}
+}
+
+func (a *Uint64) Uint64Values() []uint64 { return a.Values() }
+
+type Float32 struct {
+       floatArray[float32]
+}
+
+func NewFloat32Data(data arrow.ArrayData) *Float32 {
+       return &Float32{floatArray[float32]{newNumericData[float32](data)}}
+}
+
+func (a *Float32) Float32Values() []float32 { return a.Values() }
+
+type Float64 struct {
+       floatArray[float64]
+}
+
+func NewFloat64Data(data arrow.ArrayData) *Float64 {
+       return &Float64{floatArray: 
floatArray[float64]{newNumericData[float64](data)}}
+}
+
+func (a *Float64) Float64Values() []float64 { return a.Values() }
+
+type Int32 struct {
+       numericArray[int32]
+}
+
+func NewInt32Data(data arrow.ArrayData) *Int32 {
+       return &Int32{newNumericData[int32](data)}
+}
+
+func (a *Int32) Int32Values() []int32 { return a.Values() }
+
+type Uint32 struct {
+       numericArray[uint32]
+}
+
+func NewUint32Data(data arrow.ArrayData) *Uint32 {
+       return &Uint32{numericArray: newNumericData[uint32](data)}
+}
+
+func (a *Uint32) Uint32Values() []uint32 { return a.Values() }
+
+type Int16 struct {
+       numericArray[int16]
+}
+
+func NewInt16Data(data arrow.ArrayData) *Int16 {
+       return &Int16{newNumericData[int16](data)}
+}
+
+func (a *Int16) Int16Values() []int16 { return a.Values() }
+
+type Uint16 struct {
+       numericArray[uint16]
+}
+
+func NewUint16Data(data arrow.ArrayData) *Uint16 {
+       return &Uint16{numericArray: newNumericData[uint16](data)}
+}
+
+func (a *Uint16) Uint16Values() []uint16 { return a.Values() }
+
+type Int8 struct {
+       oneByteArrs[int8]
+}
+
+func NewInt8Data(data arrow.ArrayData) *Int8 {
+       return &Int8{oneByteArrs[int8]{newNumericData[int8](data)}}
+}
+
+func (a *Int8) Int8Values() []int8 { return a.Values() }
+
+type Uint8 struct {
+       oneByteArrs[uint8]
+}
+
+func NewUint8Data(data arrow.ArrayData) *Uint8 {
+       return &Uint8{oneByteArrs[uint8]{newNumericData[uint8](data)}}
+}
+
+func (a *Uint8) Uint8Values() []uint8 { return a.Values() }
+
+type Time32 struct {
+       timeArray[arrow.Time32]
+}
+
+func NewTime32Data(data arrow.ArrayData) *Time32 {
+       return 
&Time32{timeArray[arrow.Time32]{newNumericData[arrow.Time32](data)}}
+}
+
+func (a *Time32) Time32Values() []arrow.Time32 { return a.Values() }
+
+type Time64 struct {
+       timeArray[arrow.Time64]
+}
+
+func NewTime64Data(data arrow.ArrayData) *Time64 {
+       return 
&Time64{timeArray[arrow.Time64]{newNumericData[arrow.Time64](data)}}
+}
+
+func (a *Time64) Time64Values() []arrow.Time64 { return a.Values() }
+
+type Date32 struct {
+       dateArray[arrow.Date32]
+}
+
+func NewDate32Data(data arrow.ArrayData) *Date32 {
+       return 
&Date32{dateArray[arrow.Date32]{newNumericData[arrow.Date32](data)}}
+}
+
+func (a *Date32) Date32Values() []arrow.Date32 { return a.Values() }
+
+type Date64 struct {
+       dateArray[arrow.Date64]
+}
+
+func NewDate64Data(data arrow.ArrayData) *Date64 {
+       return 
&Date64{dateArray[arrow.Date64]{newNumericData[arrow.Date64](data)}}
+}
+
+func (a *Date64) Date64Values() []arrow.Date64 { return a.Values() }
+
+func arrayEqualFixedWidth[T arrow.FixedWidthType](left, right 
arrow.TypedArray[T]) bool {
+       for i := range left.Len() {
+               if left.IsNull(i) {
+                       continue
+               }
+               if left.Value(i) != right.Value(i) {
+                       return false
+               }
+       }
+       return true
+}
diff --git a/arrow/array/string.go b/arrow/array/string.go
index 5197e77..6ca6f4e 100644
--- a/arrow/array/string.go
+++ b/arrow/array/string.go
@@ -715,4 +715,8 @@ var (
        _ StringLike        = (*String)(nil)
        _ StringLike        = (*LargeString)(nil)
        _ StringLike        = (*StringView)(nil)
+
+       _ arrow.TypedArray[string] = (*String)(nil)
+       _ arrow.TypedArray[string] = (*LargeString)(nil)
+       _ arrow.TypedArray[string] = (*StringView)(nil)
 )
diff --git a/arrow/array/timestamp.go b/arrow/array/timestamp.go
index 37359db..74b1271 100644
--- a/arrow/array/timestamp.go
+++ b/arrow/array/timestamp.go
@@ -375,6 +375,7 @@ func (b *TimestampBuilder) UnmarshalJSON(data []byte) error 
{
 }
 
 var (
-       _ arrow.Array = (*Timestamp)(nil)
-       _ Builder     = (*TimestampBuilder)(nil)
+       _ arrow.Array                       = (*Timestamp)(nil)
+       _ Builder                           = (*TimestampBuilder)(nil)
+       _ arrow.TypedArray[arrow.Timestamp] = (*Timestamp)(nil)
 )

Reply via email to