// 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 (
	

	
	
	
)

const (
	// UnknownNullCount specifies the NullN should be calculated from the null bitmap buffer.
	UnknownNullCount = -1

	// NullValueStr represents a null value in arrow.Array.ValueStr and in Builder.AppendValueFromString.
	// It should be returned from the arrow.Array.ValueStr implementations.
	// Using it as the value in Builder.AppendValueFromString should be equivalent to Builder.AppendNull.
	NullValueStr = "(null)"
)

type array struct {
	refCount        atomic.Int64
	data            *Data
	nullBitmapBytes []byte
}

// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func ( *array) () {
	.refCount.Add(1)
}

// Release decreases the reference count by 1.
// Release may be called simultaneously from multiple goroutines.
// When the reference count goes to zero, the memory is freed.
func ( *array) () {
	debug.Assert(.refCount.Load() > 0, "too many releases")

	if .refCount.Add(-1) == 0 {
		.data.Release()
		.data, .nullBitmapBytes = nil, nil
	}
}

// DataType returns the type metadata for this instance.
func ( *array) () arrow.DataType { return .data.dtype }

// NullN returns the number of null values in the array.
func ( *array) () int {
	if .data.nulls < 0 {
		.data.nulls = .data.length - bitutil.CountSetBits(.nullBitmapBytes, .data.offset, .data.length)
	}
	return .data.nulls
}

// NullBitmapBytes returns a byte slice of the validity bitmap.
func ( *array) () []byte { return .nullBitmapBytes }

func ( *array) () arrow.ArrayData { return .data }

// Len returns the number of elements in the array.
func ( *array) () int { return .data.length }

// IsNull returns true if value at index is null.
// NOTE: IsNull will panic if NullBitmapBytes is not empty and 0 > i ≥ Len.
func ( *array) ( int) bool {
	return len(.nullBitmapBytes) != 0 && bitutil.BitIsNotSet(.nullBitmapBytes, .data.offset+)
}

// IsValid returns true if value at index is not null.
// NOTE: IsValid will panic if NullBitmapBytes is not empty and 0 > i ≥ Len.
func ( *array) ( int) bool {
	return len(.nullBitmapBytes) == 0 || bitutil.BitIsSet(.nullBitmapBytes, .data.offset+)
}

func ( *array) ( *Data) {
	// Retain before releasing in case a.data is the same as data.
	.Retain()

	if .data != nil {
		.data.Release()
	}

	if len(.buffers) > 0 && .buffers[0] != nil {
		.nullBitmapBytes = .buffers[0].Bytes()
	}
	.data = 
}

func ( *array) () int {
	return .data.Offset()
}

type arrayConstructorFn func(arrow.ArrayData) arrow.Array

var makeArrayFn [64]arrayConstructorFn

func invalidDataType( arrow.ArrayData) arrow.Array {
	panic("invalid data type: " + .DataType().ID().String())
}

// MakeFromData constructs a strongly-typed array instance from generic Data.
func ( arrow.ArrayData) arrow.Array {
	return makeArrayFn[byte(.DataType().ID()&0x3f)]()
}

// NewSlice constructs a zero-copy slice of the array with the indicated
// indices i and j, corresponding to array[i:j].
// The returned array must be Release()'d after use.
//
// NewSlice panics if the slice is outside the valid range of the input array.
// NewSlice panics if j < i.
func ( arrow.Array, ,  int64) arrow.Array {
	 := NewSliceData(.Data(), , )
	 := MakeFromData()
	.Release()
	return 
}

func init() {
	makeArrayFn = [...]arrayConstructorFn{
		arrow.NULL:                    func( arrow.ArrayData) arrow.Array { return NewNullData() },
		arrow.BOOL:                    func( arrow.ArrayData) arrow.Array { return NewBooleanData() },
		arrow.UINT8:                   func( arrow.ArrayData) arrow.Array { return NewUint8Data() },
		arrow.INT8:                    func( arrow.ArrayData) arrow.Array { return NewInt8Data() },
		arrow.UINT16:                  func( arrow.ArrayData) arrow.Array { return NewUint16Data() },
		arrow.INT16:                   func( arrow.ArrayData) arrow.Array { return NewInt16Data() },
		arrow.UINT32:                  func( arrow.ArrayData) arrow.Array { return NewUint32Data() },
		arrow.INT32:                   func( arrow.ArrayData) arrow.Array { return NewInt32Data() },
		arrow.UINT64:                  func( arrow.ArrayData) arrow.Array { return NewUint64Data() },
		arrow.INT64:                   func( arrow.ArrayData) arrow.Array { return NewInt64Data() },
		arrow.FLOAT16:                 func( arrow.ArrayData) arrow.Array { return NewFloat16Data() },
		arrow.FLOAT32:                 func( arrow.ArrayData) arrow.Array { return NewFloat32Data() },
		arrow.FLOAT64:                 func( arrow.ArrayData) arrow.Array { return NewFloat64Data() },
		arrow.STRING:                  func( arrow.ArrayData) arrow.Array { return NewStringData() },
		arrow.BINARY:                  func( arrow.ArrayData) arrow.Array { return NewBinaryData() },
		arrow.FIXED_SIZE_BINARY:       func( arrow.ArrayData) arrow.Array { return NewFixedSizeBinaryData() },
		arrow.DATE32:                  func( arrow.ArrayData) arrow.Array { return NewDate32Data() },
		arrow.DATE64:                  func( arrow.ArrayData) arrow.Array { return NewDate64Data() },
		arrow.TIMESTAMP:               func( arrow.ArrayData) arrow.Array { return NewTimestampData() },
		arrow.TIME32:                  func( arrow.ArrayData) arrow.Array { return NewTime32Data() },
		arrow.TIME64:                  func( arrow.ArrayData) arrow.Array { return NewTime64Data() },
		arrow.INTERVAL_MONTHS:         func( arrow.ArrayData) arrow.Array { return NewMonthIntervalData() },
		arrow.INTERVAL_DAY_TIME:       func( arrow.ArrayData) arrow.Array { return NewDayTimeIntervalData() },
		arrow.DECIMAL32:               func( arrow.ArrayData) arrow.Array { return NewDecimal32Data() },
		arrow.DECIMAL64:               func( arrow.ArrayData) arrow.Array { return NewDecimal64Data() },
		arrow.DECIMAL128:              func( arrow.ArrayData) arrow.Array { return NewDecimal128Data() },
		arrow.DECIMAL256:              func( arrow.ArrayData) arrow.Array { return NewDecimal256Data() },
		arrow.LIST:                    func( arrow.ArrayData) arrow.Array { return NewListData() },
		arrow.STRUCT:                  func( arrow.ArrayData) arrow.Array { return NewStructData() },
		arrow.SPARSE_UNION:            func( arrow.ArrayData) arrow.Array { return NewSparseUnionData() },
		arrow.DENSE_UNION:             func( arrow.ArrayData) arrow.Array { return NewDenseUnionData() },
		arrow.DICTIONARY:              func( arrow.ArrayData) arrow.Array { return NewDictionaryData() },
		arrow.MAP:                     func( arrow.ArrayData) arrow.Array { return NewMapData() },
		arrow.EXTENSION:               func( arrow.ArrayData) arrow.Array { return NewExtensionData() },
		arrow.FIXED_SIZE_LIST:         func( arrow.ArrayData) arrow.Array { return NewFixedSizeListData() },
		arrow.DURATION:                func( arrow.ArrayData) arrow.Array { return NewDurationData() },
		arrow.LARGE_STRING:            func( arrow.ArrayData) arrow.Array { return NewLargeStringData() },
		arrow.LARGE_BINARY:            func( arrow.ArrayData) arrow.Array { return NewLargeBinaryData() },
		arrow.LARGE_LIST:              func( arrow.ArrayData) arrow.Array { return NewLargeListData() },
		arrow.INTERVAL_MONTH_DAY_NANO: func( arrow.ArrayData) arrow.Array { return NewMonthDayNanoIntervalData() },
		arrow.RUN_END_ENCODED:         func( arrow.ArrayData) arrow.Array { return NewRunEndEncodedData() },
		arrow.LIST_VIEW:               func( arrow.ArrayData) arrow.Array { return NewListViewData() },
		arrow.LARGE_LIST_VIEW:         func( arrow.ArrayData) arrow.Array { return NewLargeListViewData() },
		arrow.BINARY_VIEW:             func( arrow.ArrayData) arrow.Array { return NewBinaryViewData() },
		arrow.STRING_VIEW:             func( arrow.ArrayData) arrow.Array { return NewStringViewData() },
		// invalid data types to fill out array to size 2^6 - 1
		63: invalidDataType,
	}
}