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

	
	
	
	
	
)

type ListLike interface {
	arrow.Array
	ListValues() arrow.Array
	ValueOffsets(i int) (start, end int64)
}

type VarLenListLike interface {
	ListLike
}

// List represents an immutable sequence of array values.
type List struct {
	array
	values  arrow.Array
	offsets []int32
}

var _ ListLike = (*List)(nil)

// NewListData returns a new List array value, from data.
func ( arrow.ArrayData) *List {
	 := &List{}
	.refCount.Add(1)
	.setData(.(*Data))
	return 
}

func ( *List) () arrow.Array { return .values }

func ( *List) ( int) string {
	if !.IsValid() {
		return NullValueStr
	}
	return string(.GetOneForMarshal().(json.RawMessage))
}

func ( *List) () string {
	 := new(strings.Builder)
	.WriteString("[")
	for  := 0;  < .Len(); ++ {
		if  > 0 {
			.WriteString(" ")
		}
		if .IsNull() {
			.WriteString(NullValueStr)
			continue
		}
		 := .newListValue()
		fmt.Fprintf(, "%v", )
		.Release()
	}
	.WriteString("]")
	return .String()
}

func ( *List) ( int) arrow.Array {
	,  := .ValueOffsets()
	return NewSlice(.values, , )
}

func ( *List) ( *Data) {
	debug.Assert(len(.buffers) >= 2, "list data should have 2 buffers")
	.array.setData()
	 := .buffers[1]
	if  != nil {
		.offsets = arrow.Int32Traits.CastFromBytes(.Bytes())
	}
	.values = MakeFromData(.childData[0])
}

func ( *List) ( int) interface{} {
	if .IsNull() {
		return nil
	}

	 := .newListValue()
	defer .Release()
	,  := json.Marshal()
	if  != nil {
		panic()
	}
	return json.RawMessage()
}

func ( *List) () ([]byte, error) {
	var  bytes.Buffer
	 := json.NewEncoder(&)

	.WriteByte('[')
	for  := 0;  < .Len(); ++ {
		if  != 0 {
			.WriteByte(',')
		}
		if  := .Encode(.GetOneForMarshal());  != nil {
			return nil, 
		}
	}
	.WriteByte(']')
	return .Bytes(), nil
}

func arrayEqualList(,  *List) bool {
	for  := 0;  < .Len(); ++ {
		if .IsNull() {
			continue
		}
		 := func() bool {
			 := .newListValue()
			defer .Release()
			 := .newListValue()
			defer .Release()
			return Equal(, )
		}()
		if ! {
			return false
		}
	}
	return true
}

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

func ( *List) () []int32 { return .offsets }

func ( *List) () {
	.array.Retain()
	.values.Retain()
}

func ( *List) () {
	.array.Release()
	.values.Release()
}

func ( *List) ( int) (,  int64) {
	debug.Assert( >= 0 &&  < .data.length, "index out of range")
	 :=  + .data.offset
	,  = int64(.offsets[]), int64(.offsets[+1])
	return
}

// LargeList represents an immutable sequence of array values.
type LargeList struct {
	array
	values  arrow.Array
	offsets []int64
}

var _ ListLike = (*LargeList)(nil)

// NewLargeListData returns a new LargeList array value, from data.
func ( arrow.ArrayData) *LargeList {
	 := new(LargeList)
	.refCount.Add(1)
	.setData(.(*Data))
	return 
}

func ( *LargeList) () arrow.Array { return .values }

func ( *LargeList) ( int) string {
	if !.IsValid() {
		return NullValueStr
	}
	return string(.GetOneForMarshal().(json.RawMessage))
}

func ( *LargeList) () string {
	 := new(strings.Builder)
	.WriteString("[")
	for  := 0;  < .Len(); ++ {
		if  > 0 {
			.WriteString(" ")
		}
		if .IsNull() {
			.WriteString(NullValueStr)
			continue
		}
		 := .newListValue()
		fmt.Fprintf(, "%v", )
		.Release()
	}
	.WriteString("]")
	return .String()
}

func ( *LargeList) ( int) arrow.Array {
	,  := .ValueOffsets()
	return NewSlice(.values, , )
}

func ( *LargeList) ( *Data) {
	debug.Assert(len(.buffers) >= 2, "list data should have 2 buffers")
	.array.setData()
	 := .buffers[1]
	if  != nil {
		.offsets = arrow.Int64Traits.CastFromBytes(.Bytes())
	}
	.values = MakeFromData(.childData[0])
}

func ( *LargeList) ( int) interface{} {
	if .IsNull() {
		return nil
	}

	 := .newListValue()
	defer .Release()
	,  := json.Marshal()
	if  != nil {
		panic()
	}
	return json.RawMessage()
}

func ( *LargeList) () ([]byte, error) {
	var  bytes.Buffer
	 := json.NewEncoder(&)

	.WriteByte('[')
	for  := 0;  < .Len(); ++ {
		if  != 0 {
			.WriteByte(',')
		}
		if  := .Encode(.GetOneForMarshal());  != nil {
			return nil, 
		}
	}
	.WriteByte(']')
	return .Bytes(), nil
}

func arrayEqualLargeList(,  *LargeList) bool {
	for  := 0;  < .Len(); ++ {
		if .IsNull() {
			continue
		}
		 := func() bool {
			 := .newListValue()
			defer .Release()
			 := .newListValue()
			defer .Release()
			return Equal(, )
		}()
		if ! {
			return false
		}
	}
	return true
}

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

func ( *LargeList) () []int64 { return .offsets }

func ( *LargeList) ( int) (,  int64) {
	debug.Assert( >= 0 &&  < .data.length, "index out of range")
	 :=  + .data.offset
	,  = .offsets[], .offsets[+1]
	return
}

func ( *LargeList) () {
	.array.Retain()
	.values.Retain()
}

func ( *LargeList) () {
	.array.Release()
	.values.Release()
}

type baseListBuilder struct {
	builder

	values  Builder // value builder for the list's elements.
	offsets Builder

	// actual list type
	dt              arrow.DataType
	appendOffsetVal func(int)
}

type ListLikeBuilder interface {
	Builder
	ValueBuilder() Builder
	Append(bool)
}

type VarLenListLikeBuilder interface {
	ListLikeBuilder
	AppendWithSize(bool, int)
}

type ListBuilder struct {
	baseListBuilder
}

type LargeListBuilder struct {
	baseListBuilder
}

// NewListBuilder returns a builder, using the provided memory allocator.
// The created list builder will create a list whose elements will be of type etype.
func ( memory.Allocator,  arrow.DataType) *ListBuilder {
	 := NewInt32Builder()
	 := &ListBuilder{
		baseListBuilder{
			builder:         builder{mem: },
			values:          NewBuilder(, ),
			offsets:         ,
			dt:              arrow.ListOf(),
			appendOffsetVal: func( int) { .Append(int32()) },
		},
	}
	.refCount.Add(1)
	return 
}

// NewListBuilderWithField takes a field to use for the child rather than just
// a datatype to allow for more customization.
func ( memory.Allocator,  arrow.Field) *ListBuilder {
	 := NewInt32Builder()
	 := &ListBuilder{
		baseListBuilder{
			builder:         builder{mem: },
			values:          NewBuilder(, .Type),
			offsets:         ,
			dt:              arrow.ListOfField(),
			appendOffsetVal: func( int) { .Append(int32()) },
		},
	}
	.refCount.Add(1)
	return 
}

func ( *baseListBuilder) () arrow.DataType {
	switch dt := .dt.(type) {
	case *arrow.ListType:
		 := .ElemField()
		.Type = .values.Type()
		return arrow.ListOfField()
	case *arrow.LargeListType:
		 := .ElemField()
		.Type = .values.Type()
		return arrow.LargeListOfField()
	}
	return nil
}

// NewLargeListBuilder returns a builder, using the provided memory allocator.
// The created list builder will create a list whose elements will be of type etype.
func ( memory.Allocator,  arrow.DataType) *LargeListBuilder {
	 := NewInt64Builder()
	 := &LargeListBuilder{
		baseListBuilder{
			builder:         builder{mem: },
			values:          NewBuilder(, ),
			offsets:         ,
			dt:              arrow.LargeListOf(),
			appendOffsetVal: func( int) { .Append(int64()) },
		},
	}
	.refCount.Add(1)
	return 
}

// NewLargeListBuilderWithField takes a field rather than just an element type
// to allow for more customization of the final type of the LargeList Array
func ( memory.Allocator,  arrow.Field) *LargeListBuilder {
	 := NewInt64Builder()
	 := &LargeListBuilder{
		baseListBuilder{
			builder:         builder{mem: },
			values:          NewBuilder(, .Type),
			offsets:         ,
			dt:              arrow.LargeListOfField(),
			appendOffsetVal: func( int) { .Append(int64()) },
		},
	}
	.refCount.Add(1)
	return 
}

// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
func ( *baseListBuilder) () {
	debug.Assert(.refCount.Load() > 0, "too many releases")

	if .refCount.Add(-1) == 0 {
		if .nullBitmap != nil {
			.nullBitmap.Release()
			.nullBitmap = nil
		}
		.values.Release()
		.offsets.Release()
	}
}

func ( *baseListBuilder) () {
	.appendOffsetVal(.values.Len())
}

func ( *baseListBuilder) ( bool) {
	.Reserve(1)
	.unsafeAppendBoolToBitmap()
	.appendNextOffset()
}

func ( *baseListBuilder) ( bool,  int) {
	.Append()
}

func ( *baseListBuilder) () {
	.Reserve(1)
	.unsafeAppendBoolToBitmap(false)
	.appendNextOffset()
}

func ( *baseListBuilder) ( int) {
	for  := 0;  < ; ++ {
		.AppendNull()
	}
}

func ( *baseListBuilder) () {
	.Append(true)
}

func ( *baseListBuilder) ( int) {
	for  := 0;  < ; ++ {
		.AppendEmptyValue()
	}
}

func ( *ListBuilder) ( []int32,  []bool) {
	.Reserve(len())
	.offsets.(*Int32Builder).AppendValues(, nil)
	.unsafeAppendBoolsToBitmap(, len())
}

func ( *LargeListBuilder) ( []int64,  []bool) {
	.Reserve(len())
	.offsets.(*Int64Builder).AppendValues(, nil)
	.unsafeAppendBoolsToBitmap(, len())
}

func ( *baseListBuilder) ( bool) {
	if  {
		bitutil.SetBit(.nullBitmap.Bytes(), .length)
	} else {
		.nulls++
	}
	.length++
}

func ( *baseListBuilder) ( int) {
	.builder.init()
	.offsets.init( + 1)
}

// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func ( *baseListBuilder) ( int) {
	.reserve(, .resizeHelper)
	.offsets.Reserve()
}

// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func ( *baseListBuilder) ( int) {
	.resizeHelper()
	.offsets.Resize()
}

func ( *baseListBuilder) ( int) {
	if  < minBuilderCapacity {
		 = minBuilderCapacity
	}

	if .capacity == 0 {
		.init()
	} else {
		.resize(, .builder.init)
	}
}

func ( *baseListBuilder) () Builder {
	return .values
}

// NewArray creates a List array from the memory buffers used by the builder and resets the ListBuilder
// so it can be used to build a new array.
func ( *ListBuilder) () arrow.Array {
	return .NewListArray()
}

// NewArray creates a LargeList array from the memory buffers used by the builder and resets the LargeListBuilder
// so it can be used to build a new array.
func ( *LargeListBuilder) () arrow.Array {
	return .NewLargeListArray()
}

// NewListArray creates a List array from the memory buffers used by the builder and resets the ListBuilder
// so it can be used to build a new array.
func ( *ListBuilder) () ( *List) {
	 := .newData()
	 = NewListData()
	.Release()
	return
}

// NewLargeListArray creates a List array from the memory buffers used by the builder and resets the LargeListBuilder
// so it can be used to build a new array.
func ( *LargeListBuilder) () ( *LargeList) {
	 := .newData()
	 = NewLargeListData()
	.Release()
	return
}

func ( *baseListBuilder) () ( *Data) {
	if .offsets.Len() != .length+1 {
		.appendNextOffset()
	}
	 := .values.NewArray()
	defer .Release()

	var  *memory.Buffer
	if .offsets != nil {
		 := .offsets.NewArray()
		defer .Release()
		 = .Data().Buffers()[1]
	}

	 = NewData(
		.Type(), .length,
		[]*memory.Buffer{
			.nullBitmap,
			,
		},
		[]arrow.ArrayData{.Data()},
		.nulls,
		0,
	)
	.reset()

	return
}

func ( *baseListBuilder) ( string) error {
	if  == NullValueStr {
		.AppendNull()
		return nil
	}

	return .UnmarshalOne(json.NewDecoder(strings.NewReader()))
}

func ( *baseListBuilder) ( *json.Decoder) error {
	,  := .Token()
	if  != nil {
		return 
	}

	switch  {
	case json.Delim('['):
		.Append(true)
		if  := .values.Unmarshal();  != nil {
			return 
		}
		// consume ']'
		,  := .Token()
		return 
	case nil:
		.AppendNull()
	default:
		return &json.UnmarshalTypeError{
			Value:  fmt.Sprint(),
			Struct: .dt.String(),
		}
	}

	return nil
}

func ( *baseListBuilder) ( *json.Decoder) error {
	for .More() {
		if  := .UnmarshalOne();  != nil {
			return 
		}
	}
	return nil
}

func ( *baseListBuilder) ( []byte) error {
	 := json.NewDecoder(bytes.NewReader())
	,  := .Token()
	if  != nil {
		return 
	}

	if ,  := .(json.Delim); ! ||  != '[' {
		return fmt.Errorf("list builder must unpack from json array, found %s", )
	}

	return .Unmarshal()
}

// ListView represents an immutable sequence of array values defined by an
// offset into a child array and a length.
type ListView struct {
	array
	values  arrow.Array
	offsets []int32
	sizes   []int32
}

var _ VarLenListLike = (*ListView)(nil)

func ( arrow.ArrayData) *ListView {
	 := &ListView{}
	.refCount.Add(1)
	.setData(.(*Data))
	return 
}

func ( *ListView) () arrow.Array { return .values }

func ( *ListView) ( int) string {
	if !.IsValid() {
		return NullValueStr
	}
	return string(.GetOneForMarshal().(json.RawMessage))
}

func ( *ListView) () string {
	 := new(strings.Builder)
	.WriteString("[")
	for  := 0;  < .Len(); ++ {
		if  > 0 {
			.WriteString(" ")
		}
		if .IsNull() {
			.WriteString(NullValueStr)
			continue
		}
		 := .newListValue()
		fmt.Fprintf(, "%v", )
		.Release()
	}
	.WriteString("]")
	return .String()
}

func ( *ListView) ( int) arrow.Array {
	,  := .ValueOffsets()
	return NewSlice(.values, , )
}

func ( *ListView) ( *Data) {
	debug.Assert(len(.buffers) >= 3, "list-view data should have 3 buffers")
	.array.setData()
	 := .buffers[1]
	if  != nil {
		.offsets = arrow.Int32Traits.CastFromBytes(.Bytes())
	}
	 := .buffers[2]
	if  != nil {
		.sizes = arrow.Int32Traits.CastFromBytes(.Bytes())
	}
	.values = MakeFromData(.childData[0])
}

func ( *ListView) ( int) interface{} {
	if .IsNull() {
		return nil
	}

	 := .newListValue()
	defer .Release()
	,  := json.Marshal()
	if  != nil {
		panic()
	}
	return json.RawMessage()
}

func ( *ListView) () ([]byte, error) {
	var  bytes.Buffer
	 := json.NewEncoder(&)

	.WriteByte('[')
	for  := 0;  < .Len(); ++ {
		if  != 0 {
			.WriteByte(',')
		}
		if  := .Encode(.GetOneForMarshal());  != nil {
			return nil, 
		}
	}
	.WriteByte(']')
	return .Bytes(), nil
}

func arrayEqualListView(,  *ListView) bool {
	for  := 0;  < .Len(); ++ {
		if .IsNull() {
			continue
		}
		 := func() bool {
			 := .newListValue()
			defer .Release()
			 := .newListValue()
			defer .Release()
			return Equal(, )
		}()
		if ! {
			return false
		}
	}
	return true
}

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

func ( *ListView) () []int32 { return .offsets }

func ( *ListView) () []int32 { return .sizes }

func ( *ListView) () {
	.array.Retain()
	.values.Retain()
}

func ( *ListView) () {
	.array.Release()
	.values.Release()
}

func ( *ListView) ( int) (,  int64) {
	debug.Assert( >= 0 &&  < .data.length, "index out of range")
	 :=  + .data.offset
	 := int64(.sizes[])
	// If size is 0, skip accessing offsets.
	if  == 0 {
		,  = 0, 0
		return
	}
	 = int64(.offsets[])
	 =  + 
	return
}

// LargeListView represents an immutable sequence of array values defined by an
// offset into a child array and a length.
type LargeListView struct {
	array
	values  arrow.Array
	offsets []int64
	sizes   []int64
}

var _ VarLenListLike = (*LargeListView)(nil)

// NewLargeListViewData returns a new LargeListView array value, from data.
func ( arrow.ArrayData) *LargeListView {
	 := new(LargeListView)
	.refCount.Add(1)
	.setData(.(*Data))
	return 
}

func ( *LargeListView) () arrow.Array { return .values }

func ( *LargeListView) ( int) string {
	if !.IsValid() {
		return NullValueStr
	}
	return string(.GetOneForMarshal().(json.RawMessage))
}

func ( *LargeListView) () string {
	 := new(strings.Builder)
	.WriteString("[")
	for  := 0;  < .Len(); ++ {
		if  > 0 {
			.WriteString(" ")
		}
		if .IsNull() {
			.WriteString(NullValueStr)
			continue
		}
		 := .newListValue()
		fmt.Fprintf(, "%v", )
		.Release()
	}
	.WriteString("]")
	return .String()
}

func ( *LargeListView) ( int) arrow.Array {
	,  := .ValueOffsets()
	return NewSlice(.values, , )
}

func ( *LargeListView) ( *Data) {
	debug.Assert(len(.buffers) >= 3, "list-view data should have 3 buffers")
	.array.setData()
	 := .buffers[1]
	if  != nil {
		.offsets = arrow.Int64Traits.CastFromBytes(.Bytes())
	}
	 := .buffers[2]
	if  != nil {
		.sizes = arrow.Int64Traits.CastFromBytes(.Bytes())
	}
	.values = MakeFromData(.childData[0])
}

func ( *LargeListView) ( int) interface{} {
	if .IsNull() {
		return nil
	}

	 := .newListValue()
	defer .Release()
	,  := json.Marshal()
	if  != nil {
		panic()
	}
	return json.RawMessage()
}

func ( *LargeListView) () ([]byte, error) {
	var  bytes.Buffer
	 := json.NewEncoder(&)

	.WriteByte('[')
	for  := 0;  < .Len(); ++ {
		if  != 0 {
			.WriteByte(',')
		}
		if  := .Encode(.GetOneForMarshal());  != nil {
			return nil, 
		}
	}
	.WriteByte(']')
	return .Bytes(), nil
}

func arrayEqualLargeListView(,  *LargeListView) bool {
	for  := 0;  < .Len(); ++ {
		if .IsNull() {
			continue
		}
		 := func() bool {
			 := .newListValue()
			defer .Release()
			 := .newListValue()
			defer .Release()
			return Equal(, )
		}()
		if ! {
			return false
		}
	}
	return true
}

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

func ( *LargeListView) () []int64 { return .offsets }

func ( *LargeListView) () []int64 { return .sizes }

func ( *LargeListView) ( int) (,  int64) {
	debug.Assert( >= 0 &&  < .data.length, "index out of range")
	 :=  + .data.offset
	 := .sizes[]
	// If size is 0, skip accessing offsets.
	if  == 0 {
		return 0, 0
	}
	 = .offsets[]
	 =  + 
	return
}

func ( *LargeListView) () {
	.array.Retain()
	.values.Retain()
}

func ( *LargeListView) () {
	.array.Release()
	.values.Release()
}

// Accessors for offsets and sizes to make ListView and LargeListView validation generic.
type offsetsAndSizes interface {
	offsetAt(slot int64) int64
	sizeAt(slot int64) int64
}

var (
	_ offsetsAndSizes = (*ListView)(nil)
	_ offsetsAndSizes = (*LargeListView)(nil)
)

func ( *ListView) ( int64) int64 { return int64(.offsets[int64(.data.offset)+]) }

func ( *ListView) ( int64) int64 { return int64(.sizes[int64(.data.offset)+]) }

func ( *LargeListView) ( int64) int64 { return .offsets[int64(.data.offset)+] }

func ( *LargeListView) ( int64) int64 { return .sizes[int64(.data.offset)+] }

func outOfBoundsListViewOffset( offsetsAndSizes,  int64,  int64) error {
	 := .offsetAt()
	return fmt.Errorf("%w: Offset invariant failure: offset for slot %d out of bounds. Expected %d to be at least 0 and less than %d", arrow.ErrInvalid, , , )
}

func outOfBoundsListViewSize( offsetsAndSizes,  int64,  int64) error {
	 := .sizeAt()
	if  < 0 {
		return fmt.Errorf("%w: Offset invariant failure: size for slot %d out of bounds: %d < 0", arrow.ErrInvalid, , )
	}
	 := .offsetAt()
	return fmt.Errorf("%w: Offset invariant failure: size for slot %d out of bounds: %d + %d > %d", arrow.ErrInvalid, , , , )
}

// Pre-condition: Basic validation has already been performed
func ( *array) ( offsetsAndSizes,  int64) error {
	for  := int64(0);  < int64(.Len());  += 1 {
		 := .sizeAt()
		if  > 0 {
			 := .offsetAt()
			if  < 0 ||  >  {
				return outOfBoundsListViewOffset(, , )
			}
			if  > -int64() {
				return outOfBoundsListViewSize(, , )
			}
		} else if  < 0 {
			return outOfBoundsListViewSize(, , )
		}
	}

	return nil
}

func ( *array) ( offsetsAndSizes,  int,  bool,  int64,  bool) error {
	 := .Len() > 0
	if .data.buffers[1] == nil {
		// For length 0, an empty offsets buffer is accepted (ARROW-544).
		if  {
			return fmt.Errorf("non-empty array but offsets are null")
		}
		return nil
	}
	if  && .data.buffers[2] == nil {
		if  {
			return fmt.Errorf("non-empty array but sizes are null")
		}
		return nil
	}

	var  int
	if  {
		 = .Len() + .Offset()
		if ! {
			 += 1
		}
	} else {
		 = 0
	}
	 := .data.buffers[1].Len()
	if / <  {
		return fmt.Errorf("offsets buffer size (bytes): %d isn't large enough for length: %d and offset: %d",
			, .Len(), .Offset())
	}
	if  {
		 := .Len() + .Offset()
		 := .data.buffers[2].Len()
		if / <  {
			return fmt.Errorf("sizes buffer size (bytes): %d isn't large enough for length: %d and offset: %d",
				, .Len(), .Offset())
		}
	}

	if  &&  > 0 {
		if  {
			return .fullyValidateOffsetsAndSizes(, )
		}
		// TODO: implement validation of List and LargeList
		// return fullyValidateOffsets(offset_limit)
		return nil
	}
	return nil
}

func ( *ListView) ( bool) error {
	 := .data.childData[0]
	 := .Len()
	return .validateOffsetsAndMaybeSizes(, 4, true, int64(), )
}

func ( *ListView) () error {
	return .validate(false)
}

func ( *ListView) () error {
	return .validate(true)
}

func ( *LargeListView) ( bool) error {
	 := .data.childData[0]
	 := .Len()
	return .validateOffsetsAndMaybeSizes(, 8, true, int64(), )
}

func ( *LargeListView) () error {
	return .validate(false)
}

func ( *LargeListView) () error {
	return .validate(true)
}

type baseListViewBuilder struct {
	builder

	values  Builder // value builder for the list-view's elements.
	offsets Builder
	sizes   Builder

	// actual list-view type
	dt              arrow.DataType
	appendOffsetVal func(int)
	appendSizeVal   func(int)
}

type ListViewBuilder struct {
	baseListViewBuilder
}

type LargeListViewBuilder struct {
	baseListViewBuilder
}

// NewListViewBuilder returns a builder, using the provided memory allocator.
// The created list-view builder will create a list whose elements will be
// of type etype.
func ( memory.Allocator,  arrow.DataType) *ListViewBuilder {
	 := NewInt32Builder()
	 := NewInt32Builder()
	 := &ListViewBuilder{
		baseListViewBuilder{
			builder:         builder{mem: },
			values:          NewBuilder(, ),
			offsets:         ,
			sizes:           ,
			dt:              arrow.ListViewOf(),
			appendOffsetVal: func( int) { .Append(int32()) },
			appendSizeVal:   func( int) { .Append(int32()) },
		},
	}
	.refCount.Add(1)
	return 
}

// NewListViewBuilderWithField takes a field to use for the child rather than just
// a datatype to allow for more customization.
func ( memory.Allocator,  arrow.Field) *ListViewBuilder {
	 := NewInt32Builder()
	 := NewInt32Builder()
	 := &ListViewBuilder{
		baseListViewBuilder{
			builder:         builder{mem: },
			values:          NewBuilder(, .Type),
			offsets:         ,
			sizes:           ,
			dt:              arrow.ListViewOfField(),
			appendOffsetVal: func( int) { .Append(int32()) },
			appendSizeVal:   func( int) { .Append(int32()) },
		},
	}
	.refCount.Add(1)
	return 
}

func ( *baseListViewBuilder) () arrow.DataType {
	switch dt := .dt.(type) {
	case *arrow.ListViewType:
		 := .ElemField()
		.Type = .values.Type()
		return arrow.ListViewOfField()
	case *arrow.LargeListViewType:
		 := .ElemField()
		.Type = .values.Type()
		return arrow.LargeListViewOfField()
	}
	return nil
}

// NewLargeListViewBuilder returns a builder, using the provided memory allocator.
// The created list-view builder will create a list whose elements will be of type etype.
func ( memory.Allocator,  arrow.DataType) *LargeListViewBuilder {
	 := NewInt64Builder()
	 := NewInt64Builder()
	 := &LargeListViewBuilder{
		baseListViewBuilder{
			builder:         builder{mem: },
			values:          NewBuilder(, ),
			offsets:         ,
			sizes:           ,
			dt:              arrow.LargeListViewOf(),
			appendOffsetVal: func( int) { .Append(int64()) },
			appendSizeVal:   func( int) { .Append(int64()) },
		},
	}
	.refCount.Add(1)
	return 
}

// NewLargeListViewBuilderWithField takes a field rather than just an element type
// to allow for more customization of the final type of the LargeListView Array
func ( memory.Allocator,  arrow.Field) *LargeListViewBuilder {
	 := NewInt64Builder()
	 := NewInt64Builder()
	 := &LargeListViewBuilder{
		baseListViewBuilder{
			builder:         builder{mem: },
			values:          NewBuilder(, .Type),
			offsets:         ,
			sizes:           ,
			dt:              arrow.LargeListViewOfField(),
			appendOffsetVal: func( int) { .Append(int64()) },
			appendSizeVal:   func( int) { .Append(int64()) },
		},
	}

	.refCount.Add(1)
	return 
}

// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
func ( *baseListViewBuilder) () {
	debug.Assert(.refCount.Load() > 0, "too many releases")

	if .refCount.Add(-1) == 0 {
		if .nullBitmap != nil {
			.nullBitmap.Release()
			.nullBitmap = nil
		}
		.values.Release()
		.offsets.Release()
		.sizes.Release()
	}
}

func ( *baseListViewBuilder) ( int,  int) {
	.Reserve(1)
	.unsafeAppendBoolToBitmap(true)
	.appendOffsetVal()
	.appendSizeVal()
}

func ( *baseListViewBuilder) ( bool) {
	debug.Assert(false, "baseListViewBuilder.Append should never be called -- use AppendWithSize instead")
}

func ( *baseListViewBuilder) ( bool,  int) {
	debug.Assert( ||  == 0, "invalid list-view should have size 0")
	.Reserve(1)
	.unsafeAppendBoolToBitmap()
	.appendOffsetVal(.values.Len())
	.appendSizeVal()
}

func ( *baseListViewBuilder) () {
	.AppendWithSize(false, 0)
}

func ( *baseListViewBuilder) ( int) {
	for  := 0;  < ; ++ {
		.AppendNull()
	}
}

func ( *baseListViewBuilder) () {
	.AppendWithSize(true, 0)
}

func ( *baseListViewBuilder) ( int) {
	for  := 0;  < ; ++ {
		.AppendEmptyValue()
	}
}

func ( *ListViewBuilder) ( []int32,  []int32,  []bool) {
	.Reserve(len())
	.offsets.(*Int32Builder).AppendValues(, nil)
	.sizes.(*Int32Builder).AppendValues(, nil)
	.unsafeAppendBoolsToBitmap(, len())
}

func ( *LargeListViewBuilder) ( []int64,  []int64,  []bool) {
	.Reserve(len())
	.offsets.(*Int64Builder).AppendValues(, nil)
	.sizes.(*Int64Builder).AppendValues(, nil)
	.unsafeAppendBoolsToBitmap(, len())
}

func ( *baseListViewBuilder) ( bool) {
	if  {
		bitutil.SetBit(.nullBitmap.Bytes(), .length)
	} else {
		.nulls++
	}
	.length++
}

func ( *baseListViewBuilder) ( int) {
	.builder.init()
	.offsets.init()
	.sizes.init()
}

// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func ( *baseListViewBuilder) ( int) {
	.reserve(, .resizeHelper)
	.offsets.Reserve()
	.sizes.Reserve()
}

// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func ( *baseListViewBuilder) ( int) {
	.resizeHelper()
	.offsets.Resize()
	.sizes.Resize()
}

func ( *baseListViewBuilder) ( int) {
	if  < minBuilderCapacity {
		 = minBuilderCapacity
	}

	if .capacity == 0 {
		.init()
	} else {
		.resize(, .builder.init)
	}
}

func ( *baseListViewBuilder) () Builder {
	return .values
}

// NewArray creates a ListView array from the memory buffers used by the builder and
// resets the ListViewBuilder so it can be used to build a new array.
func ( *ListViewBuilder) () arrow.Array {
	return .NewListViewArray()
}

// NewArray creates a LargeListView array from the memory buffers used by the builder
// and resets the LargeListViewBuilder so it can be used to build a new array.
func ( *LargeListViewBuilder) () arrow.Array {
	return .NewLargeListViewArray()
}

// NewListViewArray creates a ListView array from the memory buffers used by the builder
// and resets the ListViewBuilder so it can be used to build a new array.
func ( *ListViewBuilder) () ( *ListView) {
	 := .newData()
	 = NewListViewData()
	.Release()
	return
}

// NewLargeListViewArray creates a ListView array from the memory buffers used by the
// builder and resets the LargeListViewBuilder so it can be used to build a new array.
func ( *LargeListViewBuilder) () ( *LargeListView) {
	 := .newData()
	 = NewLargeListViewData()
	.Release()
	return
}

func ( *baseListViewBuilder) () ( *Data) {
	 := .values.NewArray()
	defer .Release()

	var  *memory.Buffer
	if .offsets != nil {
		 := .offsets.NewArray()
		defer .Release()
		 = .Data().Buffers()[1]
	}

	var  *memory.Buffer
	if .sizes != nil {
		 := .sizes.NewArray()
		defer .Release()
		 = .Data().Buffers()[1]
	}

	 = NewData(
		.Type(), .length,
		[]*memory.Buffer{
			.nullBitmap,
			,
			,
		},
		[]arrow.ArrayData{.Data()},
		.nulls,
		0,
	)
	.reset()

	return
}

func ( *baseListViewBuilder) ( string) error {
	if  == NullValueStr {
		.AppendNull()
		return nil
	}

	return .UnmarshalOne(json.NewDecoder(strings.NewReader()))
}

func ( *baseListViewBuilder) ( *json.Decoder) error {
	,  := .Token()
	if  != nil {
		return 
	}

	switch  {
	case json.Delim('['):
		 := .values.Len()
		// 0 is a placeholder size as we don't know the actual size yet
		.AppendWithSize(true, 0)
		if  := .values.Unmarshal();  != nil {
			return 
		}
		// consume ']'
		,  := .Token()
		// replace the last size with the actual size
		switch .sizes.(type) {
		case *Int32Builder:
			.sizes.(*Int32Builder).rawData[.sizes.Len()-1] = int32(.values.Len() - )
		case *Int64Builder:
			.sizes.(*Int64Builder).rawData[.sizes.Len()-1] = int64(.values.Len() - )
		}
		return 
	case nil:
		.AppendNull()
	default:
		return &json.UnmarshalTypeError{
			Value:  fmt.Sprint(),
			Struct: .dt.String(),
		}
	}

	return nil
}

func ( *baseListViewBuilder) ( *json.Decoder) error {
	for .More() {
		if  := .UnmarshalOne();  != nil {
			return 
		}
	}
	return nil
}

func ( *baseListViewBuilder) ( []byte) error {
	 := json.NewDecoder(bytes.NewReader())
	,  := .Token()
	if  != nil {
		return 
	}

	if ,  := .(json.Delim); ! ||  != '[' {
		return fmt.Errorf("list-view builder must unpack from json array, found %s", )
	}

	return .Unmarshal()
}

// Find the minimum offset+size in a LIST_VIEW/LARGE_LIST_VIEW array.
//
// Pre-conditions:
//
//	input.DataType() is ListViewType if Offset=int32 or LargeListViewType if Offset=int64
//	input.Len() > 0 && input.NullN() != input.Len()
func minListViewOffset[ int32 | int64]( arrow.ArrayData)  {
	var  []byte
	if .Buffers()[0] != nil {
		 = .Buffers()[0].Bytes()
	}
	 := arrow.GetData[](.Buffers()[1].Bytes())[.Offset():]
	 := arrow.GetData[](.Buffers()[2].Bytes())[.Offset():]

	 := func( int) bool {
		return  != nil && bitutil.BitIsNotSet(, .Offset()+)
	}

	// It's very likely that the first non-null non-empty list-view starts at
	// offset 0 of the child array.
	 := 0
	for  < .Len() && (() || [] == 0) {
		 += 1
	}
	if  >= .Len() {
		return 0
	}
	 := []
	if  == 0 {
		// early exit: offset 0 found already
		return 0
	}

	// Slow path: scan the buffers entirely.
	 += 1
	for ;  < .Len();  += 1 {
		if () {
			continue
		}
		 := []
		if  <  && [] > 0 {
			 = 
		}
	}
	return 
}

// Find the maximum offset+size in a LIST_VIEW/LARGE_LIST_VIEW array.
//
// Pre-conditions:
//
//	input.DataType() is ListViewType if Offset=int32 or LargeListViewType if Offset=int64
//	input.Len() > 0 && input.NullN() != input.Len()
func maxListViewEnd[ int32 | int64]( arrow.ArrayData)  {
	 := .Offset()
	var  []byte
	if .Buffers()[0] != nil {
		 = .Buffers()[0].Bytes()
	}
	 := arrow.GetData[](.Buffers()[1].Bytes())[:]
	 := arrow.GetData[](.Buffers()[2].Bytes())[:]

	 := func( int) bool {
		return  != nil && bitutil.BitIsNotSet(, +)
	}

	 := .Len() - 1 // safe because input.Len() > 0
	for  != 0 && (() || [] == 0) {
		 -= 1
	}
	 := []
	 := []
	if  == 0 {
		if () || [] == 0 {
			return 0
		} else {
			return  + 
		}
	}

	 := .Children()[0]
	 := [] + []
	if  == (.Len()) {
		// Early-exit: maximum possible view-end found already.
		return 
	}

	// Slow path: scan the buffers entirely.
	for ;  >= 0;  -= 1 {
		 := []
		 := []
		if  > 0 && !() {
			if + >  {
				 =  + 
				if  == (.Len()) {
					return 
				}
			}
		}
	}
	return 
}

func rangeOfValuesUsed( arrow.ArrayData) (int, int) {
	if .Len() == 0 || .NullN() == .Len() {
		return 0, 0
	}
	var ,  int
	switch .DataType().(type) {
	case *arrow.ListViewType:
		 = int(minListViewOffset[int32]())
		 = int(maxListViewEnd[int32]())
	case *arrow.LargeListViewType:
		 = int(minListViewOffset[int64]())
		 = int(maxListViewEnd[int64]())
	case *arrow.ListType:
		 := arrow.Int32Traits.CastFromBytes(.Buffers()[1].Bytes())[.Offset():]
		 = int([0])
		 = int([len()-1])
	case *arrow.LargeListType:
		 := arrow.Int64Traits.CastFromBytes(.Buffers()[1].Bytes())[.Offset():]
		 = int([0])
		 = int([len()-1])
	case *arrow.MapType:
		 := arrow.Int32Traits.CastFromBytes(.Buffers()[1].Bytes())[.Offset():]
		 = int([0])
		 = int([len()-1])
	}
	return ,  - 
}

// Returns the smallest contiguous range of values of the child array that are
// referenced by all the list values in the input array.
func ( VarLenListLike) (int, int) {
	return rangeOfValuesUsed(.Data())
}

var (
	_ arrow.Array = (*List)(nil)
	_ arrow.Array = (*LargeList)(nil)
	_ arrow.Array = (*ListView)(nil)
	_ arrow.Array = (*LargeListView)(nil)

	_ Builder = (*ListBuilder)(nil)
	_ Builder = (*LargeListBuilder)(nil)
	_ Builder = (*ListViewBuilder)(nil)
	_ Builder = (*LargeListViewBuilder)(nil)

	_ VarLenListLike = (*List)(nil)
	_ VarLenListLike = (*LargeList)(nil)
	_ VarLenListLike = (*Map)(nil)
	_ VarLenListLike = (*ListView)(nil)
	_ VarLenListLike = (*LargeListView)(nil)
	_ ListLike       = (*FixedSizeList)(nil)

	_ VarLenListLikeBuilder = (*ListBuilder)(nil)
	_ VarLenListLikeBuilder = (*LargeListBuilder)(nil)
	_ VarLenListLikeBuilder = (*ListBuilder)(nil)
	_ VarLenListLikeBuilder = (*LargeListBuilder)(nil)
	_ VarLenListLikeBuilder = (*MapBuilder)(nil)
	_ ListLikeBuilder       = (*FixedSizeListBuilder)(nil)
)